mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
msm: kgsl: Add suspend and resume for hwsched driver
Add the support for performing a driver wide suspend and resume with hwsched driver. Change-Id: I9bc47e714aaafd33f52ea618fdecf14cb512ea61 Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
parent
26b7004ddf
commit
0fc2ce7e40
7 changed files with 111 additions and 21 deletions
|
|
@ -1881,11 +1881,11 @@ static int adreno_last_close(struct kgsl_device *device)
|
|||
* Wait up to 1 second for the active count to go low
|
||||
* and then start complaining about it
|
||||
*/
|
||||
if (kgsl_active_count_wait(device, 0)) {
|
||||
if (kgsl_active_count_wait(device, 0, HZ)) {
|
||||
dev_err(device->dev,
|
||||
"Waiting for the active count to become 0\n");
|
||||
|
||||
while (kgsl_active_count_wait(device, 0))
|
||||
while (kgsl_active_count_wait(device, 0, HZ))
|
||||
dev_err(device->dev,
|
||||
"Still waiting for the active count\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3201,7 +3201,7 @@ static int a6xx_gmu_pm_suspend(struct adreno_device *adreno_dev)
|
|||
reinit_completion(&device->halt_gate);
|
||||
|
||||
/* wait for active count so device can be put in slumber */
|
||||
ret = kgsl_active_count_wait(device, 0);
|
||||
ret = kgsl_active_count_wait(device, 0, HZ);
|
||||
if (ret) {
|
||||
dev_err(device->dev,
|
||||
"Timed out waiting for the active count\n");
|
||||
|
|
@ -3232,10 +3232,9 @@ static void a6xx_gmu_pm_resume(struct adreno_device *adreno_dev)
|
|||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
|
||||
|
||||
if (!test_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags)) {
|
||||
dev_err(device->dev, "resume invoked without a suspend\n");
|
||||
if (WARN(!test_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags),
|
||||
"resume invoked without a suspend\n"))
|
||||
return;
|
||||
}
|
||||
|
||||
adreno_dispatcher_unhalt(device);
|
||||
|
||||
|
|
|
|||
|
|
@ -672,12 +672,95 @@ static int a6xx_hwsched_bus_set(struct adreno_device *adreno_dev, int buslevel,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int a6xx_hwsched_pm_suspend(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
|
||||
int ret;
|
||||
|
||||
if (test_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags))
|
||||
return 0;
|
||||
|
||||
trace_kgsl_pwr_request_state(device, KGSL_STATE_SUSPEND);
|
||||
|
||||
/* Halt any new submissions */
|
||||
reinit_completion(&device->halt_gate);
|
||||
|
||||
mutex_unlock(&device->mutex);
|
||||
|
||||
/* Flush any currently running instances of the dispatcher */
|
||||
kthread_flush_worker(&kgsl_driver.worker);
|
||||
|
||||
mutex_lock(&device->mutex);
|
||||
|
||||
/* This ensures that dispatcher doesn't submit any new work */
|
||||
adreno_dispatcher_halt(device);
|
||||
|
||||
/**
|
||||
* Wait for the dispatcher to retire everything by waiting
|
||||
* for the active count to go to zero.
|
||||
*/
|
||||
ret = kgsl_active_count_wait(device, 0, msecs_to_jiffies(100));
|
||||
if (ret) {
|
||||
dev_err(device->dev, "Timed out waiting for the active count\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (test_bit(GMU_PRIV_GPU_STARTED, &gmu->flags)) {
|
||||
unsigned long wait = jiffies +
|
||||
msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
|
||||
|
||||
do {
|
||||
if (a6xx_hw_isidle(adreno_dev))
|
||||
break;
|
||||
} while (time_before(jiffies, wait));
|
||||
|
||||
if (!a6xx_hw_isidle(adreno_dev)) {
|
||||
dev_err(device->dev, "Timed out idling the gpu\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
a6xx_hwsched_power_off(adreno_dev);
|
||||
}
|
||||
|
||||
set_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags);
|
||||
|
||||
trace_kgsl_pwr_set_state(device, KGSL_STATE_SUSPEND);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
adreno_dispatcher_unhalt(device);
|
||||
adreno_hwsched_start(adreno_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void a6xx_hwsched_pm_resume(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
|
||||
|
||||
if (WARN(!test_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags),
|
||||
"resume invoked without a suspend\n"))
|
||||
return;
|
||||
|
||||
adreno_dispatcher_unhalt(device);
|
||||
|
||||
adreno_hwsched_start(adreno_dev);
|
||||
|
||||
clear_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags);
|
||||
}
|
||||
|
||||
const struct adreno_power_ops a6xx_hwsched_power_ops = {
|
||||
.first_open = a6xx_hwsched_first_open,
|
||||
.last_close = a6xx_hwsched_power_off,
|
||||
.active_count_get = a6xx_hwsched_active_count_get,
|
||||
.active_count_put = a6xx_hwsched_active_count_put,
|
||||
.touch_wakeup = a6xx_hwsched_touch_wakeup,
|
||||
.pm_suspend = a6xx_hwsched_pm_suspend,
|
||||
.pm_resume = a6xx_hwsched_pm_resume,
|
||||
.gpu_clock_set = a6xx_hwsched_clock_set,
|
||||
.gpu_bus_set = a6xx_hwsched_bus_set,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1153,7 +1153,7 @@ static int a6xx_rgmu_pm_suspend(struct adreno_device *adreno_dev)
|
|||
reinit_completion(&device->halt_gate);
|
||||
|
||||
/* wait for active count so device can be put in slumber */
|
||||
ret = kgsl_active_count_wait(device, 0);
|
||||
ret = kgsl_active_count_wait(device, 0, HZ);
|
||||
if (ret) {
|
||||
dev_err(device->dev,
|
||||
"Timed out waiting for the active count\n");
|
||||
|
|
@ -1183,10 +1183,9 @@ static void a6xx_rgmu_pm_resume(struct adreno_device *adreno_dev)
|
|||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct a6xx_rgmu_device *rgmu = to_a6xx_rgmu(adreno_dev);
|
||||
|
||||
if (!test_bit(RGMU_PRIV_PM_SUSPEND, &rgmu->flags)) {
|
||||
dev_err(device->dev, "resume invoked without a suspend\n");
|
||||
if (WARN(!test_bit(GMU_PRIV_PM_SUSPEND, &rgmu->flags),
|
||||
"resume invoked without a suspend\n"))
|
||||
return;
|
||||
}
|
||||
|
||||
adreno_dispatcher_unhalt(device);
|
||||
|
||||
|
|
|
|||
|
|
@ -296,6 +296,13 @@ static int hwsched_sendcmd(struct adreno_device *adreno_dev,
|
|||
|
||||
mutex_lock(&device->mutex);
|
||||
|
||||
if (adreno_gpu_halt(adreno_dev) != 0) {
|
||||
mutex_unlock(&device->mutex);
|
||||
kmem_cache_free(obj_cache, obj);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
||||
if (kgsl_context_detached(context)) {
|
||||
mutex_unlock(&device->mutex);
|
||||
kmem_cache_free(obj_cache, obj);
|
||||
|
|
|
|||
|
|
@ -2026,7 +2026,7 @@ static int _suspend(struct kgsl_device *device)
|
|||
/* drain to prevent from more commands being submitted */
|
||||
device->ftbl->drain(device);
|
||||
/* wait for active count so device can be put in slumber */
|
||||
ret = kgsl_active_count_wait(device, 0);
|
||||
ret = kgsl_active_count_wait(device, 0, HZ);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
@ -2155,17 +2155,10 @@ static int _check_active_count(struct kgsl_device *device, int count)
|
|||
return atomic_read(&device->active_cnt) > count ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* kgsl_active_count_wait() - Wait for activity to finish.
|
||||
* @device: Pointer to a KGSL device
|
||||
* @count: Active count value to wait for
|
||||
*
|
||||
* Block until the active_cnt value hits the desired value
|
||||
*/
|
||||
int kgsl_active_count_wait(struct kgsl_device *device, int count)
|
||||
int kgsl_active_count_wait(struct kgsl_device *device, int count,
|
||||
unsigned long wait_jiffies)
|
||||
{
|
||||
int result = 0;
|
||||
long wait_jiffies = HZ;
|
||||
|
||||
if (WARN_ON(!mutex_is_locked(&device->mutex)))
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -198,7 +198,16 @@ kgsl_pwrctrl_active_freq(struct kgsl_pwrctrl *pwr)
|
|||
return pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq;
|
||||
}
|
||||
|
||||
int kgsl_active_count_wait(struct kgsl_device *device, int count);
|
||||
/**
|
||||
* kgsl_active_count_wait() - Wait for activity to finish.
|
||||
* @device: Pointer to a KGSL device
|
||||
* @count: Active count value to wait for
|
||||
* @wait_jiffies: Jiffies to wait
|
||||
*
|
||||
* Block until the active_cnt value hits the desired value
|
||||
*/
|
||||
int kgsl_active_count_wait(struct kgsl_device *device, int count,
|
||||
unsigned long wait_jiffies);
|
||||
void kgsl_pwrctrl_busy_time(struct kgsl_device *device, u64 time, u64 busy);
|
||||
void kgsl_pwrctrl_set_constraint(struct kgsl_device *device,
|
||||
struct kgsl_pwr_constraint *pwrc, uint32_t id);
|
||||
|
|
|
|||
Loading…
Reference in a new issue