Commit b5ab5e24 authored by Ohad Ben-Cohen's avatar Ohad Ben-Cohen

remoteproc: maintain a generic child device for each rproc

For each registered rproc, maintain a generic remoteproc device whose
parent is the low level platform-specific device (commonly a pdev, but
it may certainly be any other type of device too).

With this in hand, the resulting device hierarchy might then look like:

omap-rproc.0
 |
 - remoteproc0  <---- new !
    |
    - virtio0
    |
    - virtio1
       |
       - rpmsg0
       |
       - rpmsg1
       |
       - rpmsg2

Where:
- omap-rproc.0 is the low level device that's bound to the
  driver which invokes rproc_register()
- remoteproc0 is the result of this patch, and will be added by the
  remoteproc framework when rproc_register() is invoked
- virtio0 and virtio1 are vdevs that are registered by remoteproc
  when it realizes that they are supported by the firmware
  of the physical remote processor represented by omap-rproc.0
- rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg
  channels, and are registerd by the rpmsg bus when it gets notified
  about their existence

Technically, this patch:
- changes 'struct rproc' to contain this generic remoteproc.x device
- creates a new "remoteproc" type, to which this new generic remoteproc.x
  device belong to.
- adds a super simple enumeration method for the indices of the
  remoteproc.x devices
- updates all dev_* messaging to use the generic remoteproc.x device
  instead of the low level platform-specific device
- updates all dma_* allocations to use the parent of remoteproc.x (where
  the platform-specific memory pools, most commonly CMA, are to be found)

Adding this generic device has several merits:
- we can now add remoteproc runtime PM support simply by hooking onto the
  new "remoteproc" type
- all remoteproc log messages will now carry a common name prefix
  instead of having a platform-specific one
- having a device as part of the rproc struct makes it possible to simplify
  refcounting (see subsequent patch)

