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

Commit 990059b7 authored by Prakash Kamliya's avatar Prakash Kamliya
Browse files

msm: kgsl: Change the active context tracker



The active context tracker that we bolted on the side of the
dispatcher was designed mainly to see if there was 1 OR more than 1
active context, not much more than that.  Since it is apparent that
we'll need to track up to 4 contexts and possibly more later the
algorithm needs to change.

The new algorithm puts all active contexts on a linked list  - every
time a context is used it is popped from the list and put on the
tip with an updated time. To count the number of active contexts
walk the list until you get a context with an active time older than
you are looking for.  You also can do other magic on the context,
like see if it matches up with a given command queue.

Change-Id: Ic0dedbad6be9fd1925121ee54e0000c42b089f44
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: default avatarPrakash Kamliya <pkamliya@codeaurora.org>
parent a8371783
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@ static struct adreno_device device_3d0 = {
	.pwrctrl_flag = BIT(ADRENO_SPTP_PC_CTRL) | BIT(ADRENO_PPD_CTRL) |
		BIT(ADRENO_LM_CTRL) | BIT(ADRENO_HWCG_CTRL),
	.profile.enabled = false,
	.active_list = LIST_HEAD_INIT(device_3d0.active_list),
	.active_list_lock = __SPIN_LOCK_UNLOCKED(device_3d0.active_list_lock),
};

