Loading drivers/gpu/msm/adreno.c +2 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading drivers/gpu/msm/adreno.h +5 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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; }; /** Loading drivers/gpu/msm/adreno_dispatch.c +55 −45 Original line number Diff line number Diff line Loading @@ -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); } /* Loading Loading @@ -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); Loading drivers/gpu/msm/adreno_dispatch.h +1 −10 Original line number Diff line number Diff line Loading @@ -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; }; Loading drivers/gpu/msm/adreno_drawctxt.c +6 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading
drivers/gpu/msm/adreno.c +2 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading
drivers/gpu/msm/adreno.h +5 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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; }; /** Loading
drivers/gpu/msm/adreno_dispatch.c +55 −45 Original line number Diff line number Diff line Loading @@ -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); } /* Loading Loading @@ -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); Loading
drivers/gpu/msm/adreno_dispatch.h +1 −10 Original line number Diff line number Diff line Loading @@ -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; }; Loading
drivers/gpu/msm/adreno_drawctxt.c +6 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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