diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 90fa9adbf4f4..ee52485bd4ca 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3348,11 +3348,7 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, break; /* Wait a small amount of time before trying again */ - if (in_atomic()) - udelay(GMU_CORE_WAKEUP_DELAY_US); - else - usleep_range(GMU_CORE_WAKEUP_DELAY_US, - 3 * GMU_CORE_WAKEUP_DELAY_US); + udelay(GMU_CORE_WAKEUP_DELAY_US); /* Try to write the fenced register again */ adreno_writereg(adreno_dev, offset, val); diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index 59cb54928686..a82c6397e9d5 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -36,8 +36,6 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) { struct adreno_ringbuffer *rb = adreno_dev->cur_rb; unsigned long flags; - bool write = false; - unsigned int val; int ret = 0; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -49,8 +47,29 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) * dispatcher context. Do it now. */ if (rb->skip_inline_wptr) { - write = true; - val = rb->wptr; + /* + * There could be a situation where GPU comes out of + * ifpc after a fenced write transaction but before + * reading AHB_FENCE_STATUS from KMD, it goes back to + * ifpc due to inactivity (kernel scheduler plays a + * role here). Thus, the GPU could technically be + * re-collapsed between subsequent register writes + * leading to a prolonged preemption sequence. The + * keepalive bit prevents any further power collapse + * while it is set. + */ + if (gmu_core_isenabled(device)) + gmu_core_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, + 0x0, 0x2); + + ret = adreno_gmu_fenced_write(adreno_dev, + ADRENO_REG_CP_RB_WPTR, rb->wptr, + FENCE_STATUS_WRITEDROPPED0_MASK); + + /* Clear the keep alive */ + if (gmu_core_isenabled(device)) + gmu_core_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, + 0x2, 0x0); reset_timer = true; rb->skip_inline_wptr = false; @@ -72,30 +91,6 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) spin_unlock_irqrestore(&rb->preempt_lock, flags); - if (write) { - bool gmu_core_enabled = gmu_core_isenabled(device); - - /* - * There could be a situation where GPU comes out of ifpc after - * a fenced write but before reading AHB_FENCE_STATUS from KMD, - * it goes back to ifpc due to inactivity (kernel scheduler - * plays a role here). Thus, the GPU could technically be - * re-collapsed between subsequent register writes leading to a - * prolonged preemption sequence. The keepalive bit prevents any - * further power collapse while it is set. - */ - if (gmu_core_enabled) - gmu_core_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, 0, 2); - - ret = adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_RB_WPTR, - val, - FENCE_STATUS_WRITEDROPPED0_MASK); - - /* Clear the keep alive */ - if (gmu_core_enabled) - gmu_core_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, 2, 0); - } - if (in_interrupt() == 0) { /* If WPTR update fails, set the fault and trigger recovery */ if (ret) { diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index e4c9313472a7..4eddaccc2c8d 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -92,8 +92,6 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev, { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); unsigned long flags; - bool write = false; - unsigned int val; int ret = 0; spin_lock_irqsave(&rb->preempt_lock, flags); @@ -106,9 +104,28 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev, */ kgsl_pwrscale_busy(KGSL_DEVICE(adreno_dev)); - write = true; - val = rb->_wptr; + /* + * There could be a situation where GPU comes out of + * ifpc after a fenced write transaction but before + * reading AHB_FENCE_STATUS from KMD, it goes back to + * ifpc due to inactivity (kernel scheduler plays a + * role here). Put a keep alive vote to avoid such + * unlikely scenario. + */ + if (gpudev->gpu_keepalive) + gpudev->gpu_keepalive(adreno_dev, true); + + /* + * Ensure the write posted after a possible + * GMU wakeup (write could have dropped during wakeup) + */ + ret = adreno_gmu_fenced_write(adreno_dev, + ADRENO_REG_CP_RB_WPTR, rb->_wptr, + FENCE_STATUS_WRITEDROPPED0_MASK); rb->skip_inline_wptr = false; + if (gpudev->gpu_keepalive) + gpudev->gpu_keepalive(adreno_dev, false); + } } else { /* @@ -123,29 +140,6 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev, rb->wptr = rb->_wptr; spin_unlock_irqrestore(&rb->preempt_lock, flags); - /* - * Ensure the write posted after a possible GMU wakeup (write could have - * dropped during wakeup) - */ - if (write) { - /* - * There could be a situation where GPU comes out of ifpc after - * a fenced write but before reading AHB_FENCE_STATUS from KMD, - * it goes back to ifpc due to inactivity (kernel scheduler - * plays a role here). Put a keep alive vote to avoid such an - * unlikely scenario. - */ - if (gpudev->gpu_keepalive) - gpudev->gpu_keepalive(adreno_dev, true); - - ret = adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_RB_WPTR, - val, - FENCE_STATUS_WRITEDROPPED0_MASK); - - if (gpudev->gpu_keepalive) - gpudev->gpu_keepalive(adreno_dev, false); - } - if (ret) { /* If WPTR update fails, set the fault and trigger recovery */ adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);