Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f3a132f authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

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: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent c7fdd108
Loading
Loading
Loading
Loading
+117 −0
Original line number Diff line number Diff line
@@ -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);
+9 −165
Original line number Diff line number Diff line
@@ -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,
+78 −0
Original line number Diff line number Diff line
/* 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