// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2021 Raspberry Pi
 */

#include "v3d_drv.h"
#include "v3d_regs.h"

#define V3D_PERFMONID_MIN	1
#define V3D_PERFMONID_MAX	U32_MAX

void v3d_perfmon_get(struct v3d_perfmon *perfmon)
{
	if (perfmon)
		refcount_inc(&perfmon->refcnt);
}

void v3d_perfmon_put(struct v3d_perfmon *perfmon)
{
	if (perfmon && refcount_dec_and_test(&perfmon->refcnt)) {
		mutex_destroy(&perfmon->lock);
		kfree(perfmon);
	}
}

void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
{
	unsigned int i;
	u32 mask;
	u8 ncounters;

	if (WARN_ON_ONCE(!perfmon || v3d->active_perfmon))
		return;

	ncounters = perfmon->ncounters;
	mask = GENMASK(ncounters - 1, 0);

	for (i = 0; i < ncounters; i++) {
		u32 source = i / 4;
		u32 channel = V3D_SET_FIELD(perfmon->counters[i], V3D_PCTR_S0);

		i++;
		channel |= V3D_SET_FIELD(i < ncounters ? perfmon->counters[i] : 0,
					 V3D_PCTR_S1);
		i++;
		channel |= V3D_SET_FIELD(i < ncounters ? perfmon->counters[i] : 0,
					 V3D_PCTR_S2);
		i++;
		channel |= V3D_SET_FIELD(i < ncounters ? perfmon->counters[i] : 0,
					 V3D_PCTR_S3);
		V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel);
	}

	V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask);
	V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask);
	V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);

	v3d->active_perfmon = perfmon;
}

void v3d_perfmon_stop(struct v3d_dev *v3d, struct v3d_perfmon *perfmon,
		      bool capture)
{
	unsigned int i;

	if (!perfmon || !v3d->active_perfmon)
		return;

	mutex_lock(&perfmon->lock);
	if (perfmon != v3d->active_perfmon) {
		mutex_unlock(&perfmon->lock);
		return;
	}

	if (capture)
		for (i = 0; i < perfmon->ncounters; i++)
			perfmon->values[i] += V3D_CORE_READ(0, V3D_PCTR_0_PCTRX(i));

	V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, 0);

	v3d->active_perfmon = NULL;
	mutex_unlock(&perfmon->lock);
}

struct v3d_perfmon *v3d_perfmon_find(struct v3d_file_priv *v3d_priv, int id)
{
	struct v3d_perfmon *perfmon;

	mutex_lock(&v3d_priv->perfmon.lock);
	perfmon = idr_find(&v3d_priv->perfmon.idr, id);
	v3d_perfmon_get(perfmon);
	mutex_unlock(&v3d_priv->perfmon.lock);

	return perfmon;
}

void v3d_perfmon_open_file(struct v3d_file_priv *v3d_priv)
{
	mutex_init(&v3d_priv->perfmon.lock);
	idr_init_base(&v3d_priv->perfmon.idr, 1);
}

static int v3d_perfmon_idr_del(int id, void *elem, void *data)
{
	struct v3d_perfmon *perfmon = elem;

	v3d_perfmon_put(perfmon);

	return 0;
}

void v3d_perfmon_close_file(struct v3d_file_priv *v3d_priv)
{
	mutex_lock(&v3d_priv->perfmon.lock);
	idr_for_each(&v3d_priv->perfmon.idr, v3d_perfmon_idr_del, NULL);
	idr_destroy(&v3d_priv->perfmon.idr);
	mutex_unlock(&v3d_priv->perfmon.lock);
	mutex_destroy(&v3d_priv->perfmon.lock);
}

int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
			     struct drm_file *file_priv)
{
	struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
	struct drm_v3d_perfmon_create *req = data;
	struct v3d_perfmon *perfmon;
	unsigned int i;
	int ret;

	/* Number of monitored counters cannot exceed HW limits. */
	if (req->ncounters > DRM_V3D_MAX_PERF_COUNTERS ||
	    !req->ncounters)
		return -EINVAL;

	/* Make sure all counters are valid. */
	for (i = 0; i < req->ncounters; i++) {
		if (req->counters[i] >= V3D_PERFCNT_NUM)
			return -EINVAL;
	}

	perfmon = kzalloc(struct_size(perfmon, values, req->ncounters),
			  GFP_KERNEL);
	if (!perfmon)
		return -ENOMEM;

	for (i = 0; i < req->ncounters; i++)
		perfmon->counters[i] = req->counters[i];

	perfmon->ncounters = req->ncounters;

	refcount_set(&perfmon->refcnt, 1);
	mutex_init(&perfmon->lock);

	mutex_lock(&v3d_priv->perfmon.lock);
	ret = idr_alloc(&v3d_priv->perfmon.idr, perfmon, V3D_PERFMONID_MIN,
			V3D_PERFMONID_MAX, GFP_KERNEL);
	mutex_unlock(&v3d_priv->perfmon.lock);

	if (ret < 0) {
		mutex_destroy(&perfmon->lock);
		kfree(perfmon);
		return ret;
	}

	req->id = ret;

	return 0;
}

int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
			      struct drm_file *file_priv)
{
	struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
	struct drm_v3d_perfmon_destroy *req = data;
	struct v3d_perfmon *perfmon;

	mutex_lock(&v3d_priv->perfmon.lock);
	perfmon = idr_remove(&v3d_priv->perfmon.idr, req->id);
	mutex_unlock(&v3d_priv->perfmon.lock);

	if (!perfmon)
		return -EINVAL;

	v3d_perfmon_put(perfmon);

	return 0;
}

int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
				 struct drm_file *file_priv)
{
	struct v3d_dev *v3d = to_v3d_dev(dev);
	struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
	struct drm_v3d_perfmon_get_values *req = data;
	struct v3d_perfmon *perfmon;
	int ret = 0;

	if (req->pad != 0)
		return -EINVAL;

	mutex_lock(&v3d_priv->perfmon.lock);
	perfmon = idr_find(&v3d_priv->perfmon.idr, req->id);
	v3d_perfmon_get(perfmon);
	mutex_unlock(&v3d_priv->perfmon.lock);

	if (!perfmon)
		return -EINVAL;

	v3d_perfmon_stop(v3d, perfmon, true);

	if (copy_to_user(u64_to_user_ptr(req->values_ptr), perfmon->values,
			 perfmon->ncounters * sizeof(u64)))
		ret = -EFAULT;

	v3d_perfmon_put(perfmon);

	return ret;
}