Thanks to Stephen Boyd <sboyd@codeaurora.org> for suggesting and
discussing these ideas in one of the remoteproc review threads and
to Fernando Guzman Lugo <fernando.lugo@ti.com> for trying them out
with the (upcoming) runtime PM support for remoteproc.

Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
Reviewed-by: default avatarStephen Boyd <sboyd@codeaurora.org>
Signed-off-by: default avatarOhad Ben-Cohen <ohad@wizery.com>
parent 6db20ea8
...@@ -66,7 +66,7 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, ...@@ -66,7 +66,7 @@ static int omap_rproc_mbox_callback(struct notifier_block *this,
{ {
mbox_msg_t msg = (mbox_msg_t) data; mbox_msg_t msg = (mbox_msg_t) data;
struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb);
struct device *dev = oproc->rproc->dev; struct device *dev = oproc->rproc->dev.parent;
const char *name = oproc->rproc->name; const char *name = oproc->rproc->name;
dev_dbg(dev, "mbox msg: 0x%x\n", msg); dev_dbg(dev, "mbox msg: 0x%x\n", msg);
...@@ -92,12 +92,13 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, ...@@ -92,12 +92,13 @@ static int omap_rproc_mbox_callback(struct notifier_block *this,
static void omap_rproc_kick(struct rproc *rproc, int vqid) static void omap_rproc_kick(struct rproc *rproc, int vqid)
{ {
struct omap_rproc *oproc = rproc->priv; struct omap_rproc *oproc = rproc->priv;
struct device *dev = rproc->dev.parent;
int ret; int ret;
/* send the index of the triggered virtqueue in the mailbox payload */ /* send the index of the triggered virtqueue in the mailbox payload */
ret = omap_mbox_msg_send(oproc->mbox, vqid); ret = omap_mbox_msg_send(oproc->mbox, vqid);
if (ret) if (ret)
dev_err(rproc->dev, "omap_mbox_msg_send failed: %d\n", ret); dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret);
} }
/* /*
...@@ -110,7 +111,8 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) ...@@ -110,7 +111,8 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid)
static int omap_rproc_start(struct rproc *rproc) static int omap_rproc_start(struct rproc *rproc)
{ {
struct omap_rproc *oproc = rproc->priv; struct omap_rproc *oproc = rproc->priv;
struct platform_device *pdev = to_platform_device(rproc->dev); struct device *dev = rproc->dev.parent;
struct platform_device *pdev = to_platform_device(dev);
struct omap_rproc_pdata *pdata = pdev->dev.platform_data; struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
int ret; int ret;
...@@ -120,7 +122,7 @@ static int omap_rproc_start(struct rproc *rproc) ...@@ -120,7 +122,7 @@ static int omap_rproc_start(struct rproc *rproc)
oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb); oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
if (IS_ERR(oproc->mbox)) { if (IS_ERR(oproc->mbox)) {
ret = PTR_ERR(oproc->mbox); ret = PTR_ERR(oproc->mbox);
dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); dev_err(dev, "omap_mbox_get failed: %d\n", ret);
return ret; return ret;
} }
...@@ -133,13 +135,13 @@ static int omap_rproc_start(struct rproc *rproc) ...@@ -133,13 +135,13 @@ static int omap_rproc_start(struct rproc *rproc)
*/ */
ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST);
if (ret) { if (ret) {
dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); dev_err(dev, "omap_mbox_get failed: %d\n", ret);
goto put_mbox; goto put_mbox;
} }
ret = pdata->device_enable(pdev); ret = pdata->device_enable(pdev);
if (ret) { if (ret) {
dev_err(rproc->dev, "omap_device_enable failed: %d\n", ret); dev_err(dev, "omap_device_enable failed: %d\n", ret);
goto put_mbox; goto put_mbox;
} }
...@@ -153,7 +155,8 @@ static int omap_rproc_start(struct rproc *rproc) ...@@ -153,7 +155,8 @@ static int omap_rproc_start(struct rproc *rproc)
/* power off the remote processor */ /* power off the remote processor */
static int omap_rproc_stop(struct rproc *rproc) static int omap_rproc_stop(struct rproc *rproc)
{ {
struct platform_device *pdev = to_platform_device(rproc->dev); struct device *dev = rproc->dev.parent;
struct platform_device *pdev = to_platform_device(dev);
struct omap_rproc_pdata *pdata = pdev->dev.platform_data; struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
struct omap_rproc *oproc = rproc->priv; struct omap_rproc *oproc = rproc->priv;
int ret; int ret;
......
This diff is collapsed.
...@@ -124,7 +124,7 @@ struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, ...@@ -124,7 +124,7 @@ struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc,
tfile = debugfs_create_file(name, 0400, rproc->dbg_dir, tfile = debugfs_create_file(name, 0400, rproc->dbg_dir,
trace, &trace_rproc_ops); trace, &trace_rproc_ops);
if (!tfile) { if (!tfile) {
dev_err(rproc->dev, "failed to create debugfs trace entry\n"); dev_err(&rproc->dev, "failed to create debugfs trace entry\n");
return NULL; return NULL;
} }
...@@ -141,7 +141,7 @@ void rproc_delete_debug_dir(struct rproc *rproc) ...@@ -141,7 +141,7 @@ void rproc_delete_debug_dir(struct rproc *rproc)
void rproc_create_debug_dir(struct rproc *rproc) void rproc_create_debug_dir(struct rproc *rproc)
{ {
struct device *dev = rproc->dev; struct device *dev = &rproc->dev;
if (!rproc_dbg) if (!rproc_dbg)
return; return;
......
...@@ -36,7 +36,7 @@ static void rproc_virtio_notify(struct virtqueue *vq) ...@@ -36,7 +36,7 @@ static void rproc_virtio_notify(struct virtqueue *vq)
struct rproc *rproc = rvring->rvdev->rproc; struct rproc *rproc = rvring->rvdev->rproc;
int notifyid = rvring->notifyid; int notifyid = rvring->notifyid;
dev_dbg(rproc->dev, "kicking vq index: %d\n", notifyid); dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid);
rproc->ops->kick(rproc, notifyid); rproc->ops->kick(rproc, notifyid);
} }
...@@ -57,7 +57,7 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid) ...@@ -57,7 +57,7 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid)
{ {
struct rproc_vring *rvring; struct rproc_vring *rvring;
dev_dbg(rproc->dev, "vq index %d is interrupted\n", notifyid); dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid);
rvring = idr_find(&rproc->notifyids, notifyid); rvring = idr_find(&rproc->notifyids, notifyid);
if (!rvring || !rvring->vq) if (!rvring || !rvring->vq)
...@@ -74,6 +74,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, ...@@ -74,6 +74,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
{ {
struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
struct rproc *rproc = vdev_to_rproc(vdev); struct rproc *rproc = vdev_to_rproc(vdev);
struct device *dev = &rproc->dev;
struct rproc_vring *rvring; struct rproc_vring *rvring;
struct virtqueue *vq; struct virtqueue *vq;
void *addr; void *addr;
...@@ -95,7 +96,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, ...@@ -95,7 +96,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
size = vring_size(len, rvring->align); size = vring_size(len, rvring->align);
memset(addr, 0, size); memset(addr, 0, size);
dev_dbg(rproc->dev, "vring%d: va %p qsz %d notifyid %d\n", dev_dbg(dev, "vring%d: va %p qsz %d notifyid %d\n",
id, addr, len, rvring->notifyid); id, addr, len, rvring->notifyid);
/* /*
...@@ -105,7 +106,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, ...@@ -105,7 +106,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
vq = vring_new_virtqueue(len, rvring->align, vdev, false, addr, vq = vring_new_virtqueue(len, rvring->align, vdev, false, addr,
rproc_virtio_notify, callback, name); rproc_virtio_notify, callback, name);
if (!vq) { if (!vq) {
dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name); dev_err(dev, "vring_new_virtqueue %s failed\n", name);
rproc_free_vring(rvring); rproc_free_vring(rvring);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
...@@ -152,7 +153,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, ...@@ -152,7 +153,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
/* now that the vqs are all set, boot the remote processor */ /* now that the vqs are all set, boot the remote processor */
ret = rproc_boot(rproc); ret = rproc_boot(rproc);
if (ret) { if (ret) {
dev_err(rproc->dev, "rproc_boot() failed %d\n", ret); dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret);
goto error; goto error;
} }
...@@ -254,7 +255,7 @@ static void rproc_vdev_release(struct device *dev) ...@@ -254,7 +255,7 @@ static void rproc_vdev_release(struct device *dev)
int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
{ {
struct rproc *rproc = rvdev->rproc; struct rproc *rproc = rvdev->rproc;
struct device *dev = rproc->dev; struct device *dev = &rproc->dev;
struct virtio_device *vdev = &rvdev->vdev; struct virtio_device *vdev = &rvdev->vdev;
int ret; int ret;
......
...@@ -911,7 +911,8 @@ static int rpmsg_probe(struct virtio_device *vdev) ...@@ -911,7 +911,8 @@ static int rpmsg_probe(struct virtio_device *vdev)
vrp->svq = vqs[1]; vrp->svq = vqs[1];
/* allocate coherent memory for the buffers */ /* allocate coherent memory for the buffers */
bufs_va = dma_alloc_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, bufs_va = dma_alloc_coherent(vdev->dev.parent->parent,
RPMSG_TOTAL_BUF_SPACE,
&vrp->bufs_dma, GFP_KERNEL); &vrp->bufs_dma, GFP_KERNEL);
if (!bufs_va) if (!bufs_va)
goto vqs_del; goto vqs_del;
......
...@@ -369,7 +369,7 @@ enum rproc_state { ...@@ -369,7 +369,7 @@ enum rproc_state {
* @firmware: name of firmware file to be loaded * @firmware: name of firmware file to be loaded
* @priv: private data which belongs to the platform-specific rproc module * @priv: private data which belongs to the platform-specific rproc module
* @ops: platform-specific start/stop rproc handlers * @ops: platform-specific start/stop rproc handlers
* @dev: underlying device * @dev: virtual device for refcounting and common remoteproc behavior
* @refcount: refcount of users that have a valid pointer to this rproc * @refcount: refcount of users that have a valid pointer to this rproc
* @power: refcount of users who need this rproc powered up * @power: refcount of users who need this rproc powered up
* @state: state of the device * @state: state of the device
...@@ -383,6 +383,7 @@ enum rproc_state { ...@@ -383,6 +383,7 @@ enum rproc_state {
* @bootaddr: address of first instruction to boot rproc with (optional) * @bootaddr: address of first instruction to boot rproc with (optional)
* @rvdevs: list of remote virtio devices * @rvdevs: list of remote virtio devices
* @notifyids: idr for dynamically assigning rproc-wide unique notify ids * @notifyids: idr for dynamically assigning rproc-wide unique notify ids
* @index: index of this rproc device
*/ */
struct rproc { struct rproc {
struct klist_node node; struct klist_node node;
...@@ -391,7 +392,7 @@ struct rproc { ...@@ -391,7 +392,7 @@ struct rproc {
const char *firmware; const char *firmware;
void *priv; void *priv;
const struct rproc_ops *ops; const struct rproc_ops *ops;
struct device *dev; struct device dev;
struct kref refcount; struct kref refcount;
atomic_t power; atomic_t power;
unsigned int state; unsigned int state;
...@@ -405,6 +406,7 @@ struct rproc { ...@@ -405,6 +406,7 @@ struct rproc {
u32 bootaddr; u32 bootaddr;
struct list_head rvdevs; struct list_head rvdevs;
struct idr notifyids; struct idr notifyids;
int index;
}; };
/* we currently support only two vrings per rvdev */ /* we currently support only two vrings per rvdev */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment