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 df3e1a44707a..e721218bf352 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(); |
@@ -479,7 +480,7 @@ static void __device_links_no_driver(struct device *dev) | |||
479 | if (link->flags & DL_FLAG_STATELESS) | 480 | if (link->flags & DL_FLAG_STATELESS) |
480 | continue; | 481 | continue; |
481 | 482 | ||
482 | if (link->flags & DL_FLAG_AUTOREMOVE) | 483 | if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) |
483 | kref_put(&link->kref, __device_link_del); | 484 | kref_put(&link->kref, __device_link_del); |
484 | else if (link->status != DL_STATE_SUPPLIER_UNBIND) | 485 | else if (link->status != DL_STATE_SUPPLIER_UNBIND) |
485 | WRITE_ONCE(link->status, DL_STATE_AVAILABLE); | 486 | WRITE_ONCE(link->status, DL_STATE_AVAILABLE); |
@@ -515,8 +516,18 @@ void device_links_driver_cleanup(struct device *dev) | |||
515 | if (link->flags & DL_FLAG_STATELESS) | 516 | if (link->flags & DL_FLAG_STATELESS) |
516 | continue; | 517 | continue; |
517 | 518 | ||
518 | WARN_ON(link->flags & DL_FLAG_AUTOREMOVE); | 519 | WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER); |
519 | WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); | 520 | WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); |
521 | |||
522 | /* | ||
523 | * autoremove the links between this @dev and its consumer | ||
524 | * devices that are not active, i.e. where the link state | ||
525 | * has moved to DL_STATE_SUPPLIER_UNBIND. | ||
526 | */ | ||
527 | if (link->status == DL_STATE_SUPPLIER_UNBIND && | ||
528 | link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) | ||
529 | kref_put(&link->kref, __device_link_del); | ||
530 | |||
520 | WRITE_ONCE(link->status, DL_STATE_DORMANT); | 531 | WRITE_ONCE(link->status, DL_STATE_DORMANT); |
521 | } | 532 | } |
522 | 533 | ||