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 <hdhatt@codeaurora.org>
This commit is contained in:
Harshdeep Dhatt 2020-09-16 14:44:57 -06:00
commit 4f3a132f88
3 changed files with 204 additions and 165 deletions

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"
@ -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);

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