Skip to content

Commit 2f8c3ae

Browse files
Saravana Kannangregkh
authored andcommitted
driver core: Add wait_for_init_devices_probe helper function
Some devices might need to be probed and bound successfully before the kernel boot sequence can finish and move on to init/userspace. For example, a network interface might need to be bound to be able to mount a NFS rootfs. With fw_devlink=on by default, some of these devices might be blocked from probing because they are waiting on a optional supplier that doesn't have a driver. While fw_devlink will eventually identify such devices and unblock the probing automatically, it might be too late by the time it unblocks the probing of devices. For example, the IP4 autoconfig might timeout before fw_devlink unblocks probing of the network interface. This function is available to temporarily try and probe all devices that have a driver even if some of their suppliers haven't been added or don't have drivers. The drivers can then decide which of the suppliers are optional vs mandatory and probe the device if possible. By the time this function returns, all such "best effort" probes are guaranteed to be completed. If a device successfully probes in this mode, we delete all fw_devlink discovered dependencies of that device where the supplier hasn't yet probed successfully because they have to be optional dependencies. This also means that some devices that aren't needed for init and could have waited for their optional supplier to probe (when the supplier's module is loaded later on) would end up probing prematurely with limited functionality. So call this function only when boot would fail without it. Tested-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Saravana Kannan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f821727 commit 2f8c3ae

File tree

4 files changed

+110
-11
lines changed

4 files changed

+110
-11
lines changed

drivers/base/base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ extern int devres_release_all(struct device *dev);
160160
extern void device_block_probing(void);
161161
extern void device_unblock_probing(void);
162162
extern void deferred_probe_extend_timeout(void);
163+
extern void driver_deferred_probe_trigger(void);
163164

164165
/* /sys/devices directory */
165166
extern struct kset *devices_kset;

drivers/base/core.c

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static unsigned int defer_sync_state_count = 1;
5454
static DEFINE_MUTEX(fwnode_link_lock);
5555
static bool fw_devlink_is_permissive(void);
5656
static bool fw_devlink_drv_reg_done;
57+
static bool fw_devlink_best_effort;
5758

5859
/**
5960
* fwnode_link_add - Create a link between two fwnode_handles.
@@ -965,6 +966,11 @@ static void device_links_missing_supplier(struct device *dev)
965966
}
966967
}
967968

969+
static bool dev_is_best_effort(struct device *dev)
970+
{
971+
return fw_devlink_best_effort && dev->can_match;
972+
}
973+
968974
/**
969975
* device_links_check_suppliers - Check presence of supplier drivers.
970976
* @dev: Consumer device.
@@ -984,7 +990,7 @@ static void device_links_missing_supplier(struct device *dev)
984990
int device_links_check_suppliers(struct device *dev)
985991
{
986992
struct device_link *link;
987-
int ret = 0;
993+
int ret = 0, fwnode_ret = 0;
988994
struct fwnode_handle *sup_fw;
989995

990996
/*
@@ -997,12 +1003,17 @@ int device_links_check_suppliers(struct device *dev)
9971003
sup_fw = list_first_entry(&dev->fwnode->suppliers,
9981004
struct fwnode_link,
9991005
c_hook)->supplier;
1000-
dev_err_probe(dev, -EPROBE_DEFER, "wait for supplier %pfwP\n",
1001-
sup_fw);
1002-
mutex_unlock(&fwnode_link_lock);
1003-
return -EPROBE_DEFER;
1006+
if (!dev_is_best_effort(dev)) {
1007+
fwnode_ret = -EPROBE_DEFER;
1008+
dev_err_probe(dev, -EPROBE_DEFER,
1009+
"wait for supplier %pfwP\n", sup_fw);
1010+
} else {
1011+
fwnode_ret = -EAGAIN;
1012+
}
10041013
}
10051014
mutex_unlock(&fwnode_link_lock);
1015+
if (fwnode_ret == -EPROBE_DEFER)
1016+
return fwnode_ret;
10061017

10071018
device_links_write_lock();
10081019

@@ -1012,6 +1023,14 @@ int device_links_check_suppliers(struct device *dev)
10121023

10131024
if (link->status != DL_STATE_AVAILABLE &&
10141025
!(link->flags & DL_FLAG_SYNC_STATE_ONLY)) {
1026+
1027+
if (dev_is_best_effort(dev) &&
1028+
link->flags & DL_FLAG_INFERRED &&
1029+
!link->supplier->can_match) {
1030+
ret = -EAGAIN;
1031+
continue;
1032+
}
1033+
10151034
device_links_missing_supplier(dev);
10161035
dev_err_probe(dev, -EPROBE_DEFER,
10171036
"supplier %s not ready\n",
@@ -1024,7 +1043,8 @@ int device_links_check_suppliers(struct device *dev)
10241043
dev->links.status = DL_DEV_PROBING;
10251044

10261045
device_links_write_unlock();
1027-
return ret;
1046+
1047+
return ret ? ret : fwnode_ret;
10281048
}
10291049

10301050
/**
@@ -1289,6 +1309,18 @@ void device_links_driver_bound(struct device *dev)
12891309
* save to drop the managed link completely.
12901310
*/
12911311
device_link_drop_managed(link);
1312+
} else if (dev_is_best_effort(dev) &&
1313+
link->flags & DL_FLAG_INFERRED &&
1314+
link->status != DL_STATE_CONSUMER_PROBE &&
1315+
!link->supplier->can_match) {
1316+
/*
1317+
* When dev_is_best_effort() is true, we ignore device
1318+
* links to suppliers that don't have a driver. If the
1319+
* consumer device still managed to probe, there's no
1320+
* point in maintaining a device link in a weird state
1321+
* (consumer probed before supplier). So delete it.
1322+
*/
1323+
device_link_drop_managed(link);
12921324
} else {
12931325
WARN_ON(link->status != DL_STATE_CONSUMER_PROBE);
12941326
WRITE_ONCE(link->status, DL_STATE_ACTIVE);
@@ -1655,6 +1687,62 @@ void fw_devlink_drivers_done(void)
16551687
device_links_write_unlock();
16561688
}
16571689

