summaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2016-05-05 09:29:39 -0400
committerBjorn Andersson <bjorn.andersson@linaro.org>2016-05-06 14:46:36 -0400
commit3d87fa1d47c10c71684e1eca15cb051746ab1d56 (patch)
tree03d70b9ead994d59d25067990b99b43c08c9fb87 /drivers/remoteproc
parent9735a22799b9214d17d3c231fe377fc852f042e9 (diff)
remoteproc: core: Task sync during rproc_fw_boot()
By default, rproc_fw_boot() needs to wait for rproc to be configured, but a race may occur when using rpmsg/virtio. In this case, it can be called locally in a safe manor. This patch represents two usecases: - External call (via exported rproc_boot()), which waits - Internal call can use 'nowait' version of rproc_boot() Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/remoteproc_core.c29
-rw-r--r--drivers/remoteproc/remoteproc_internal.h1
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c2
3 files changed, 29 insertions, 3 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 3d7d58a109d8..1210d6db40b1 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1030,8 +1030,9 @@ static void rproc_crash_handler_work(struct work_struct *work)
1030} 1030}
1031 1031
1032/** 1032/**
1033 * rproc_boot() - boot a remote processor 1033 * __rproc_boot() - boot a remote processor
1034 * @rproc: handle of a remote processor 1034 * @rproc: handle of a remote processor
1035 * @wait: wait for rproc registration completion
1035 * 1036 *
1036 * Boot a remote processor (i.e. load its firmware, power it on, ...). 1037 * Boot a remote processor (i.e. load its firmware, power it on, ...).
1037 * 1038 *
@@ -1040,7 +1041,7 @@ static void rproc_crash_handler_work(struct work_struct *work)
1040 * 1041 *
1041 * Returns 0 on success, and an appropriate error value otherwise. 1042 * Returns 0 on success, and an appropriate error value otherwise.
1042 */ 1043 */
1043int rproc_boot(struct rproc *rproc) 1044static int __rproc_boot(struct rproc *rproc, bool wait)
1044{ 1045{
1045 const struct firmware *firmware_p; 1046 const struct firmware *firmware_p;
1046 struct device *dev; 1047 struct device *dev;
@@ -1088,6 +1089,10 @@ int rproc_boot(struct rproc *rproc)
1088 goto downref_rproc; 1089 goto downref_rproc;
1089 } 1090 }
1090 1091
1092 /* if rproc virtio is not yet configured, wait */
1093 if (wait)
1094 wait_for_completion(&rproc->firmware_loading_complete);
1095
1091 ret = rproc_fw_boot(rproc, firmware_p); 1096 ret = rproc_fw_boot(rproc, firmware_p);
1092 1097
1093 release_firmware(firmware_p); 1098 release_firmware(firmware_p);
@@ -1101,9 +1106,29 @@ unlock_mutex:
1101 mutex_unlock(&rproc->lock); 1106 mutex_unlock(&rproc->lock);
1102 return ret; 1107 return ret;
1103} 1108}
1109
1110/**
1111 * rproc_boot() - boot a remote processor
1112 * @rproc: handle of a remote processor
1113 */
1114int rproc_boot(struct rproc *rproc)
1115{
1116 return __rproc_boot(rproc, true);
1117}
1104EXPORT_SYMBOL(rproc_boot); 1118EXPORT_SYMBOL(rproc_boot);
1105 1119
1106/** 1120/**
1121 * rproc_boot_nowait() - boot a remote processor
1122 * @rproc: handle of a remote processor
1123 *
1124 * Same as rproc_boot() but don't wait for rproc registration completion
1125 */
1126int rproc_boot_nowait(struct rproc *rproc)
1127{
1128 return __rproc_boot(rproc, false);
1129}
1130
1131/**
1107 * rproc_shutdown() - power off the remote processor 1132 * rproc_shutdown() - power off the remote processor
1108 * @rproc: the remote processor 1133 * @rproc: the remote processor
1109 * 1134 *
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 8041b95cb058..57e1de59bec8 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -48,6 +48,7 @@ struct rproc_fw_ops {
48/* from remoteproc_core.c */ 48/* from remoteproc_core.c */
49void rproc_release(struct kref *kref); 49void rproc_release(struct kref *kref);
50irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); 50irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
51int rproc_boot_nowait(struct rproc *rproc);
51 52
52/* from remoteproc_virtio.c */ 53/* from remoteproc_virtio.c */
53int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id); 54int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index e44872fb9e5e..cc91556313e1 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -161,7 +161,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
161 } 161 }
162 162
163 /* now that the vqs are all set, boot the remote processor */ 163 /* now that the vqs are all set, boot the remote processor */
164 ret = rproc_boot(rproc); 164 ret = rproc_boot_nowait(rproc);
165 if (ret) { 165 if (ret) {
166 dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret); 166 dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret);
167 goto error; 167 goto error;