aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c25
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