/* Ptr to array for the current set of fault detect registers */
+5 −0
Original line number Diff line number Diff line
@@ -326,6 +326,8 @@ struct adreno_gpu_core {
 * @csdev: Pointer to a coresight device (if applicable)
 * @gpmu_throttle_counters - counteers for number of throttled clocks
 * @irq_storm_work: Worker to handle possible interrupt storms
 * @active_list: List to track active contexts
 * @active_list_lock: Lock to protect active_list
 */
struct adreno_device {
	struct kgsl_device dev;    /* Must be first field in this struct */
@@ -387,6 +389,9 @@ struct adreno_device {
	struct coresight_device *csdev;
	uint32_t gpmu_throttle_counters[ADRENO_GPMU_THROTTLE_COUNTERS];
	struct work_struct irq_storm_work;

	struct list_head active_list;
	spinlock_t active_list_lock;
};

/**
+55 −45
Original line number Diff line number Diff line
@@ -78,59 +78,69 @@ unsigned int adreno_cmdbatch_timeout = 2000;
/* Interval for reading and comparing fault detection registers */
static unsigned int _fault_timer_interval = 200;

/**
 * _track_context - Add a context ID to the list of recently seen contexts
 * for the command queue
 * @cmdqueue: cmdqueue to add the context to
 * @id: ID of the context to add
 *
 * This function is called when a new item is added to a context - this tracks
 * the number of active contexts seen in the last 100ms for the command queue
 */
static void _track_context(struct adreno_dispatcher_cmdqueue *cmdqueue,
		unsigned int id)
static void _add_context(struct adreno_device *adreno_dev,
		struct adreno_context *drawctxt)
{
	struct adreno_context_list *list = cmdqueue->active_contexts;
	int oldest = -1, empty = -1;
	unsigned long age = 0;
	int i, count = 0;
	bool updated = false;

	for (i = 0; i < ACTIVE_CONTEXT_LIST_MAX; i++) {

		/* If the new ID matches the slot update the expire time */
		if (list[i].id == id) {
			list[i].jiffies = jiffies + msecs_to_jiffies(100);
			updated = true;
			count++;
			continue;
		}
	/* Remove it from the list */
	list_del_init(&drawctxt->active_node);

		/* Remember and skip empty slots */
		if ((list[i].id == 0) ||
			time_after(jiffies, list[i].jiffies)) {
			empty = i;
			continue;
	/* And push it to the front */
	drawctxt->active_time = jiffies;
	list_add(&drawctxt->active_node, &adreno_dev->active_list);
}

		count++;
static int __count_context(struct adreno_context *drawctxt, void *data)
{
	unsigned long expires = drawctxt->active_time + msecs_to_jiffies(100);

		/* Remember the oldest active entry */
		if (oldest == -1 || time_before(list[i].jiffies, age)) {
			age = list[i].jiffies;
			oldest = i;
	return time_after(jiffies, expires) ? 0 : 1;
}

static int __count_cmdqueue_context(struct adreno_context *drawctxt, void *data)
{
	unsigned long expires = drawctxt->active_time + msecs_to_jiffies(100);

	if (time_after(jiffies, expires))
		return 0;

	return (&drawctxt->rb->dispatch_q ==
			(struct adreno_dispatcher_cmdqueue *) data) ? 1 : 0;
}

	if (updated == false) {
		int pos = (empty != -1) ? empty : oldest;
static int _adreno_count_active_contexts(struct adreno_device *adreno_dev,
		int (*func)(struct adreno_context *, void *), void *data)
{
	struct adreno_context *ctxt;
	int count = 0;

	list_for_each_entry(ctxt, &adreno_dev->active_list, active_node) {
		if (func(ctxt, data) == 0)
			return count;

		list[pos].jiffies = jiffies + msecs_to_jiffies(100);
		list[pos].id = id;
		count++;
	}

	cmdqueue->active_context_count = count;
	return count;
}

static void _track_context(struct adreno_device *adreno_dev,
		struct adreno_dispatcher_cmdqueue *cmdqueue,
		struct adreno_context *drawctxt)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);

	spin_lock(&adreno_dev->active_list_lock);

	_add_context(adreno_dev, drawctxt);

	device->active_context_count =
			_adreno_count_active_contexts(adreno_dev,
					__count_context, NULL);
	cmdqueue->active_context_count =
			_adreno_count_active_contexts(adreno_dev,
					__count_cmdqueue_context, cmdqueue);

	spin_unlock(&adreno_dev->active_list_lock);
}

/*
@@ -1174,7 +1184,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
	drawctxt->queued++;
	trace_adreno_cmdbatch_queued(cmdbatch, drawctxt->queued);

	_track_context(dispatch_q, drawctxt->base.id);
	_track_context(adreno_dev, dispatch_q, drawctxt);

	spin_unlock(&drawctxt->lock);

+1 −10
Original line number Diff line number Diff line
@@ -64,28 +64,19 @@ enum adreno_dispatcher_starve_timer_states {

#define CMDQUEUE_NEXT(_i, _s) (((_i) + 1) % (_s))

#define ACTIVE_CONTEXT_LIST_MAX 2

struct adreno_context_list {
	unsigned int id;
	unsigned long jiffies;
};

/**
 * struct adreno_dispatcher_cmdqueue - List of commands for a RB level
 * @cmd_q: List of command batches submitted to dispatcher
 * @inflight: Number of commands inflight in this q
 * @head: Head pointer to the q
 * @tail: Queues tail pointer
 * @active_contexts: List of most recently seen contexts
 * @active_context_count: Number of active contexts in the active_contexts list
 * @active_context_count: Number of active contexts seen in this rb cmdqueue
 */
struct adreno_dispatcher_cmdqueue {
	struct kgsl_cmdbatch *cmd_q[ADRENO_DISPATCH_CMDQUEUE_SIZE];
	unsigned int inflight;
	unsigned int head;
	unsigned int tail;
	struct adreno_context_list active_contexts[ACTIVE_CONTEXT_LIST_MAX];
	int active_context_count;
};

+6 −0
Original line number Diff line number Diff line
@@ -420,6 +420,8 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,

	adreno_context_debugfs_init(ADRENO_DEVICE(device), drawctxt);

	INIT_LIST_HEAD(&drawctxt->active_node);

	/* copy back whatever flags we dediced were valid */
	*flags = drawctxt->base.flags;
	return &drawctxt->base;
@@ -462,6 +464,10 @@ void adreno_drawctxt_detach(struct kgsl_context *context)
	drawctxt = ADRENO_CONTEXT(context);
	rb = drawctxt->rb;

	spin_lock(&adreno_dev->active_list_lock);
	list_del_init(&drawctxt->active_node);
	spin_unlock(&adreno_dev->active_list_lock);

	/* deactivate context */
	mutex_lock(&device->mutex);
	if (rb->drawctxt_active == drawctxt) {
Loading