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

Commit 68918673 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

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

parents fceae6a2 2a826db0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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

+10 −5
Original line number Diff line number Diff line
@@ -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);

	if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
		set_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);

	return 0;
	}

error:
	a6xx_gmu_remove(device);
+66 −2
Original line number Diff line number Diff line
@@ -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];
}
+14 −0
Original line number Diff line number Diff line
@@ -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
+128 −2
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"
@@ -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);
Loading