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

remoteproc: Introduce subdevices

A subdevice is an abstract entity that can be used to tie actions to the
booting and shutting down of a remote processor. The subdevice object is
expected to be embedded in concrete implementations, allowing for a
variety of use cases to be implemented.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

+94
+72
drivers/remoteproc/remoteproc_core.c
··· 736 736 return ret; 737 737 } 738 738 739 + static int rproc_probe_subdevices(struct rproc *rproc) 740 + { 741 + struct rproc_subdev *subdev; 742 + int ret; 743 + 744 + list_for_each_entry(subdev, &rproc->subdevs, node) { 745 + ret = subdev->probe(subdev); 746 + if (ret) 747 + goto unroll_registration; 748 + } 749 + 750 + return 0; 751 + 752 + unroll_registration: 753 + list_for_each_entry_continue_reverse(subdev, &rproc->subdevs, node) 754 + subdev->remove(subdev); 755 + 756 + return ret; 757 + } 758 + 759 + static void rproc_remove_subdevices(struct rproc *rproc) 760 + { 761 + struct rproc_subdev *subdev; 762 + 763 + list_for_each_entry(subdev, &rproc->subdevs, node) 764 + subdev->remove(subdev); 765 + } 766 + 739 767 /** 740 768 * rproc_resource_cleanup() - clean up and free all acquired resources 741 769 * @rproc: rproc handle ··· 906 878 goto clean_up_resources; 907 879 } 908 880 881 + /* probe any subdevices for the remote processor */ 882 + ret = rproc_probe_subdevices(rproc); 883 + if (ret) { 884 + dev_err(dev, "failed to probe subdevices for %s: %d\n", 885 + rproc->name, ret); 886 + goto stop_rproc; 887 + } 888 + 909 889 rproc->state = RPROC_RUNNING; 910 890 911 891 dev_info(dev, "remote processor %s is now up\n", rproc->name); 912 892 913 893 return 0; 914 894 895 + stop_rproc: 896 + rproc->ops->stop(rproc); 915 897 clean_up_resources: 916 898 rproc_resource_cleanup(rproc); 917 899 clean_up: ··· 1158 1120 /* if the remote proc is still needed, bail out */ 1159 1121 if (!atomic_dec_and_test(&rproc->power)) 1160 1122 goto out; 1123 + 1124 + /* remove any subdevices for the remote processor */ 1125 + rproc_remove_subdevices(rproc); 1161 1126 1162 1127 /* power off the remote processor */ 1163 1128 ret = rproc->ops->stop(rproc); ··· 1413 1372 INIT_LIST_HEAD(&rproc->mappings); 1414 1373 INIT_LIST_HEAD(&rproc->traces); 1415 1374 INIT_LIST_HEAD(&rproc->rvdevs); 1375 + INIT_LIST_HEAD(&rproc->subdevs); 1416 1376 1417 1377 INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work); 1418 1378 init_completion(&rproc->crash_comp); ··· 1499 1457 return 0; 1500 1458 } 1501 1459 EXPORT_SYMBOL(rproc_del); 1460 + 1461 + /** 1462 + * rproc_add_subdev() - add a subdevice to a remoteproc 1463 + * @rproc: rproc handle to add the subdevice to 1464 + * @subdev: subdev handle to register 1465 + * @probe: function to call when the rproc boots 1466 + * @remove: function to call when the rproc shuts down 1467 + */ 1468 + void rproc_add_subdev(struct rproc *rproc, 1469 + struct rproc_subdev *subdev, 1470 + int (*probe)(struct rproc_subdev *subdev), 1471 + void (*remove)(struct rproc_subdev *subdev)) 1472 + { 1473 + subdev->probe = probe; 1474 + subdev->remove = remove; 1475 + 1476 + list_add_tail(&subdev->node, &rproc->subdevs); 1477 + } 1478 + EXPORT_SYMBOL(rproc_add_subdev); 1479 + 1480 + /** 1481 + * rproc_remove_subdev() - remove a subdevice from a remoteproc 1482 + * @rproc: rproc handle to remove the subdevice from 1483 + * @subdev: subdev handle, previously registered with rproc_add_subdev() 1484 + */ 1485 + void rproc_remove_subdev(struct rproc *rproc, struct rproc_subdev *subdev) 1486 + { 1487 + list_del(&subdev->node); 1488 + } 1489 + EXPORT_SYMBOL(rproc_remove_subdev); 1502 1490 1503 1491 /** 1504 1492 * rproc_report_crash() - rproc crash reporter function
+22
include/linux/remoteproc.h
··· 400 400 * @firmware_loading_complete: marks e/o asynchronous firmware loading 401 401 * @bootaddr: address of first instruction to boot rproc with (optional) 402 402 * @rvdevs: list of remote virtio devices 403 + * @subdevs: list of subdevices, to following the running state 403 404 * @notifyids: idr for dynamically assigning rproc-wide unique notify ids 404 405 * @index: index of this rproc device 405 406 * @crash_handler: workqueue for handling a crash ··· 432 431 struct completion firmware_loading_complete; 433 432 u32 bootaddr; 434 433 struct list_head rvdevs; 434 + struct list_head subdevs; 435 435 struct idr notifyids; 436 436 int index; 437 437 struct work_struct crash_handler; ··· 444 442 struct resource_table *cached_table; 445 443 bool has_iommu; 446 444 bool auto_boot; 445 + }; 446 + 447 + /** 448 + * struct rproc_subdev - subdevice tied to a remoteproc 449 + * @node: list node related to the rproc subdevs list 450 + * @probe: probe function, called as the rproc is started 451 + * @remove: remove function, called as the rproc is stopped 452 + */ 453 + struct rproc_subdev { 454 + struct list_head node; 455 + 456 + int (*probe)(struct rproc_subdev *subdev); 457 + void (*remove)(struct rproc_subdev *subdev); 447 458 }; 448 459 449 460 /* we currently support only two vrings per rvdev */ ··· 525 510 526 511 return rvdev->rproc; 527 512 } 513 + 514 + void rproc_add_subdev(struct rproc *rproc, 515 + struct rproc_subdev *subdev, 516 + int (*probe)(struct rproc_subdev *subdev), 517 + void (*remove)(struct rproc_subdev *subdev)); 518 + 519 + void rproc_remove_subdev(struct rproc *rproc, struct rproc_subdev *subdev); 528 520 529 521 #endif /* REMOTEPROC_H */