Skip to content

Commit 3fb1686

Browse files
Saravana Kannangregkh
authored andcommitted
driver core: fw_devlink: Make cycle detection more robust
fw_devlink could only detect a single and simple cycle because it relied mainly on device link cycle detection code that only checked for cycles between devices. The expectation was that the firmware wouldn't have complicated cycles and multiple cycles between devices. That expectation has been proven to be wrong. For example, fw_devlink could handle: +-+ +-+ |A+------> |B+ +-+ +++ ^ | | | +----------+ But it couldn't handle even something as "simple" as: +---------------------+ | | v | +-+ +-+ +++ |A+------> |B+------> |C| +-+ +++ +-+ ^ | | | +----------+ But firmware has even more complicated cycles like: +---------------------+ | | v | +-+ +---+ +++ +--+A+------>| B +-----> |C|<--+ | +-+ ++--+ +++ | | ^ | ^ | | | | | | | | | +---------+ +---------+ | | | +------------------------------+ And this is without including parent child dependencies or nodes in the cycle that are just firmware nodes that'll never have a struct device created for them. The proper way to treat these devices it to not force any probe ordering between them, while still enforce dependencies between node in the cycles (A, B and C) and their consumers. So this patch goes all out and just deals with all types of cycles. It does this by: 1. Following dependencies across device links, parent-child and fwnode links. 2. When it find cycles, it mark the device links and fwnode links as such instead of just deleting them or making the indistinguishable from proxy SYNC_STATE_ONLY device links. This way, when new nodes get added, we can immediately find and mark any new cycles whether the new node is a device or firmware node. Fixes: 2de9d8e ("driver core: fw_devlink: Improve handling of cyclic dependencies") Signed-off-by: Saravana Kannan <[email protected]> Tested-by: Colin Foster <[email protected]> Tested-by: Sudeep Holla <[email protected]> Tested-by: Douglas Anderson <[email protected]> Tested-by: Geert Uytterhoeven <[email protected]> Tested-by: Luca Weiss <[email protected]> # qcom/sm7225-fairphone-fp4 Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent cd115c0 commit 3fb1686

File tree

1 file changed

+129
-119
lines changed

1 file changed

+129
-119
lines changed

drivers/base/core.c

Lines changed: 129 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,47 +1866,6 @@ static void fw_devlink_unblock_consumers(struct device *dev)
18661866
device_links_write_unlock();
18671867
}
18681868

1869-
/**
1870-
* fw_devlink_relax_cycle - Convert cyclic links to SYNC_STATE_ONLY links
1871-
* @con: Device to check dependencies for.
1872-
* @sup: Device to check against.
1873-
*
1874-
* Check if @sup depends on @con or any device dependent on it (its child or
1875-
* its consumer etc). When such a cyclic dependency is found, convert all
1876-
* device links created solely by fw_devlink into SYNC_STATE_ONLY device links.
1877-
* This is the equivalent of doing fw_devlink=permissive just between the
1878-
* devices in the cycle. We need to do this because, at this point, fw_devlink
1879-
* can't tell which of these dependencies is not a real dependency.
1880-
*
1881-
* Return 1 if a cycle is found. Otherwise, return 0.
1882-
*/
1883-
static int fw_devlink_relax_cycle(struct device *con, void *sup)
1884-
{
1885-
struct device_link *link;
1886-
int ret;
1887-
1888-
if (con == sup)
1889-
return 1;
1890-
1891-
ret = device_for_each_child(con, sup, fw_devlink_relax_cycle);
1892-
if (ret)
1893-
return ret;
1894-
1895-
list_for_each_entry(link, &con->links.consumers, s_node) {
1896-
if (!(link->flags & DL_FLAG_CYCLE) &&
1897-
device_link_flag_is_sync_state_only(link->flags))
1898-
continue;
1899-
1900-
if (!fw_devlink_relax_cycle(link->consumer, sup))
1901-
continue;
1902-
1903-
ret = 1;
1904-
1905-
fw_devlink_relax_link(link);
1906-
link->flags |= DL_FLAG_CYCLE;
1907-
}
1908-
return ret;
1909-
}
19101869

