diff options
Diffstat (limited to 'drivers/base/dd.c')
| -rw-r--r-- | drivers/base/dd.c | 40 | 
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 70f79fc71539..ec69b43f926a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -274,12 +274,42 @@ static int __init deferred_probe_timeout_setup(char *str)  }  __setup("deferred_probe_timeout=", deferred_probe_timeout_setup); +/** + * driver_deferred_probe_check_state() - Check deferred probe state + * @dev: device to check + * + * Return: + * * -ENODEV if initcalls have completed and modules are disabled. + * * -ETIMEDOUT if the deferred probe timeout was set and has expired + *   and modules are enabled. + * * -EPROBE_DEFER in other cases. + * + * Drivers or subsystems can opt-in to calling this function instead of directly + * returning -EPROBE_DEFER. + */ +int driver_deferred_probe_check_state(struct device *dev) +{ +	if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) { +		dev_warn(dev, "ignoring dependency for device, assuming no driver\n"); +		return -ENODEV; +	} + +	if (!driver_deferred_probe_timeout && initcalls_done) { +		dev_warn(dev, "deferred probe timeout, ignoring dependency\n"); +		return -ETIMEDOUT; +	} + +	return -EPROBE_DEFER; +} +EXPORT_SYMBOL_GPL(driver_deferred_probe_check_state); +  static void deferred_probe_timeout_work_func(struct work_struct *work)  {  	struct device_private *p;  	fw_devlink_drivers_done(); +	driver_deferred_probe_timeout = 0;  	driver_deferred_probe_trigger();  	flush_work(&deferred_probe_work); @@ -881,6 +911,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)  		dev_dbg(dev, "Device match requests probe deferral\n");  		dev->can_match = true;  		driver_deferred_probe_add(dev); +		/* +		 * Device can't match with a driver right now, so don't attempt +		 * to match or bind with other drivers on the bus. +		 */ +		return ret;  	} else if (ret < 0) {  		dev_dbg(dev, "Bus failed to match device: %d\n", ret);  		return ret; @@ -1120,6 +1155,11 @@ static int __driver_attach(struct device *dev, void *data)  		dev_dbg(dev, "Device match requests probe deferral\n");  		dev->can_match = true;  		driver_deferred_probe_add(dev); +		/* +		 * Driver could not match with device, but may match with +		 * another device on the bus. +		 */ +		return 0;  	} else if (ret < 0) {  		dev_dbg(dev, "Bus failed to match device: %d\n", ret);  		return ret;  | 
