From: Greg Kroah-Hartman Date: Thu, 19 Mar 2020 07:37:49 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v4.4.217~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=32d7f923a74d7dbc5d31902b6982c2004a451b57;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: driver-core-add-device-link-flag-dl_flag_autoprobe_consumer.patch driver-core-fix-adding-device-links-to-probing-suppliers.patch driver-core-fix-creation-of-device-links-with-pm-runtime-flags.patch driver-core-make-driver-core-own-stateful-device-links.patch driver-core-remove-device-link-creation-limitation.patch driver-core-remove-the-link-if-there-is-no-driver-with-auto-flag.patch --- diff --git a/queue-4.19/driver-core-add-device-link-flag-dl_flag_autoprobe_consumer.patch b/queue-4.19/driver-core-add-device-link-flag-dl_flag_autoprobe_consumer.patch new file mode 100644 index 00000000000..d24e92444a6 --- /dev/null +++ b/queue-4.19/driver-core-add-device-link-flag-dl_flag_autoprobe_consumer.patch @@ -0,0 +1,122 @@ +From e7dd40105aac9ba051e44ad711123bc53a5e4c71 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Fri, 1 Feb 2019 01:59:42 +0100 +Subject: driver core: Add device link flag DL_FLAG_AUTOPROBE_CONSUMER + +From: Rafael J. Wysocki + +commit e7dd40105aac9ba051e44ad711123bc53a5e4c71 upstream. + +Add a new device link flag, DL_FLAG_AUTOPROBE_CONSUMER, to request the +driver core to probe for a consumer driver automatically after binding +a driver to the supplier device on a persistent managed device link. + +As unbinding the supplier driver on a managed device link causes the +consumer driver to be detached from its device automatically, this +flag provides a complementary mechanism which is needed to address +some "composite device" use cases. + +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Saravana Kannan +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/driver-api/device_link.rst | 9 +++++++++ + drivers/base/core.c | 16 +++++++++++++++- + drivers/base/dd.c | 2 +- + include/linux/device.h | 3 +++ + 4 files changed, 28 insertions(+), 2 deletions(-) + +--- a/Documentation/driver-api/device_link.rst ++++ b/Documentation/driver-api/device_link.rst +@@ -94,6 +94,15 @@ Similarly, when the device link is added + ``DL_FLAG_AUTOREMOVE_SUPPLIER`` causes the device link to be automatically + purged when the supplier fails to probe or later unbinds. + ++If neither ``DL_FLAG_AUTOREMOVE_CONSUMER`` nor ``DL_FLAG_AUTOREMOVE_SUPPLIER`` ++is set, ``DL_FLAG_AUTOPROBE_CONSUMER`` can be used to request the driver core ++to probe for a driver for the consumer driver on the link automatically after ++a driver has been bound to the supplier device. ++ ++Note, however, that any combinations of ``DL_FLAG_AUTOREMOVE_CONSUMER``, ++``DL_FLAG_AUTOREMOVE_SUPPLIER`` or ``DL_FLAG_AUTOPROBE_CONSUMER`` with ++``DL_FLAG_STATELESS`` are invalid and cannot be used. ++ + Limitations + =========== + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -195,6 +195,12 @@ void device_pm_move_to_tail(struct devic + * the link will be maintained until one of the devices pointed to by it (either + * the consumer or the supplier) is unregistered. + * ++ * Also, if DL_FLAG_STATELESS, DL_FLAG_AUTOREMOVE_CONSUMER and ++ * DL_FLAG_AUTOREMOVE_SUPPLIER are not set in @flags (that is, a persistent ++ * managed device link is being added), the DL_FLAG_AUTOPROBE_CONSUMER flag can ++ * be used to request the driver core to automaticall probe for a consmer ++ * driver after successfully binding a driver to the supplier device. ++ * + * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER + * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and + * will cause NULL to be returned upfront. +@@ -215,7 +221,12 @@ struct device_link *device_link_add(stru + + if (!consumer || !supplier || + (flags & DL_FLAG_STATELESS && +- flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER))) ++ flags & (DL_FLAG_AUTOREMOVE_CONSUMER | ++ DL_FLAG_AUTOREMOVE_SUPPLIER | ++ DL_FLAG_AUTOPROBE_CONSUMER)) || ++ (flags & DL_FLAG_AUTOPROBE_CONSUMER && ++ flags & (DL_FLAG_AUTOREMOVE_CONSUMER | ++ DL_FLAG_AUTOREMOVE_SUPPLIER))) + return NULL; + + if (flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) { +@@ -576,6 +587,9 @@ void device_links_driver_bound(struct de + + WARN_ON(link->status != DL_STATE_DORMANT); + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); ++ ++ if (link->flags & DL_FLAG_AUTOPROBE_CONSUMER) ++ driver_deferred_probe_add(link->consumer); + } + + list_for_each_entry(link, &dev->links.suppliers, c_node) { +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -116,7 +116,7 @@ static void deferred_probe_work_func(str + } + static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func); + +-static void driver_deferred_probe_add(struct device *dev) ++void driver_deferred_probe_add(struct device *dev) + { + mutex_lock(&deferred_probe_mutex); + if (list_empty(&dev->p->deferred_probe)) { +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -339,6 +339,7 @@ struct device *driver_find_device(struct + struct device *start, void *data, + int (*match)(struct device *dev, void *data)); + ++void driver_deferred_probe_add(struct device *dev); + int driver_deferred_probe_check_state(struct device *dev); + + /** +@@ -824,12 +825,14 @@ enum device_link_state { + * PM_RUNTIME: If set, the runtime PM framework will use this link. + * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation. + * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind. ++ * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds. + */ + #define DL_FLAG_STATELESS BIT(0) + #define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1) + #define DL_FLAG_PM_RUNTIME BIT(2) + #define DL_FLAG_RPM_ACTIVE BIT(3) + #define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4) ++#define DL_FLAG_AUTOPROBE_CONSUMER BIT(5) + + /** + * struct device_link - Device link representation. diff --git a/queue-4.19/driver-core-fix-adding-device-links-to-probing-suppliers.patch b/queue-4.19/driver-core-fix-adding-device-links-to-probing-suppliers.patch new file mode 100644 index 00000000000..c9e904d2acc --- /dev/null +++ b/queue-4.19/driver-core-fix-adding-device-links-to-probing-suppliers.patch @@ -0,0 +1,197 @@ +From 15cfb094160385cc0b303c4cda483caa102af654 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Fri, 1 Feb 2019 01:50:39 +0100 +Subject: driver core: Fix adding device links to probing suppliers + +From: Rafael J. Wysocki + +commit 15cfb094160385cc0b303c4cda483caa102af654 upstream. + +Currently, it is not valid to add a device link from a consumer +driver ->probe callback to a supplier that is still probing too, but +generally this is a valid use case. For example, if the consumer has +just acquired a resource that can only be available if the supplier +is functional, adding a device link to that supplier right away +should be safe (and even desirable arguably), but device_link_add() +doesn't handle that case correctly and the initial state of the link +created by it is wrong then. + +To address this problem, change the initial state of device links +added between a probing supplier and a probing consumer to +DL_STATE_CONSUMER_PROBE and update device_links_driver_bound() to +skip such links on the supplier side. + +With this change, if the supplier probe completes first, +device_links_driver_bound() called for it will skip the link state +update and when it is called for the consumer, the link state will +be updated to "active". In turn, if the consumer probe completes +first, device_links_driver_bound() called for it will change the +state of the link to "active" and when it is called for the +supplier, the link status update will be skipped. + +However, in principle the supplier or consumer probe may still fail +after the link has been added, so modify device_links_no_driver() to +change device links in the "active" or "consumer probe" state to +"dormant" on the supplier side and update __device_links_no_driver() +to change the link state to "available" only if it is "consumer +probe" or "active". + +Then, if the supplier probe fails first, the leftover link to the +probing consumer will become "dormant" and device_links_no_driver() +called for the consumer (when its probe fails) will clean it up. +In turn, if the consumer probe fails first, it will either drop the +link, or change its state to "available" and, in the latter case, +when device_links_no_driver() is called for the supplier, it will +update the link state to "dormant". [If the supplier probe fails, +but the consumer probe succeeds, which should not happen as long as +the consumer driver is correct, the link still will be around, but +it will be "dormant" until the supplier is probed again.] + +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Saravana Kannan +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/driver-api/device_link.rst | 10 ++-- + drivers/base/core.c | 74 +++++++++++++++++++++++++++---- + 2 files changed, 73 insertions(+), 11 deletions(-) + +--- a/Documentation/driver-api/device_link.rst ++++ b/Documentation/driver-api/device_link.rst +@@ -59,11 +59,15 @@ device ``->probe`` callback or a boot-ti + + Another example for an inconsistent state would be a device link that + represents a driver presence dependency, yet is added from the consumer's +-``->probe`` callback while the supplier hasn't probed yet: Had the driver +-core known about the device link earlier, it wouldn't have probed the ++``->probe`` callback while the supplier hasn't started to probe yet: Had the ++driver core known about the device link earlier, it wouldn't have probed the + consumer in the first place. The onus is thus on the consumer to check + presence of the supplier after adding the link, and defer probing on +-non-presence. ++non-presence. [Note that it is valid to create a link from the consumer's ++``->probe`` callback while the supplier is still probing, but the consumer must ++know that the supplier is functional already at the link creation time (that is ++the case, for instance, if the consumer has just acquired some resources that ++would not have been available had the supplier not been functional then).] + + If a device link is added in the ``->probe`` callback of the supplier or + consumer driver, it is typically deleted in its ``->remove`` callback for +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -287,17 +287,26 @@ struct device_link *device_link_add(stru + link->status = DL_STATE_NONE; + } else { + switch (supplier->links.status) { +- case DL_DEV_DRIVER_BOUND: ++ case DL_DEV_PROBING: + switch (consumer->links.status) { + case DL_DEV_PROBING: + /* +- * Some callers expect the link creation during +- * consumer driver probe to resume the supplier +- * even without DL_FLAG_RPM_ACTIVE. ++ * A consumer driver can create a link to a ++ * supplier that has not completed its probing ++ * yet as long as it knows that the supplier is ++ * already functional (for example, it has just ++ * acquired some resources from the supplier). + */ +- if (flags & DL_FLAG_PM_RUNTIME) +- pm_runtime_resume(supplier); +- ++ link->status = DL_STATE_CONSUMER_PROBE; ++ break; ++ default: ++ link->status = DL_STATE_DORMANT; ++ break; ++ } ++ break; ++ case DL_DEV_DRIVER_BOUND: ++ switch (consumer->links.status) { ++ case DL_DEV_PROBING: + link->status = DL_STATE_CONSUMER_PROBE; + break; + case DL_DEV_DRIVER_BOUND: +@@ -318,6 +327,14 @@ struct device_link *device_link_add(stru + } + + /* ++ * Some callers expect the link creation during consumer driver probe to ++ * resume the supplier even without DL_FLAG_RPM_ACTIVE. ++ */ ++ if (link->status == DL_STATE_CONSUMER_PROBE && ++ flags & DL_FLAG_PM_RUNTIME) ++ pm_runtime_resume(supplier); ++ ++ /* + * Move the consumer and all of the devices depending on it to the end + * of dpm_list and the devices_kset list. + * +@@ -508,6 +525,16 @@ void device_links_driver_bound(struct de + if (link->flags & DL_FLAG_STATELESS) + continue; + ++ /* ++ * Links created during consumer probe may be in the "consumer ++ * probe" state to start with if the supplier is still probing ++ * when they are created and they may become "active" if the ++ * consumer probe returns first. Skip them here. ++ */ ++ if (link->status == DL_STATE_CONSUMER_PROBE || ++ link->status == DL_STATE_ACTIVE) ++ continue; ++ + WARN_ON(link->status != DL_STATE_DORMANT); + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); + } +@@ -547,17 +574,48 @@ static void __device_links_no_driver(str + + if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) + __device_link_del(&link->kref); +- else if (link->status != DL_STATE_SUPPLIER_UNBIND) ++ else if (link->status == DL_STATE_CONSUMER_PROBE || ++ link->status == DL_STATE_ACTIVE) + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); + } + + dev->links.status = DL_DEV_NO_DRIVER; + } + ++/** ++ * device_links_no_driver - Update links after failing driver probe. ++ * @dev: Device whose driver has just failed to probe. ++ * ++ * Clean up leftover links to consumers for @dev and invoke ++ * %__device_links_no_driver() to update links to suppliers for it as ++ * appropriate. ++ * ++ * Links with the DL_FLAG_STATELESS flag set are ignored. ++ */ + void device_links_no_driver(struct device *dev) + { ++ struct device_link *link; ++ + device_links_write_lock(); ++ ++ list_for_each_entry(link, &dev->links.consumers, s_node) { ++ if (link->flags & DL_FLAG_STATELESS) ++ continue; ++ ++ /* ++ * The probe has failed, so if the status of the link is ++ * "consumer probe" or "active", it must have been added by ++ * a probing consumer while this device was still probing. ++ * Change its state to "dormant", as it represents a valid ++ * relationship, but it is not functionally meaningful. ++ */ ++ if (link->status == DL_STATE_CONSUMER_PROBE || ++ link->status == DL_STATE_ACTIVE) ++ WRITE_ONCE(link->status, DL_STATE_DORMANT); ++ } ++ + __device_links_no_driver(dev); ++ + device_links_write_unlock(); + } + diff --git a/queue-4.19/driver-core-fix-creation-of-device-links-with-pm-runtime-flags.patch b/queue-4.19/driver-core-fix-creation-of-device-links-with-pm-runtime-flags.patch new file mode 100644 index 00000000000..d7927bacde5 --- /dev/null +++ b/queue-4.19/driver-core-fix-creation-of-device-links-with-pm-runtime-flags.patch @@ -0,0 +1,53 @@ +From fb583c8eeeb1fd57e24ef41ed94c9112067aeac9 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Tue, 30 Jul 2019 11:28:57 +0200 +Subject: driver core: Fix creation of device links with PM-runtime flags + +From: Rafael J. Wysocki + +commit fb583c8eeeb1fd57e24ef41ed94c9112067aeac9 upstream. + +After commit 515db266a9da ("driver core: Remove device link creation +limitation"), if PM-runtime flags are passed to device_link_add(), it +will fail (returning NULL) due to an overly restrictive flags check +introduced by that commit. + +Fix this issue by extending the check in question to cover the +PM-runtime flags too. + +Fixes: 515db266a9da ("driver core: Remove device link creation limitation") +Reported-by: Dmitry Osipenko +Tested-by: Jon Hunter +Signed-off-by: Rafael J. Wysocki +Tested-by: Dmitry Osipenko +Tested-by: Marek Szyprowski +Link: https://lore.kernel.org/r/7674989.cD04D8YV3U@kreacher +Signed-off-by: Saravana Kannan +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/core.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -213,6 +213,9 @@ void device_pm_move_to_tail(struct devic + DL_FLAG_AUTOREMOVE_SUPPLIER | \ + DL_FLAG_AUTOPROBE_CONSUMER) + ++#define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \ ++ DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE) ++ + /** + * device_link_add - Create a link between two devices. + * @consumer: Consumer end of the link. +@@ -274,8 +277,7 @@ struct device_link *device_link_add(stru + { + struct device_link *link; + +- if (!consumer || !supplier || +- (flags & ~(DL_FLAG_STATELESS | DL_MANAGED_LINK_FLAGS)) || ++ if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || + (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || + (flags & DL_FLAG_AUTOPROBE_CONSUMER && + flags & (DL_FLAG_AUTOREMOVE_CONSUMER | diff --git a/queue-4.19/driver-core-make-driver-core-own-stateful-device-links.patch b/queue-4.19/driver-core-make-driver-core-own-stateful-device-links.patch new file mode 100644 index 00000000000..d0c5ad54aec --- /dev/null +++ b/queue-4.19/driver-core-make-driver-core-own-stateful-device-links.patch @@ -0,0 +1,265 @@ +From 72175d4ea4c442d95cf690c3e968eeee90fd43ca Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Fri, 1 Feb 2019 01:58:33 +0100 +Subject: driver core: Make driver core own stateful device links + +From: Rafael J. Wysocki + +commit 72175d4ea4c442d95cf690c3e968eeee90fd43ca upstream. + +Even though stateful device links are managed by the driver core in +principle, their creators are allowed and sometimes even expected +to drop references to them via device_link_del() or +device_link_remove(), but that doesn't really play well with the +"persistent" link concept. + +If "persistent" managed device links are created from driver +probe callbacks, device_link_add() called to do that will take a +new reference on the link each time the callback runs and those +references will never be dropped, which kind of isn't nice. + +This issues arises because of the link reference counting carried +out by device_link_add() for existing links, but that is only done to +avoid deleting device links that may still be necessary, which +shouldn't be a concern for managed (stateful) links. These device +links are managed by the driver core and whoever creates one of them +will need it at least as long as until the consumer driver is detached +from its device and deleting it may be left to the driver core just +fine. + +For this reason, rework device_link_add() to apply the reference +counting to stateless links only and make device_link_del() and +device_link_remove() drop references to stateless links only too. +After this change, if called to add a stateful device link for +a consumer-supplier pair for which a stateful device link is +present already, device_link_add() will return the existing link +without incrementing its reference counter. Accordingly, +device_link_del() and device_link_remove() will WARN() and do +nothing when called to drop a reference to a stateful link. Thus, +effectively, all stateful device links will be owned by the driver +core. + +In addition, clean up the handling of the link management flags, +DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_AUTOREMOVE_SUPPLIER, so that +(a) they are never set at the same time and (b) if device_link_add() +is called for a consumer-supplier pair with an existing stateful link +between them, the flags of that link will be combined with the flags +passed to device_link_add() to ensure that the life time of the link +is sufficient for all of the callers of device_link_add() for the +same consumer-supplier pair. + +Update the device_link_add() kerneldoc comment to reflect the +above changes. + +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Saravana Kannan +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/driver-api/device_link.rst | 42 +++++++++++------- + drivers/base/core.c | 69 ++++++++++++++++++++++++------- + 2 files changed, 79 insertions(+), 32 deletions(-) + +--- a/Documentation/driver-api/device_link.rst ++++ b/Documentation/driver-api/device_link.rst +@@ -25,8 +25,8 @@ suspend/resume and shutdown ordering. + + Device links allow representation of such dependencies in the driver core. + +-In its standard form, a device link combines *both* dependency types: +-It guarantees correct suspend/resume and shutdown ordering between a ++In its standard or *managed* form, a device link combines *both* dependency ++types: It guarantees correct suspend/resume and shutdown ordering between a + "supplier" device and its "consumer" devices, and it guarantees driver + presence on the supplier. The consumer devices are not probed before the + supplier is bound to a driver, and they're unbound before the supplier +@@ -69,12 +69,14 @@ know that the supplier is functional alr + the case, for instance, if the consumer has just acquired some resources that + would not have been available had the supplier not been functional then).] + +-If a device link is added in the ``->probe`` callback of the supplier or +-consumer driver, it is typically deleted in its ``->remove`` callback for +-symmetry. That way, if the driver is compiled as a module, the device +-link is added on module load and orderly deleted on unload. The same +-restrictions that apply to device link addition (e.g. exclusion of a +-parallel suspend/resume transition) apply equally to deletion. ++If a device link with ``DL_FLAG_STATELESS`` set (i.e. a stateless device link) ++is added in the ``->probe`` callback of the supplier or consumer driver, it is ++typically deleted in its ``->remove`` callback for symmetry. That way, if the ++driver is compiled as a module, the device link is added on module load and ++orderly deleted on unload. The same restrictions that apply to device link ++addition (e.g. exclusion of a parallel suspend/resume transition) apply equally ++to deletion. Device links with ``DL_FLAG_STATELESS`` unset (i.e. managed ++device links) are deleted automatically by the driver core. + + Several flags may be specified on device link addition, two of which + have already been mentioned above: ``DL_FLAG_STATELESS`` to express that no +@@ -87,8 +89,6 @@ link is added from the consumer's ``->pr + can be specified to runtime resume the supplier upon addition of the + device link. ``DL_FLAG_AUTOREMOVE_CONSUMER`` causes the device link to be + automatically purged when the consumer fails to probe or later unbinds. +-This obviates the need to explicitly delete the link in the ``->remove`` +-callback or in the error path of the ``->probe`` callback. + + Similarly, when the device link is added from supplier's ``->probe`` callback, + ``DL_FLAG_AUTOREMOVE_SUPPLIER`` causes the device link to be automatically +@@ -97,12 +97,20 @@ purged when the supplier fails to probe + Limitations + =========== + +-Driver authors should be aware that a driver presence dependency (i.e. when +-``DL_FLAG_STATELESS`` is not specified on link addition) may cause probing of +-the consumer to be deferred indefinitely. This can become a problem if the +-consumer is required to probe before a certain initcall level is reached. +-Worse, if the supplier driver is blacklisted or missing, the consumer will +-never be probed. ++Driver authors should be aware that a driver presence dependency for managed ++device links (i.e. when ``DL_FLAG_STATELESS`` is not specified on link addition) ++may cause probing of the consumer to be deferred indefinitely. This can become ++a problem if the consumer is required to probe before a certain initcall level ++is reached. Worse, if the supplier driver is blacklisted or missing, the ++consumer will never be probed. ++ ++Moreover, managed device links cannot be deleted directly. They are deleted ++by the driver core when they are not necessary any more in accordance with the ++``DL_FLAG_AUTOREMOVE_CONSUMER`` and ``DL_FLAG_AUTOREMOVE_SUPPLIER`` flags. ++However, stateless device links (i.e. device links with ``DL_FLAG_STATELESS`` ++set) are expected to be removed by whoever called :c:func:`device_link_add()` ++to add them with the help of either :c:func:`device_link_del()` or ++:c:func:`device_link_remove()`. + + Sometimes drivers depend on optional resources. They are able to operate + in a degraded mode (reduced feature set or performance) when those resources +@@ -286,4 +294,4 @@ API + === + + .. kernel-doc:: drivers/base/core.c +- :functions: device_link_add device_link_del ++ :functions: device_link_add device_link_del device_link_remove +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -179,10 +179,21 @@ void device_pm_move_to_tail(struct devic + * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be + * ignored. + * +- * If the DL_FLAG_AUTOREMOVE_CONSUMER flag is set, the link will be removed +- * automatically when the consumer device driver unbinds from it. Analogously, +- * if DL_FLAG_AUTOREMOVE_SUPPLIER is set in @flags, the link will be removed +- * automatically when the supplier device driver unbinds from it. ++ * If DL_FLAG_STATELESS is set in @flags, the link is not going to be managed by ++ * the driver core and, in particular, the caller of this function is expected ++ * to drop the reference to the link acquired by it directly. ++ * ++ * If that flag is not set, however, the caller of this function is handing the ++ * management of the link over to the driver core entirely and its return value ++ * can only be used to check whether or not the link is present. In that case, ++ * the DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_AUTOREMOVE_SUPPLIER device link ++ * flags can be used to indicate to the driver core when the link can be safely ++ * deleted. Namely, setting one of them in @flags indicates to the driver core ++ * that the link is not going to be used (by the given caller of this function) ++ * after unbinding the consumer or supplier driver, respectively, from its ++ * device, so the link can be deleted at that point. If none of them is set, ++ * the link will be maintained until one of the devices pointed to by it (either ++ * the consumer or the supplier) is unregistered. + * + * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER + * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and +@@ -228,6 +239,14 @@ struct device_link *device_link_add(stru + goto out; + } + ++ /* ++ * DL_FLAG_AUTOREMOVE_SUPPLIER indicates that the link will be needed ++ * longer than for DL_FLAG_AUTOREMOVE_CONSUMER and setting them both ++ * together doesn't make sense, so prefer DL_FLAG_AUTOREMOVE_SUPPLIER. ++ */ ++ if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) ++ flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER; ++ + list_for_each_entry(link, &supplier->links.consumers, s_node) { + if (link->consumer != consumer) + continue; +@@ -241,12 +260,6 @@ struct device_link *device_link_add(stru + goto out; + } + +- if (flags & DL_FLAG_AUTOREMOVE_CONSUMER) +- link->flags |= DL_FLAG_AUTOREMOVE_CONSUMER; +- +- if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) +- link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER; +- + if (flags & DL_FLAG_PM_RUNTIME) { + if (!(link->flags & DL_FLAG_PM_RUNTIME)) { + pm_runtime_new_link(consumer); +@@ -256,7 +269,25 @@ struct device_link *device_link_add(stru + refcount_inc(&link->rpm_active); + } + +- kref_get(&link->kref); ++ if (flags & DL_FLAG_STATELESS) { ++ kref_get(&link->kref); ++ goto out; ++ } ++ ++ /* ++ * If the life time of the link following from the new flags is ++ * longer than indicated by the flags of the existing link, ++ * update the existing link to stay around longer. ++ */ ++ if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) { ++ if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) { ++ link->flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER; ++ link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER; ++ } ++ } else if (!(flags & DL_FLAG_AUTOREMOVE_CONSUMER)) { ++ link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER | ++ DL_FLAG_AUTOREMOVE_SUPPLIER); ++ } + goto out; + } + +@@ -406,8 +437,16 @@ static void __device_link_del(struct kre + } + #endif /* !CONFIG_SRCU */ + ++static void device_link_put_kref(struct device_link *link) ++{ ++ if (link->flags & DL_FLAG_STATELESS) ++ kref_put(&link->kref, __device_link_del); ++ else ++ WARN(1, "Unable to drop a managed device link reference\n"); ++} ++ + /** +- * device_link_del - Delete a link between two devices. ++ * device_link_del - Delete a stateless link between two devices. + * @link: Device link to delete. + * + * The caller must ensure proper synchronization of this function with runtime +@@ -419,14 +458,14 @@ void device_link_del(struct device_link + { + device_links_write_lock(); + device_pm_lock(); +- kref_put(&link->kref, __device_link_del); ++ device_link_put_kref(link); + device_pm_unlock(); + device_links_write_unlock(); + } + EXPORT_SYMBOL_GPL(device_link_del); + + /** +- * device_link_remove - remove a link between two devices. ++ * device_link_remove - Delete a stateless link between two devices. + * @consumer: Consumer end of the link. + * @supplier: Supplier end of the link. + * +@@ -445,7 +484,7 @@ void device_link_remove(void *consumer, + + list_for_each_entry(link, &supplier->links.consumers, s_node) { + if (link->consumer == consumer) { +- kref_put(&link->kref, __device_link_del); ++ device_link_put_kref(link); + break; + } + } diff --git a/queue-4.19/driver-core-remove-device-link-creation-limitation.patch b/queue-4.19/driver-core-remove-device-link-creation-limitation.patch new file mode 100644 index 00000000000..ce3151e655d --- /dev/null +++ b/queue-4.19/driver-core-remove-device-link-creation-limitation.patch @@ -0,0 +1,501 @@ +From 515db266a9dace92b0cbaed9a6044dd5304b8ca9 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Tue, 16 Jul 2019 17:21:06 +0200 +Subject: driver core: Remove device link creation limitation + +From: Rafael J. Wysocki + +commit 515db266a9dace92b0cbaed9a6044dd5304b8ca9 upstream. + +If device_link_add() is called for a consumer/supplier pair with an +existing device link between them and the existing link's type is +not in agreement with the flags passed to that function by its +caller, NULL will be returned. That is seriously inconvenient, +because it forces the callers of device_link_add() to worry about +what others may or may not do even if that is not relevant to them +for any other reasons. + +It turns out, however, that this limitation can be made go away +relatively easily. + +The underlying observation is that if DL_FLAG_STATELESS has been +passed to device_link_add() in flags for the given consumer/supplier +pair at least once, calling either device_link_del() or +device_link_remove() to release the link returned by it should work, +but there are no other requirements associated with that flag. In +turn, if at least one of the callers of device_link_add() for the +given consumer/supplier pair has not passed DL_FLAG_STATELESS to it +in flags, the driver core should track the status of the link and act +on it as appropriate (ie. the link should be treated as "managed"). +This means that DL_FLAG_STATELESS needs to be set for managed device +links and it should be valid to call device_link_del() or +device_link_remove() to drop references to them in certain +sutiations. + +To allow that to happen, introduce a new (internal) device link flag +called DL_FLAG_MANAGED and make device_link_add() set it automatically +whenever DL_FLAG_STATELESS is not passed to it. Also make it take +additional references to existing device links that were previously +stateless (that is, with DL_FLAG_STATELESS set and DL_FLAG_MANAGED +unset) and will need to be managed going forward and initialize +their status (which has been DL_STATE_NONE so far). + +Accordingly, when a managed device link is dropped automatically +by the driver core, make it clear DL_FLAG_MANAGED, reset the link's +status back to DL_STATE_NONE and drop the reference to it associated +with DL_FLAG_MANAGED instead of just deleting it right away (to +allow it to stay around in case it still needs to be released +explicitly by someone). + +With that, since setting DL_FLAG_STATELESS doesn't mean that the +device link in question is not managed any more, replace all of the +status-tracking checks against DL_FLAG_STATELESS with analogous +checks against DL_FLAG_MANAGED and update the documentation to +reflect these changes. + +While at it, make device_link_add() reject flags that it does not +recognize, including DL_FLAG_MANAGED. + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Saravana Kannan +Tested-by: Marek Szyprowski +Review-by: Saravana Kannan +Link: https://lore.kernel.org/r/2305283.AStDPdUUnE@kreacher +Signed-off-by: Saravana Kannan +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/driver-api/device_link.rst | 4 + drivers/base/core.c | 176 +++++++++++++++++-------------- + drivers/base/power/runtime.c | 4 + include/linux/device.h | 4 + 4 files changed, 106 insertions(+), 82 deletions(-) + +--- a/Documentation/driver-api/device_link.rst ++++ b/Documentation/driver-api/device_link.rst +@@ -75,8 +75,8 @@ typically deleted in its ``->remove`` ca + driver is compiled as a module, the device link is added on module load and + orderly deleted on unload. The same restrictions that apply to device link + addition (e.g. exclusion of a parallel suspend/resume transition) apply equally +-to deletion. Device links with ``DL_FLAG_STATELESS`` unset (i.e. managed +-device links) are deleted automatically by the driver core. ++to deletion. Device links managed by the driver core are deleted automatically ++by it. + + Several flags may be specified on device link addition, two of which + have already been mentioned above: ``DL_FLAG_STATELESS`` to express that no +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -124,6 +124,50 @@ static int device_is_dependent(struct de + return ret; + } + ++static void device_link_init_status(struct device_link *link, ++ struct device *consumer, ++ struct device *supplier) ++{ ++ switch (supplier->links.status) { ++ case DL_DEV_PROBING: ++ switch (consumer->links.status) { ++ case DL_DEV_PROBING: ++ /* ++ * A consumer driver can create a link to a supplier ++ * that has not completed its probing yet as long as it ++ * knows that the supplier is already functional (for ++ * example, it has just acquired some resources from the ++ * supplier). ++ */ ++ link->status = DL_STATE_CONSUMER_PROBE; ++ break; ++ default: ++ link->status = DL_STATE_DORMANT; ++ break; ++ } ++ break; ++ case DL_DEV_DRIVER_BOUND: ++ switch (consumer->links.status) { ++ case DL_DEV_PROBING: ++ link->status = DL_STATE_CONSUMER_PROBE; ++ break; ++ case DL_DEV_DRIVER_BOUND: ++ link->status = DL_STATE_ACTIVE; ++ break; ++ default: ++ link->status = DL_STATE_AVAILABLE; ++ break; ++ } ++ break; ++ case DL_DEV_UNBINDING: ++ link->status = DL_STATE_SUPPLIER_UNBIND; ++ break; ++ default: ++ link->status = DL_STATE_DORMANT; ++ break; ++ } ++} ++ + static int device_reorder_to_tail(struct device *dev, void *not_used) + { + struct device_link *link; +@@ -165,6 +209,10 @@ void device_pm_move_to_tail(struct devic + device_links_read_unlock(idx); + } + ++#define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ ++ DL_FLAG_AUTOREMOVE_SUPPLIER | \ ++ DL_FLAG_AUTOPROBE_CONSUMER) ++ + /** + * device_link_add - Create a link between two devices. + * @consumer: Consumer end of the link. +@@ -179,9 +227,9 @@ void device_pm_move_to_tail(struct devic + * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be + * ignored. + * +- * If DL_FLAG_STATELESS is set in @flags, the link is not going to be managed by +- * the driver core and, in particular, the caller of this function is expected +- * to drop the reference to the link acquired by it directly. ++ * If DL_FLAG_STATELESS is set in @flags, the caller of this function is ++ * expected to release the link returned by it directly with the help of either ++ * device_link_del() or device_link_remove(). + * + * If that flag is not set, however, the caller of this function is handing the + * management of the link over to the driver core entirely and its return value +@@ -201,9 +249,16 @@ void device_pm_move_to_tail(struct devic + * be used to request the driver core to automaticall probe for a consmer + * driver after successfully binding a driver to the supplier device. + * +- * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER +- * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and +- * will cause NULL to be returned upfront. ++ * The combination of DL_FLAG_STATELESS and one of DL_FLAG_AUTOREMOVE_CONSUMER, ++ * DL_FLAG_AUTOREMOVE_SUPPLIER, or DL_FLAG_AUTOPROBE_CONSUMER set in @flags at ++ * the same time is invalid and will cause NULL to be returned upfront. ++ * However, if a device link between the given @consumer and @supplier pair ++ * exists already when this function is called for them, the existing link will ++ * be returned regardless of its current type and status (the link's flags may ++ * be modified then). The caller of this function is then expected to treat ++ * the link as though it has just been created, so (in particular) if ++ * DL_FLAG_STATELESS was passed in @flags, the link needs to be released ++ * explicitly when not needed any more (as stated above). + * + * A side effect of the link creation is re-ordering of dpm_list and the + * devices_kset list by moving the consumer device and all devices depending +@@ -220,10 +275,8 @@ struct device_link *device_link_add(stru + struct device_link *link; + + if (!consumer || !supplier || +- (flags & DL_FLAG_STATELESS && +- flags & (DL_FLAG_AUTOREMOVE_CONSUMER | +- DL_FLAG_AUTOREMOVE_SUPPLIER | +- DL_FLAG_AUTOPROBE_CONSUMER)) || ++ (flags & ~(DL_FLAG_STATELESS | DL_MANAGED_LINK_FLAGS)) || ++ (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || + (flags & DL_FLAG_AUTOPROBE_CONSUMER && + flags & (DL_FLAG_AUTOREMOVE_CONSUMER | + DL_FLAG_AUTOREMOVE_SUPPLIER))) +@@ -236,6 +289,9 @@ struct device_link *device_link_add(stru + } + } + ++ if (!(flags & DL_FLAG_STATELESS)) ++ flags |= DL_FLAG_MANAGED; ++ + device_links_write_lock(); + device_pm_lock(); + +@@ -262,15 +318,6 @@ struct device_link *device_link_add(stru + if (link->consumer != consumer) + continue; + +- /* +- * Don't return a stateless link if the caller wants a stateful +- * one and vice versa. +- */ +- if (WARN_ON((flags & DL_FLAG_STATELESS) != (link->flags & DL_FLAG_STATELESS))) { +- link = NULL; +- goto out; +- } +- + if (flags & DL_FLAG_PM_RUNTIME) { + if (!(link->flags & DL_FLAG_PM_RUNTIME)) { + pm_runtime_new_link(consumer); +@@ -281,6 +328,7 @@ struct device_link *device_link_add(stru + } + + if (flags & DL_FLAG_STATELESS) { ++ link->flags |= DL_FLAG_STATELESS; + kref_get(&link->kref); + goto out; + } +@@ -299,6 +347,11 @@ struct device_link *device_link_add(stru + link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER | + DL_FLAG_AUTOREMOVE_SUPPLIER); + } ++ if (!(link->flags & DL_FLAG_MANAGED)) { ++ kref_get(&link->kref); ++ link->flags |= DL_FLAG_MANAGED; ++ device_link_init_status(link, consumer, supplier); ++ } + goto out; + } + +@@ -325,48 +378,10 @@ struct device_link *device_link_add(stru + kref_init(&link->kref); + + /* Determine the initial link state. */ +- if (flags & DL_FLAG_STATELESS) { ++ if (flags & DL_FLAG_STATELESS) + link->status = DL_STATE_NONE; +- } else { +- switch (supplier->links.status) { +- case DL_DEV_PROBING: +- switch (consumer->links.status) { +- case DL_DEV_PROBING: +- /* +- * A consumer driver can create a link to a +- * supplier that has not completed its probing +- * yet as long as it knows that the supplier is +- * already functional (for example, it has just +- * acquired some resources from the supplier). +- */ +- link->status = DL_STATE_CONSUMER_PROBE; +- break; +- default: +- link->status = DL_STATE_DORMANT; +- break; +- } +- break; +- case DL_DEV_DRIVER_BOUND: +- switch (consumer->links.status) { +- case DL_DEV_PROBING: +- link->status = DL_STATE_CONSUMER_PROBE; +- break; +- case DL_DEV_DRIVER_BOUND: +- link->status = DL_STATE_ACTIVE; +- break; +- default: +- link->status = DL_STATE_AVAILABLE; +- break; +- } +- break; +- case DL_DEV_UNBINDING: +- link->status = DL_STATE_SUPPLIER_UNBIND; +- break; +- default: +- link->status = DL_STATE_DORMANT; +- break; +- } +- } ++ else ++ device_link_init_status(link, consumer, supplier); + + /* + * Some callers expect the link creation during consumer driver probe to +@@ -528,7 +543,7 @@ static void device_links_missing_supplie + * mark the link as "consumer probe in progress" to make the supplier removal + * wait for us to complete (or bad things may happen). + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links without the DL_FLAG_MANAGED flag set are ignored. + */ + int device_links_check_suppliers(struct device *dev) + { +@@ -538,7 +553,7 @@ int device_links_check_suppliers(struct + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.suppliers, c_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + if (link->status != DL_STATE_AVAILABLE) { +@@ -563,7 +578,7 @@ int device_links_check_suppliers(struct + * + * Also change the status of @dev's links to suppliers to "active". + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links without the DL_FLAG_MANAGED flag set are ignored. + */ + void device_links_driver_bound(struct device *dev) + { +@@ -572,7 +587,7 @@ void device_links_driver_bound(struct de + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.consumers, s_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + /* +@@ -593,7 +608,7 @@ void device_links_driver_bound(struct de + } + + list_for_each_entry(link, &dev->links.suppliers, c_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); +@@ -605,6 +620,13 @@ void device_links_driver_bound(struct de + device_links_write_unlock(); + } + ++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. + * @dev: Device without a drvier. +@@ -615,18 +637,18 @@ void device_links_driver_bound(struct de + * unless they already are in the "supplier unbind in progress" state in which + * case they need not be updated. + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links without the DL_FLAG_MANAGED flag set are ignored. + */ + static void __device_links_no_driver(struct device *dev) + { + struct device_link *link, *ln; + + list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) +- __device_link_del(&link->kref); ++ device_link_drop_managed(link); + else if (link->status == DL_STATE_CONSUMER_PROBE || + link->status == DL_STATE_ACTIVE) + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); +@@ -643,7 +665,7 @@ static void __device_links_no_driver(str + * %__device_links_no_driver() to update links to suppliers for it as + * appropriate. + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links without the DL_FLAG_MANAGED flag set are ignored. + */ + void device_links_no_driver(struct device *dev) + { +@@ -652,7 +674,7 @@ void device_links_no_driver(struct devic + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.consumers, s_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + /* +@@ -680,7 +702,7 @@ void device_links_no_driver(struct devic + * invoke %__device_links_no_driver() to update links to suppliers for it as + * appropriate. + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links without the DL_FLAG_MANAGED flag set are ignored. + */ + void device_links_driver_cleanup(struct device *dev) + { +@@ -689,7 +711,7 @@ void device_links_driver_cleanup(struct + device_links_write_lock(); + + list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER); +@@ -702,7 +724,7 @@ void device_links_driver_cleanup(struct + */ + if (link->status == DL_STATE_SUPPLIER_UNBIND && + link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) +- __device_link_del(&link->kref); ++ device_link_drop_managed(link); + + WRITE_ONCE(link->status, DL_STATE_DORMANT); + } +@@ -724,7 +746,7 @@ void device_links_driver_cleanup(struct + * + * Return 'false' if there are no probing or active consumers. + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links without the DL_FLAG_MANAGED flag set are ignored. + */ + bool device_links_busy(struct device *dev) + { +@@ -734,7 +756,7 @@ bool device_links_busy(struct device *de + device_links_write_lock(); + + list_for_each_entry(link, &dev->links.consumers, s_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + if (link->status == DL_STATE_CONSUMER_PROBE +@@ -764,7 +786,7 @@ bool device_links_busy(struct device *de + * driver to unbind and start over (the consumer will not re-probe as we have + * changed the state of the link already). + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links without the DL_FLAG_MANAGED flag set are ignored. + */ + void device_links_unbind_consumers(struct device *dev) + { +@@ -776,7 +798,7 @@ void device_links_unbind_consumers(struc + list_for_each_entry(link, &dev->links.consumers, s_node) { + enum device_link_state status; + +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + status = link->status; +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -1531,7 +1531,7 @@ void pm_runtime_remove(struct device *de + * runtime PM references to the device, drop the usage counter of the device + * (as many times as needed). + * +- * Links with the DL_FLAG_STATELESS flag set are ignored. ++ * Links with the DL_FLAG_MANAGED flag unset are ignored. + * + * Since the device is guaranteed to be runtime-active at the point this is + * called, nothing else needs to be done here. +@@ -1548,7 +1548,7 @@ void pm_runtime_clean_up_links(struct de + idx = device_links_read_lock(); + + list_for_each_entry_rcu(link, &dev->links.consumers, s_node) { +- if (link->flags & DL_FLAG_STATELESS) ++ if (!(link->flags & DL_FLAG_MANAGED)) + continue; + + while (refcount_dec_not_one(&link->rpm_active)) +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -820,12 +820,13 @@ enum device_link_state { + /* + * Device link flags. + * +- * STATELESS: The core won't track the presence of supplier/consumer drivers. ++ * STATELESS: The core will not remove this link automatically. + * AUTOREMOVE_CONSUMER: Remove the link automatically on consumer driver unbind. + * PM_RUNTIME: If set, the runtime PM framework will use this link. + * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation. + * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind. + * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds. ++ * MANAGED: The core tracks presence of supplier/consumer drivers (internal). + */ + #define DL_FLAG_STATELESS BIT(0) + #define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1) +@@ -833,6 +834,7 @@ enum device_link_state { + #define DL_FLAG_RPM_ACTIVE BIT(3) + #define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4) + #define DL_FLAG_AUTOPROBE_CONSUMER BIT(5) ++#define DL_FLAG_MANAGED BIT(6) + + /** + * struct device_link - Device link representation. diff --git a/queue-4.19/driver-core-remove-the-link-if-there-is-no-driver-with-auto-flag.patch b/queue-4.19/driver-core-remove-the-link-if-there-is-no-driver-with-auto-flag.patch new file mode 100644 index 00000000000..b4e6d93de3e --- /dev/null +++ b/queue-4.19/driver-core-remove-the-link-if-there-is-no-driver-with-auto-flag.patch @@ -0,0 +1,43 @@ +From 0fe6f7874d467456da6f6a221dd92499a3ab1780 Mon Sep 17 00:00:00 2001 +From: Yong Wu +Date: Tue, 1 Jan 2019 12:51:05 +0800 +Subject: driver core: Remove the link if there is no driver with AUTO flag + +From: Yong Wu + +commit 0fe6f7874d467456da6f6a221dd92499a3ab1780 upstream. + +DL_FLAG_AUTOREMOVE_CONSUMER/SUPPLIER means "Remove the link +automatically on consumer/supplier driver unbind", that means we should +remove whole the device_link when there is no this driver no matter what +the ref_count of the link is. + +CC: Greg Kroah-Hartman +Signed-off-by: Yong Wu +Signed-off-by: Saravana Kannan +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -546,7 +546,7 @@ static void __device_links_no_driver(str + continue; + + if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) +- kref_put(&link->kref, __device_link_del); ++ __device_link_del(&link->kref); + else if (link->status != DL_STATE_SUPPLIER_UNBIND) + WRITE_ONCE(link->status, DL_STATE_AVAILABLE); + } +@@ -591,7 +591,7 @@ void device_links_driver_cleanup(struct + */ + if (link->status == DL_STATE_SUPPLIER_UNBIND && + link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) +- kref_put(&link->kref, __device_link_del); ++ __device_link_del(&link->kref); + + WRITE_ONCE(link->status, DL_STATE_DORMANT); + } diff --git a/queue-4.19/series b/queue-4.19/series index 8bca37ab830..fa8f2c422db 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -33,3 +33,9 @@ wimax-i2400-fix-memory-leak.patch wimax-i2400-fix-memory-leak-in-i2400m_op_rfkill_sw_t.patch mmc-sdhci-omap-don-t-finish_mrq-on-a-command-error-d.patch mmc-sdhci-omap-fix-tuning-procedure-for-temperatures.patch +driver-core-remove-the-link-if-there-is-no-driver-with-auto-flag.patch +driver-core-fix-adding-device-links-to-probing-suppliers.patch +driver-core-make-driver-core-own-stateful-device-links.patch +driver-core-add-device-link-flag-dl_flag_autoprobe_consumer.patch +driver-core-remove-device-link-creation-limitation.patch +driver-core-fix-creation-of-device-links-with-pm-runtime-flags.patch