aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorLuden <luden@ghostmail.com>2016-03-28 22:08:59 +0000
committerZiyan <jaraidaniel@gmail.com>2016-05-01 23:35:59 +0200
commitf5899ac868e8e65f92c5a40cd7f532df32069e44 (patch)
tree3768759fe95102592d80553449164201c54fa53f /drivers/remoteproc
parentf3ccb5a5514a8b6a87b77b2ee4c146886ff6d104 (diff)
downloadkernel_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-xdrivers/remoteproc/remoteproc.c84
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);