19111870
static bool fwnode_init_without_drv(struct fwnode_handle *fwnode)
19121871
{
@@ -1937,6 +1896,111 @@ static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode)
19371896
return false;
19381897
}
19391898

1899+
/**
1900+
* __fw_devlink_relax_cycles - Relax and mark dependency cycles.
1901+
* @con: Potential consumer device.
1902+
* @sup_handle: Potential supplier's fwnode.
1903+
*
1904+
* Needs to be called with fwnode_lock and device link lock held.
1905+
*
1906+
* Check if @sup_handle or any of its ancestors or suppliers direct/indirectly
1907+
* depend on @con. This function can detect multiple cyles between @sup_handle
1908+
* and @con. When such dependency cycles are found, convert all device links
1909+
* created solely by fw_devlink into SYNC_STATE_ONLY device links. Also, mark
1910+
* all fwnode links in the cycle with FWLINK_FLAG_CYCLE so that when they are
1911+
* converted into a device link in the future, they are created as
1912+
* SYNC_STATE_ONLY device links. This is the equivalent of doing
1913+
* fw_devlink=permissive just between the devices in the cycle. We need to do
1914+
* this because, at this point, fw_devlink can't tell which of these
1915+
* dependencies is not a real dependency.
1916+
*
1917+
* Return true if one or more cycles were found. Otherwise, return false.
1918+
*/
1919+
static bool __fw_devlink_relax_cycles(struct device *con,
1920+
struct fwnode_handle *sup_handle)
1921+
{
1922+
struct device *sup_dev = NULL, *par_dev = NULL;
1923+
struct fwnode_link *link;
1924+
struct device_link *dev_link;
1925+
bool ret = false;
1926+
1927+
if (!sup_handle)
1928+
return false;
1929+
1930+
/*
1931+
* We aren't trying to find all cycles. Just a cycle between con and
1932+
* sup_handle.
1933+
*/
1934+
if (sup_handle->flags & FWNODE_FLAG_VISITED)
1935+
return false;
1936+
1937+
sup_handle->flags |= FWNODE_FLAG_VISITED;
1938+
1939+
sup_dev = get_dev_from_fwnode(sup_handle);
1940+
1941+
/* Termination condition. */
1942+
if (sup_dev == con) {
1943+
ret = true;
1944+
goto out;
1945+
}
1946+
1947+
/*
1948+
* If sup_dev is bound to a driver and @con hasn't started binding to a
1949+
* driver, sup_dev can't be a consumer of @con. So, no need to check
1950+
* further.
1951+
*/
1952+
if (sup_dev && sup_dev->links.status == DL_DEV_DRIVER_BOUND &&
1953+
con->links.status == DL_DEV_NO_DRIVER) {
1954+
ret = false;
1955+
goto out;
1956+
}
1957+
1958+
list_for_each_entry(link, &sup_handle->suppliers, c_hook) {
1959+
if (__fw_devlink_relax_cycles(con, link->supplier)) {
1960+
__fwnode_link_cycle(link);
1961+
ret = true;
1962+
}
1963+
}
1964+
1965+
/*
1966+
* Give priority to device parent over fwnode parent to account for any
1967+
* quirks in how fwnodes are converted to devices.
1968+
*/
1969+
if (sup_dev)
1970+
par_dev = get_device(sup_dev->parent);
1971+
else
1972+
par_dev = fwnode_get_next_parent_dev(sup_handle);
1973+
1974+
if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode))
1975+
ret = true;
1976+
1977+
if (!sup_dev)
1978+
goto out;
1979+
1980+
list_for_each_entry(dev_link, &sup_dev->links.suppliers, c_node) {
1981+
/*
1982+
* Ignore a SYNC_STATE_ONLY flag only if it wasn't marked as
1983+
* such due to a cycle.
1984+
*/
1985+
if (device_link_flag_is_sync_state_only(dev_link->flags) &&
1986+
!(dev_link->flags & DL_FLAG_CYCLE))
1987+
continue;
1988+
1989+
if (__fw_devlink_relax_cycles(con,
1990+
dev_link->supplier->fwnode)) {
1991+
fw_devlink_relax_link(dev_link);
1992+
dev_link->flags |= DL_FLAG_CYCLE;
1993+
ret = true;
1994+
}
1995+
}
1996+
1997+
out:
1998+
sup_handle->flags &= ~FWNODE_FLAG_VISITED;
1999+
put_device(sup_dev);
2000+
put_device(par_dev);
2001+
return ret;
2002+
}
2003+
19402004
/**
19412005
* fw_devlink_create_devlink - Create a device link from a consumer to fwnode
19422006
* @con: consumer device for the device link
@@ -1989,6 +2053,21 @@ static int fw_devlink_create_devlink(struct device *con,
19892053
fwnode_is_ancestor_of(sup_handle, con->fwnode))
19902054
return -EINVAL;
19912055

2056+
/*
2057+
* SYNC_STATE_ONLY device links don't block probing and supports cycles.
2058+
* So cycle detection isn't necessary and shouldn't be done.
2059+
*/
2060+
if (!(flags & DL_FLAG_SYNC_STATE_ONLY)) {
2061+
device_links_write_lock();
2062+
if (__fw_devlink_relax_cycles(con, sup_handle)) {
2063+
__fwnode_link_cycle(link);
2064+
flags = fw_devlink_get_flags(link->flags);
2065+
dev_info(con, "Fixed dependency cycle(s) with %pfwf\n",
2066+
sup_handle);
2067+
}
2068+
device_links_write_unlock();
2069+
}
2070+
19922071
if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
19932072
sup_dev = fwnode_get_next_parent_dev(sup_handle);
19942073
else
@@ -2002,23 +2081,16 @@ static int fw_devlink_create_devlink(struct device *con,
20022081
*/
20032082
if (sup_dev->links.status == DL_DEV_NO_DRIVER &&
20042083
sup_handle->flags & FWNODE_FLAG_INITIALIZED) {
2084+
dev_dbg(con,
2085+
"Not linking %pfwf - dev might never probe\n",
2086+
sup_handle);
20052087
ret = -EINVAL;
20062088
goto out;
20072089
}
20082090

2009-
/*
2010-
* If this fails, it is due to cycles in device links. Just
2011-
* give up on this link and treat it as invalid.
2012-
*/
2013-
if (!device_link_add(con, sup_dev, flags) &&
2014-
!(flags & DL_FLAG_SYNC_STATE_ONLY)) {
2015-
dev_info(con, "Fixing up cyclic dependency with %s\n",
2016-
dev_name(sup_dev));
2017-
device_links_write_lock();
2018-
fw_devlink_relax_cycle(con, sup_dev);
2019-
device_links_write_unlock();
2020-
device_link_add(con, sup_dev,
2021-
FW_DEVLINK_FLAGS_PERMISSIVE);
2091+
if (!device_link_add(con, sup_dev, flags)) {
2092+
dev_err(con, "Failed to create device link with %s\n",
2093+
dev_name(sup_dev));
20222094
ret = -EINVAL;
20232095
}
20242096

@@ -2031,49 +2103,12 @@ static int fw_devlink_create_devlink(struct device *con,
20312103
*/
20322104
if (fwnode_init_without_drv(sup_handle) ||
20332105
fwnode_ancestor_init_without_drv(sup_handle)) {
2034-
dev_dbg(con, "Not linking %pfwP - Might never probe\n",
2106+
dev_dbg(con, "Not linking %pfwf - might never become dev\n",
20352107
sup_handle);
20362108
return -EINVAL;
20372109
}
20382110

2039-
/*
2040-
* DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports
2041-
* cycles. So cycle detection isn't necessary and shouldn't be
2042-
* done.
2043-
*/
2044-
if (flags & DL_FLAG_SYNC_STATE_ONLY)
2045-
return -EAGAIN;
2046-
2047-
/*
2048-
* If we can't find the supplier device from its fwnode, it might be
2049-
* due to a cyclic dependency between fwnodes. Some of these cycles can
2050-
* be broken by applying logic. Check for these types of cycles and
2051-
* break them so that devices in the cycle probe properly.
2052-
*
2053-
* If the supplier's parent is dependent on the consumer, then the
2054-
* consumer and supplier have a cyclic dependency. Since fw_devlink
2055-
* can't tell which of the inferred dependencies are incorrect, don't
2056-
* enforce probe ordering between any of the devices in this cyclic
2057-
* dependency. Do this by relaxing all the fw_devlink device links in
2058-
* this cycle and by treating the fwnode link between the consumer and
2059-
* the supplier as an invalid dependency.
2060-
*/
2061-
sup_dev = fwnode_get_next_parent_dev(sup_handle);
2062-
if (sup_dev && device_is_dependent(con, sup_dev)) {
2063-
dev_info(con, "Fixing up cyclic dependency with %pfwP (%s)\n",
2064-
sup_handle, dev_name(sup_dev));
2065-
device_links_write_lock();
2066-
fw_devlink_relax_cycle(con, sup_dev);
2067-
device_links_write_unlock();
2068-
ret = -EINVAL;
2069-
} else {
2070-
/*
2071-
* Can't check for cycles or no cycles. So let's try
2072-
* again later.
2073-
*/
2074-
ret = -EAGAIN;
2075-
}
2076-
2111+
ret = -EAGAIN;
20772112
out:
20782113
put_device(sup_dev);
20792114
return ret;
@@ -2156,10 +2191,7 @@ static void __fw_devlink_link_to_consumers(struct device *dev)
21562191
*
21572192
* The function creates normal (non-SYNC_STATE_ONLY) device links between @dev
21582193
* and the real suppliers of @dev. Once these device links are created, the
2159-
* fwnode links are deleted. When such device links are successfully created,
2160-
* this function is called recursively on those supplier devices. This is
2161-
* needed to detect and break some invalid cycles in fwnode links. See
2162-
* fw_devlink_create_devlink() for more details.
2194+
* fwnode links are deleted.
21632195
*
21642196
* In addition, it also looks at all the suppliers of the entire fwnode tree
21652197
* because some of the child devices of @dev that have not been added yet
@@ -2180,35 +2212,13 @@ static void __fw_devlink_link_to_suppliers(struct device *dev,
21802212

21812213
list_for_each_entry_safe(link, tmp, &fwnode->suppliers, c_hook) {
21822214
int ret;
2183-
struct device *sup_dev;
21842215
struct fwnode_handle *sup = link->supplier;
21852216

21862217
ret = fw_devlink_create_devlink(dev, sup, link);
21872218
if (!own_link || ret == -EAGAIN)
21882219
continue;
21892220

21902221
__fwnode_link_del(link);
2191-
2192-
/* If no device link was created, nothing more to do. */
2193-
if (ret)
2194-
continue;
2195-
2196-
/*
2197-
* If a device link was successfully created to a supplier, we
2198-
* now need to try and link the supplier to all its suppliers.
2199-
*
2200-
* This is needed to detect and delete false dependencies in
2201-
* fwnode links that haven't been converted to a device link
2202-
* yet. See comments in fw_devlink_create_devlink() for more
2203-
* details on the false dependency.
2204-
*
2205-
* Without deleting these false dependencies, some devices will
2206-
* never probe because they'll keep waiting for their false
2207-
* dependency fwnode links to be converted to device links.
2208-
*/
2209-
sup_dev = get_dev_from_fwnode(sup);
2210-
__fw_devlink_link_to_suppliers(sup_dev, sup_dev->fwnode);
2211-
put_device(sup_dev);
22122222
}
22132223

22142224
/*

0 commit comments

Comments
 (0)