From f6acf3ab9f87b346cf1c6e3de3a470c0ec606081 Mon Sep 17 00:00:00 2001 From: SecureCRT Date: Sat, 23 Jun 2012 17:48:20 +0800 Subject: [PATCH] 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. --- drivers/gpu/msm/adreno.c | 31 +++++++++++++++---------------- drivers/gpu/msm/kgsl.c | 3 ++- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 739f2276..e9ddb5e2 100755 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1182,13 +1182,21 @@ static int adreno_waittimestamp(struct kgsl_device *device, 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 (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. + */ + queue_work(device->work_queue, &device->ts_expired_ws); + status = 0; + goto done; + } 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) +// pwr->pwrlevels[pwr->active_pwrlevel].o_fraction) // io = 0; mutex_unlock(&device->mutex); /* We need to make sure that the process is @@ -1212,28 +1220,19 @@ static int adreno_waittimestamp(struct kgsl_device *device, } /*this wait timed out*/ } - } - 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, + "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 { + if (!adreno_idle(device, KGSL_TIMEOUT_DEFAULT)) status = 0; } - done: return (int)status; } diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index e06a7c7e..6f1120de 100755 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -99,7 +99,8 @@ static int kgsl_add_event(struct kgsl_device *device, u32 ts, if (n == &device->events) list_add_tail(&event->list, &device->events); - + + queue_work(device->work_queue, &device->ts_expired_ws); return 0; } #endif