Driver core fixes for 5.7-rc7 - take 2
So, turns out the kobject fix didn't quite work, so here are 4 patches that in the end, result in just 2 driver core fixes for reported issues that no one has had problems with. The kobject patch that was originally in here has now been reverted, as Guenter reported boot problems with it on some of his systems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXsk+SQ8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykByQCg1sVoMoeC2hidsp635K3Id6q3GIUAn3h+wSDh E2LNBDvSCo40J8LA/5UX =ZZsF -----END PGP SIGNATURE----- Merge tag 'driver-core-5.7-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core Pull driver core fixes from Greg KH: "So, turns out the kobject fix didn't quite work, so here are four patches that in the end, result in just two driver core fixes for reported issues that no one has had problems with. The kobject patch that was originally in here has now been reverted, as Guenter reported boot problems with it on some of his systems" * tag 'driver-core-5.7-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: Revert "kobject: Make sure the parent does not get released before its children" kobject: Make sure the parent does not get released before its children driver core: Fix handling of SYNC_STATE_ONLY + STATELESS device links driver core: Fix SYNC_STATE_ONLY device link implementation
This commit is contained in:
commit
23f0dac848
|
@ -365,6 +365,7 @@ struct device_link *device_link_add(struct device *consumer,
|
||||||
link->flags |= DL_FLAG_STATELESS;
|
link->flags |= DL_FLAG_STATELESS;
|
||||||
goto reorder;
|
goto reorder;
|
||||||
} else {
|
} else {
|
||||||
|
link->flags |= DL_FLAG_STATELESS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,12 +434,16 @@ struct device_link *device_link_add(struct device *consumer,
|
||||||
flags & DL_FLAG_PM_RUNTIME)
|
flags & DL_FLAG_PM_RUNTIME)
|
||||||
pm_runtime_resume(supplier);
|
pm_runtime_resume(supplier);
|
||||||
|
|
||||||
|
list_add_tail_rcu(&link->s_node, &supplier->links.consumers);
|
||||||
|
list_add_tail_rcu(&link->c_node, &consumer->links.suppliers);
|
||||||
|
|
||||||
if (flags & DL_FLAG_SYNC_STATE_ONLY) {
|
if (flags & DL_FLAG_SYNC_STATE_ONLY) {
|
||||||
dev_dbg(consumer,
|
dev_dbg(consumer,
|
||||||
"Linked as a sync state only consumer to %s\n",
|
"Linked as a sync state only consumer to %s\n",
|
||||||
dev_name(supplier));
|
dev_name(supplier));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
reorder:
|
reorder:
|
||||||
/*
|
/*
|
||||||
* Move the consumer and all of the devices depending on it to the end
|
* Move the consumer and all of the devices depending on it to the end
|
||||||
|
@ -449,12 +454,9 @@ reorder:
|
||||||
*/
|
*/
|
||||||
device_reorder_to_tail(consumer, NULL);
|
device_reorder_to_tail(consumer, NULL);
|
||||||
|
|
||||||
list_add_tail_rcu(&link->s_node, &supplier->links.consumers);
|
|
||||||
list_add_tail_rcu(&link->c_node, &consumer->links.suppliers);
|
|
||||||
|
|
||||||
dev_dbg(consumer, "Linked as a consumer to %s\n", dev_name(supplier));
|
dev_dbg(consumer, "Linked as a consumer to %s\n", dev_name(supplier));
|
||||||
|
|
||||||
out:
|
out:
|
||||||
device_pm_unlock();
|
device_pm_unlock();
|
||||||
device_links_write_unlock();
|
device_links_write_unlock();
|
||||||
|
|
||||||
|
@ -829,6 +831,13 @@ static void __device_links_supplier_defer_sync(struct device *sup)
|
||||||
list_add_tail(&sup->links.defer_sync, &deferred_sync);
|
list_add_tail(&sup->links.defer_sync, &deferred_sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void device_link_drop_managed(struct device_link *link)
|
||||||
|
{
|
||||||
|
link->flags &= ~DL_FLAG_MANAGED;
|
||||||
|
WRITE_ONCE(link->status, DL_STATE_NONE);
|
||||||
|
kref_put(&link->kref, __device_link_del);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_links_driver_bound - Update device links after probing its driver.
|
* device_links_driver_bound - Update device links after probing its driver.
|
||||||
* @dev: Device to update the links for.
|
* @dev: Device to update the links for.
|
||||||
|
@ -842,7 +851,7 @@ static void __device_links_supplier_defer_sync(struct device *sup)
|
||||||
*/
|
*/
|
||||||
void device_links_driver_bound(struct device *dev)
|
void device_links_driver_bound(struct device *dev)
|
||||||
{
|
{
|
||||||
struct device_link *link;
|
struct device_link *link, *ln;
|
||||||
LIST_HEAD(sync_list);
|
LIST_HEAD(sync_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -882,18 +891,35 @@ void device_links_driver_bound(struct device *dev)
|
||||||
else
|
else
|
||||||
__device_links_queue_sync_state(dev, &sync_list);
|
__device_links_queue_sync_state(dev, &sync_list);
|
||||||
|
|
||||||
list_for_each_entry(link, &dev->links.suppliers, c_node) {
|
list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
|
||||||
|
struct device *supplier;
|
||||||
|
|
||||||
if (!(link->flags & DL_FLAG_MANAGED))
|
if (!(link->flags & DL_FLAG_MANAGED))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
WARN_ON(link->status != DL_STATE_CONSUMER_PROBE);
|
supplier = link->supplier;
|
||||||
WRITE_ONCE(link->status, DL_STATE_ACTIVE);
|
if (link->flags & DL_FLAG_SYNC_STATE_ONLY) {
|
||||||
|
/*
|
||||||
|
* When DL_FLAG_SYNC_STATE_ONLY is set, it means no
|
||||||
|
* other DL_MANAGED_LINK_FLAGS have been set. So, it's
|
||||||
|
* save to drop the managed link completely.
|
||||||
|
*/
|
||||||
|
device_link_drop_managed(link);
|
||||||
|
} else {
|
||||||
|
WARN_ON(link->status != DL_STATE_CONSUMER_PROBE);
|
||||||
|
WRITE_ONCE(link->status, DL_STATE_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This needs to be done even for the deleted
|
||||||
|
* DL_FLAG_SYNC_STATE_ONLY device link in case it was the last
|
||||||
|
* device link that was preventing the supplier from getting a
|
||||||
|
* sync_state() call.
|
||||||
|
*/
|
||||||
if (defer_sync_state_count)
|
if (defer_sync_state_count)
|
||||||
__device_links_supplier_defer_sync(link->supplier);
|
__device_links_supplier_defer_sync(supplier);
|
||||||
else
|
else
|
||||||
__device_links_queue_sync_state(link->supplier,
|
__device_links_queue_sync_state(supplier, &sync_list);
|
||||||
&sync_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->links.status = DL_DEV_DRIVER_BOUND;
|
dev->links.status = DL_DEV_DRIVER_BOUND;
|
||||||
|
@ -903,13 +929,6 @@ void device_links_driver_bound(struct device *dev)
|
||||||
device_links_flush_sync_list(&sync_list, dev);
|
device_links_flush_sync_list(&sync_list, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_link_drop_managed(struct device_link *link)
|
|
||||||
{
|
|
||||||
link->flags &= ~DL_FLAG_MANAGED;
|
|
||||||
WRITE_ONCE(link->status, DL_STATE_NONE);
|
|
||||||
kref_put(&link->kref, __device_link_del);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __device_links_no_driver - Update links of a device without a driver.
|
* __device_links_no_driver - Update links of a device without a driver.
|
||||||
* @dev: Device without a drvier.
|
* @dev: Device without a drvier.
|
||||||
|
|
Loading…
Reference in New Issue