Revert "msm: kgsl: Avoid busy waiting for fenced GMU writes"
This regresses 3DMark scores by a short margin due to regwrite being outside the spinlock that causes potential race condition. Hence, revert this. This reverts commit 0cbd93ad24ea0eaf839ed151149a1180ecf23a57. Reported-by: Kazuki H <kazukih0205@gmail.com> Suggested-by: Sultan Alsawaf <sultan@kerneltoast.com> Cc: EmanuelCN <emanuelghub@gmail.com> Signed-off-by: Tashfin Shakeer Rhythm <tashfinshakeerrhythm@gmail.com>
This commit is contained in:
committed by
balgxmr
parent
bce599d91e
commit
70f98fe87a
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user