diff options
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 2ab316d85651..9d3c15d4dde8 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -178,10 +178,10 @@ void device_pm_move_to_tail(struct device *dev) | |||
178 | * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be | 178 | * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be |
179 | * ignored. | 179 | * ignored. |
180 | * | 180 | * |
181 | * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically | 181 | * If the DL_FLAG_AUTOREMOVE_CONSUMER is set, the link will be removed |
182 | * when the consumer device driver unbinds from it. The combination of both | 182 | * automatically when the consumer device driver unbinds from it. |
183 | * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL | 183 | * The combination of both DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_STATELESS |
184 | * to be returned. | 184 | * set is invalid and will cause NULL to be returned. |
185 | * | 185 | * |
186 | * A side effect of the link creation is re-ordering of dpm_list and the | 186 | * A side effect of the link creation is re-ordering of dpm_list and the |
187 | * devices_kset list by moving the consumer device and all devices depending | 187 | * devices_kset list by moving the consumer device and all devices depending |
@@ -198,7 +198,8 @@ struct device_link *device_link_add(struct device *consumer, | |||
198 | struct device_link *link; | 198 | struct device_link *link; |
199 | 199 | ||
200 | if (!consumer || !supplier || | 200 | if (!consumer || !supplier || |
201 | ((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_AUTOREMOVE))) | 201 | ((flags & DL_FLAG_STATELESS) && |
202 | (flags & DL_FLAG_AUTOREMOVE_CONSUMER))) | ||
202 | return NULL; | 203 | return NULL; |
203 | 204 | ||
204 | device_links_write_lock(); | 205 | device_links_write_lock(); |
@@ -509,7 +510,7 @@ static void __device_links_no_driver(struct device *dev) | |||
509 | if (link->flags & DL_FLAG_STATELESS) | 510 | if (link->flags & DL_FLAG_STATELESS) |
510 | continue; | 511 | continue; |
511 | 512 | ||
512 | if (link->flags & DL_FLAG_AUTOREMOVE) | 513 | if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) |
513 | kref_put(&link->kref, __device_link_del); | 514 | kref_put(&link->kref, __device_link_del); |
514 | else if (link->status != DL_STATE_SUPPLIER_UNBIND) | 515 | else if (link->status != DL_STATE_SUPPLIER_UNBIND) |
515 | WRITE_ONCE(link->status, DL_STATE_AVAILABLE); | 516 | WRITE_ONCE(link->status, DL_STATE_AVAILABLE); |
@@ -545,8 +546,18 @@ void device_links_driver_cleanup(struct device *dev) | |||
545 | if (link->flags & DL_FLAG_STATELESS) | 546 | if (link->flags & DL_FLAG_STATELESS) |
546 | continue; | 547 | continue; |
547 | 548 | ||
548 | WARN_ON(link->flags & DL_FLAG_AUTOREMOVE); | 549 | WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER); |
549 | WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); | 550 | WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); |
551 | |||
552 | /* | ||
553 | * autoremove the links between this @dev and its consumer | ||
554 | * devices that are not active, i.e. where the link state | ||
555 | * has moved to DL_STATE_SUPPLIER_UNBIND. | ||
556 | */ | ||
557 | if (link->status == DL_STATE_SUPPLIER_UNBIND && | ||
558 | link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) | ||
559 | kref_put(&link->kref, __device_link_del); | ||
560 | |||
550 | WRITE_ONCE(link->status, DL_STATE_DORMANT); | 561 | WRITE_ONCE(link->status, DL_STATE_DORMANT); |
551 | } | 562 | } |
552 | 563 | ||