1690+
/**
1691+
* wait_for_init_devices_probe - Try to probe any device needed for init
1692+
*
1693+
* Some devices might need to be probed and bound successfully before the kernel
1694+
* boot sequence can finish and move on to init/userspace. For example, a
1695+
* network interface might need to be bound to be able to mount a NFS rootfs.
1696+
*
1697+
* With fw_devlink=on by default, some of these devices might be blocked from
1698+
* probing because they are waiting on a optional supplier that doesn't have a
1699+
* driver. While fw_devlink will eventually identify such devices and unblock
1700+
* the probing automatically, it might be too late by the time it unblocks the
1701+
* probing of devices. For example, the IP4 autoconfig might timeout before
1702+
* fw_devlink unblocks probing of the network interface.
1703+
*
1704+
* This function is available to temporarily try and probe all devices that have
1705+
* a driver even if some of their suppliers haven't been added or don't have
1706+
* drivers.
1707+
*
1708+
* The drivers can then decide which of the suppliers are optional vs mandatory
1709+
* and probe the device if possible. By the time this function returns, all such
1710+
* "best effort" probes are guaranteed to be completed. If a device successfully
1711+
* probes in this mode, we delete all fw_devlink discovered dependencies of that
1712+
* device where the supplier hasn't yet probed successfully because they have to
1713+
* be optional dependencies.
1714+
*
1715+
* Any devices that didn't successfully probe go back to being treated as if
1716+
* this function was never called.
1717+
*
1718+
* This also means that some devices that aren't needed for init and could have
1719+
* waited for their optional supplier to probe (when the supplier's module is
1720+
* loaded later on) would end up probing prematurely with limited functionality.
1721+
* So call this function only when boot would fail without it.
1722+
*/
1723+
void __init wait_for_init_devices_probe(void)
1724+
{
1725+
if (!fw_devlink_flags || fw_devlink_is_permissive())
1726+
return;
1727+
1728+
/*
1729+
* Wait for all ongoing probes to finish so that the "best effort" is
1730+
* only applied to devices that can't probe otherwise.
1731+
*/
1732+
wait_for_device_probe();
1733+
1734+
pr_info("Trying to probe devices needed for running init ...\n");
1735+
fw_devlink_best_effort = true;
1736+
driver_deferred_probe_trigger();
1737+
1738+
/*
1739+
* Wait for all "best effort" probes to finish before going back to
1740+
* normal enforcement.
1741+
*/
1742+
wait_for_device_probe();
1743+
fw_devlink_best_effort = false;
1744+
}
1745+
16581746
static void fw_devlink_unblock_consumers(struct device *dev)
16591747
{
16601748
struct device_link *link;

drivers/base/dd.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static bool driver_deferred_probe_enable;
172172
* changes in the midst of a probe, then deferred processing should be triggered
173173
* again.
174174
*/
175-
static void driver_deferred_probe_trigger(void)
175+
void driver_deferred_probe_trigger(void)
176176
{
177177
if (!driver_deferred_probe_enable)
178178
return;
@@ -580,7 +580,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
580580
{
581581
bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE) &&
582582
!drv->suppress_bind_attrs;
583-
int ret;
583+
int ret, link_ret;
584584

585585
if (defer_all_probes) {
586586
/*
@@ -592,9 +592,9 @@ static int really_probe(struct device *dev, struct device_driver *drv)
592592
return -EPROBE_DEFER;
593593
}
594594

595-
ret = device_links_check_suppliers(dev);
596-
if (ret)
597-
return ret;
595+
link_ret = device_links_check_suppliers(dev);
596+
if (link_ret == -EPROBE_DEFER)
597+
return link_ret;
598598

599599
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
600600
drv->bus->name, __func__, drv->name, dev_name(dev));
@@ -633,6 +633,15 @@ static int really_probe(struct device *dev, struct device_driver *drv)
633633

634634
ret = call_driver_probe(dev, drv);
635635
if (ret) {
636+
/*
637+
* If fw_devlink_best_effort is active (denoted by -EAGAIN), the
638+
* device might actually probe properly once some of its missing
639+
* suppliers have probed. So, treat this as if the driver
640+
* returned -EPROBE_DEFER.
641+
*/
642+
if (link_ret == -EAGAIN)
643+
ret = -EPROBE_DEFER;
644+
636645
/*
637646
* Return probe errors as positive values so that the callers
638647
* can distinguish them from other errors.

include/linux/device/driver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ extern struct device_driver *driver_find(const char *name,
129129
struct bus_type *bus);
130130
extern int driver_probe_done(void);
131131
extern void wait_for_device_probe(void);
132+
void __init wait_for_init_devices_probe(void);
132133

133134
/* sysfs interface for exporting driver attributes */
134135

0 commit comments

Comments
 (0)