Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00dd2972 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Give userspace access to GPU preemption counters"

parents bbaf0421 5816d1ec
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/ioctl.h>
#include "kgsl_device.h"
#include "adreno.h"
#include "adreno_a5xx.h"

long adreno_ioctl_perfcounter_get(struct kgsl_device_private *dev_priv,
	unsigned int cmd, void *data)
@@ -79,6 +80,40 @@ static long adreno_ioctl_perfcounter_read(struct kgsl_device_private *dev_priv,
		read->count);
}

static long adreno_ioctl_preemption_counters_query(
		struct kgsl_device_private *dev_priv,
		unsigned int cmd, void *data)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_priv->device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	struct kgsl_preemption_counters_query *read = data;
	int size_level = A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE_IN_DWORDS *
					 sizeof(unsigned int);
	int levels_to_copy;

	if (!adreno_is_a5xx(adreno_dev) ||
		!adreno_is_preemption_enabled(adreno_dev))
		return -EOPNOTSUPP;

	if (read->size_user < size_level)
		return -EINVAL;

	/* Calculate number of preemption counter levels to copy to userspace */
	levels_to_copy = (read->size_user / size_level);
	if (levels_to_copy > gpudev->num_prio_levels)
		levels_to_copy = gpudev->num_prio_levels;

	if (copy_to_user((void __user *) (uintptr_t) read->counters,
			adreno_dev->preemption_counters.hostptr,
			levels_to_copy * size_level))
		return -EFAULT;

	read->max_priority_level = levels_to_copy;
	read->size_priority_level = size_level;

	return 0;
}

long adreno_ioctl_helper(struct kgsl_device_private *dev_priv,
		unsigned int cmd, unsigned long arg,
		const struct kgsl_ioctl *cmds, int len)
@@ -122,6 +157,8 @@ static struct kgsl_ioctl adreno_ioctl_funcs[] = {
	{ IOCTL_KGSL_PERFCOUNTER_PUT, adreno_ioctl_perfcounter_put },
	{ IOCTL_KGSL_PERFCOUNTER_QUERY, adreno_ioctl_perfcounter_query },
	{ IOCTL_KGSL_PERFCOUNTER_READ, adreno_ioctl_perfcounter_read },
	{ IOCTL_KGSL_PREEMPTIONCOUNTER_QUERY,
		adreno_ioctl_preemption_counters_query },
};

long adreno_ioctl(struct kgsl_device_private *dev_priv,
+27 −0
Original line number Diff line number Diff line
@@ -1386,4 +1386,31 @@ struct kgsl_gpu_command {
#define IOCTL_KGSL_GPU_COMMAND \
	_IOWR(KGSL_IOC_TYPE, 0x4A, struct kgsl_gpu_command)

/**
 * struct kgsl_preemption_counters_query - argument to
 * IOCTL_KGSL_PREEMPTIONCOUNTER_QUERY
 * @counters: Return preemption counters array
 * @size_user: Size allocated by userspace
 * @size_priority_level: Size of preemption counters for each
 * priority level
 * @max_priority_level: Return max number of priority levels
 *
 * Query the available preemption counters. The array counters
 * is used to return preemption counters. The size of the array
 * is passed in so the kernel will only write at most size_user
 * or max available preemption counters.  The total number of
 * preemption counters is returned in max_priority_level. If the
 * array or size passed in are invalid, then an error is
 * returned back.
 */
struct kgsl_preemption_counters_query {
	uint64_t __user counters;
	unsigned int size_user;
	unsigned int size_priority_level;
	unsigned int max_priority_level;
};

#define IOCTL_KGSL_PREEMPTIONCOUNTER_QUERY \
	_IOWR(KGSL_IOC_TYPE, 0x4B, struct kgsl_preemption_counters_query)

#endif /* _UAPI_MSM_KGSL_H */