Merge "msm: kgsl: Hook preemption sysfs nodes to hwscheduling"

This commit is contained in:
qctecmdr 2020-10-08 08:33:26 -07:00 • committed by Gerrit - the friendly Code Review server
commit 689186736c
9 changed files with 401 additions and 176 deletions

View file

@ -78,6 +78,7 @@
#define HFI_VALUE_LOG_EVENT_OFF 113
#define HFI_VALUE_DCVS_OBJ 114
#define HFI_VALUE_LM_CS0 115
#define HFI_VALUE_PREEMPT_COUNT 120
#define HFI_VALUE_GLOBAL_TOKEN 0xFFFFFFFF

View file

@ -987,18 +987,23 @@ static int a6xx_hwsched_bind(struct device *dev, struct device *master,
void *data)
{
struct kgsl_device *device = dev_get_drvdata(master);
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int ret;
ret = a6xx_gmu_probe(device, to_platform_device(dev));
if (ret)
goto error;
ret = a6xx_hwsched_hfi_probe(ADRENO_DEVICE(device));
ret = a6xx_hwsched_hfi_probe(adreno_dev);
if (ret)
goto error;
if (!ret) {
set_bit(GMU_DISPATCH, &device->gmu_core.flags);
return 0;
}
set_bit(GMU_DISPATCH, &device->gmu_core.flags);
if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
set_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
return 0;
error:
a6xx_gmu_remove(device);

View file

@ -296,7 +296,7 @@ static irqreturn_t a6xx_hwsched_hfi_handler(int irq, void *data)
}
/* Ignore OOB bits */
status &= GENMASK(31, 31 - (oob_max - 1));
status &= GENMASK(31 - (oob_max - 1), 0);
if (status & ~hfi->irq_mask)
dev_err_ratelimited(&gmu->pdev->dev,
@ -545,6 +545,9 @@ static struct mem_alloc_entry *get_mem_alloc_entry(
if (!(desc->flags & MEMFLAG_GFX_WRITEABLE))
flags |= KGSL_MEMFLAGS_GPUREADONLY;
if (desc->flags & MEMFLAG_GFX_SECURE)
flags |= KGSL_MEMFLAGS_SECURE;
entry->gpu_md = kgsl_allocate_global(device, desc->size, flags, priv,
memkind_string);
if (IS_ERR(entry->gpu_md)) {
@ -730,6 +733,26 @@ static void enable_async_hfi(struct adreno_device *adreno_dev)
(u32)~hfi->irq_mask);
}
static int enable_preemption(struct adreno_device *adreno_dev)
{
u32 data;
if (!adreno_is_preemption_enabled(adreno_dev))
return 0;
/*
* Bits [0:1] contains the preemption level
* Bit 2 is to enable/disable gmem save/restore
* Bit 3 is to enable/disable skipsaverestore
*/
data = FIELD_PREP(GENMASK(1, 0), adreno_dev->preempt.preempt_level) |
FIELD_PREP(BIT(2), adreno_dev->preempt.usesgmem) |
FIELD_PREP(BIT(3), adreno_dev->preempt.skipsaverestore);
return a6xx_hfi_send_feature_ctrl(adreno_dev, HFI_FEATURE_PREEMPTION, 1,
data);
}
int a6xx_hwsched_hfi_start(struct adreno_device *adreno_dev)
{
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
@ -766,7 +789,11 @@ int a6xx_hwsched_hfi_start(struct adreno_device *adreno_dev)
ret = a6xx_hfi_send_feature_ctrl(adreno_dev, HFI_FEATURE_KPROF, 1, 0);
if (ret)
return ret;
goto err;
ret = enable_preemption(adreno_dev);
if (ret)
goto err;
ret = a6xx_hfi_send_core_fw_start(adreno_dev);
if (ret)
@ -1326,3 +1353,40 @@ void a6xx_hwsched_context_detach(struct adreno_context *drawctxt)
mutex_unlock(&device->mutex);
}
int a6xx_hwsched_preempt_count_get(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct hfi_get_value_cmd cmd;
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
struct a6xx_hwsched_hfi *hfi = to_a6xx_hwsched_hfi(adreno_dev);
u32 seqnum = atomic_inc_return(&gmu->hfi.seqnum);
struct pending_cmd pending_ack;
int rc;
if (device->state != KGSL_STATE_ACTIVE)
return 0;
CMD_MSG_HDR(cmd, H2F_MSG_GET_VALUE);
cmd.hdr = MSG_HDR_SET_SEQNUM(cmd.hdr, seqnum);
cmd.type = HFI_VALUE_PREEMPT_COUNT;
cmd.subtype = 0;
add_waiter(hfi, cmd.hdr, &pending_ack);
rc = a6xx_hfi_cmdq_write(adreno_dev, (u32 *)&cmd);
if (rc)
goto done;
rc = wait_ack_completion(adreno_dev, &pending_ack);
if (rc)
goto done;
rc = check_ack_failure(adreno_dev, &pending_ack);
done:
del_waiter(hfi, &pending_ack);
return rc ? rc : pending_ack.results[2];
}

View file

@ -104,6 +104,9 @@ enum mem_kind {
/* Host initializes the buffer */
#define MEMFLAG_HOST_INIT BIT(9)
/* Gfx buffer needs to be secure */
#define MEMFLAG_GFX_SECURE BIT(12)
struct mem_alloc_entry {
struct hfi_mem_alloc_desc desc;
struct kgsl_memdesc *gpu_md;
@ -214,4 +217,15 @@ void a6xx_hwsched_context_detach(struct adreno_context *drawctxt);
/* Helper function to get to a6xx hwsched hfi device from adreno device */
struct a6xx_hwsched_hfi *to_a6xx_hwsched_hfi(struct adreno_device *adreno_dev);
/**
* a6xx_hwsched_preempt_count_get - Get preemption count from GMU
* @adreno_dev: Pointer to adreno device
*
* This function sends a GET_VALUE HFI packet to get the number of
* preemptions completed since last SLUMBER exit.
*
* Return: Preemption count on success or negative error on failure
*/
int a6xx_hwsched_preempt_count_get(struct adreno_device *adreno_dev);
#endif

View file

@ -4,8 +4,10 @@
*/
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <soc/qcom/msm_performance.h>
#include "adreno.h"
#include "adreno_sysfs.h"
#include "adreno_trace.h"
#include "kgsl_gmu_core.h"
#include "kgsl_timeline.h"
@ -858,8 +860,7 @@ static void dispatcher_handle_jobs_list(struct adreno_device *adreno_dev,
llist_for_each_entry_safe(job, next, list, node) {
int ret;
if (adreno_gpu_stopped(adreno_dev) ||
adreno_drawctxt_bad(job->drawctxt)) {
if (adreno_drawctxt_bad(job->drawctxt)) {
kgsl_context_put(&job->drawctxt->base);
kmem_cache_free(jobs_cache, job);
continue;
@ -879,6 +880,16 @@ static void dispatcher_handle_jobs_list(struct adreno_device *adreno_dev,
continue;
}
/*
* If gpu is in fault or dispatcher is halted, add back the jobs
* so that they are processed after recovery or when dispatcher
* is resumed.
*/
if (adreno_gpu_stopped(adreno_dev)) {
llist_add(&job->node, &dispatcher->jobs[id]);
continue;
}
ret = dispatcher_context_sendcmds(adreno_dev, job->drawctxt);
/*
@ -2649,6 +2660,116 @@ void adreno_dispatcher_stop_fault_timer(struct kgsl_device *device)
del_timer_sync(&dispatcher->fault_timer);
}
static int _skipsaverestore_store(struct adreno_device *adreno_dev, bool val)
{
adreno_dev->preempt.skipsaverestore = val ? true : false;
return 0;
}
static bool _skipsaverestore_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.skipsaverestore;
}
static int _usesgmem_store(struct adreno_device *adreno_dev, bool val)
{
adreno_dev->preempt.usesgmem = val ? true : false;
return 0;
}
static bool _usesgmem_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.usesgmem;
}
static int _preempt_level_store(struct adreno_device *adreno_dev,
unsigned int val)
{
adreno_dev->preempt.preempt_level = min_t(unsigned int, val, 2);
return 0;
}
static unsigned int _preempt_level_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.preempt_level;
}
static void change_preemption(struct adreno_device *adreno_dev, void *priv)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_context *context;
struct adreno_context *drawctxt;
struct adreno_ringbuffer *rb;
int id, i, ret;
/* Make sure all ringbuffers are finished */
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
ret = adreno_ringbuffer_waittimestamp(rb, rb->timestamp,
2 * 1000);
if (ret) {
dev_err(device->dev,
"Cannot disable preemption because couldn't idle ringbuffer[%d] ret: %d\n",
rb->id, ret);
return;
}
}
change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
adreno_dev->cur_rb = &adreno_dev->ringbuffers[0];
adreno_dev->next_rb = NULL;
adreno_dev->prev_rb = NULL;
/* Update the ringbuffer for each draw context */
write_lock(&device->context_lock);
idr_for_each_entry(&device->context_idr, context, id) {
drawctxt = ADRENO_CONTEXT(context);
drawctxt->rb = adreno_ctx_get_rb(adreno_dev, drawctxt);
/*
* Make sure context destroy checks against the correct
* ringbuffer's timestamp.
*/
adreno_rb_readtimestamp(adreno_dev, drawctxt->rb,
KGSL_TIMESTAMP_RETIRED, &drawctxt->internal_timestamp);
}
write_unlock(&device->context_lock);
}
static int _preemption_store(struct adreno_device *adreno_dev, bool val)
{
if (!(ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) ||
(test_bit(ADRENO_DEVICE_PREEMPTION,
&adreno_dev->priv) == val))
return 0;
return adreno_power_cycle(adreno_dev, change_preemption, NULL);
}
static bool _preemption_show(struct adreno_device *adreno_dev)
{
return adreno_is_preemption_enabled(adreno_dev);
}
static unsigned int _preempt_count_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.count;
}
static ADRENO_SYSFS_BOOL(preemption);
static ADRENO_SYSFS_U32(preempt_level);
static ADRENO_SYSFS_BOOL(usesgmem);
static ADRENO_SYSFS_BOOL(skipsaverestore);
static ADRENO_SYSFS_RO_U32(preempt_count);
static const struct attribute *_preempt_attr_list[] = {
&adreno_attr_preemption.attr.attr,
&adreno_attr_preempt_level.attr.attr,
&adreno_attr_usesgmem.attr.attr,
&adreno_attr_skipsaverestore.attr.attr,
&adreno_attr_preempt_count.attr.attr,
NULL,
};
/**
* adreno_dispatcher_close() - close the dispatcher
* @adreno_dev: pointer to the adreno device structure
@ -2660,6 +2781,7 @@ void adreno_dispatcher_close(struct adreno_device *adreno_dev)
struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
int i;
struct adreno_ringbuffer *rb;
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
mutex_lock(&dispatcher->mutex);
del_timer_sync(&dispatcher->timer);
@ -2681,6 +2803,8 @@ void adreno_dispatcher_close(struct adreno_device *adreno_dev)
kobject_put(&dispatcher->kobj);
kmem_cache_destroy(jobs_cache);
sysfs_remove_files(&device->dev->kobj, _preempt_attr_list);
}
struct dispatcher_attribute {
@ -2830,6 +2954,8 @@ int adreno_dispatcher_init(struct adreno_device *adreno_dev)
if (ret)
return ret;
sysfs_create_files(&device->dev->kobj, _preempt_attr_list);
mutex_init(&dispatcher->mutex);
timer_setup(&dispatcher->timer, adreno_dispatcher_timer, 0);

View file

@ -7,6 +7,7 @@
#include "adreno_a6xx.h"
#include "adreno_a6xx_hwsched.h"
#include "adreno_snapshot.h"
#include "adreno_sysfs.h"
#include "adreno_trace.h"
/* This structure represents inflight command object */
@ -1006,10 +1007,91 @@ void adreno_hwsched_start(struct adreno_device *adreno_dev)
adreno_hwsched_trigger(adreno_dev);
}
static int _skipsaverestore_store(struct adreno_device *adreno_dev, bool val)
{
return adreno_power_cycle_bool(adreno_dev,
&adreno_dev->preempt.skipsaverestore, val);
}
static bool _skipsaverestore_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.skipsaverestore;
}
static int _usesgmem_store(struct adreno_device *adreno_dev, bool val)
{
return adreno_power_cycle_bool(adreno_dev,
&adreno_dev->preempt.usesgmem, val);
}
static bool _usesgmem_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.usesgmem;
}
static int _preempt_level_store(struct adreno_device *adreno_dev,
unsigned int val)
{
return adreno_power_cycle_u32(adreno_dev,
&adreno_dev->preempt.preempt_level,
min_t(unsigned int, val, 2));
}
static unsigned int _preempt_level_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.preempt_level;
}
static void change_preemption(struct adreno_device *adreno_dev, void *priv)
{
change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
}
static int _preemption_store(struct adreno_device *adreno_dev, bool val)
{
if (!(ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) ||
(test_bit(ADRENO_DEVICE_PREEMPTION,
&adreno_dev->priv) == val))
return 0;
return adreno_power_cycle(adreno_dev, change_preemption, NULL);
}
static bool _preemption_show(struct adreno_device *adreno_dev)
{
return adreno_is_preemption_enabled(adreno_dev);
}
static unsigned int _preempt_count_show(struct adreno_device *adreno_dev)
{
int count = a6xx_hwsched_preempt_count_get(adreno_dev);
return count < 0 ? 0 : count;
}
static ADRENO_SYSFS_BOOL(preemption);
static ADRENO_SYSFS_U32(preempt_level);
static ADRENO_SYSFS_BOOL(usesgmem);
static ADRENO_SYSFS_BOOL(skipsaverestore);
static ADRENO_SYSFS_RO_U32(preempt_count);
static const struct attribute *_preempt_attr_list[] = {
&adreno_attr_preemption.attr.attr,
&adreno_attr_preempt_level.attr.attr,
&adreno_attr_usesgmem.attr.attr,
&adreno_attr_skipsaverestore.attr.attr,
&adreno_attr_preempt_count.attr.attr,
NULL,
};
void adreno_hwsched_dispatcher_close(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
kmem_cache_destroy(jobs_cache);
kmem_cache_destroy(obj_cache);
sysfs_remove_files(&device->dev->kobj, _preempt_attr_list);
}
static void adreno_hwsched_init_replay(struct adreno_hwsched *hwsched)
@ -1231,6 +1313,7 @@ static void adreno_hwsched_work(struct kthread_work *work)
void adreno_hwsched_init(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_hwsched *hwsched = to_hwsched(adreno_dev);
int i;
@ -1249,6 +1332,8 @@ void adreno_hwsched_init(struct adreno_device *adreno_dev)
init_llist_head(&hwsched->jobs[i]);
init_llist_head(&hwsched->requeue[i]);
}
sysfs_create_files(&device->dev->kobj, _preempt_attr_list);
}
void adreno_hwsched_mark_drawobj(struct adreno_device *adreno_dev,

View file

@ -6,18 +6,7 @@
#include <linux/sysfs.h>
#include "adreno.h"
struct adreno_sysfs_attribute_u32 {
struct device_attribute attr;
u32 (*show)(struct adreno_device *adreno_dev);
int (*store)(struct adreno_device *adreno_dev, u32 val);
};
struct adreno_sysfs_attribute_bool {
struct device_attribute attr;
bool (*show)(struct adreno_device *adreno_dev);
int (*store)(struct adreno_device *adreno_dev, bool val);
};
#include "adreno_sysfs.h"
static int _ft_policy_store(struct adreno_device *adreno_dev,
unsigned int val)
@ -31,47 +20,6 @@ static unsigned int _ft_policy_show(struct adreno_device *adreno_dev)
return adreno_dev->ft_policy;
}
static int _preempt_level_store(struct adreno_device *adreno_dev,
unsigned int val)
{
struct adreno_preemption *preempt = &adreno_dev->preempt;
if (val <= 2)
preempt->preempt_level = val;
return 0;
}
static unsigned int _preempt_level_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.preempt_level;
}
static int _usesgmem_store(struct adreno_device *adreno_dev, bool val)
{
struct adreno_preemption *preempt = &adreno_dev->preempt;
preempt->usesgmem = val ? true : false;
return 0;
}
static bool _usesgmem_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.usesgmem;
}
static int _skipsaverestore_store(struct adreno_device *adreno_dev, bool val)
{
struct adreno_preemption *preempt = &adreno_dev->preempt;
preempt->skipsaverestore = val ? true : false;
return 0;
}
static bool _skipsaverestore_show(struct adreno_device *adreno_dev)
{
return adreno_dev->preempt.skipsaverestore;
}
static int _ft_pagefault_policy_store(struct adreno_device *adreno_dev,
unsigned int val)
{
@ -139,62 +87,6 @@ static bool _ft_hang_intr_status_show(struct adreno_device *adreno_dev)
return true;
}
static void change_preemption(struct adreno_device *adreno_dev, void *priv)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_context *context;
struct adreno_context *drawctxt;
struct adreno_ringbuffer *rb;
int id, i, ret;
/* Make sure all ringbuffers are finished */
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
ret = adreno_ringbuffer_waittimestamp(rb, rb->timestamp,
2 * 1000);
if (ret) {
dev_err(device->dev,
"Cannot disable preemption because couldn't idle ringbuffer[%d] ret: %d\n",
rb->id, ret);
return;
}
}
change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
adreno_dev->cur_rb = &adreno_dev->ringbuffers[0];
adreno_dev->next_rb = NULL;
adreno_dev->prev_rb = NULL;
/* Update the ringbuffer for each draw context */
write_lock(&device->context_lock);
idr_for_each_entry(&device->context_idr, context, id) {
drawctxt = ADRENO_CONTEXT(context);
drawctxt->rb = adreno_ctx_get_rb(adreno_dev, drawctxt);
/*
* Make sure context destroy checks against the correct
* ringbuffer's timestamp.
*/
adreno_rb_readtimestamp(adreno_dev, drawctxt->rb,
KGSL_TIMESTAMP_RETIRED, &drawctxt->internal_timestamp);
}
write_unlock(&device->context_lock);
}
static int _preemption_store(struct adreno_device *adreno_dev, bool val)
{
if (!(ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) ||
(test_bit(ADRENO_DEVICE_PREEMPTION,
&adreno_dev->priv) == val))
return 0;
return adreno_power_cycle(adreno_dev, change_preemption, NULL);
}
static bool _preemption_show(struct adreno_device *adreno_dev)
{
return adreno_is_preemption_enabled(adreno_dev);
}
static int _hwcg_store(struct adreno_device *adreno_dev, bool val)
{
if (adreno_dev->hwcg_enabled == val)
@ -269,13 +161,6 @@ static unsigned int _ifpc_count_show(struct adreno_device *adreno_dev)
return adreno_dev->ifpc_count;
}
static unsigned int _preempt_count_show(struct adreno_device *adreno_dev)
{
struct adreno_preemption *preempt = &adreno_dev->preempt;
return preempt->count;
}
static bool _acd_show(struct adreno_device *adreno_dev)
{
return adreno_dev->acd_enabled;
@ -301,9 +186,8 @@ static int _bcl_store(struct adreno_device *adreno_dev, bool val)
val);
}
static ssize_t _sysfs_store_u32(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
ssize_t adreno_sysfs_store_u32(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev));
struct adreno_sysfs_attribute_u32 *_attr =
@ -322,9 +206,8 @@ static ssize_t _sysfs_store_u32(struct device *dev,
return count;
}
static ssize_t _sysfs_show_u32(struct device *dev,
struct device_attribute *attr,
char *buf)
ssize_t adreno_sysfs_show_u32(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev));
struct adreno_sysfs_attribute_u32 *_attr =
@ -333,9 +216,8 @@ static ssize_t _sysfs_show_u32(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "0x%X\n", _attr->show(adreno_dev));
}
static ssize_t _sysfs_store_bool(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
ssize_t adreno_sysfs_store_bool(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev));
struct adreno_sysfs_attribute_bool *_attr =
@ -354,9 +236,8 @@ static ssize_t _sysfs_store_bool(struct device *dev,
return count;
}
static ssize_t _sysfs_show_bool(struct device *dev,
struct device_attribute *attr,
char *buf)
ssize_t adreno_sysfs_show_bool(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_get_drvdata(dev));
struct adreno_sysfs_attribute_bool *_attr =
@ -364,39 +245,8 @@ static ssize_t _sysfs_show_bool(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%d\n", _attr->show(adreno_dev));
}
#define ADRENO_SYSFS_BOOL(_name) \
struct adreno_sysfs_attribute_bool adreno_attr_##_name = { \
.attr = __ATTR(_name, 0644, _sysfs_show_bool, _sysfs_store_bool), \
.show = _ ## _name ## _show, \
.store = _ ## _name ## _store, \
}
#define ADRENO_SYSFS_RO_BOOL(_name) \
struct adreno_sysfs_attribute_bool adreno_attr_##_name = { \
.attr = __ATTR(_name, 0444, _sysfs_show_bool, NULL), \
.show = _ ## _name ## _show, \
}
#define ADRENO_SYSFS_U32(_name) \
struct adreno_sysfs_attribute_u32 adreno_attr_##_name = { \
.attr = __ATTR(_name, 0644, _sysfs_show_u32, _sysfs_store_u32), \
.show = _ ## _name ## _show, \
.store = _ ## _name ## _store, \
}
#define ADRENO_SYSFS_RO_U32(_name) \
struct adreno_sysfs_attribute_u32 adreno_attr_##_name = { \
.attr = __ATTR(_name, 0444, _sysfs_show_u32, NULL), \
.show = _ ## _name ## _show, \
}
static ADRENO_SYSFS_U32(ft_policy);
static ADRENO_SYSFS_U32(ft_pagefault_policy);
static ADRENO_SYSFS_U32(preempt_level);
static ADRENO_SYSFS_RO_U32(preempt_count);
static ADRENO_SYSFS_BOOL(usesgmem);
static ADRENO_SYSFS_BOOL(skipsaverestore);
static ADRENO_SYSFS_BOOL(ft_long_ib_detect);
static ADRENO_SYSFS_RO_BOOL(ft_hang_intr_status);
static ADRENO_SYSFS_BOOL(gpu_llc_slice_enable);
@ -407,7 +257,6 @@ static DEVICE_INT_ATTR(wake_timeout, 0644, adreno_wake_timeout);
static ADRENO_SYSFS_BOOL(sptp_pc);
static ADRENO_SYSFS_BOOL(lm);
static ADRENO_SYSFS_BOOL(preemption);
static ADRENO_SYSFS_BOOL(hwcg);
static ADRENO_SYSFS_BOOL(throttling);
static ADRENO_SYSFS_BOOL(ifpc);
@ -425,17 +274,12 @@ static const struct attribute *_attr_list[] = {
&dev_attr_wake_timeout.attr.attr,
&adreno_attr_sptp_pc.attr.attr,
&adreno_attr_lm.attr.attr,
&adreno_attr_preemption.attr.attr,
&adreno_attr_hwcg.attr.attr,
&adreno_attr_throttling.attr.attr,
&adreno_attr_gpu_llc_slice_enable.attr.attr,
&adreno_attr_gpuhtw_llc_slice_enable.attr.attr,
&adreno_attr_preempt_level.attr.attr,
&adreno_attr_usesgmem.attr.attr,
&adreno_attr_skipsaverestore.attr.attr,
&adreno_attr_ifpc.attr.attr,
&adreno_attr_ifpc_count.attr.attr,
&adreno_attr_preempt_count.attr.attr,
&adreno_attr_acd.attr.attr,
&adreno_attr_bcl.attr.attr,
NULL,

View file

@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#ifndef _ADRENO_SYSFS_H_
#define _ADRENO_SYSFS_H_
/*
* struct adreno_sysfs_attribute_u32 - Container for accessing and modifying
* integers in kgsl via sysfs
*/
struct adreno_sysfs_attribute_u32 {
/** #attr: The device attribute corresponding to the sysfs node */
struct device_attribute attr;
/** @show: Function to show the value of the integer */
u32 (*show)(struct adreno_device *adreno_dev);
/** @store: Function to store the value of the integer */
int (*store)(struct adreno_device *adreno_dev, u32 val);
};
/*
* struct adreno_sysfs_attribute_bool - Container for accessing and modifying
* booleans in kgsl via sysfs
*/
struct adreno_sysfs_attribute_bool {
/** #attr: The device attribute corresponding to the sysfs node */
struct device_attribute attr;
/** @show: Function to show the value of the boolean */
bool (*show)(struct adreno_device *adreno_dev);
/** @store: Function to store the value of the boolean */
int (*store)(struct adreno_device *adreno_dev, bool val);
};
/* Helper function to modify an integer in kgsl */
ssize_t adreno_sysfs_store_u32(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
/* Helper function to read an integer in kgsl */
ssize_t adreno_sysfs_show_u32(struct device *dev,
struct device_attribute *attr, char *buf);
/* Helper function to modify a boolean in kgsl */
ssize_t adreno_sysfs_store_bool(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
/* Helper function to read a boolean in kgsl */
ssize_t adreno_sysfs_show_bool(struct device *dev,
struct device_attribute *attr, char *buf);
#define ADRENO_SYSFS_BOOL(_name) \
struct adreno_sysfs_attribute_bool adreno_attr_##_name = { \
.attr = __ATTR(_name, 0644, adreno_sysfs_show_bool, \
adreno_sysfs_store_bool), \
.show = _ ## _name ## _show, \
.store = _ ## _name ## _store, \
}
#define ADRENO_SYSFS_RO_BOOL(_name) \
struct adreno_sysfs_attribute_bool adreno_attr_##_name = { \
.attr = __ATTR(_name, 0444, adreno_sysfs_show_bool, NULL), \
.show = _ ## _name ## _show, \
}
#define ADRENO_SYSFS_U32(_name) \
struct adreno_sysfs_attribute_u32 adreno_attr_##_name = { \
.attr = __ATTR(_name, 0644, adreno_sysfs_show_u32, \
adreno_sysfs_store_u32), \
.show = _ ## _name ## _show, \
.store = _ ## _name ## _store, \
}
#define ADRENO_SYSFS_RO_U32(_name) \
struct adreno_sysfs_attribute_u32 adreno_attr_##_name = { \
.attr = __ATTR(_name, 0444, adreno_sysfs_show_u32, NULL), \
.show = _ ## _name ## _show, \
}
#endif

View file

@ -72,11 +72,19 @@ static int globals_print(struct seq_file *s, void *unused)
list_for_each_entry(md, &device->globals, node) {
struct kgsl_memdesc *memdesc = &md->memdesc;
char flags[6];
seq_printf(s, "0x%pK-0x%pK %16llu %s\n",
flags[0] = memdesc->priv & KGSL_MEMDESC_PRIVILEGED ? 'p' : '-';
flags[1] = !(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY) ? 'w' : '-';
flags[2] = kgsl_memdesc_is_secured(memdesc) ? 's' : '-';
flags[3] = memdesc->priv & KGSL_MEMDESC_RANDOM ? 'r' : '-';
flags[4] = memdesc->priv & KGSL_MEMDESC_UCODE ? 'u' : '-';
flags[5] = '\0';
seq_printf(s, "0x%pK-0x%pK %16llu %5s %s\n",
(u64 *)(uintptr_t) memdesc->gpuaddr,
(u64 *)(uintptr_t) (memdesc->gpuaddr +
memdesc->size - 1), memdesc->size,
memdesc->size - 1), memdesc->size, flags,
md->name);
}