struct gk20a_platform *platform = platform_get_drvdata(g->dev);
int ret = 0;
- if (platform->unrailgate)
+ if (platform->unrailgate) {
+ mutex_lock(&platform->railgate_lock);
ret = platform->unrailgate(platform->g->dev);
+ mutex_unlock(&platform->railgate_lock);
+ }
return ret;
}
struct gk20a_platform *platform = platform_get_drvdata(dev);
int err = 0;
+ mutex_init(&platform->railgate_lock);
+
/* Initialise pm runtime */
if (platform->clockgate_delay) {
pm_runtime_set_autosuspend_delay(&dev->dev,
/* acquire busy lock to block other busy() calls */
down_write(&g->busy_lock);
+ /* acquire railgate lock to prevent unrailgate in midst of do_idle() */
+ mutex_lock(&platform->railgate_lock);
+
+ /* check if it is already railgated ? */
+ if (platform->is_railgated(pdev))
+ return 0;
+
/* prevent suspend by incrementing usage counter */
pm_runtime_get_noresume(&pdev->dev);
}
/* GPU is not rail gated by now, return error */
- up_write(&g->busy_lock);
- return -EBUSY;
+ goto fail_timeout;
fail:
pm_runtime_put_noidle(&pdev->dev);
+fail_timeout:
+ mutex_unlock(&platform->railgate_lock);
up_write(&g->busy_lock);
return -EBUSY;
}
bus_find_device_by_name(&platform_bus_type,
NULL, "gk20a.0"));
struct gk20a *g = get_gk20a(pdev);
+ struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev);
/* release the lock and open up all other busy() calls */
+ mutex_unlock(&platform->railgate_lock);
up_write(&g->busy_lock);
return 0;