The firmware corresponding to a device (dev.fwnode) might be able to provide functional dependency information between a device and its supplier and consumer devices. Tracking this functional dependency allows optimizing device probe order and informing a supplier when all its consumers have probed (and thereby actively managing their resources). The existing device links feature allows tracking and using supplier-consumer relationships. So, this patch adds the add_links() fwnode callback to allow firmware to create device links for each device as the device is added. However, when consumer devices are added, they might not have a supplier device to link to despite needing mandatory resources/functionality from one or more suppliers. A waiting_for_suppliers list is created to track such consumers and retry linking them when new devices get added.
Showing the changes to include/linux (2 of 4 files). Show all
Unified · Split
| @@ -1135,11 +1135,13 @@ enum dl_dev_state { · 1134 unmodified lines | ||
| 1135 | 1135 | * struct dev_links_info - Device data related to device links. |
| 1136 | 1136 | * @suppliers: List of links to supplier devices. |
| 1137 | 1137 | * @consumers: List of links to consumer devices. |
| 1138 | + * @needs_suppliers: Hook to global list of devices waiting for suppliers. | |
| 1138 | 1139 | * @status: Driver status information. |
| 1139 | 1140 | */ |
| 1140 | 1141 | struct dev_links_info { |
| 1141 | 1142 | struct list_head suppliers; |
| 1142 | 1143 | struct list_head consumers; |
| 1144 | + struct list_head needs_suppliers; | |
| 1143 | 1145 | enum dl_dev_state status; |
| 1144 | 1146 | }; |
| 1145 | 1147 | |
| @@ -66,6 +66,21 @@ struct fwnode_reference_args { · 65 unmodified lines | ||
| 66 | 66 | * endpoint node. |
| 67 | 67 | * @graph_get_port_parent: Return the parent node of a port node. |
| 68 | 68 | * @graph_parse_endpoint: Parse endpoint for port and endpoint id. |
| 69 | + * @add_links: Called after the device corresponding to the fwnode is added | |
| 70 | + * using device_add(). The function is expected to create device | |
| 71 | + * links to all the suppliers of the device that are available at | |
| 72 | + * the time this function is called. The function must NOT stop | |
| 73 | + * at the first failed device link if other unlinked supplier | |
| 74 | + * devices are present in the system. If some suppliers are not | |
| 75 | + * yet available, this function will be called again when other | |
| 76 | + * devices are added to allow creating device links to any newly | |
| 77 | + * available suppliers. | |
| 78 | + * | |
| 79 | + * Return 0 if device links have been successfully created to all | |
| 80 | + * the suppliers of this device or if the supplier information is | |
| 81 | + * not known. Return an error if and only if the supplier | |
| 82 | + * information is known but some of the suppliers are not yet | |
| 83 | + * available to create device links to. | |
| 69 | 84 | */ |
| 70 | 85 | struct fwnode_operations { |
| 71 | 86 | struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); |
| @@ -103,6 +118,8 @@ struct fwnode_operations { · 31 unmodified lines | ||
| 103 | 118 | (*graph_get_port_parent)(struct fwnode_handle *fwnode); |
| 104 | 119 | int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode, |
| 105 | 120 | struct fwnode_endpoint *endpoint); |
| 121 | + int (*add_links)(const struct fwnode_handle *fwnode, | |
| 122 | + struct device *dev); | |
| 106 | 123 | }; |
| 107 | 124 | |
| 108 | 125 | #define fwnode_has_op(fwnode, op) \ |