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

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

msm: kgsl: Add KGSL_PROP_QUERY_CAPABILITIES



Add a new property to query the capabilities of the kernel. The first
supported query type will return a list of property IDs that the kernel
driver supports.

Change-Id: Ic0dedbadba2f6af6c9d1c4d46cb11e3bb74b0028
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent cf8acfa8
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -2442,6 +2442,20 @@ static int adreno_getproperty(struct kgsl_device *device,
	return -ENODEV;
}

static int adreno_query_property_list(struct kgsl_device *device, u32 *list,
		u32 count)
{
	int i;

	if (!list)
		return ARRAY_SIZE(adreno_property_funcs);

	for (i = 0; i < count && i < ARRAY_SIZE(adreno_property_funcs); i++)
		list[i] = adreno_property_funcs[i].type;

	return i;
}

int adreno_set_constraint(struct kgsl_device *device,
				struct kgsl_context *context,
				struct kgsl_device_constraint *constraint)
@@ -3750,6 +3764,7 @@ static const struct kgsl_functable adreno_functable = {
	.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
	.dispatcher_halt = adreno_dispatcher_halt,
	.dispatcher_unhalt = adreno_dispatcher_unhalt,
	.query_property_list = adreno_query_property_list,
};

static struct platform_driver adreno_platform_driver = {
+125 −0
Original line number Diff line number Diff line
@@ -1500,6 +1500,106 @@ static long kgsl_prop_secure_ctxt_support(struct kgsl_device_private *dev_priv,
	return 0;
}

static int kgsl_query_caps_properties(struct kgsl_device *device,
		struct kgsl_capabilities *caps)
{
	struct kgsl_capabilities_properties props;
	size_t copy;
	u32 count, *local;
	int ret;

	/* Return the size of the subtype struct */
	if (caps->size == 0) {
		caps->size = sizeof(props);
		return 0;
	}

	memset(&props, 0, sizeof(props));

	copy = min_t(size_t, caps->size, sizeof(props));

	if (copy_from_user(&props, u64_to_user_ptr(caps->data), copy))
		return -EFAULT;

	/* Get the number of properties */
	count = kgsl_query_property_list(device, NULL, 0);

	/*
	 * If the incoming user count is zero, they are querying the number of
	 * available properties. Set it and return.
	 */
	if (props.count == 0) {
		props.count = count;
		goto done;
	}

	/* Copy the lesser of the user or kernel property count */
	if (props.count < count)
		count = props.count;

	/* Create a local buffer to store the property list */
	local = kcalloc(count, sizeof(u32), GFP_KERNEL);
	if (!local)
		return -ENOMEM;

	/* Get the properties */
	props.count = kgsl_query_property_list(device, local, count);

	ret = copy_to_user(u64_to_user_ptr(props.list), local,
		props.count * sizeof(u32));

	kfree(local);

	if (ret)
		return -EFAULT;

done:
	if (copy_to_user(u64_to_user_ptr(caps->data), &props, copy))
		return -EFAULT;

	return 0;
}

static long kgsl_prop_query_capabilities(struct kgsl_device_private *dev_priv,
		struct kgsl_device_getproperty *param)
{
	struct kgsl_capabilities caps;
	long ret;
	size_t copy;

	/*
	 * If sizebytes is zero, tell the user how big the capabilities struct
	 * should be
	 */
	if (param->sizebytes == 0) {
		param->sizebytes = sizeof(caps);
		return 0;
	}

	memset(&caps, 0, sizeof(caps));

	copy = min_t(size_t, param->sizebytes, sizeof(caps));

	if (copy_from_user(&caps, param->value, copy))
		return -EFAULT;

	/* querytype must be non zero */
	if (caps.querytype == 0)
		return -EINVAL;

	if (caps.querytype == KGSL_QUERY_CAPS_PROPERTIES)
		ret = kgsl_query_caps_properties(dev_priv->device, &caps);
	else {
		/* Unsupported querytypes should return a unique return value */
		return -EOPNOTSUPP;
	}

	if (copy_to_user(param->value, &caps, copy))
		return -EFAULT;

