3169 lines · 81.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * 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. */ #include <linux/acpi.h>#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/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 (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 (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_pm_move_to_tail - Move set of devices to the end of device lists * @dev: Device to move * * This is a device_reorder_to_tail() wrapper taking the requisite locks. * * It moves the @dev along with all of its children and all of its consumers * to the ends of the device_kset and dpm_list, recursively. */void device_pm_move_to_tail(struct device *dev){	int idx; 	idx = device_links_read_lock();	device_pm_lock();	device_reorder_to_tail(dev, NULL);	device_pm_unlock();	device_links_read_unlock(idx);} /** * 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_CONSUMER is set, the link will be removed * automatically when the consumer device driver unbinds from it. * The combination of both DL_FLAG_AUTOREMOVE_CONSUMER 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_CONSUMER)))		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) {			kref_get(&link->kref);			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);		/*		 * If the link is being added by the consumer driver at probe		 * time, balance the decrementation of the supplier's runtime PM		 * usage counter after consumer probe in driver_probe_device().		 */		if (consumer->links.status == DL_DEV_PROBING)			pm_runtime_get_noresume(supplier);	}	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;	kref_init(&link->kref); 	/* 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:				/*				 * Some callers expect the link creation during				 * consumer driver probe to resume the supplier				 * even without DL_FLAG_RPM_ACTIVE.				 */				if (flags & DL_FLAG_PM_RUNTIME)					pm_runtime_resume(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 kref *kref){	struct device_link *link = container_of(kref, struct device_link, kref); 	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 kref *kref){	struct device_link *link = container_of(kref, struct device_link, kref); 	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(&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.  If the link was added multiple times, it needs to be deleted as often. * Care is required for hotplugged devices:  Their links are purged on removal * and calling device_link_del() is then no longer allowed. */void device_link_del(struct device_link *link){	device_links_write_lock();	device_pm_lock();	kref_put(&link->kref, __device_link_del);	device_pm_unlock();	device_links_write_unlock();}EXPORT_SYMBOL_GPL(device_link_del); /** * device_link_remove - remove a link between two devices. * @consumer: Consumer end of the link. * @supplier: Supplier end of the link. * * The caller must ensure proper synchronization of this function with runtime * PM. */void device_link_remove(void *consumer, struct device *supplier){	struct device_link *link; 	if (WARN_ON(consumer == supplier))		return; 	device_links_write_lock();	device_pm_lock(); 	list_for_each_entry(link, &supplier->links.consumers, s_node) {		if (link->consumer == consumer) {			kref_put(&link->kref, __device_link_del);			break;		}	} 	device_pm_unlock();	device_links_write_unlock();}EXPORT_SYMBOL_GPL(device_link_remove); 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",

Lines 1–500 of 3169.