diff options
author | Ohad Ben-Cohen <ohad@wizery.com> | 2012-05-30 15:01:25 -0400 |
---|---|---|
committer | Ohad Ben-Cohen <ohad@wizery.com> | 2012-07-05 17:53:03 -0400 |
commit | b5ab5e24e960b9f780a4cc96815cfd4b0d412720 (patch) | |
tree | d07fbf490e03e9e2706c14a9bc24ae4f47b05111 /drivers | |
parent | 6db20ea8d85064175c7ef594c433c6c2e6bbab83 (diff) |
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: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/remoteproc/omap_remoteproc.c | 17 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 135 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_debugfs.c | 4 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_virtio.c | 13 | ||||
-rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 3 |
5 files changed, 113 insertions, 59 deletions
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 69425c4e86f3..b5e6d2981741 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c | |||
@@ -66,7 +66,7 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, | |||
66 | { | 66 | { |
67 | mbox_msg_t msg = (mbox_msg_t) data; | 67 | mbox_msg_t msg = (mbox_msg_t) data; |
68 | struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); | 68 | struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); |
69 | struct device *dev = oproc->rproc->dev; | 69 | struct device *dev = oproc->rproc->dev.parent; |
70 | const char *name = oproc->rproc->name; | 70 | const char *name = oproc->rproc->name; |
71 | 71 | ||
72 | dev_dbg(dev, "mbox msg: 0x%x\n", msg); | 72 | dev_dbg(dev, "mbox msg: 0x%x\n", msg); |
@@ -92,12 +92,13 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, | |||
92 | static void omap_rproc_kick(struct rproc *rproc, int vqid) | 92 | static void omap_rproc_kick(struct rproc *rproc, int vqid) |
93 | { | 93 | { |
94 | struct omap_rproc *oproc = rproc->priv; | 94 | struct omap_rproc *oproc = rproc->priv; |
95 | struct device *dev = rproc->dev.parent; | ||
95 | int ret; | 96 | int ret; |
96 | 97 | ||
97 | /* send the index of the triggered virtqueue in the mailbox payload */ | 98 | /* send the index of the triggered virtqueue in the mailbox payload */ |
98 | ret = omap_mbox_msg_send(oproc->mbox, vqid); | 99 | ret = omap_mbox_msg_send(oproc->mbox, vqid); |
99 | if (ret) | 100 | if (ret) |
100 | dev_err(rproc->dev, "omap_mbox_msg_send failed: %d\n", ret); | 101 | dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret); |
101 | } | 102 | } |
102 | 103 | ||
103 | /* | 104 | /* |
@@ -110,7 +111,8 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) | |||
110 | static int omap_rproc_start(struct rproc *rproc) | 111 | static int omap_rproc_start(struct rproc *rproc) |
111 | { | 112 | { |
112 | struct omap_rproc *oproc = rproc->priv; | 113 | struct omap_rproc *oproc = rproc->priv; |
113 | struct platform_device *pdev = to_platform_device(rproc->dev); | 114 | struct device *dev = rproc->dev.parent; |
115 | struct platform_device *pdev = to_platform_device(dev); | ||
114 | struct omap_rproc_pdata *pdata = pdev->dev.platform_data; | 116 | struct omap_rproc_pdata *pdata = pdev->dev.platform_data; |
115 | int ret; | 117 | int ret; |
116 | 118 | ||
@@ -120,7 +122,7 @@ static int omap_rproc_start(struct rproc *rproc) | |||
120 | oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb); | 122 | oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb); |
121 | if (IS_ERR(oproc->mbox)) { | 123 | if (IS_ERR(oproc->mbox)) { |
122 | ret = PTR_ERR(oproc->mbox); | 124 | ret = PTR_ERR(oproc->mbox); |
123 | dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); | 125 | dev_err(dev, "omap_mbox_get failed: %d\n", ret); |
124 | return ret; | 126 | return ret; |
125 | } | 127 | } |
126 | 128 | ||
@@ -133,13 +135,13 @@ static int omap_rproc_start(struct rproc *rproc) | |||
133 | */ | 135 | */ |
134 | ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); | 136 | ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); |
135 | if (ret) { | 137 | if (ret) { |
136 | dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); | 138 | dev_err(dev, "omap_mbox_get failed: %d\n", ret); |
137 | goto put_mbox; | 139 | goto put_mbox; |
138 | } | 140 | } |
139 | 141 | ||
140 | ret = pdata->device_enable(pdev); | 142 | ret = pdata->device_enable(pdev); |
141 | if (ret) { | 143 | if (ret) { |
142 | dev_err(rproc->dev, "omap_device_enable failed: %d\n", ret); | 144 | dev_err(dev, "omap_device_enable failed: %d\n", ret); |
143 | goto put_mbox; | 145 | goto put_mbox; |
144 | } | 146 | } |
145 | 147 | ||
@@ -153,7 +155,8 @@ put_mbox: | |||
153 | /* power off the remote processor */ | 155 | /* power off the remote processor */ |
154 | static int omap_rproc_stop(struct rproc *rproc) | 156 | static int omap_rproc_stop(struct rproc *rproc) |
155 | { | 157 | { |
156 | struct platform_device *pdev = to_platform_device(rproc->dev); | 158 | struct device *dev = rproc->dev.parent; |
159 | struct platform_device *pdev = to_platform_device(dev); | ||
157 | struct omap_rproc_pdata *pdata = pdev->dev.platform_data; | 160 | struct omap_rproc_pdata *pdata = pdev->dev.platform_data; |
158 | struct omap_rproc *oproc = rproc->priv; | 161 | struct omap_rproc *oproc = rproc->priv; |
159 | int ret; | 162 | int ret; |
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 288d4175bbf6..25f937843836 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
36 | #include <linux/remoteproc.h> | 36 | #include <linux/remoteproc.h> |
37 | #include <linux/iommu.h> | 37 | #include <linux/iommu.h> |
38 | #include <linux/idr.h> | ||
38 | #include <linux/klist.h> | 39 | #include <linux/klist.h> |
39 | #include <linux/elf.h> | 40 | #include <linux/elf.h> |
40 | #include <linux/virtio_ids.h> | 41 | #include <linux/virtio_ids.h> |
@@ -66,6 +67,9 @@ typedef int (*rproc_handle_resources_t)(struct rproc *rproc, | |||
66 | struct resource_table *table, int len); | 67 | struct resource_table *table, int len); |
67 | typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); | 68 | typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); |
68 | 69 | ||
70 | /* Unique indices for remoteproc devices */ | ||
71 | static DEFINE_IDA(rproc_dev_index); | ||
72 | |||
69 | /* | 73 | /* |
70 | * This is the IOMMU fault handler we register with the IOMMU API | 74 | * This is the IOMMU fault handler we register with the IOMMU API |
71 | * (when relevant; not all remote processors access memory through | 75 | * (when relevant; not all remote processors access memory through |
@@ -92,7 +96,7 @@ static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev, | |||
92 | static int rproc_enable_iommu(struct rproc *rproc) | 96 | static int rproc_enable_iommu(struct rproc *rproc) |
93 | { | 97 | { |
94 | struct iommu_domain *domain; | 98 | struct iommu_domain *domain; |
95 | struct device *dev = rproc->dev; | 99 | struct device *dev = rproc->dev.parent; |
96 | int ret; | 100 | int ret; |
97 | 101 | ||
98 | /* | 102 | /* |
@@ -137,7 +141,7 @@ free_domain: | |||
137 | static void rproc_disable_iommu(struct rproc *rproc) | 141 | static void rproc_disable_iommu(struct rproc *rproc) |
138 | { | 142 | { |
139 | struct iommu_domain *domain = rproc->domain; | 143 | struct iommu_domain *domain = rproc->domain; |
140 | struct device *dev = rproc->dev; | 144 | struct device *dev = rproc->dev.parent; |
141 | 145 | ||
142 | if (!domain) | 146 | if (!domain) |
143 | return; | 147 | return; |
@@ -217,7 +221,7 @@ static void *rproc_da_to_va(struct rproc *rproc, u64 da, int len) | |||
217 | static int | 221 | static int |
218 | rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len) | 222 | rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len) |
219 | { | 223 | { |
220 | struct device *dev = rproc->dev; | 224 | struct device *dev = &rproc->dev; |
221 | struct elf32_hdr *ehdr; | 225 | struct elf32_hdr *ehdr; |
222 | struct elf32_phdr *phdr; | 226 | struct elf32_phdr *phdr; |
223 | int i, ret = 0; | 227 | int i, ret = 0; |
@@ -282,7 +286,7 @@ rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len) | |||
282 | int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) | 286 | int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) |
283 | { | 287 | { |
284 | struct rproc *rproc = rvdev->rproc; | 288 | struct rproc *rproc = rvdev->rproc; |
285 | struct device *dev = rproc->dev; | 289 | struct device *dev = &rproc->dev; |
286 | struct rproc_vring *rvring = &rvdev->vring[i]; | 290 | struct rproc_vring *rvring = &rvdev->vring[i]; |
287 | dma_addr_t dma; | 291 | dma_addr_t dma; |
288 | void *va; | 292 | void *va; |
@@ -301,9 +305,9 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) | |||
301 | * this call will also configure the IOMMU for us | 305 | * this call will also configure the IOMMU for us |
302 | * TODO: let the rproc know the da of this vring | 306 | * TODO: let the rproc know the da of this vring |
303 | */ | 307 | */ |
304 | va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL); | 308 | va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL); |
305 | if (!va) { | 309 | if (!va) { |
306 | dev_err(dev, "dma_alloc_coherent failed\n"); | 310 | dev_err(dev->parent, "dma_alloc_coherent failed\n"); |
307 | return -EINVAL; | 311 | return -EINVAL; |
308 | } | 312 | } |
309 | 313 | ||
@@ -316,7 +320,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) | |||
316 | ret = idr_get_new(&rproc->notifyids, rvring, ¬ifyid); | 320 | ret = idr_get_new(&rproc->notifyids, rvring, ¬ifyid); |
317 | if (ret) { | 321 | if (ret) { |
318 | dev_err(dev, "idr_get_new failed: %d\n", ret); | 322 | dev_err(dev, "idr_get_new failed: %d\n", ret); |
319 | dma_free_coherent(dev, size, va, dma); | 323 | dma_free_coherent(dev->parent, size, va, dma); |
320 | return ret; | 324 | return ret; |
321 | } | 325 | } |
322 | 326 | ||
@@ -334,7 +338,7 @@ static int | |||
334 | rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i) | 338 | rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i) |
335 | { | 339 | { |
336 | struct rproc *rproc = rvdev->rproc; | 340 | struct rproc *rproc = rvdev->rproc; |
337 | struct device *dev = rproc->dev; | 341 | struct device *dev = &rproc->dev; |
338 | struct fw_rsc_vdev_vring *vring = &rsc->vring[i]; | 342 | struct fw_rsc_vdev_vring *vring = &rsc->vring[i]; |
339 | struct rproc_vring *rvring = &rvdev->vring[i]; | 343 | struct rproc_vring *rvring = &rvdev->vring[i]; |
340 | 344 | ||
@@ -366,7 +370,7 @@ void rproc_free_vring(struct rproc_vring *rvring) | |||
366 | int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align)); | 370 | int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align)); |
367 | struct rproc *rproc = rvring->rvdev->rproc; | 371 | struct rproc *rproc = rvring->rvdev->rproc; |
368 | 372 | ||
369 | dma_free_coherent(rproc->dev, size, rvring->va, rvring->dma); | 373 | dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma); |
370 | idr_remove(&rproc->notifyids, rvring->notifyid); | 374 | idr_remove(&rproc->notifyids, rvring->notifyid); |
371 | } | 375 | } |
372 | 376 | ||
@@ -400,14 +404,14 @@ void rproc_free_vring(struct rproc_vring *rvring) | |||
400 | static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, | 404 | static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, |
401 | int avail) | 405 | int avail) |
402 | { | 406 | { |
403 | struct device *dev = rproc->dev; | 407 | struct device *dev = &rproc->dev; |
404 | struct rproc_vdev *rvdev; | 408 | struct rproc_vdev *rvdev; |
405 | int i, ret; | 409 | int i, ret; |
406 | 410 | ||
407 | /* make sure resource isn't truncated */ | 411 | /* make sure resource isn't truncated */ |
408 | if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) | 412 | if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) |
409 | + rsc->config_len > avail) { | 413 | + rsc->config_len > avail) { |
410 | dev_err(rproc->dev, "vdev rsc is truncated\n"); | 414 | dev_err(dev, "vdev rsc is truncated\n"); |
411 | return -EINVAL; | 415 | return -EINVAL; |
412 | } | 416 | } |
413 | 417 | ||
@@ -476,12 +480,12 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, | |||
476 | int avail) | 480 | int avail) |
477 | { | 481 | { |
478 | struct rproc_mem_entry *trace; | 482 | struct rproc_mem_entry *trace; |
479 | struct device *dev = rproc->dev; | 483 | struct device *dev = &rproc->dev; |
480 | void *ptr; | 484 | void *ptr; |
481 | char name[15]; | 485 | char name[15]; |
482 | 486 | ||
483 | if (sizeof(*rsc) > avail) { | 487 | if (sizeof(*rsc) > avail) { |
484 | dev_err(rproc->dev, "trace rsc is truncated\n"); | 488 | dev_err(dev, "trace rsc is truncated\n"); |
485 | return -EINVAL; | 489 | return -EINVAL; |
486 | } | 490 | } |
487 | 491 | ||
@@ -558,6 +562,7 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, | |||
558 | int avail) | 562 | int avail) |
559 | { | 563 | { |
560 | struct rproc_mem_entry *mapping; | 564 | struct rproc_mem_entry *mapping; |
565 | struct device *dev = &rproc->dev; | ||
561 | int ret; | 566 | int ret; |
562 | 567 | ||
563 | /* no point in handling this resource without a valid iommu domain */ | 568 | /* no point in handling this resource without a valid iommu domain */ |
@@ -565,25 +570,25 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, | |||
565 | return -EINVAL; | 570 | return -EINVAL; |
566 | 571 | ||
567 | if (sizeof(*rsc) > avail) { | 572 | if (sizeof(*rsc) > avail) { |
568 | dev_err(rproc->dev, "devmem rsc is truncated\n"); | 573 | dev_err(dev, "devmem rsc is truncated\n"); |
569 | return -EINVAL; | 574 | return -EINVAL; |
570 | } | 575 | } |
571 | 576 | ||
572 | /* make sure reserved bytes are zeroes */ | 577 | /* make sure reserved bytes are zeroes */ |
573 | if (rsc->reserved) { | 578 | if (rsc->reserved) { |
574 | dev_err(rproc->dev, "devmem rsc has non zero reserved bytes\n"); | 579 | dev_err(dev, "devmem rsc has non zero reserved bytes\n"); |
575 | return -EINVAL; | 580 | return -EINVAL; |
576 | } | 581 | } |
577 | 582 | ||
578 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); | 583 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); |
579 | if (!mapping) { | 584 | if (!mapping) { |
580 | dev_err(rproc->dev, "kzalloc mapping failed\n"); | 585 | dev_err(dev, "kzalloc mapping failed\n"); |
581 | return -ENOMEM; | 586 | return -ENOMEM; |
582 | } | 587 | } |
583 | 588 | ||
584 | ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, rsc->flags); | 589 | ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, rsc->flags); |
585 | if (ret) { | 590 | if (ret) { |
586 | dev_err(rproc->dev, "failed to map devmem: %d\n", ret); | 591 | dev_err(dev, "failed to map devmem: %d\n", ret); |
587 | goto out; | 592 | goto out; |
588 | } | 593 | } |
589 | 594 | ||
@@ -598,7 +603,7 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, | |||
598 | mapping->len = rsc->len; | 603 | mapping->len = rsc->len; |
599 | list_add_tail(&mapping->node, &rproc->mappings); | 604 | list_add_tail(&mapping->node, &rproc->mappings); |
600 | 605 | ||
601 | dev_dbg(rproc->dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", | 606 | dev_dbg(dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", |
602 | rsc->pa, rsc->da, rsc->len); | 607 | rsc->pa, rsc->da, rsc->len); |
603 | 608 | ||
604 | return 0; | 609 | return 0; |
@@ -630,13 +635,13 @@ static int rproc_handle_carveout(struct rproc *rproc, | |||
630 | struct fw_rsc_carveout *rsc, int avail) | 635 | struct fw_rsc_carveout *rsc, int avail) |
631 | { | 636 | { |
632 | struct rproc_mem_entry *carveout, *mapping; | 637 | struct rproc_mem_entry *carveout, *mapping; |
633 | struct device *dev = rproc->dev; | 638 | struct device *dev = &rproc->dev; |
634 | dma_addr_t dma; | 639 | dma_addr_t dma; |
635 | void *va; | 640 | void *va; |
636 | int ret; | 641 | int ret; |
637 | 642 | ||
638 | if (sizeof(*rsc) > avail) { | 643 | if (sizeof(*rsc) > avail) { |
639 | dev_err(rproc->dev, "carveout rsc is truncated\n"); | 644 | dev_err(dev, "carveout rsc is truncated\n"); |
640 | return -EINVAL; | 645 | return -EINVAL; |
641 | } | 646 | } |
642 | 647 | ||
@@ -662,9 +667,9 @@ static int rproc_handle_carveout(struct rproc *rproc, | |||
662 | goto free_mapping; | 667 | goto free_mapping; |
663 | } | 668 | } |
664 | 669 | ||
665 | va = dma_alloc_coherent(dev, rsc->len, &dma, GFP_KERNEL); | 670 | va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL); |
666 | if (!va) { | 671 | if (!va) { |
667 | dev_err(dev, "failed to dma alloc carveout: %d\n", rsc->len); | 672 | dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len); |
668 | ret = -ENOMEM; | 673 | ret = -ENOMEM; |
669 | goto free_carv; | 674 | goto free_carv; |
670 | } | 675 | } |
@@ -735,7 +740,7 @@ static int rproc_handle_carveout(struct rproc *rproc, | |||
735 | return 0; | 740 | return 0; |
736 | 741 | ||
737 | dma_free: | 742 | dma_free: |
738 | dma_free_coherent(dev, rsc->len, va, dma); | 743 | dma_free_coherent(dev->parent, rsc->len, va, dma); |
739 | free_carv: | 744 | free_carv: |
740 | kfree(carveout); | 745 | kfree(carveout); |
741 | free_mapping: | 746 | free_mapping: |
@@ -758,7 +763,7 @@ static rproc_handle_resource_t rproc_handle_rsc[] = { | |||
758 | static int | 763 | static int |
759 | rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len) | 764 | rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len) |
760 | { | 765 | { |
761 | struct device *dev = rproc->dev; | 766 | struct device *dev = &rproc->dev; |
762 | rproc_handle_resource_t handler; | 767 | rproc_handle_resource_t handler; |
763 | int ret = 0, i; | 768 | int ret = 0, i; |
764 | 769 | ||
@@ -797,7 +802,7 @@ rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len | |||
797 | static int | 802 | static int |
798 | rproc_handle_virtio_rsc(struct rproc *rproc, struct resource_table *table, int len) | 803 | rproc_handle_virtio_rsc(struct rproc *rproc, struct resource_table *table, int len) |
799 | { | 804 | { |
800 | struct device *dev = rproc->dev; | 805 | struct device *dev = &rproc->dev; |
801 | int ret = 0, i; | 806 | int ret = 0, i; |
802 | 807 | ||
803 | for (i = 0; i < table->num; i++) { | 808 | for (i = 0; i < table->num; i++) { |
@@ -850,7 +855,7 @@ rproc_find_rsc_table(struct rproc *rproc, const u8 *elf_data, size_t len, | |||
850 | struct elf32_hdr *ehdr; | 855 | struct elf32_hdr *ehdr; |
851 | struct elf32_shdr *shdr; | 856 | struct elf32_shdr *shdr; |
852 | const char *name_table; | 857 | const char *name_table; |
853 | struct device *dev = rproc->dev; | 858 | struct device *dev = &rproc->dev; |
854 | struct resource_table *table = NULL; | 859 | struct resource_table *table = NULL; |
855 | int i; | 860 | int i; |
856 | 861 | ||
@@ -916,7 +921,7 @@ rproc_find_rsc_table(struct rproc *rproc, const u8 *elf_data, size_t len, | |||
916 | static void rproc_resource_cleanup(struct rproc *rproc) | 921 | static void rproc_resource_cleanup(struct rproc *rproc) |
917 | { | 922 | { |
918 | struct rproc_mem_entry *entry, *tmp; | 923 | struct rproc_mem_entry *entry, *tmp; |
919 | struct device *dev = rproc->dev; | 924 | struct device *dev = &rproc->dev; |
920 | 925 | ||
921 | /* clean up debugfs trace entries */ | 926 | /* clean up debugfs trace entries */ |
922 | list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { | 927 | list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { |
@@ -928,7 +933,7 @@ static void rproc_resource_cleanup(struct rproc *rproc) | |||
928 | 933 | ||
929 | /* clean up carveout allocations */ | 934 | /* clean up carveout allocations */ |
930 | list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { | 935 | list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { |
931 | dma_free_coherent(dev, entry->len, entry->va, entry->dma); | 936 | dma_free_coherent(dev->parent, entry->len, entry->va, entry->dma); |
932 | list_del(&entry->node); | 937 | list_del(&entry->node); |
933 | kfree(entry); | 938 | kfree(entry); |
934 | } | 939 | } |
@@ -953,7 +958,7 @@ static void rproc_resource_cleanup(struct rproc *rproc) | |||
953 | static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) | 958 | static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) |
954 | { | 959 | { |
955 | const char *name = rproc->firmware; | 960 | const char *name = rproc->firmware; |
956 | struct device *dev = rproc->dev; | 961 | struct device *dev = &rproc->dev; |
957 | struct elf32_hdr *ehdr; | 962 | struct elf32_hdr *ehdr; |
958 | char class; | 963 | char class; |
959 | 964 | ||
@@ -1014,7 +1019,7 @@ static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) | |||
1014 | */ | 1019 | */ |
1015 | static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | 1020 | static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) |
1016 | { | 1021 | { |
1017 | struct device *dev = rproc->dev; | 1022 | struct device *dev = &rproc->dev; |
1018 | const char *name = rproc->firmware; | 1023 | const char *name = rproc->firmware; |
1019 | struct elf32_hdr *ehdr; | 1024 | struct elf32_hdr *ehdr; |
1020 | struct resource_table *table; | 1025 | struct resource_table *table; |
@@ -1138,7 +1143,7 @@ int rproc_boot(struct rproc *rproc) | |||
1138 | return -EINVAL; | 1143 | return -EINVAL; |
1139 | } | 1144 | } |
1140 | 1145 | ||
1141 | dev = rproc->dev; | 1146 | dev = &rproc->dev; |
1142 | 1147 | ||
1143 | ret = mutex_lock_interruptible(&rproc->lock); | 1148 | ret = mutex_lock_interruptible(&rproc->lock); |
1144 | if (ret) { | 1149 | if (ret) { |
@@ -1154,7 +1159,7 @@ int rproc_boot(struct rproc *rproc) | |||
1154 | } | 1159 | } |
1155 | 1160 | ||
1156 | /* prevent underlying implementation from being removed */ | 1161 | /* prevent underlying implementation from being removed */ |
1157 | if (!try_module_get(dev->driver->owner)) { | 1162 | if (!try_module_get(dev->parent->driver->owner)) { |
1158 | dev_err(dev, "%s: can't get owner\n", __func__); | 1163 | dev_err(dev, "%s: can't get owner\n", __func__); |
1159 | ret = -EINVAL; | 1164 | ret = -EINVAL; |
1160 | goto unlock_mutex; | 1165 | goto unlock_mutex; |
@@ -1181,7 +1186,7 @@ int rproc_boot(struct rproc *rproc) | |||
1181 | 1186 | ||
1182 | downref_rproc: | 1187 | downref_rproc: |
1183 | if (ret) { | 1188 | if (ret) { |
1184 | module_put(dev->driver->owner); | 1189 | module_put(dev->parent->driver->owner); |
1185 | atomic_dec(&rproc->power); | 1190 | atomic_dec(&rproc->power); |
1186 | } | 1191 | } |
1187 | unlock_mutex: | 1192 | unlock_mutex: |
@@ -1215,7 +1220,7 @@ EXPORT_SYMBOL(rproc_boot); | |||
1215 | */ | 1220 | */ |
1216 | void rproc_shutdown(struct rproc *rproc) | 1221 | void rproc_shutdown(struct rproc *rproc) |
1217 | { | 1222 | { |
1218 | struct device *dev = rproc->dev; | 1223 | struct device *dev = &rproc->dev; |
1219 | int ret; | 1224 | int ret; |
1220 | 1225 | ||
1221 | ret = mutex_lock_interruptible(&rproc->lock); | 1226 | ret = mutex_lock_interruptible(&rproc->lock); |
@@ -1248,7 +1253,7 @@ void rproc_shutdown(struct rproc *rproc) | |||
1248 | out: | 1253 | out: |
1249 | mutex_unlock(&rproc->lock); | 1254 | mutex_unlock(&rproc->lock); |
1250 | if (!ret) | 1255 | if (!ret) |
1251 | module_put(dev->driver->owner); | 1256 | module_put(dev->parent->driver->owner); |
1252 | } | 1257 | } |
1253 | EXPORT_SYMBOL(rproc_shutdown); | 1258 | EXPORT_SYMBOL(rproc_shutdown); |
1254 | 1259 | ||
@@ -1271,7 +1276,7 @@ void rproc_release(struct kref *kref) | |||
1271 | { | 1276 | { |
1272 | struct rproc *rproc = container_of(kref, struct rproc, refcount); | 1277 | struct rproc *rproc = container_of(kref, struct rproc, refcount); |
1273 | 1278 | ||
1274 | dev_info(rproc->dev, "removing %s\n", rproc->name); | 1279 | dev_info(&rproc->dev, "removing %s\n", rproc->name); |
1275 | 1280 | ||
1276 | rproc_delete_debug_dir(rproc); | 1281 | rproc_delete_debug_dir(rproc); |
1277 | 1282 | ||
@@ -1403,13 +1408,17 @@ EXPORT_SYMBOL(rproc_put); | |||
1403 | */ | 1408 | */ |
1404 | int rproc_register(struct rproc *rproc) | 1409 | int rproc_register(struct rproc *rproc) |
1405 | { | 1410 | { |
1406 | struct device *dev = rproc->dev; | 1411 | struct device *dev = &rproc->dev; |
1407 | int ret = 0; | 1412 | int ret = 0; |
1408 | 1413 | ||
1414 | ret = device_add(dev); | ||
1415 | if (ret < 0) | ||
1416 | return ret; | ||
1417 | |||
1409 | /* expose to rproc_get_by_name users */ | 1418 | /* expose to rproc_get_by_name users */ |
1410 | klist_add_tail(&rproc->node, &rprocs); | 1419 | klist_add_tail(&rproc->node, &rprocs); |
1411 | 1420 | ||
1412 | dev_info(rproc->dev, "%s is available\n", rproc->name); | 1421 | dev_info(dev, "%s is available\n", rproc->name); |
1413 | 1422 | ||
1414 | dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n"); | 1423 | dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n"); |
1415 | dev_info(dev, "THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.\n"); | 1424 | dev_info(dev, "THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.\n"); |
@@ -1442,6 +1451,33 @@ int rproc_register(struct rproc *rproc) | |||
1442 | EXPORT_SYMBOL(rproc_register); | 1451 | EXPORT_SYMBOL(rproc_register); |
1443 | 1452 | ||
1444 | /** | 1453 | /** |
1454 | * rproc_type_release() - release a remote processor instance | ||
1455 | * @dev: the rproc's device | ||
1456 | * | ||
1457 | * This function should _never_ be called directly. | ||
1458 | * | ||
1459 | * It will be called by the driver core when no one holds a valid pointer | ||
1460 | * to @dev anymore. | ||
1461 | */ | ||
1462 | static void rproc_type_release(struct device *dev) | ||
1463 | { | ||
1464 | struct rproc *rproc = container_of(dev, struct rproc, dev); | ||
1465 | |||
1466 | idr_remove_all(&rproc->notifyids); | ||
1467 | idr_destroy(&rproc->notifyids); | ||
1468 | |||
1469 | if (rproc->index >= 0) | ||
1470 | ida_simple_remove(&rproc_dev_index, rproc->index); | ||
1471 | |||
1472 | kfree(rproc); | ||
1473 | } | ||
1474 | |||
1475 | static struct device_type rproc_type = { | ||
1476 | .name = "remoteproc", | ||
1477 | .release = rproc_type_release, | ||
1478 | }; | ||
1479 | |||
1480 | /** | ||
1445 | * rproc_alloc() - allocate a remote processor handle | 1481 | * rproc_alloc() - allocate a remote processor handle |
1446 | * @dev: the underlying device | 1482 | * @dev: the underlying device |
1447 | * @name: name of this remote processor | 1483 | * @name: name of this remote processor |
@@ -1479,12 +1515,25 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, | |||
1479 | return NULL; | 1515 | return NULL; |
1480 | } | 1516 | } |
1481 | 1517 | ||
1482 | rproc->dev = dev; | ||
1483 | rproc->name = name; | 1518 | rproc->name = name; |
1484 | rproc->ops = ops; | 1519 | rproc->ops = ops; |
1485 | rproc->firmware = firmware; | 1520 | rproc->firmware = firmware; |
1486 | rproc->priv = &rproc[1]; | 1521 | rproc->priv = &rproc[1]; |
1487 | 1522 | ||
1523 | device_initialize(&rproc->dev); | ||
1524 | rproc->dev.parent = dev; | ||
1525 | rproc->dev.type = &rproc_type; | ||
1526 | |||
1527 | /* Assign a unique device index and name */ | ||
1528 | rproc->index = ida_simple_get(&rproc_dev_index, 0, 0, GFP_KERNEL); | ||
1529 | if (rproc->index < 0) { | ||
1530 | dev_err(dev, "ida_simple_get failed: %d\n", rproc->index); | ||
1531 | put_device(&rproc->dev); | ||
1532 | return NULL; | ||
1533 | } | ||
1534 | |||
1535 | dev_set_name(&rproc->dev, "remoteproc%d", rproc->index); | ||
1536 | |||
1488 | atomic_set(&rproc->power, 0); | 1537 | atomic_set(&rproc->power, 0); |
1489 | 1538 | ||
1490 | kref_init(&rproc->refcount); | 1539 | kref_init(&rproc->refcount); |
@@ -1516,10 +1565,7 @@ EXPORT_SYMBOL(rproc_alloc); | |||
1516 | */ | 1565 | */ |
1517 | void rproc_free(struct rproc *rproc) | 1566 | void rproc_free(struct rproc *rproc) |
1518 | { | 1567 | { |
1519 | idr_remove_all(&rproc->notifyids); | 1568 | put_device(&rproc->dev); |
1520 | idr_destroy(&rproc->notifyids); | ||
1521 | |||
1522 | kfree(rproc); | ||
1523 | } | 1569 | } |
1524 | EXPORT_SYMBOL(rproc_free); | 1570 | EXPORT_SYMBOL(rproc_free); |
1525 | 1571 | ||
@@ -1560,6 +1606,8 @@ int rproc_unregister(struct rproc *rproc) | |||
1560 | /* the rproc is downref'ed as soon as it's removed from the klist */ | 1606 | /* the rproc is downref'ed as soon as it's removed from the klist */ |
1561 | klist_del(&rproc->node); | 1607 | klist_del(&rproc->node); |
1562 | 1608 | ||
1609 | device_del(&rproc->dev); | ||
1610 | |||
1563 | /* the rproc will only be released after its refcount drops to zero */ | 1611 | /* the rproc will only be released after its refcount drops to zero */ |
1564 | kref_put(&rproc->refcount, rproc_release); | 1612 | kref_put(&rproc->refcount, rproc_release); |
1565 | 1613 | ||
@@ -1570,6 +1618,7 @@ EXPORT_SYMBOL(rproc_unregister); | |||
1570 | static int __init remoteproc_init(void) | 1618 | static int __init remoteproc_init(void) |
1571 | { | 1619 | { |
1572 | rproc_init_debugfs(); | 1620 | rproc_init_debugfs(); |
1621 | |||
1573 | return 0; | 1622 | return 0; |
1574 | } | 1623 | } |
1575 | module_init(remoteproc_init); | 1624 | module_init(remoteproc_init); |
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 85d31a69e117..03833850f214 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c | |||
@@ -124,7 +124,7 @@ struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, | |||
124 | tfile = debugfs_create_file(name, 0400, rproc->dbg_dir, | 124 | tfile = debugfs_create_file(name, 0400, rproc->dbg_dir, |
125 | trace, &trace_rproc_ops); | 125 | trace, &trace_rproc_ops); |
126 | if (!tfile) { | 126 | if (!tfile) { |
127 | dev_err(rproc->dev, "failed to create debugfs trace entry\n"); | 127 | dev_err(&rproc->dev, "failed to create debugfs trace entry\n"); |
128 | return NULL; | 128 | return NULL; |
129 | } | 129 | } |
130 | 130 | ||
@@ -141,7 +141,7 @@ void rproc_delete_debug_dir(struct rproc *rproc) | |||
141 | 141 | ||
142 | void rproc_create_debug_dir(struct rproc *rproc) | 142 | void rproc_create_debug_dir(struct rproc *rproc) |
143 | { | 143 | { |
144 | struct device *dev = rproc->dev; | 144 | struct device *dev = &rproc->dev; |
145 | 145 | ||
146 | if (!rproc_dbg) | 146 | if (!rproc_dbg) |
147 | return; | 147 | return; |
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 26a7144e7f3b..b6621831a58a 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c | |||
@@ -36,7 +36,7 @@ static void rproc_virtio_notify(struct virtqueue *vq) | |||
36 | struct rproc *rproc = rvring->rvdev->rproc; | 36 | struct rproc *rproc = rvring->rvdev->rproc; |
37 | int notifyid = rvring->notifyid; | 37 | int notifyid = rvring->notifyid; |
38 | 38 | ||
39 | dev_dbg(rproc->dev, "kicking vq index: %d\n", notifyid); | 39 | dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid); |
40 | 40 | ||
41 | rproc->ops->kick(rproc, notifyid); | 41 | rproc->ops->kick(rproc, notifyid); |
42 | } | 42 | } |
@@ -57,7 +57,7 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid) | |||
57 | { | 57 | { |
58 | struct rproc_vring *rvring; | 58 | struct rproc_vring *rvring; |
59 | 59 | ||
60 | dev_dbg(rproc->dev, "vq index %d is interrupted\n", notifyid); | 60 | dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid); |
61 | 61 | ||
62 | rvring = idr_find(&rproc->notifyids, notifyid); | 62 | rvring = idr_find(&rproc->notifyids, notifyid); |
63 | if (!rvring || !rvring->vq) | 63 | if (!rvring || !rvring->vq) |
@@ -74,6 +74,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, | |||
74 | { | 74 | { |
75 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); | 75 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); |
76 | struct rproc *rproc = vdev_to_rproc(vdev); | 76 | struct rproc *rproc = vdev_to_rproc(vdev); |
77 | struct device *dev = &rproc->dev; | ||
77 | struct rproc_vring *rvring; | 78 | struct rproc_vring *rvring; |
78 | struct virtqueue *vq; | 79 | struct virtqueue *vq; |
79 | void *addr; | 80 | void *addr; |
@@ -95,7 +96,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, | |||
95 | size = vring_size(len, rvring->align); | 96 | size = vring_size(len, rvring->align); |
96 | memset(addr, 0, size); | 97 | memset(addr, 0, size); |
97 | 98 | ||
98 | dev_dbg(rproc->dev, "vring%d: va %p qsz %d notifyid %d\n", | 99 | dev_dbg(dev, "vring%d: va %p qsz %d notifyid %d\n", |
99 | id, addr, len, rvring->notifyid); | 100 | id, addr, len, rvring->notifyid); |
100 | 101 | ||
101 | /* | 102 | /* |
@@ -105,7 +106,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, | |||
105 | vq = vring_new_virtqueue(len, rvring->align, vdev, false, addr, | 106 | vq = vring_new_virtqueue(len, rvring->align, vdev, false, addr, |
106 | rproc_virtio_notify, callback, name); | 107 | rproc_virtio_notify, callback, name); |
107 | if (!vq) { | 108 | if (!vq) { |
108 | dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name); | 109 | dev_err(dev, "vring_new_virtqueue %s failed\n", name); |
109 | rproc_free_vring(rvring); | 110 | rproc_free_vring(rvring); |
110 | return ERR_PTR(-ENOMEM); | 111 | return ERR_PTR(-ENOMEM); |
111 | } | 112 | } |
@@ -152,7 +153,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
152 | /* now that the vqs are all set, boot the remote processor */ | 153 | /* now that the vqs are all set, boot the remote processor */ |
153 | ret = rproc_boot(rproc); | 154 | ret = rproc_boot(rproc); |
154 | if (ret) { | 155 | if (ret) { |
155 | dev_err(rproc->dev, "rproc_boot() failed %d\n", ret); | 156 | dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret); |
156 | goto error; | 157 | goto error; |
157 | } | 158 | } |
158 | 159 | ||
@@ -254,7 +255,7 @@ static void rproc_vdev_release(struct device *dev) | |||
254 | int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) | 255 | int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) |
255 | { | 256 | { |
256 | struct rproc *rproc = rvdev->rproc; | 257 | struct rproc *rproc = rvdev->rproc; |
257 | struct device *dev = rproc->dev; | 258 | struct device *dev = &rproc->dev; |
258 | struct virtio_device *vdev = &rvdev->vdev; | 259 | struct virtio_device *vdev = &rvdev->vdev; |
259 | int ret; | 260 | int ret; |
260 | 261 | ||
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 75506ec2840e..691e52ec48d9 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
@@ -911,7 +911,8 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
911 | vrp->svq = vqs[1]; | 911 | vrp->svq = vqs[1]; |
912 | 912 | ||
913 | /* allocate coherent memory for the buffers */ | 913 | /* allocate coherent memory for the buffers */ |
914 | bufs_va = dma_alloc_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, | 914 | bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, |
915 | RPMSG_TOTAL_BUF_SPACE, | ||
915 | &vrp->bufs_dma, GFP_KERNEL); | 916 | &vrp->bufs_dma, GFP_KERNEL); |
916 | if (!bufs_va) | 917 | if (!bufs_va) |
917 | goto vqs_del; | 918 | goto vqs_del; |