aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-01-31 19:58:33 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-02-01 04:04:08 -0500
commit72175d4ea4c442d95cf690c3e968eeee90fd43ca (patch)
treee387388f696463439e31686520522e005a574058 /drivers/base/core.c
parentea4f640025183860792063ba5852aec60704ad8e (diff)
driver core: Make driver core own stateful device links
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 <rafael.j.wysocki@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8c7327d45406..9d49b461b1d9 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -192,10 +192,21 @@ static void device_link_rpm_prepare(struct device *consumer,
192 * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be 192 * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be
193 * ignored. 193 * ignored.
194 * 194 *
195 * If the DL_FLAG_AUTOREMOVE_CONSUMER flag is set, the link will be removed 195 * If DL_FLAG_STATELESS is set in @flags, the link is not going to be managed by
196 * automatically when the consumer device driver unbinds from it. Analogously, 196 * the driver core and, in particular, the caller of this function is expected
197 * if DL_FLAG_AUTOREMOVE_SUPPLIER is set in @flags, the link will be removed 197 * to drop the reference to the link acquired by it directly.
198 * automatically when the supplier device driver unbinds from it. 198 *
199 * If that flag is not set, however, the caller of this function is handing the
200 * management of the link over to the driver core entirely and its return value
201 * can only be used to check whether or not the link is present. In that case,
202 * the DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_AUTOREMOVE_SUPPLIER device link
203 * flags can be used to indicate to the driver core when the link can be safely
204 * deleted. Namely, setting one of them in @flags indicates to the driver core
205 * that the link is not going to be used (by the given caller of this function)
206 * after unbinding the consumer or supplier driver, respectively, from its
207 * device, so the link can be deleted at that point. If none of them is set,
208 * the link will be maintained until one of the devices pointed to by it (either
209 * the consumer or the supplier) is unregistered.
199 * 210 *
200 * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER 211 * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER
201 * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and 212 * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and
@@ -241,6 +252,14 @@ struct device_link *device_link_add(struct device *consumer,
241 goto out; 252 goto out;
242 } 253 }
243 254
255 /*
256 * DL_FLAG_AUTOREMOVE_SUPPLIER indicates that the link will be needed
257 * longer than for DL_FLAG_AUTOREMOVE_CONSUMER and setting them both
258 * together doesn't make sense, so prefer DL_FLAG_AUTOREMOVE_SUPPLIER.
259 */
260 if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
261 flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
262
244 list_for_each_entry(link, &supplier->links.consumers, s_node) { 263 list_for_each_entry(link, &supplier->links.consumers, s_node) {
245 if (link->consumer != consumer) 264 if (link->consumer != consumer)
246 continue; 265 continue;
@@ -254,12 +273,6 @@ struct device_link *device_link_add(struct device *consumer,
254 goto out; 273 goto out;
255 } 274 }
256 275
257 if (flags & DL_FLAG_AUTOREMOVE_CONSUMER)
258 link->flags |= DL_FLAG_AUTOREMOVE_CONSUMER;
259
260 if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
261 link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER;
262
263 if (flags & DL_FLAG_PM_RUNTIME) { 276 if (flags & DL_FLAG_PM_RUNTIME) {
264 if (!(link->flags & DL_FLAG_PM_RUNTIME)) { 277 if (!(link->flags & DL_FLAG_PM_RUNTIME)) {
265 device_link_rpm_prepare(consumer, supplier); 278 device_link_rpm_prepare(consumer, supplier);
@@ -269,7 +282,25 @@ struct device_link *device_link_add(struct device *consumer,
269 refcount_inc(&link->rpm_active); 282 refcount_inc(&link->rpm_active);
270 } 283 }
271 284
272 kref_get(&link->kref); 285 if (flags & DL_FLAG_STATELESS) {
286 kref_get(&link->kref);
287 goto out;
288 }
289
290 /*
291 * If the life time of the link following from the new flags is
292 * longer than indicated by the flags of the existing link,
293 * update the existing link to stay around longer.
294 */
295 if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) {
296 if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
297 link->flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
298 link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER;
299 }
300 } else if (!(flags & DL_FLAG_AUTOREMOVE_CONSUMER)) {
301 link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER |
302 DL_FLAG_AUTOREMOVE_SUPPLIER);
303 }
273 goto out; 304 goto out;
274 } 305 }
275 306
@@ -419,8 +450,16 @@ static void __device_link_del(struct kref *kref)
419} 450}
420#endif /* !CONFIG_SRCU */ 451#endif /* !CONFIG_SRCU */
421 452
453static void device_link_put_kref(struct device_link *link)
454{
455 if (link->flags & DL_FLAG_STATELESS)
456 kref_put(&link->kref, __device_link_del);
457 else
458 WARN(1, "Unable to drop a managed device link reference\n");
459}
460
422/** 461/**
423 * device_link_del - Delete a link between two devices. 462 * device_link_del - Delete a stateless link between two devices.
424 * @link: Device link to delete. 463 * @link: Device link to delete.
425 * 464 *
426 * The caller must ensure proper synchronization of this function with runtime 465 * The caller must ensure proper synchronization of this function with runtime
@@ -432,14 +471,14 @@ void device_link_del(struct device_link *link)
432{ 471{
433 device_links_write_lock(); 472 device_links_write_lock();
434 device_pm_lock(); 473 device_pm_lock();
435 kref_put(&link->kref, __device_link_del); 474 device_link_put_kref(link);
436 device_pm_unlock(); 475 device_pm_unlock();
437 device_links_write_unlock(); 476 device_links_write_unlock();
438} 477}
439EXPORT_SYMBOL_GPL(device_link_del); 478EXPORT_SYMBOL_GPL(device_link_del);
440 479
441/** 480/**
442 * device_link_remove - remove a link between two devices. 481 * device_link_remove - Delete a stateless link between two devices.
443 * @consumer: Consumer end of the link. 482 * @consumer: Consumer end of the link.
444 * @supplier: Supplier end of the link. 483 * @supplier: Supplier end of the link.
445 * 484 *
@@ -458,7 +497,7 @@ void device_link_remove(void *consumer, struct device *supplier)
458 497
459 list_for_each_entry(link, &supplier->links.consumers, s_node) { 498 list_for_each_entry(link, &supplier->links.consumers, s_node) {
460 if (link->consumer == consumer) { 499 if (link->consumer == consumer) {
461 kref_put(&link->kref, __device_link_del); 500 device_link_put_kref(link);
462 break; 501 break;
463 } 502 }
464 } 503 }