/* * drivers/base/core.c - core driver model code (device registration, etc) * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (c) 2006 Novell, Inc. * * This file is released under the GPLv2 * */ #include <linux/device.h>#include <linux/err.h>#include <linux/fwnode.h>#include <linux/init.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/kdev_t.h>#include <linux/notifier.h>#include <linux/of.h>#include <linux/of_device.h>#include <linux/genhd.h>#include <linux/kallsyms.h>#include <linux/mutex.h>#include <linux/pm_runtime.h>#include <linux/netdevice.h>#include <linux/sched/signal.h>#include <linux/sysfs.h> #include "base.h"#include "power/power.h" #ifdef CONFIG_SYSFS_DEPRECATED#ifdef CONFIG_SYSFS_DEPRECATED_V2long sysfs_deprecated = 1;#elselong sysfs_deprecated = 0;#endifstatic int __init sysfs_deprecated_setup(char *arg){ return kstrtol(arg, 10, &sysfs_deprecated);}early_param("sysfs.deprecated", sysfs_deprecated_setup);#endif /* Device links support. */ #ifdef CONFIG_SRCUstatic DEFINE_MUTEX(device_links_lock);DEFINE_STATIC_SRCU(device_links_srcu); static inline void device_links_write_lock(void){ mutex_lock(&device_links_lock);} static inline void device_links_write_unlock(void){ mutex_unlock(&device_links_lock);} int device_links_read_lock(void){ return srcu_read_lock(&device_links_srcu);} void device_links_read_unlock(int idx){ srcu_read_unlock(&device_links_srcu, idx);}#else /* !CONFIG_SRCU */static DECLARE_RWSEM(device_links_lock); static inline void device_links_write_lock(void){ down_write(&device_links_lock);} static inline void device_links_write_unlock(void){ up_write(&device_links_lock);} int device_links_read_lock(void){ down_read(&device_links_lock); return 0;} void device_links_read_unlock(int not_used){ up_read(&device_links_lock);}#endif /* !CONFIG_SRCU */ /** * device_is_dependent - Check if one device depends on another one * @dev: Device to check dependencies for. * @target: Device to check against. * * Check if @target depends on @dev or any device dependent on it (its child or * its consumer etc). Return 1 if that is the case or 0 otherwise. */static int device_is_dependent(struct device *dev, void *target){ struct device_link *link; int ret; if (WARN_ON(dev == target)) return 1; ret = device_for_each_child(dev, target, device_is_dependent); if (ret) return ret; list_for_each_entry(link, &dev->links.consumers, s_node) { if (WARN_ON(link->consumer == target)) return 1; ret = device_is_dependent(link->consumer, target); if (ret) break; } return ret;} static int device_reorder_to_tail(struct device *dev, void *not_used){ struct device_link *link; /* * Devices that have not been registered yet will be put to the ends * of the lists during the registration, so skip them here. */ if (device_is_registered(dev)) devices_kset_move_last(dev); if (device_pm_initialized(dev)) device_pm_move_last(dev); device_for_each_child(dev, NULL, device_reorder_to_tail); list_for_each_entry(link, &dev->links.consumers, s_node) device_reorder_to_tail(link->consumer, NULL); return 0;} /** * device_link_add - Create a link between two devices. * @consumer: Consumer end of the link. * @supplier: Supplier end of the link. * @flags: Link flags. * * The caller is responsible for the proper synchronization of the link creation * with runtime PM. First, setting the DL_FLAG_PM_RUNTIME flag will cause the * runtime PM framework to take the link into account. Second, if the * DL_FLAG_RPM_ACTIVE flag is set in addition to it, the supplier devices will * be forced into the active metastate and reference-counted upon the creation * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be * ignored. * * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically * when the consumer device driver unbinds from it. The combination of both * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL * to be returned. * * A side effect of the link creation is re-ordering of dpm_list and the * devices_kset list by moving the consumer device and all devices depending * on it to the ends of these lists (that does not happen to devices that have * not been registered when this function is called). * * The supplier device is required to be registered when this function is called * and NULL will be returned if that is not the case. The consumer device need * not be registered, however. */struct device_link *device_link_add(struct device *consumer, struct device *supplier, u32 flags){ struct device_link *link; if (!consumer || !supplier || ((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_AUTOREMOVE))) return NULL; device_links_write_lock(); device_pm_lock(); /* * If the supplier has not been fully registered yet or there is a * reverse dependency between the consumer and the supplier already in * the graph, return NULL. */ if (!device_pm_initialized(supplier) || device_is_dependent(consumer, supplier)) { link = NULL; goto out; } list_for_each_entry(link, &supplier->links.consumers, s_node) if (link->consumer == consumer) goto out; link = kzalloc(sizeof(*link), GFP_KERNEL); if (!link) goto out; if (flags & DL_FLAG_PM_RUNTIME) { if (flags & DL_FLAG_RPM_ACTIVE) { if (pm_runtime_get_sync(supplier) < 0) { pm_runtime_put_noidle(supplier); kfree(link); link = NULL; goto out; } link->rpm_active = true; } pm_runtime_new_link(consumer); } get_device(supplier); link->supplier = supplier; INIT_LIST_HEAD(&link->s_node); get_device(consumer); link->consumer = consumer; INIT_LIST_HEAD(&link->c_node); link->flags = flags; /* Determine the initial link state. */ if (flags & DL_FLAG_STATELESS) { link->status = DL_STATE_NONE; } else { switch (supplier->links.status) { case DL_DEV_DRIVER_BOUND: switch (consumer->links.status) { case DL_DEV_PROBING: /* * Balance the decrementation of the supplier's * runtime PM usage counter after consumer probe * in driver_probe_device(). */ if (flags & DL_FLAG_PM_RUNTIME) pm_runtime_get_sync(supplier); link->status = DL_STATE_CONSUMER_PROBE; break; case DL_DEV_DRIVER_BOUND: link->status = DL_STATE_ACTIVE; break; default: link->status = DL_STATE_AVAILABLE; break; } break; case DL_DEV_UNBINDING: link->status = DL_STATE_SUPPLIER_UNBIND; break; default: link->status = DL_STATE_DORMANT; break; } } /* * Move the consumer and all of the devices depending on it to the end * of dpm_list and the devices_kset list. * * It is necessary to hold dpm_list locked throughout all that or else * we may end up suspending with a wrong ordering of it. */ device_reorder_to_tail(consumer, NULL); list_add_tail_rcu(&link->s_node, &supplier->links.consumers); list_add_tail_rcu(&link->c_node, &consumer->links.suppliers); dev_info(consumer, "Linked as a consumer to %s\n", dev_name(supplier)); out: device_pm_unlock(); device_links_write_unlock(); return link;}EXPORT_SYMBOL_GPL(device_link_add); static void device_link_free(struct device_link *link){ put_device(link->consumer); put_device(link->supplier); kfree(link);} #ifdef CONFIG_SRCUstatic void __device_link_free_srcu(struct rcu_head *rhead){ device_link_free(container_of(rhead, struct device_link, rcu_head));} static void __device_link_del(struct device_link *link){ dev_info(link->consumer, "Dropping the link to %s\n", dev_name(link->supplier)); if (link->flags & DL_FLAG_PM_RUNTIME) pm_runtime_drop_link(link->consumer); list_del_rcu(&link->s_node); list_del_rcu(&link->c_node); call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);}#else /* !CONFIG_SRCU */static void __device_link_del(struct device_link *link){ dev_info(link->consumer, "Dropping the link to %s\n", dev_name(link->supplier)); list_del(&link->s_node); list_del(&link->c_node); device_link_free(link);}#endif /* !CONFIG_SRCU */ /** * device_link_del - Delete a link between two devices. * @link: Device link to delete. * * The caller must ensure proper synchronization of this function with runtime * PM. */void device_link_del(struct device_link *link){ device_links_write_lock(); device_pm_lock(); __device_link_del(link); device_pm_unlock(); device_links_write_unlock();}EXPORT_SYMBOL_GPL(device_link_del); static void device_links_missing_supplier(struct device *dev){ struct device_link *link; list_for_each_entry(link, &dev->links.suppliers, c_node) if (link->status == DL_STATE_CONSUMER_PROBE) WRITE_ONCE(link->status, DL_STATE_AVAILABLE);} /** * device_links_check_suppliers - Check presence of supplier drivers. * @dev: Consumer device. * * Check links from this device to any suppliers. Walk the list of the device's * links to suppliers and see if all of them are available. If not, simply * return -EPROBE_DEFER. * * We need to guarantee that the supplier will not go away after the check has * been positive here. It only can go away in __device_release_driver() and * that function checks the device's links to consumers. This means we need to * mark the link as "consumer probe in progress" to make the supplier removal * wait for us to complete (or bad things may happen). * * Links with the DL_FLAG_STATELESS flag set are ignored. */int device_links_check_suppliers(struct device *dev){ struct device_link *link; int ret = 0; device_links_write_lock(); list_for_each_entry(link, &dev->links.suppliers, c_node) { if (link->flags & DL_FLAG_STATELESS) continue; if (link->status != DL_STATE_AVAILABLE) { device_links_missing_supplier(dev); ret = -EPROBE_DEFER; break; } WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE); } dev->links.status = DL_DEV_PROBING; device_links_write_unlock(); return ret;} /** * device_links_driver_bound - Update device links after probing its driver. * @dev: Device to update the links for. * * The probe has been successful, so update links from this device to any * consumers by changing their status to "available". * * Also change the status of @dev's links to suppliers to "active". * * Links with the DL_FLAG_STATELESS flag set are ignored. */void device_links_driver_bound(struct device *dev){ struct device_link *link; device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { if (link->flags & DL_FLAG_STATELESS) continue; WARN_ON(link->status != DL_STATE_DORMANT); WRITE_ONCE(link->status, DL_STATE_AVAILABLE); } list_for_each_entry(link, &dev->links.suppliers, c_node) { if (link->flags & DL_FLAG_STATELESS) continue; WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); WRITE_ONCE(link->status, DL_STATE_ACTIVE); } dev->links.status = DL_DEV_DRIVER_BOUND; device_links_write_unlock();} /** * __device_links_no_driver - Update links of a device without a driver. * @dev: Device without a drvier. * * Delete all non-persistent links from this device to any suppliers. * * Persistent links stay around, but their status is changed to "available", * unless they already are in the "supplier unbind in progress" state in which * case they need not be updated. * * Links with the DL_FLAG_STATELESS flag set are ignored. */static void __device_links_no_driver(struct device *dev){ struct device_link *link, *ln; list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { if (link->flags & DL_FLAG_STATELESS) continue; if (link->flags & DL_FLAG_AUTOREMOVE) __device_link_del(link); else if (link->status != DL_STATE_SUPPLIER_UNBIND) WRITE_ONCE(link->status, DL_STATE_AVAILABLE); } dev->links.status = DL_DEV_NO_DRIVER;} void device_links_no_driver(struct device *dev){ device_links_write_lock(); __device_links_no_driver(dev); device_links_write_unlock();} /** * device_links_driver_cleanup - Update links after driver removal. * @dev: Device whose driver has just gone away. * * Update links to consumers for @dev by changing their status to "dormant" and * invoke %__device_links_no_driver() to update links to suppliers for it as * appropriate. * * Links with the DL_FLAG_STATELESS flag set are ignored. */void device_links_driver_cleanup(struct device *dev){ struct device_link *link; device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { if (link->flags & DL_FLAG_STATELESS) continue; WARN_ON(link->flags & DL_FLAG_AUTOREMOVE); WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); WRITE_ONCE(link->status, DL_STATE_DORMANT); } __device_links_no_driver(dev); device_links_write_unlock();} /** * device_links_busy - Check if there are any busy links to consumers. * @dev: Device to check. * * Check each consumer of the device and return 'true' if its link's status * is one of "consumer probe" or "active" (meaning that the given consumer is * probing right now or its driver is present). Otherwise, change the link * state to "supplier unbind" to prevent the consumer from being probed * successfully going forward.Lines 1–500 of 2903. Load more
/* * drivers/base/core.c - core driver model code (device registration, etc) * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (c) 2006 Novell, Inc. * * This file is released under the GPLv2 * */ #include <linux/device.h> #include <linux/err.h> #include <linux/fwnode.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/kdev_t.h> #include <linux/notifier.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/genhd.h> #include <linux/kallsyms.h> #include <linux/mutex.h> #include <linux/pm_runtime.h> #include <linux/netdevice.h> #include <linux/sched/signal.h> #include <linux/sysfs.h> #include "base.h" #include "power/power.h" #ifdef CONFIG_SYSFS_DEPRECATED #ifdef CONFIG_SYSFS_DEPRECATED_V2 long sysfs_deprecated = 1; #else long sysfs_deprecated = 0; #endif static int __init sysfs_deprecated_setup(char *arg) { return kstrtol(arg, 10, &sysfs_deprecated); } early_param("sysfs.deprecated", sysfs_deprecated_setup); #endif /* Device links support. */ #ifdef CONFIG_SRCU static DEFINE_MUTEX(device_links_lock); DEFINE_STATIC_SRCU(device_links_srcu); static inline void device_links_write_lock(void) { mutex_lock(&device_links_lock); } static inline void device_links_write_unlock(void) { mutex_unlock(&device_links_lock); } int device_links_read_lock(void) { return srcu_read_lock(&device_links_srcu); } void device_links_read_unlock(int idx) { srcu_read_unlock(&device_links_srcu, idx); } #else /* !CONFIG_SRCU */ static DECLARE_RWSEM(device_links_lock); static inline void device_links_write_lock(void) { down_write(&device_links_lock); } static inline void device_links_write_unlock(void) { up_write(&device_links_lock); } int device_links_read_lock(void) { down_read(&device_links_lock); return 0; } void device_links_read_unlock(int not_used) { up_read(&device_links_lock); } #endif /* !CONFIG_SRCU */ /** * device_is_dependent - Check if one device depends on another one * @dev: Device to check dependencies for. * @target: Device to check against. * * Check if @target depends on @dev or any device dependent on it (its child or * its consumer etc). Return 1 if that is the case or 0 otherwise. */ static int device_is_dependent(struct device *dev, void *target) { struct device_link *link; int ret; if (WARN_ON(dev == target)) return 1; ret = device_for_each_child(dev, target, device_is_dependent); if (ret) return ret; list_for_each_entry(link, &dev->links.consumers, s_node) { if (WARN_ON(link->consumer == target)) return 1; ret = device_is_dependent(link->consumer, target); if (ret) break; } return ret; } static int device_reorder_to_tail(struct device *dev, void *not_used) { struct device_link *link; /* * Devices that have not been registered yet will be put to the ends * of the lists during the registration, so skip them here. */ if (device_is_registered(dev)) devices_kset_move_last(dev); if (device_pm_initialized(dev)) device_pm_move_last(dev); device_for_each_child(dev, NULL, device_reorder_to_tail); list_for_each_entry(link, &dev->links.consumers, s_node) device_reorder_to_tail(link->consumer, NULL); return 0; } /** * device_link_add - Create a link between two devices. * @consumer: Consumer end of the link. * @supplier: Supplier end of the link. * @flags: Link flags. * * The caller is responsible for the proper synchronization of the link creation * with runtime PM. First, setting the DL_FLAG_PM_RUNTIME flag will cause the * runtime PM framework to take the link into account. Second, if the * DL_FLAG_RPM_ACTIVE flag is set in addition to it, the supplier devices will * be forced into the active metastate and reference-counted upon the creation * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be * ignored. * * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically * when the consumer device driver unbinds from it. The combination of both * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL * to be returned. * * A side effect of the link creation is re-ordering of dpm_list and the * devices_kset list by moving the consumer device and all devices depending * on it to the ends of these lists (that does not happen to devices that have * not been registered when this function is called). * * The supplier device is required to be registered when this function is called * and NULL will be returned if that is not the case. The consumer device need * not be registered, however. */ struct device_link *device_link_add(struct device *consumer, struct device *supplier, u32 flags) { struct device_link *link; if (!consumer || !supplier || ((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_AUTOREMOVE))) return NULL; device_links_write_lock(); device_pm_lock(); /* * If the supplier has not been fully registered yet or there is a * reverse dependency between the consumer and the supplier already in * the graph, return NULL. */ if (!device_pm_initialized(supplier) || device_is_dependent(consumer, supplier)) { link = NULL; goto out; } list_for_each_entry(link, &supplier->links.consumers, s_node) if (link->consumer == consumer) goto out; link = kzalloc(sizeof(*link), GFP_KERNEL); if (!link) goto out; if (flags & DL_FLAG_PM_RUNTIME) { if (flags & DL_FLAG_RPM_ACTIVE) { if (pm_runtime_get_sync(supplier) < 0) { pm_runtime_put_noidle(supplier); kfree(link); link = NULL; goto out; } link->rpm_active = true; } pm_runtime_new_link(consumer); } get_device(supplier); link->supplier = supplier; INIT_LIST_HEAD(&link->s_node); get_device(consumer); link->consumer = consumer; INIT_LIST_HEAD(&link->c_node); link->flags = flags; /* Determine the initial link state. */ if (flags & DL_FLAG_STATELESS) { link->status = DL_STATE_NONE; } else { switch (supplier->links.status) { case DL_DEV_DRIVER_BOUND: switch (consumer->links.status) { case DL_DEV_PROBING: /* * Balance the decrementation of the supplier's * runtime PM usage counter after consumer probe * in driver_probe_device(). */ if (flags & DL_FLAG_PM_RUNTIME) pm_runtime_get_sync(supplier); link->status = DL_STATE_CONSUMER_PROBE; break; case DL_DEV_DRIVER_BOUND: link->status = DL_STATE_ACTIVE; break; default: link->status = DL_STATE_AVAILABLE; break; } break; case DL_DEV_UNBINDING: link->status = DL_STATE_SUPPLIER_UNBIND; break; default: link->status = DL_STATE_DORMANT; break; } } /* * Move the consumer and all of the devices depending on it to the end * of dpm_list and the devices_kset list. * * It is necessary to hold dpm_list locked throughout all that or else * we may end up suspending with a wrong ordering of it. */ device_reorder_to_tail(consumer, NULL); list_add_tail_rcu(&link->s_node, &supplier->links.consumers); list_add_tail_rcu(&link->c_node, &consumer->links.suppliers); dev_info(consumer, "Linked as a consumer to %s\n", dev_name(supplier)); out: device_pm_unlock(); device_links_write_unlock(); return link; } EXPORT_SYMBOL_GPL(device_link_add); static void device_link_free(struct device_link *link) { put_device(link->consumer); put_device(link->supplier); kfree(link); } #ifdef CONFIG_SRCU static void __device_link_free_srcu(struct rcu_head *rhead) { device_link_free(container_of(rhead, struct device_link, rcu_head)); } static void __device_link_del(struct device_link *link) { dev_info(link->consumer, "Dropping the link to %s\n", dev_name(link->supplier)); if (link->flags & DL_FLAG_PM_RUNTIME) pm_runtime_drop_link(link->consumer); list_del_rcu(&link->s_node); list_del_rcu(&link->c_node); call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); } #else /* !CONFIG_SRCU */ static void __device_link_del(struct device_link *link) { dev_info(link->consumer, "Dropping the link to %s\n", dev_name(link->supplier)); list_del(&link->s_node); list_del(&link->c_node); device_link_free(link); } #endif /* !CONFIG_SRCU */ /** * device_link_del - Delete a link between two devices. * @link: Device link to delete. * * The caller must ensure proper synchronization of this function with runtime * PM. */ void device_link_del(struct device_link *link) { device_links_write_lock(); device_pm_lock(); __device_link_del(link); device_pm_unlock(); device_links_write_unlock(); } EXPORT_SYMBOL_GPL(device_link_del); static void device_links_missing_supplier(struct device *dev) { struct device_link *link; list_for_each_entry(link, &dev->links.suppliers, c_node) if (link->status == DL_STATE_CONSUMER_PROBE) WRITE_ONCE(link->status, DL_STATE_AVAILABLE); } /** * device_links_check_suppliers - Check presence of supplier drivers. * @dev: Consumer device. * * Check links from this device to any suppliers. Walk the list of the device's * links to suppliers and see if all of them are available. If not, simply * return -EPROBE_DEFER. * * We need to guarantee that the supplier will not go away after the check has * been positive here. It only can go away in __device_release_driver() and * that function checks the device's links to consumers. This means we need to * mark the link as "consumer probe in progress" to make the supplier removal * wait for us to complete (or bad things may happen). * * Links with the DL_FLAG_STATELESS flag set are ignored. */ int device_links_check_suppliers(struct device *dev) { struct device_link *link; int ret = 0; device_links_write_lock(); list_for_each_entry(link, &dev->links.suppliers, c_node) { if (link->flags & DL_FLAG_STATELESS) continue; if (link->status != DL_STATE_AVAILABLE) { device_links_missing_supplier(dev); ret = -EPROBE_DEFER; break; } WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE); } dev->links.status = DL_DEV_PROBING; device_links_write_unlock(); return ret; } /** * device_links_driver_bound - Update device links after probing its driver. * @dev: Device to update the links for. * * The probe has been successful, so update links from this device to any * consumers by changing their status to "available". * * Also change the status of @dev's links to suppliers to "active". * * Links with the DL_FLAG_STATELESS flag set are ignored. */ void device_links_driver_bound(struct device *dev) { struct device_link *link; device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { if (link->flags & DL_FLAG_STATELESS) continue; WARN_ON(link->status != DL_STATE_DORMANT); WRITE_ONCE(link->status, DL_STATE_AVAILABLE); } list_for_each_entry(link, &dev->links.suppliers, c_node) { if (link->flags & DL_FLAG_STATELESS) continue; WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); WRITE_ONCE(link->status, DL_STATE_ACTIVE); } dev->links.status = DL_DEV_DRIVER_BOUND; device_links_write_unlock(); } /** * __device_links_no_driver - Update links of a device without a driver. * @dev: Device without a drvier. * * Delete all non-persistent links from this device to any suppliers. * * Persistent links stay around, but their status is changed to "available", * unless they already are in the "supplier unbind in progress" state in which * case they need not be updated. * * Links with the DL_FLAG_STATELESS flag set are ignored. */ static void __device_links_no_driver(struct device *dev) { struct device_link *link, *ln; list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { if (link->flags & DL_FLAG_STATELESS) continue; if (link->flags & DL_FLAG_AUTOREMOVE) __device_link_del(link); else if (link->status != DL_STATE_SUPPLIER_UNBIND) WRITE_ONCE(link->status, DL_STATE_AVAILABLE); } dev->links.status = DL_DEV_NO_DRIVER; } void device_links_no_driver(struct device *dev) { device_links_write_lock(); __device_links_no_driver(dev); device_links_write_unlock(); } /** * device_links_driver_cleanup - Update links after driver removal. * @dev: Device whose driver has just gone away. * * Update links to consumers for @dev by changing their status to "dormant" and * invoke %__device_links_no_driver() to update links to suppliers for it as * appropriate. * * Links with the DL_FLAG_STATELESS flag set are ignored. */ void device_links_driver_cleanup(struct device *dev) { struct device_link *link; device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { if (link->flags & DL_FLAG_STATELESS) continue; WARN_ON(link->flags & DL_FLAG_AUTOREMOVE); WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); WRITE_ONCE(link->status, DL_STATE_DORMANT); } __device_links_no_driver(dev); device_links_write_unlock(); } /** * device_links_busy - Check if there are any busy links to consumers. * @dev: Device to check. * * Check each consumer of the device and return 'true' if its link's status * is one of "consumer probe" or "active" (meaning that the given consumer is * probing right now or its driver is present). Otherwise, change the link * state to "supplier unbind" to prevent the consumer from being probed * successfully going forward.