Skip to content

Commit f9aa460

Browse files
Saravana Kannangregkh
authored andcommitted
driver core: Refactor fw_devlink feature
The current implementation of fw_devlink is very inefficient because it tries to get away without creating fwnode links in the name of saving memory usage. Past attempts to optimize runtime at the cost of memory usage were blocked with request for data showing that the optimization made significant improvement for real world scenarios. We have those scenarios now. There have been several reports of boot time increase in the order of seconds in this thread [1]. Several OEMs and SoC manufacturers have also privately reported significant (350-400ms) increase in boot time due to all the parsing done by fw_devlink. So this patch uses all the setup done by the previous patches in this series to refactor fw_devlink to be more efficient. Most of the code has been moved out of firmware specific (DT mostly) code into driver core. This brings the following benefits: - Instead of parsing the device tree multiple times during bootup, fw_devlink parses each fwnode node/property only once and creates fwnode links. The rest of the fw_devlink code then just looks at these fwnode links to do rest of the work. - Makes it much easier to debug probe issue due to fw_devlink in the future. fw_devlink=on blocks the probing of devices if they depend on a device that hasn't been added yet. With this refactor, it'll be very easy to tell what that device is because we now have a reference to the fwnode of the device. - Much easier to add fw_devlink support to ACPI and other firmware types. A refactor to move the common bits from DT specific code to driver core was in my TODO list as a prerequisite to adding ACPI support to fw_devlink. This series gets that done. [1] - https://lore.kernel.org/linux-omap/[email protected]/ Tested-by: Laurent Pinchart <[email protected]> Tested-by: Grygorii Strashko <[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 e82a840 commit f9aa460

File tree

2 files changed

+238
-92
lines changed

2 files changed

+238
-92
lines changed

drivers/base/core.c

Lines changed: 238 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ early_param("sysfs.deprecated", sysfs_deprecated_setup);
4646
#endif
4747

4848
/* Device links support. */
49-
static LIST_HEAD(wait_for_suppliers);
50-
static DEFINE_MUTEX(wfs_lock);
5149
static LIST_HEAD(deferred_sync);
5250
static unsigned int defer_sync_state_count = 1;
5351
static DEFINE_MUTEX(fwnode_link_lock);
@@ -803,74 +801,6 @@ struct device_link *device_link_add(struct device *consumer,
803801
}
804802
EXPORT_SYMBOL_GPL(device_link_add);
805803

