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/remoteproc/remoteproc_core.c | |
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/remoteproc/remoteproc_core.c')
-rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 135 |
1 files changed, 92 insertions, 43 deletions
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); |