diff options
Diffstat (limited to 'drivers/remoteproc/remoteproc_core.c')
-rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 117 |
1 files changed, 85 insertions, 32 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index a9609d971f7f..aa6206706fe3 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -241,7 +241,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) if (notifyid > rproc->max_notifyid) rproc->max_notifyid = notifyid; - dev_dbg(dev, "vring%d: va %p dma %pad size 0x%x idr %d\n", + dev_dbg(dev, "vring%d: va %pK dma %pad size 0x%x idr %d\n", i, va, &dma, size, notifyid); rvring->va = va; @@ -301,14 +301,14 @@ void rproc_free_vring(struct rproc_vring *rvring) rsc->vring[idx].notifyid = -1; } -static int rproc_vdev_do_probe(struct rproc_subdev *subdev) +static int rproc_vdev_do_start(struct rproc_subdev *subdev) { struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); return rproc_add_virtio_dev(rvdev, rvdev->id); } -static void rproc_vdev_do_remove(struct rproc_subdev *subdev, bool crashed) +static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed) { struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); @@ -399,8 +399,10 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, list_add_tail(&rvdev->node, &rproc->rvdevs); - rproc_add_subdev(rproc, &rvdev->subdev, - rproc_vdev_do_probe, rproc_vdev_do_remove); + rvdev->subdev.start = rproc_vdev_do_start; + rvdev->subdev.stop = rproc_vdev_do_stop; + + rproc_add_subdev(rproc, &rvdev->subdev); return 0; @@ -497,7 +499,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, rproc->num_traces++; - dev_dbg(dev, "%s added: va %p, da 0x%x, len 0x%x\n", + dev_dbg(dev, "%s added: va %pK, da 0x%x, len 0x%x\n", name, ptr, rsc->da, rsc->len); return 0; @@ -635,7 +637,7 @@ static int rproc_handle_carveout(struct rproc *rproc, goto free_carv; } - dev_dbg(dev, "carveout va %p, dma %pad, len 0x%x\n", + dev_dbg(dev, "carveout va %pK, dma %pad, len 0x%x\n", va, &dma, rsc->len); /* @@ -774,32 +776,72 @@ static int rproc_handle_resources(struct rproc *rproc, return ret; } -static int rproc_probe_subdevices(struct rproc *rproc) +static int rproc_prepare_subdevices(struct rproc *rproc) { struct rproc_subdev *subdev; int ret; list_for_each_entry(subdev, &rproc->subdevs, node) { - ret = subdev->probe(subdev); - if (ret) - goto unroll_registration; + if (subdev->prepare) { + ret = subdev->prepare(subdev); + if (ret) + goto unroll_preparation; + } + } + + return 0; + +unroll_preparation: + list_for_each_entry_continue_reverse(subdev, &rproc->subdevs, node) { + if (subdev->unprepare) + subdev->unprepare(subdev); + } + + return ret; +} + +static int rproc_start_subdevices(struct rproc *rproc) +{ + struct rproc_subdev *subdev; + int ret; + + list_for_each_entry(subdev, &rproc->subdevs, node) { + if (subdev->start) { + ret = subdev->start(subdev); + if (ret) + goto unroll_registration; + } } return 0; unroll_registration: - list_for_each_entry_continue_reverse(subdev, &rproc->subdevs, node) - subdev->remove(subdev, true); + list_for_each_entry_continue_reverse(subdev, &rproc->subdevs, node) { + if (subdev->stop) + subdev->stop(subdev, true); + } return ret; } -static void rproc_remove_subdevices(struct rproc *rproc, bool crashed) +static void rproc_stop_subdevices(struct rproc *rproc, bool crashed) { struct rproc_subdev *subdev; - list_for_each_entry_reverse(subdev, &rproc->subdevs, node) - subdev->remove(subdev, crashed); + list_for_each_entry_reverse(subdev, &rproc->subdevs, node) { + if (subdev->stop) + subdev->stop(subdev, crashed); + } +} + +static void rproc_unprepare_subdevices(struct rproc *rproc) +{ + struct rproc_subdev *subdev; + + list_for_each_entry_reverse(subdev, &rproc->subdevs, node) { + if (subdev->unprepare) + subdev->unprepare(subdev); + } } /** @@ -894,20 +936,26 @@ static int rproc_start(struct rproc *rproc, const struct firmware *fw) rproc->table_ptr = loaded_table; } + ret = rproc_prepare_subdevices(rproc); + if (ret) { + dev_err(dev, "failed to prepare subdevices for %s: %d\n", + rproc->name, ret); + goto reset_table_ptr; + } + /* power up the remote processor */ ret = rproc->ops->start(rproc); if (ret) { dev_err(dev, "can't start rproc %s: %d\n", rproc->name, ret); - return ret; + goto unprepare_subdevices; } - /* probe any subdevices for the remote processor */ - ret = rproc_probe_subdevices(rproc); + /* Start any subdevices for the remote processor */ + ret = rproc_start_subdevices(rproc); if (ret) { dev_err(dev, "failed to probe subdevices for %s: %d\n", rproc->name, ret); - rproc->ops->stop(rproc); - return ret; + goto stop_rproc; } rproc->state = RPROC_RUNNING; @@ -915,6 +963,15 @@ static int rproc_start(struct rproc *rproc, const struct firmware *fw) dev_info(dev, "remote processor %s is now up\n", rproc->name); return 0; + +stop_rproc: + rproc->ops->stop(rproc); +unprepare_subdevices: + rproc_unprepare_subdevices(rproc); +reset_table_ptr: + rproc->table_ptr = rproc->cached_table; + + return ret; } /* @@ -1014,8 +1071,8 @@ static int rproc_stop(struct rproc *rproc, bool crashed) struct device *dev = &rproc->dev; int ret; - /* remove any subdevices for the remote processor */ - rproc_remove_subdevices(rproc, crashed); + /* Stop any subdevices for the remote processor */ + rproc_stop_subdevices(rproc, crashed); /* the installed resource table is no longer accessible */ rproc->table_ptr = rproc->cached_table; @@ -1027,6 +1084,8 @@ static int rproc_stop(struct rproc *rproc, bool crashed) return ret; } + rproc_unprepare_subdevices(rproc); + rproc->state = RPROC_OFFLINE; dev_info(dev, "stopped remote processor %s\n", rproc->name); @@ -1657,17 +1716,11 @@ EXPORT_SYMBOL(rproc_del); * rproc_add_subdev() - add a subdevice to a remoteproc * @rproc: rproc handle to add the subdevice to * @subdev: subdev handle to register - * @probe: function to call when the rproc boots - * @remove: function to call when the rproc shuts down + * + * Caller is responsible for populating optional subdevice function pointers. */ -void rproc_add_subdev(struct rproc *rproc, - struct rproc_subdev *subdev, - int (*probe)(struct rproc_subdev *subdev), - void (*remove)(struct rproc_subdev *subdev, bool crashed)) +void rproc_add_subdev(struct rproc *rproc, struct rproc_subdev *subdev) { - subdev->probe = probe; - subdev->remove = remove; - list_add_tail(&subdev->node, &rproc->subdevs); } EXPORT_SYMBOL(rproc_add_subdev); |