Loading drivers/gpu/msm/adreno_a6xx_preempt.c +49 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,38 @@ static struct adreno_ringbuffer *a6xx_next_ringbuffer( return NULL; } #define GMU_ACTIVE_STATE_RETRY_MAX 100 static int adreno_gmu_wait_for_active(struct adreno_device *adreno_dev) { unsigned int reg, num_retries = 0; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); if (!kgsl_gmu_isenabled(device)) return 0; kgsl_gmu_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, ®); while (reg != GPU_HW_ACTIVE) { /* Wait for small time before trying again */ udelay(5); kgsl_gmu_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, ®); if (num_retries == GMU_ACTIVE_STATE_RETRY_MAX && reg != GPU_HW_ACTIVE) { dev_err(adreno_dev->dev.dev, "GMU failed to move to ACTIVE state: 0x%x\n", reg); return -ETIMEDOUT; } num_retries++; } return 0; } void a6xx_preemption_trigger(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading Loading @@ -361,6 +393,23 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev) upper_32_bits(gpuaddr), FENCE_STATUS_WRITEDROPPED1_MASK); /* * Above fence writes will make sure GMU comes out of * IFPC state if its was in IFPC state but it doesn't * guarantee that GMU FW actually moved to ACTIVE state * i.e. wake-up from IFPC is complete. * Wait for GMU to move to ACTIVE state before triggering * preemption. This is require to make sure CP doesn't * interrupt GMU during wake-up from IFPC. */ if (adreno_gmu_wait_for_active(adreno_dev)) { adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE); adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); adreno_dispatcher_schedule(device); return; } adreno_dev->next_rb = next; /* Start the timer to detect a stuck preemption */ Loading Loading
drivers/gpu/msm/adreno_a6xx_preempt.c +49 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,38 @@ static struct adreno_ringbuffer *a6xx_next_ringbuffer( return NULL; } #define GMU_ACTIVE_STATE_RETRY_MAX 100 static int adreno_gmu_wait_for_active(struct adreno_device *adreno_dev) { unsigned int reg, num_retries = 0; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); if (!kgsl_gmu_isenabled(device)) return 0; kgsl_gmu_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, ®); while (reg != GPU_HW_ACTIVE) { /* Wait for small time before trying again */ udelay(5); kgsl_gmu_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, ®); if (num_retries == GMU_ACTIVE_STATE_RETRY_MAX && reg != GPU_HW_ACTIVE) { dev_err(adreno_dev->dev.dev, "GMU failed to move to ACTIVE state: 0x%x\n", reg); return -ETIMEDOUT; } num_retries++; } return 0; } void a6xx_preemption_trigger(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); Loading Loading @@ -361,6 +393,23 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev) upper_32_bits(gpuaddr), FENCE_STATUS_WRITEDROPPED1_MASK); /* * Above fence writes will make sure GMU comes out of * IFPC state if its was in IFPC state but it doesn't * guarantee that GMU FW actually moved to ACTIVE state * i.e. wake-up from IFPC is complete. * Wait for GMU to move to ACTIVE state before triggering * preemption. This is require to make sure CP doesn't * interrupt GMU during wake-up from IFPC. */ if (adreno_gmu_wait_for_active(adreno_dev)) { adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE); adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT); adreno_dispatcher_schedule(device); return; } adreno_dev->next_rb = next; /* Start the timer to detect a stuck preemption */ Loading