806-
/**
807-
* device_link_wait_for_supplier - Add device to wait_for_suppliers list
808-
* @consumer: Consumer device
809-
*
810-
* Marks the @consumer device as waiting for suppliers to become available by
811-
* adding it to the wait_for_suppliers list. The consumer device will never be
812-
* probed until it's removed from the wait_for_suppliers list.
813-
*
814-
* The caller is responsible for adding the links to the supplier devices once
815-
* they are available and removing the @consumer device from the
816-
* wait_for_suppliers list once links to all the suppliers have been created.
817-
*
818-
* This function is NOT meant to be called from the probe function of the
819-
* consumer but rather from code that creates/adds the consumer device.
820-
*/
821-
static void device_link_wait_for_supplier(struct device *consumer,
822-
bool need_for_probe)
823-
{
824-
mutex_lock(&wfs_lock);
825-
list_add_tail(&consumer->links.needs_suppliers, &wait_for_suppliers);
826-
consumer->links.need_for_probe = need_for_probe;
827-
mutex_unlock(&wfs_lock);
828-
}
829-
830-
static void device_link_wait_for_mandatory_supplier(struct device *consumer)
831-
{
832-
device_link_wait_for_supplier(consumer, true);
833-
}
834-
835-
static void device_link_wait_for_optional_supplier(struct device *consumer)
836-
{
837-
device_link_wait_for_supplier(consumer, false);
838-
}
839-
840-
/**
841-
* device_link_add_missing_supplier_links - Add links from consumer devices to
842-
* supplier devices, leaving any
843-
* consumer with inactive suppliers on
844-
* the wait_for_suppliers list
845-
*
846-
* Loops through all consumers waiting on suppliers and tries to add all their
847-
* supplier links. If that succeeds, the consumer device is removed from
848-
* wait_for_suppliers list. Otherwise, they are left in the wait_for_suppliers
849-
* list. Devices left on the wait_for_suppliers list will not be probed.
850-
*
851-
* The fwnode add_links callback is expected to return 0 if it has found and
852-
* added all the supplier links for the consumer device. It should return an
853-
* error if it isn't able to do so.
854-
*
855-
* The caller of device_link_wait_for_supplier() is expected to call this once
856-
* it's aware of potential suppliers becoming available.
857-
*/
858-
static void device_link_add_missing_supplier_links(void)
859-
{
860-
struct device *dev, *tmp;
861-
862-
mutex_lock(&wfs_lock);
863-
list_for_each_entry_safe(dev, tmp, &wait_for_suppliers,
864-
links.needs_suppliers) {
865-
int ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
866-
if (!ret)
867-
list_del_init(&dev->links.needs_suppliers);
868-
else if (ret != -ENODEV)
869-
dev->links.need_for_probe = false;
870-
}
871-
mutex_unlock(&wfs_lock);
872-
}
873-
874804
#ifdef CONFIG_SRCU
875805
static void __device_link_del(struct kref *kref)
876806
{
@@ -1195,9 +1125,8 @@ void device_links_driver_bound(struct device *dev)
11951125
* the device links it needs to or make new device links as it needs
11961126
* them. So, it no longer needs to wait on any suppliers.
11971127
*/
1198-
mutex_lock(&wfs_lock);
1199-
list_del_init(&dev->links.needs_suppliers);
1200-
mutex_unlock(&wfs_lock);
1128+
if (dev->fwnode && dev->fwnode->dev == dev)
1129+
fwnode_links_purge_suppliers(dev->fwnode);
12011130
device_remove_file(dev, &dev_attr_waiting_for_supplier);
12021131

12031132
device_links_write_lock();
@@ -1488,10 +1417,6 @@ static void device_links_purge(struct device *dev)
14881417
if (dev->class == &devlink_class)
14891418
return;
14901419

1491-
mutex_lock(&wfs_lock);
1492-
list_del_init(&dev->links.needs_suppliers);
1493-
mutex_unlock(&wfs_lock);
1494-
14951420
/*
14961421
* Delete all of the remaining links from this device to any other
14971422
* devices (either consumers or suppliers).
@@ -1561,19 +1486,246 @@ static void fw_devlink_parse_fwtree(struct fwnode_handle *fwnode)
15611486
fw_devlink_parse_fwtree(child);
15621487
}
15631488

1564-
static void fw_devlink_link_device(struct device *dev)
1489+
/**
1490+
* fw_devlink_create_devlink - Create a device link from a consumer to fwnode
1491+
* @con - Consumer device for the device link
1492+
* @sup_handle - fwnode handle of supplier
1493+
*
1494+
* This function will try to create a device link between the consumer device
1495+
* @con and the supplier device represented by @sup_handle.
1496+
*
1497+
* The supplier has to be provided as a fwnode because incorrect cycles in
1498+
* fwnode links can sometimes cause the supplier device to never be created.
1499+
* This function detects such cases and returns an error if it cannot create a
1500+
* device link from the consumer to a missing supplier.
1501+
*
1502+
* Returns,
1503+
* 0 on successfully creating a device link
1504+
* -EINVAL if the device link cannot be created as expected
1505+
* -EAGAIN if the device link cannot be created right now, but it may be
1506+
* possible to do that in the future
1507+
*/
1508+
static int fw_devlink_create_devlink(struct device *con,
1509+
struct fwnode_handle *sup_handle, u32 flags)
1510+
{
1511+
struct device *sup_dev;
1512+
int ret = 0;
1513+
1514+
sup_dev = get_dev_from_fwnode(sup_handle);
1515+
if (sup_dev) {
1516+
/*
1517+
* If this fails, it is due to cycles in device links. Just
1518+
* give up on this link and treat it as invalid.
1519+
*/
1520+
if (!device_link_add(con, sup_dev, flags))
1521+
ret = -EINVAL;
1522+
1523+
goto out;
1524+
}
1525+
1526+
/*
1527+
* DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports
1528+
* cycles. So cycle detection isn't necessary and shouldn't be
1529+
* done.
1530+
*/
1531+
if (flags & DL_FLAG_SYNC_STATE_ONLY)
1532+
return -EAGAIN;
1533+
1534+
/*
1535+
* If we can't find the supplier device from its fwnode, it might be
1536+
* due to a cyclic dependency between fwnodes. Some of these cycles can
1537+
* be broken by applying logic. Check for these types of cycles and
1538+
* break them so that devices in the cycle probe properly.
1539+
*
1540+
* If the supplier's parent is dependent on the consumer, then
1541+
* the consumer-supplier dependency is a false dependency. So,
1542+
* treat it as an invalid link.
1543+
*/
1544+
sup_dev = fwnode_get_next_parent_dev(sup_handle);
1545+
if (sup_dev && device_is_dependent(con, sup_dev)) {
1546+
dev_dbg(con, "Not linking to %pfwP - False link\n",
1547+
sup_handle);
1548+
ret = -EINVAL;
1549+
} else {
1550+
/*
1551+
* Can't check for cycles or no cycles. So let's try
1552+
* again later.
1553+
*/
1554+
ret = -EAGAIN;
1555+
}
1556+
1557+
out:
1558+
put_device(sup_dev);
1559+
return ret;
1560+
}
1561+
1562+
/**
1563+
* __fw_devlink_link_to_consumers - Create device links to consumers of a device
1564+
* @dev - Device that needs to be linked to its consumers
1565+
*
1566+
* This function looks at all the consumer fwnodes of @dev and creates device
1567+
* links between the consumer device and @dev (supplier).
1568+
*
1569+
* If the consumer device has not been added yet, then this function creates a
1570+
* SYNC_STATE_ONLY link between @dev (supplier) and the closest ancestor device
1571+
* of the consumer fwnode. This is necessary to make sure @dev doesn't get a
1572+
* sync_state() callback before the real consumer device gets to be added and
1573+
* then probed.
1574+
*
1575+
* Once device links are created from the real consumer to @dev (supplier), the
1576+
* fwnode links are deleted.
1577+
*/
1578+
static void __fw_devlink_link_to_consumers(struct device *dev)
1579+
{
1580+
struct fwnode_handle *fwnode = dev->fwnode;
1581+
struct fwnode_link *link, *tmp;
1582+
1583+
list_for_each_entry_safe(link, tmp, &fwnode->consumers, s_hook) {
1584+
u32 dl_flags = fw_devlink_get_flags();
1585+
struct device *con_dev;
1586+
bool own_link = true;
1587+
int ret;
1588+
1589+
con_dev = get_dev_from_fwnode(link->consumer);
1590+
/*
1591+
* If consumer device is not available yet, make a "proxy"
1592+
* SYNC_STATE_ONLY link from the consumer's parent device to
1593+
* the supplier device. This is necessary to make sure the
1594+
* supplier doesn't get a sync_state() callback before the real
1595+
* consumer can create a device link to the supplier.
1596+
*
1597+
* This proxy link step is needed to handle the case where the
1598+
* consumer's parent device is added before the supplier.
1599+
*/
1600+
if (!con_dev) {
1601+
con_dev = fwnode_get_next_parent_dev(link->consumer);
1602+
/*
1603+
* However, if the consumer's parent device is also the
1604+
* parent of the supplier, don't create a
1605+
* consumer-supplier link from the parent to its child
1606+
* device. Such a dependency is impossible.
1607+
*/
1608+
if (con_dev &&
1609+
fwnode_is_ancestor_of(con_dev->fwnode, fwnode)) {
1610+
put_device(con_dev);
1611+
con_dev = NULL;
1612+
} else {
1613+
own_link = false;
1614+
dl_flags = DL_FLAG_SYNC_STATE_ONLY;
1615+
}
1616+
}
1617+
1618+
if (!con_dev)
1619+
continue;
1620+
1621+
ret = fw_devlink_create_devlink(con_dev, fwnode, dl_flags);
1622+
put_device(con_dev);
1623+
if (!own_link || ret == -EAGAIN)
1624+
continue;
1625+
1626+
list_del(&link->s_hook);
1627+
list_del(&link->c_hook);
1628+
kfree(link);
1629+
}
1630+
}
1631+
1632+
/**
1633+
* __fw_devlink_link_to_suppliers - Create device links to suppliers of a device
1634+
* @dev - The consumer device that needs to be linked to its suppliers
1635+
* @fwnode - Root of the fwnode tree that is used to create device links
1636+
*
1637+
* This function looks at all the supplier fwnodes of fwnode tree rooted at
1638+
* @fwnode and creates device links between @dev (consumer) and all the
1639+
* supplier devices of the entire fwnode tree at @fwnode.
1640+
*
1641+
* The function creates normal (non-SYNC_STATE_ONLY) device links between @dev
1642+
* and the real suppliers of @dev. Once these device links are created, the
1643+
* fwnode links are deleted. When such device links are successfully created,
1644+
* this function is called recursively on those supplier devices. This is
1645+
* needed to detect and break some invalid cycles in fwnode links. See
1646+
* fw_devlink_create_devlink() for more details.
1647+
*
1648+
* In addition, it also looks at all the suppliers of the entire fwnode tree
1649+
* because some of the child devices of @dev that have not been added yet
1650+
* (because @dev hasn't probed) might already have their suppliers added to
1651+
* driver core. So, this function creates SYNC_STATE_ONLY device links between
1652+
* @dev (consumer) and these suppliers to make sure they don't execute their
1653+
* sync_state() callbacks before these child devices have a chance to create
1654+
* their device links. The fwnode links that correspond to the child devices
1655+
* aren't delete because they are needed later to create the device links
1656+
* between the real consumer and supplier devices.
1657+
*/
1658+
static void __fw_devlink_link_to_suppliers(struct device *dev,
1659+
struct fwnode_handle *fwnode)
15651660
{
1566-
int fw_ret;
1661+
bool own_link = (dev->fwnode == fwnode);
1662+
struct fwnode_link *link, *tmp;
1663+
struct fwnode_handle *child = NULL;
1664+
u32 dl_flags;
1665+
1666+
if (own_link)
1667+
dl_flags = fw_devlink_get_flags();
1668+
else
1669+
dl_flags = DL_FLAG_SYNC_STATE_ONLY;
15671670

1568-
device_link_add_missing_supplier_links();
1671+
list_for_each_entry_safe(link, tmp, &fwnode->suppliers, c_hook) {
1672+
int ret;
1673+
struct device *sup_dev;
1674+
struct fwnode_handle *sup = link->supplier;
1675+
1676+
ret = fw_devlink_create_devlink(dev, sup, dl_flags);
1677+
if (!own_link || ret == -EAGAIN)
1678+
continue;
15691679

1570-
if (fw_devlink_flags && fwnode_has_op(dev->fwnode, add_links)) {
1571-
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
1572-
if (fw_ret == -ENODEV && !fw_devlink_is_permissive())
1573-
device_link_wait_for_mandatory_supplier(dev);
1574-
else if (fw_ret)
1575-
device_link_wait_for_optional_supplier(dev);
1680+
list_del(&link->s_hook);
1681+
list_del(&link->c_hook);
1682+
kfree(link);
1683+
1684+
/* If no device link was created, nothing more to do. */
1685+
if (ret)
1686+
continue;
1687+
1688+
/*
1689+
* If a device link was successfully created to a supplier, we
1690+
* now need to try and link the supplier to all its suppliers.
1691+
*
1692+
* This is needed to detect and delete false dependencies in
1693+
* fwnode links that haven't been converted to a device link
1694+
* yet. See comments in fw_devlink_create_devlink() for more
1695+
* details on the false dependency.
1696+
*
1697+
* Without deleting these false dependencies, some devices will
1698+
* never probe because they'll keep waiting for their false
1699+
* dependency fwnode links to be converted to device links.
1700+
*/
1701+
sup_dev = get_dev_from_fwnode(sup);
1702+
__fw_devlink_link_to_suppliers(sup_dev, sup_dev->fwnode);
1703+
put_device(sup_dev);
15761704
}
1705+
1706+
/*
1707+
* Make "proxy" SYNC_STATE_ONLY device links to represent the needs of
1708+
* all the descendants. This proxy link step is needed to handle the
1709+
* case where the supplier is added before the consumer's parent device
1710+
* (@dev).
1711+
*/
1712+
while ((child = fwnode_get_next_available_child_node(fwnode, child)))
1713+
__fw_devlink_link_to_suppliers(dev, child);
1714+
}
1715+
1716+
static void fw_devlink_link_device(struct device *dev)
1717+
{
1718+
struct fwnode_handle *fwnode = dev->fwnode;
1719+
1720+
if (!fw_devlink_flags)
1721+
return;
1722+
1723+
fw_devlink_parse_fwtree(fwnode);
1724+
1725+
mutex_lock(&fwnode_link_lock);
1726+
__fw_devlink_link_to_consumers(dev);
1727+
__fw_devlink_link_to_suppliers(dev, fwnode);
1728+
mutex_unlock(&fwnode_link_lock);
15771729
}
15781730

15791731
/* Device links support end. */
@@ -2431,7 +2583,6 @@ void device_initialize(struct device *dev)
24312583
#endif
24322584
INIT_LIST_HEAD(&dev->links.consumers);
24332585
INIT_LIST_HEAD(&dev->links.suppliers);
2434-
INIT_LIST_HEAD(&dev->links.needs_suppliers);
24352586
INIT_LIST_HEAD(&dev->links.defer_sync);
24362587
dev->links.status = DL_DEV_NO_DRIVER;
24372588
}

include/linux/device.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,18 +351,13 @@ enum dl_dev_state {
351351
* struct dev_links_info - Device data related to device links.
352352
* @suppliers: List of links to supplier devices.
353353
* @consumers: List of links to consumer devices.
354-
* @needs_suppliers: Hook to global list of devices waiting for suppliers.
355354
* @defer_sync: Hook to global list of devices that have deferred sync_state.
356-
* @need_for_probe: If needs_suppliers is on a list, this indicates if the
357-
* suppliers are needed for probe or not.
358355
* @status: Driver status information.
359356
*/
360357
struct dev_links_info {
361358
struct list_head suppliers;
362359
struct list_head consumers;
363-
struct list_head needs_suppliers;
364360
struct list_head defer_sync;
365-
bool need_for_probe;
366361
enum dl_dev_state status;
367362
};
368363

0 commit comments

Comments
 (0)