880d405719
git-subtree-dir: qcom/opensource/graphics-kernel git-subtree-mainline:992813d9c1
git-subtree-split:b4fdc4c042
Change-Id: repo: https://git.codelinaro.org/clo/la/platform/vendor/qcom/opensource/graphics-kernel tag: GRAPHICS.LA.14.0.r1-07700-lanai.0
194 lines
5.0 KiB
C
194 lines
5.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
|
|
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "adreno.h"
|
|
#include "adreno_compat.h"
|
|
#include "kgsl_compat.h"
|
|
|
|
int adreno_getproperty_compat(struct kgsl_device *device,
|
|
struct kgsl_device_getproperty *param)
|
|
{
|
|
int status = -EINVAL;
|
|
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
|
|
|
switch (param->type) {
|
|
case KGSL_PROP_DEVICE_INFO:
|
|
{
|
|
struct kgsl_devinfo_compat devinfo;
|
|
|
|
if (param->sizebytes != sizeof(devinfo)) {
|
|
status = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
memset(&devinfo, 0, sizeof(devinfo));
|
|
devinfo.device_id = device->id + 1;
|
|
devinfo.chip_id = adreno_dev->chipid;
|
|
devinfo.mmu_enabled =
|
|
kgsl_mmu_has_feature(device, KGSL_MMU_PAGED);
|
|
devinfo.gmem_gpubaseaddr = 0;
|
|
devinfo.gmem_sizebytes =
|
|
adreno_dev->gpucore->gmem_size;
|
|
|
|
if (copy_to_user(param->value, &devinfo,
|
|
sizeof(devinfo))) {
|
|
status = -EFAULT;
|
|
break;
|
|
}
|
|
status = 0;
|
|
}
|
|
break;
|
|
case KGSL_PROP_DEVICE_SHADOW:
|
|
{
|
|
struct kgsl_shadowprop_compat shadowprop;
|
|
|
|
if (param->sizebytes != sizeof(shadowprop)) {
|
|
status = -EINVAL;
|
|
break;
|
|
}
|
|
memset(&shadowprop, 0, sizeof(shadowprop));
|
|
if (device->memstore->hostptr) {
|
|
/* Give a token address to identify memstore */
|
|
shadowprop.gpuaddr = (unsigned int)
|
|
KGSL_MEMSTORE_TOKEN_ADDRESS;
|
|
shadowprop.size =
|
|
(unsigned int) device->memstore->size;
|
|
/*
|
|
* GSL needs this to be set, even if it
|
|
* appears to be meaningless
|
|
*/
|
|
shadowprop.flags = KGSL_FLAGS_INITIALIZED |
|
|
KGSL_FLAGS_PER_CONTEXT_TIMESTAMPS;
|
|
}
|
|
if (copy_to_user(param->value, &shadowprop,
|
|
sizeof(shadowprop))) {
|
|
status = -EFAULT;
|
|
break;
|
|
}
|
|
status = 0;
|
|
}
|
|
break;
|
|
default:
|
|
status = device->ftbl->getproperty(device, param);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
int adreno_setproperty_compat(struct kgsl_device_private *dev_priv,
|
|
unsigned int type,
|
|
void __user *value,
|
|
unsigned int sizebytes)
|
|
{
|
|
int status = -EINVAL;
|
|
struct kgsl_device *device = dev_priv->device;
|
|
|
|
switch (type) {
|
|
case KGSL_PROP_PWR_CONSTRAINT:
|
|
case KGSL_PROP_L3_PWR_CONSTRAINT: {
|
|
struct kgsl_device_constraint_compat constraint32;
|
|
struct kgsl_device_constraint constraint;
|
|
struct kgsl_context *context;
|
|
|
|
if (sizebytes != sizeof(constraint32))
|
|
break;
|
|
|
|
if (copy_from_user(&constraint32, value,
|
|
sizeof(constraint32))) {
|
|
status = -EFAULT;
|
|
break;
|
|
}
|
|
|
|
/* Populate the real constraint type from the compat */
|
|
constraint.type = constraint32.type;
|
|
constraint.context_id = constraint32.context_id;
|
|
constraint.data = compat_ptr(constraint32.data);
|
|
constraint.size = (size_t)constraint32.size;
|
|
|
|
context = kgsl_context_get_owner(dev_priv,
|
|
constraint.context_id);
|
|
if (context == NULL)
|
|
break;
|
|
status = adreno_set_constraint(device, context,
|
|
&constraint);
|
|
kgsl_context_put(context);
|
|
}
|
|
break;
|
|
default:
|
|
/*
|
|
* Call adreno_setproperty in case the property type was
|
|
* KGSL_PROP_PWRCTRL
|
|
*/
|
|
status = device->ftbl->setproperty(dev_priv, type, value,
|
|
sizebytes);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static long adreno_ioctl_perfcounter_query_compat(
|
|
struct kgsl_device_private *dev_priv, unsigned int cmd,
|
|
void *data)
|
|
{
|
|
struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_priv->device);
|
|
struct kgsl_perfcounter_query_compat *query32 = data;
|
|
struct kgsl_perfcounter_query query;
|
|
long result;
|
|
|
|
query.groupid = query32->groupid;
|
|
query.countables = compat_ptr(query32->countables);
|
|
query.count = query32->count;
|
|
query.max_counters = query32->max_counters;
|
|
|
|
result = adreno_perfcounter_query_group(adreno_dev,
|
|
query.groupid, query.countables,
|
|
query.count, &query.max_counters);
|
|
query32->max_counters = query.max_counters;
|
|
|
|
return result;
|
|
}
|
|
|
|
static long adreno_ioctl_perfcounter_read_compat(
|
|
struct kgsl_device_private *dev_priv, unsigned int cmd,
|
|
void *data)
|
|
{
|
|
struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_priv->device);
|
|
struct kgsl_perfcounter_read_compat *read32 = data;
|
|
struct kgsl_perfcounter_read read;
|
|
|
|
/*
|
|
* When performance counter zapping is enabled, the counters are cleared
|
|
* across context switches. Reading the counters when they are zapped is
|
|
* not permitted.
|
|
*/
|
|
if (!adreno_dev->perfcounter)
|
|
return -EPERM;
|
|
|
|
read.reads = (struct kgsl_perfcounter_read_group __user *)
|
|
(uintptr_t)read32->reads;
|
|
read.count = read32->count;
|
|
|
|
return adreno_perfcounter_read_group(adreno_dev, read.reads,
|
|
read.count);
|
|
}
|
|
|
|
static struct kgsl_ioctl adreno_compat_ioctl_funcs[] = {
|
|
{ IOCTL_KGSL_PERFCOUNTER_GET, adreno_ioctl_perfcounter_get },
|
|
{ IOCTL_KGSL_PERFCOUNTER_PUT, adreno_ioctl_perfcounter_put },
|
|
{ IOCTL_KGSL_PERFCOUNTER_QUERY_COMPAT,
|
|
adreno_ioctl_perfcounter_query_compat },
|
|
{ IOCTL_KGSL_PERFCOUNTER_READ_COMPAT,
|
|
adreno_ioctl_perfcounter_read_compat },
|
|
};
|
|
|
|
long adreno_compat_ioctl(struct kgsl_device_private *dev_priv,
|
|
unsigned int cmd, unsigned long arg)
|
|
{
|
|
return adreno_ioctl_helper(dev_priv, cmd, arg,
|
|
adreno_compat_ioctl_funcs,
|
|
ARRAY_SIZE(adreno_compat_ioctl_funcs));
|
|
}
|