msm: kgsl: Add a sysfs node to control performance counter reads

Currently performance counters are global and can be read by anyone. Change
the behaviour to disable reading global counters as default and add a sysfs
node to enable/disable reads.

Change-Id: Ic3785acd9bd7425c2a844ed103d7b870d9f80adf
Signed-off-by: Mohammed Mirza Mandayappurath Manzoor <quic_mmandaya@quicinc.com>
Signed-off-by: Pankaj Gupta <quic_gpankaj@quicinc.com>
Signed-off-by: Harshitha Sai Neelati <quic_hsaineel@quicinc.com>
This commit is contained in:
Pankaj Gupta 2022-03-01 20:17:37 +05:30 • committed by Gerrit - the friendly Code Review server
commit cc4445fc27
5 changed files with 59 additions and 1 deletions

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2002,2007-2018,2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -1426,6 +1427,8 @@ static int adreno_probe(struct platform_device *pdev)
adreno_debugfs_init(adreno_dev);
adreno_profile_init(adreno_dev);
adreno_dev->perfcounter = false;
adreno_sysfs_init(adreno_dev);
kgsl_pwrscale_init(&pdev->dev, CONFIG_QCOM_ADRENO_DEFAULT_GOVERNOR);

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2008-2018,2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -578,6 +579,11 @@ struct adreno_device {
bool gpuhtw_llc_slice_enable;
unsigned int zap_loaded;
unsigned int soc_hw_rev;
/*
* @perfcounter: Flag to clear perfcounters across contexts and
* controls perfcounter ioctl read
*/
bool perfcounter;
};
/**

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -260,6 +261,14 @@ static long adreno_ioctl_perfcounter_read_compat(
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;

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2002,2007-2018,2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -141,6 +142,14 @@ static long adreno_ioctl_perfcounter_read(struct kgsl_device_private *dev_priv,
struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_priv->device);
struct kgsl_perfcounter_read *read = data;
/*
* 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;
return (long) adreno_perfcounter_read_group(adreno_dev, read->reads,
read->count);
}

View file

@ -1,4 +1,5 @@
/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -353,6 +354,31 @@ static unsigned int _preempt_count_show(struct adreno_device *adreno_dev)
return preempt->count;
}
static unsigned int _perfcounter_show(struct adreno_device *adreno_dev)
{
return adreno_dev->perfcounter;
}
static int _perfcounter_store(struct adreno_device *adreno_dev,
unsigned int val)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
if (adreno_dev->perfcounter == val)
return 0;
mutex_lock(&device->mutex);
/* Power down the GPU before changing the state */
kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
adreno_dev->perfcounter = val;
kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
mutex_unlock(&device->mutex);
return 0;
}
static ssize_t _sysfs_store_u32(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@ -457,6 +483,7 @@ static ADRENO_SYSFS_BOOL(hwcg);
static ADRENO_SYSFS_BOOL(throttling);
static ADRENO_SYSFS_BOOL(ifpc);
static ADRENO_SYSFS_RO_U32(ifpc_count);
static ADRENO_SYSFS_BOOL(perfcounter);
@ -480,6 +507,7 @@ static const struct device_attribute *_attr_list[] = {
&adreno_attr_ifpc.attr,
&adreno_attr_ifpc_count.attr,
&adreno_attr_preempt_count.attr,
&adreno_attr_perfcounter.attr,
NULL,
};
@ -637,8 +665,11 @@ int adreno_sysfs_init(struct adreno_device *adreno_dev)
ret = kgsl_create_device_sysfs_files(device->dev, _attr_list);
/* Add the PPD directory and files */
if (ret == 0)
if (ret == 0) {
/* Notify userspace */
kobject_uevent(&device->dev->kobj, KOBJ_ADD);
ppd_sysfs_init(adreno_dev);
}
return 0;
}