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 | * struct dev_links_info - Device data related to device links. | 1135 | * struct dev_links_info - Device data related to device links. |
| 1136 | * @suppliers: List of links to supplier devices. | 1136 | * @suppliers: List of links to supplier devices. |
| 1137 | * @consumers: List of links to consumer devices. | 1137 | * @consumers: List of links to consumer devices. |
| 1138 | * @needs_suppliers: Hook to global list of devices waiting for suppliers. | ||
| 1138 | * @status: Driver status information. | 1139 | * @status: Driver status information. |
| 1139 | */ | 1140 | */ |
| 1140 | struct dev_links_info { | 1141 | struct dev_links_info { |
| 1141 | struct list_head suppliers; | 1142 | struct list_head suppliers; |
| 1142 | struct list_head consumers; | 1143 | struct list_head consumers; |
| 1144 | struct list_head needs_suppliers; | ||
| 1143 | enum dl_dev_state status; | 1145 | enum dl_dev_state status; |
| 1144 | }; | 1146 | }; |
| 1145 | 1147 | ||
| @@ -66,6 +66,21 @@ struct fwnode_reference_args { · 65 unmodified lines | |||
| 66 | * endpoint node. | 66 | * endpoint node. |
| 67 | * @graph_get_port_parent: Return the parent node of a port node. | 67 | * @graph_get_port_parent: Return the parent node of a port node. |
| 68 | * @graph_parse_endpoint: Parse endpoint for port and endpoint id. | 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 | struct fwnode_operations { | 85 | struct fwnode_operations { |
| 71 | struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); | 86 | struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); |
| @@ -103,6 +118,8 @@ struct fwnode_operations { · 31 unmodified lines | |||
| 103 | (*graph_get_port_parent)(struct fwnode_handle *fwnode); | 118 | (*graph_get_port_parent)(struct fwnode_handle *fwnode); |
| 104 | int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode, | 119 | int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode, |
| 105 | struct fwnode_endpoint *endpoint); | 120 | struct fwnode_endpoint *endpoint); |
| 121 | int (*add_links)(const struct fwnode_handle *fwnode, | ||
| 122 | struct device *dev); | ||
| 106 | }; | 123 | }; |
| 107 | 124 | ||
| 108 | #define fwnode_has_op(fwnode, op) \ | 125 | #define fwnode_has_op(fwnode, op) \ |