diff options
| -rw-r--r-- | drivers/base/dd.c | 55 | ||||
| -rw-r--r-- | drivers/pinctrl/devicetree.c | 7 | ||||
| -rw-r--r-- | include/linux/device.h | 1 |
3 files changed, 51 insertions, 12 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0df9b4461766..994a90747420 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
| @@ -235,6 +235,19 @@ static int __init deferred_probe_timeout_setup(char *str) | |||
| 235 | } | 235 | } |
| 236 | __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); | 236 | __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); |
| 237 | 237 | ||
| 238 | static int __driver_deferred_probe_check_state(struct device *dev) | ||
| 239 | { | ||
| 240 | if (!initcalls_done) | ||
| 241 | return -EPROBE_DEFER; | ||
| 242 | |||
| 243 | if (!deferred_probe_timeout) { | ||
| 244 | dev_WARN(dev, "deferred probe timeout, ignoring dependency"); | ||
| 245 | return -ETIMEDOUT; | ||
| 246 | } | ||
| 247 | |||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | |||
| 238 | /** | 251 | /** |
| 239 | * driver_deferred_probe_check_state() - Check deferred probe state | 252 | * driver_deferred_probe_check_state() - Check deferred probe state |
| 240 | * @dev: device to check | 253 | * @dev: device to check |
| @@ -248,14 +261,40 @@ __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); | |||
| 248 | */ | 261 | */ |
| 249 | int driver_deferred_probe_check_state(struct device *dev) | 262 | int driver_deferred_probe_check_state(struct device *dev) |
| 250 | { | 263 | { |
| 251 | if (initcalls_done) { | 264 | int ret; |
| 252 | if (!deferred_probe_timeout) { | 265 | |
| 253 | dev_WARN(dev, "deferred probe timeout, ignoring dependency"); | 266 | ret = __driver_deferred_probe_check_state(dev); |
| 254 | return -ETIMEDOUT; | 267 | if (ret < 0) |
| 255 | } | 268 | return ret; |
| 256 | dev_warn(dev, "ignoring dependency for device, assuming no driver"); | 269 | |
| 257 | return -ENODEV; | 270 | dev_warn(dev, "ignoring dependency for device, assuming no driver"); |
| 258 | } | 271 | |
| 272 | return -ENODEV; | ||
| 273 | } | ||
| 274 | |||
| 275 | /** | ||
| 276 | * driver_deferred_probe_check_state_continue() - check deferred probe state | ||
| 277 | * @dev: device to check | ||
| 278 | * | ||
| 279 | * Returns -ETIMEDOUT if deferred probe debug timeout has expired, or | ||
| 280 | * -EPROBE_DEFER otherwise. | ||
| 281 | * | ||
| 282 | * Drivers or subsystems can opt-in to calling this function instead of | ||
| 283 | * directly returning -EPROBE_DEFER. | ||
| 284 | * | ||
| 285 | * This is similar to driver_deferred_probe_check_state(), but it allows the | ||
| 286 | * subsystem to keep deferring probe after built-in drivers have had a chance | ||
| 287 | * to probe. One scenario where that is useful is if built-in drivers rely on | ||
| 288 | * resources that are provided by modular drivers. | ||
| 289 | */ | ||
| 290 | int driver_deferred_probe_check_state_continue(struct device *dev) | ||
| 291 | { | ||
| 292 | int ret; | ||
| 293 | |||
| 294 | ret = __driver_deferred_probe_check_state(dev); | ||
| 295 | if (ret < 0) | ||
| 296 | return ret; | ||
| 297 | |||
| 259 | return -EPROBE_DEFER; | 298 | return -EPROBE_DEFER; |
| 260 | } | 299 | } |
| 261 | 300 | ||
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index f7e354f85518..88ddbb2e30de 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c | |||
| @@ -112,12 +112,11 @@ static int dt_to_map_one_config(struct pinctrl *p, | |||
| 112 | np_pctldev = of_get_next_parent(np_pctldev); | 112 | np_pctldev = of_get_next_parent(np_pctldev); |
| 113 | if (!np_pctldev || of_node_is_root(np_pctldev)) { | 113 | if (!np_pctldev || of_node_is_root(np_pctldev)) { |
| 114 | of_node_put(np_pctldev); | 114 | of_node_put(np_pctldev); |
| 115 | ret = driver_deferred_probe_check_state(p->dev); | ||
| 116 | /* keep deferring if modules are enabled unless we've timed out */ | 115 | /* keep deferring if modules are enabled unless we've timed out */ |
| 117 | if (IS_ENABLED(CONFIG_MODULES) && !allow_default && ret == -ENODEV) | 116 | if (IS_ENABLED(CONFIG_MODULES) && !allow_default) |
| 118 | ret = -EPROBE_DEFER; | 117 | return driver_deferred_probe_check_state_continue(p->dev); |
| 119 | 118 | ||
| 120 | return ret; | 119 | return driver_deferred_probe_check_state(p->dev); |
| 121 | } | 120 | } |
| 122 | /* If we're creating a hog we can use the passed pctldev */ | 121 | /* If we're creating a hog we can use the passed pctldev */ |
| 123 | if (hog_pctldev && (np_pctldev == p->dev->of_node)) { | 122 | if (hog_pctldev && (np_pctldev == p->dev->of_node)) { |
diff --git a/include/linux/device.h b/include/linux/device.h index 709308560d32..ef61e2d50ecc 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -343,6 +343,7 @@ struct device *driver_find_device(struct device_driver *drv, | |||
| 343 | 343 | ||
| 344 | void driver_deferred_probe_add(struct device *dev); | 344 | void driver_deferred_probe_add(struct device *dev); |
| 345 | int driver_deferred_probe_check_state(struct device *dev); | 345 | int driver_deferred_probe_check_state(struct device *dev); |
| 346 | int driver_deferred_probe_check_state_continue(struct device *dev); | ||
| 346 | 347 | ||
| 347 | /** | 348 | /** |
| 348 | * struct subsys_interface - interfaces to device functions | 349 | * struct subsys_interface - interfaces to device functions |
