From 4f3a132f8831b175a2d58141ced3f1d8a0dcee7e Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Wed, 16 Sep 2020 14:44:57 -0600 Subject: [PATCH] msm: kgsl: Move preemption sysfs nodes to dispatcher This paves the way to hook preemption sysfs nodes to hwscheduling which need to talk to GMU when changing preemption parameters via sysfs. Change-Id: I6940dbf294ad71a18b2dcded207cbacf18ba661d Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno_dispatch.c | 117 ++++++++++++++++++++ drivers/gpu/msm/adreno_sysfs.c | 174 ++---------------------------- drivers/gpu/msm/adreno_sysfs.h | 78 ++++++++++++++ 3 files changed, 204 insertions(+), 165 deletions(-) create mode 100644 drivers/gpu/msm/adreno_sysfs.h diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 9d0c2604d7e4..88d4e734f377 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -4,8 +4,10 @@ */ #include +#include #include #include "adreno.h" +#include "adreno_sysfs.h" #include "adreno_trace.h" #include "kgsl_gmu_core.h" #include "kgsl_timeline.h" @@ -2658,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 @@ -2669,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); @@ -2690,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 { @@ -2839,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); diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index be8ef6db3d74..b926438c9391 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -6,18 +6,7 @@ #include #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, diff --git a/drivers/gpu/msm/adreno_sysfs.h b/drivers/gpu/msm/adreno_sysfs.h new file mode 100644 index 000000000000..66212d34dbc8 --- /dev/null +++ b/drivers/gpu/msm/adreno_sysfs.h @@ -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