driver core: Add device link flag DL_FLAG_AUTOPROBE_CONSUMER
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 <rafael.j.wysocki@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
72175d4ea4
commit
e7dd40105a
|
@ -94,6 +94,15 @@ Similarly, when the device link is added from supplier's ``->probe`` callback,
|
||||||
``DL_FLAG_AUTOREMOVE_SUPPLIER`` causes the device link to be automatically
|
``DL_FLAG_AUTOREMOVE_SUPPLIER`` causes the device link to be automatically
|
||||||
purged when the supplier fails to probe or later unbinds.
|
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
|
Limitations
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,12 @@ static void device_link_rpm_prepare(struct device *consumer,
|
||||||
* the link will be maintained until one of the devices pointed to by it (either
|
* the link will be maintained until one of the devices pointed to by it (either
|
||||||
* the consumer or the supplier) is unregistered.
|
* 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
|
* 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
|
* or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and
|
||||||
* will cause NULL to be returned upfront.
|
* will cause NULL to be returned upfront.
|
||||||
|
@ -228,7 +234,12 @@ struct device_link *device_link_add(struct device *consumer,
|
||||||
|
|
||||||
if (!consumer || !supplier ||
|
if (!consumer || !supplier ||
|
||||||
(flags & DL_FLAG_STATELESS &&
|
(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;
|
return NULL;
|
||||||
|
|
||||||
if (flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) {
|
if (flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) {
|
||||||
|
@ -589,6 +600,9 @@ void device_links_driver_bound(struct device *dev)
|
||||||
|
|
||||||
WARN_ON(link->status != DL_STATE_DORMANT);
|
WARN_ON(link->status != DL_STATE_DORMANT);
|
||||||
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
|
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) {
|
list_for_each_entry(link, &dev->links.suppliers, c_node) {
|
||||||
|
|
|
@ -116,7 +116,7 @@ static void deferred_probe_work_func(struct work_struct *work)
|
||||||
}
|
}
|
||||||
static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func);
|
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);
|
mutex_lock(&deferred_probe_mutex);
|
||||||
if (list_empty(&dev->p->deferred_probe)) {
|
if (list_empty(&dev->p->deferred_probe)) {
|
||||||
|
|
|
@ -341,6 +341,7 @@ struct device *driver_find_device(struct device_driver *drv,
|
||||||
struct device *start, void *data,
|
struct device *start, void *data,
|
||||||
int (*match)(struct device *dev, 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);
|
int driver_deferred_probe_check_state(struct device *dev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -827,12 +828,14 @@ enum device_link_state {
|
||||||
* PM_RUNTIME: If set, the runtime PM framework will use this link.
|
* 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.
|
* RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation.
|
||||||
* AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind.
|
* 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_STATELESS BIT(0)
|
||||||
#define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1)
|
#define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1)
|
||||||
#define DL_FLAG_PM_RUNTIME BIT(2)
|
#define DL_FLAG_PM_RUNTIME BIT(2)
|
||||||
#define DL_FLAG_RPM_ACTIVE BIT(3)
|
#define DL_FLAG_RPM_ACTIVE BIT(3)
|
||||||
#define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4)
|
#define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4)
|
||||||
|
#define DL_FLAG_AUTOPROBE_CONSUMER BIT(5)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct device_link - Device link representation.
|
* struct device_link - Device link representation.
|
||||||
|
|
Loading…
Reference in a new issue