msm: kgsl: fix error handling in adreno_waittimestamp()
This function was incorrectly reporting hangs when an error such as ERESTARTSYS was returned by __wait_event_interruptible_timeout(). msm: kgsl: Make sure WPTR reg is updated properly Sometimes writes to WPTR register do not take effect, causing a 3D core hang. Make sure the WPTR is updated properly when waiting. msm: kgsl: Set default value of wait_timeout in the adreno_dev struct Set the initalization value of wait_timeout at compile time in the declaration of the adreno_device struct instead of at runtime in adreno_probe.
This commit is contained in:
parent
73aff24078
commit
ae32a212a5
@ -120,6 +120,7 @@ static struct adreno_device device_3d0 = {
|
||||
},
|
||||
.pfp_fw = NULL,
|
||||
.pm4_fw = NULL,
|
||||
.wait_timeout = 10000, /* in milliseconds */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -432,8 +433,6 @@ adreno_probe(struct platform_device *pdev)
|
||||
adreno_dev = ADRENO_DEVICE(device);
|
||||
device->parentdev = &pdev->dev;
|
||||
|
||||
adreno_dev->wait_timeout = 10000; /* default value in milliseconds */
|
||||
|
||||
init_completion(&device->recovery_gate);
|
||||
|
||||
status = adreno_ringbuffer_init(device);
|
||||
@ -834,6 +833,12 @@ static int adreno_getproperty(struct kgsl_device *device,
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline void adreno_poke(struct kgsl_device *device)
|
||||
{
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
adreno_regwrite(device, REG_CP_RB_WPTR, adreno_dev->ringbuffer.wptr);
|
||||
}
|
||||
|
||||
/* Caller must hold the device mutex. */
|
||||
int adreno_idle(struct kgsl_device *device, unsigned int timeout)
|
||||
{
|
||||
@ -852,6 +857,7 @@ int adreno_idle(struct kgsl_device *device, unsigned int timeout)
|
||||
retry:
|
||||
if (rb->flags & KGSL_FLAGS_STARTED) {
|
||||
do {
|
||||
adreno_poke(device);
|
||||
GSL_RB_GET_READPTR(rb, &rb->rptr);
|
||||
if (time_after(jiffies, wait_time)) {
|
||||
KGSL_DRV_ERR(device, "rptr: %x, wptr: %x\n",
|
||||
@ -1111,8 +1117,12 @@ static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
{
|
||||
long status = 0;
|
||||
uint io = 1;
|
||||
static uint io_cnt;
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
|
||||
int retries;
|
||||
unsigned int msecs_first;
|
||||
unsigned int msecs_part;
|
||||
|
||||
/* Don't wait forever, set a max value for now */
|
||||
if (msecs == -1)
|
||||
@ -1125,26 +1135,45 @@ static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
status = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Keep the first timeout as 100msecs before rewriting
|
||||
* the WPTR. Less visible impact if the WPTR has not
|
||||
* been updated properly.
|
||||
*/
|
||||
msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
|
||||
msecs_part = (msecs - msecs_first + 3) / 4;
|
||||
for (retries = 0; retries < 5; retries++) {
|
||||
if (!kgsl_check_timestamp(device, timestamp)) {
|
||||
if (pwr->active_pwrlevel) {
|
||||
int low_pwrlevel = pwr->num_pwrlevels -
|
||||
KGSL_PWRLEVEL_LOW_OFFSET;
|
||||
if (pwr->active_pwrlevel == low_pwrlevel)
|
||||
io = 0;
|
||||
}
|
||||
adreno_poke(device);
|
||||
// the QSD8X50 don't support io_fraction ?? // SecureCRT 2012-06-20
|
||||
// io_cnt = (io_cnt + 1) % 100;
|
||||
// if (io_cnt <
|
||||
// pwr->pwrlevels[pwr->active_pwrlevel].
|
||||
// io_fraction)
|
||||
// io = 0;
|
||||
mutex_unlock(&device->mutex);
|
||||
/* We need to make sure that the process is placed in wait-q
|
||||
* before its condition is called */
|
||||
/* We need to make sure that the process is
|
||||
* placed in wait-q before its condition is called
|
||||
*/
|
||||
status = kgsl_wait_event_interruptible_timeout(
|
||||
device->wait_queue,
|
||||
kgsl_check_interrupt_timestamp(device,
|
||||
timestamp),
|
||||
msecs_to_jiffies(msecs), io);
|
||||
msecs_to_jiffies(retries ?
|
||||
msecs_part : msecs_first), io);
|
||||
mutex_lock(&device->mutex);
|
||||
|
||||
if (status > 0)
|
||||
status = 0;
|
||||
else if (status == 0) {
|
||||
if (status > 0) {
|
||||
/*completed before the wait finished */
|
||||
status = 0;
|
||||
goto done;
|
||||
} else if (status < 0) {
|
||||
/*an error occurred*/
|
||||
goto done;
|
||||
}
|
||||
/*this wait timed out*/
|
||||
}
|
||||
}
|
||||
if (!kgsl_check_timestamp(device, timestamp)) {
|
||||
status = -ETIMEDOUT;
|
||||
KGSL_DRV_ERR(device,
|
||||
@ -1162,8 +1191,8 @@ static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
KGSL_TIMEOUT_DEFAULT))
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
|
Loading…
x
Reference in New Issue
Block a user