diff options
author | Luden <luden@ghostmail.com> | 2016-03-28 22:08:59 +0000 |
---|---|---|
committer | Ziyan <jaraidaniel@gmail.com> | 2016-05-01 23:35:59 +0200 |
commit | f5899ac868e8e65f92c5a40cd7f532df32069e44 (patch) | |
tree | 3768759fe95102592d80553449164201c54fa53f /drivers/remoteproc | |
parent | f3ccb5a5514a8b6a87b77b2ee4c146886ff6d104 (diff) | |
download | kernel_samsung_tuna-f5899ac868e8e65f92c5a40cd7f532df32069e44.tar.gz kernel_samsung_tuna-f5899ac868e8e65f92c5a40cd7f532df32069e44.tar.bz2 kernel_samsung_tuna-f5899ac868e8e65f92c5a40cd7f532df32069e44.zip |
Ducati reloading fix for early suspend.
When the device is suspended with the running camera and then resumed,
it's possible that autosuspend counter won't reach zero and the main
condition in rproc_last_busy() won't be satisfied, so rproc won't be
restarted.
Fixed that by tracking the need to restart rproc separately and
independent of pm state.
Also cleaned up reference counting in rproc_put and rproc_get a bit
to make sure that forced offline and restart don't screw up the number
of references + won't result in race conditions.
Diffstat (limited to 'drivers/remoteproc')
-rwxr-xr-x | drivers/remoteproc/remoteproc.c | 84 |
1 files changed, 54 insertions, 30 deletions
diff --git a/drivers/remoteproc/remoteproc.c b/drivers/remoteproc/remoteproc.c index 939274c434e..9c10b2e2a03 100755 --- a/drivers/remoteproc/remoteproc.c +++ b/drivers/remoteproc/remoteproc.c @@ -1293,20 +1293,22 @@ static struct rproc *_rproc_get(const char *name, bool use_refcounting) mutex_lock(&rproc->lock); } - /* prevent underlying implementation from being removed */ - if (!try_module_get(rproc->owner)) { - dev_err(dev, "%s: can't get owner\n", __func__); - goto unlock_mutex; - } + if (use_refcounting) { + /* prevent underlying implementation from being removed */ + if (!try_module_get(rproc->owner)) { + dev_err(dev, "%s: can't get owner\n", __func__); + goto unlock_mutex; + } - /* bail if rproc is already powered up */ - if (use_refcounting && rproc->count++) { - ret = rproc; - goto unlock_mutex; + /* bail if rproc is already powered up */ + if (rproc->count++) { + ret = rproc; + goto unlock_mutex; + } } - if (use_refcounting && rproc->state != RPROC_OFFLINE) { - dev_info(dev, "redundant rproc restart request, ignoring\n"); + if (rproc->state != RPROC_OFFLINE) { + dev_err(dev, "requested rproc start from non-OFFLINE mode: %d, ignoring\n", rproc->state); ret = rproc; goto unlock_mutex; } @@ -1327,8 +1329,10 @@ static struct rproc *_rproc_get(const char *name, bool use_refcounting) if (err) { dev_err(dev, "failed to load rproc %s\n", rproc->name); complete_all(&rproc->firmware_loading_complete); - module_put(rproc->owner); - rproc->count -= (use_refcounting ? 1 : 0); + if (use_refcounting) { + module_put(rproc->owner); + --rproc->count; + } goto unlock_mutex; } @@ -1437,22 +1441,23 @@ static void _rproc_put(struct rproc *rproc, bool use_refcounting) goto out; } } + +#ifdef CONFIG_CMA + omap_ion_ipu_free_memory(); +#endif } if (rproc->state == RPROC_CRASHED) complete_all(&rproc->error_comp); rproc->state = RPROC_OFFLINE; + rproc->need_restart = !use_refcounting; dev_info(dev, "stopped remote processor %s\n", rproc->name); -#ifdef CONFIG_CMA - omap_ion_ipu_free_memory(); -#endif - out: mutex_unlock(&rproc->lock); - if (!ret) + if (!ret && use_refcounting) module_put(rproc->owner); } void rproc_put(struct rproc *rproc) @@ -1481,13 +1486,29 @@ int rproc_event_unregister(struct rproc *rproc, struct notifier_block *nb) } EXPORT_SYMBOL_GPL(rproc_event_unregister); -static int rproc_runtime_resume(struct device *dev); +static void rproc_restart(struct rproc *rproc); void rproc_last_busy(struct rproc *rproc) { #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND struct device *dev = rproc->dev; + mutex_lock(&rproc->lock); + if (rproc->need_restart) { + WARN_ONCE(rproc->state != RPROC_OFFLINE, "Requested restart in non-OFFLINE mode: %d", rproc->state); + rproc->need_restart = false; + mutex_unlock(&rproc->lock); + + mutex_lock(&rproc->pm_lock); + pm_runtime_mark_last_busy(dev); + mutex_unlock(&rproc->pm_lock); + + rproc_restart(rproc); + return; + } else { + mutex_unlock(&rproc->lock); + } + mutex_lock(&rproc->pm_lock); if (pm_runtime_suspended(dev) || !pm_runtime_autosuspend_expiration(dev)) { @@ -1504,11 +1525,6 @@ void rproc_last_busy(struct rproc *rproc) mutex_unlock(&rproc->lock); return; } - if (rproc->state == RPROC_OFFLINE) { - mutex_unlock(&rproc->lock); - rproc_runtime_resume(dev); - return; - } mutex_unlock(&rproc->lock); pm_runtime_get_sync(dev); pm_runtime_mark_last_busy(dev); @@ -1608,12 +1624,6 @@ static int rproc_runtime_resume(struct device *dev) dev_dbg(dev, "Enter %s\n", __func__); - if (rproc->state == RPROC_OFFLINE) { - dev_info(dev, "rproc_runtime_resume in RPROC_OFFLINE mode - waking up.\n"); - _rproc_get(rproc->name, false); - rpmsg_reset_all_devices(); - } - if (rproc->ops->resume) ret = rproc->ops->resume(rproc); @@ -1623,6 +1633,19 @@ static int rproc_runtime_resume(struct device *dev) return 0; } +static void rproc_restart(struct rproc *rproc) +{ + dev_info(rproc->dev, "%s: restarting rproc.\n", __func__); + /* Reload firmware and start remote processor. */ + _rproc_get(rproc->name, false); + /* Remote processor will try to re-create rpmsg channels + * on restart, therefore reset devices and channels so that + * new ones can be created. */ + rpmsg_reset_all_devices(); + /* Needed for omap_rpmsg to set mbox handle. */ + rproc_runtime_resume(rproc->dev); +} + static int rproc_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -1782,6 +1805,7 @@ int rproc_register(struct device *dev, const char *name, BLOCKING_INIT_NOTIFIER_HEAD(&rproc->nbh); rproc->state = RPROC_OFFLINE; + rproc->need_restart = false; rproc->qos_request = kzalloc(sizeof(*rproc->qos_request), GFP_KERNEL); |