Loading drivers/gpu/drm/msm/adreno/a5xx_gpu.h +7 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ struct a5xx_gpu { * PREEMPT_NONE - no preemption in progress. Next state START. * PREEMPT_START - The trigger is evaulating if preemption is possible. Next * states: TRIGGERED, NONE * PREEMPT_ABORT - An intermediate state before moving back to NONE. Next * state: NONE. * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next * states: FAULTED, PENDING * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger Loading @@ -81,6 +83,7 @@ struct a5xx_gpu { enum preempt_state { PREEMPT_NONE = 0, PREEMPT_START, PREEMPT_ABORT, PREEMPT_TRIGGERED, PREEMPT_FAULTED, PREEMPT_PENDING, Loading Loading @@ -184,7 +187,10 @@ int a5xx_snapshot(struct msm_gpu *gpu, struct msm_snapshot *snapshot); /* Return true if we are in a preempt state */ static inline bool a5xx_in_preempt(struct a5xx_gpu *a5xx_gpu) { return !(atomic_read(&a5xx_gpu->preempt_state) == PREEMPT_NONE); int preempt_state = atomic_read(&a5xx_gpu->preempt_state); return !(preempt_state == PREEMPT_NONE || preempt_state == PREEMPT_ABORT); } int a5xx_counters_init(struct adreno_gpu *adreno_gpu); Loading drivers/gpu/drm/msm/adreno/a5xx_preempt.c +14 −3 Original line number Diff line number Diff line Loading @@ -128,9 +128,20 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) * one do nothing except to update the wptr to the latest and greatest */ if (!ring || (a5xx_gpu->cur_ring == ring)) { update_wptr(gpu, ring); /* * Its possible that while a preemption request is in progress * from an irq context, a user context trying to submit might * fail to update the write pointer, because it determines * that the preempt state is not PREEMPT_NONE. * * Close the race by introducing an intermediate * state PREEMPT_ABORT to let the submit path * know that the ringbuffer is not going to change * and can safely update the write pointer. */ /* Set the state back to NONE */ set_preempt_state(a5xx_gpu, PREEMPT_ABORT); update_wptr(gpu, a5xx_gpu->cur_ring); set_preempt_state(a5xx_gpu, PREEMPT_NONE); return; } Loading Loading
drivers/gpu/drm/msm/adreno/a5xx_gpu.h +7 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ struct a5xx_gpu { * PREEMPT_NONE - no preemption in progress. Next state START. * PREEMPT_START - The trigger is evaulating if preemption is possible. Next * states: TRIGGERED, NONE * PREEMPT_ABORT - An intermediate state before moving back to NONE. Next * state: NONE. * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next * states: FAULTED, PENDING * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger Loading @@ -81,6 +83,7 @@ struct a5xx_gpu { enum preempt_state { PREEMPT_NONE = 0, PREEMPT_START, PREEMPT_ABORT, PREEMPT_TRIGGERED, PREEMPT_FAULTED, PREEMPT_PENDING, Loading Loading @@ -184,7 +187,10 @@ int a5xx_snapshot(struct msm_gpu *gpu, struct msm_snapshot *snapshot); /* Return true if we are in a preempt state */ static inline bool a5xx_in_preempt(struct a5xx_gpu *a5xx_gpu) { return !(atomic_read(&a5xx_gpu->preempt_state) == PREEMPT_NONE); int preempt_state = atomic_read(&a5xx_gpu->preempt_state); return !(preempt_state == PREEMPT_NONE || preempt_state == PREEMPT_ABORT); } int a5xx_counters_init(struct adreno_gpu *adreno_gpu); Loading
drivers/gpu/drm/msm/adreno/a5xx_preempt.c +14 −3 Original line number Diff line number Diff line Loading @@ -128,9 +128,20 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) * one do nothing except to update the wptr to the latest and greatest */ if (!ring || (a5xx_gpu->cur_ring == ring)) { update_wptr(gpu, ring); /* * Its possible that while a preemption request is in progress * from an irq context, a user context trying to submit might * fail to update the write pointer, because it determines * that the preempt state is not PREEMPT_NONE. * * Close the race by introducing an intermediate * state PREEMPT_ABORT to let the submit path * know that the ringbuffer is not going to change * and can safely update the write pointer. */ /* Set the state back to NONE */ set_preempt_state(a5xx_gpu, PREEMPT_ABORT); update_wptr(gpu, a5xx_gpu->cur_ring); set_preempt_state(a5xx_gpu, PREEMPT_NONE); return; } Loading