msm: kgsl: queue timestamp expired work more often
There are a some workloads where interrupts do not
always get generated, and as a result the timestamp
work was not triggered often enough.
Queue timestamp expired work from adreno_waittimestamp(),
when the timestamp expires while we are not waiting.
It is possible in this case that no interrupt fired
because no processes were waiting.
Queue timestamp expired work when freememontimestamp
is called, which reduces the amount of memory
built up by applications that use this api often.
CRs-Fixed: 336057
Change-Id: Ib4610dfa53af04b5a7b1eb51281d32d0e5be8471
Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index bde4045..06f4a14 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1160,57 +1160,56 @@
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)) {
- adreno_poke(device);
- 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
+ if (kgsl_check_timestamp(device, timestamp)) {
+ /* if the timestamp happens while we're not
+ * waiting, there's a chance that an interrupt
+ * will not be generated and thus the timestamp
+ * work needs to be queued.
*/
- status = kgsl_wait_event_interruptible_timeout(
- device->wait_queue,
- kgsl_check_interrupt_timestamp(device,
- timestamp),
- msecs_to_jiffies(retries ?
- msecs_part : msecs_first), io);
- mutex_lock(&device->mutex);
-
- 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*/
+ queue_work(device->work_queue, &device->ts_expired_ws);
+ status = 0;
+ goto done;
}
- }
- if (!kgsl_check_timestamp(device, timestamp)) {
- status = -ETIMEDOUT;
- KGSL_DRV_ERR(device,
- "Device hang detected while waiting "
- "for timestamp: %x, last "
- "submitted(rb->timestamp): %x, wptr: "
- "%x\n", timestamp,
- adreno_dev->ringbuffer.timestamp,
- adreno_dev->ringbuffer.wptr);
- if (!adreno_dump_and_recover(device)) {
- /* wait for idle after recovery as the
- * timestamp that this process wanted
- * to wait on may be invalid */
- if (!adreno_idle(device,
- KGSL_TIMEOUT_DEFAULT))
- status = 0;
- }
- } else {
- status = 0;
- }
+ adreno_poke(device);
+ 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
+ */
+ status = kgsl_wait_event_interruptible_timeout(
+ device->wait_queue,
+ kgsl_check_interrupt_timestamp(device,
+ timestamp),
+ msecs_to_jiffies(retries ?
+ msecs_part : msecs_first), io);
+ mutex_lock(&device->mutex);
+ 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*/
+ }
+ status = -ETIMEDOUT;
+ KGSL_DRV_ERR(device,
+ "Device hang detected while waiting for timestamp: %x,"
+ "last submitted(rb->timestamp): %x, wptr: %x\n",
+ timestamp, adreno_dev->ringbuffer.timestamp,
+ adreno_dev->ringbuffer.wptr);
+ if (!adreno_dump_and_recover(device)) {
+ /* wait for idle after recovery as the
+ * timestamp that this process wanted
+ * to wait on may be invalid */
+ if (!adreno_idle(device, KGSL_TIMEOUT_DEFAULT))
+ status = 0;
+ }
done:
return (int)status;
}