	return ret;
}

static const struct {
	int type;
	long (*func)(struct kgsl_device_private *dev_priv,
@@ -1509,6 +1609,7 @@ static const struct {
	{ 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 },
	{ KGSL_PROP_QUERY_CAPABILITIES, kgsl_prop_query_capabilities },
};

/*call all ioctl sub functions with driver locked*/
@@ -1530,6 +1631,30 @@ long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
	return device->ftbl->getproperty(device, param);
}

int kgsl_query_property_list(struct kgsl_device *device, u32 *list, u32 count)
{
	int num = 0;

	if (!list) {
		num = ARRAY_SIZE(kgsl_property_funcs);

		if (device->ftbl->query_property_list)
			num += device->ftbl->query_property_list(device, list,
				count);

		return num;
	}

	for (; num < count && num < ARRAY_SIZE(kgsl_property_funcs); num++)
		list[num] = kgsl_property_funcs[num].type;

	if (device->ftbl->query_property_list)
		num += device->ftbl->query_property_list(device, &list[num],
			count - num);

	return num;
}

long kgsl_ioctl_device_setproperty(struct kgsl_device_private *dev_priv,
					  unsigned int cmd, void *data)
{
+23 −0
Original line number Diff line number Diff line
@@ -180,6 +180,14 @@ struct kgsl_functable {
	void (*stop_fault_timer)(struct kgsl_device *device);
	void (*dispatcher_halt)(struct kgsl_device *device);
	void (*dispatcher_unhalt)(struct kgsl_device *device);
	/**
	 * @query_property_list: query the list of properties
	 * supported by the device. If 'list' is NULL just return the total
	 * number of properties available otherwise copy up to 'count' items
	 * into the list and return the total number of items copied.
	 */
	int (*query_property_list)(struct kgsl_device *device, u32 *list,
		u32 count);
};

struct kgsl_ioctl {
@@ -889,6 +897,21 @@ void kgsl_snapshot_add_section(struct kgsl_device *device, u16 id,
	size_t (*func)(struct kgsl_device *, u8 *, size_t, void *),
	void *priv);

/**
 * kgsl_query_property_list - Get a list of valid properties
 * @device: A KGSL device handle
 * @list: Pointer to a list of u32s
 * @count: Number of items in @list
 *
 * Populate a list with the IDs for supported properties. If @list is NULL,
 * just return the number of properties available, otherwise fill up to @count
 * items in the list with property identifiers.
 *
 * Returns the number of total properties if @list is NULL or the number of
 * properties copied to @list.
 */
int kgsl_query_property_list(struct kgsl_device *device, u32 *list, u32 count);

/**
 * kgsl_get_bus_scale_table() - Get the bus scaling table from devicetree
 * @device: kgsl device handle
+33 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 */

#ifndef _UAPI_MSM_KGSL_H
@@ -336,6 +336,38 @@ enum kgsl_timestamp_type {
#define KGSL_PROP_SECURE_BUFFER_ALIGNMENT 0x23
#define KGSL_PROP_SECURE_CTXT_SUPPORT 0x24
#define KGSL_PROP_SPEED_BIN		0x25
/* KGSL_PROP_GAMING_BIN	is 0x26 in 4.14 but not yet supported here */
#define KGSL_PROP_QUERY_CAPABILITIES	0x27

/*
 * kgsl_capabilties_properties returns a list of supported properties.
 * If the user passes 0 for 'count' the kernel will set it to the number of
 * supported properties. The list is expected to be 'count * sizeof(uint32_t)'
 * bytes long. The kernel will return the actual number of entries copied into
 * list via 'count'.
 */
struct kgsl_capabilities_properties {
	__u64 list;
	__u32 count;
};

/*
 * KGSL_QUERY_CAPS_PROPERTIES returns a list of the valid properties in the
 * kernel.  The subtype data should be struct kgsl_capabilities_properties
 */
#define KGSL_QUERY_CAPS_PROPERTIES 1

/*
 * kgsl_capabilities allows the user to query kernel capabiilties. The 'data'
 * type should be set appropriately for the querytype (see above). Pass 0 to
 * 'size' and the kernel will set it to the expected size of 'data' that is
 * appropriate for querytype (in bytes).
 */
struct kgsl_capabilities {
	__u64 data;
	__u64 size;
	__u32 querytype;
};

struct kgsl_shadowprop {
	unsigned long gpuaddr;