patch "driver core: Call sync_state() even if supplier has no consumers" added to driver-core-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
driver core: Call sync_state() even if supplier has no consumers
to my driver-core git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
in the driver-core-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 21eb93f432b1a785df193df1a56a59e9eb3a985f Mon Sep 17 00:00:00 2001
From: Saravana Kannan <[email protected]>
Date: Fri, 21 Feb 2020 00:05:08 -0800
Subject: driver core: Call sync_state() even if supplier has no consumers
The initial patch that added sync_state() support didn't handle the case where a supplier has no consumers. This was because when a device is successfully bound with a driver, only its suppliers were checked to see if they are eligible to get a sync_state(). This is not sufficient for devices that have no consumers but still need to do device state clean up. So fix this.
--- drivers/base/core.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
drivers/base/core.c +17 -6
@@ -745,25 +745,31 @@ static void __device_links_queue_sync_state(struct device *dev,/** * device_links_flush_sync_list - Call sync_state() on a list of devices * @list: List of devices to call sync_state() on +* @dont_lock_dev: Device for which lock is already held by the caller * * Calls sync_state() on all the devices that have been queued for it. This -* function is used in conjunction with __device_links_queue_sync_state(). +* function is used in conjunction with __device_links_queue_sync_state(). The +* @dont_lock_dev parameter is useful when this function is called from a +* context where a device lock is already held. */ -static void device_links_flush_sync_list (struct list_head *list) +static void device_links_flush_sync_list (struct list_head *list, +struct device *dont_lock_dev) {struct device *dev, *tmp;list_for_each_entry_safe (dev, tmp, list, links.defer_sync) {list_del_init (&dev->links.defer_sync); -device_lock (dev); +if (dev != dont_lock_dev) +device_lock (dev);if (dev->bus->sync_state) dev->bus->sync_state (dev);else if (dev->driver && dev->driver->sync_state) dev->driver->sync_state (dev); -device_unlock (dev); +if (dev != dont_lock_dev) +device_unlock (dev);put_device (dev); }
@@ -801,7 +807,7 @@ void device_links_supplier_sync_state_resume(void) out:device_links_write_unlock (); -device_links_flush_sync_list (&sync_list); +device_links_flush_sync_list (&sync_list,NULL ); }static int sync_state_resume_initcall (void )
@@ -865,6 +871,11 @@ void device_links_driver_bound(struct device *dev)driver_deferred_probe_add (link->consumer); } +if (defer_sync_state_count) +__device_links_supplier_defer_sync (dev); +else +__device_links_queue_sync_state (dev, &sync_list); +list_for_each_entry (link, &dev->links.suppliers, c_node) {if (!(link->flags &DL_FLAG_MANAGED ))continue ;
@@ -883,7 +894,7 @@ void device_links_driver_bound(struct device *dev)device_links_write_unlock (); -device_links_flush_sync_list (&sync_list); +device_links_flush_sync_list (&sync_list, dev); }static void device_link_drop_managed (struct device_link *link)
Signature · 1 line
2.25.1