diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 0fddc996..1d0b98b6 100755 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -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: