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:
Tashfin Shakeer Rhythm
2023-05-06 12:44:54 +06:00
committed by balgxmr
parent bce599d91e
commit 70f98fe87a
3 changed files with 45 additions and 60 deletions

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);