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

Commit a47492dc authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Refactor getproperty/setproperty



To support upcoming capabilities changes, first rework the getproperty
and setproperty for both KGSL and adreno to make it less complex and
easier to fit in with the upcoming model.

Change-Id: Ic0dedbad023d23ddb74f9d0208111e168554f0b6
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 64d97908
Loading
Loading
Loading
Loading
+55 −53
Original line number Diff line number Diff line
@@ -2254,19 +2254,20 @@ int adreno_reset(struct kgsl_device *device, int fault)
	return ret;
}

static int copy_prop(void __user *dst, size_t count, void *src, size_t size)
static int copy_prop(struct kgsl_device_getproperty *param,
		void *src, size_t size)
{
	if (count != size)
	if (param->sizebytes != size)
		return -EINVAL;

	if (copy_to_user(dst, src, count))
	if (copy_to_user(param->value, src, param->sizebytes))
		return -EFAULT;

	return 0;
}

static int adreno_prop_device_info(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct kgsl_devinfo devinfo = {
@@ -2277,11 +2278,11 @@ static int adreno_prop_device_info(struct kgsl_device *device,
		.gmem_sizebytes = adreno_dev->gpucore->gmem_size,
	};

	return copy_prop(value, count, &devinfo, sizeof(devinfo));
	return copy_prop(param, &devinfo, sizeof(devinfo));
}

static int adreno_prop_device_shadow(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct kgsl_shadowprop shadowprop = { 0 };

@@ -2298,11 +2299,11 @@ static int adreno_prop_device_shadow(struct kgsl_device *device,
			KGSL_FLAGS_PER_CONTEXT_TIMESTAMPS;
	}

	return copy_prop(value, count, &shadowprop, sizeof(shadowprop));
	return copy_prop(param, &shadowprop, sizeof(shadowprop));
}

static int adreno_prop_device_qdss_stm(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct kgsl_qdss_stm_prop qdssprop = {0};
	struct kgsl_memdesc *qdss_desc = kgsl_mmu_get_qdss_global_entry(device);
@@ -2312,11 +2313,11 @@ static int adreno_prop_device_qdss_stm(struct kgsl_device *device,
		qdssprop.size = qdss_desc->size;
	}

	return copy_prop(value, count, &qdssprop, sizeof(qdssprop));
	return copy_prop(param, &qdssprop, sizeof(qdssprop));
}

static int adreno_prop_device_qtimer(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct kgsl_qtimer_prop qtimerprop = {0};
	struct kgsl_memdesc *qtimer_desc =
@@ -2327,33 +2328,33 @@ static int adreno_prop_device_qtimer(struct kgsl_device *device,
		qtimerprop.size = qtimer_desc->size;
	}

	return copy_prop(value, count, &qtimerprop, sizeof(qtimerprop));
	return copy_prop(param, &qtimerprop, sizeof(qtimerprop));
}

static int adreno_prop_s32(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	int val = 0;

	if (type == KGSL_PROP_MMU_ENABLE)
	if (param->type == KGSL_PROP_MMU_ENABLE)
		val = MMU_FEATURE(&device->mmu, KGSL_MMU_PAGED);
	else if (type == KGSL_PROP_INTERRUPT_WAITS)
	else if (param->type == KGSL_PROP_INTERRUPT_WAITS)
		val = 1;

	return copy_prop(value, count, &val, sizeof(val));
	return copy_prop(param, &val, sizeof(val));
}

static int adreno_prop_uche_gmem_addr(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	u64 vaddr = adreno_dev->gpucore->gmem_base;

	return copy_prop(value, count, &vaddr, sizeof(vaddr));
	return copy_prop(param, &vaddr, sizeof(vaddr));
}

static int adreno_prop_ucode_version(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct kgsl_ucode_version ucode = {
@@ -2361,11 +2362,11 @@ static int adreno_prop_ucode_version(struct kgsl_device *device,
		.pm4 = adreno_dev->fw[ADRENO_FW_PM4].version,
	};

	return copy_prop(value, count, &ucode, sizeof(ucode));
	return copy_prop(param, &ucode, sizeof(ucode));
}

static int adreno_prop_gpmu_version(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct kgsl_gpmu_version gpmu = { 0 };
@@ -2380,64 +2381,65 @@ static int adreno_prop_gpmu_version(struct kgsl_device *device,
	gpmu.minor = adreno_dev->gpucore->gpmu_minor;
	gpmu.features = adreno_dev->gpucore->gpmu_features;

	return copy_prop(value, count, &gpmu, sizeof(gpmu));
	return copy_prop(param, &gpmu, sizeof(gpmu));
}

static int adreno_prop_u32(struct kgsl_device *device,
		u32 type, void __user *value, size_t count)
		struct kgsl_device_getproperty *param)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	u32 val = 0;

	if (type == KGSL_PROP_HIGHEST_BANK_BIT) {
	if (param->type == KGSL_PROP_HIGHEST_BANK_BIT) {
		if (of_property_read_u32(device->pdev->dev.of_node,
			"qcom,highest-bank-bit", &val))
			return -EINVAL;
	} else if (type == KGSL_PROP_MIN_ACCESS_LENGTH)
	} else if (param->type == KGSL_PROP_MIN_ACCESS_LENGTH)
		of_property_read_u32(device->pdev->dev.of_node,
			"qcom,min-access-length", &val);
	else if (type == KGSL_PROP_UBWC_MODE)
	else if (param->type == KGSL_PROP_UBWC_MODE)
		of_property_read_u32(device->pdev->dev.of_node,
			"qcom,ubwc-mode", &val);
	else if (type == KGSL_PROP_DEVICE_BITNESS)
	else if (param->type == KGSL_PROP_DEVICE_BITNESS)
		val = adreno_support_64bit(adreno_dev) ? 48 : 32;

	else if (type == KGSL_PROP_SPEED_BIN)
	else if (param->type == KGSL_PROP_SPEED_BIN)
		val = adreno_dev->speed_bin;

	return copy_prop(value, count, &val, sizeof(val));
	return copy_prop(param, &val, sizeof(val));
}

static struct {
	int (*func)(struct kgsl_device *device, u32 type, void __user *value,
		size_t count);
static const struct {
	int type;
	int (*func)(struct kgsl_device *device,
		struct kgsl_device_getproperty *param);
} adreno_property_funcs[] = {
	[KGSL_PROP_DEVICE_INFO] = { .func = adreno_prop_device_info },
	[KGSL_PROP_DEVICE_SHADOW] = { .func = adreno_prop_device_shadow },
	[KGSL_PROP_DEVICE_QDSS_STM] = { .func = adreno_prop_device_qdss_stm },
	[KGSL_PROP_DEVICE_QTIMER] = { .func = adreno_prop_device_qtimer },
	[KGSL_PROP_MMU_ENABLE] = { .func = adreno_prop_s32 },
	[KGSL_PROP_INTERRUPT_WAITS] = { .func = adreno_prop_s32 },
	[KGSL_PROP_UCHE_GMEM_VADDR] = { .func = adreno_prop_uche_gmem_addr },
	[KGSL_PROP_UCODE_VERSION] = { .func = adreno_prop_ucode_version },
	[KGSL_PROP_GPMU_VERSION] = { .func = adreno_prop_gpmu_version },
	[KGSL_PROP_HIGHEST_BANK_BIT] = { .func = adreno_prop_u32 },
	[KGSL_PROP_MIN_ACCESS_LENGTH] = { .func = adreno_prop_u32 },
	[KGSL_PROP_UBWC_MODE] = { .func = adreno_prop_u32 },
	[KGSL_PROP_DEVICE_BITNESS] = { .func = adreno_prop_u32 },
	[KGSL_PROP_SPEED_BIN] = { .func = adreno_prop_u32 },
	{ KGSL_PROP_DEVICE_INFO, adreno_prop_device_info },
	{ KGSL_PROP_DEVICE_SHADOW, adreno_prop_device_shadow },
	{ KGSL_PROP_DEVICE_QDSS_STM, adreno_prop_device_qdss_stm },
	{ KGSL_PROP_DEVICE_QTIMER, adreno_prop_device_qtimer },
	{ KGSL_PROP_MMU_ENABLE, adreno_prop_s32 },
	{ KGSL_PROP_INTERRUPT_WAITS, adreno_prop_s32 },
	{ KGSL_PROP_UCHE_GMEM_VADDR, adreno_prop_uche_gmem_addr },
	{ KGSL_PROP_UCODE_VERSION, adreno_prop_ucode_version },
	{ KGSL_PROP_GPMU_VERSION, adreno_prop_gpmu_version },
	{ KGSL_PROP_HIGHEST_BANK_BIT, adreno_prop_u32 },
	{ KGSL_PROP_MIN_ACCESS_LENGTH, adreno_prop_u32 },
	{ KGSL_PROP_UBWC_MODE, adreno_prop_u32 },
	{ KGSL_PROP_DEVICE_BITNESS, adreno_prop_u32 },
	{ KGSL_PROP_SPEED_BIN, adreno_prop_u32 },
};

static int adreno_getproperty(struct kgsl_device *device,
				unsigned int type,
				void __user *value,
				size_t sizebytes)
		struct kgsl_device_getproperty *param)
{
	if (type >= ARRAY_SIZE(adreno_property_funcs) ||
		!adreno_property_funcs[type].func)
		return -ENODEV;
	int i;

	for (i = 0; i < ARRAY_SIZE(adreno_property_funcs); i++) {
		if (param->type == adreno_property_funcs[i].type)
			return adreno_property_funcs[i].func(device, param);
	}

	return adreno_property_funcs[type].func(device, type, value, sizebytes);
	return -ENODEV;
}

int adreno_set_constraint(struct kgsl_device *device,
+8 −11
Original line number Diff line number Diff line
@@ -12,19 +12,17 @@
#include "adreno_compat.h"

int adreno_getproperty_compat(struct kgsl_device *device,
				unsigned int type,
				void __user *value,
				size_t sizebytes)
		struct kgsl_device_getproperty *param)
{
	int status = -EINVAL;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

	switch (type) {
	switch (param->type) {
	case KGSL_PROP_DEVICE_INFO:
		{
			struct kgsl_devinfo_compat devinfo;

			if (sizebytes != sizeof(devinfo)) {
			if (param->sizebytes != sizeof(devinfo)) {
				status = -EINVAL;
				break;
			}
@@ -39,8 +37,8 @@ int adreno_getproperty_compat(struct kgsl_device *device,
			devinfo.gmem_sizebytes =
					adreno_dev->gpucore->gmem_size;

			if (copy_to_user(value, &devinfo, sizeof(devinfo)) !=
					0) {
			if (copy_to_user(param->value, &devinfo,
				sizeof(devinfo))) {
				status = -EFAULT;
				break;
			}
@@ -51,7 +49,7 @@ int adreno_getproperty_compat(struct kgsl_device *device,
		{
			struct kgsl_shadowprop_compat shadowprop;

			if (sizebytes != sizeof(shadowprop)) {
			if (param->sizebytes != sizeof(shadowprop)) {
				status = -EINVAL;
				break;
			}
@@ -75,7 +73,7 @@ int adreno_getproperty_compat(struct kgsl_device *device,
				shadowprop.flags = KGSL_FLAGS_INITIALIZED |
					KGSL_FLAGS_PER_CONTEXT_TIMESTAMPS;
			}
			if (copy_to_user(value, &shadowprop,
			if (copy_to_user(param->value, &shadowprop,
				sizeof(shadowprop))) {
				status = -EFAULT;
				break;
@@ -84,8 +82,7 @@ int adreno_getproperty_compat(struct kgsl_device *device,
		}
		break;
	default:
		status = device->ftbl->getproperty(device, type, value,
						sizebytes);
		status = device->ftbl->getproperty(device, param);
	}

	return status;
+4 −7
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2013-2015, 2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, 2017, 2019 The Linux Foundation. All rights reserved.
 */
#ifndef __ADRENO_COMPAT_H
#define __ADRENO_COMPAT_H
@@ -11,9 +11,7 @@
#include "kgsl_device.h"

int adreno_getproperty_compat(struct kgsl_device *device,
			unsigned int type,
			void __user *value,
			size_t sizebytes);
		struct kgsl_device_getproperty *param);

int adreno_setproperty_compat(struct kgsl_device_private *dev_priv,
				unsigned int type,
@@ -26,8 +24,7 @@ long adreno_compat_ioctl(struct kgsl_device_private *dev_priv,
#else

static inline int adreno_getproperty_compat(struct kgsl_device *device,
				unsigned int type,
				void __user *value, size_t sizebytes)
		struct kgsL_device_getproperty *param);
{
	return -EINVAL;
}
+100 −97
Original line number Diff line number Diff line
@@ -1409,78 +1409,66 @@ static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry)
	return ret;
}

/*call all ioctl sub functions with driver locked*/
long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
					  unsigned int cmd, void *data)
{
	int result = 0;
	struct kgsl_device_getproperty *param = data;

	switch (param->type) {
	case KGSL_PROP_VERSION:
	{
		struct kgsl_version version;

		if (param->sizebytes != sizeof(version)) {
			result = -EINVAL;
			break;
		}

		version.drv_major = KGSL_VERSION_MAJOR;
		version.drv_minor = KGSL_VERSION_MINOR;
static long kgsl_prop_version(struct kgsl_device_private *dev_priv,
		struct kgsl_device_getproperty *param)
{
	struct kgsl_version version = {
		.drv_major = KGSL_VERSION_MAJOR,
		.drv_minor = KGSL_VERSION_MINOR,
		.dev_major = 3,
		.dev_minor = 1,
	};

		version.dev_major = 3;
		version.dev_minor = 1;
	if (param->sizebytes != sizeof(version))
		return -EINVAL;

	if (copy_to_user(param->value, &version, sizeof(version)))
			result = -EFAULT;
		return -EFAULT;

		break;
	return 0;
}
	case KGSL_PROP_GPU_RESET_STAT:
	{

/* Return reset status of given context and clear it */
		uint32_t id;
static long kgsl_prop_gpu_reset_stat(struct kgsl_device_private *dev_priv,
		struct kgsl_device_getproperty *param)
{
	u32 id;
	struct kgsl_context *context;

		if (param->sizebytes != sizeof(unsigned int)) {
			result = -EINVAL;
			break;
		}
	if (param->sizebytes != sizeof(id))
		return -EINVAL;

	/* We expect the value passed in to contain the context id */
		if (copy_from_user(&id, param->value,
			sizeof(unsigned int))) {
			result = -EFAULT;
			break;
		}
	if (copy_from_user(&id, param->value, sizeof(id)))
		return -EFAULT;

	context = kgsl_context_get_owner(dev_priv, id);
		if (!context) {
			result = -EINVAL;
			break;
		}
	if (!context)
		return -EINVAL;

	/*
	 * Copy the reset status to value which also serves as
	 * the out parameter
	 */
		if (copy_to_user(param->value, &(context->reset_status),
			sizeof(unsigned int)))
			result = -EFAULT;
		else {
			/* Clear reset status once its been queried */
			context->reset_status = KGSL_CTX_STAT_NO_ERROR;
		}
	id = context->reset_status;

	context->reset_status = KGSL_CTX_STAT_NO_ERROR;
	kgsl_context_put(context);
		break;

	if (copy_to_user(param->value, &id, sizeof(id)))
		return -EFAULT;

	return 0;
}
	case KGSL_PROP_SECURE_BUFFER_ALIGNMENT:

static long kgsl_prop_secure_buf_alignment(struct kgsl_device_private *dev_priv,
		struct kgsl_device_getproperty *param)
{
		unsigned int align;
	u32 align;

	if (param->sizebytes != sizeof(align))
		return -EINVAL;

		if (param->sizebytes != sizeof(unsigned int)) {
			result = -EINVAL;
			break;
		}
	/*
	 * XPUv2 impose the constraint of 1MB memory alignment,
	 * on the other hand Hypervisor does not have such
@@ -1491,40 +1479,55 @@ long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
			KGSL_MMU_HYP_SECURE_ALLOC) ? PAGE_SIZE : SZ_1M;

	if (copy_to_user(param->value, &align, sizeof(align)))
			result = -EFAULT;
		return -EFAULT;

		break;
	return 0;
}
	case KGSL_PROP_SECURE_CTXT_SUPPORT:

static long kgsl_prop_secure_ctxt_support(struct kgsl_device_private *dev_priv,
		struct kgsl_device_getproperty *param)
{
		unsigned int secure_ctxt;
	u32 secure;

		if (param->sizebytes != sizeof(unsigned int)) {
			result = -EINVAL;
			break;
		}
	if (param->sizebytes != sizeof(secure))
		return -EINVAL;

		secure_ctxt = dev_priv->device->mmu.secured ? 1 : 0;
	secure = dev_priv->device->mmu.secured ? 1 : 0;

		if (copy_to_user(param->value, &secure_ctxt,
				sizeof(secure_ctxt)))
			result = -EFAULT;
	if (copy_to_user(param->value, &secure, sizeof(secure)))
		return -EFAULT;

		break;
	return 0;
}
	default:
		if (is_compat_task())
			result = dev_priv->device->ftbl->getproperty_compat(
					dev_priv->device, param->type,
					param->value, param->sizebytes);
		else
			result = dev_priv->device->ftbl->getproperty(
					dev_priv->device, param->type,
					param->value, param->sizebytes);

static const struct {
	int type;
	long (*func)(struct kgsl_device_private *dev_priv,
		struct kgsl_device_getproperty *param);
} kgsl_property_funcs[] = {
	{ KGSL_PROP_VERSION, kgsl_prop_version },
	{ KGSL_PROP_GPU_RESET_STAT, kgsl_prop_gpu_reset_stat},
	{ KGSL_PROP_SECURE_BUFFER_ALIGNMENT, kgsl_prop_secure_buf_alignment },
	{ KGSL_PROP_SECURE_CTXT_SUPPORT, kgsl_prop_secure_ctxt_support },
};

/*call all ioctl sub functions with driver locked*/
long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
					  unsigned int cmd, void *data)
{
	struct kgsl_device *device = dev_priv->device;
	struct kgsl_device_getproperty *param = data;
	int i;

	for (i = 0; i < ARRAY_SIZE(kgsl_property_funcs); i++) {
		if (param->type == kgsl_property_funcs[i].type)
			return kgsl_property_funcs[i].func(dev_priv, param);
	}

	if (is_compat_task())
		return device->ftbl->getproperty_compat(device, param);

	return result;
	return device->ftbl->getproperty(device, param);
}

long kgsl_ioctl_device_setproperty(struct kgsl_device_private *dev_priv,
+2 −4
Original line number Diff line number Diff line
@@ -122,11 +122,9 @@ struct kgsl_functable {
	int (*start)(struct kgsl_device *device, int priority);
	int (*stop)(struct kgsl_device *device);
	int (*getproperty)(struct kgsl_device *device,
		unsigned int type, void __user *value,
		size_t sizebytes);
		struct kgsl_device_getproperty *param);
	int (*getproperty_compat)(struct kgsl_device *device,
		unsigned int type, void __user *value,
		size_t sizebytes);
		struct kgsl_device_getproperty *param);
	int (*waittimestamp)(struct kgsl_device *device,
		struct kgsl_context *context, unsigned int timestamp,
		unsigned int msecs);