Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'rproc-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux

Pull remoteproc updates from Bjorn Andersson:
"Support for remoteprocs that will perform recovery without help from
Linux is introduced.

The virtio integration is transitioned towards remoteproc_virtio.c and
represented by a platform_device, in preparation for instantiating
virtio instances from DeviceTree.

The iMX remoteproc driver has a couple of sparse warnings corrected
and a couple of error message printouts are cleaned up. The keystone
driver is transitioned to use the gpiod API"

* tag 'rproc-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux:
remoteproc: virtio: Fix warning on bindings by removing the of_match_table
remoteproc: Support attach recovery after rproc crash
remoteproc: Introduce rproc features
remoteproc: virtio: Create platform device for the remoteproc_virtio
remoteproc: Move rproc_vdev management to remoteproc_virtio.c
remoteproc: core: Introduce rproc_add_rvdev function
remoteproc: core: Introduce rproc_rvdev_add_device function
remoteproc: Harden rproc_handle_vdev() against integer overflow
remoteproc/keystone: Switch to using gpiod API
drivers/remoteproc: Fix repeated words in comments
remoteproc: imx_dsp_rproc: fix argument 2 of rproc_mem_entry_init
remoteproc: imx_rproc: Simplify some error message

+298 -202
+2 -2
drivers/remoteproc/imx_dsp_rproc.c
··· 599 599 } 600 600 601 601 /* Register memory region */ 602 - mem = rproc_mem_entry_init(dev, cpu_addr, (dma_addr_t)att->sa, 602 + mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)att->sa, 603 603 att->size, da, NULL, NULL, "dsp_mem"); 604 604 605 605 if (mem) ··· 635 635 } 636 636 637 637 /* Register memory region */ 638 - mem = rproc_mem_entry_init(dev, cpu_addr, (dma_addr_t)rmem->base, 638 + mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)rmem->base, 639 639 rmem->size, da, NULL, NULL, it.node->name); 640 640 641 641 if (mem)
+5 -9
drivers/remoteproc/imx_rproc.c
··· 646 646 struct imx_rproc *priv = rproc->priv; 647 647 struct device *dev = priv->dev; 648 648 struct mbox_client *cl; 649 - int ret; 650 649 651 650 if (!of_get_property(dev->of_node, "mbox-names", NULL)) 652 651 return 0; ··· 658 659 cl->rx_callback = imx_rproc_rx_callback; 659 660 660 661 priv->tx_ch = mbox_request_channel_byname(cl, "tx"); 661 - if (IS_ERR(priv->tx_ch)) { 662 - ret = PTR_ERR(priv->tx_ch); 663 - return dev_err_probe(cl->dev, ret, 664 - "failed to request tx mailbox channel: %d\n", ret); 665 - } 662 + if (IS_ERR(priv->tx_ch)) 663 + return dev_err_probe(cl->dev, PTR_ERR(priv->tx_ch), 664 + "failed to request tx mailbox channel\n"); 666 665 667 666 priv->rx_ch = mbox_request_channel_byname(cl, "rx"); 668 667 if (IS_ERR(priv->rx_ch)) { 669 668 mbox_free_channel(priv->tx_ch); 670 - ret = PTR_ERR(priv->rx_ch); 671 - return dev_err_probe(cl->dev, ret, 672 - "failed to request rx mailbox channel: %d\n", ret); 669 + return dev_err_probe(cl->dev, PTR_ERR(priv->rx_ch), 670 + "failed to request rx mailbox channel\n"); 673 671 } 674 672 675 673 return 0;
+9 -7
drivers/remoteproc/keystone_remoteproc.c
··· 14 14 #include <linux/workqueue.h> 15 15 #include <linux/of_address.h> 16 16 #include <linux/of_reserved_mem.h> 17 - #include <linux/of_gpio.h> 17 + #include <linux/gpio/consumer.h> 18 18 #include <linux/regmap.h> 19 19 #include <linux/mfd/syscon.h> 20 20 #include <linux/remoteproc.h> ··· 59 59 int num_mems; 60 60 struct regmap *dev_ctrl; 61 61 struct reset_control *reset; 62 + struct gpio_desc *kick_gpio; 62 63 u32 boot_offset; 63 64 int irq_ring; 64 65 int irq_fault; 65 - int kick_gpio; 66 66 struct work_struct workqueue; 67 67 }; 68 68 ··· 232 232 { 233 233 struct keystone_rproc *ksproc = rproc->priv; 234 234 235 - if (WARN_ON(ksproc->kick_gpio < 0)) 235 + if (!ksproc->kick_gpio) 236 236 return; 237 237 238 - gpio_set_value(ksproc->kick_gpio, 1); 238 + gpiod_set_value(ksproc->kick_gpio, 1); 239 239 } 240 240 241 241 /* ··· 432 432 goto disable_clk; 433 433 } 434 434 435 - ksproc->kick_gpio = of_get_named_gpio_flags(np, "kick-gpios", 0, NULL); 436 - if (ksproc->kick_gpio < 0) { 437 - ret = ksproc->kick_gpio; 435 + ksproc->kick_gpio = gpiod_get(dev, "kick", GPIOD_ASIS); 436 + ret = PTR_ERR_OR_ZERO(ksproc->kick_gpio); 437 + if (ret) { 438 438 dev_err(dev, "failed to get gpio for virtio kicks, status = %d\n", 439 439 ret); 440 440 goto disable_clk; ··· 466 466 467 467 release_mem: 468 468 of_reserved_mem_device_release(dev); 469 + gpiod_put(ksproc->kick_gpio); 469 470 disable_clk: 470 471 pm_runtime_put_sync(dev); 471 472 disable_rpm: ··· 481 480 struct keystone_rproc *ksproc = platform_get_drvdata(pdev); 482 481 483 482 rproc_del(ksproc->rproc); 483 + gpiod_put(ksproc->kick_gpio); 484 484 pm_runtime_put_sync(&pdev->dev); 485 485 pm_runtime_disable(&pdev->dev); 486 486 rproc_free(ksproc->rproc);
+66 -157
drivers/remoteproc/remoteproc_core.c
··· 23 23 #include <linux/panic_notifier.h> 24 24 #include <linux/slab.h> 25 25 #include <linux/mutex.h> 26 - #include <linux/dma-map-ops.h> 27 26 #include <linux/dma-mapping.h> 28 - #include <linux/dma-direct.h> /* XXX: pokes into bus_dma_range */ 29 27 #include <linux/firmware.h> 30 28 #include <linux/string.h> 31 29 #include <linux/debugfs.h> ··· 344 346 if (rproc_check_carveout_da(rproc, mem, rsc->vring[i].da, size)) 345 347 return -ENOMEM; 346 348 } else { 347 - /* Register carveout in in list */ 349 + /* Register carveout in list */ 348 350 mem = rproc_mem_entry_init(dev, NULL, 0, 349 351 size, rsc->vring[i].da, 350 352 rproc_alloc_carveout, ··· 382 384 return 0; 383 385 } 384 386 385 - static int 387 + int 386 388 rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i) 387 389 { 388 390 struct rproc *rproc = rvdev->rproc; ··· 433 435 } 434 436 } 435 437 436 - static int rproc_vdev_do_start(struct rproc_subdev *subdev) 438 + void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev) 437 439 { 438 - struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 439 - 440 - return rproc_add_virtio_dev(rvdev, rvdev->id); 440 + if (rvdev && rproc) 441 + list_add_tail(&rvdev->node, &rproc->rvdevs); 441 442 } 442 443 443 - static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed) 444 + void rproc_remove_rvdev(struct rproc_vdev *rvdev) 444 445 { 445 - struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 446 - int ret; 447 - 448 - ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev); 449 - if (ret) 450 - dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret); 446 + if (rvdev) 447 + list_del(&rvdev->node); 451 448 } 452 - 453 - /** 454 - * rproc_rvdev_release() - release the existence of a rvdev 455 - * 456 - * @dev: the subdevice's dev 457 - */ 458 - static void rproc_rvdev_release(struct device *dev) 459 - { 460 - struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev); 461 - 462 - of_reserved_mem_device_release(dev); 463 - dma_release_coherent_memory(dev); 464 - 465 - kfree(rvdev); 466 - } 467 - 468 - static int copy_dma_range_map(struct device *to, struct device *from) 469 - { 470 - const struct bus_dma_region *map = from->dma_range_map, *new_map, *r; 471 - int num_ranges = 0; 472 - 473 - if (!map) 474 - return 0; 475 - 476 - for (r = map; r->size; r++) 477 - num_ranges++; 478 - 479 - new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)), 480 - GFP_KERNEL); 481 - if (!new_map) 482 - return -ENOMEM; 483 - to->dma_range_map = new_map; 484 - return 0; 485 - } 486 - 487 449 /** 488 450 * rproc_handle_vdev() - handle a vdev fw resource 489 451 * @rproc: the remote processor ··· 478 520 struct fw_rsc_vdev *rsc = ptr; 479 521 struct device *dev = &rproc->dev; 480 522 struct rproc_vdev *rvdev; 481 - int i, ret; 482 - char name[16]; 523 + size_t rsc_size; 524 + struct rproc_vdev_data rvdev_data; 525 + struct platform_device *pdev; 483 526 484 527 /* make sure resource isn't truncated */ 485 - if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len > 486 - avail) { 528 + rsc_size = struct_size(rsc, vring, rsc->num_of_vrings); 529 + if (size_add(rsc_size, rsc->config_len) > avail) { 487 530 dev_err(dev, "vdev rsc is truncated\n"); 488 531 return -EINVAL; 489 532 } ··· 504 545 return -EINVAL; 505 546 } 506 547 507 - rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL); 508 - if (!rvdev) 509 - return -ENOMEM; 548 + rvdev_data.id = rsc->id; 549 + rvdev_data.index = rproc->nb_vdev++; 550 + rvdev_data.rsc_offset = offset; 551 + rvdev_data.rsc = rsc; 510 552 511 - kref_init(&rvdev->refcount); 512 - 513 - rvdev->id = rsc->id; 514 - rvdev->rproc = rproc; 515 - rvdev->index = rproc->nb_vdev++; 516 - 517 - /* Initialise vdev subdevice */ 518 - snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index); 519 - rvdev->dev.parent = &rproc->dev; 520 - rvdev->dev.release = rproc_rvdev_release; 521 - dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name); 522 - dev_set_drvdata(&rvdev->dev, rvdev); 523 - 524 - ret = device_register(&rvdev->dev); 525 - if (ret) { 526 - put_device(&rvdev->dev); 527 - return ret; 553 + pdev = platform_device_register_data(dev, "rproc-virtio", rvdev_data.index, &rvdev_data, 554 + sizeof(rvdev_data)); 555 + if (IS_ERR(pdev)) { 556 + dev_err(dev, "failed to create rproc-virtio device\n"); 557 + return PTR_ERR(pdev); 528 558 } 529 - 530 - ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent); 531 - if (ret) 532 - goto free_rvdev; 533 - 534 - /* Make device dma capable by inheriting from parent's capabilities */ 535 - set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent)); 536 - 537 - ret = dma_coerce_mask_and_coherent(&rvdev->dev, 538 - dma_get_mask(rproc->dev.parent)); 539 - if (ret) { 540 - dev_warn(dev, 541 - "Failed to set DMA mask %llx. Trying to continue... (%pe)\n", 542 - dma_get_mask(rproc->dev.parent), ERR_PTR(ret)); 543 - } 544 - 545 - /* parse the vrings */ 546 - for (i = 0; i < rsc->num_of_vrings; i++) { 547 - ret = rproc_parse_vring(rvdev, rsc, i); 548 - if (ret) 549 - goto free_rvdev; 550 - } 551 - 552 - /* remember the resource offset*/ 553 - rvdev->rsc_offset = offset; 554 - 555 - /* allocate the vring resources */ 556 - for (i = 0; i < rsc->num_of_vrings; i++) { 557 - ret = rproc_alloc_vring(rvdev, i); 558 - if (ret) 559 - goto unwind_vring_allocations; 560 - } 561 - 562 - list_add_tail(&rvdev->node, &rproc->rvdevs); 563 - 564 - rvdev->subdev.start = rproc_vdev_do_start; 565 - rvdev->subdev.stop = rproc_vdev_do_stop; 566 - 567 - rproc_add_subdev(rproc, &rvdev->subdev); 568 559 569 560 return 0; 570 - 571 - unwind_vring_allocations: 572 - for (i--; i >= 0; i--) 573 - rproc_free_vring(&rvdev->vring[i]); 574 - free_rvdev: 575 - device_unregister(&rvdev->dev); 576 - return ret; 577 - } 578 - 579 - void rproc_vdev_release(struct kref *ref) 580 - { 581 - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount); 582 - struct rproc_vring *rvring; 583 - struct rproc *rproc = rvdev->rproc; 584 - int id; 585 - 586 - for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) { 587 - rvring = &rvdev->vring[id]; 588 - rproc_free_vring(rvring); 589 - } 590 - 591 - rproc_remove_subdev(rproc, &rvdev->subdev); 592 - list_del(&rvdev->node); 593 - device_unregister(&rvdev->dev); 594 561 } 595 562 596 563 /** ··· 1250 1365 1251 1366 /* clean up remote vdev entries */ 1252 1367 list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node) 1253 - kref_put(&rvdev->refcount, rproc_vdev_release); 1368 + platform_device_unregister(rvdev->pdev); 1254 1369 1255 1370 rproc_coredump_cleanup(rproc); 1256 1371 } ··· 1770 1885 return 0; 1771 1886 } 1772 1887 1888 + static int rproc_attach_recovery(struct rproc *rproc) 1889 + { 1890 + int ret; 1891 + 1892 + ret = __rproc_detach(rproc); 1893 + if (ret) 1894 + return ret; 1895 + 1896 + return __rproc_attach(rproc); 1897 + } 1898 + 1899 + static int rproc_boot_recovery(struct rproc *rproc) 1900 + { 1901 + const struct firmware *firmware_p; 1902 + struct device *dev = &rproc->dev; 1903 + int ret; 1904 + 1905 + ret = rproc_stop(rproc, true); 1906 + if (ret) 1907 + return ret; 1908 + 1909 + /* generate coredump */ 1910 + rproc->ops->coredump(rproc); 1911 + 1912 + /* load firmware */ 1913 + ret = request_firmware(&firmware_p, rproc->firmware, dev); 1914 + if (ret < 0) { 1915 + dev_err(dev, "request_firmware failed: %d\n", ret); 1916 + return ret; 1917 + } 1918 + 1919 + /* boot the remote processor up again */ 1920 + ret = rproc_start(rproc, firmware_p); 1921 + 1922 + release_firmware(firmware_p); 1923 + 1924 + return ret; 1925 + } 1926 + 1773 1927 /** 1774 1928 * rproc_trigger_recovery() - recover a remoteproc 1775 1929 * @rproc: the remote processor ··· 1823 1899 */ 1824 1900 int rproc_trigger_recovery(struct rproc *rproc) 1825 1901 { 1826 - const struct firmware *firmware_p; 1827 1902 struct device *dev = &rproc->dev; 1828 1903 int ret; 1829 1904 ··· 1836 1913 1837 1914 dev_err(dev, "recovering %s\n", rproc->name); 1838 1915 1839 - ret = rproc_stop(rproc, true); 1840 - if (ret) 1841 - goto unlock_mutex; 1842 - 1843 - /* generate coredump */ 1844 - rproc->ops->coredump(rproc); 1845 - 1846 - /* load firmware */ 1847 - ret = request_firmware(&firmware_p, rproc->firmware, dev); 1848 - if (ret < 0) { 1849 - dev_err(dev, "request_firmware failed: %d\n", ret); 1850 - goto unlock_mutex; 1851 - } 1852 - 1853 - /* boot the remote processor up again */ 1854 - ret = rproc_start(rproc, firmware_p); 1855 - 1856 - release_firmware(firmware_p); 1916 + if (rproc_has_feature(rproc, RPROC_FEAT_ATTACH_ON_RECOVERY)) 1917 + ret = rproc_attach_recovery(rproc); 1918 + else 1919 + ret = rproc_boot_recovery(rproc); 1857 1920 1858 1921 unlock_mutex: 1859 1922 mutex_unlock(&rproc->lock);
+34 -4
drivers/remoteproc/remoteproc_internal.h
··· 24 24 struct rproc_mem_entry trace_mem; 25 25 }; 26 26 27 + /** 28 + * struct rproc_vdev_data - remoteproc virtio device data 29 + * @rsc_offset: offset of the vdev's resource entry 30 + * @id: virtio device id (as in virtio_ids.h) 31 + * @index: vdev position versus other vdev declared in resource table 32 + * @rsc: pointer to the vdev resource entry. Valid only during vdev init as 33 + * the resource can be cached by rproc. 34 + */ 35 + struct rproc_vdev_data { 36 + u32 rsc_offset; 37 + unsigned int id; 38 + u32 index; 39 + struct fw_rsc_vdev *rsc; 40 + }; 41 + 42 + static inline bool rproc_has_feature(struct rproc *rproc, unsigned int feature) 43 + { 44 + return test_bit(feature, rproc->features); 45 + } 46 + 47 + static inline int rproc_set_feature(struct rproc *rproc, unsigned int feature) 48 + { 49 + if (feature >= RPROC_MAX_FEATURES) 50 + return -EINVAL; 51 + 52 + set_bit(feature, rproc->features); 53 + 54 + return 0; 55 + } 56 + 27 57 /* from remoteproc_core.c */ 28 58 void rproc_release(struct kref *kref); 29 - irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); 30 - void rproc_vdev_release(struct kref *ref); 31 59 int rproc_of_parse_firmware(struct device *dev, int index, 32 60 const char **fw_name); 33 61 34 62 /* from remoteproc_virtio.c */ 35 - int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id); 36 - int rproc_remove_virtio_dev(struct device *dev, void *data); 63 + irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); 37 64 38 65 /* from remoteproc_debugfs.c */ 39 66 void rproc_remove_trace_file(struct dentry *tfile); ··· 110 83 111 84 void rproc_free_vring(struct rproc_vring *rvring); 112 85 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i); 86 + int rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i); 113 87 114 88 phys_addr_t rproc_va_to_pa(void *cpu_addr); 115 89 int rproc_trigger_recovery(struct rproc *rproc); ··· 123 95 const struct firmware *fw); 124 96 struct rproc_mem_entry * 125 97 rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...); 98 + void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev); 99 + void rproc_remove_rvdev(struct rproc_vdev *rvdev); 126 100 127 101 static inline int rproc_prepare_device(struct rproc *rproc) 128 102 {
+164 -19
drivers/remoteproc/remoteproc_virtio.c
··· 9 9 * Brian Swetland <swetland@google.com> 10 10 */ 11 11 12 + #include <linux/dma-direct.h> 12 13 #include <linux/dma-map-ops.h> 14 + #include <linux/dma-mapping.h> 13 15 #include <linux/export.h> 14 16 #include <linux/of_reserved_mem.h> 17 + #include <linux/platform_device.h> 15 18 #include <linux/remoteproc.h> 16 19 #include <linux/virtio.h> 17 20 #include <linux/virtio_config.h> ··· 26 23 27 24 #include "remoteproc_internal.h" 28 25 26 + static int copy_dma_range_map(struct device *to, struct device *from) 27 + { 28 + const struct bus_dma_region *map = from->dma_range_map, *new_map, *r; 29 + int num_ranges = 0; 30 + 31 + if (!map) 32 + return 0; 33 + 34 + for (r = map; r->size; r++) 35 + num_ranges++; 36 + 37 + new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)), 38 + GFP_KERNEL); 39 + if (!new_map) 40 + return -ENOMEM; 41 + to->dma_range_map = new_map; 42 + return 0; 43 + } 44 + 29 45 static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) 30 46 { 31 - return container_of(vdev->dev.parent, struct rproc_vdev, dev); 47 + struct platform_device *pdev; 48 + 49 + pdev = container_of(vdev->dev.parent, struct platform_device, dev); 50 + 51 + return platform_get_drvdata(pdev); 32 52 } 33 53 34 54 static struct rproc *vdev_to_rproc(struct virtio_device *vdev) ··· 348 322 { 349 323 struct virtio_device *vdev = dev_to_virtio(dev); 350 324 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 351 - struct rproc *rproc = vdev_to_rproc(vdev); 352 325 353 326 kfree(vdev); 354 327 355 - kref_put(&rvdev->refcount, rproc_vdev_release); 356 - 357 - put_device(&rproc->dev); 328 + put_device(&rvdev->pdev->dev); 358 329 } 359 330 360 331 /** ··· 364 341 * 365 342 * Return: 0 on success or an appropriate error value otherwise 366 343 */ 367 - int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) 344 + static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) 368 345 { 369 346 struct rproc *rproc = rvdev->rproc; 370 - struct device *dev = &rvdev->dev; 347 + struct device *dev = &rvdev->pdev->dev; 371 348 struct virtio_device *vdev; 372 349 struct rproc_mem_entry *mem; 373 350 int ret; ··· 437 414 vdev->dev.parent = dev; 438 415 vdev->dev.release = rproc_virtio_dev_release; 439 416 440 - /* 441 - * We're indirectly making a non-temporary copy of the rproc pointer 442 - * here, because drivers probed with this vdev will indirectly 443 - * access the wrapping rproc. 444 - * 445 - * Therefore we must increment the rproc refcount here, and decrement 446 - * it _only_ when the vdev is released. 447 - */ 448 - get_device(&rproc->dev); 449 - 450 417 /* Reference the vdev and vring allocations */ 451 - kref_get(&rvdev->refcount); 418 + get_device(dev); 452 419 453 420 ret = register_virtio_device(vdev); 454 421 if (ret) { ··· 462 449 * 463 450 * Return: 0 464 451 */ 465 - int rproc_remove_virtio_dev(struct device *dev, void *data) 452 + static int rproc_remove_virtio_dev(struct device *dev, void *data) 466 453 { 467 454 struct virtio_device *vdev = dev_to_virtio(dev); 468 455 469 456 unregister_virtio_device(vdev); 470 457 return 0; 471 458 } 459 + 460 + static int rproc_vdev_do_start(struct rproc_subdev *subdev) 461 + { 462 + struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 463 + 464 + return rproc_add_virtio_dev(rvdev, rvdev->id); 465 + } 466 + 467 + static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed) 468 + { 469 + struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 470 + struct device *dev = &rvdev->pdev->dev; 471 + int ret; 472 + 473 + ret = device_for_each_child(dev, NULL, rproc_remove_virtio_dev); 474 + if (ret) 475 + dev_warn(dev, "can't remove vdev child device: %d\n", ret); 476 + } 477 + 478 + static int rproc_virtio_probe(struct platform_device *pdev) 479 + { 480 + struct device *dev = &pdev->dev; 481 + struct rproc_vdev_data *rvdev_data = dev->platform_data; 482 + struct rproc_vdev *rvdev; 483 + struct rproc *rproc = container_of(dev->parent, struct rproc, dev); 484 + struct fw_rsc_vdev *rsc; 485 + int i, ret; 486 + 487 + if (!rvdev_data) 488 + return -EINVAL; 489 + 490 + rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL); 491 + if (!rvdev) 492 + return -ENOMEM; 493 + 494 + rvdev->id = rvdev_data->id; 495 + rvdev->rproc = rproc; 496 + rvdev->index = rvdev_data->index; 497 + 498 + ret = copy_dma_range_map(dev, rproc->dev.parent); 499 + if (ret) 500 + return ret; 501 + 502 + /* Make device dma capable by inheriting from parent's capabilities */ 503 + set_dma_ops(dev, get_dma_ops(rproc->dev.parent)); 504 + 505 + ret = dma_coerce_mask_and_coherent(dev, dma_get_mask(rproc->dev.parent)); 506 + if (ret) { 507 + dev_warn(dev, "Failed to set DMA mask %llx. Trying to continue... (%pe)\n", 508 + dma_get_mask(rproc->dev.parent), ERR_PTR(ret)); 509 + } 510 + 511 + platform_set_drvdata(pdev, rvdev); 512 + rvdev->pdev = pdev; 513 + 514 + rsc = rvdev_data->rsc; 515 + 516 + /* parse the vrings */ 517 + for (i = 0; i < rsc->num_of_vrings; i++) { 518 + ret = rproc_parse_vring(rvdev, rsc, i); 519 + if (ret) 520 + return ret; 521 + } 522 + 523 + /* remember the resource offset*/ 524 + rvdev->rsc_offset = rvdev_data->rsc_offset; 525 + 526 + /* allocate the vring resources */ 527 + for (i = 0; i < rsc->num_of_vrings; i++) { 528 + ret = rproc_alloc_vring(rvdev, i); 529 + if (ret) 530 + goto unwind_vring_allocations; 531 + } 532 + 533 + rproc_add_rvdev(rproc, rvdev); 534 + 535 + rvdev->subdev.start = rproc_vdev_do_start; 536 + rvdev->subdev.stop = rproc_vdev_do_stop; 537 + 538 + rproc_add_subdev(rproc, &rvdev->subdev); 539 + 540 + /* 541 + * We're indirectly making a non-temporary copy of the rproc pointer 542 + * here, because the platform device or the vdev device will indirectly 543 + * access the wrapping rproc. 544 + * 545 + * Therefore we must increment the rproc refcount here, and decrement 546 + * it _only_ on platform remove. 547 + */ 548 + get_device(&rproc->dev); 549 + 550 + return 0; 551 + 552 + unwind_vring_allocations: 553 + for (i--; i >= 0; i--) 554 + rproc_free_vring(&rvdev->vring[i]); 555 + 556 + return ret; 557 + } 558 + 559 + static int rproc_virtio_remove(struct platform_device *pdev) 560 + { 561 + struct rproc_vdev *rvdev = dev_get_drvdata(&pdev->dev); 562 + struct rproc *rproc = rvdev->rproc; 563 + struct rproc_vring *rvring; 564 + int id; 565 + 566 + for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) { 567 + rvring = &rvdev->vring[id]; 568 + rproc_free_vring(rvring); 569 + } 570 + 571 + rproc_remove_subdev(rproc, &rvdev->subdev); 572 + rproc_remove_rvdev(rvdev); 573 + 574 + of_reserved_mem_device_release(&pdev->dev); 575 + dma_release_coherent_memory(&pdev->dev); 576 + 577 + put_device(&rproc->dev); 578 + 579 + return 0; 580 + } 581 + 582 + /* Platform driver */ 583 + static struct platform_driver rproc_virtio_driver = { 584 + .probe = rproc_virtio_probe, 585 + .remove = rproc_virtio_remove, 586 + .driver = { 587 + .name = "rproc-virtio", 588 + }, 589 + }; 590 + builtin_platform_driver(rproc_virtio_driver);
+18 -4
include/linux/remoteproc.h
··· 490 490 }; 491 491 492 492 /** 493 + * enum rproc_features - features supported 494 + * 495 + * @RPROC_FEAT_ATTACH_ON_RECOVERY: The remote processor does not need help 496 + * from Linux to recover, such as firmware 497 + * loading. Linux just needs to attach after 498 + * recovery. 499 + */ 500 + 501 + enum rproc_features { 502 + RPROC_FEAT_ATTACH_ON_RECOVERY, 503 + RPROC_MAX_FEATURES, 504 + }; 505 + 506 + /** 493 507 * struct rproc - represents a physical remote processor device 494 508 * @node: list node of this rproc object 495 509 * @domain: iommu domain ··· 544 530 * @elf_machine: firmware ELF machine 545 531 * @cdev: character device of the rproc 546 532 * @cdev_put_on_release: flag to indicate if remoteproc should be shutdown on @char_dev release 533 + * @features: indicate remoteproc features 547 534 */ 548 535 struct rproc { 549 536 struct list_head node; ··· 585 570 u16 elf_machine; 586 571 struct cdev cdev; 587 572 bool cdev_put_on_release; 573 + DECLARE_BITMAP(features, RPROC_MAX_FEATURES); 588 574 }; 589 575 590 576 /** ··· 632 616 633 617 /** 634 618 * struct rproc_vdev - remoteproc state for a supported virtio device 635 - * @refcount: reference counter for the vdev and vring allocations 636 619 * @subdev: handle for registering the vdev as a rproc subdevice 637 - * @dev: device struct used for reference count semantics 620 + * @pdev: remoteproc virtio platform device 638 621 * @id: virtio device id (as in virtio_ids.h) 639 622 * @node: list node 640 623 * @rproc: the rproc handle ··· 642 627 * @index: vdev position versus other vdev declared in resource table 643 628 */ 644 629 struct rproc_vdev { 645 - struct kref refcount; 646 630 647 631 struct rproc_subdev subdev; 648 - struct device dev; 632 + struct platform_device *pdev; 649 633 650 634 unsigned int id; 651 635 struct list_head node;