bool kick = false;
mutex_lock(&pdata->lock);
+
pdata->refcount -= refs;
- if (pdata->refcount == 0) {
- if (nvhost_module_powered(dev))
- schedule_clockgating_locked(dev);
- kick = true;
+
+ /* submits on the fly -> exit */
+ if (pdata->refcount)
+ goto out;
+
+ if (pdata->idle) {
+ /* give a reference for idle(). otherwise the dev can be
+ * clockgated */
+ pdata->refcount++;
+ mutex_unlock(&pdata->lock);
+ pdata->idle(dev);
+ mutex_lock(&pdata->lock);
+ pdata->refcount--;
}
+
+ /* check that we don't have any new submits on the channel */
+ if (pdata->refcount)
+ goto out;
+
+ /* no new submits. just schedule clock gating */
+ kick = true;
+ if (nvhost_module_powered(dev))
+ schedule_clockgating_locked(dev);
+
+out:
mutex_unlock(&pdata->lock);
- if (kick) {
+ /* wake up a waiting thread if we actually went to idle state */
+ if (kick)
wake_up(&pdata->idle_wq);
- if (pdata->idle)
- pdata->idle(dev);
- }
}
int nvhost_module_get_rate(struct platform_device *dev, unsigned long *rate,
struct nvhost_channel *channel = waiter->data;
int nr_completed = waiter->count;
- nvhost_cdma_update(&channel->cdma);
nvhost_module_idle_mult(channel->dev, nr_completed);
+ nvhost_cdma_update(&channel->cdma);
/* Add nr_completed to trace */
trace_nvhost_channel_submit_complete(channel->dev->name,