18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * drivers/base/core.c - core driver model code (device registration, etc)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2002-3 Patrick Mochel
68c2ecf20Sopenharmony_ci * Copyright (c) 2002-3 Open Source Development Labs
78c2ecf20Sopenharmony_ci * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de>
88c2ecf20Sopenharmony_ci * Copyright (c) 2006 Novell, Inc.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/acpi.h>
128c2ecf20Sopenharmony_ci#include <linux/cpufreq.h>
138c2ecf20Sopenharmony_ci#include <linux/device.h>
148c2ecf20Sopenharmony_ci#include <linux/err.h>
158c2ecf20Sopenharmony_ci#include <linux/fwnode.h>
168c2ecf20Sopenharmony_ci#include <linux/init.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/string.h>
208c2ecf20Sopenharmony_ci#include <linux/kdev_t.h>
218c2ecf20Sopenharmony_ci#include <linux/notifier.h>
228c2ecf20Sopenharmony_ci#include <linux/of.h>
238c2ecf20Sopenharmony_ci#include <linux/of_device.h>
248c2ecf20Sopenharmony_ci#include <linux/genhd.h>
258c2ecf20Sopenharmony_ci#include <linux/mutex.h>
268c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
278c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
288c2ecf20Sopenharmony_ci#include <linux/rcupdate.h>
298c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
308c2ecf20Sopenharmony_ci#include <linux/sched/mm.h>
318c2ecf20Sopenharmony_ci#include <linux/sysfs.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "base.h"
348c2ecf20Sopenharmony_ci#include "power/power.h"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#ifdef CONFIG_SYSFS_DEPRECATED
378c2ecf20Sopenharmony_ci#ifdef CONFIG_SYSFS_DEPRECATED_V2
388c2ecf20Sopenharmony_cilong sysfs_deprecated = 1;
398c2ecf20Sopenharmony_ci#else
408c2ecf20Sopenharmony_cilong sysfs_deprecated = 0;
418c2ecf20Sopenharmony_ci#endif
428c2ecf20Sopenharmony_cistatic int __init sysfs_deprecated_setup(char *arg)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	return kstrtol(arg, 10, &sysfs_deprecated);
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ciearly_param("sysfs.deprecated", sysfs_deprecated_setup);
478c2ecf20Sopenharmony_ci#endif
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* Device links support. */
508c2ecf20Sopenharmony_cistatic LIST_HEAD(wait_for_suppliers);
518c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(wfs_lock);
528c2ecf20Sopenharmony_cistatic LIST_HEAD(deferred_sync);
538c2ecf20Sopenharmony_cistatic unsigned int defer_sync_state_count = 1;
548c2ecf20Sopenharmony_cistatic unsigned int defer_fw_devlink_count;
558c2ecf20Sopenharmony_cistatic LIST_HEAD(deferred_fw_devlink);
568c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(defer_fw_devlink_lock);
578c2ecf20Sopenharmony_cistatic bool fw_devlink_is_permissive(void);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#ifdef CONFIG_SRCU
608c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(device_links_lock);
618c2ecf20Sopenharmony_ciDEFINE_STATIC_SRCU(device_links_srcu);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic inline void device_links_write_lock(void)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	mutex_lock(&device_links_lock);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic inline void device_links_write_unlock(void)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	mutex_unlock(&device_links_lock);
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciint device_links_read_lock(void) __acquires(&device_links_srcu)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	return srcu_read_lock(&device_links_srcu);
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_civoid device_links_read_unlock(int idx) __releases(&device_links_srcu)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	srcu_read_unlock(&device_links_srcu, idx);
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciint device_links_read_lock_held(void)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	return srcu_read_lock_held(&device_links_srcu);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic void device_link_synchronize_removal(void)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	synchronize_srcu(&device_links_srcu);
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci#else /* !CONFIG_SRCU */
938c2ecf20Sopenharmony_cistatic DECLARE_RWSEM(device_links_lock);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic inline void device_links_write_lock(void)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	down_write(&device_links_lock);
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic inline void device_links_write_unlock(void)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	up_write(&device_links_lock);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciint device_links_read_lock(void)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	down_read(&device_links_lock);
1088c2ecf20Sopenharmony_ci	return 0;
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_civoid device_links_read_unlock(int not_used)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	up_read(&device_links_lock);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_LOCK_ALLOC
1178c2ecf20Sopenharmony_ciint device_links_read_lock_held(void)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	return lockdep_is_held(&device_links_lock);
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci#endif
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic inline void device_link_synchronize_removal(void)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci#endif /* !CONFIG_SRCU */
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic bool device_is_ancestor(struct device *dev, struct device *target)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	while (target->parent) {
1318c2ecf20Sopenharmony_ci		target = target->parent;
1328c2ecf20Sopenharmony_ci		if (dev == target)
1338c2ecf20Sopenharmony_ci			return true;
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci	return false;
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci/**
1398c2ecf20Sopenharmony_ci * device_is_dependent - Check if one device depends on another one
1408c2ecf20Sopenharmony_ci * @dev: Device to check dependencies for.
1418c2ecf20Sopenharmony_ci * @target: Device to check against.
1428c2ecf20Sopenharmony_ci *
1438c2ecf20Sopenharmony_ci * Check if @target depends on @dev or any device dependent on it (its child or
1448c2ecf20Sopenharmony_ci * its consumer etc).  Return 1 if that is the case or 0 otherwise.
1458c2ecf20Sopenharmony_ci */
1468c2ecf20Sopenharmony_ciint device_is_dependent(struct device *dev, void *target)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct device_link *link;
1498c2ecf20Sopenharmony_ci	int ret;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	/*
1528c2ecf20Sopenharmony_ci	 * The "ancestors" check is needed to catch the case when the target
1538c2ecf20Sopenharmony_ci	 * device has not been completely initialized yet and it is still
1548c2ecf20Sopenharmony_ci	 * missing from the list of children of its parent device.
1558c2ecf20Sopenharmony_ci	 */
1568c2ecf20Sopenharmony_ci	if (dev == target || device_is_ancestor(dev, target))
1578c2ecf20Sopenharmony_ci		return 1;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	ret = device_for_each_child(dev, target, device_is_dependent);
1608c2ecf20Sopenharmony_ci	if (ret)
1618c2ecf20Sopenharmony_ci		return ret;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.consumers, s_node) {
1648c2ecf20Sopenharmony_ci		if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED))
1658c2ecf20Sopenharmony_ci			continue;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		if (link->consumer == target)
1688c2ecf20Sopenharmony_ci			return 1;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci		ret = device_is_dependent(link->consumer, target);
1718c2ecf20Sopenharmony_ci		if (ret)
1728c2ecf20Sopenharmony_ci			break;
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci	return ret;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic void device_link_init_status(struct device_link *link,
1788c2ecf20Sopenharmony_ci				    struct device *consumer,
1798c2ecf20Sopenharmony_ci				    struct device *supplier)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	switch (supplier->links.status) {
1828c2ecf20Sopenharmony_ci	case DL_DEV_PROBING:
1838c2ecf20Sopenharmony_ci		switch (consumer->links.status) {
1848c2ecf20Sopenharmony_ci		case DL_DEV_PROBING:
1858c2ecf20Sopenharmony_ci			/*
1868c2ecf20Sopenharmony_ci			 * A consumer driver can create a link to a supplier
1878c2ecf20Sopenharmony_ci			 * that has not completed its probing yet as long as it
1888c2ecf20Sopenharmony_ci			 * knows that the supplier is already functional (for
1898c2ecf20Sopenharmony_ci			 * example, it has just acquired some resources from the
1908c2ecf20Sopenharmony_ci			 * supplier).
1918c2ecf20Sopenharmony_ci			 */
1928c2ecf20Sopenharmony_ci			link->status = DL_STATE_CONSUMER_PROBE;
1938c2ecf20Sopenharmony_ci			break;
1948c2ecf20Sopenharmony_ci		default:
1958c2ecf20Sopenharmony_ci			link->status = DL_STATE_DORMANT;
1968c2ecf20Sopenharmony_ci			break;
1978c2ecf20Sopenharmony_ci		}
1988c2ecf20Sopenharmony_ci		break;
1998c2ecf20Sopenharmony_ci	case DL_DEV_DRIVER_BOUND:
2008c2ecf20Sopenharmony_ci		switch (consumer->links.status) {
2018c2ecf20Sopenharmony_ci		case DL_DEV_PROBING:
2028c2ecf20Sopenharmony_ci			link->status = DL_STATE_CONSUMER_PROBE;
2038c2ecf20Sopenharmony_ci			break;
2048c2ecf20Sopenharmony_ci		case DL_DEV_DRIVER_BOUND:
2058c2ecf20Sopenharmony_ci			link->status = DL_STATE_ACTIVE;
2068c2ecf20Sopenharmony_ci			break;
2078c2ecf20Sopenharmony_ci		default:
2088c2ecf20Sopenharmony_ci			link->status = DL_STATE_AVAILABLE;
2098c2ecf20Sopenharmony_ci			break;
2108c2ecf20Sopenharmony_ci		}
2118c2ecf20Sopenharmony_ci		break;
2128c2ecf20Sopenharmony_ci	case DL_DEV_UNBINDING:
2138c2ecf20Sopenharmony_ci		link->status = DL_STATE_SUPPLIER_UNBIND;
2148c2ecf20Sopenharmony_ci		break;
2158c2ecf20Sopenharmony_ci	default:
2168c2ecf20Sopenharmony_ci		link->status = DL_STATE_DORMANT;
2178c2ecf20Sopenharmony_ci		break;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic int device_reorder_to_tail(struct device *dev, void *not_used)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	struct device_link *link;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	/*
2268c2ecf20Sopenharmony_ci	 * Devices that have not been registered yet will be put to the ends
2278c2ecf20Sopenharmony_ci	 * of the lists during the registration, so skip them here.
2288c2ecf20Sopenharmony_ci	 */
2298c2ecf20Sopenharmony_ci	if (device_is_registered(dev))
2308c2ecf20Sopenharmony_ci		devices_kset_move_last(dev);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	if (device_pm_initialized(dev))
2338c2ecf20Sopenharmony_ci		device_pm_move_last(dev);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	device_for_each_child(dev, NULL, device_reorder_to_tail);
2368c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.consumers, s_node) {
2378c2ecf20Sopenharmony_ci		if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED))
2388c2ecf20Sopenharmony_ci			continue;
2398c2ecf20Sopenharmony_ci		device_reorder_to_tail(link->consumer, NULL);
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	return 0;
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci/**
2468c2ecf20Sopenharmony_ci * device_pm_move_to_tail - Move set of devices to the end of device lists
2478c2ecf20Sopenharmony_ci * @dev: Device to move
2488c2ecf20Sopenharmony_ci *
2498c2ecf20Sopenharmony_ci * This is a device_reorder_to_tail() wrapper taking the requisite locks.
2508c2ecf20Sopenharmony_ci *
2518c2ecf20Sopenharmony_ci * It moves the @dev along with all of its children and all of its consumers
2528c2ecf20Sopenharmony_ci * to the ends of the device_kset and dpm_list, recursively.
2538c2ecf20Sopenharmony_ci */
2548c2ecf20Sopenharmony_civoid device_pm_move_to_tail(struct device *dev)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	int idx;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	idx = device_links_read_lock();
2598c2ecf20Sopenharmony_ci	device_pm_lock();
2608c2ecf20Sopenharmony_ci	device_reorder_to_tail(dev, NULL);
2618c2ecf20Sopenharmony_ci	device_pm_unlock();
2628c2ecf20Sopenharmony_ci	device_links_read_unlock(idx);
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci#define to_devlink(dev)	container_of((dev), struct device_link, link_dev)
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cistatic ssize_t status_show(struct device *dev,
2688c2ecf20Sopenharmony_ci			   struct device_attribute *attr, char *buf)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	const char *output;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	switch (to_devlink(dev)->status) {
2738c2ecf20Sopenharmony_ci	case DL_STATE_NONE:
2748c2ecf20Sopenharmony_ci		output = "not tracked";
2758c2ecf20Sopenharmony_ci		break;
2768c2ecf20Sopenharmony_ci	case DL_STATE_DORMANT:
2778c2ecf20Sopenharmony_ci		output = "dormant";
2788c2ecf20Sopenharmony_ci		break;
2798c2ecf20Sopenharmony_ci	case DL_STATE_AVAILABLE:
2808c2ecf20Sopenharmony_ci		output = "available";
2818c2ecf20Sopenharmony_ci		break;
2828c2ecf20Sopenharmony_ci	case DL_STATE_CONSUMER_PROBE:
2838c2ecf20Sopenharmony_ci		output = "consumer probing";
2848c2ecf20Sopenharmony_ci		break;
2858c2ecf20Sopenharmony_ci	case DL_STATE_ACTIVE:
2868c2ecf20Sopenharmony_ci		output = "active";
2878c2ecf20Sopenharmony_ci		break;
2888c2ecf20Sopenharmony_ci	case DL_STATE_SUPPLIER_UNBIND:
2898c2ecf20Sopenharmony_ci		output = "supplier unbinding";
2908c2ecf20Sopenharmony_ci		break;
2918c2ecf20Sopenharmony_ci	default:
2928c2ecf20Sopenharmony_ci		output = "unknown";
2938c2ecf20Sopenharmony_ci		break;
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%s\n", output);
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(status);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic ssize_t auto_remove_on_show(struct device *dev,
3018c2ecf20Sopenharmony_ci				   struct device_attribute *attr, char *buf)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	struct device_link *link = to_devlink(dev);
3048c2ecf20Sopenharmony_ci	const char *output;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
3078c2ecf20Sopenharmony_ci		output = "supplier unbind";
3088c2ecf20Sopenharmony_ci	else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
3098c2ecf20Sopenharmony_ci		output = "consumer unbind";
3108c2ecf20Sopenharmony_ci	else
3118c2ecf20Sopenharmony_ci		output = "never";
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%s\n", output);
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(auto_remove_on);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic ssize_t runtime_pm_show(struct device *dev,
3188c2ecf20Sopenharmony_ci			       struct device_attribute *attr, char *buf)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	struct device_link *link = to_devlink(dev);
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME));
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(runtime_pm);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic ssize_t sync_state_only_show(struct device *dev,
3278c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct device_link *link = to_devlink(dev);
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%d\n",
3328c2ecf20Sopenharmony_ci			  !!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(sync_state_only);
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic struct attribute *devlink_attrs[] = {
3378c2ecf20Sopenharmony_ci	&dev_attr_status.attr,
3388c2ecf20Sopenharmony_ci	&dev_attr_auto_remove_on.attr,
3398c2ecf20Sopenharmony_ci	&dev_attr_runtime_pm.attr,
3408c2ecf20Sopenharmony_ci	&dev_attr_sync_state_only.attr,
3418c2ecf20Sopenharmony_ci	NULL,
3428c2ecf20Sopenharmony_ci};
3438c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(devlink);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic void device_link_release_fn(struct work_struct *work)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	struct device_link *link = container_of(work, struct device_link, rm_work);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	/* Ensure that all references to the link object have been dropped. */
3508c2ecf20Sopenharmony_ci	device_link_synchronize_removal();
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	pm_runtime_release_supplier(link);
3538c2ecf20Sopenharmony_ci	pm_request_idle(link->supplier);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	put_device(link->consumer);
3568c2ecf20Sopenharmony_ci	put_device(link->supplier);
3578c2ecf20Sopenharmony_ci	kfree(link);
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic void devlink_dev_release(struct device *dev)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	struct device_link *link = to_devlink(dev);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	INIT_WORK(&link->rm_work, device_link_release_fn);
3658c2ecf20Sopenharmony_ci	/*
3668c2ecf20Sopenharmony_ci	 * It may take a while to complete this work because of the SRCU
3678c2ecf20Sopenharmony_ci	 * synchronization in device_link_release_fn() and if the consumer or
3688c2ecf20Sopenharmony_ci	 * supplier devices get deleted when it runs, so put it into the "long"
3698c2ecf20Sopenharmony_ci	 * workqueue.
3708c2ecf20Sopenharmony_ci	 */
3718c2ecf20Sopenharmony_ci	queue_work(system_long_wq, &link->rm_work);
3728c2ecf20Sopenharmony_ci}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic struct class devlink_class = {
3758c2ecf20Sopenharmony_ci	.name = "devlink",
3768c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
3778c2ecf20Sopenharmony_ci	.dev_groups = devlink_groups,
3788c2ecf20Sopenharmony_ci	.dev_release = devlink_dev_release,
3798c2ecf20Sopenharmony_ci};
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_cistatic int devlink_add_symlinks(struct device *dev,
3828c2ecf20Sopenharmony_ci				struct class_interface *class_intf)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	int ret;
3858c2ecf20Sopenharmony_ci	size_t len;
3868c2ecf20Sopenharmony_ci	struct device_link *link = to_devlink(dev);
3878c2ecf20Sopenharmony_ci	struct device *sup = link->supplier;
3888c2ecf20Sopenharmony_ci	struct device *con = link->consumer;
3898c2ecf20Sopenharmony_ci	char *buf;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
3928c2ecf20Sopenharmony_ci		  strlen(dev_bus_name(con)) + strlen(dev_name(con)));
3938c2ecf20Sopenharmony_ci	len += strlen(":");
3948c2ecf20Sopenharmony_ci	len += strlen("supplier:") + 1;
3958c2ecf20Sopenharmony_ci	buf = kzalloc(len, GFP_KERNEL);
3968c2ecf20Sopenharmony_ci	if (!buf)
3978c2ecf20Sopenharmony_ci		return -ENOMEM;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	ret = sysfs_create_link(&link->link_dev.kobj, &sup->kobj, "supplier");
4008c2ecf20Sopenharmony_ci	if (ret)
4018c2ecf20Sopenharmony_ci		goto out;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	ret = sysfs_create_link(&link->link_dev.kobj, &con->kobj, "consumer");
4048c2ecf20Sopenharmony_ci	if (ret)
4058c2ecf20Sopenharmony_ci		goto err_con;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
4088c2ecf20Sopenharmony_ci	ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf);
4098c2ecf20Sopenharmony_ci	if (ret)
4108c2ecf20Sopenharmony_ci		goto err_con_dev;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
4138c2ecf20Sopenharmony_ci	ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf);
4148c2ecf20Sopenharmony_ci	if (ret)
4158c2ecf20Sopenharmony_ci		goto err_sup_dev;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	goto out;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cierr_sup_dev:
4208c2ecf20Sopenharmony_ci	snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
4218c2ecf20Sopenharmony_ci	sysfs_remove_link(&sup->kobj, buf);
4228c2ecf20Sopenharmony_cierr_con_dev:
4238c2ecf20Sopenharmony_ci	sysfs_remove_link(&link->link_dev.kobj, "consumer");
4248c2ecf20Sopenharmony_cierr_con:
4258c2ecf20Sopenharmony_ci	sysfs_remove_link(&link->link_dev.kobj, "supplier");
4268c2ecf20Sopenharmony_ciout:
4278c2ecf20Sopenharmony_ci	kfree(buf);
4288c2ecf20Sopenharmony_ci	return ret;
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic void devlink_remove_symlinks(struct device *dev,
4328c2ecf20Sopenharmony_ci				   struct class_interface *class_intf)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	struct device_link *link = to_devlink(dev);
4358c2ecf20Sopenharmony_ci	size_t len;
4368c2ecf20Sopenharmony_ci	struct device *sup = link->supplier;
4378c2ecf20Sopenharmony_ci	struct device *con = link->consumer;
4388c2ecf20Sopenharmony_ci	char *buf;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	sysfs_remove_link(&link->link_dev.kobj, "consumer");
4418c2ecf20Sopenharmony_ci	sysfs_remove_link(&link->link_dev.kobj, "supplier");
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
4448c2ecf20Sopenharmony_ci		  strlen(dev_bus_name(con)) + strlen(dev_name(con)));
4458c2ecf20Sopenharmony_ci	len += strlen(":");
4468c2ecf20Sopenharmony_ci	len += strlen("supplier:") + 1;
4478c2ecf20Sopenharmony_ci	buf = kzalloc(len, GFP_KERNEL);
4488c2ecf20Sopenharmony_ci	if (!buf) {
4498c2ecf20Sopenharmony_ci		WARN(1, "Unable to properly free device link symlinks!\n");
4508c2ecf20Sopenharmony_ci		return;
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	if (device_is_registered(con)) {
4548c2ecf20Sopenharmony_ci		snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
4558c2ecf20Sopenharmony_ci		sysfs_remove_link(&con->kobj, buf);
4568c2ecf20Sopenharmony_ci	}
4578c2ecf20Sopenharmony_ci	snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
4588c2ecf20Sopenharmony_ci	sysfs_remove_link(&sup->kobj, buf);
4598c2ecf20Sopenharmony_ci	kfree(buf);
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_cistatic struct class_interface devlink_class_intf = {
4638c2ecf20Sopenharmony_ci	.class = &devlink_class,
4648c2ecf20Sopenharmony_ci	.add_dev = devlink_add_symlinks,
4658c2ecf20Sopenharmony_ci	.remove_dev = devlink_remove_symlinks,
4668c2ecf20Sopenharmony_ci};
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_cistatic int __init devlink_class_init(void)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	int ret;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	ret = class_register(&devlink_class);
4738c2ecf20Sopenharmony_ci	if (ret)
4748c2ecf20Sopenharmony_ci		return ret;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	ret = class_interface_register(&devlink_class_intf);
4778c2ecf20Sopenharmony_ci	if (ret)
4788c2ecf20Sopenharmony_ci		class_unregister(&devlink_class);
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	return ret;
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_cipostcore_initcall(devlink_class_init);
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci#define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \
4858c2ecf20Sopenharmony_ci			       DL_FLAG_AUTOREMOVE_SUPPLIER | \
4868c2ecf20Sopenharmony_ci			       DL_FLAG_AUTOPROBE_CONSUMER  | \
4878c2ecf20Sopenharmony_ci			       DL_FLAG_SYNC_STATE_ONLY)
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci#define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \
4908c2ecf20Sopenharmony_ci			    DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci/**
4938c2ecf20Sopenharmony_ci * device_link_add - Create a link between two devices.
4948c2ecf20Sopenharmony_ci * @consumer: Consumer end of the link.
4958c2ecf20Sopenharmony_ci * @supplier: Supplier end of the link.
4968c2ecf20Sopenharmony_ci * @flags: Link flags.
4978c2ecf20Sopenharmony_ci *
4988c2ecf20Sopenharmony_ci * The caller is responsible for the proper synchronization of the link creation
4998c2ecf20Sopenharmony_ci * with runtime PM.  First, setting the DL_FLAG_PM_RUNTIME flag will cause the
5008c2ecf20Sopenharmony_ci * runtime PM framework to take the link into account.  Second, if the
5018c2ecf20Sopenharmony_ci * DL_FLAG_RPM_ACTIVE flag is set in addition to it, the supplier devices will
5028c2ecf20Sopenharmony_ci * be forced into the active metastate and reference-counted upon the creation
5038c2ecf20Sopenharmony_ci * of the link.  If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be
5048c2ecf20Sopenharmony_ci * ignored.
5058c2ecf20Sopenharmony_ci *
5068c2ecf20Sopenharmony_ci * If DL_FLAG_STATELESS is set in @flags, the caller of this function is
5078c2ecf20Sopenharmony_ci * expected to release the link returned by it directly with the help of either
5088c2ecf20Sopenharmony_ci * device_link_del() or device_link_remove().
5098c2ecf20Sopenharmony_ci *
5108c2ecf20Sopenharmony_ci * If that flag is not set, however, the caller of this function is handing the
5118c2ecf20Sopenharmony_ci * management of the link over to the driver core entirely and its return value
5128c2ecf20Sopenharmony_ci * can only be used to check whether or not the link is present.  In that case,
5138c2ecf20Sopenharmony_ci * the DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_AUTOREMOVE_SUPPLIER device link
5148c2ecf20Sopenharmony_ci * flags can be used to indicate to the driver core when the link can be safely
5158c2ecf20Sopenharmony_ci * deleted.  Namely, setting one of them in @flags indicates to the driver core
5168c2ecf20Sopenharmony_ci * that the link is not going to be used (by the given caller of this function)
5178c2ecf20Sopenharmony_ci * after unbinding the consumer or supplier driver, respectively, from its
5188c2ecf20Sopenharmony_ci * device, so the link can be deleted at that point.  If none of them is set,
5198c2ecf20Sopenharmony_ci * the link will be maintained until one of the devices pointed to by it (either
5208c2ecf20Sopenharmony_ci * the consumer or the supplier) is unregistered.
5218c2ecf20Sopenharmony_ci *
5228c2ecf20Sopenharmony_ci * Also, if DL_FLAG_STATELESS, DL_FLAG_AUTOREMOVE_CONSUMER and
5238c2ecf20Sopenharmony_ci * DL_FLAG_AUTOREMOVE_SUPPLIER are not set in @flags (that is, a persistent
5248c2ecf20Sopenharmony_ci * managed device link is being added), the DL_FLAG_AUTOPROBE_CONSUMER flag can
5258c2ecf20Sopenharmony_ci * be used to request the driver core to automaticall probe for a consmer
5268c2ecf20Sopenharmony_ci * driver after successfully binding a driver to the supplier device.
5278c2ecf20Sopenharmony_ci *
5288c2ecf20Sopenharmony_ci * The combination of DL_FLAG_STATELESS and one of DL_FLAG_AUTOREMOVE_CONSUMER,
5298c2ecf20Sopenharmony_ci * DL_FLAG_AUTOREMOVE_SUPPLIER, or DL_FLAG_AUTOPROBE_CONSUMER set in @flags at
5308c2ecf20Sopenharmony_ci * the same time is invalid and will cause NULL to be returned upfront.
5318c2ecf20Sopenharmony_ci * However, if a device link between the given @consumer and @supplier pair
5328c2ecf20Sopenharmony_ci * exists already when this function is called for them, the existing link will
5338c2ecf20Sopenharmony_ci * be returned regardless of its current type and status (the link's flags may
5348c2ecf20Sopenharmony_ci * be modified then).  The caller of this function is then expected to treat
5358c2ecf20Sopenharmony_ci * the link as though it has just been created, so (in particular) if
5368c2ecf20Sopenharmony_ci * DL_FLAG_STATELESS was passed in @flags, the link needs to be released
5378c2ecf20Sopenharmony_ci * explicitly when not needed any more (as stated above).
5388c2ecf20Sopenharmony_ci *
5398c2ecf20Sopenharmony_ci * A side effect of the link creation is re-ordering of dpm_list and the
5408c2ecf20Sopenharmony_ci * devices_kset list by moving the consumer device and all devices depending
5418c2ecf20Sopenharmony_ci * on it to the ends of these lists (that does not happen to devices that have
5428c2ecf20Sopenharmony_ci * not been registered when this function is called).
5438c2ecf20Sopenharmony_ci *
5448c2ecf20Sopenharmony_ci * The supplier device is required to be registered when this function is called
5458c2ecf20Sopenharmony_ci * and NULL will be returned if that is not the case.  The consumer device need
5468c2ecf20Sopenharmony_ci * not be registered, however.
5478c2ecf20Sopenharmony_ci */
5488c2ecf20Sopenharmony_cistruct device_link *device_link_add(struct device *consumer,
5498c2ecf20Sopenharmony_ci				    struct device *supplier, u32 flags)
5508c2ecf20Sopenharmony_ci{
5518c2ecf20Sopenharmony_ci	struct device_link *link;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	if (!consumer || !supplier || consumer == supplier ||
5548c2ecf20Sopenharmony_ci	    flags & ~DL_ADD_VALID_FLAGS ||
5558c2ecf20Sopenharmony_ci	    (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) ||
5568c2ecf20Sopenharmony_ci	    (flags & DL_FLAG_SYNC_STATE_ONLY &&
5578c2ecf20Sopenharmony_ci	     flags != DL_FLAG_SYNC_STATE_ONLY) ||
5588c2ecf20Sopenharmony_ci	    (flags & DL_FLAG_AUTOPROBE_CONSUMER &&
5598c2ecf20Sopenharmony_ci	     flags & (DL_FLAG_AUTOREMOVE_CONSUMER |
5608c2ecf20Sopenharmony_ci		      DL_FLAG_AUTOREMOVE_SUPPLIER)))
5618c2ecf20Sopenharmony_ci		return NULL;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	if (flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) {
5648c2ecf20Sopenharmony_ci		if (pm_runtime_get_sync(supplier) < 0) {
5658c2ecf20Sopenharmony_ci			pm_runtime_put_noidle(supplier);
5668c2ecf20Sopenharmony_ci			return NULL;
5678c2ecf20Sopenharmony_ci		}
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	if (!(flags & DL_FLAG_STATELESS))
5718c2ecf20Sopenharmony_ci		flags |= DL_FLAG_MANAGED;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	device_links_write_lock();
5748c2ecf20Sopenharmony_ci	device_pm_lock();
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	/*
5778c2ecf20Sopenharmony_ci	 * If the supplier has not been fully registered yet or there is a
5788c2ecf20Sopenharmony_ci	 * reverse (non-SYNC_STATE_ONLY) dependency between the consumer and
5798c2ecf20Sopenharmony_ci	 * the supplier already in the graph, return NULL. If the link is a
5808c2ecf20Sopenharmony_ci	 * SYNC_STATE_ONLY link, we don't check for reverse dependencies
5818c2ecf20Sopenharmony_ci	 * because it only affects sync_state() callbacks.
5828c2ecf20Sopenharmony_ci	 */
5838c2ecf20Sopenharmony_ci	if (!device_pm_initialized(supplier)
5848c2ecf20Sopenharmony_ci	    || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
5858c2ecf20Sopenharmony_ci		  device_is_dependent(consumer, supplier))) {
5868c2ecf20Sopenharmony_ci		link = NULL;
5878c2ecf20Sopenharmony_ci		goto out;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	/*
5918c2ecf20Sopenharmony_ci	 * DL_FLAG_AUTOREMOVE_SUPPLIER indicates that the link will be needed
5928c2ecf20Sopenharmony_ci	 * longer than for DL_FLAG_AUTOREMOVE_CONSUMER and setting them both
5938c2ecf20Sopenharmony_ci	 * together doesn't make sense, so prefer DL_FLAG_AUTOREMOVE_SUPPLIER.
5948c2ecf20Sopenharmony_ci	 */
5958c2ecf20Sopenharmony_ci	if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
5968c2ecf20Sopenharmony_ci		flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	list_for_each_entry(link, &supplier->links.consumers, s_node) {
5998c2ecf20Sopenharmony_ci		if (link->consumer != consumer)
6008c2ecf20Sopenharmony_ci			continue;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci		if (flags & DL_FLAG_PM_RUNTIME) {
6038c2ecf20Sopenharmony_ci			if (!(link->flags & DL_FLAG_PM_RUNTIME)) {
6048c2ecf20Sopenharmony_ci				pm_runtime_new_link(consumer);
6058c2ecf20Sopenharmony_ci				link->flags |= DL_FLAG_PM_RUNTIME;
6068c2ecf20Sopenharmony_ci			}
6078c2ecf20Sopenharmony_ci			if (flags & DL_FLAG_RPM_ACTIVE)
6088c2ecf20Sopenharmony_ci				refcount_inc(&link->rpm_active);
6098c2ecf20Sopenharmony_ci		}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci		if (flags & DL_FLAG_STATELESS) {
6128c2ecf20Sopenharmony_ci			kref_get(&link->kref);
6138c2ecf20Sopenharmony_ci			if (link->flags & DL_FLAG_SYNC_STATE_ONLY &&
6148c2ecf20Sopenharmony_ci			    !(link->flags & DL_FLAG_STATELESS)) {
6158c2ecf20Sopenharmony_ci				link->flags |= DL_FLAG_STATELESS;
6168c2ecf20Sopenharmony_ci				goto reorder;
6178c2ecf20Sopenharmony_ci			} else {
6188c2ecf20Sopenharmony_ci				link->flags |= DL_FLAG_STATELESS;
6198c2ecf20Sopenharmony_ci				goto out;
6208c2ecf20Sopenharmony_ci			}
6218c2ecf20Sopenharmony_ci		}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci		/*
6248c2ecf20Sopenharmony_ci		 * If the life time of the link following from the new flags is
6258c2ecf20Sopenharmony_ci		 * longer than indicated by the flags of the existing link,
6268c2ecf20Sopenharmony_ci		 * update the existing link to stay around longer.
6278c2ecf20Sopenharmony_ci		 */
6288c2ecf20Sopenharmony_ci		if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) {
6298c2ecf20Sopenharmony_ci			if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
6308c2ecf20Sopenharmony_ci				link->flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
6318c2ecf20Sopenharmony_ci				link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER;
6328c2ecf20Sopenharmony_ci			}
6338c2ecf20Sopenharmony_ci		} else if (!(flags & DL_FLAG_AUTOREMOVE_CONSUMER)) {
6348c2ecf20Sopenharmony_ci			link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER |
6358c2ecf20Sopenharmony_ci					 DL_FLAG_AUTOREMOVE_SUPPLIER);
6368c2ecf20Sopenharmony_ci		}
6378c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED)) {
6388c2ecf20Sopenharmony_ci			kref_get(&link->kref);
6398c2ecf20Sopenharmony_ci			link->flags |= DL_FLAG_MANAGED;
6408c2ecf20Sopenharmony_ci			device_link_init_status(link, consumer, supplier);
6418c2ecf20Sopenharmony_ci		}
6428c2ecf20Sopenharmony_ci		if (link->flags & DL_FLAG_SYNC_STATE_ONLY &&
6438c2ecf20Sopenharmony_ci		    !(flags & DL_FLAG_SYNC_STATE_ONLY)) {
6448c2ecf20Sopenharmony_ci			link->flags &= ~DL_FLAG_SYNC_STATE_ONLY;
6458c2ecf20Sopenharmony_ci			goto reorder;
6468c2ecf20Sopenharmony_ci		}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci		goto out;
6498c2ecf20Sopenharmony_ci	}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	link = kzalloc(sizeof(*link), GFP_KERNEL);
6528c2ecf20Sopenharmony_ci	if (!link)
6538c2ecf20Sopenharmony_ci		goto out;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	refcount_set(&link->rpm_active, 1);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	get_device(supplier);
6588c2ecf20Sopenharmony_ci	link->supplier = supplier;
6598c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&link->s_node);
6608c2ecf20Sopenharmony_ci	get_device(consumer);
6618c2ecf20Sopenharmony_ci	link->consumer = consumer;
6628c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&link->c_node);
6638c2ecf20Sopenharmony_ci	link->flags = flags;
6648c2ecf20Sopenharmony_ci	kref_init(&link->kref);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	link->link_dev.class = &devlink_class;
6678c2ecf20Sopenharmony_ci	device_set_pm_not_required(&link->link_dev);
6688c2ecf20Sopenharmony_ci	dev_set_name(&link->link_dev, "%s:%s--%s:%s",
6698c2ecf20Sopenharmony_ci		     dev_bus_name(supplier), dev_name(supplier),
6708c2ecf20Sopenharmony_ci		     dev_bus_name(consumer), dev_name(consumer));
6718c2ecf20Sopenharmony_ci	if (device_register(&link->link_dev)) {
6728c2ecf20Sopenharmony_ci		put_device(&link->link_dev);
6738c2ecf20Sopenharmony_ci		link = NULL;
6748c2ecf20Sopenharmony_ci		goto out;
6758c2ecf20Sopenharmony_ci	}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	if (flags & DL_FLAG_PM_RUNTIME) {
6788c2ecf20Sopenharmony_ci		if (flags & DL_FLAG_RPM_ACTIVE)
6798c2ecf20Sopenharmony_ci			refcount_inc(&link->rpm_active);
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci		pm_runtime_new_link(consumer);
6828c2ecf20Sopenharmony_ci	}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	/* Determine the initial link state. */
6858c2ecf20Sopenharmony_ci	if (flags & DL_FLAG_STATELESS)
6868c2ecf20Sopenharmony_ci		link->status = DL_STATE_NONE;
6878c2ecf20Sopenharmony_ci	else
6888c2ecf20Sopenharmony_ci		device_link_init_status(link, consumer, supplier);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	/*
6918c2ecf20Sopenharmony_ci	 * Some callers expect the link creation during consumer driver probe to
6928c2ecf20Sopenharmony_ci	 * resume the supplier even without DL_FLAG_RPM_ACTIVE.
6938c2ecf20Sopenharmony_ci	 */
6948c2ecf20Sopenharmony_ci	if (link->status == DL_STATE_CONSUMER_PROBE &&
6958c2ecf20Sopenharmony_ci	    flags & DL_FLAG_PM_RUNTIME)
6968c2ecf20Sopenharmony_ci		pm_runtime_resume(supplier);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	list_add_tail_rcu(&link->s_node, &supplier->links.consumers);
6998c2ecf20Sopenharmony_ci	list_add_tail_rcu(&link->c_node, &consumer->links.suppliers);
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	if (flags & DL_FLAG_SYNC_STATE_ONLY) {
7028c2ecf20Sopenharmony_ci		dev_dbg(consumer,
7038c2ecf20Sopenharmony_ci			"Linked as a sync state only consumer to %s\n",
7048c2ecf20Sopenharmony_ci			dev_name(supplier));
7058c2ecf20Sopenharmony_ci		goto out;
7068c2ecf20Sopenharmony_ci	}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_cireorder:
7098c2ecf20Sopenharmony_ci	/*
7108c2ecf20Sopenharmony_ci	 * Move the consumer and all of the devices depending on it to the end
7118c2ecf20Sopenharmony_ci	 * of dpm_list and the devices_kset list.
7128c2ecf20Sopenharmony_ci	 *
7138c2ecf20Sopenharmony_ci	 * It is necessary to hold dpm_list locked throughout all that or else
7148c2ecf20Sopenharmony_ci	 * we may end up suspending with a wrong ordering of it.
7158c2ecf20Sopenharmony_ci	 */
7168c2ecf20Sopenharmony_ci	device_reorder_to_tail(consumer, NULL);
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	dev_dbg(consumer, "Linked as a consumer to %s\n", dev_name(supplier));
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ciout:
7218c2ecf20Sopenharmony_ci	device_pm_unlock();
7228c2ecf20Sopenharmony_ci	device_links_write_unlock();
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	if ((flags & DL_FLAG_PM_RUNTIME && flags & DL_FLAG_RPM_ACTIVE) && !link)
7258c2ecf20Sopenharmony_ci		pm_runtime_put(supplier);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	return link;
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_link_add);
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci/**
7328c2ecf20Sopenharmony_ci * device_link_wait_for_supplier - Add device to wait_for_suppliers list
7338c2ecf20Sopenharmony_ci * @consumer: Consumer device
7348c2ecf20Sopenharmony_ci *
7358c2ecf20Sopenharmony_ci * Marks the @consumer device as waiting for suppliers to become available by
7368c2ecf20Sopenharmony_ci * adding it to the wait_for_suppliers list. The consumer device will never be
7378c2ecf20Sopenharmony_ci * probed until it's removed from the wait_for_suppliers list.
7388c2ecf20Sopenharmony_ci *
7398c2ecf20Sopenharmony_ci * The caller is responsible for adding the links to the supplier devices once
7408c2ecf20Sopenharmony_ci * they are available and removing the @consumer device from the
7418c2ecf20Sopenharmony_ci * wait_for_suppliers list once links to all the suppliers have been created.
7428c2ecf20Sopenharmony_ci *
7438c2ecf20Sopenharmony_ci * This function is NOT meant to be called from the probe function of the
7448c2ecf20Sopenharmony_ci * consumer but rather from code that creates/adds the consumer device.
7458c2ecf20Sopenharmony_ci */
7468c2ecf20Sopenharmony_cistatic void device_link_wait_for_supplier(struct device *consumer,
7478c2ecf20Sopenharmony_ci					  bool need_for_probe)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	mutex_lock(&wfs_lock);
7508c2ecf20Sopenharmony_ci	list_add_tail(&consumer->links.needs_suppliers, &wait_for_suppliers);
7518c2ecf20Sopenharmony_ci	consumer->links.need_for_probe = need_for_probe;
7528c2ecf20Sopenharmony_ci	mutex_unlock(&wfs_lock);
7538c2ecf20Sopenharmony_ci}
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_cistatic void device_link_wait_for_mandatory_supplier(struct device *consumer)
7568c2ecf20Sopenharmony_ci{
7578c2ecf20Sopenharmony_ci	device_link_wait_for_supplier(consumer, true);
7588c2ecf20Sopenharmony_ci}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_cistatic void device_link_wait_for_optional_supplier(struct device *consumer)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	device_link_wait_for_supplier(consumer, false);
7638c2ecf20Sopenharmony_ci}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci/**
7668c2ecf20Sopenharmony_ci * device_link_add_missing_supplier_links - Add links from consumer devices to
7678c2ecf20Sopenharmony_ci *					    supplier devices, leaving any
7688c2ecf20Sopenharmony_ci *					    consumer with inactive suppliers on
7698c2ecf20Sopenharmony_ci *					    the wait_for_suppliers list
7708c2ecf20Sopenharmony_ci *
7718c2ecf20Sopenharmony_ci * Loops through all consumers waiting on suppliers and tries to add all their
7728c2ecf20Sopenharmony_ci * supplier links. If that succeeds, the consumer device is removed from
7738c2ecf20Sopenharmony_ci * wait_for_suppliers list. Otherwise, they are left in the wait_for_suppliers
7748c2ecf20Sopenharmony_ci * list.  Devices left on the wait_for_suppliers list will not be probed.
7758c2ecf20Sopenharmony_ci *
7768c2ecf20Sopenharmony_ci * The fwnode add_links callback is expected to return 0 if it has found and
7778c2ecf20Sopenharmony_ci * added all the supplier links for the consumer device. It should return an
7788c2ecf20Sopenharmony_ci * error if it isn't able to do so.
7798c2ecf20Sopenharmony_ci *
7808c2ecf20Sopenharmony_ci * The caller of device_link_wait_for_supplier() is expected to call this once
7818c2ecf20Sopenharmony_ci * it's aware of potential suppliers becoming available.
7828c2ecf20Sopenharmony_ci */
7838c2ecf20Sopenharmony_cistatic void device_link_add_missing_supplier_links(void)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	struct device *dev, *tmp;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	mutex_lock(&wfs_lock);
7888c2ecf20Sopenharmony_ci	list_for_each_entry_safe(dev, tmp, &wait_for_suppliers,
7898c2ecf20Sopenharmony_ci				 links.needs_suppliers) {
7908c2ecf20Sopenharmony_ci		int ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
7918c2ecf20Sopenharmony_ci		if (!ret)
7928c2ecf20Sopenharmony_ci			list_del_init(&dev->links.needs_suppliers);
7938c2ecf20Sopenharmony_ci		else if (ret != -ENODEV || fw_devlink_is_permissive())
7948c2ecf20Sopenharmony_ci			dev->links.need_for_probe = false;
7958c2ecf20Sopenharmony_ci	}
7968c2ecf20Sopenharmony_ci	mutex_unlock(&wfs_lock);
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci#ifdef CONFIG_SRCU
8008c2ecf20Sopenharmony_cistatic void __device_link_del(struct kref *kref)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	struct device_link *link = container_of(kref, struct device_link, kref);
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	dev_dbg(link->consumer, "Dropping the link to %s\n",
8058c2ecf20Sopenharmony_ci		dev_name(link->supplier));
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	pm_runtime_drop_link(link);
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	list_del_rcu(&link->s_node);
8108c2ecf20Sopenharmony_ci	list_del_rcu(&link->c_node);
8118c2ecf20Sopenharmony_ci	device_unregister(&link->link_dev);
8128c2ecf20Sopenharmony_ci}
8138c2ecf20Sopenharmony_ci#else /* !CONFIG_SRCU */
8148c2ecf20Sopenharmony_cistatic void __device_link_del(struct kref *kref)
8158c2ecf20Sopenharmony_ci{
8168c2ecf20Sopenharmony_ci	struct device_link *link = container_of(kref, struct device_link, kref);
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	dev_info(link->consumer, "Dropping the link to %s\n",
8198c2ecf20Sopenharmony_ci		 dev_name(link->supplier));
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	pm_runtime_drop_link(link);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	list_del(&link->s_node);
8248c2ecf20Sopenharmony_ci	list_del(&link->c_node);
8258c2ecf20Sopenharmony_ci	device_unregister(&link->link_dev);
8268c2ecf20Sopenharmony_ci}
8278c2ecf20Sopenharmony_ci#endif /* !CONFIG_SRCU */
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_cistatic void device_link_put_kref(struct device_link *link)
8308c2ecf20Sopenharmony_ci{
8318c2ecf20Sopenharmony_ci	if (link->flags & DL_FLAG_STATELESS)
8328c2ecf20Sopenharmony_ci		kref_put(&link->kref, __device_link_del);
8338c2ecf20Sopenharmony_ci	else
8348c2ecf20Sopenharmony_ci		WARN(1, "Unable to drop a managed device link reference\n");
8358c2ecf20Sopenharmony_ci}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci/**
8388c2ecf20Sopenharmony_ci * device_link_del - Delete a stateless link between two devices.
8398c2ecf20Sopenharmony_ci * @link: Device link to delete.
8408c2ecf20Sopenharmony_ci *
8418c2ecf20Sopenharmony_ci * The caller must ensure proper synchronization of this function with runtime
8428c2ecf20Sopenharmony_ci * PM.  If the link was added multiple times, it needs to be deleted as often.
8438c2ecf20Sopenharmony_ci * Care is required for hotplugged devices:  Their links are purged on removal
8448c2ecf20Sopenharmony_ci * and calling device_link_del() is then no longer allowed.
8458c2ecf20Sopenharmony_ci */
8468c2ecf20Sopenharmony_civoid device_link_del(struct device_link *link)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	device_links_write_lock();
8498c2ecf20Sopenharmony_ci	device_link_put_kref(link);
8508c2ecf20Sopenharmony_ci	device_links_write_unlock();
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_link_del);
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci/**
8558c2ecf20Sopenharmony_ci * device_link_remove - Delete a stateless link between two devices.
8568c2ecf20Sopenharmony_ci * @consumer: Consumer end of the link.
8578c2ecf20Sopenharmony_ci * @supplier: Supplier end of the link.
8588c2ecf20Sopenharmony_ci *
8598c2ecf20Sopenharmony_ci * The caller must ensure proper synchronization of this function with runtime
8608c2ecf20Sopenharmony_ci * PM.
8618c2ecf20Sopenharmony_ci */
8628c2ecf20Sopenharmony_civoid device_link_remove(void *consumer, struct device *supplier)
8638c2ecf20Sopenharmony_ci{
8648c2ecf20Sopenharmony_ci	struct device_link *link;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	if (WARN_ON(consumer == supplier))
8678c2ecf20Sopenharmony_ci		return;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	device_links_write_lock();
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	list_for_each_entry(link, &supplier->links.consumers, s_node) {
8728c2ecf20Sopenharmony_ci		if (link->consumer == consumer) {
8738c2ecf20Sopenharmony_ci			device_link_put_kref(link);
8748c2ecf20Sopenharmony_ci			break;
8758c2ecf20Sopenharmony_ci		}
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	device_links_write_unlock();
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_link_remove);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_cistatic void device_links_missing_supplier(struct device *dev)
8838c2ecf20Sopenharmony_ci{
8848c2ecf20Sopenharmony_ci	struct device_link *link;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.suppliers, c_node) {
8878c2ecf20Sopenharmony_ci		if (link->status != DL_STATE_CONSUMER_PROBE)
8888c2ecf20Sopenharmony_ci			continue;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci		if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
8918c2ecf20Sopenharmony_ci			WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
8928c2ecf20Sopenharmony_ci		} else {
8938c2ecf20Sopenharmony_ci			WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
8948c2ecf20Sopenharmony_ci			WRITE_ONCE(link->status, DL_STATE_DORMANT);
8958c2ecf20Sopenharmony_ci		}
8968c2ecf20Sopenharmony_ci	}
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci/**
9008c2ecf20Sopenharmony_ci * device_links_check_suppliers - Check presence of supplier drivers.
9018c2ecf20Sopenharmony_ci * @dev: Consumer device.
9028c2ecf20Sopenharmony_ci *
9038c2ecf20Sopenharmony_ci * Check links from this device to any suppliers.  Walk the list of the device's
9048c2ecf20Sopenharmony_ci * links to suppliers and see if all of them are available.  If not, simply
9058c2ecf20Sopenharmony_ci * return -EPROBE_DEFER.
9068c2ecf20Sopenharmony_ci *
9078c2ecf20Sopenharmony_ci * We need to guarantee that the supplier will not go away after the check has
9088c2ecf20Sopenharmony_ci * been positive here.  It only can go away in __device_release_driver() and
9098c2ecf20Sopenharmony_ci * that function  checks the device's links to consumers.  This means we need to
9108c2ecf20Sopenharmony_ci * mark the link as "consumer probe in progress" to make the supplier removal
9118c2ecf20Sopenharmony_ci * wait for us to complete (or bad things may happen).
9128c2ecf20Sopenharmony_ci *
9138c2ecf20Sopenharmony_ci * Links without the DL_FLAG_MANAGED flag set are ignored.
9148c2ecf20Sopenharmony_ci */
9158c2ecf20Sopenharmony_ciint device_links_check_suppliers(struct device *dev)
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	struct device_link *link;
9188c2ecf20Sopenharmony_ci	int ret = 0;
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	/*
9218c2ecf20Sopenharmony_ci	 * Device waiting for supplier to become available is not allowed to
9228c2ecf20Sopenharmony_ci	 * probe.
9238c2ecf20Sopenharmony_ci	 */
9248c2ecf20Sopenharmony_ci	mutex_lock(&wfs_lock);
9258c2ecf20Sopenharmony_ci	if (!list_empty(&dev->links.needs_suppliers) &&
9268c2ecf20Sopenharmony_ci	    dev->links.need_for_probe) {
9278c2ecf20Sopenharmony_ci		mutex_unlock(&wfs_lock);
9288c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci	mutex_unlock(&wfs_lock);
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	device_links_write_lock();
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.suppliers, c_node) {
9358c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
9368c2ecf20Sopenharmony_ci			continue;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci		if (link->status != DL_STATE_AVAILABLE &&
9398c2ecf20Sopenharmony_ci		    !(link->flags & DL_FLAG_SYNC_STATE_ONLY)) {
9408c2ecf20Sopenharmony_ci			device_links_missing_supplier(dev);
9418c2ecf20Sopenharmony_ci			ret = -EPROBE_DEFER;
9428c2ecf20Sopenharmony_ci			break;
9438c2ecf20Sopenharmony_ci		}
9448c2ecf20Sopenharmony_ci		WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE);
9458c2ecf20Sopenharmony_ci	}
9468c2ecf20Sopenharmony_ci	dev->links.status = DL_DEV_PROBING;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	device_links_write_unlock();
9498c2ecf20Sopenharmony_ci	return ret;
9508c2ecf20Sopenharmony_ci}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci/**
9538c2ecf20Sopenharmony_ci * __device_links_queue_sync_state - Queue a device for sync_state() callback
9548c2ecf20Sopenharmony_ci * @dev: Device to call sync_state() on
9558c2ecf20Sopenharmony_ci * @list: List head to queue the @dev on
9568c2ecf20Sopenharmony_ci *
9578c2ecf20Sopenharmony_ci * Queues a device for a sync_state() callback when the device links write lock
9588c2ecf20Sopenharmony_ci * isn't held. This allows the sync_state() execution flow to use device links
9598c2ecf20Sopenharmony_ci * APIs.  The caller must ensure this function is called with
9608c2ecf20Sopenharmony_ci * device_links_write_lock() held.
9618c2ecf20Sopenharmony_ci *
9628c2ecf20Sopenharmony_ci * This function does a get_device() to make sure the device is not freed while
9638c2ecf20Sopenharmony_ci * on this list.
9648c2ecf20Sopenharmony_ci *
9658c2ecf20Sopenharmony_ci * So the caller must also ensure that device_links_flush_sync_list() is called
9668c2ecf20Sopenharmony_ci * as soon as the caller releases device_links_write_lock().  This is necessary
9678c2ecf20Sopenharmony_ci * to make sure the sync_state() is called in a timely fashion and the
9688c2ecf20Sopenharmony_ci * put_device() is called on this device.
9698c2ecf20Sopenharmony_ci */
9708c2ecf20Sopenharmony_cistatic void __device_links_queue_sync_state(struct device *dev,
9718c2ecf20Sopenharmony_ci					    struct list_head *list)
9728c2ecf20Sopenharmony_ci{
9738c2ecf20Sopenharmony_ci	struct device_link *link;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	if (!dev_has_sync_state(dev))
9768c2ecf20Sopenharmony_ci		return;
9778c2ecf20Sopenharmony_ci	if (dev->state_synced)
9788c2ecf20Sopenharmony_ci		return;
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.consumers, s_node) {
9818c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
9828c2ecf20Sopenharmony_ci			continue;
9838c2ecf20Sopenharmony_ci		if (link->status != DL_STATE_ACTIVE)
9848c2ecf20Sopenharmony_ci			return;
9858c2ecf20Sopenharmony_ci	}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	/*
9888c2ecf20Sopenharmony_ci	 * Set the flag here to avoid adding the same device to a list more
9898c2ecf20Sopenharmony_ci	 * than once. This can happen if new consumers get added to the device
9908c2ecf20Sopenharmony_ci	 * and probed before the list is flushed.
9918c2ecf20Sopenharmony_ci	 */
9928c2ecf20Sopenharmony_ci	dev->state_synced = true;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	if (WARN_ON(!list_empty(&dev->links.defer_hook)))
9958c2ecf20Sopenharmony_ci		return;
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	get_device(dev);
9988c2ecf20Sopenharmony_ci	list_add_tail(&dev->links.defer_hook, list);
9998c2ecf20Sopenharmony_ci}
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci/**
10028c2ecf20Sopenharmony_ci * device_links_flush_sync_list - Call sync_state() on a list of devices
10038c2ecf20Sopenharmony_ci * @list: List of devices to call sync_state() on
10048c2ecf20Sopenharmony_ci * @dont_lock_dev: Device for which lock is already held by the caller
10058c2ecf20Sopenharmony_ci *
10068c2ecf20Sopenharmony_ci * Calls sync_state() on all the devices that have been queued for it. This
10078c2ecf20Sopenharmony_ci * function is used in conjunction with __device_links_queue_sync_state(). The
10088c2ecf20Sopenharmony_ci * @dont_lock_dev parameter is useful when this function is called from a
10098c2ecf20Sopenharmony_ci * context where a device lock is already held.
10108c2ecf20Sopenharmony_ci */
10118c2ecf20Sopenharmony_cistatic void device_links_flush_sync_list(struct list_head *list,
10128c2ecf20Sopenharmony_ci					 struct device *dont_lock_dev)
10138c2ecf20Sopenharmony_ci{
10148c2ecf20Sopenharmony_ci	struct device *dev, *tmp;
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ci	list_for_each_entry_safe(dev, tmp, list, links.defer_hook) {
10178c2ecf20Sopenharmony_ci		list_del_init(&dev->links.defer_hook);
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci		if (dev != dont_lock_dev)
10208c2ecf20Sopenharmony_ci			device_lock(dev);
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci		if (dev->bus->sync_state)
10238c2ecf20Sopenharmony_ci			dev->bus->sync_state(dev);
10248c2ecf20Sopenharmony_ci		else if (dev->driver && dev->driver->sync_state)
10258c2ecf20Sopenharmony_ci			dev->driver->sync_state(dev);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci		if (dev != dont_lock_dev)
10288c2ecf20Sopenharmony_ci			device_unlock(dev);
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci		put_device(dev);
10318c2ecf20Sopenharmony_ci	}
10328c2ecf20Sopenharmony_ci}
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_civoid device_links_supplier_sync_state_pause(void)
10358c2ecf20Sopenharmony_ci{
10368c2ecf20Sopenharmony_ci	device_links_write_lock();
10378c2ecf20Sopenharmony_ci	defer_sync_state_count++;
10388c2ecf20Sopenharmony_ci	device_links_write_unlock();
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_civoid device_links_supplier_sync_state_resume(void)
10428c2ecf20Sopenharmony_ci{
10438c2ecf20Sopenharmony_ci	struct device *dev, *tmp;
10448c2ecf20Sopenharmony_ci	LIST_HEAD(sync_list);
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	device_links_write_lock();
10478c2ecf20Sopenharmony_ci	if (!defer_sync_state_count) {
10488c2ecf20Sopenharmony_ci		WARN(true, "Unmatched sync_state pause/resume!");
10498c2ecf20Sopenharmony_ci		goto out;
10508c2ecf20Sopenharmony_ci	}
10518c2ecf20Sopenharmony_ci	defer_sync_state_count--;
10528c2ecf20Sopenharmony_ci	if (defer_sync_state_count)
10538c2ecf20Sopenharmony_ci		goto out;
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_hook) {
10568c2ecf20Sopenharmony_ci		/*
10578c2ecf20Sopenharmony_ci		 * Delete from deferred_sync list before queuing it to
10588c2ecf20Sopenharmony_ci		 * sync_list because defer_hook is used for both lists.
10598c2ecf20Sopenharmony_ci		 */
10608c2ecf20Sopenharmony_ci		list_del_init(&dev->links.defer_hook);
10618c2ecf20Sopenharmony_ci		__device_links_queue_sync_state(dev, &sync_list);
10628c2ecf20Sopenharmony_ci	}
10638c2ecf20Sopenharmony_ciout:
10648c2ecf20Sopenharmony_ci	device_links_write_unlock();
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	device_links_flush_sync_list(&sync_list, NULL);
10678c2ecf20Sopenharmony_ci}
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_cistatic int sync_state_resume_initcall(void)
10708c2ecf20Sopenharmony_ci{
10718c2ecf20Sopenharmony_ci	device_links_supplier_sync_state_resume();
10728c2ecf20Sopenharmony_ci	return 0;
10738c2ecf20Sopenharmony_ci}
10748c2ecf20Sopenharmony_cilate_initcall(sync_state_resume_initcall);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_cistatic void __device_links_supplier_defer_sync(struct device *sup)
10778c2ecf20Sopenharmony_ci{
10788c2ecf20Sopenharmony_ci	if (list_empty(&sup->links.defer_hook) && dev_has_sync_state(sup))
10798c2ecf20Sopenharmony_ci		list_add_tail(&sup->links.defer_hook, &deferred_sync);
10808c2ecf20Sopenharmony_ci}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_cistatic void device_link_drop_managed(struct device_link *link)
10838c2ecf20Sopenharmony_ci{
10848c2ecf20Sopenharmony_ci	link->flags &= ~DL_FLAG_MANAGED;
10858c2ecf20Sopenharmony_ci	WRITE_ONCE(link->status, DL_STATE_NONE);
10868c2ecf20Sopenharmony_ci	kref_put(&link->kref, __device_link_del);
10878c2ecf20Sopenharmony_ci}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_cistatic ssize_t waiting_for_supplier_show(struct device *dev,
10908c2ecf20Sopenharmony_ci					 struct device_attribute *attr,
10918c2ecf20Sopenharmony_ci					 char *buf)
10928c2ecf20Sopenharmony_ci{
10938c2ecf20Sopenharmony_ci	bool val;
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	device_lock(dev);
10968c2ecf20Sopenharmony_ci	mutex_lock(&wfs_lock);
10978c2ecf20Sopenharmony_ci	val = !list_empty(&dev->links.needs_suppliers)
10988c2ecf20Sopenharmony_ci	      && dev->links.need_for_probe;
10998c2ecf20Sopenharmony_ci	mutex_unlock(&wfs_lock);
11008c2ecf20Sopenharmony_ci	device_unlock(dev);
11018c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%u\n", val);
11028c2ecf20Sopenharmony_ci}
11038c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(waiting_for_supplier);
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci/**
11068c2ecf20Sopenharmony_ci * device_links_driver_bound - Update device links after probing its driver.
11078c2ecf20Sopenharmony_ci * @dev: Device to update the links for.
11088c2ecf20Sopenharmony_ci *
11098c2ecf20Sopenharmony_ci * The probe has been successful, so update links from this device to any
11108c2ecf20Sopenharmony_ci * consumers by changing their status to "available".
11118c2ecf20Sopenharmony_ci *
11128c2ecf20Sopenharmony_ci * Also change the status of @dev's links to suppliers to "active".
11138c2ecf20Sopenharmony_ci *
11148c2ecf20Sopenharmony_ci * Links without the DL_FLAG_MANAGED flag set are ignored.
11158c2ecf20Sopenharmony_ci */
11168c2ecf20Sopenharmony_civoid device_links_driver_bound(struct device *dev)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	struct device_link *link, *ln;
11198c2ecf20Sopenharmony_ci	LIST_HEAD(sync_list);
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	/*
11228c2ecf20Sopenharmony_ci	 * If a device probes successfully, it's expected to have created all
11238c2ecf20Sopenharmony_ci	 * the device links it needs to or make new device links as it needs
11248c2ecf20Sopenharmony_ci	 * them. So, it no longer needs to wait on any suppliers.
11258c2ecf20Sopenharmony_ci	 */
11268c2ecf20Sopenharmony_ci	mutex_lock(&wfs_lock);
11278c2ecf20Sopenharmony_ci	list_del_init(&dev->links.needs_suppliers);
11288c2ecf20Sopenharmony_ci	mutex_unlock(&wfs_lock);
11298c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_waiting_for_supplier);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	device_links_write_lock();
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.consumers, s_node) {
11348c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
11358c2ecf20Sopenharmony_ci			continue;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci		/*
11388c2ecf20Sopenharmony_ci		 * Links created during consumer probe may be in the "consumer
11398c2ecf20Sopenharmony_ci		 * probe" state to start with if the supplier is still probing
11408c2ecf20Sopenharmony_ci		 * when they are created and they may become "active" if the
11418c2ecf20Sopenharmony_ci		 * consumer probe returns first.  Skip them here.
11428c2ecf20Sopenharmony_ci		 */
11438c2ecf20Sopenharmony_ci		if (link->status == DL_STATE_CONSUMER_PROBE ||
11448c2ecf20Sopenharmony_ci		    link->status == DL_STATE_ACTIVE)
11458c2ecf20Sopenharmony_ci			continue;
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci		WARN_ON(link->status != DL_STATE_DORMANT);
11488c2ecf20Sopenharmony_ci		WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci		if (link->flags & DL_FLAG_AUTOPROBE_CONSUMER)
11518c2ecf20Sopenharmony_ci			driver_deferred_probe_add(link->consumer);
11528c2ecf20Sopenharmony_ci	}
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	if (defer_sync_state_count)
11558c2ecf20Sopenharmony_ci		__device_links_supplier_defer_sync(dev);
11568c2ecf20Sopenharmony_ci	else
11578c2ecf20Sopenharmony_ci		__device_links_queue_sync_state(dev, &sync_list);
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
11608c2ecf20Sopenharmony_ci		struct device *supplier;
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
11638c2ecf20Sopenharmony_ci			continue;
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci		supplier = link->supplier;
11668c2ecf20Sopenharmony_ci		if (link->flags & DL_FLAG_SYNC_STATE_ONLY) {
11678c2ecf20Sopenharmony_ci			/*
11688c2ecf20Sopenharmony_ci			 * When DL_FLAG_SYNC_STATE_ONLY is set, it means no
11698c2ecf20Sopenharmony_ci			 * other DL_MANAGED_LINK_FLAGS have been set. So, it's
11708c2ecf20Sopenharmony_ci			 * save to drop the managed link completely.
11718c2ecf20Sopenharmony_ci			 */
11728c2ecf20Sopenharmony_ci			device_link_drop_managed(link);
11738c2ecf20Sopenharmony_ci		} else {
11748c2ecf20Sopenharmony_ci			WARN_ON(link->status != DL_STATE_CONSUMER_PROBE);
11758c2ecf20Sopenharmony_ci			WRITE_ONCE(link->status, DL_STATE_ACTIVE);
11768c2ecf20Sopenharmony_ci		}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci		/*
11798c2ecf20Sopenharmony_ci		 * This needs to be done even for the deleted
11808c2ecf20Sopenharmony_ci		 * DL_FLAG_SYNC_STATE_ONLY device link in case it was the last
11818c2ecf20Sopenharmony_ci		 * device link that was preventing the supplier from getting a
11828c2ecf20Sopenharmony_ci		 * sync_state() call.
11838c2ecf20Sopenharmony_ci		 */
11848c2ecf20Sopenharmony_ci		if (defer_sync_state_count)
11858c2ecf20Sopenharmony_ci			__device_links_supplier_defer_sync(supplier);
11868c2ecf20Sopenharmony_ci		else
11878c2ecf20Sopenharmony_ci			__device_links_queue_sync_state(supplier, &sync_list);
11888c2ecf20Sopenharmony_ci	}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	dev->links.status = DL_DEV_DRIVER_BOUND;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	device_links_write_unlock();
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	device_links_flush_sync_list(&sync_list, dev);
11958c2ecf20Sopenharmony_ci}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci/**
11988c2ecf20Sopenharmony_ci * __device_links_no_driver - Update links of a device without a driver.
11998c2ecf20Sopenharmony_ci * @dev: Device without a drvier.
12008c2ecf20Sopenharmony_ci *
12018c2ecf20Sopenharmony_ci * Delete all non-persistent links from this device to any suppliers.
12028c2ecf20Sopenharmony_ci *
12038c2ecf20Sopenharmony_ci * Persistent links stay around, but their status is changed to "available",
12048c2ecf20Sopenharmony_ci * unless they already are in the "supplier unbind in progress" state in which
12058c2ecf20Sopenharmony_ci * case they need not be updated.
12068c2ecf20Sopenharmony_ci *
12078c2ecf20Sopenharmony_ci * Links without the DL_FLAG_MANAGED flag set are ignored.
12088c2ecf20Sopenharmony_ci */
12098c2ecf20Sopenharmony_cistatic void __device_links_no_driver(struct device *dev)
12108c2ecf20Sopenharmony_ci{
12118c2ecf20Sopenharmony_ci	struct device_link *link, *ln;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
12148c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
12158c2ecf20Sopenharmony_ci			continue;
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci		if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
12188c2ecf20Sopenharmony_ci			device_link_drop_managed(link);
12198c2ecf20Sopenharmony_ci			continue;
12208c2ecf20Sopenharmony_ci		}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci		if (link->status != DL_STATE_CONSUMER_PROBE &&
12238c2ecf20Sopenharmony_ci		    link->status != DL_STATE_ACTIVE)
12248c2ecf20Sopenharmony_ci			continue;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci		if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
12278c2ecf20Sopenharmony_ci			WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
12288c2ecf20Sopenharmony_ci		} else {
12298c2ecf20Sopenharmony_ci			WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
12308c2ecf20Sopenharmony_ci			WRITE_ONCE(link->status, DL_STATE_DORMANT);
12318c2ecf20Sopenharmony_ci		}
12328c2ecf20Sopenharmony_ci	}
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	dev->links.status = DL_DEV_NO_DRIVER;
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci/**
12388c2ecf20Sopenharmony_ci * device_links_no_driver - Update links after failing driver probe.
12398c2ecf20Sopenharmony_ci * @dev: Device whose driver has just failed to probe.
12408c2ecf20Sopenharmony_ci *
12418c2ecf20Sopenharmony_ci * Clean up leftover links to consumers for @dev and invoke
12428c2ecf20Sopenharmony_ci * %__device_links_no_driver() to update links to suppliers for it as
12438c2ecf20Sopenharmony_ci * appropriate.
12448c2ecf20Sopenharmony_ci *
12458c2ecf20Sopenharmony_ci * Links without the DL_FLAG_MANAGED flag set are ignored.
12468c2ecf20Sopenharmony_ci */
12478c2ecf20Sopenharmony_civoid device_links_no_driver(struct device *dev)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	struct device_link *link;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	device_links_write_lock();
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.consumers, s_node) {
12548c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
12558c2ecf20Sopenharmony_ci			continue;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci		/*
12588c2ecf20Sopenharmony_ci		 * The probe has failed, so if the status of the link is
12598c2ecf20Sopenharmony_ci		 * "consumer probe" or "active", it must have been added by
12608c2ecf20Sopenharmony_ci		 * a probing consumer while this device was still probing.
12618c2ecf20Sopenharmony_ci		 * Change its state to "dormant", as it represents a valid
12628c2ecf20Sopenharmony_ci		 * relationship, but it is not functionally meaningful.
12638c2ecf20Sopenharmony_ci		 */
12648c2ecf20Sopenharmony_ci		if (link->status == DL_STATE_CONSUMER_PROBE ||
12658c2ecf20Sopenharmony_ci		    link->status == DL_STATE_ACTIVE)
12668c2ecf20Sopenharmony_ci			WRITE_ONCE(link->status, DL_STATE_DORMANT);
12678c2ecf20Sopenharmony_ci	}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	__device_links_no_driver(dev);
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	device_links_write_unlock();
12728c2ecf20Sopenharmony_ci}
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci/**
12758c2ecf20Sopenharmony_ci * device_links_driver_cleanup - Update links after driver removal.
12768c2ecf20Sopenharmony_ci * @dev: Device whose driver has just gone away.
12778c2ecf20Sopenharmony_ci *
12788c2ecf20Sopenharmony_ci * Update links to consumers for @dev by changing their status to "dormant" and
12798c2ecf20Sopenharmony_ci * invoke %__device_links_no_driver() to update links to suppliers for it as
12808c2ecf20Sopenharmony_ci * appropriate.
12818c2ecf20Sopenharmony_ci *
12828c2ecf20Sopenharmony_ci * Links without the DL_FLAG_MANAGED flag set are ignored.
12838c2ecf20Sopenharmony_ci */
12848c2ecf20Sopenharmony_civoid device_links_driver_cleanup(struct device *dev)
12858c2ecf20Sopenharmony_ci{
12868c2ecf20Sopenharmony_ci	struct device_link *link, *ln;
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	device_links_write_lock();
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) {
12918c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
12928c2ecf20Sopenharmony_ci			continue;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci		WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER);
12958c2ecf20Sopenharmony_ci		WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND);
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci		/*
12988c2ecf20Sopenharmony_ci		 * autoremove the links between this @dev and its consumer
12998c2ecf20Sopenharmony_ci		 * devices that are not active, i.e. where the link state
13008c2ecf20Sopenharmony_ci		 * has moved to DL_STATE_SUPPLIER_UNBIND.
13018c2ecf20Sopenharmony_ci		 */
13028c2ecf20Sopenharmony_ci		if (link->status == DL_STATE_SUPPLIER_UNBIND &&
13038c2ecf20Sopenharmony_ci		    link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
13048c2ecf20Sopenharmony_ci			device_link_drop_managed(link);
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci		WRITE_ONCE(link->status, DL_STATE_DORMANT);
13078c2ecf20Sopenharmony_ci	}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	list_del_init(&dev->links.defer_hook);
13108c2ecf20Sopenharmony_ci	__device_links_no_driver(dev);
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	device_links_write_unlock();
13138c2ecf20Sopenharmony_ci}
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci/**
13168c2ecf20Sopenharmony_ci * device_links_busy - Check if there are any busy links to consumers.
13178c2ecf20Sopenharmony_ci * @dev: Device to check.
13188c2ecf20Sopenharmony_ci *
13198c2ecf20Sopenharmony_ci * Check each consumer of the device and return 'true' if its link's status
13208c2ecf20Sopenharmony_ci * is one of "consumer probe" or "active" (meaning that the given consumer is
13218c2ecf20Sopenharmony_ci * probing right now or its driver is present).  Otherwise, change the link
13228c2ecf20Sopenharmony_ci * state to "supplier unbind" to prevent the consumer from being probed
13238c2ecf20Sopenharmony_ci * successfully going forward.
13248c2ecf20Sopenharmony_ci *
13258c2ecf20Sopenharmony_ci * Return 'false' if there are no probing or active consumers.
13268c2ecf20Sopenharmony_ci *
13278c2ecf20Sopenharmony_ci * Links without the DL_FLAG_MANAGED flag set are ignored.
13288c2ecf20Sopenharmony_ci */
13298c2ecf20Sopenharmony_cibool device_links_busy(struct device *dev)
13308c2ecf20Sopenharmony_ci{
13318c2ecf20Sopenharmony_ci	struct device_link *link;
13328c2ecf20Sopenharmony_ci	bool ret = false;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	device_links_write_lock();
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.consumers, s_node) {
13378c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED))
13388c2ecf20Sopenharmony_ci			continue;
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci		if (link->status == DL_STATE_CONSUMER_PROBE
13418c2ecf20Sopenharmony_ci		    || link->status == DL_STATE_ACTIVE) {
13428c2ecf20Sopenharmony_ci			ret = true;
13438c2ecf20Sopenharmony_ci			break;
13448c2ecf20Sopenharmony_ci		}
13458c2ecf20Sopenharmony_ci		WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND);
13468c2ecf20Sopenharmony_ci	}
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci	dev->links.status = DL_DEV_UNBINDING;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	device_links_write_unlock();
13518c2ecf20Sopenharmony_ci	return ret;
13528c2ecf20Sopenharmony_ci}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci/**
13558c2ecf20Sopenharmony_ci * device_links_unbind_consumers - Force unbind consumers of the given device.
13568c2ecf20Sopenharmony_ci * @dev: Device to unbind the consumers of.
13578c2ecf20Sopenharmony_ci *
13588c2ecf20Sopenharmony_ci * Walk the list of links to consumers for @dev and if any of them is in the
13598c2ecf20Sopenharmony_ci * "consumer probe" state, wait for all device probes in progress to complete
13608c2ecf20Sopenharmony_ci * and start over.
13618c2ecf20Sopenharmony_ci *
13628c2ecf20Sopenharmony_ci * If that's not the case, change the status of the link to "supplier unbind"
13638c2ecf20Sopenharmony_ci * and check if the link was in the "active" state.  If so, force the consumer
13648c2ecf20Sopenharmony_ci * driver to unbind and start over (the consumer will not re-probe as we have
13658c2ecf20Sopenharmony_ci * changed the state of the link already).
13668c2ecf20Sopenharmony_ci *
13678c2ecf20Sopenharmony_ci * Links without the DL_FLAG_MANAGED flag set are ignored.
13688c2ecf20Sopenharmony_ci */
13698c2ecf20Sopenharmony_civoid device_links_unbind_consumers(struct device *dev)
13708c2ecf20Sopenharmony_ci{
13718c2ecf20Sopenharmony_ci	struct device_link *link;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci start:
13748c2ecf20Sopenharmony_ci	device_links_write_lock();
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	list_for_each_entry(link, &dev->links.consumers, s_node) {
13778c2ecf20Sopenharmony_ci		enum device_link_state status;
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci		if (!(link->flags & DL_FLAG_MANAGED) ||
13808c2ecf20Sopenharmony_ci		    link->flags & DL_FLAG_SYNC_STATE_ONLY)
13818c2ecf20Sopenharmony_ci			continue;
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci		status = link->status;
13848c2ecf20Sopenharmony_ci		if (status == DL_STATE_CONSUMER_PROBE) {
13858c2ecf20Sopenharmony_ci			device_links_write_unlock();
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci			wait_for_device_probe();
13888c2ecf20Sopenharmony_ci			goto start;
13898c2ecf20Sopenharmony_ci		}
13908c2ecf20Sopenharmony_ci		WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND);
13918c2ecf20Sopenharmony_ci		if (status == DL_STATE_ACTIVE) {
13928c2ecf20Sopenharmony_ci			struct device *consumer = link->consumer;
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci			get_device(consumer);
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_ci			device_links_write_unlock();
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci			device_release_driver_internal(consumer, NULL,
13998c2ecf20Sopenharmony_ci						       consumer->parent);
14008c2ecf20Sopenharmony_ci			put_device(consumer);
14018c2ecf20Sopenharmony_ci			goto start;
14028c2ecf20Sopenharmony_ci		}
14038c2ecf20Sopenharmony_ci	}
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	device_links_write_unlock();
14068c2ecf20Sopenharmony_ci}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci/**
14098c2ecf20Sopenharmony_ci * device_links_purge - Delete existing links to other devices.
14108c2ecf20Sopenharmony_ci * @dev: Target device.
14118c2ecf20Sopenharmony_ci */
14128c2ecf20Sopenharmony_cistatic void device_links_purge(struct device *dev)
14138c2ecf20Sopenharmony_ci{
14148c2ecf20Sopenharmony_ci	struct device_link *link, *ln;
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	if (dev->class == &devlink_class)
14178c2ecf20Sopenharmony_ci		return;
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	mutex_lock(&wfs_lock);
14208c2ecf20Sopenharmony_ci	list_del_init(&dev->links.needs_suppliers);
14218c2ecf20Sopenharmony_ci	mutex_unlock(&wfs_lock);
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	/*
14248c2ecf20Sopenharmony_ci	 * Delete all of the remaining links from this device to any other
14258c2ecf20Sopenharmony_ci	 * devices (either consumers or suppliers).
14268c2ecf20Sopenharmony_ci	 */
14278c2ecf20Sopenharmony_ci	device_links_write_lock();
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
14308c2ecf20Sopenharmony_ci		WARN_ON(link->status == DL_STATE_ACTIVE);
14318c2ecf20Sopenharmony_ci		__device_link_del(&link->kref);
14328c2ecf20Sopenharmony_ci	}
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
14358c2ecf20Sopenharmony_ci		WARN_ON(link->status != DL_STATE_DORMANT &&
14368c2ecf20Sopenharmony_ci			link->status != DL_STATE_NONE);
14378c2ecf20Sopenharmony_ci		__device_link_del(&link->kref);
14388c2ecf20Sopenharmony_ci	}
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	device_links_write_unlock();
14418c2ecf20Sopenharmony_ci}
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_cistatic u32 fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY;
14448c2ecf20Sopenharmony_cistatic int __init fw_devlink_setup(char *arg)
14458c2ecf20Sopenharmony_ci{
14468c2ecf20Sopenharmony_ci	if (!arg)
14478c2ecf20Sopenharmony_ci		return -EINVAL;
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	if (strcmp(arg, "off") == 0) {
14508c2ecf20Sopenharmony_ci		fw_devlink_flags = 0;
14518c2ecf20Sopenharmony_ci	} else if (strcmp(arg, "permissive") == 0) {
14528c2ecf20Sopenharmony_ci		fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY;
14538c2ecf20Sopenharmony_ci	} else if (strcmp(arg, "on") == 0) {
14548c2ecf20Sopenharmony_ci		fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER;
14558c2ecf20Sopenharmony_ci	} else if (strcmp(arg, "rpm") == 0) {
14568c2ecf20Sopenharmony_ci		fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER |
14578c2ecf20Sopenharmony_ci				   DL_FLAG_PM_RUNTIME;
14588c2ecf20Sopenharmony_ci	}
14598c2ecf20Sopenharmony_ci	return 0;
14608c2ecf20Sopenharmony_ci}
14618c2ecf20Sopenharmony_ciearly_param("fw_devlink", fw_devlink_setup);
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ciu32 fw_devlink_get_flags(void)
14648c2ecf20Sopenharmony_ci{
14658c2ecf20Sopenharmony_ci	return fw_devlink_flags;
14668c2ecf20Sopenharmony_ci}
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_cistatic bool fw_devlink_is_permissive(void)
14698c2ecf20Sopenharmony_ci{
14708c2ecf20Sopenharmony_ci	return fw_devlink_flags == DL_FLAG_SYNC_STATE_ONLY;
14718c2ecf20Sopenharmony_ci}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cistatic void fw_devlink_link_device(struct device *dev)
14748c2ecf20Sopenharmony_ci{
14758c2ecf20Sopenharmony_ci	int fw_ret;
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	if (!fw_devlink_flags)
14788c2ecf20Sopenharmony_ci		return;
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci	mutex_lock(&defer_fw_devlink_lock);
14818c2ecf20Sopenharmony_ci	if (!defer_fw_devlink_count)
14828c2ecf20Sopenharmony_ci		device_link_add_missing_supplier_links();
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	/*
14858c2ecf20Sopenharmony_ci	 * The device's fwnode not having add_links() doesn't affect if other
14868c2ecf20Sopenharmony_ci	 * consumers can find this device as a supplier.  So, this check is
14878c2ecf20Sopenharmony_ci	 * intentionally placed after device_link_add_missing_supplier_links().
14888c2ecf20Sopenharmony_ci	 */
14898c2ecf20Sopenharmony_ci	if (!fwnode_has_op(dev->fwnode, add_links))
14908c2ecf20Sopenharmony_ci		goto out;
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	/*
14938c2ecf20Sopenharmony_ci	 * If fw_devlink is being deferred, assume all devices have mandatory
14948c2ecf20Sopenharmony_ci	 * suppliers they need to link to later. Then, when the fw_devlink is
14958c2ecf20Sopenharmony_ci	 * resumed, all these devices will get a chance to try and link to any
14968c2ecf20Sopenharmony_ci	 * suppliers they have.
14978c2ecf20Sopenharmony_ci	 */
14988c2ecf20Sopenharmony_ci	if (!defer_fw_devlink_count) {
14998c2ecf20Sopenharmony_ci		fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
15008c2ecf20Sopenharmony_ci		if (fw_ret == -ENODEV && fw_devlink_is_permissive())
15018c2ecf20Sopenharmony_ci			fw_ret = -EAGAIN;
15028c2ecf20Sopenharmony_ci	} else {
15038c2ecf20Sopenharmony_ci		fw_ret = -ENODEV;
15048c2ecf20Sopenharmony_ci		/*
15058c2ecf20Sopenharmony_ci		 * defer_hook is not used to add device to deferred_sync list
15068c2ecf20Sopenharmony_ci		 * until device is bound. Since deferred fw devlink also blocks
15078c2ecf20Sopenharmony_ci		 * probing, same list hook can be used for deferred_fw_devlink.
15088c2ecf20Sopenharmony_ci		 */
15098c2ecf20Sopenharmony_ci		list_add_tail(&dev->links.defer_hook, &deferred_fw_devlink);
15108c2ecf20Sopenharmony_ci	}
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	if (fw_ret == -ENODEV)
15138c2ecf20Sopenharmony_ci		device_link_wait_for_mandatory_supplier(dev);
15148c2ecf20Sopenharmony_ci	else if (fw_ret)
15158c2ecf20Sopenharmony_ci		device_link_wait_for_optional_supplier(dev);
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ciout:
15188c2ecf20Sopenharmony_ci	mutex_unlock(&defer_fw_devlink_lock);
15198c2ecf20Sopenharmony_ci}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci/**
15228c2ecf20Sopenharmony_ci * fw_devlink_pause - Pause parsing of fwnode to create device links
15238c2ecf20Sopenharmony_ci *
15248c2ecf20Sopenharmony_ci * Calling this function defers any fwnode parsing to create device links until
15258c2ecf20Sopenharmony_ci * fw_devlink_resume() is called. Both these functions are ref counted and the
15268c2ecf20Sopenharmony_ci * caller needs to match the calls.
15278c2ecf20Sopenharmony_ci *
15288c2ecf20Sopenharmony_ci * While fw_devlink is paused:
15298c2ecf20Sopenharmony_ci * - Any device that is added won't have its fwnode parsed to create device
15308c2ecf20Sopenharmony_ci *   links.
15318c2ecf20Sopenharmony_ci * - The probe of the device will also be deferred during this period.
15328c2ecf20Sopenharmony_ci * - Any devices that were already added, but waiting for suppliers won't be
15338c2ecf20Sopenharmony_ci *   able to link to newly added devices.
15348c2ecf20Sopenharmony_ci *
15358c2ecf20Sopenharmony_ci * Once fw_devlink_resume():
15368c2ecf20Sopenharmony_ci * - All the fwnodes that was not parsed will be parsed.
15378c2ecf20Sopenharmony_ci * - All the devices that were deferred probing will be reattempted if they
15388c2ecf20Sopenharmony_ci *   aren't waiting for any more suppliers.
15398c2ecf20Sopenharmony_ci *
15408c2ecf20Sopenharmony_ci * This pair of functions, is mainly meant to optimize the parsing of fwnodes
15418c2ecf20Sopenharmony_ci * when a lot of devices that need to link to each other are added in a short
15428c2ecf20Sopenharmony_ci * interval of time. For example, adding all the top level devices in a system.
15438c2ecf20Sopenharmony_ci *
15448c2ecf20Sopenharmony_ci * For example, if N devices are added and:
15458c2ecf20Sopenharmony_ci * - All the consumers are added before their suppliers
15468c2ecf20Sopenharmony_ci * - All the suppliers of the N devices are part of the N devices
15478c2ecf20Sopenharmony_ci *
15488c2ecf20Sopenharmony_ci * Then:
15498c2ecf20Sopenharmony_ci *
15508c2ecf20Sopenharmony_ci * - With the use of fw_devlink_pause() and fw_devlink_resume(), each device
15518c2ecf20Sopenharmony_ci *   will only need one parsing of its fwnode because it is guaranteed to find
15528c2ecf20Sopenharmony_ci *   all the supplier devices already registered and ready to link to. It won't
15538c2ecf20Sopenharmony_ci *   have to do another pass later to find one or more suppliers it couldn't
15548c2ecf20Sopenharmony_ci *   find in the first parse of the fwnode. So, we'll only need O(N) fwnode
15558c2ecf20Sopenharmony_ci *   parses.
15568c2ecf20Sopenharmony_ci *
15578c2ecf20Sopenharmony_ci * - Without the use of fw_devlink_pause() and fw_devlink_resume(), we would
15588c2ecf20Sopenharmony_ci *   end up doing O(N^2) parses of fwnodes because every device that's added is
15598c2ecf20Sopenharmony_ci *   guaranteed to trigger a parse of the fwnode of every device added before
15608c2ecf20Sopenharmony_ci *   it. This O(N^2) parse is made worse by the fact that when a fwnode of a
15618c2ecf20Sopenharmony_ci *   device is parsed, all it descendant devices might need to have their
15628c2ecf20Sopenharmony_ci *   fwnodes parsed too (even if the devices themselves aren't added).
15638c2ecf20Sopenharmony_ci */
15648c2ecf20Sopenharmony_civoid fw_devlink_pause(void)
15658c2ecf20Sopenharmony_ci{
15668c2ecf20Sopenharmony_ci	mutex_lock(&defer_fw_devlink_lock);
15678c2ecf20Sopenharmony_ci	defer_fw_devlink_count++;
15688c2ecf20Sopenharmony_ci	mutex_unlock(&defer_fw_devlink_lock);
15698c2ecf20Sopenharmony_ci}
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci/** fw_devlink_resume - Resume parsing of fwnode to create device links
15728c2ecf20Sopenharmony_ci *
15738c2ecf20Sopenharmony_ci * This function is used in conjunction with fw_devlink_pause() and is ref
15748c2ecf20Sopenharmony_ci * counted. See documentation for fw_devlink_pause() for more details.
15758c2ecf20Sopenharmony_ci */
15768c2ecf20Sopenharmony_civoid fw_devlink_resume(void)
15778c2ecf20Sopenharmony_ci{
15788c2ecf20Sopenharmony_ci	struct device *dev, *tmp;
15798c2ecf20Sopenharmony_ci	LIST_HEAD(probe_list);
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	mutex_lock(&defer_fw_devlink_lock);
15828c2ecf20Sopenharmony_ci	if (!defer_fw_devlink_count) {
15838c2ecf20Sopenharmony_ci		WARN(true, "Unmatched fw_devlink pause/resume!");
15848c2ecf20Sopenharmony_ci		goto out;
15858c2ecf20Sopenharmony_ci	}
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	defer_fw_devlink_count--;
15888c2ecf20Sopenharmony_ci	if (defer_fw_devlink_count)
15898c2ecf20Sopenharmony_ci		goto out;
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	device_link_add_missing_supplier_links();
15928c2ecf20Sopenharmony_ci	list_splice_tail_init(&deferred_fw_devlink, &probe_list);
15938c2ecf20Sopenharmony_ciout:
15948c2ecf20Sopenharmony_ci	mutex_unlock(&defer_fw_devlink_lock);
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	/*
15978c2ecf20Sopenharmony_ci	 * bus_probe_device() can cause new devices to get added and they'll
15988c2ecf20Sopenharmony_ci	 * try to grab defer_fw_devlink_lock. So, this needs to be done outside
15998c2ecf20Sopenharmony_ci	 * the defer_fw_devlink_lock.
16008c2ecf20Sopenharmony_ci	 */
16018c2ecf20Sopenharmony_ci	list_for_each_entry_safe(dev, tmp, &probe_list, links.defer_hook) {
16028c2ecf20Sopenharmony_ci		list_del_init(&dev->links.defer_hook);
16038c2ecf20Sopenharmony_ci		bus_probe_device(dev);
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci}
16068c2ecf20Sopenharmony_ci/* Device links support end. */
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ciint (*platform_notify)(struct device *dev) = NULL;
16098c2ecf20Sopenharmony_ciint (*platform_notify_remove)(struct device *dev) = NULL;
16108c2ecf20Sopenharmony_cistatic struct kobject *dev_kobj;
16118c2ecf20Sopenharmony_cistruct kobject *sysfs_dev_char_kobj;
16128c2ecf20Sopenharmony_cistruct kobject *sysfs_dev_block_kobj;
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(device_hotplug_lock);
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_civoid lock_device_hotplug(void)
16178c2ecf20Sopenharmony_ci{
16188c2ecf20Sopenharmony_ci	mutex_lock(&device_hotplug_lock);
16198c2ecf20Sopenharmony_ci}
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_civoid unlock_device_hotplug(void)
16228c2ecf20Sopenharmony_ci{
16238c2ecf20Sopenharmony_ci	mutex_unlock(&device_hotplug_lock);
16248c2ecf20Sopenharmony_ci}
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ciint lock_device_hotplug_sysfs(void)
16278c2ecf20Sopenharmony_ci{
16288c2ecf20Sopenharmony_ci	if (mutex_trylock(&device_hotplug_lock))
16298c2ecf20Sopenharmony_ci		return 0;
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci	/* Avoid busy looping (5 ms of sleep should do). */
16328c2ecf20Sopenharmony_ci	msleep(5);
16338c2ecf20Sopenharmony_ci	return restart_syscall();
16348c2ecf20Sopenharmony_ci}
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci#ifdef CONFIG_BLOCK
16378c2ecf20Sopenharmony_cistatic inline int device_is_not_partition(struct device *dev)
16388c2ecf20Sopenharmony_ci{
16398c2ecf20Sopenharmony_ci	return !(dev->type == &part_type);
16408c2ecf20Sopenharmony_ci}
16418c2ecf20Sopenharmony_ci#else
16428c2ecf20Sopenharmony_cistatic inline int device_is_not_partition(struct device *dev)
16438c2ecf20Sopenharmony_ci{
16448c2ecf20Sopenharmony_ci	return 1;
16458c2ecf20Sopenharmony_ci}
16468c2ecf20Sopenharmony_ci#endif
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_cistatic int
16498c2ecf20Sopenharmony_cidevice_platform_notify(struct device *dev, enum kobject_action action)
16508c2ecf20Sopenharmony_ci{
16518c2ecf20Sopenharmony_ci	int ret;
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci	ret = acpi_platform_notify(dev, action);
16548c2ecf20Sopenharmony_ci	if (ret)
16558c2ecf20Sopenharmony_ci		return ret;
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	ret = software_node_notify(dev, action);
16588c2ecf20Sopenharmony_ci	if (ret)
16598c2ecf20Sopenharmony_ci		return ret;
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	if (platform_notify && action == KOBJ_ADD)
16628c2ecf20Sopenharmony_ci		platform_notify(dev);
16638c2ecf20Sopenharmony_ci	else if (platform_notify_remove && action == KOBJ_REMOVE)
16648c2ecf20Sopenharmony_ci		platform_notify_remove(dev);
16658c2ecf20Sopenharmony_ci	return 0;
16668c2ecf20Sopenharmony_ci}
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci/**
16698c2ecf20Sopenharmony_ci * dev_driver_string - Return a device's driver name, if at all possible
16708c2ecf20Sopenharmony_ci * @dev: struct device to get the name of
16718c2ecf20Sopenharmony_ci *
16728c2ecf20Sopenharmony_ci * Will return the device's driver's name if it is bound to a device.  If
16738c2ecf20Sopenharmony_ci * the device is not bound to a driver, it will return the name of the bus
16748c2ecf20Sopenharmony_ci * it is attached to.  If it is not attached to a bus either, an empty
16758c2ecf20Sopenharmony_ci * string will be returned.
16768c2ecf20Sopenharmony_ci */
16778c2ecf20Sopenharmony_ciconst char *dev_driver_string(const struct device *dev)
16788c2ecf20Sopenharmony_ci{
16798c2ecf20Sopenharmony_ci	struct device_driver *drv;
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci	/* dev->driver can change to NULL underneath us because of unbinding,
16828c2ecf20Sopenharmony_ci	 * so be careful about accessing it.  dev->bus and dev->class should
16838c2ecf20Sopenharmony_ci	 * never change once they are set, so they don't need special care.
16848c2ecf20Sopenharmony_ci	 */
16858c2ecf20Sopenharmony_ci	drv = READ_ONCE(dev->driver);
16868c2ecf20Sopenharmony_ci	return drv ? drv->name : dev_bus_name(dev);
16878c2ecf20Sopenharmony_ci}
16888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dev_driver_string);
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_cistatic ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
16938c2ecf20Sopenharmony_ci			     char *buf)
16948c2ecf20Sopenharmony_ci{
16958c2ecf20Sopenharmony_ci	struct device_attribute *dev_attr = to_dev_attr(attr);
16968c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
16978c2ecf20Sopenharmony_ci	ssize_t ret = -EIO;
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	if (dev_attr->show)
17008c2ecf20Sopenharmony_ci		ret = dev_attr->show(dev, dev_attr, buf);
17018c2ecf20Sopenharmony_ci	if (ret >= (ssize_t)PAGE_SIZE) {
17028c2ecf20Sopenharmony_ci		printk("dev_attr_show: %pS returned bad count\n",
17038c2ecf20Sopenharmony_ci				dev_attr->show);
17048c2ecf20Sopenharmony_ci	}
17058c2ecf20Sopenharmony_ci	return ret;
17068c2ecf20Sopenharmony_ci}
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_cistatic ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
17098c2ecf20Sopenharmony_ci			      const char *buf, size_t count)
17108c2ecf20Sopenharmony_ci{
17118c2ecf20Sopenharmony_ci	struct device_attribute *dev_attr = to_dev_attr(attr);
17128c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
17138c2ecf20Sopenharmony_ci	ssize_t ret = -EIO;
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	if (dev_attr->store)
17168c2ecf20Sopenharmony_ci		ret = dev_attr->store(dev, dev_attr, buf, count);
17178c2ecf20Sopenharmony_ci	return ret;
17188c2ecf20Sopenharmony_ci}
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_cistatic const struct sysfs_ops dev_sysfs_ops = {
17218c2ecf20Sopenharmony_ci	.show	= dev_attr_show,
17228c2ecf20Sopenharmony_ci	.store	= dev_attr_store,
17238c2ecf20Sopenharmony_ci};
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr)
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_cissize_t device_store_ulong(struct device *dev,
17288c2ecf20Sopenharmony_ci			   struct device_attribute *attr,
17298c2ecf20Sopenharmony_ci			   const char *buf, size_t size)
17308c2ecf20Sopenharmony_ci{
17318c2ecf20Sopenharmony_ci	struct dev_ext_attribute *ea = to_ext_attr(attr);
17328c2ecf20Sopenharmony_ci	int ret;
17338c2ecf20Sopenharmony_ci	unsigned long new;
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	ret = kstrtoul(buf, 0, &new);
17368c2ecf20Sopenharmony_ci	if (ret)
17378c2ecf20Sopenharmony_ci		return ret;
17388c2ecf20Sopenharmony_ci	*(unsigned long *)(ea->var) = new;
17398c2ecf20Sopenharmony_ci	/* Always return full write size even if we didn't consume all */
17408c2ecf20Sopenharmony_ci	return size;
17418c2ecf20Sopenharmony_ci}
17428c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_store_ulong);
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_cissize_t device_show_ulong(struct device *dev,
17458c2ecf20Sopenharmony_ci			  struct device_attribute *attr,
17468c2ecf20Sopenharmony_ci			  char *buf)
17478c2ecf20Sopenharmony_ci{
17488c2ecf20Sopenharmony_ci	struct dev_ext_attribute *ea = to_ext_attr(attr);
17498c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%lx\n", *(unsigned long *)(ea->var));
17508c2ecf20Sopenharmony_ci}
17518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_show_ulong);
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_cissize_t device_store_int(struct device *dev,
17548c2ecf20Sopenharmony_ci			 struct device_attribute *attr,
17558c2ecf20Sopenharmony_ci			 const char *buf, size_t size)
17568c2ecf20Sopenharmony_ci{
17578c2ecf20Sopenharmony_ci	struct dev_ext_attribute *ea = to_ext_attr(attr);
17588c2ecf20Sopenharmony_ci	int ret;
17598c2ecf20Sopenharmony_ci	long new;
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	ret = kstrtol(buf, 0, &new);
17628c2ecf20Sopenharmony_ci	if (ret)
17638c2ecf20Sopenharmony_ci		return ret;
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	if (new > INT_MAX || new < INT_MIN)
17668c2ecf20Sopenharmony_ci		return -EINVAL;
17678c2ecf20Sopenharmony_ci	*(int *)(ea->var) = new;
17688c2ecf20Sopenharmony_ci	/* Always return full write size even if we didn't consume all */
17698c2ecf20Sopenharmony_ci	return size;
17708c2ecf20Sopenharmony_ci}
17718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_store_int);
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_cissize_t device_show_int(struct device *dev,
17748c2ecf20Sopenharmony_ci			struct device_attribute *attr,
17758c2ecf20Sopenharmony_ci			char *buf)
17768c2ecf20Sopenharmony_ci{
17778c2ecf20Sopenharmony_ci	struct dev_ext_attribute *ea = to_ext_attr(attr);
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%d\n", *(int *)(ea->var));
17808c2ecf20Sopenharmony_ci}
17818c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_show_int);
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_cissize_t device_store_bool(struct device *dev, struct device_attribute *attr,
17848c2ecf20Sopenharmony_ci			  const char *buf, size_t size)
17858c2ecf20Sopenharmony_ci{
17868c2ecf20Sopenharmony_ci	struct dev_ext_attribute *ea = to_ext_attr(attr);
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	if (strtobool(buf, ea->var) < 0)
17898c2ecf20Sopenharmony_ci		return -EINVAL;
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	return size;
17928c2ecf20Sopenharmony_ci}
17938c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_store_bool);
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_cissize_t device_show_bool(struct device *dev, struct device_attribute *attr,
17968c2ecf20Sopenharmony_ci			 char *buf)
17978c2ecf20Sopenharmony_ci{
17988c2ecf20Sopenharmony_ci	struct dev_ext_attribute *ea = to_ext_attr(attr);
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%d\n", *(bool *)(ea->var));
18018c2ecf20Sopenharmony_ci}
18028c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_show_bool);
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci/**
18058c2ecf20Sopenharmony_ci * device_release - free device structure.
18068c2ecf20Sopenharmony_ci * @kobj: device's kobject.
18078c2ecf20Sopenharmony_ci *
18088c2ecf20Sopenharmony_ci * This is called once the reference count for the object
18098c2ecf20Sopenharmony_ci * reaches 0. We forward the call to the device's release
18108c2ecf20Sopenharmony_ci * method, which should handle actually freeing the structure.
18118c2ecf20Sopenharmony_ci */
18128c2ecf20Sopenharmony_cistatic void device_release(struct kobject *kobj)
18138c2ecf20Sopenharmony_ci{
18148c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
18158c2ecf20Sopenharmony_ci	struct device_private *p = dev->p;
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci	/*
18188c2ecf20Sopenharmony_ci	 * Some platform devices are driven without driver attached
18198c2ecf20Sopenharmony_ci	 * and managed resources may have been acquired.  Make sure
18208c2ecf20Sopenharmony_ci	 * all resources are released.
18218c2ecf20Sopenharmony_ci	 *
18228c2ecf20Sopenharmony_ci	 * Drivers still can add resources into device after device
18238c2ecf20Sopenharmony_ci	 * is deleted but alive, so release devres here to avoid
18248c2ecf20Sopenharmony_ci	 * possible memory leak.
18258c2ecf20Sopenharmony_ci	 */
18268c2ecf20Sopenharmony_ci	devres_release_all(dev);
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci	kfree(dev->dma_range_map);
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	if (dev->release)
18318c2ecf20Sopenharmony_ci		dev->release(dev);
18328c2ecf20Sopenharmony_ci	else if (dev->type && dev->type->release)
18338c2ecf20Sopenharmony_ci		dev->type->release(dev);
18348c2ecf20Sopenharmony_ci	else if (dev->class && dev->class->dev_release)
18358c2ecf20Sopenharmony_ci		dev->class->dev_release(dev);
18368c2ecf20Sopenharmony_ci	else
18378c2ecf20Sopenharmony_ci		WARN(1, KERN_ERR "Device '%s' does not have a release() function, it is broken and must be fixed. See Documentation/core-api/kobject.rst.\n",
18388c2ecf20Sopenharmony_ci			dev_name(dev));
18398c2ecf20Sopenharmony_ci	kfree(p);
18408c2ecf20Sopenharmony_ci}
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_cistatic const void *device_namespace(struct kobject *kobj)
18438c2ecf20Sopenharmony_ci{
18448c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
18458c2ecf20Sopenharmony_ci	const void *ns = NULL;
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci	if (dev->class && dev->class->ns_type)
18488c2ecf20Sopenharmony_ci		ns = dev->class->namespace(dev);
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	return ns;
18518c2ecf20Sopenharmony_ci}
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_cistatic void device_get_ownership(struct kobject *kobj, kuid_t *uid, kgid_t *gid)
18548c2ecf20Sopenharmony_ci{
18558c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci	if (dev->class && dev->class->get_ownership)
18588c2ecf20Sopenharmony_ci		dev->class->get_ownership(dev, uid, gid);
18598c2ecf20Sopenharmony_ci}
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_cistatic struct kobj_type device_ktype = {
18628c2ecf20Sopenharmony_ci	.release	= device_release,
18638c2ecf20Sopenharmony_ci	.sysfs_ops	= &dev_sysfs_ops,
18648c2ecf20Sopenharmony_ci	.namespace	= device_namespace,
18658c2ecf20Sopenharmony_ci	.get_ownership	= device_get_ownership,
18668c2ecf20Sopenharmony_ci};
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_cistatic int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
18708c2ecf20Sopenharmony_ci{
18718c2ecf20Sopenharmony_ci	struct kobj_type *ktype = get_ktype(kobj);
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_ci	if (ktype == &device_ktype) {
18748c2ecf20Sopenharmony_ci		struct device *dev = kobj_to_dev(kobj);
18758c2ecf20Sopenharmony_ci		if (dev->bus)
18768c2ecf20Sopenharmony_ci			return 1;
18778c2ecf20Sopenharmony_ci		if (dev->class)
18788c2ecf20Sopenharmony_ci			return 1;
18798c2ecf20Sopenharmony_ci	}
18808c2ecf20Sopenharmony_ci	return 0;
18818c2ecf20Sopenharmony_ci}
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_cistatic const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
18848c2ecf20Sopenharmony_ci{
18858c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci	if (dev->bus)
18888c2ecf20Sopenharmony_ci		return dev->bus->name;
18898c2ecf20Sopenharmony_ci	if (dev->class)
18908c2ecf20Sopenharmony_ci		return dev->class->name;
18918c2ecf20Sopenharmony_ci	return NULL;
18928c2ecf20Sopenharmony_ci}
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_cistatic int dev_uevent(struct kset *kset, struct kobject *kobj,
18958c2ecf20Sopenharmony_ci		      struct kobj_uevent_env *env)
18968c2ecf20Sopenharmony_ci{
18978c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
18988c2ecf20Sopenharmony_ci	struct device_driver *driver;
18998c2ecf20Sopenharmony_ci	int retval = 0;
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	/* add device node properties if present */
19028c2ecf20Sopenharmony_ci	if (MAJOR(dev->devt)) {
19038c2ecf20Sopenharmony_ci		const char *tmp;
19048c2ecf20Sopenharmony_ci		const char *name;
19058c2ecf20Sopenharmony_ci		umode_t mode = 0;
19068c2ecf20Sopenharmony_ci		kuid_t uid = GLOBAL_ROOT_UID;
19078c2ecf20Sopenharmony_ci		kgid_t gid = GLOBAL_ROOT_GID;
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci		add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
19108c2ecf20Sopenharmony_ci		add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
19118c2ecf20Sopenharmony_ci		name = device_get_devnode(dev, &mode, &uid, &gid, &tmp);
19128c2ecf20Sopenharmony_ci		if (name) {
19138c2ecf20Sopenharmony_ci			add_uevent_var(env, "DEVNAME=%s", name);
19148c2ecf20Sopenharmony_ci			if (mode)
19158c2ecf20Sopenharmony_ci				add_uevent_var(env, "DEVMODE=%#o", mode & 0777);
19168c2ecf20Sopenharmony_ci			if (!uid_eq(uid, GLOBAL_ROOT_UID))
19178c2ecf20Sopenharmony_ci				add_uevent_var(env, "DEVUID=%u", from_kuid(&init_user_ns, uid));
19188c2ecf20Sopenharmony_ci			if (!gid_eq(gid, GLOBAL_ROOT_GID))
19198c2ecf20Sopenharmony_ci				add_uevent_var(env, "DEVGID=%u", from_kgid(&init_user_ns, gid));
19208c2ecf20Sopenharmony_ci			kfree(tmp);
19218c2ecf20Sopenharmony_ci		}
19228c2ecf20Sopenharmony_ci	}
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci	if (dev->type && dev->type->name)
19258c2ecf20Sopenharmony_ci		add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	/* Synchronize with module_remove_driver() */
19288c2ecf20Sopenharmony_ci	rcu_read_lock();
19298c2ecf20Sopenharmony_ci	driver = READ_ONCE(dev->driver);
19308c2ecf20Sopenharmony_ci	if (driver)
19318c2ecf20Sopenharmony_ci		add_uevent_var(env, "DRIVER=%s", driver->name);
19328c2ecf20Sopenharmony_ci	rcu_read_unlock();
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci	/* Add common DT information about the device */
19358c2ecf20Sopenharmony_ci	of_device_uevent(dev, env);
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ci	/* have the bus specific function add its stuff */
19388c2ecf20Sopenharmony_ci	if (dev->bus && dev->bus->uevent) {
19398c2ecf20Sopenharmony_ci		retval = dev->bus->uevent(dev, env);
19408c2ecf20Sopenharmony_ci		if (retval)
19418c2ecf20Sopenharmony_ci			pr_debug("device: '%s': %s: bus uevent() returned %d\n",
19428c2ecf20Sopenharmony_ci				 dev_name(dev), __func__, retval);
19438c2ecf20Sopenharmony_ci	}
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci	/* have the class specific function add its stuff */
19468c2ecf20Sopenharmony_ci	if (dev->class && dev->class->dev_uevent) {
19478c2ecf20Sopenharmony_ci		retval = dev->class->dev_uevent(dev, env);
19488c2ecf20Sopenharmony_ci		if (retval)
19498c2ecf20Sopenharmony_ci			pr_debug("device: '%s': %s: class uevent() "
19508c2ecf20Sopenharmony_ci				 "returned %d\n", dev_name(dev),
19518c2ecf20Sopenharmony_ci				 __func__, retval);
19528c2ecf20Sopenharmony_ci	}
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_ci	/* have the device type specific function add its stuff */
19558c2ecf20Sopenharmony_ci	if (dev->type && dev->type->uevent) {
19568c2ecf20Sopenharmony_ci		retval = dev->type->uevent(dev, env);
19578c2ecf20Sopenharmony_ci		if (retval)
19588c2ecf20Sopenharmony_ci			pr_debug("device: '%s': %s: dev_type uevent() "
19598c2ecf20Sopenharmony_ci				 "returned %d\n", dev_name(dev),
19608c2ecf20Sopenharmony_ci				 __func__, retval);
19618c2ecf20Sopenharmony_ci	}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_ci	return retval;
19648c2ecf20Sopenharmony_ci}
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_cistatic const struct kset_uevent_ops device_uevent_ops = {
19678c2ecf20Sopenharmony_ci	.filter =	dev_uevent_filter,
19688c2ecf20Sopenharmony_ci	.name =		dev_uevent_name,
19698c2ecf20Sopenharmony_ci	.uevent =	dev_uevent,
19708c2ecf20Sopenharmony_ci};
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_cistatic ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
19738c2ecf20Sopenharmony_ci			   char *buf)
19748c2ecf20Sopenharmony_ci{
19758c2ecf20Sopenharmony_ci	struct kobject *top_kobj;
19768c2ecf20Sopenharmony_ci	struct kset *kset;
19778c2ecf20Sopenharmony_ci	struct kobj_uevent_env *env = NULL;
19788c2ecf20Sopenharmony_ci	int i;
19798c2ecf20Sopenharmony_ci	int len = 0;
19808c2ecf20Sopenharmony_ci	int retval;
19818c2ecf20Sopenharmony_ci
19828c2ecf20Sopenharmony_ci	/* search the kset, the device belongs to */
19838c2ecf20Sopenharmony_ci	top_kobj = &dev->kobj;
19848c2ecf20Sopenharmony_ci	while (!top_kobj->kset && top_kobj->parent)
19858c2ecf20Sopenharmony_ci		top_kobj = top_kobj->parent;
19868c2ecf20Sopenharmony_ci	if (!top_kobj->kset)
19878c2ecf20Sopenharmony_ci		goto out;
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	kset = top_kobj->kset;
19908c2ecf20Sopenharmony_ci	if (!kset->uevent_ops || !kset->uevent_ops->uevent)
19918c2ecf20Sopenharmony_ci		goto out;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	/* respect filter */
19948c2ecf20Sopenharmony_ci	if (kset->uevent_ops && kset->uevent_ops->filter)
19958c2ecf20Sopenharmony_ci		if (!kset->uevent_ops->filter(kset, &dev->kobj))
19968c2ecf20Sopenharmony_ci			goto out;
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci	env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
19998c2ecf20Sopenharmony_ci	if (!env)
20008c2ecf20Sopenharmony_ci		return -ENOMEM;
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci	/* let the kset specific function add its keys */
20038c2ecf20Sopenharmony_ci	retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
20048c2ecf20Sopenharmony_ci	if (retval)
20058c2ecf20Sopenharmony_ci		goto out;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	/* copy keys to file */
20088c2ecf20Sopenharmony_ci	for (i = 0; i < env->envp_idx; i++)
20098c2ecf20Sopenharmony_ci		len += sysfs_emit_at(buf, len, "%s\n", env->envp[i]);
20108c2ecf20Sopenharmony_ciout:
20118c2ecf20Sopenharmony_ci	kfree(env);
20128c2ecf20Sopenharmony_ci	return len;
20138c2ecf20Sopenharmony_ci}
20148c2ecf20Sopenharmony_ci
20158c2ecf20Sopenharmony_cistatic ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
20168c2ecf20Sopenharmony_ci			    const char *buf, size_t count)
20178c2ecf20Sopenharmony_ci{
20188c2ecf20Sopenharmony_ci	int rc;
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ci	rc = kobject_synth_uevent(&dev->kobj, buf, count);
20218c2ecf20Sopenharmony_ci
20228c2ecf20Sopenharmony_ci	if (rc) {
20238c2ecf20Sopenharmony_ci		dev_err(dev, "uevent: failed to send synthetic uevent\n");
20248c2ecf20Sopenharmony_ci		return rc;
20258c2ecf20Sopenharmony_ci	}
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	return count;
20288c2ecf20Sopenharmony_ci}
20298c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(uevent);
20308c2ecf20Sopenharmony_ci
20318c2ecf20Sopenharmony_cistatic ssize_t online_show(struct device *dev, struct device_attribute *attr,
20328c2ecf20Sopenharmony_ci			   char *buf)
20338c2ecf20Sopenharmony_ci{
20348c2ecf20Sopenharmony_ci	bool val;
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	device_lock(dev);
20378c2ecf20Sopenharmony_ci	val = !dev->offline;
20388c2ecf20Sopenharmony_ci	device_unlock(dev);
20398c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%u\n", val);
20408c2ecf20Sopenharmony_ci}
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_cistatic ssize_t online_store(struct device *dev, struct device_attribute *attr,
20438c2ecf20Sopenharmony_ci			    const char *buf, size_t count)
20448c2ecf20Sopenharmony_ci{
20458c2ecf20Sopenharmony_ci	bool val;
20468c2ecf20Sopenharmony_ci	int ret;
20478c2ecf20Sopenharmony_ci
20488c2ecf20Sopenharmony_ci	ret = strtobool(buf, &val);
20498c2ecf20Sopenharmony_ci	if (ret < 0)
20508c2ecf20Sopenharmony_ci		return ret;
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	ret = lock_device_hotplug_sysfs();
20538c2ecf20Sopenharmony_ci	if (ret)
20548c2ecf20Sopenharmony_ci		return ret;
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	ret = val ? device_online(dev) : device_offline(dev);
20578c2ecf20Sopenharmony_ci	unlock_device_hotplug();
20588c2ecf20Sopenharmony_ci	return ret < 0 ? ret : count;
20598c2ecf20Sopenharmony_ci}
20608c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(online);
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_cistatic ssize_t removable_show(struct device *dev, struct device_attribute *attr,
20638c2ecf20Sopenharmony_ci			      char *buf)
20648c2ecf20Sopenharmony_ci{
20658c2ecf20Sopenharmony_ci	const char *loc;
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci	switch (dev->removable) {
20688c2ecf20Sopenharmony_ci	case DEVICE_REMOVABLE:
20698c2ecf20Sopenharmony_ci		loc = "removable";
20708c2ecf20Sopenharmony_ci		break;
20718c2ecf20Sopenharmony_ci	case DEVICE_FIXED:
20728c2ecf20Sopenharmony_ci		loc = "fixed";
20738c2ecf20Sopenharmony_ci		break;
20748c2ecf20Sopenharmony_ci	default:
20758c2ecf20Sopenharmony_ci		loc = "unknown";
20768c2ecf20Sopenharmony_ci	}
20778c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%s\n", loc);
20788c2ecf20Sopenharmony_ci}
20798c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(removable);
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ciint device_add_groups(struct device *dev, const struct attribute_group **groups)
20828c2ecf20Sopenharmony_ci{
20838c2ecf20Sopenharmony_ci	return sysfs_create_groups(&dev->kobj, groups);
20848c2ecf20Sopenharmony_ci}
20858c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_add_groups);
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_civoid device_remove_groups(struct device *dev,
20888c2ecf20Sopenharmony_ci			  const struct attribute_group **groups)
20898c2ecf20Sopenharmony_ci{
20908c2ecf20Sopenharmony_ci	sysfs_remove_groups(&dev->kobj, groups);
20918c2ecf20Sopenharmony_ci}
20928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_remove_groups);
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ciunion device_attr_group_devres {
20958c2ecf20Sopenharmony_ci	const struct attribute_group *group;
20968c2ecf20Sopenharmony_ci	const struct attribute_group **groups;
20978c2ecf20Sopenharmony_ci};
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_cistatic int devm_attr_group_match(struct device *dev, void *res, void *data)
21008c2ecf20Sopenharmony_ci{
21018c2ecf20Sopenharmony_ci	return ((union device_attr_group_devres *)res)->group == data;
21028c2ecf20Sopenharmony_ci}
21038c2ecf20Sopenharmony_ci
21048c2ecf20Sopenharmony_cistatic void devm_attr_group_remove(struct device *dev, void *res)
21058c2ecf20Sopenharmony_ci{
21068c2ecf20Sopenharmony_ci	union device_attr_group_devres *devres = res;
21078c2ecf20Sopenharmony_ci	const struct attribute_group *group = devres->group;
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: removing group %p\n", __func__, group);
21108c2ecf20Sopenharmony_ci	sysfs_remove_group(&dev->kobj, group);
21118c2ecf20Sopenharmony_ci}
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_cistatic void devm_attr_groups_remove(struct device *dev, void *res)
21148c2ecf20Sopenharmony_ci{
21158c2ecf20Sopenharmony_ci	union device_attr_group_devres *devres = res;
21168c2ecf20Sopenharmony_ci	const struct attribute_group **groups = devres->groups;
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s: removing groups %p\n", __func__, groups);
21198c2ecf20Sopenharmony_ci	sysfs_remove_groups(&dev->kobj, groups);
21208c2ecf20Sopenharmony_ci}
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci/**
21238c2ecf20Sopenharmony_ci * devm_device_add_group - given a device, create a managed attribute group
21248c2ecf20Sopenharmony_ci * @dev:	The device to create the group for
21258c2ecf20Sopenharmony_ci * @grp:	The attribute group to create
21268c2ecf20Sopenharmony_ci *
21278c2ecf20Sopenharmony_ci * This function creates a group for the first time.  It will explicitly
21288c2ecf20Sopenharmony_ci * warn and error if any of the attribute files being created already exist.
21298c2ecf20Sopenharmony_ci *
21308c2ecf20Sopenharmony_ci * Returns 0 on success or error code on failure.
21318c2ecf20Sopenharmony_ci */
21328c2ecf20Sopenharmony_ciint devm_device_add_group(struct device *dev, const struct attribute_group *grp)
21338c2ecf20Sopenharmony_ci{
21348c2ecf20Sopenharmony_ci	union device_attr_group_devres *devres;
21358c2ecf20Sopenharmony_ci	int error;
21368c2ecf20Sopenharmony_ci
21378c2ecf20Sopenharmony_ci	devres = devres_alloc(devm_attr_group_remove,
21388c2ecf20Sopenharmony_ci			      sizeof(*devres), GFP_KERNEL);
21398c2ecf20Sopenharmony_ci	if (!devres)
21408c2ecf20Sopenharmony_ci		return -ENOMEM;
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_ci	error = sysfs_create_group(&dev->kobj, grp);
21438c2ecf20Sopenharmony_ci	if (error) {
21448c2ecf20Sopenharmony_ci		devres_free(devres);
21458c2ecf20Sopenharmony_ci		return error;
21468c2ecf20Sopenharmony_ci	}
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	devres->group = grp;
21498c2ecf20Sopenharmony_ci	devres_add(dev, devres);
21508c2ecf20Sopenharmony_ci	return 0;
21518c2ecf20Sopenharmony_ci}
21528c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_device_add_group);
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci/**
21558c2ecf20Sopenharmony_ci * devm_device_remove_group: remove a managed group from a device
21568c2ecf20Sopenharmony_ci * @dev:	device to remove the group from
21578c2ecf20Sopenharmony_ci * @grp:	group to remove
21588c2ecf20Sopenharmony_ci *
21598c2ecf20Sopenharmony_ci * This function removes a group of attributes from a device. The attributes
21608c2ecf20Sopenharmony_ci * previously have to have been created for this group, otherwise it will fail.
21618c2ecf20Sopenharmony_ci */
21628c2ecf20Sopenharmony_civoid devm_device_remove_group(struct device *dev,
21638c2ecf20Sopenharmony_ci			      const struct attribute_group *grp)
21648c2ecf20Sopenharmony_ci{
21658c2ecf20Sopenharmony_ci	WARN_ON(devres_release(dev, devm_attr_group_remove,
21668c2ecf20Sopenharmony_ci			       devm_attr_group_match,
21678c2ecf20Sopenharmony_ci			       /* cast away const */ (void *)grp));
21688c2ecf20Sopenharmony_ci}
21698c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_device_remove_group);
21708c2ecf20Sopenharmony_ci
21718c2ecf20Sopenharmony_ci/**
21728c2ecf20Sopenharmony_ci * devm_device_add_groups - create a bunch of managed attribute groups
21738c2ecf20Sopenharmony_ci * @dev:	The device to create the group for
21748c2ecf20Sopenharmony_ci * @groups:	The attribute groups to create, NULL terminated
21758c2ecf20Sopenharmony_ci *
21768c2ecf20Sopenharmony_ci * This function creates a bunch of managed attribute groups.  If an error
21778c2ecf20Sopenharmony_ci * occurs when creating a group, all previously created groups will be
21788c2ecf20Sopenharmony_ci * removed, unwinding everything back to the original state when this
21798c2ecf20Sopenharmony_ci * function was called.  It will explicitly warn and error if any of the
21808c2ecf20Sopenharmony_ci * attribute files being created already exist.
21818c2ecf20Sopenharmony_ci *
21828c2ecf20Sopenharmony_ci * Returns 0 on success or error code from sysfs_create_group on failure.
21838c2ecf20Sopenharmony_ci */
21848c2ecf20Sopenharmony_ciint devm_device_add_groups(struct device *dev,
21858c2ecf20Sopenharmony_ci			   const struct attribute_group **groups)
21868c2ecf20Sopenharmony_ci{
21878c2ecf20Sopenharmony_ci	union device_attr_group_devres *devres;
21888c2ecf20Sopenharmony_ci	int error;
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	devres = devres_alloc(devm_attr_groups_remove,
21918c2ecf20Sopenharmony_ci			      sizeof(*devres), GFP_KERNEL);
21928c2ecf20Sopenharmony_ci	if (!devres)
21938c2ecf20Sopenharmony_ci		return -ENOMEM;
21948c2ecf20Sopenharmony_ci
21958c2ecf20Sopenharmony_ci	error = sysfs_create_groups(&dev->kobj, groups);
21968c2ecf20Sopenharmony_ci	if (error) {
21978c2ecf20Sopenharmony_ci		devres_free(devres);
21988c2ecf20Sopenharmony_ci		return error;
21998c2ecf20Sopenharmony_ci	}
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ci	devres->groups = groups;
22028c2ecf20Sopenharmony_ci	devres_add(dev, devres);
22038c2ecf20Sopenharmony_ci	return 0;
22048c2ecf20Sopenharmony_ci}
22058c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_device_add_groups);
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci/**
22088c2ecf20Sopenharmony_ci * devm_device_remove_groups - remove a list of managed groups
22098c2ecf20Sopenharmony_ci *
22108c2ecf20Sopenharmony_ci * @dev:	The device for the groups to be removed from
22118c2ecf20Sopenharmony_ci * @groups:	NULL terminated list of groups to be removed
22128c2ecf20Sopenharmony_ci *
22138c2ecf20Sopenharmony_ci * If groups is not NULL, remove the specified groups from the device.
22148c2ecf20Sopenharmony_ci */
22158c2ecf20Sopenharmony_civoid devm_device_remove_groups(struct device *dev,
22168c2ecf20Sopenharmony_ci			       const struct attribute_group **groups)
22178c2ecf20Sopenharmony_ci{
22188c2ecf20Sopenharmony_ci	WARN_ON(devres_release(dev, devm_attr_groups_remove,
22198c2ecf20Sopenharmony_ci			       devm_attr_group_match,
22208c2ecf20Sopenharmony_ci			       /* cast away const */ (void *)groups));
22218c2ecf20Sopenharmony_ci}
22228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_device_remove_groups);
22238c2ecf20Sopenharmony_ci
22248c2ecf20Sopenharmony_cistatic int device_add_attrs(struct device *dev)
22258c2ecf20Sopenharmony_ci{
22268c2ecf20Sopenharmony_ci	struct class *class = dev->class;
22278c2ecf20Sopenharmony_ci	const struct device_type *type = dev->type;
22288c2ecf20Sopenharmony_ci	int error;
22298c2ecf20Sopenharmony_ci
22308c2ecf20Sopenharmony_ci	if (class) {
22318c2ecf20Sopenharmony_ci		error = device_add_groups(dev, class->dev_groups);
22328c2ecf20Sopenharmony_ci		if (error)
22338c2ecf20Sopenharmony_ci			return error;
22348c2ecf20Sopenharmony_ci	}
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_ci	if (type) {
22378c2ecf20Sopenharmony_ci		error = device_add_groups(dev, type->groups);
22388c2ecf20Sopenharmony_ci		if (error)
22398c2ecf20Sopenharmony_ci			goto err_remove_class_groups;
22408c2ecf20Sopenharmony_ci	}
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_ci	error = device_add_groups(dev, dev->groups);
22438c2ecf20Sopenharmony_ci	if (error)
22448c2ecf20Sopenharmony_ci		goto err_remove_type_groups;
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci	if (device_supports_offline(dev) && !dev->offline_disabled) {
22478c2ecf20Sopenharmony_ci		error = device_create_file(dev, &dev_attr_online);
22488c2ecf20Sopenharmony_ci		if (error)
22498c2ecf20Sopenharmony_ci			goto err_remove_dev_groups;
22508c2ecf20Sopenharmony_ci	}
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ci	if (fw_devlink_flags && !fw_devlink_is_permissive()) {
22538c2ecf20Sopenharmony_ci		error = device_create_file(dev, &dev_attr_waiting_for_supplier);
22548c2ecf20Sopenharmony_ci		if (error)
22558c2ecf20Sopenharmony_ci			goto err_remove_dev_online;
22568c2ecf20Sopenharmony_ci	}
22578c2ecf20Sopenharmony_ci
22588c2ecf20Sopenharmony_ci	if (dev_removable_is_valid(dev)) {
22598c2ecf20Sopenharmony_ci		error = device_create_file(dev, &dev_attr_removable);
22608c2ecf20Sopenharmony_ci		if (error)
22618c2ecf20Sopenharmony_ci			goto err_remove_dev_waiting_for_supplier;
22628c2ecf20Sopenharmony_ci	}
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci	return 0;
22658c2ecf20Sopenharmony_ci
22668c2ecf20Sopenharmony_ci err_remove_dev_waiting_for_supplier:
22678c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_waiting_for_supplier);
22688c2ecf20Sopenharmony_ci err_remove_dev_online:
22698c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_online);
22708c2ecf20Sopenharmony_ci err_remove_dev_groups:
22718c2ecf20Sopenharmony_ci	device_remove_groups(dev, dev->groups);
22728c2ecf20Sopenharmony_ci err_remove_type_groups:
22738c2ecf20Sopenharmony_ci	if (type)
22748c2ecf20Sopenharmony_ci		device_remove_groups(dev, type->groups);
22758c2ecf20Sopenharmony_ci err_remove_class_groups:
22768c2ecf20Sopenharmony_ci	if (class)
22778c2ecf20Sopenharmony_ci		device_remove_groups(dev, class->dev_groups);
22788c2ecf20Sopenharmony_ci
22798c2ecf20Sopenharmony_ci	return error;
22808c2ecf20Sopenharmony_ci}
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_cistatic void device_remove_attrs(struct device *dev)
22838c2ecf20Sopenharmony_ci{
22848c2ecf20Sopenharmony_ci	struct class *class = dev->class;
22858c2ecf20Sopenharmony_ci	const struct device_type *type = dev->type;
22868c2ecf20Sopenharmony_ci
22878c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_removable);
22888c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_waiting_for_supplier);
22898c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_online);
22908c2ecf20Sopenharmony_ci	device_remove_groups(dev, dev->groups);
22918c2ecf20Sopenharmony_ci
22928c2ecf20Sopenharmony_ci	if (type)
22938c2ecf20Sopenharmony_ci		device_remove_groups(dev, type->groups);
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci	if (class)
22968c2ecf20Sopenharmony_ci		device_remove_groups(dev, class->dev_groups);
22978c2ecf20Sopenharmony_ci}
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_cistatic ssize_t dev_show(struct device *dev, struct device_attribute *attr,
23008c2ecf20Sopenharmony_ci			char *buf)
23018c2ecf20Sopenharmony_ci{
23028c2ecf20Sopenharmony_ci	return print_dev_t(buf, dev->devt);
23038c2ecf20Sopenharmony_ci}
23048c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(dev);
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci/* /sys/devices/ */
23078c2ecf20Sopenharmony_cistruct kset *devices_kset;
23088c2ecf20Sopenharmony_ci
23098c2ecf20Sopenharmony_ci/**
23108c2ecf20Sopenharmony_ci * devices_kset_move_before - Move device in the devices_kset's list.
23118c2ecf20Sopenharmony_ci * @deva: Device to move.
23128c2ecf20Sopenharmony_ci * @devb: Device @deva should come before.
23138c2ecf20Sopenharmony_ci */
23148c2ecf20Sopenharmony_cistatic void devices_kset_move_before(struct device *deva, struct device *devb)
23158c2ecf20Sopenharmony_ci{
23168c2ecf20Sopenharmony_ci	if (!devices_kset)
23178c2ecf20Sopenharmony_ci		return;
23188c2ecf20Sopenharmony_ci	pr_debug("devices_kset: Moving %s before %s\n",
23198c2ecf20Sopenharmony_ci		 dev_name(deva), dev_name(devb));
23208c2ecf20Sopenharmony_ci	spin_lock(&devices_kset->list_lock);
23218c2ecf20Sopenharmony_ci	list_move_tail(&deva->kobj.entry, &devb->kobj.entry);
23228c2ecf20Sopenharmony_ci	spin_unlock(&devices_kset->list_lock);
23238c2ecf20Sopenharmony_ci}
23248c2ecf20Sopenharmony_ci
23258c2ecf20Sopenharmony_ci/**
23268c2ecf20Sopenharmony_ci * devices_kset_move_after - Move device in the devices_kset's list.
23278c2ecf20Sopenharmony_ci * @deva: Device to move
23288c2ecf20Sopenharmony_ci * @devb: Device @deva should come after.
23298c2ecf20Sopenharmony_ci */
23308c2ecf20Sopenharmony_cistatic void devices_kset_move_after(struct device *deva, struct device *devb)
23318c2ecf20Sopenharmony_ci{
23328c2ecf20Sopenharmony_ci	if (!devices_kset)
23338c2ecf20Sopenharmony_ci		return;
23348c2ecf20Sopenharmony_ci	pr_debug("devices_kset: Moving %s after %s\n",
23358c2ecf20Sopenharmony_ci		 dev_name(deva), dev_name(devb));
23368c2ecf20Sopenharmony_ci	spin_lock(&devices_kset->list_lock);
23378c2ecf20Sopenharmony_ci	list_move(&deva->kobj.entry, &devb->kobj.entry);
23388c2ecf20Sopenharmony_ci	spin_unlock(&devices_kset->list_lock);
23398c2ecf20Sopenharmony_ci}
23408c2ecf20Sopenharmony_ci
23418c2ecf20Sopenharmony_ci/**
23428c2ecf20Sopenharmony_ci * devices_kset_move_last - move the device to the end of devices_kset's list.
23438c2ecf20Sopenharmony_ci * @dev: device to move
23448c2ecf20Sopenharmony_ci */
23458c2ecf20Sopenharmony_civoid devices_kset_move_last(struct device *dev)
23468c2ecf20Sopenharmony_ci{
23478c2ecf20Sopenharmony_ci	if (!devices_kset)
23488c2ecf20Sopenharmony_ci		return;
23498c2ecf20Sopenharmony_ci	pr_debug("devices_kset: Moving %s to end of list\n", dev_name(dev));
23508c2ecf20Sopenharmony_ci	spin_lock(&devices_kset->list_lock);
23518c2ecf20Sopenharmony_ci	list_move_tail(&dev->kobj.entry, &devices_kset->list);
23528c2ecf20Sopenharmony_ci	spin_unlock(&devices_kset->list_lock);
23538c2ecf20Sopenharmony_ci}
23548c2ecf20Sopenharmony_ci
23558c2ecf20Sopenharmony_ci/**
23568c2ecf20Sopenharmony_ci * device_create_file - create sysfs attribute file for device.
23578c2ecf20Sopenharmony_ci * @dev: device.
23588c2ecf20Sopenharmony_ci * @attr: device attribute descriptor.
23598c2ecf20Sopenharmony_ci */
23608c2ecf20Sopenharmony_ciint device_create_file(struct device *dev,
23618c2ecf20Sopenharmony_ci		       const struct device_attribute *attr)
23628c2ecf20Sopenharmony_ci{
23638c2ecf20Sopenharmony_ci	int error = 0;
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci	if (dev) {
23668c2ecf20Sopenharmony_ci		WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
23678c2ecf20Sopenharmony_ci			"Attribute %s: write permission without 'store'\n",
23688c2ecf20Sopenharmony_ci			attr->attr.name);
23698c2ecf20Sopenharmony_ci		WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
23708c2ecf20Sopenharmony_ci			"Attribute %s: read permission without 'show'\n",
23718c2ecf20Sopenharmony_ci			attr->attr.name);
23728c2ecf20Sopenharmony_ci		error = sysfs_create_file(&dev->kobj, &attr->attr);
23738c2ecf20Sopenharmony_ci	}
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci	return error;
23768c2ecf20Sopenharmony_ci}
23778c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_create_file);
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci/**
23808c2ecf20Sopenharmony_ci * device_remove_file - remove sysfs attribute file.
23818c2ecf20Sopenharmony_ci * @dev: device.
23828c2ecf20Sopenharmony_ci * @attr: device attribute descriptor.
23838c2ecf20Sopenharmony_ci */
23848c2ecf20Sopenharmony_civoid device_remove_file(struct device *dev,
23858c2ecf20Sopenharmony_ci			const struct device_attribute *attr)
23868c2ecf20Sopenharmony_ci{
23878c2ecf20Sopenharmony_ci	if (dev)
23888c2ecf20Sopenharmony_ci		sysfs_remove_file(&dev->kobj, &attr->attr);
23898c2ecf20Sopenharmony_ci}
23908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_remove_file);
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ci/**
23938c2ecf20Sopenharmony_ci * device_remove_file_self - remove sysfs attribute file from its own method.
23948c2ecf20Sopenharmony_ci * @dev: device.
23958c2ecf20Sopenharmony_ci * @attr: device attribute descriptor.
23968c2ecf20Sopenharmony_ci *
23978c2ecf20Sopenharmony_ci * See kernfs_remove_self() for details.
23988c2ecf20Sopenharmony_ci */
23998c2ecf20Sopenharmony_cibool device_remove_file_self(struct device *dev,
24008c2ecf20Sopenharmony_ci			     const struct device_attribute *attr)
24018c2ecf20Sopenharmony_ci{
24028c2ecf20Sopenharmony_ci	if (dev)
24038c2ecf20Sopenharmony_ci		return sysfs_remove_file_self(&dev->kobj, &attr->attr);
24048c2ecf20Sopenharmony_ci	else
24058c2ecf20Sopenharmony_ci		return false;
24068c2ecf20Sopenharmony_ci}
24078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_remove_file_self);
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci/**
24108c2ecf20Sopenharmony_ci * device_create_bin_file - create sysfs binary attribute file for device.
24118c2ecf20Sopenharmony_ci * @dev: device.
24128c2ecf20Sopenharmony_ci * @attr: device binary attribute descriptor.
24138c2ecf20Sopenharmony_ci */
24148c2ecf20Sopenharmony_ciint device_create_bin_file(struct device *dev,
24158c2ecf20Sopenharmony_ci			   const struct bin_attribute *attr)
24168c2ecf20Sopenharmony_ci{
24178c2ecf20Sopenharmony_ci	int error = -EINVAL;
24188c2ecf20Sopenharmony_ci	if (dev)
24198c2ecf20Sopenharmony_ci		error = sysfs_create_bin_file(&dev->kobj, attr);
24208c2ecf20Sopenharmony_ci	return error;
24218c2ecf20Sopenharmony_ci}
24228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_create_bin_file);
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci/**
24258c2ecf20Sopenharmony_ci * device_remove_bin_file - remove sysfs binary attribute file
24268c2ecf20Sopenharmony_ci * @dev: device.
24278c2ecf20Sopenharmony_ci * @attr: device binary attribute descriptor.
24288c2ecf20Sopenharmony_ci */
24298c2ecf20Sopenharmony_civoid device_remove_bin_file(struct device *dev,
24308c2ecf20Sopenharmony_ci			    const struct bin_attribute *attr)
24318c2ecf20Sopenharmony_ci{
24328c2ecf20Sopenharmony_ci	if (dev)
24338c2ecf20Sopenharmony_ci		sysfs_remove_bin_file(&dev->kobj, attr);
24348c2ecf20Sopenharmony_ci}
24358c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_remove_bin_file);
24368c2ecf20Sopenharmony_ci
24378c2ecf20Sopenharmony_cistatic void klist_children_get(struct klist_node *n)
24388c2ecf20Sopenharmony_ci{
24398c2ecf20Sopenharmony_ci	struct device_private *p = to_device_private_parent(n);
24408c2ecf20Sopenharmony_ci	struct device *dev = p->device;
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci	get_device(dev);
24438c2ecf20Sopenharmony_ci}
24448c2ecf20Sopenharmony_ci
24458c2ecf20Sopenharmony_cistatic void klist_children_put(struct klist_node *n)
24468c2ecf20Sopenharmony_ci{
24478c2ecf20Sopenharmony_ci	struct device_private *p = to_device_private_parent(n);
24488c2ecf20Sopenharmony_ci	struct device *dev = p->device;
24498c2ecf20Sopenharmony_ci
24508c2ecf20Sopenharmony_ci	put_device(dev);
24518c2ecf20Sopenharmony_ci}
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci/**
24548c2ecf20Sopenharmony_ci * device_initialize - init device structure.
24558c2ecf20Sopenharmony_ci * @dev: device.
24568c2ecf20Sopenharmony_ci *
24578c2ecf20Sopenharmony_ci * This prepares the device for use by other layers by initializing
24588c2ecf20Sopenharmony_ci * its fields.
24598c2ecf20Sopenharmony_ci * It is the first half of device_register(), if called by
24608c2ecf20Sopenharmony_ci * that function, though it can also be called separately, so one
24618c2ecf20Sopenharmony_ci * may use @dev's fields. In particular, get_device()/put_device()
24628c2ecf20Sopenharmony_ci * may be used for reference counting of @dev after calling this
24638c2ecf20Sopenharmony_ci * function.
24648c2ecf20Sopenharmony_ci *
24658c2ecf20Sopenharmony_ci * All fields in @dev must be initialized by the caller to 0, except
24668c2ecf20Sopenharmony_ci * for those explicitly set to some other value.  The simplest
24678c2ecf20Sopenharmony_ci * approach is to use kzalloc() to allocate the structure containing
24688c2ecf20Sopenharmony_ci * @dev.
24698c2ecf20Sopenharmony_ci *
24708c2ecf20Sopenharmony_ci * NOTE: Use put_device() to give up your reference instead of freeing
24718c2ecf20Sopenharmony_ci * @dev directly once you have called this function.
24728c2ecf20Sopenharmony_ci */
24738c2ecf20Sopenharmony_civoid device_initialize(struct device *dev)
24748c2ecf20Sopenharmony_ci{
24758c2ecf20Sopenharmony_ci	dev->kobj.kset = devices_kset;
24768c2ecf20Sopenharmony_ci	kobject_init(&dev->kobj, &device_ktype);
24778c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->dma_pools);
24788c2ecf20Sopenharmony_ci	mutex_init(&dev->mutex);
24798c2ecf20Sopenharmony_ci#ifdef CONFIG_PROVE_LOCKING
24808c2ecf20Sopenharmony_ci	mutex_init(&dev->lockdep_mutex);
24818c2ecf20Sopenharmony_ci#endif
24828c2ecf20Sopenharmony_ci	lockdep_set_novalidate_class(&dev->mutex);
24838c2ecf20Sopenharmony_ci	spin_lock_init(&dev->devres_lock);
24848c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->devres_head);
24858c2ecf20Sopenharmony_ci	device_pm_init(dev);
24868c2ecf20Sopenharmony_ci	set_dev_node(dev, -1);
24878c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_MSI_IRQ
24888c2ecf20Sopenharmony_ci	raw_spin_lock_init(&dev->msi_lock);
24898c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->msi_list);
24908c2ecf20Sopenharmony_ci#endif
24918c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->links.consumers);
24928c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->links.suppliers);
24938c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->links.needs_suppliers);
24948c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->links.defer_hook);
24958c2ecf20Sopenharmony_ci	dev->links.status = DL_DEV_NO_DRIVER;
24968c2ecf20Sopenharmony_ci}
24978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_initialize);
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_cistruct kobject *virtual_device_parent(struct device *dev)
25008c2ecf20Sopenharmony_ci{
25018c2ecf20Sopenharmony_ci	static struct kobject *virtual_dir = NULL;
25028c2ecf20Sopenharmony_ci
25038c2ecf20Sopenharmony_ci	if (!virtual_dir)
25048c2ecf20Sopenharmony_ci		virtual_dir = kobject_create_and_add("virtual",
25058c2ecf20Sopenharmony_ci						     &devices_kset->kobj);
25068c2ecf20Sopenharmony_ci
25078c2ecf20Sopenharmony_ci	return virtual_dir;
25088c2ecf20Sopenharmony_ci}
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_cistruct class_dir {
25118c2ecf20Sopenharmony_ci	struct kobject kobj;
25128c2ecf20Sopenharmony_ci	struct class *class;
25138c2ecf20Sopenharmony_ci};
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci#define to_class_dir(obj) container_of(obj, struct class_dir, kobj)
25168c2ecf20Sopenharmony_ci
25178c2ecf20Sopenharmony_cistatic void class_dir_release(struct kobject *kobj)
25188c2ecf20Sopenharmony_ci{
25198c2ecf20Sopenharmony_ci	struct class_dir *dir = to_class_dir(kobj);
25208c2ecf20Sopenharmony_ci	kfree(dir);
25218c2ecf20Sopenharmony_ci}
25228c2ecf20Sopenharmony_ci
25238c2ecf20Sopenharmony_cistatic const
25248c2ecf20Sopenharmony_cistruct kobj_ns_type_operations *class_dir_child_ns_type(struct kobject *kobj)
25258c2ecf20Sopenharmony_ci{
25268c2ecf20Sopenharmony_ci	struct class_dir *dir = to_class_dir(kobj);
25278c2ecf20Sopenharmony_ci	return dir->class->ns_type;
25288c2ecf20Sopenharmony_ci}
25298c2ecf20Sopenharmony_ci
25308c2ecf20Sopenharmony_cistatic struct kobj_type class_dir_ktype = {
25318c2ecf20Sopenharmony_ci	.release	= class_dir_release,
25328c2ecf20Sopenharmony_ci	.sysfs_ops	= &kobj_sysfs_ops,
25338c2ecf20Sopenharmony_ci	.child_ns_type	= class_dir_child_ns_type
25348c2ecf20Sopenharmony_ci};
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_cistatic struct kobject *
25378c2ecf20Sopenharmony_ciclass_dir_create_and_add(struct class *class, struct kobject *parent_kobj)
25388c2ecf20Sopenharmony_ci{
25398c2ecf20Sopenharmony_ci	struct class_dir *dir;
25408c2ecf20Sopenharmony_ci	int retval;
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_ci	dir = kzalloc(sizeof(*dir), GFP_KERNEL);
25438c2ecf20Sopenharmony_ci	if (!dir)
25448c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_ci	dir->class = class;
25478c2ecf20Sopenharmony_ci	kobject_init(&dir->kobj, &class_dir_ktype);
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	dir->kobj.kset = &class->p->glue_dirs;
25508c2ecf20Sopenharmony_ci
25518c2ecf20Sopenharmony_ci	retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name);
25528c2ecf20Sopenharmony_ci	if (retval < 0) {
25538c2ecf20Sopenharmony_ci		kobject_put(&dir->kobj);
25548c2ecf20Sopenharmony_ci		return ERR_PTR(retval);
25558c2ecf20Sopenharmony_ci	}
25568c2ecf20Sopenharmony_ci	return &dir->kobj;
25578c2ecf20Sopenharmony_ci}
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(gdp_mutex);
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_cistatic struct kobject *get_device_parent(struct device *dev,
25628c2ecf20Sopenharmony_ci					 struct device *parent)
25638c2ecf20Sopenharmony_ci{
25648c2ecf20Sopenharmony_ci	if (dev->class) {
25658c2ecf20Sopenharmony_ci		struct kobject *kobj = NULL;
25668c2ecf20Sopenharmony_ci		struct kobject *parent_kobj;
25678c2ecf20Sopenharmony_ci		struct kobject *k;
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci#ifdef CONFIG_BLOCK
25708c2ecf20Sopenharmony_ci		/* block disks show up in /sys/block */
25718c2ecf20Sopenharmony_ci		if (sysfs_deprecated && dev->class == &block_class) {
25728c2ecf20Sopenharmony_ci			if (parent && parent->class == &block_class)
25738c2ecf20Sopenharmony_ci				return &parent->kobj;
25748c2ecf20Sopenharmony_ci			return &block_class.p->subsys.kobj;
25758c2ecf20Sopenharmony_ci		}
25768c2ecf20Sopenharmony_ci#endif
25778c2ecf20Sopenharmony_ci
25788c2ecf20Sopenharmony_ci		/*
25798c2ecf20Sopenharmony_ci		 * If we have no parent, we live in "virtual".
25808c2ecf20Sopenharmony_ci		 * Class-devices with a non class-device as parent, live
25818c2ecf20Sopenharmony_ci		 * in a "glue" directory to prevent namespace collisions.
25828c2ecf20Sopenharmony_ci		 */
25838c2ecf20Sopenharmony_ci		if (parent == NULL)
25848c2ecf20Sopenharmony_ci			parent_kobj = virtual_device_parent(dev);
25858c2ecf20Sopenharmony_ci		else if (parent->class && !dev->class->ns_type)
25868c2ecf20Sopenharmony_ci			return &parent->kobj;
25878c2ecf20Sopenharmony_ci		else
25888c2ecf20Sopenharmony_ci			parent_kobj = &parent->kobj;
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci		mutex_lock(&gdp_mutex);
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci		/* find our class-directory at the parent and reference it */
25938c2ecf20Sopenharmony_ci		spin_lock(&dev->class->p->glue_dirs.list_lock);
25948c2ecf20Sopenharmony_ci		list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry)
25958c2ecf20Sopenharmony_ci			if (k->parent == parent_kobj) {
25968c2ecf20Sopenharmony_ci				kobj = kobject_get(k);
25978c2ecf20Sopenharmony_ci				break;
25988c2ecf20Sopenharmony_ci			}
25998c2ecf20Sopenharmony_ci		spin_unlock(&dev->class->p->glue_dirs.list_lock);
26008c2ecf20Sopenharmony_ci		if (kobj) {
26018c2ecf20Sopenharmony_ci			mutex_unlock(&gdp_mutex);
26028c2ecf20Sopenharmony_ci			return kobj;
26038c2ecf20Sopenharmony_ci		}
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_ci		/* or create a new class-directory at the parent device */
26068c2ecf20Sopenharmony_ci		k = class_dir_create_and_add(dev->class, parent_kobj);
26078c2ecf20Sopenharmony_ci		/* do not emit an uevent for this simple "glue" directory */
26088c2ecf20Sopenharmony_ci		mutex_unlock(&gdp_mutex);
26098c2ecf20Sopenharmony_ci		return k;
26108c2ecf20Sopenharmony_ci	}
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci	/* subsystems can specify a default root directory for their devices */
26138c2ecf20Sopenharmony_ci	if (!parent && dev->bus && dev->bus->dev_root)
26148c2ecf20Sopenharmony_ci		return &dev->bus->dev_root->kobj;
26158c2ecf20Sopenharmony_ci
26168c2ecf20Sopenharmony_ci	if (parent)
26178c2ecf20Sopenharmony_ci		return &parent->kobj;
26188c2ecf20Sopenharmony_ci	return NULL;
26198c2ecf20Sopenharmony_ci}
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_cistatic inline bool live_in_glue_dir(struct kobject *kobj,
26228c2ecf20Sopenharmony_ci				    struct device *dev)
26238c2ecf20Sopenharmony_ci{
26248c2ecf20Sopenharmony_ci	if (!kobj || !dev->class ||
26258c2ecf20Sopenharmony_ci	    kobj->kset != &dev->class->p->glue_dirs)
26268c2ecf20Sopenharmony_ci		return false;
26278c2ecf20Sopenharmony_ci	return true;
26288c2ecf20Sopenharmony_ci}
26298c2ecf20Sopenharmony_ci
26308c2ecf20Sopenharmony_cistatic inline struct kobject *get_glue_dir(struct device *dev)
26318c2ecf20Sopenharmony_ci{
26328c2ecf20Sopenharmony_ci	return dev->kobj.parent;
26338c2ecf20Sopenharmony_ci}
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci/*
26368c2ecf20Sopenharmony_ci * make sure cleaning up dir as the last step, we need to make
26378c2ecf20Sopenharmony_ci * sure .release handler of kobject is run with holding the
26388c2ecf20Sopenharmony_ci * global lock
26398c2ecf20Sopenharmony_ci */
26408c2ecf20Sopenharmony_cistatic void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
26418c2ecf20Sopenharmony_ci{
26428c2ecf20Sopenharmony_ci	unsigned int ref;
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci	/* see if we live in a "glue" directory */
26458c2ecf20Sopenharmony_ci	if (!live_in_glue_dir(glue_dir, dev))
26468c2ecf20Sopenharmony_ci		return;
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_ci	mutex_lock(&gdp_mutex);
26498c2ecf20Sopenharmony_ci	/**
26508c2ecf20Sopenharmony_ci	 * There is a race condition between removing glue directory
26518c2ecf20Sopenharmony_ci	 * and adding a new device under the glue directory.
26528c2ecf20Sopenharmony_ci	 *
26538c2ecf20Sopenharmony_ci	 * CPU1:                                         CPU2:
26548c2ecf20Sopenharmony_ci	 *
26558c2ecf20Sopenharmony_ci	 * device_add()
26568c2ecf20Sopenharmony_ci	 *   get_device_parent()
26578c2ecf20Sopenharmony_ci	 *     class_dir_create_and_add()
26588c2ecf20Sopenharmony_ci	 *       kobject_add_internal()
26598c2ecf20Sopenharmony_ci	 *         create_dir()    // create glue_dir
26608c2ecf20Sopenharmony_ci	 *
26618c2ecf20Sopenharmony_ci	 *                                               device_add()
26628c2ecf20Sopenharmony_ci	 *                                                 get_device_parent()
26638c2ecf20Sopenharmony_ci	 *                                                   kobject_get() // get glue_dir
26648c2ecf20Sopenharmony_ci	 *
26658c2ecf20Sopenharmony_ci	 * device_del()
26668c2ecf20Sopenharmony_ci	 *   cleanup_glue_dir()
26678c2ecf20Sopenharmony_ci	 *     kobject_del(glue_dir)
26688c2ecf20Sopenharmony_ci	 *
26698c2ecf20Sopenharmony_ci	 *                                               kobject_add()
26708c2ecf20Sopenharmony_ci	 *                                                 kobject_add_internal()
26718c2ecf20Sopenharmony_ci	 *                                                   create_dir() // in glue_dir
26728c2ecf20Sopenharmony_ci	 *                                                     sysfs_create_dir_ns()
26738c2ecf20Sopenharmony_ci	 *                                                       kernfs_create_dir_ns(sd)
26748c2ecf20Sopenharmony_ci	 *
26758c2ecf20Sopenharmony_ci	 *       sysfs_remove_dir() // glue_dir->sd=NULL
26768c2ecf20Sopenharmony_ci	 *       sysfs_put()        // free glue_dir->sd
26778c2ecf20Sopenharmony_ci	 *
26788c2ecf20Sopenharmony_ci	 *                                                         // sd is freed
26798c2ecf20Sopenharmony_ci	 *                                                         kernfs_new_node(sd)
26808c2ecf20Sopenharmony_ci	 *                                                           kernfs_get(glue_dir)
26818c2ecf20Sopenharmony_ci	 *                                                           kernfs_add_one()
26828c2ecf20Sopenharmony_ci	 *                                                           kernfs_put()
26838c2ecf20Sopenharmony_ci	 *
26848c2ecf20Sopenharmony_ci	 * Before CPU1 remove last child device under glue dir, if CPU2 add
26858c2ecf20Sopenharmony_ci	 * a new device under glue dir, the glue_dir kobject reference count
26868c2ecf20Sopenharmony_ci	 * will be increase to 2 in kobject_get(k). And CPU2 has been called
26878c2ecf20Sopenharmony_ci	 * kernfs_create_dir_ns(). Meanwhile, CPU1 call sysfs_remove_dir()
26888c2ecf20Sopenharmony_ci	 * and sysfs_put(). This result in glue_dir->sd is freed.
26898c2ecf20Sopenharmony_ci	 *
26908c2ecf20Sopenharmony_ci	 * Then the CPU2 will see a stale "empty" but still potentially used
26918c2ecf20Sopenharmony_ci	 * glue dir around in kernfs_new_node().
26928c2ecf20Sopenharmony_ci	 *
26938c2ecf20Sopenharmony_ci	 * In order to avoid this happening, we also should make sure that
26948c2ecf20Sopenharmony_ci	 * kernfs_node for glue_dir is released in CPU1 only when refcount
26958c2ecf20Sopenharmony_ci	 * for glue_dir kobj is 1.
26968c2ecf20Sopenharmony_ci	 */
26978c2ecf20Sopenharmony_ci	ref = kref_read(&glue_dir->kref);
26988c2ecf20Sopenharmony_ci	if (!kobject_has_children(glue_dir) && !--ref)
26998c2ecf20Sopenharmony_ci		kobject_del(glue_dir);
27008c2ecf20Sopenharmony_ci	kobject_put(glue_dir);
27018c2ecf20Sopenharmony_ci	mutex_unlock(&gdp_mutex);
27028c2ecf20Sopenharmony_ci}
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_cistatic int device_add_class_symlinks(struct device *dev)
27058c2ecf20Sopenharmony_ci{
27068c2ecf20Sopenharmony_ci	struct device_node *of_node = dev_of_node(dev);
27078c2ecf20Sopenharmony_ci	int error;
27088c2ecf20Sopenharmony_ci
27098c2ecf20Sopenharmony_ci	if (of_node) {
27108c2ecf20Sopenharmony_ci		error = sysfs_create_link(&dev->kobj, of_node_kobj(of_node), "of_node");
27118c2ecf20Sopenharmony_ci		if (error)
27128c2ecf20Sopenharmony_ci			dev_warn(dev, "Error %d creating of_node link\n",error);
27138c2ecf20Sopenharmony_ci		/* An error here doesn't warrant bringing down the device */
27148c2ecf20Sopenharmony_ci	}
27158c2ecf20Sopenharmony_ci
27168c2ecf20Sopenharmony_ci	if (!dev->class)
27178c2ecf20Sopenharmony_ci		return 0;
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ci	error = sysfs_create_link(&dev->kobj,
27208c2ecf20Sopenharmony_ci				  &dev->class->p->subsys.kobj,
27218c2ecf20Sopenharmony_ci				  "subsystem");
27228c2ecf20Sopenharmony_ci	if (error)
27238c2ecf20Sopenharmony_ci		goto out_devnode;
27248c2ecf20Sopenharmony_ci
27258c2ecf20Sopenharmony_ci	if (dev->parent && device_is_not_partition(dev)) {
27268c2ecf20Sopenharmony_ci		error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
27278c2ecf20Sopenharmony_ci					  "device");
27288c2ecf20Sopenharmony_ci		if (error)
27298c2ecf20Sopenharmony_ci			goto out_subsys;
27308c2ecf20Sopenharmony_ci	}
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci#ifdef CONFIG_BLOCK
27338c2ecf20Sopenharmony_ci	/* /sys/block has directories and does not need symlinks */
27348c2ecf20Sopenharmony_ci	if (sysfs_deprecated && dev->class == &block_class)
27358c2ecf20Sopenharmony_ci		return 0;
27368c2ecf20Sopenharmony_ci#endif
27378c2ecf20Sopenharmony_ci
27388c2ecf20Sopenharmony_ci	/* link in the class directory pointing to the device */
27398c2ecf20Sopenharmony_ci	error = sysfs_create_link(&dev->class->p->subsys.kobj,
27408c2ecf20Sopenharmony_ci				  &dev->kobj, dev_name(dev));
27418c2ecf20Sopenharmony_ci	if (error)
27428c2ecf20Sopenharmony_ci		goto out_device;
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_ci	return 0;
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ciout_device:
27478c2ecf20Sopenharmony_ci	sysfs_remove_link(&dev->kobj, "device");
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ciout_subsys:
27508c2ecf20Sopenharmony_ci	sysfs_remove_link(&dev->kobj, "subsystem");
27518c2ecf20Sopenharmony_ciout_devnode:
27528c2ecf20Sopenharmony_ci	sysfs_remove_link(&dev->kobj, "of_node");
27538c2ecf20Sopenharmony_ci	return error;
27548c2ecf20Sopenharmony_ci}
27558c2ecf20Sopenharmony_ci
27568c2ecf20Sopenharmony_cistatic void device_remove_class_symlinks(struct device *dev)
27578c2ecf20Sopenharmony_ci{
27588c2ecf20Sopenharmony_ci	if (dev_of_node(dev))
27598c2ecf20Sopenharmony_ci		sysfs_remove_link(&dev->kobj, "of_node");
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_ci	if (!dev->class)
27628c2ecf20Sopenharmony_ci		return;
27638c2ecf20Sopenharmony_ci
27648c2ecf20Sopenharmony_ci	if (dev->parent && device_is_not_partition(dev))
27658c2ecf20Sopenharmony_ci		sysfs_remove_link(&dev->kobj, "device");
27668c2ecf20Sopenharmony_ci	sysfs_remove_link(&dev->kobj, "subsystem");
27678c2ecf20Sopenharmony_ci#ifdef CONFIG_BLOCK
27688c2ecf20Sopenharmony_ci	if (sysfs_deprecated && dev->class == &block_class)
27698c2ecf20Sopenharmony_ci		return;
27708c2ecf20Sopenharmony_ci#endif
27718c2ecf20Sopenharmony_ci	sysfs_delete_link(&dev->class->p->subsys.kobj, &dev->kobj, dev_name(dev));
27728c2ecf20Sopenharmony_ci}
27738c2ecf20Sopenharmony_ci
27748c2ecf20Sopenharmony_ci/**
27758c2ecf20Sopenharmony_ci * dev_set_name - set a device name
27768c2ecf20Sopenharmony_ci * @dev: device
27778c2ecf20Sopenharmony_ci * @fmt: format string for the device's name
27788c2ecf20Sopenharmony_ci */
27798c2ecf20Sopenharmony_ciint dev_set_name(struct device *dev, const char *fmt, ...)
27808c2ecf20Sopenharmony_ci{
27818c2ecf20Sopenharmony_ci	va_list vargs;
27828c2ecf20Sopenharmony_ci	int err;
27838c2ecf20Sopenharmony_ci
27848c2ecf20Sopenharmony_ci	va_start(vargs, fmt);
27858c2ecf20Sopenharmony_ci	err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
27868c2ecf20Sopenharmony_ci	va_end(vargs);
27878c2ecf20Sopenharmony_ci	return err;
27888c2ecf20Sopenharmony_ci}
27898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_set_name);
27908c2ecf20Sopenharmony_ci
27918c2ecf20Sopenharmony_ci/**
27928c2ecf20Sopenharmony_ci * device_to_dev_kobj - select a /sys/dev/ directory for the device
27938c2ecf20Sopenharmony_ci * @dev: device
27948c2ecf20Sopenharmony_ci *
27958c2ecf20Sopenharmony_ci * By default we select char/ for new entries.  Setting class->dev_obj
27968c2ecf20Sopenharmony_ci * to NULL prevents an entry from being created.  class->dev_kobj must
27978c2ecf20Sopenharmony_ci * be set (or cleared) before any devices are registered to the class
27988c2ecf20Sopenharmony_ci * otherwise device_create_sys_dev_entry() and
27998c2ecf20Sopenharmony_ci * device_remove_sys_dev_entry() will disagree about the presence of
28008c2ecf20Sopenharmony_ci * the link.
28018c2ecf20Sopenharmony_ci */
28028c2ecf20Sopenharmony_cistatic struct kobject *device_to_dev_kobj(struct device *dev)
28038c2ecf20Sopenharmony_ci{
28048c2ecf20Sopenharmony_ci	struct kobject *kobj;
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ci	if (dev->class)
28078c2ecf20Sopenharmony_ci		kobj = dev->class->dev_kobj;
28088c2ecf20Sopenharmony_ci	else
28098c2ecf20Sopenharmony_ci		kobj = sysfs_dev_char_kobj;
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci	return kobj;
28128c2ecf20Sopenharmony_ci}
28138c2ecf20Sopenharmony_ci
28148c2ecf20Sopenharmony_cistatic int device_create_sys_dev_entry(struct device *dev)
28158c2ecf20Sopenharmony_ci{
28168c2ecf20Sopenharmony_ci	struct kobject *kobj = device_to_dev_kobj(dev);
28178c2ecf20Sopenharmony_ci	int error = 0;
28188c2ecf20Sopenharmony_ci	char devt_str[15];
28198c2ecf20Sopenharmony_ci
28208c2ecf20Sopenharmony_ci	if (kobj) {
28218c2ecf20Sopenharmony_ci		format_dev_t(devt_str, dev->devt);
28228c2ecf20Sopenharmony_ci		error = sysfs_create_link(kobj, &dev->kobj, devt_str);
28238c2ecf20Sopenharmony_ci	}
28248c2ecf20Sopenharmony_ci
28258c2ecf20Sopenharmony_ci	return error;
28268c2ecf20Sopenharmony_ci}
28278c2ecf20Sopenharmony_ci
28288c2ecf20Sopenharmony_cistatic void device_remove_sys_dev_entry(struct device *dev)
28298c2ecf20Sopenharmony_ci{
28308c2ecf20Sopenharmony_ci	struct kobject *kobj = device_to_dev_kobj(dev);
28318c2ecf20Sopenharmony_ci	char devt_str[15];
28328c2ecf20Sopenharmony_ci
28338c2ecf20Sopenharmony_ci	if (kobj) {
28348c2ecf20Sopenharmony_ci		format_dev_t(devt_str, dev->devt);
28358c2ecf20Sopenharmony_ci		sysfs_remove_link(kobj, devt_str);
28368c2ecf20Sopenharmony_ci	}
28378c2ecf20Sopenharmony_ci}
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_cistatic int device_private_init(struct device *dev)
28408c2ecf20Sopenharmony_ci{
28418c2ecf20Sopenharmony_ci	dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
28428c2ecf20Sopenharmony_ci	if (!dev->p)
28438c2ecf20Sopenharmony_ci		return -ENOMEM;
28448c2ecf20Sopenharmony_ci	dev->p->device = dev;
28458c2ecf20Sopenharmony_ci	klist_init(&dev->p->klist_children, klist_children_get,
28468c2ecf20Sopenharmony_ci		   klist_children_put);
28478c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&dev->p->deferred_probe);
28488c2ecf20Sopenharmony_ci	return 0;
28498c2ecf20Sopenharmony_ci}
28508c2ecf20Sopenharmony_ci
28518c2ecf20Sopenharmony_ci/**
28528c2ecf20Sopenharmony_ci * device_add - add device to device hierarchy.
28538c2ecf20Sopenharmony_ci * @dev: device.
28548c2ecf20Sopenharmony_ci *
28558c2ecf20Sopenharmony_ci * This is part 2 of device_register(), though may be called
28568c2ecf20Sopenharmony_ci * separately _iff_ device_initialize() has been called separately.
28578c2ecf20Sopenharmony_ci *
28588c2ecf20Sopenharmony_ci * This adds @dev to the kobject hierarchy via kobject_add(), adds it
28598c2ecf20Sopenharmony_ci * to the global and sibling lists for the device, then
28608c2ecf20Sopenharmony_ci * adds it to the other relevant subsystems of the driver model.
28618c2ecf20Sopenharmony_ci *
28628c2ecf20Sopenharmony_ci * Do not call this routine or device_register() more than once for
28638c2ecf20Sopenharmony_ci * any device structure.  The driver model core is not designed to work
28648c2ecf20Sopenharmony_ci * with devices that get unregistered and then spring back to life.
28658c2ecf20Sopenharmony_ci * (Among other things, it's very hard to guarantee that all references
28668c2ecf20Sopenharmony_ci * to the previous incarnation of @dev have been dropped.)  Allocate
28678c2ecf20Sopenharmony_ci * and register a fresh new struct device instead.
28688c2ecf20Sopenharmony_ci *
28698c2ecf20Sopenharmony_ci * NOTE: _Never_ directly free @dev after calling this function, even
28708c2ecf20Sopenharmony_ci * if it returned an error! Always use put_device() to give up your
28718c2ecf20Sopenharmony_ci * reference instead.
28728c2ecf20Sopenharmony_ci *
28738c2ecf20Sopenharmony_ci * Rule of thumb is: if device_add() succeeds, you should call
28748c2ecf20Sopenharmony_ci * device_del() when you want to get rid of it. If device_add() has
28758c2ecf20Sopenharmony_ci * *not* succeeded, use *only* put_device() to drop the reference
28768c2ecf20Sopenharmony_ci * count.
28778c2ecf20Sopenharmony_ci */
28788c2ecf20Sopenharmony_ciint device_add(struct device *dev)
28798c2ecf20Sopenharmony_ci{
28808c2ecf20Sopenharmony_ci	struct device *parent;
28818c2ecf20Sopenharmony_ci	struct kobject *kobj;
28828c2ecf20Sopenharmony_ci	struct class_interface *class_intf;
28838c2ecf20Sopenharmony_ci	int error = -EINVAL;
28848c2ecf20Sopenharmony_ci	struct kobject *glue_dir = NULL;
28858c2ecf20Sopenharmony_ci
28868c2ecf20Sopenharmony_ci	dev = get_device(dev);
28878c2ecf20Sopenharmony_ci	if (!dev)
28888c2ecf20Sopenharmony_ci		goto done;
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_ci	if (!dev->p) {
28918c2ecf20Sopenharmony_ci		error = device_private_init(dev);
28928c2ecf20Sopenharmony_ci		if (error)
28938c2ecf20Sopenharmony_ci			goto done;
28948c2ecf20Sopenharmony_ci	}
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci	/*
28978c2ecf20Sopenharmony_ci	 * for statically allocated devices, which should all be converted
28988c2ecf20Sopenharmony_ci	 * some day, we need to initialize the name. We prevent reading back
28998c2ecf20Sopenharmony_ci	 * the name, and force the use of dev_name()
29008c2ecf20Sopenharmony_ci	 */
29018c2ecf20Sopenharmony_ci	if (dev->init_name) {
29028c2ecf20Sopenharmony_ci		dev_set_name(dev, "%s", dev->init_name);
29038c2ecf20Sopenharmony_ci		dev->init_name = NULL;
29048c2ecf20Sopenharmony_ci	}
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci	/* subsystems can specify simple device enumeration */
29078c2ecf20Sopenharmony_ci	if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
29088c2ecf20Sopenharmony_ci		dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci	if (!dev_name(dev)) {
29118c2ecf20Sopenharmony_ci		error = -EINVAL;
29128c2ecf20Sopenharmony_ci		goto name_error;
29138c2ecf20Sopenharmony_ci	}
29148c2ecf20Sopenharmony_ci
29158c2ecf20Sopenharmony_ci	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
29168c2ecf20Sopenharmony_ci
29178c2ecf20Sopenharmony_ci	parent = get_device(dev->parent);
29188c2ecf20Sopenharmony_ci	kobj = get_device_parent(dev, parent);
29198c2ecf20Sopenharmony_ci	if (IS_ERR(kobj)) {
29208c2ecf20Sopenharmony_ci		error = PTR_ERR(kobj);
29218c2ecf20Sopenharmony_ci		goto parent_error;
29228c2ecf20Sopenharmony_ci	}
29238c2ecf20Sopenharmony_ci	if (kobj)
29248c2ecf20Sopenharmony_ci		dev->kobj.parent = kobj;
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci	/* use parent numa_node */
29278c2ecf20Sopenharmony_ci	if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
29288c2ecf20Sopenharmony_ci		set_dev_node(dev, dev_to_node(parent));
29298c2ecf20Sopenharmony_ci
29308c2ecf20Sopenharmony_ci	/* first, register with generic layer. */
29318c2ecf20Sopenharmony_ci	/* we require the name to be set before, and pass NULL */
29328c2ecf20Sopenharmony_ci	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
29338c2ecf20Sopenharmony_ci	if (error) {
29348c2ecf20Sopenharmony_ci		glue_dir = get_glue_dir(dev);
29358c2ecf20Sopenharmony_ci		goto Error;
29368c2ecf20Sopenharmony_ci	}
29378c2ecf20Sopenharmony_ci
29388c2ecf20Sopenharmony_ci	/* notify platform of device entry */
29398c2ecf20Sopenharmony_ci	error = device_platform_notify(dev, KOBJ_ADD);
29408c2ecf20Sopenharmony_ci	if (error)
29418c2ecf20Sopenharmony_ci		goto platform_error;
29428c2ecf20Sopenharmony_ci
29438c2ecf20Sopenharmony_ci	error = device_create_file(dev, &dev_attr_uevent);
29448c2ecf20Sopenharmony_ci	if (error)
29458c2ecf20Sopenharmony_ci		goto attrError;
29468c2ecf20Sopenharmony_ci
29478c2ecf20Sopenharmony_ci	error = device_add_class_symlinks(dev);
29488c2ecf20Sopenharmony_ci	if (error)
29498c2ecf20Sopenharmony_ci		goto SymlinkError;
29508c2ecf20Sopenharmony_ci	error = device_add_attrs(dev);
29518c2ecf20Sopenharmony_ci	if (error)
29528c2ecf20Sopenharmony_ci		goto AttrsError;
29538c2ecf20Sopenharmony_ci	error = bus_add_device(dev);
29548c2ecf20Sopenharmony_ci	if (error)
29558c2ecf20Sopenharmony_ci		goto BusError;
29568c2ecf20Sopenharmony_ci	error = dpm_sysfs_add(dev);
29578c2ecf20Sopenharmony_ci	if (error)
29588c2ecf20Sopenharmony_ci		goto DPMError;
29598c2ecf20Sopenharmony_ci	device_pm_add(dev);
29608c2ecf20Sopenharmony_ci
29618c2ecf20Sopenharmony_ci	if (MAJOR(dev->devt)) {
29628c2ecf20Sopenharmony_ci		error = device_create_file(dev, &dev_attr_dev);
29638c2ecf20Sopenharmony_ci		if (error)
29648c2ecf20Sopenharmony_ci			goto DevAttrError;
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_ci		error = device_create_sys_dev_entry(dev);
29678c2ecf20Sopenharmony_ci		if (error)
29688c2ecf20Sopenharmony_ci			goto SysEntryError;
29698c2ecf20Sopenharmony_ci
29708c2ecf20Sopenharmony_ci		devtmpfs_create_node(dev);
29718c2ecf20Sopenharmony_ci	}
29728c2ecf20Sopenharmony_ci
29738c2ecf20Sopenharmony_ci	/* Notify clients of device addition.  This call must come
29748c2ecf20Sopenharmony_ci	 * after dpm_sysfs_add() and before kobject_uevent().
29758c2ecf20Sopenharmony_ci	 */
29768c2ecf20Sopenharmony_ci	if (dev->bus)
29778c2ecf20Sopenharmony_ci		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
29788c2ecf20Sopenharmony_ci					     BUS_NOTIFY_ADD_DEVICE, dev);
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_ci	kobject_uevent(&dev->kobj, KOBJ_ADD);
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci	/*
29838c2ecf20Sopenharmony_ci	 * Check if any of the other devices (consumers) have been waiting for
29848c2ecf20Sopenharmony_ci	 * this device (supplier) to be added so that they can create a device
29858c2ecf20Sopenharmony_ci	 * link to it.
29868c2ecf20Sopenharmony_ci	 *
29878c2ecf20Sopenharmony_ci	 * This needs to happen after device_pm_add() because device_link_add()
29888c2ecf20Sopenharmony_ci	 * requires the supplier be registered before it's called.
29898c2ecf20Sopenharmony_ci	 *
29908c2ecf20Sopenharmony_ci	 * But this also needs to happen before bus_probe_device() to make sure
29918c2ecf20Sopenharmony_ci	 * waiting consumers can link to it before the driver is bound to the
29928c2ecf20Sopenharmony_ci	 * device and the driver sync_state callback is called for this device.
29938c2ecf20Sopenharmony_ci	 */
29948c2ecf20Sopenharmony_ci	if (dev->fwnode && !dev->fwnode->dev) {
29958c2ecf20Sopenharmony_ci		dev->fwnode->dev = dev;
29968c2ecf20Sopenharmony_ci		fw_devlink_link_device(dev);
29978c2ecf20Sopenharmony_ci	}
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci	bus_probe_device(dev);
30008c2ecf20Sopenharmony_ci	if (parent)
30018c2ecf20Sopenharmony_ci		klist_add_tail(&dev->p->knode_parent,
30028c2ecf20Sopenharmony_ci			       &parent->p->klist_children);
30038c2ecf20Sopenharmony_ci
30048c2ecf20Sopenharmony_ci	if (dev->class) {
30058c2ecf20Sopenharmony_ci		mutex_lock(&dev->class->p->mutex);
30068c2ecf20Sopenharmony_ci		/* tie the class to the device */
30078c2ecf20Sopenharmony_ci		klist_add_tail(&dev->p->knode_class,
30088c2ecf20Sopenharmony_ci			       &dev->class->p->klist_devices);
30098c2ecf20Sopenharmony_ci
30108c2ecf20Sopenharmony_ci		/* notify any interfaces that the device is here */
30118c2ecf20Sopenharmony_ci		list_for_each_entry(class_intf,
30128c2ecf20Sopenharmony_ci				    &dev->class->p->interfaces, node)
30138c2ecf20Sopenharmony_ci			if (class_intf->add_dev)
30148c2ecf20Sopenharmony_ci				class_intf->add_dev(dev, class_intf);
30158c2ecf20Sopenharmony_ci		mutex_unlock(&dev->class->p->mutex);
30168c2ecf20Sopenharmony_ci	}
30178c2ecf20Sopenharmony_cidone:
30188c2ecf20Sopenharmony_ci	put_device(dev);
30198c2ecf20Sopenharmony_ci	return error;
30208c2ecf20Sopenharmony_ci SysEntryError:
30218c2ecf20Sopenharmony_ci	if (MAJOR(dev->devt))
30228c2ecf20Sopenharmony_ci		device_remove_file(dev, &dev_attr_dev);
30238c2ecf20Sopenharmony_ci DevAttrError:
30248c2ecf20Sopenharmony_ci	device_pm_remove(dev);
30258c2ecf20Sopenharmony_ci	dpm_sysfs_remove(dev);
30268c2ecf20Sopenharmony_ci DPMError:
30278c2ecf20Sopenharmony_ci	bus_remove_device(dev);
30288c2ecf20Sopenharmony_ci BusError:
30298c2ecf20Sopenharmony_ci	device_remove_attrs(dev);
30308c2ecf20Sopenharmony_ci AttrsError:
30318c2ecf20Sopenharmony_ci	device_remove_class_symlinks(dev);
30328c2ecf20Sopenharmony_ci SymlinkError:
30338c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_uevent);
30348c2ecf20Sopenharmony_ci attrError:
30358c2ecf20Sopenharmony_ci	device_platform_notify(dev, KOBJ_REMOVE);
30368c2ecf20Sopenharmony_ciplatform_error:
30378c2ecf20Sopenharmony_ci	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
30388c2ecf20Sopenharmony_ci	glue_dir = get_glue_dir(dev);
30398c2ecf20Sopenharmony_ci	kobject_del(&dev->kobj);
30408c2ecf20Sopenharmony_ci Error:
30418c2ecf20Sopenharmony_ci	cleanup_glue_dir(dev, glue_dir);
30428c2ecf20Sopenharmony_ciparent_error:
30438c2ecf20Sopenharmony_ci	put_device(parent);
30448c2ecf20Sopenharmony_ciname_error:
30458c2ecf20Sopenharmony_ci	kfree(dev->p);
30468c2ecf20Sopenharmony_ci	dev->p = NULL;
30478c2ecf20Sopenharmony_ci	goto done;
30488c2ecf20Sopenharmony_ci}
30498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_add);
30508c2ecf20Sopenharmony_ci
30518c2ecf20Sopenharmony_ci/**
30528c2ecf20Sopenharmony_ci * device_register - register a device with the system.
30538c2ecf20Sopenharmony_ci * @dev: pointer to the device structure
30548c2ecf20Sopenharmony_ci *
30558c2ecf20Sopenharmony_ci * This happens in two clean steps - initialize the device
30568c2ecf20Sopenharmony_ci * and add it to the system. The two steps can be called
30578c2ecf20Sopenharmony_ci * separately, but this is the easiest and most common.
30588c2ecf20Sopenharmony_ci * I.e. you should only call the two helpers separately if
30598c2ecf20Sopenharmony_ci * have a clearly defined need to use and refcount the device
30608c2ecf20Sopenharmony_ci * before it is added to the hierarchy.
30618c2ecf20Sopenharmony_ci *
30628c2ecf20Sopenharmony_ci * For more information, see the kerneldoc for device_initialize()
30638c2ecf20Sopenharmony_ci * and device_add().
30648c2ecf20Sopenharmony_ci *
30658c2ecf20Sopenharmony_ci * NOTE: _Never_ directly free @dev after calling this function, even
30668c2ecf20Sopenharmony_ci * if it returned an error! Always use put_device() to give up the
30678c2ecf20Sopenharmony_ci * reference initialized in this function instead.
30688c2ecf20Sopenharmony_ci */
30698c2ecf20Sopenharmony_ciint device_register(struct device *dev)
30708c2ecf20Sopenharmony_ci{
30718c2ecf20Sopenharmony_ci	device_initialize(dev);
30728c2ecf20Sopenharmony_ci	return device_add(dev);
30738c2ecf20Sopenharmony_ci}
30748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_register);
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_ci/**
30778c2ecf20Sopenharmony_ci * get_device - increment reference count for device.
30788c2ecf20Sopenharmony_ci * @dev: device.
30798c2ecf20Sopenharmony_ci *
30808c2ecf20Sopenharmony_ci * This simply forwards the call to kobject_get(), though
30818c2ecf20Sopenharmony_ci * we do take care to provide for the case that we get a NULL
30828c2ecf20Sopenharmony_ci * pointer passed in.
30838c2ecf20Sopenharmony_ci */
30848c2ecf20Sopenharmony_cistruct device *get_device(struct device *dev)
30858c2ecf20Sopenharmony_ci{
30868c2ecf20Sopenharmony_ci	return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL;
30878c2ecf20Sopenharmony_ci}
30888c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(get_device);
30898c2ecf20Sopenharmony_ci
30908c2ecf20Sopenharmony_ci/**
30918c2ecf20Sopenharmony_ci * put_device - decrement reference count.
30928c2ecf20Sopenharmony_ci * @dev: device in question.
30938c2ecf20Sopenharmony_ci */
30948c2ecf20Sopenharmony_civoid put_device(struct device *dev)
30958c2ecf20Sopenharmony_ci{
30968c2ecf20Sopenharmony_ci	/* might_sleep(); */
30978c2ecf20Sopenharmony_ci	if (dev)
30988c2ecf20Sopenharmony_ci		kobject_put(&dev->kobj);
30998c2ecf20Sopenharmony_ci}
31008c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(put_device);
31018c2ecf20Sopenharmony_ci
31028c2ecf20Sopenharmony_cibool kill_device(struct device *dev)
31038c2ecf20Sopenharmony_ci{
31048c2ecf20Sopenharmony_ci	/*
31058c2ecf20Sopenharmony_ci	 * Require the device lock and set the "dead" flag to guarantee that
31068c2ecf20Sopenharmony_ci	 * the update behavior is consistent with the other bitfields near
31078c2ecf20Sopenharmony_ci	 * it and that we cannot have an asynchronous probe routine trying
31088c2ecf20Sopenharmony_ci	 * to run while we are tearing out the bus/class/sysfs from
31098c2ecf20Sopenharmony_ci	 * underneath the device.
31108c2ecf20Sopenharmony_ci	 */
31118c2ecf20Sopenharmony_ci	lockdep_assert_held(&dev->mutex);
31128c2ecf20Sopenharmony_ci
31138c2ecf20Sopenharmony_ci	if (dev->p->dead)
31148c2ecf20Sopenharmony_ci		return false;
31158c2ecf20Sopenharmony_ci	dev->p->dead = true;
31168c2ecf20Sopenharmony_ci	return true;
31178c2ecf20Sopenharmony_ci}
31188c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(kill_device);
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci/**
31218c2ecf20Sopenharmony_ci * device_del - delete device from system.
31228c2ecf20Sopenharmony_ci * @dev: device.
31238c2ecf20Sopenharmony_ci *
31248c2ecf20Sopenharmony_ci * This is the first part of the device unregistration
31258c2ecf20Sopenharmony_ci * sequence. This removes the device from the lists we control
31268c2ecf20Sopenharmony_ci * from here, has it removed from the other driver model
31278c2ecf20Sopenharmony_ci * subsystems it was added to in device_add(), and removes it
31288c2ecf20Sopenharmony_ci * from the kobject hierarchy.
31298c2ecf20Sopenharmony_ci *
31308c2ecf20Sopenharmony_ci * NOTE: this should be called manually _iff_ device_add() was
31318c2ecf20Sopenharmony_ci * also called manually.
31328c2ecf20Sopenharmony_ci */
31338c2ecf20Sopenharmony_civoid device_del(struct device *dev)
31348c2ecf20Sopenharmony_ci{
31358c2ecf20Sopenharmony_ci	struct device *parent = dev->parent;
31368c2ecf20Sopenharmony_ci	struct kobject *glue_dir = NULL;
31378c2ecf20Sopenharmony_ci	struct class_interface *class_intf;
31388c2ecf20Sopenharmony_ci	unsigned int noio_flag;
31398c2ecf20Sopenharmony_ci
31408c2ecf20Sopenharmony_ci	device_lock(dev);
31418c2ecf20Sopenharmony_ci	kill_device(dev);
31428c2ecf20Sopenharmony_ci	device_unlock(dev);
31438c2ecf20Sopenharmony_ci
31448c2ecf20Sopenharmony_ci	if (dev->fwnode && dev->fwnode->dev == dev)
31458c2ecf20Sopenharmony_ci		dev->fwnode->dev = NULL;
31468c2ecf20Sopenharmony_ci
31478c2ecf20Sopenharmony_ci	/* Notify clients of device removal.  This call must come
31488c2ecf20Sopenharmony_ci	 * before dpm_sysfs_remove().
31498c2ecf20Sopenharmony_ci	 */
31508c2ecf20Sopenharmony_ci	noio_flag = memalloc_noio_save();
31518c2ecf20Sopenharmony_ci	if (dev->bus)
31528c2ecf20Sopenharmony_ci		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
31538c2ecf20Sopenharmony_ci					     BUS_NOTIFY_DEL_DEVICE, dev);
31548c2ecf20Sopenharmony_ci
31558c2ecf20Sopenharmony_ci	dpm_sysfs_remove(dev);
31568c2ecf20Sopenharmony_ci	if (parent)
31578c2ecf20Sopenharmony_ci		klist_del(&dev->p->knode_parent);
31588c2ecf20Sopenharmony_ci	if (MAJOR(dev->devt)) {
31598c2ecf20Sopenharmony_ci		devtmpfs_delete_node(dev);
31608c2ecf20Sopenharmony_ci		device_remove_sys_dev_entry(dev);
31618c2ecf20Sopenharmony_ci		device_remove_file(dev, &dev_attr_dev);
31628c2ecf20Sopenharmony_ci	}
31638c2ecf20Sopenharmony_ci	if (dev->class) {
31648c2ecf20Sopenharmony_ci		device_remove_class_symlinks(dev);
31658c2ecf20Sopenharmony_ci
31668c2ecf20Sopenharmony_ci		mutex_lock(&dev->class->p->mutex);
31678c2ecf20Sopenharmony_ci		/* notify any interfaces that the device is now gone */
31688c2ecf20Sopenharmony_ci		list_for_each_entry(class_intf,
31698c2ecf20Sopenharmony_ci				    &dev->class->p->interfaces, node)
31708c2ecf20Sopenharmony_ci			if (class_intf->remove_dev)
31718c2ecf20Sopenharmony_ci				class_intf->remove_dev(dev, class_intf);
31728c2ecf20Sopenharmony_ci		/* remove the device from the class list */
31738c2ecf20Sopenharmony_ci		klist_del(&dev->p->knode_class);
31748c2ecf20Sopenharmony_ci		mutex_unlock(&dev->class->p->mutex);
31758c2ecf20Sopenharmony_ci	}
31768c2ecf20Sopenharmony_ci	device_remove_file(dev, &dev_attr_uevent);
31778c2ecf20Sopenharmony_ci	device_remove_attrs(dev);
31788c2ecf20Sopenharmony_ci	bus_remove_device(dev);
31798c2ecf20Sopenharmony_ci	device_pm_remove(dev);
31808c2ecf20Sopenharmony_ci	driver_deferred_probe_del(dev);
31818c2ecf20Sopenharmony_ci	device_platform_notify(dev, KOBJ_REMOVE);
31828c2ecf20Sopenharmony_ci	device_remove_properties(dev);
31838c2ecf20Sopenharmony_ci	device_links_purge(dev);
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_ci	if (dev->bus)
31868c2ecf20Sopenharmony_ci		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
31878c2ecf20Sopenharmony_ci					     BUS_NOTIFY_REMOVED_DEVICE, dev);
31888c2ecf20Sopenharmony_ci	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
31898c2ecf20Sopenharmony_ci	glue_dir = get_glue_dir(dev);
31908c2ecf20Sopenharmony_ci	kobject_del(&dev->kobj);
31918c2ecf20Sopenharmony_ci	cleanup_glue_dir(dev, glue_dir);
31928c2ecf20Sopenharmony_ci	memalloc_noio_restore(noio_flag);
31938c2ecf20Sopenharmony_ci	put_device(parent);
31948c2ecf20Sopenharmony_ci}
31958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_del);
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci/**
31988c2ecf20Sopenharmony_ci * device_unregister - unregister device from system.
31998c2ecf20Sopenharmony_ci * @dev: device going away.
32008c2ecf20Sopenharmony_ci *
32018c2ecf20Sopenharmony_ci * We do this in two parts, like we do device_register(). First,
32028c2ecf20Sopenharmony_ci * we remove it from all the subsystems with device_del(), then
32038c2ecf20Sopenharmony_ci * we decrement the reference count via put_device(). If that
32048c2ecf20Sopenharmony_ci * is the final reference count, the device will be cleaned up
32058c2ecf20Sopenharmony_ci * via device_release() above. Otherwise, the structure will
32068c2ecf20Sopenharmony_ci * stick around until the final reference to the device is dropped.
32078c2ecf20Sopenharmony_ci */
32088c2ecf20Sopenharmony_civoid device_unregister(struct device *dev)
32098c2ecf20Sopenharmony_ci{
32108c2ecf20Sopenharmony_ci	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
32118c2ecf20Sopenharmony_ci	device_del(dev);
32128c2ecf20Sopenharmony_ci	put_device(dev);
32138c2ecf20Sopenharmony_ci}
32148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_unregister);
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_cistatic struct device *prev_device(struct klist_iter *i)
32178c2ecf20Sopenharmony_ci{
32188c2ecf20Sopenharmony_ci	struct klist_node *n = klist_prev(i);
32198c2ecf20Sopenharmony_ci	struct device *dev = NULL;
32208c2ecf20Sopenharmony_ci	struct device_private *p;
32218c2ecf20Sopenharmony_ci
32228c2ecf20Sopenharmony_ci	if (n) {
32238c2ecf20Sopenharmony_ci		p = to_device_private_parent(n);
32248c2ecf20Sopenharmony_ci		dev = p->device;
32258c2ecf20Sopenharmony_ci	}
32268c2ecf20Sopenharmony_ci	return dev;
32278c2ecf20Sopenharmony_ci}
32288c2ecf20Sopenharmony_ci
32298c2ecf20Sopenharmony_cistatic struct device *next_device(struct klist_iter *i)
32308c2ecf20Sopenharmony_ci{
32318c2ecf20Sopenharmony_ci	struct klist_node *n = klist_next(i);
32328c2ecf20Sopenharmony_ci	struct device *dev = NULL;
32338c2ecf20Sopenharmony_ci	struct device_private *p;
32348c2ecf20Sopenharmony_ci
32358c2ecf20Sopenharmony_ci	if (n) {
32368c2ecf20Sopenharmony_ci		p = to_device_private_parent(n);
32378c2ecf20Sopenharmony_ci		dev = p->device;
32388c2ecf20Sopenharmony_ci	}
32398c2ecf20Sopenharmony_ci	return dev;
32408c2ecf20Sopenharmony_ci}
32418c2ecf20Sopenharmony_ci
32428c2ecf20Sopenharmony_ci/**
32438c2ecf20Sopenharmony_ci * device_get_devnode - path of device node file
32448c2ecf20Sopenharmony_ci * @dev: device
32458c2ecf20Sopenharmony_ci * @mode: returned file access mode
32468c2ecf20Sopenharmony_ci * @uid: returned file owner
32478c2ecf20Sopenharmony_ci * @gid: returned file group
32488c2ecf20Sopenharmony_ci * @tmp: possibly allocated string
32498c2ecf20Sopenharmony_ci *
32508c2ecf20Sopenharmony_ci * Return the relative path of a possible device node.
32518c2ecf20Sopenharmony_ci * Non-default names may need to allocate a memory to compose
32528c2ecf20Sopenharmony_ci * a name. This memory is returned in tmp and needs to be
32538c2ecf20Sopenharmony_ci * freed by the caller.
32548c2ecf20Sopenharmony_ci */
32558c2ecf20Sopenharmony_ciconst char *device_get_devnode(struct device *dev,
32568c2ecf20Sopenharmony_ci			       umode_t *mode, kuid_t *uid, kgid_t *gid,
32578c2ecf20Sopenharmony_ci			       const char **tmp)
32588c2ecf20Sopenharmony_ci{
32598c2ecf20Sopenharmony_ci	char *s;
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ci	*tmp = NULL;
32628c2ecf20Sopenharmony_ci
32638c2ecf20Sopenharmony_ci	/* the device type may provide a specific name */
32648c2ecf20Sopenharmony_ci	if (dev->type && dev->type->devnode)
32658c2ecf20Sopenharmony_ci		*tmp = dev->type->devnode(dev, mode, uid, gid);
32668c2ecf20Sopenharmony_ci	if (*tmp)
32678c2ecf20Sopenharmony_ci		return *tmp;
32688c2ecf20Sopenharmony_ci
32698c2ecf20Sopenharmony_ci	/* the class may provide a specific name */
32708c2ecf20Sopenharmony_ci	if (dev->class && dev->class->devnode)
32718c2ecf20Sopenharmony_ci		*tmp = dev->class->devnode(dev, mode);
32728c2ecf20Sopenharmony_ci	if (*tmp)
32738c2ecf20Sopenharmony_ci		return *tmp;
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_ci	/* return name without allocation, tmp == NULL */
32768c2ecf20Sopenharmony_ci	if (strchr(dev_name(dev), '!') == NULL)
32778c2ecf20Sopenharmony_ci		return dev_name(dev);
32788c2ecf20Sopenharmony_ci
32798c2ecf20Sopenharmony_ci	/* replace '!' in the name with '/' */
32808c2ecf20Sopenharmony_ci	s = kstrdup(dev_name(dev), GFP_KERNEL);
32818c2ecf20Sopenharmony_ci	if (!s)
32828c2ecf20Sopenharmony_ci		return NULL;
32838c2ecf20Sopenharmony_ci	strreplace(s, '!', '/');
32848c2ecf20Sopenharmony_ci	return *tmp = s;
32858c2ecf20Sopenharmony_ci}
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ci/**
32888c2ecf20Sopenharmony_ci * device_for_each_child - device child iterator.
32898c2ecf20Sopenharmony_ci * @parent: parent struct device.
32908c2ecf20Sopenharmony_ci * @fn: function to be called for each device.
32918c2ecf20Sopenharmony_ci * @data: data for the callback.
32928c2ecf20Sopenharmony_ci *
32938c2ecf20Sopenharmony_ci * Iterate over @parent's child devices, and call @fn for each,
32948c2ecf20Sopenharmony_ci * passing it @data.
32958c2ecf20Sopenharmony_ci *
32968c2ecf20Sopenharmony_ci * We check the return of @fn each time. If it returns anything
32978c2ecf20Sopenharmony_ci * other than 0, we break out and return that value.
32988c2ecf20Sopenharmony_ci */
32998c2ecf20Sopenharmony_ciint device_for_each_child(struct device *parent, void *data,
33008c2ecf20Sopenharmony_ci			  int (*fn)(struct device *dev, void *data))
33018c2ecf20Sopenharmony_ci{
33028c2ecf20Sopenharmony_ci	struct klist_iter i;
33038c2ecf20Sopenharmony_ci	struct device *child;
33048c2ecf20Sopenharmony_ci	int error = 0;
33058c2ecf20Sopenharmony_ci
33068c2ecf20Sopenharmony_ci	if (!parent->p)
33078c2ecf20Sopenharmony_ci		return 0;
33088c2ecf20Sopenharmony_ci
33098c2ecf20Sopenharmony_ci	klist_iter_init(&parent->p->klist_children, &i);
33108c2ecf20Sopenharmony_ci	while (!error && (child = next_device(&i)))
33118c2ecf20Sopenharmony_ci		error = fn(child, data);
33128c2ecf20Sopenharmony_ci	klist_iter_exit(&i);
33138c2ecf20Sopenharmony_ci	return error;
33148c2ecf20Sopenharmony_ci}
33158c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_for_each_child);
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ci/**
33188c2ecf20Sopenharmony_ci * device_for_each_child_reverse - device child iterator in reversed order.
33198c2ecf20Sopenharmony_ci * @parent: parent struct device.
33208c2ecf20Sopenharmony_ci * @fn: function to be called for each device.
33218c2ecf20Sopenharmony_ci * @data: data for the callback.
33228c2ecf20Sopenharmony_ci *
33238c2ecf20Sopenharmony_ci * Iterate over @parent's child devices, and call @fn for each,
33248c2ecf20Sopenharmony_ci * passing it @data.
33258c2ecf20Sopenharmony_ci *
33268c2ecf20Sopenharmony_ci * We check the return of @fn each time. If it returns anything
33278c2ecf20Sopenharmony_ci * other than 0, we break out and return that value.
33288c2ecf20Sopenharmony_ci */
33298c2ecf20Sopenharmony_ciint device_for_each_child_reverse(struct device *parent, void *data,
33308c2ecf20Sopenharmony_ci				  int (*fn)(struct device *dev, void *data))
33318c2ecf20Sopenharmony_ci{
33328c2ecf20Sopenharmony_ci	struct klist_iter i;
33338c2ecf20Sopenharmony_ci	struct device *child;
33348c2ecf20Sopenharmony_ci	int error = 0;
33358c2ecf20Sopenharmony_ci
33368c2ecf20Sopenharmony_ci	if (!parent->p)
33378c2ecf20Sopenharmony_ci		return 0;
33388c2ecf20Sopenharmony_ci
33398c2ecf20Sopenharmony_ci	klist_iter_init(&parent->p->klist_children, &i);
33408c2ecf20Sopenharmony_ci	while ((child = prev_device(&i)) && !error)
33418c2ecf20Sopenharmony_ci		error = fn(child, data);
33428c2ecf20Sopenharmony_ci	klist_iter_exit(&i);
33438c2ecf20Sopenharmony_ci	return error;
33448c2ecf20Sopenharmony_ci}
33458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_for_each_child_reverse);
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci/**
33488c2ecf20Sopenharmony_ci * device_find_child - device iterator for locating a particular device.
33498c2ecf20Sopenharmony_ci * @parent: parent struct device
33508c2ecf20Sopenharmony_ci * @match: Callback function to check device
33518c2ecf20Sopenharmony_ci * @data: Data to pass to match function
33528c2ecf20Sopenharmony_ci *
33538c2ecf20Sopenharmony_ci * This is similar to the device_for_each_child() function above, but it
33548c2ecf20Sopenharmony_ci * returns a reference to a device that is 'found' for later use, as
33558c2ecf20Sopenharmony_ci * determined by the @match callback.
33568c2ecf20Sopenharmony_ci *
33578c2ecf20Sopenharmony_ci * The callback should return 0 if the device doesn't match and non-zero
33588c2ecf20Sopenharmony_ci * if it does.  If the callback returns non-zero and a reference to the
33598c2ecf20Sopenharmony_ci * current device can be obtained, this function will return to the caller
33608c2ecf20Sopenharmony_ci * and not iterate over any more devices.
33618c2ecf20Sopenharmony_ci *
33628c2ecf20Sopenharmony_ci * NOTE: you will need to drop the reference with put_device() after use.
33638c2ecf20Sopenharmony_ci */
33648c2ecf20Sopenharmony_cistruct device *device_find_child(struct device *parent, void *data,
33658c2ecf20Sopenharmony_ci				 int (*match)(struct device *dev, void *data))
33668c2ecf20Sopenharmony_ci{
33678c2ecf20Sopenharmony_ci	struct klist_iter i;
33688c2ecf20Sopenharmony_ci	struct device *child;
33698c2ecf20Sopenharmony_ci
33708c2ecf20Sopenharmony_ci	if (!parent)
33718c2ecf20Sopenharmony_ci		return NULL;
33728c2ecf20Sopenharmony_ci
33738c2ecf20Sopenharmony_ci	klist_iter_init(&parent->p->klist_children, &i);
33748c2ecf20Sopenharmony_ci	while ((child = next_device(&i)))
33758c2ecf20Sopenharmony_ci		if (match(child, data) && get_device(child))
33768c2ecf20Sopenharmony_ci			break;
33778c2ecf20Sopenharmony_ci	klist_iter_exit(&i);
33788c2ecf20Sopenharmony_ci	return child;
33798c2ecf20Sopenharmony_ci}
33808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_find_child);
33818c2ecf20Sopenharmony_ci
33828c2ecf20Sopenharmony_ci/**
33838c2ecf20Sopenharmony_ci * device_find_child_by_name - device iterator for locating a child device.
33848c2ecf20Sopenharmony_ci * @parent: parent struct device
33858c2ecf20Sopenharmony_ci * @name: name of the child device
33868c2ecf20Sopenharmony_ci *
33878c2ecf20Sopenharmony_ci * This is similar to the device_find_child() function above, but it
33888c2ecf20Sopenharmony_ci * returns a reference to a device that has the name @name.
33898c2ecf20Sopenharmony_ci *
33908c2ecf20Sopenharmony_ci * NOTE: you will need to drop the reference with put_device() after use.
33918c2ecf20Sopenharmony_ci */
33928c2ecf20Sopenharmony_cistruct device *device_find_child_by_name(struct device *parent,
33938c2ecf20Sopenharmony_ci					 const char *name)
33948c2ecf20Sopenharmony_ci{
33958c2ecf20Sopenharmony_ci	struct klist_iter i;
33968c2ecf20Sopenharmony_ci	struct device *child;
33978c2ecf20Sopenharmony_ci
33988c2ecf20Sopenharmony_ci	if (!parent)
33998c2ecf20Sopenharmony_ci		return NULL;
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_ci	klist_iter_init(&parent->p->klist_children, &i);
34028c2ecf20Sopenharmony_ci	while ((child = next_device(&i)))
34038c2ecf20Sopenharmony_ci		if (sysfs_streq(dev_name(child), name) && get_device(child))
34048c2ecf20Sopenharmony_ci			break;
34058c2ecf20Sopenharmony_ci	klist_iter_exit(&i);
34068c2ecf20Sopenharmony_ci	return child;
34078c2ecf20Sopenharmony_ci}
34088c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_find_child_by_name);
34098c2ecf20Sopenharmony_ci
34108c2ecf20Sopenharmony_ciint __init devices_init(void)
34118c2ecf20Sopenharmony_ci{
34128c2ecf20Sopenharmony_ci	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
34138c2ecf20Sopenharmony_ci	if (!devices_kset)
34148c2ecf20Sopenharmony_ci		return -ENOMEM;
34158c2ecf20Sopenharmony_ci	dev_kobj = kobject_create_and_add("dev", NULL);
34168c2ecf20Sopenharmony_ci	if (!dev_kobj)
34178c2ecf20Sopenharmony_ci		goto dev_kobj_err;
34188c2ecf20Sopenharmony_ci	sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
34198c2ecf20Sopenharmony_ci	if (!sysfs_dev_block_kobj)
34208c2ecf20Sopenharmony_ci		goto block_kobj_err;
34218c2ecf20Sopenharmony_ci	sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
34228c2ecf20Sopenharmony_ci	if (!sysfs_dev_char_kobj)
34238c2ecf20Sopenharmony_ci		goto char_kobj_err;
34248c2ecf20Sopenharmony_ci
34258c2ecf20Sopenharmony_ci	return 0;
34268c2ecf20Sopenharmony_ci
34278c2ecf20Sopenharmony_ci char_kobj_err:
34288c2ecf20Sopenharmony_ci	kobject_put(sysfs_dev_block_kobj);
34298c2ecf20Sopenharmony_ci block_kobj_err:
34308c2ecf20Sopenharmony_ci	kobject_put(dev_kobj);
34318c2ecf20Sopenharmony_ci dev_kobj_err:
34328c2ecf20Sopenharmony_ci	kset_unregister(devices_kset);
34338c2ecf20Sopenharmony_ci	return -ENOMEM;
34348c2ecf20Sopenharmony_ci}
34358c2ecf20Sopenharmony_ci
34368c2ecf20Sopenharmony_cistatic int device_check_offline(struct device *dev, void *not_used)
34378c2ecf20Sopenharmony_ci{
34388c2ecf20Sopenharmony_ci	int ret;
34398c2ecf20Sopenharmony_ci
34408c2ecf20Sopenharmony_ci	ret = device_for_each_child(dev, NULL, device_check_offline);
34418c2ecf20Sopenharmony_ci	if (ret)
34428c2ecf20Sopenharmony_ci		return ret;
34438c2ecf20Sopenharmony_ci
34448c2ecf20Sopenharmony_ci	return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0;
34458c2ecf20Sopenharmony_ci}
34468c2ecf20Sopenharmony_ci
34478c2ecf20Sopenharmony_ci/**
34488c2ecf20Sopenharmony_ci * device_offline - Prepare the device for hot-removal.
34498c2ecf20Sopenharmony_ci * @dev: Device to be put offline.
34508c2ecf20Sopenharmony_ci *
34518c2ecf20Sopenharmony_ci * Execute the device bus type's .offline() callback, if present, to prepare
34528c2ecf20Sopenharmony_ci * the device for a subsequent hot-removal.  If that succeeds, the device must
34538c2ecf20Sopenharmony_ci * not be used until either it is removed or its bus type's .online() callback
34548c2ecf20Sopenharmony_ci * is executed.
34558c2ecf20Sopenharmony_ci *
34568c2ecf20Sopenharmony_ci * Call under device_hotplug_lock.
34578c2ecf20Sopenharmony_ci */
34588c2ecf20Sopenharmony_ciint device_offline(struct device *dev)
34598c2ecf20Sopenharmony_ci{
34608c2ecf20Sopenharmony_ci	int ret;
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_ci	if (dev->offline_disabled)
34638c2ecf20Sopenharmony_ci		return -EPERM;
34648c2ecf20Sopenharmony_ci
34658c2ecf20Sopenharmony_ci	ret = device_for_each_child(dev, NULL, device_check_offline);
34668c2ecf20Sopenharmony_ci	if (ret)
34678c2ecf20Sopenharmony_ci		return ret;
34688c2ecf20Sopenharmony_ci
34698c2ecf20Sopenharmony_ci	device_lock(dev);
34708c2ecf20Sopenharmony_ci	if (device_supports_offline(dev)) {
34718c2ecf20Sopenharmony_ci		if (dev->offline) {
34728c2ecf20Sopenharmony_ci			ret = 1;
34738c2ecf20Sopenharmony_ci		} else {
34748c2ecf20Sopenharmony_ci			ret = dev->bus->offline(dev);
34758c2ecf20Sopenharmony_ci			if (!ret) {
34768c2ecf20Sopenharmony_ci				kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
34778c2ecf20Sopenharmony_ci				dev->offline = true;
34788c2ecf20Sopenharmony_ci			}
34798c2ecf20Sopenharmony_ci		}
34808c2ecf20Sopenharmony_ci	}
34818c2ecf20Sopenharmony_ci	device_unlock(dev);
34828c2ecf20Sopenharmony_ci
34838c2ecf20Sopenharmony_ci	return ret;
34848c2ecf20Sopenharmony_ci}
34858c2ecf20Sopenharmony_ci
34868c2ecf20Sopenharmony_ci/**
34878c2ecf20Sopenharmony_ci * device_online - Put the device back online after successful device_offline().
34888c2ecf20Sopenharmony_ci * @dev: Device to be put back online.
34898c2ecf20Sopenharmony_ci *
34908c2ecf20Sopenharmony_ci * If device_offline() has been successfully executed for @dev, but the device
34918c2ecf20Sopenharmony_ci * has not been removed subsequently, execute its bus type's .online() callback
34928c2ecf20Sopenharmony_ci * to indicate that the device can be used again.
34938c2ecf20Sopenharmony_ci *
34948c2ecf20Sopenharmony_ci * Call under device_hotplug_lock.
34958c2ecf20Sopenharmony_ci */
34968c2ecf20Sopenharmony_ciint device_online(struct device *dev)
34978c2ecf20Sopenharmony_ci{
34988c2ecf20Sopenharmony_ci	int ret = 0;
34998c2ecf20Sopenharmony_ci
35008c2ecf20Sopenharmony_ci	device_lock(dev);
35018c2ecf20Sopenharmony_ci	if (device_supports_offline(dev)) {
35028c2ecf20Sopenharmony_ci		if (dev->offline) {
35038c2ecf20Sopenharmony_ci			ret = dev->bus->online(dev);
35048c2ecf20Sopenharmony_ci			if (!ret) {
35058c2ecf20Sopenharmony_ci				kobject_uevent(&dev->kobj, KOBJ_ONLINE);
35068c2ecf20Sopenharmony_ci				dev->offline = false;
35078c2ecf20Sopenharmony_ci			}
35088c2ecf20Sopenharmony_ci		} else {
35098c2ecf20Sopenharmony_ci			ret = 1;
35108c2ecf20Sopenharmony_ci		}
35118c2ecf20Sopenharmony_ci	}
35128c2ecf20Sopenharmony_ci	device_unlock(dev);
35138c2ecf20Sopenharmony_ci
35148c2ecf20Sopenharmony_ci	return ret;
35158c2ecf20Sopenharmony_ci}
35168c2ecf20Sopenharmony_ci
35178c2ecf20Sopenharmony_cistruct root_device {
35188c2ecf20Sopenharmony_ci	struct device dev;
35198c2ecf20Sopenharmony_ci	struct module *owner;
35208c2ecf20Sopenharmony_ci};
35218c2ecf20Sopenharmony_ci
35228c2ecf20Sopenharmony_cistatic inline struct root_device *to_root_device(struct device *d)
35238c2ecf20Sopenharmony_ci{
35248c2ecf20Sopenharmony_ci	return container_of(d, struct root_device, dev);
35258c2ecf20Sopenharmony_ci}
35268c2ecf20Sopenharmony_ci
35278c2ecf20Sopenharmony_cistatic void root_device_release(struct device *dev)
35288c2ecf20Sopenharmony_ci{
35298c2ecf20Sopenharmony_ci	kfree(to_root_device(dev));
35308c2ecf20Sopenharmony_ci}
35318c2ecf20Sopenharmony_ci
35328c2ecf20Sopenharmony_ci/**
35338c2ecf20Sopenharmony_ci * __root_device_register - allocate and register a root device
35348c2ecf20Sopenharmony_ci * @name: root device name
35358c2ecf20Sopenharmony_ci * @owner: owner module of the root device, usually THIS_MODULE
35368c2ecf20Sopenharmony_ci *
35378c2ecf20Sopenharmony_ci * This function allocates a root device and registers it
35388c2ecf20Sopenharmony_ci * using device_register(). In order to free the returned
35398c2ecf20Sopenharmony_ci * device, use root_device_unregister().
35408c2ecf20Sopenharmony_ci *
35418c2ecf20Sopenharmony_ci * Root devices are dummy devices which allow other devices
35428c2ecf20Sopenharmony_ci * to be grouped under /sys/devices. Use this function to
35438c2ecf20Sopenharmony_ci * allocate a root device and then use it as the parent of
35448c2ecf20Sopenharmony_ci * any device which should appear under /sys/devices/{name}
35458c2ecf20Sopenharmony_ci *
35468c2ecf20Sopenharmony_ci * The /sys/devices/{name} directory will also contain a
35478c2ecf20Sopenharmony_ci * 'module' symlink which points to the @owner directory
35488c2ecf20Sopenharmony_ci * in sysfs.
35498c2ecf20Sopenharmony_ci *
35508c2ecf20Sopenharmony_ci * Returns &struct device pointer on success, or ERR_PTR() on error.
35518c2ecf20Sopenharmony_ci *
35528c2ecf20Sopenharmony_ci * Note: You probably want to use root_device_register().
35538c2ecf20Sopenharmony_ci */
35548c2ecf20Sopenharmony_cistruct device *__root_device_register(const char *name, struct module *owner)
35558c2ecf20Sopenharmony_ci{
35568c2ecf20Sopenharmony_ci	struct root_device *root;
35578c2ecf20Sopenharmony_ci	int err = -ENOMEM;
35588c2ecf20Sopenharmony_ci
35598c2ecf20Sopenharmony_ci	root = kzalloc(sizeof(struct root_device), GFP_KERNEL);
35608c2ecf20Sopenharmony_ci	if (!root)
35618c2ecf20Sopenharmony_ci		return ERR_PTR(err);
35628c2ecf20Sopenharmony_ci
35638c2ecf20Sopenharmony_ci	err = dev_set_name(&root->dev, "%s", name);
35648c2ecf20Sopenharmony_ci	if (err) {
35658c2ecf20Sopenharmony_ci		kfree(root);
35668c2ecf20Sopenharmony_ci		return ERR_PTR(err);
35678c2ecf20Sopenharmony_ci	}
35688c2ecf20Sopenharmony_ci
35698c2ecf20Sopenharmony_ci	root->dev.release = root_device_release;
35708c2ecf20Sopenharmony_ci
35718c2ecf20Sopenharmony_ci	err = device_register(&root->dev);
35728c2ecf20Sopenharmony_ci	if (err) {
35738c2ecf20Sopenharmony_ci		put_device(&root->dev);
35748c2ecf20Sopenharmony_ci		return ERR_PTR(err);
35758c2ecf20Sopenharmony_ci	}
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci#ifdef CONFIG_MODULES	/* gotta find a "cleaner" way to do this */
35788c2ecf20Sopenharmony_ci	if (owner) {
35798c2ecf20Sopenharmony_ci		struct module_kobject *mk = &owner->mkobj;
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_ci		err = sysfs_create_link(&root->dev.kobj, &mk->kobj, "module");
35828c2ecf20Sopenharmony_ci		if (err) {
35838c2ecf20Sopenharmony_ci			device_unregister(&root->dev);
35848c2ecf20Sopenharmony_ci			return ERR_PTR(err);
35858c2ecf20Sopenharmony_ci		}
35868c2ecf20Sopenharmony_ci		root->owner = owner;
35878c2ecf20Sopenharmony_ci	}
35888c2ecf20Sopenharmony_ci#endif
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_ci	return &root->dev;
35918c2ecf20Sopenharmony_ci}
35928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__root_device_register);
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci/**
35958c2ecf20Sopenharmony_ci * root_device_unregister - unregister and free a root device
35968c2ecf20Sopenharmony_ci * @dev: device going away
35978c2ecf20Sopenharmony_ci *
35988c2ecf20Sopenharmony_ci * This function unregisters and cleans up a device that was created by
35998c2ecf20Sopenharmony_ci * root_device_register().
36008c2ecf20Sopenharmony_ci */
36018c2ecf20Sopenharmony_civoid root_device_unregister(struct device *dev)
36028c2ecf20Sopenharmony_ci{
36038c2ecf20Sopenharmony_ci	struct root_device *root = to_root_device(dev);
36048c2ecf20Sopenharmony_ci
36058c2ecf20Sopenharmony_ci	if (root->owner)
36068c2ecf20Sopenharmony_ci		sysfs_remove_link(&root->dev.kobj, "module");
36078c2ecf20Sopenharmony_ci
36088c2ecf20Sopenharmony_ci	device_unregister(dev);
36098c2ecf20Sopenharmony_ci}
36108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(root_device_unregister);
36118c2ecf20Sopenharmony_ci
36128c2ecf20Sopenharmony_ci
36138c2ecf20Sopenharmony_cistatic void device_create_release(struct device *dev)
36148c2ecf20Sopenharmony_ci{
36158c2ecf20Sopenharmony_ci	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
36168c2ecf20Sopenharmony_ci	kfree(dev);
36178c2ecf20Sopenharmony_ci}
36188c2ecf20Sopenharmony_ci
36198c2ecf20Sopenharmony_cistatic __printf(6, 0) struct device *
36208c2ecf20Sopenharmony_cidevice_create_groups_vargs(struct class *class, struct device *parent,
36218c2ecf20Sopenharmony_ci			   dev_t devt, void *drvdata,
36228c2ecf20Sopenharmony_ci			   const struct attribute_group **groups,
36238c2ecf20Sopenharmony_ci			   const char *fmt, va_list args)
36248c2ecf20Sopenharmony_ci{
36258c2ecf20Sopenharmony_ci	struct device *dev = NULL;
36268c2ecf20Sopenharmony_ci	int retval = -ENODEV;
36278c2ecf20Sopenharmony_ci
36288c2ecf20Sopenharmony_ci	if (class == NULL || IS_ERR(class))
36298c2ecf20Sopenharmony_ci		goto error;
36308c2ecf20Sopenharmony_ci
36318c2ecf20Sopenharmony_ci	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
36328c2ecf20Sopenharmony_ci	if (!dev) {
36338c2ecf20Sopenharmony_ci		retval = -ENOMEM;
36348c2ecf20Sopenharmony_ci		goto error;
36358c2ecf20Sopenharmony_ci	}
36368c2ecf20Sopenharmony_ci
36378c2ecf20Sopenharmony_ci	device_initialize(dev);
36388c2ecf20Sopenharmony_ci	dev->devt = devt;
36398c2ecf20Sopenharmony_ci	dev->class = class;
36408c2ecf20Sopenharmony_ci	dev->parent = parent;
36418c2ecf20Sopenharmony_ci	dev->groups = groups;
36428c2ecf20Sopenharmony_ci	dev->release = device_create_release;
36438c2ecf20Sopenharmony_ci	dev_set_drvdata(dev, drvdata);
36448c2ecf20Sopenharmony_ci
36458c2ecf20Sopenharmony_ci	retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
36468c2ecf20Sopenharmony_ci	if (retval)
36478c2ecf20Sopenharmony_ci		goto error;
36488c2ecf20Sopenharmony_ci
36498c2ecf20Sopenharmony_ci	retval = device_add(dev);
36508c2ecf20Sopenharmony_ci	if (retval)
36518c2ecf20Sopenharmony_ci		goto error;
36528c2ecf20Sopenharmony_ci
36538c2ecf20Sopenharmony_ci	return dev;
36548c2ecf20Sopenharmony_ci
36558c2ecf20Sopenharmony_cierror:
36568c2ecf20Sopenharmony_ci	put_device(dev);
36578c2ecf20Sopenharmony_ci	return ERR_PTR(retval);
36588c2ecf20Sopenharmony_ci}
36598c2ecf20Sopenharmony_ci
36608c2ecf20Sopenharmony_ci/**
36618c2ecf20Sopenharmony_ci * device_create - creates a device and registers it with sysfs
36628c2ecf20Sopenharmony_ci * @class: pointer to the struct class that this device should be registered to
36638c2ecf20Sopenharmony_ci * @parent: pointer to the parent struct device of this new device, if any
36648c2ecf20Sopenharmony_ci * @devt: the dev_t for the char device to be added
36658c2ecf20Sopenharmony_ci * @drvdata: the data to be added to the device for callbacks
36668c2ecf20Sopenharmony_ci * @fmt: string for the device's name
36678c2ecf20Sopenharmony_ci *
36688c2ecf20Sopenharmony_ci * This function can be used by char device classes.  A struct device
36698c2ecf20Sopenharmony_ci * will be created in sysfs, registered to the specified class.
36708c2ecf20Sopenharmony_ci *
36718c2ecf20Sopenharmony_ci * A "dev" file will be created, showing the dev_t for the device, if
36728c2ecf20Sopenharmony_ci * the dev_t is not 0,0.
36738c2ecf20Sopenharmony_ci * If a pointer to a parent struct device is passed in, the newly created
36748c2ecf20Sopenharmony_ci * struct device will be a child of that device in sysfs.
36758c2ecf20Sopenharmony_ci * The pointer to the struct device will be returned from the call.
36768c2ecf20Sopenharmony_ci * Any further sysfs files that might be required can be created using this
36778c2ecf20Sopenharmony_ci * pointer.
36788c2ecf20Sopenharmony_ci *
36798c2ecf20Sopenharmony_ci * Returns &struct device pointer on success, or ERR_PTR() on error.
36808c2ecf20Sopenharmony_ci *
36818c2ecf20Sopenharmony_ci * Note: the struct class passed to this function must have previously
36828c2ecf20Sopenharmony_ci * been created with a call to class_create().
36838c2ecf20Sopenharmony_ci */
36848c2ecf20Sopenharmony_cistruct device *device_create(struct class *class, struct device *parent,
36858c2ecf20Sopenharmony_ci			     dev_t devt, void *drvdata, const char *fmt, ...)
36868c2ecf20Sopenharmony_ci{
36878c2ecf20Sopenharmony_ci	va_list vargs;
36888c2ecf20Sopenharmony_ci	struct device *dev;
36898c2ecf20Sopenharmony_ci
36908c2ecf20Sopenharmony_ci	va_start(vargs, fmt);
36918c2ecf20Sopenharmony_ci	dev = device_create_groups_vargs(class, parent, devt, drvdata, NULL,
36928c2ecf20Sopenharmony_ci					  fmt, vargs);
36938c2ecf20Sopenharmony_ci	va_end(vargs);
36948c2ecf20Sopenharmony_ci	return dev;
36958c2ecf20Sopenharmony_ci}
36968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_create);
36978c2ecf20Sopenharmony_ci
36988c2ecf20Sopenharmony_ci/**
36998c2ecf20Sopenharmony_ci * device_create_with_groups - creates a device and registers it with sysfs
37008c2ecf20Sopenharmony_ci * @class: pointer to the struct class that this device should be registered to
37018c2ecf20Sopenharmony_ci * @parent: pointer to the parent struct device of this new device, if any
37028c2ecf20Sopenharmony_ci * @devt: the dev_t for the char device to be added
37038c2ecf20Sopenharmony_ci * @drvdata: the data to be added to the device for callbacks
37048c2ecf20Sopenharmony_ci * @groups: NULL-terminated list of attribute groups to be created
37058c2ecf20Sopenharmony_ci * @fmt: string for the device's name
37068c2ecf20Sopenharmony_ci *
37078c2ecf20Sopenharmony_ci * This function can be used by char device classes.  A struct device
37088c2ecf20Sopenharmony_ci * will be created in sysfs, registered to the specified class.
37098c2ecf20Sopenharmony_ci * Additional attributes specified in the groups parameter will also
37108c2ecf20Sopenharmony_ci * be created automatically.
37118c2ecf20Sopenharmony_ci *
37128c2ecf20Sopenharmony_ci * A "dev" file will be created, showing the dev_t for the device, if
37138c2ecf20Sopenharmony_ci * the dev_t is not 0,0.
37148c2ecf20Sopenharmony_ci * If a pointer to a parent struct device is passed in, the newly created
37158c2ecf20Sopenharmony_ci * struct device will be a child of that device in sysfs.
37168c2ecf20Sopenharmony_ci * The pointer to the struct device will be returned from the call.
37178c2ecf20Sopenharmony_ci * Any further sysfs files that might be required can be created using this
37188c2ecf20Sopenharmony_ci * pointer.
37198c2ecf20Sopenharmony_ci *
37208c2ecf20Sopenharmony_ci * Returns &struct device pointer on success, or ERR_PTR() on error.
37218c2ecf20Sopenharmony_ci *
37228c2ecf20Sopenharmony_ci * Note: the struct class passed to this function must have previously
37238c2ecf20Sopenharmony_ci * been created with a call to class_create().
37248c2ecf20Sopenharmony_ci */
37258c2ecf20Sopenharmony_cistruct device *device_create_with_groups(struct class *class,
37268c2ecf20Sopenharmony_ci					 struct device *parent, dev_t devt,
37278c2ecf20Sopenharmony_ci					 void *drvdata,
37288c2ecf20Sopenharmony_ci					 const struct attribute_group **groups,
37298c2ecf20Sopenharmony_ci					 const char *fmt, ...)
37308c2ecf20Sopenharmony_ci{
37318c2ecf20Sopenharmony_ci	va_list vargs;
37328c2ecf20Sopenharmony_ci	struct device *dev;
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_ci	va_start(vargs, fmt);
37358c2ecf20Sopenharmony_ci	dev = device_create_groups_vargs(class, parent, devt, drvdata, groups,
37368c2ecf20Sopenharmony_ci					 fmt, vargs);
37378c2ecf20Sopenharmony_ci	va_end(vargs);
37388c2ecf20Sopenharmony_ci	return dev;
37398c2ecf20Sopenharmony_ci}
37408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_create_with_groups);
37418c2ecf20Sopenharmony_ci
37428c2ecf20Sopenharmony_ci/**
37438c2ecf20Sopenharmony_ci * device_destroy - removes a device that was created with device_create()
37448c2ecf20Sopenharmony_ci * @class: pointer to the struct class that this device was registered with
37458c2ecf20Sopenharmony_ci * @devt: the dev_t of the device that was previously registered
37468c2ecf20Sopenharmony_ci *
37478c2ecf20Sopenharmony_ci * This call unregisters and cleans up a device that was created with a
37488c2ecf20Sopenharmony_ci * call to device_create().
37498c2ecf20Sopenharmony_ci */
37508c2ecf20Sopenharmony_civoid device_destroy(struct class *class, dev_t devt)
37518c2ecf20Sopenharmony_ci{
37528c2ecf20Sopenharmony_ci	struct device *dev;
37538c2ecf20Sopenharmony_ci
37548c2ecf20Sopenharmony_ci	dev = class_find_device_by_devt(class, devt);
37558c2ecf20Sopenharmony_ci	if (dev) {
37568c2ecf20Sopenharmony_ci		put_device(dev);
37578c2ecf20Sopenharmony_ci		device_unregister(dev);
37588c2ecf20Sopenharmony_ci	}
37598c2ecf20Sopenharmony_ci}
37608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_destroy);
37618c2ecf20Sopenharmony_ci
37628c2ecf20Sopenharmony_ci/**
37638c2ecf20Sopenharmony_ci * device_rename - renames a device
37648c2ecf20Sopenharmony_ci * @dev: the pointer to the struct device to be renamed
37658c2ecf20Sopenharmony_ci * @new_name: the new name of the device
37668c2ecf20Sopenharmony_ci *
37678c2ecf20Sopenharmony_ci * It is the responsibility of the caller to provide mutual
37688c2ecf20Sopenharmony_ci * exclusion between two different calls of device_rename
37698c2ecf20Sopenharmony_ci * on the same device to ensure that new_name is valid and
37708c2ecf20Sopenharmony_ci * won't conflict with other devices.
37718c2ecf20Sopenharmony_ci *
37728c2ecf20Sopenharmony_ci * Note: Don't call this function.  Currently, the networking layer calls this
37738c2ecf20Sopenharmony_ci * function, but that will change.  The following text from Kay Sievers offers
37748c2ecf20Sopenharmony_ci * some insight:
37758c2ecf20Sopenharmony_ci *
37768c2ecf20Sopenharmony_ci * Renaming devices is racy at many levels, symlinks and other stuff are not
37778c2ecf20Sopenharmony_ci * replaced atomically, and you get a "move" uevent, but it's not easy to
37788c2ecf20Sopenharmony_ci * connect the event to the old and new device. Device nodes are not renamed at
37798c2ecf20Sopenharmony_ci * all, there isn't even support for that in the kernel now.
37808c2ecf20Sopenharmony_ci *
37818c2ecf20Sopenharmony_ci * In the meantime, during renaming, your target name might be taken by another
37828c2ecf20Sopenharmony_ci * driver, creating conflicts. Or the old name is taken directly after you
37838c2ecf20Sopenharmony_ci * renamed it -- then you get events for the same DEVPATH, before you even see
37848c2ecf20Sopenharmony_ci * the "move" event. It's just a mess, and nothing new should ever rely on
37858c2ecf20Sopenharmony_ci * kernel device renaming. Besides that, it's not even implemented now for
37868c2ecf20Sopenharmony_ci * other things than (driver-core wise very simple) network devices.
37878c2ecf20Sopenharmony_ci *
37888c2ecf20Sopenharmony_ci * We are currently about to change network renaming in udev to completely
37898c2ecf20Sopenharmony_ci * disallow renaming of devices in the same namespace as the kernel uses,
37908c2ecf20Sopenharmony_ci * because we can't solve the problems properly, that arise with swapping names
37918c2ecf20Sopenharmony_ci * of multiple interfaces without races. Means, renaming of eth[0-9]* will only
37928c2ecf20Sopenharmony_ci * be allowed to some other name than eth[0-9]*, for the aforementioned
37938c2ecf20Sopenharmony_ci * reasons.
37948c2ecf20Sopenharmony_ci *
37958c2ecf20Sopenharmony_ci * Make up a "real" name in the driver before you register anything, or add
37968c2ecf20Sopenharmony_ci * some other attributes for userspace to find the device, or use udev to add
37978c2ecf20Sopenharmony_ci * symlinks -- but never rename kernel devices later, it's a complete mess. We
37988c2ecf20Sopenharmony_ci * don't even want to get into that and try to implement the missing pieces in
37998c2ecf20Sopenharmony_ci * the core. We really have other pieces to fix in the driver core mess. :)
38008c2ecf20Sopenharmony_ci */
38018c2ecf20Sopenharmony_ciint device_rename(struct device *dev, const char *new_name)
38028c2ecf20Sopenharmony_ci{
38038c2ecf20Sopenharmony_ci	struct kobject *kobj = &dev->kobj;
38048c2ecf20Sopenharmony_ci	char *old_device_name = NULL;
38058c2ecf20Sopenharmony_ci	int error;
38068c2ecf20Sopenharmony_ci
38078c2ecf20Sopenharmony_ci	dev = get_device(dev);
38088c2ecf20Sopenharmony_ci	if (!dev)
38098c2ecf20Sopenharmony_ci		return -EINVAL;
38108c2ecf20Sopenharmony_ci
38118c2ecf20Sopenharmony_ci	dev_dbg(dev, "renaming to %s\n", new_name);
38128c2ecf20Sopenharmony_ci
38138c2ecf20Sopenharmony_ci	old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
38148c2ecf20Sopenharmony_ci	if (!old_device_name) {
38158c2ecf20Sopenharmony_ci		error = -ENOMEM;
38168c2ecf20Sopenharmony_ci		goto out;
38178c2ecf20Sopenharmony_ci	}
38188c2ecf20Sopenharmony_ci
38198c2ecf20Sopenharmony_ci	if (dev->class) {
38208c2ecf20Sopenharmony_ci		error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj,
38218c2ecf20Sopenharmony_ci					     kobj, old_device_name,
38228c2ecf20Sopenharmony_ci					     new_name, kobject_namespace(kobj));
38238c2ecf20Sopenharmony_ci		if (error)
38248c2ecf20Sopenharmony_ci			goto out;
38258c2ecf20Sopenharmony_ci	}
38268c2ecf20Sopenharmony_ci
38278c2ecf20Sopenharmony_ci	error = kobject_rename(kobj, new_name);
38288c2ecf20Sopenharmony_ci	if (error)
38298c2ecf20Sopenharmony_ci		goto out;
38308c2ecf20Sopenharmony_ci
38318c2ecf20Sopenharmony_ciout:
38328c2ecf20Sopenharmony_ci	put_device(dev);
38338c2ecf20Sopenharmony_ci
38348c2ecf20Sopenharmony_ci	kfree(old_device_name);
38358c2ecf20Sopenharmony_ci
38368c2ecf20Sopenharmony_ci	return error;
38378c2ecf20Sopenharmony_ci}
38388c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_rename);
38398c2ecf20Sopenharmony_ci
38408c2ecf20Sopenharmony_cistatic int device_move_class_links(struct device *dev,
38418c2ecf20Sopenharmony_ci				   struct device *old_parent,
38428c2ecf20Sopenharmony_ci				   struct device *new_parent)
38438c2ecf20Sopenharmony_ci{
38448c2ecf20Sopenharmony_ci	int error = 0;
38458c2ecf20Sopenharmony_ci
38468c2ecf20Sopenharmony_ci	if (old_parent)
38478c2ecf20Sopenharmony_ci		sysfs_remove_link(&dev->kobj, "device");
38488c2ecf20Sopenharmony_ci	if (new_parent)
38498c2ecf20Sopenharmony_ci		error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
38508c2ecf20Sopenharmony_ci					  "device");
38518c2ecf20Sopenharmony_ci	return error;
38528c2ecf20Sopenharmony_ci}
38538c2ecf20Sopenharmony_ci
38548c2ecf20Sopenharmony_ci/**
38558c2ecf20Sopenharmony_ci * device_move - moves a device to a new parent
38568c2ecf20Sopenharmony_ci * @dev: the pointer to the struct device to be moved
38578c2ecf20Sopenharmony_ci * @new_parent: the new parent of the device (can be NULL)
38588c2ecf20Sopenharmony_ci * @dpm_order: how to reorder the dpm_list
38598c2ecf20Sopenharmony_ci */
38608c2ecf20Sopenharmony_ciint device_move(struct device *dev, struct device *new_parent,
38618c2ecf20Sopenharmony_ci		enum dpm_order dpm_order)
38628c2ecf20Sopenharmony_ci{
38638c2ecf20Sopenharmony_ci	int error;
38648c2ecf20Sopenharmony_ci	struct device *old_parent;
38658c2ecf20Sopenharmony_ci	struct kobject *new_parent_kobj;
38668c2ecf20Sopenharmony_ci
38678c2ecf20Sopenharmony_ci	dev = get_device(dev);
38688c2ecf20Sopenharmony_ci	if (!dev)
38698c2ecf20Sopenharmony_ci		return -EINVAL;
38708c2ecf20Sopenharmony_ci
38718c2ecf20Sopenharmony_ci	device_pm_lock();
38728c2ecf20Sopenharmony_ci	new_parent = get_device(new_parent);
38738c2ecf20Sopenharmony_ci	new_parent_kobj = get_device_parent(dev, new_parent);
38748c2ecf20Sopenharmony_ci	if (IS_ERR(new_parent_kobj)) {
38758c2ecf20Sopenharmony_ci		error = PTR_ERR(new_parent_kobj);
38768c2ecf20Sopenharmony_ci		put_device(new_parent);
38778c2ecf20Sopenharmony_ci		goto out;
38788c2ecf20Sopenharmony_ci	}
38798c2ecf20Sopenharmony_ci
38808c2ecf20Sopenharmony_ci	pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev),
38818c2ecf20Sopenharmony_ci		 __func__, new_parent ? dev_name(new_parent) : "<NULL>");
38828c2ecf20Sopenharmony_ci	error = kobject_move(&dev->kobj, new_parent_kobj);
38838c2ecf20Sopenharmony_ci	if (error) {
38848c2ecf20Sopenharmony_ci		cleanup_glue_dir(dev, new_parent_kobj);
38858c2ecf20Sopenharmony_ci		put_device(new_parent);
38868c2ecf20Sopenharmony_ci		goto out;
38878c2ecf20Sopenharmony_ci	}
38888c2ecf20Sopenharmony_ci	old_parent = dev->parent;
38898c2ecf20Sopenharmony_ci	dev->parent = new_parent;
38908c2ecf20Sopenharmony_ci	if (old_parent)
38918c2ecf20Sopenharmony_ci		klist_remove(&dev->p->knode_parent);
38928c2ecf20Sopenharmony_ci	if (new_parent) {
38938c2ecf20Sopenharmony_ci		klist_add_tail(&dev->p->knode_parent,
38948c2ecf20Sopenharmony_ci			       &new_parent->p->klist_children);
38958c2ecf20Sopenharmony_ci		set_dev_node(dev, dev_to_node(new_parent));
38968c2ecf20Sopenharmony_ci	}
38978c2ecf20Sopenharmony_ci
38988c2ecf20Sopenharmony_ci	if (dev->class) {
38998c2ecf20Sopenharmony_ci		error = device_move_class_links(dev, old_parent, new_parent);
39008c2ecf20Sopenharmony_ci		if (error) {
39018c2ecf20Sopenharmony_ci			/* We ignore errors on cleanup since we're hosed anyway... */
39028c2ecf20Sopenharmony_ci			device_move_class_links(dev, new_parent, old_parent);
39038c2ecf20Sopenharmony_ci			if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
39048c2ecf20Sopenharmony_ci				if (new_parent)
39058c2ecf20Sopenharmony_ci					klist_remove(&dev->p->knode_parent);
39068c2ecf20Sopenharmony_ci				dev->parent = old_parent;
39078c2ecf20Sopenharmony_ci				if (old_parent) {
39088c2ecf20Sopenharmony_ci					klist_add_tail(&dev->p->knode_parent,
39098c2ecf20Sopenharmony_ci						       &old_parent->p->klist_children);
39108c2ecf20Sopenharmony_ci					set_dev_node(dev, dev_to_node(old_parent));
39118c2ecf20Sopenharmony_ci				}
39128c2ecf20Sopenharmony_ci			}
39138c2ecf20Sopenharmony_ci			cleanup_glue_dir(dev, new_parent_kobj);
39148c2ecf20Sopenharmony_ci			put_device(new_parent);
39158c2ecf20Sopenharmony_ci			goto out;
39168c2ecf20Sopenharmony_ci		}
39178c2ecf20Sopenharmony_ci	}
39188c2ecf20Sopenharmony_ci	switch (dpm_order) {
39198c2ecf20Sopenharmony_ci	case DPM_ORDER_NONE:
39208c2ecf20Sopenharmony_ci		break;
39218c2ecf20Sopenharmony_ci	case DPM_ORDER_DEV_AFTER_PARENT:
39228c2ecf20Sopenharmony_ci		device_pm_move_after(dev, new_parent);
39238c2ecf20Sopenharmony_ci		devices_kset_move_after(dev, new_parent);
39248c2ecf20Sopenharmony_ci		break;
39258c2ecf20Sopenharmony_ci	case DPM_ORDER_PARENT_BEFORE_DEV:
39268c2ecf20Sopenharmony_ci		device_pm_move_before(new_parent, dev);
39278c2ecf20Sopenharmony_ci		devices_kset_move_before(new_parent, dev);
39288c2ecf20Sopenharmony_ci		break;
39298c2ecf20Sopenharmony_ci	case DPM_ORDER_DEV_LAST:
39308c2ecf20Sopenharmony_ci		device_pm_move_last(dev);
39318c2ecf20Sopenharmony_ci		devices_kset_move_last(dev);
39328c2ecf20Sopenharmony_ci		break;
39338c2ecf20Sopenharmony_ci	}
39348c2ecf20Sopenharmony_ci
39358c2ecf20Sopenharmony_ci	put_device(old_parent);
39368c2ecf20Sopenharmony_ciout:
39378c2ecf20Sopenharmony_ci	device_pm_unlock();
39388c2ecf20Sopenharmony_ci	put_device(dev);
39398c2ecf20Sopenharmony_ci	return error;
39408c2ecf20Sopenharmony_ci}
39418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_move);
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_cistatic int device_attrs_change_owner(struct device *dev, kuid_t kuid,
39448c2ecf20Sopenharmony_ci				     kgid_t kgid)
39458c2ecf20Sopenharmony_ci{
39468c2ecf20Sopenharmony_ci	struct kobject *kobj = &dev->kobj;
39478c2ecf20Sopenharmony_ci	struct class *class = dev->class;
39488c2ecf20Sopenharmony_ci	const struct device_type *type = dev->type;
39498c2ecf20Sopenharmony_ci	int error;
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci	if (class) {
39528c2ecf20Sopenharmony_ci		/*
39538c2ecf20Sopenharmony_ci		 * Change the device groups of the device class for @dev to
39548c2ecf20Sopenharmony_ci		 * @kuid/@kgid.
39558c2ecf20Sopenharmony_ci		 */
39568c2ecf20Sopenharmony_ci		error = sysfs_groups_change_owner(kobj, class->dev_groups, kuid,
39578c2ecf20Sopenharmony_ci						  kgid);
39588c2ecf20Sopenharmony_ci		if (error)
39598c2ecf20Sopenharmony_ci			return error;
39608c2ecf20Sopenharmony_ci	}
39618c2ecf20Sopenharmony_ci
39628c2ecf20Sopenharmony_ci	if (type) {
39638c2ecf20Sopenharmony_ci		/*
39648c2ecf20Sopenharmony_ci		 * Change the device groups of the device type for @dev to
39658c2ecf20Sopenharmony_ci		 * @kuid/@kgid.
39668c2ecf20Sopenharmony_ci		 */
39678c2ecf20Sopenharmony_ci		error = sysfs_groups_change_owner(kobj, type->groups, kuid,
39688c2ecf20Sopenharmony_ci						  kgid);
39698c2ecf20Sopenharmony_ci		if (error)
39708c2ecf20Sopenharmony_ci			return error;
39718c2ecf20Sopenharmony_ci	}
39728c2ecf20Sopenharmony_ci
39738c2ecf20Sopenharmony_ci	/* Change the device groups of @dev to @kuid/@kgid. */
39748c2ecf20Sopenharmony_ci	error = sysfs_groups_change_owner(kobj, dev->groups, kuid, kgid);
39758c2ecf20Sopenharmony_ci	if (error)
39768c2ecf20Sopenharmony_ci		return error;
39778c2ecf20Sopenharmony_ci
39788c2ecf20Sopenharmony_ci	if (device_supports_offline(dev) && !dev->offline_disabled) {
39798c2ecf20Sopenharmony_ci		/* Change online device attributes of @dev to @kuid/@kgid. */
39808c2ecf20Sopenharmony_ci		error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name,
39818c2ecf20Sopenharmony_ci						kuid, kgid);
39828c2ecf20Sopenharmony_ci		if (error)
39838c2ecf20Sopenharmony_ci			return error;
39848c2ecf20Sopenharmony_ci	}
39858c2ecf20Sopenharmony_ci
39868c2ecf20Sopenharmony_ci	return 0;
39878c2ecf20Sopenharmony_ci}
39888c2ecf20Sopenharmony_ci
39898c2ecf20Sopenharmony_ci/**
39908c2ecf20Sopenharmony_ci * device_change_owner - change the owner of an existing device.
39918c2ecf20Sopenharmony_ci * @dev: device.
39928c2ecf20Sopenharmony_ci * @kuid: new owner's kuid
39938c2ecf20Sopenharmony_ci * @kgid: new owner's kgid
39948c2ecf20Sopenharmony_ci *
39958c2ecf20Sopenharmony_ci * This changes the owner of @dev and its corresponding sysfs entries to
39968c2ecf20Sopenharmony_ci * @kuid/@kgid. This function closely mirrors how @dev was added via driver
39978c2ecf20Sopenharmony_ci * core.
39988c2ecf20Sopenharmony_ci *
39998c2ecf20Sopenharmony_ci * Returns 0 on success or error code on failure.
40008c2ecf20Sopenharmony_ci */
40018c2ecf20Sopenharmony_ciint device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid)
40028c2ecf20Sopenharmony_ci{
40038c2ecf20Sopenharmony_ci	int error;
40048c2ecf20Sopenharmony_ci	struct kobject *kobj = &dev->kobj;
40058c2ecf20Sopenharmony_ci
40068c2ecf20Sopenharmony_ci	dev = get_device(dev);
40078c2ecf20Sopenharmony_ci	if (!dev)
40088c2ecf20Sopenharmony_ci		return -EINVAL;
40098c2ecf20Sopenharmony_ci
40108c2ecf20Sopenharmony_ci	/*
40118c2ecf20Sopenharmony_ci	 * Change the kobject and the default attributes and groups of the
40128c2ecf20Sopenharmony_ci	 * ktype associated with it to @kuid/@kgid.
40138c2ecf20Sopenharmony_ci	 */
40148c2ecf20Sopenharmony_ci	error = sysfs_change_owner(kobj, kuid, kgid);
40158c2ecf20Sopenharmony_ci	if (error)
40168c2ecf20Sopenharmony_ci		goto out;
40178c2ecf20Sopenharmony_ci
40188c2ecf20Sopenharmony_ci	/*
40198c2ecf20Sopenharmony_ci	 * Change the uevent file for @dev to the new owner. The uevent file
40208c2ecf20Sopenharmony_ci	 * was created in a separate step when @dev got added and we mirror
40218c2ecf20Sopenharmony_ci	 * that step here.
40228c2ecf20Sopenharmony_ci	 */
40238c2ecf20Sopenharmony_ci	error = sysfs_file_change_owner(kobj, dev_attr_uevent.attr.name, kuid,
40248c2ecf20Sopenharmony_ci					kgid);
40258c2ecf20Sopenharmony_ci	if (error)
40268c2ecf20Sopenharmony_ci		goto out;
40278c2ecf20Sopenharmony_ci
40288c2ecf20Sopenharmony_ci	/*
40298c2ecf20Sopenharmony_ci	 * Change the device groups, the device groups associated with the
40308c2ecf20Sopenharmony_ci	 * device class, and the groups associated with the device type of @dev
40318c2ecf20Sopenharmony_ci	 * to @kuid/@kgid.
40328c2ecf20Sopenharmony_ci	 */
40338c2ecf20Sopenharmony_ci	error = device_attrs_change_owner(dev, kuid, kgid);
40348c2ecf20Sopenharmony_ci	if (error)
40358c2ecf20Sopenharmony_ci		goto out;
40368c2ecf20Sopenharmony_ci
40378c2ecf20Sopenharmony_ci	error = dpm_sysfs_change_owner(dev, kuid, kgid);
40388c2ecf20Sopenharmony_ci	if (error)
40398c2ecf20Sopenharmony_ci		goto out;
40408c2ecf20Sopenharmony_ci
40418c2ecf20Sopenharmony_ci#ifdef CONFIG_BLOCK
40428c2ecf20Sopenharmony_ci	if (sysfs_deprecated && dev->class == &block_class)
40438c2ecf20Sopenharmony_ci		goto out;
40448c2ecf20Sopenharmony_ci#endif
40458c2ecf20Sopenharmony_ci
40468c2ecf20Sopenharmony_ci	/*
40478c2ecf20Sopenharmony_ci	 * Change the owner of the symlink located in the class directory of
40488c2ecf20Sopenharmony_ci	 * the device class associated with @dev which points to the actual
40498c2ecf20Sopenharmony_ci	 * directory entry for @dev to @kuid/@kgid. This ensures that the
40508c2ecf20Sopenharmony_ci	 * symlink shows the same permissions as its target.
40518c2ecf20Sopenharmony_ci	 */
40528c2ecf20Sopenharmony_ci	error = sysfs_link_change_owner(&dev->class->p->subsys.kobj, &dev->kobj,
40538c2ecf20Sopenharmony_ci					dev_name(dev), kuid, kgid);
40548c2ecf20Sopenharmony_ci	if (error)
40558c2ecf20Sopenharmony_ci		goto out;
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ciout:
40588c2ecf20Sopenharmony_ci	put_device(dev);
40598c2ecf20Sopenharmony_ci	return error;
40608c2ecf20Sopenharmony_ci}
40618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_change_owner);
40628c2ecf20Sopenharmony_ci
40638c2ecf20Sopenharmony_ci/**
40648c2ecf20Sopenharmony_ci * device_shutdown - call ->shutdown() on each device to shutdown.
40658c2ecf20Sopenharmony_ci */
40668c2ecf20Sopenharmony_civoid device_shutdown(void)
40678c2ecf20Sopenharmony_ci{
40688c2ecf20Sopenharmony_ci	struct device *dev, *parent;
40698c2ecf20Sopenharmony_ci
40708c2ecf20Sopenharmony_ci	wait_for_device_probe();
40718c2ecf20Sopenharmony_ci	device_block_probing();
40728c2ecf20Sopenharmony_ci
40738c2ecf20Sopenharmony_ci	cpufreq_suspend();
40748c2ecf20Sopenharmony_ci
40758c2ecf20Sopenharmony_ci	spin_lock(&devices_kset->list_lock);
40768c2ecf20Sopenharmony_ci	/*
40778c2ecf20Sopenharmony_ci	 * Walk the devices list backward, shutting down each in turn.
40788c2ecf20Sopenharmony_ci	 * Beware that device unplug events may also start pulling
40798c2ecf20Sopenharmony_ci	 * devices offline, even as the system is shutting down.
40808c2ecf20Sopenharmony_ci	 */
40818c2ecf20Sopenharmony_ci	while (!list_empty(&devices_kset->list)) {
40828c2ecf20Sopenharmony_ci		dev = list_entry(devices_kset->list.prev, struct device,
40838c2ecf20Sopenharmony_ci				kobj.entry);
40848c2ecf20Sopenharmony_ci
40858c2ecf20Sopenharmony_ci		/*
40868c2ecf20Sopenharmony_ci		 * hold reference count of device's parent to
40878c2ecf20Sopenharmony_ci		 * prevent it from being freed because parent's
40888c2ecf20Sopenharmony_ci		 * lock is to be held
40898c2ecf20Sopenharmony_ci		 */
40908c2ecf20Sopenharmony_ci		parent = get_device(dev->parent);
40918c2ecf20Sopenharmony_ci		get_device(dev);
40928c2ecf20Sopenharmony_ci		/*
40938c2ecf20Sopenharmony_ci		 * Make sure the device is off the kset list, in the
40948c2ecf20Sopenharmony_ci		 * event that dev->*->shutdown() doesn't remove it.
40958c2ecf20Sopenharmony_ci		 */
40968c2ecf20Sopenharmony_ci		list_del_init(&dev->kobj.entry);
40978c2ecf20Sopenharmony_ci		spin_unlock(&devices_kset->list_lock);
40988c2ecf20Sopenharmony_ci
40998c2ecf20Sopenharmony_ci		/* hold lock to avoid race with probe/release */
41008c2ecf20Sopenharmony_ci		if (parent)
41018c2ecf20Sopenharmony_ci			device_lock(parent);
41028c2ecf20Sopenharmony_ci		device_lock(dev);
41038c2ecf20Sopenharmony_ci
41048c2ecf20Sopenharmony_ci		/* Don't allow any more runtime suspends */
41058c2ecf20Sopenharmony_ci		pm_runtime_get_noresume(dev);
41068c2ecf20Sopenharmony_ci		pm_runtime_barrier(dev);
41078c2ecf20Sopenharmony_ci
41088c2ecf20Sopenharmony_ci		if (dev->class && dev->class->shutdown_pre) {
41098c2ecf20Sopenharmony_ci			if (initcall_debug)
41108c2ecf20Sopenharmony_ci				dev_info(dev, "shutdown_pre\n");
41118c2ecf20Sopenharmony_ci			dev->class->shutdown_pre(dev);
41128c2ecf20Sopenharmony_ci		}
41138c2ecf20Sopenharmony_ci		if (dev->bus && dev->bus->shutdown) {
41148c2ecf20Sopenharmony_ci			if (initcall_debug)
41158c2ecf20Sopenharmony_ci				dev_info(dev, "shutdown\n");
41168c2ecf20Sopenharmony_ci			dev->bus->shutdown(dev);
41178c2ecf20Sopenharmony_ci		} else if (dev->driver && dev->driver->shutdown) {
41188c2ecf20Sopenharmony_ci			if (initcall_debug)
41198c2ecf20Sopenharmony_ci				dev_info(dev, "shutdown\n");
41208c2ecf20Sopenharmony_ci			dev->driver->shutdown(dev);
41218c2ecf20Sopenharmony_ci		}
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_ci		device_unlock(dev);
41248c2ecf20Sopenharmony_ci		if (parent)
41258c2ecf20Sopenharmony_ci			device_unlock(parent);
41268c2ecf20Sopenharmony_ci
41278c2ecf20Sopenharmony_ci		put_device(dev);
41288c2ecf20Sopenharmony_ci		put_device(parent);
41298c2ecf20Sopenharmony_ci
41308c2ecf20Sopenharmony_ci		spin_lock(&devices_kset->list_lock);
41318c2ecf20Sopenharmony_ci	}
41328c2ecf20Sopenharmony_ci	spin_unlock(&devices_kset->list_lock);
41338c2ecf20Sopenharmony_ci}
41348c2ecf20Sopenharmony_ci
41358c2ecf20Sopenharmony_ci/*
41368c2ecf20Sopenharmony_ci * Device logging functions
41378c2ecf20Sopenharmony_ci */
41388c2ecf20Sopenharmony_ci
41398c2ecf20Sopenharmony_ci#ifdef CONFIG_PRINTK
41408c2ecf20Sopenharmony_cistatic void
41418c2ecf20Sopenharmony_ciset_dev_info(const struct device *dev, struct dev_printk_info *dev_info)
41428c2ecf20Sopenharmony_ci{
41438c2ecf20Sopenharmony_ci	const char *subsys;
41448c2ecf20Sopenharmony_ci
41458c2ecf20Sopenharmony_ci	memset(dev_info, 0, sizeof(*dev_info));
41468c2ecf20Sopenharmony_ci
41478c2ecf20Sopenharmony_ci	if (dev->class)
41488c2ecf20Sopenharmony_ci		subsys = dev->class->name;
41498c2ecf20Sopenharmony_ci	else if (dev->bus)
41508c2ecf20Sopenharmony_ci		subsys = dev->bus->name;
41518c2ecf20Sopenharmony_ci	else
41528c2ecf20Sopenharmony_ci		return;
41538c2ecf20Sopenharmony_ci
41548c2ecf20Sopenharmony_ci	strscpy(dev_info->subsystem, subsys, sizeof(dev_info->subsystem));
41558c2ecf20Sopenharmony_ci
41568c2ecf20Sopenharmony_ci	/*
41578c2ecf20Sopenharmony_ci	 * Add device identifier DEVICE=:
41588c2ecf20Sopenharmony_ci	 *   b12:8         block dev_t
41598c2ecf20Sopenharmony_ci	 *   c127:3        char dev_t
41608c2ecf20Sopenharmony_ci	 *   n8            netdev ifindex
41618c2ecf20Sopenharmony_ci	 *   +sound:card0  subsystem:devname
41628c2ecf20Sopenharmony_ci	 */
41638c2ecf20Sopenharmony_ci	if (MAJOR(dev->devt)) {
41648c2ecf20Sopenharmony_ci		char c;
41658c2ecf20Sopenharmony_ci
41668c2ecf20Sopenharmony_ci		if (strcmp(subsys, "block") == 0)
41678c2ecf20Sopenharmony_ci			c = 'b';
41688c2ecf20Sopenharmony_ci		else
41698c2ecf20Sopenharmony_ci			c = 'c';
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci		snprintf(dev_info->device, sizeof(dev_info->device),
41728c2ecf20Sopenharmony_ci			 "%c%u:%u", c, MAJOR(dev->devt), MINOR(dev->devt));
41738c2ecf20Sopenharmony_ci	} else if (strcmp(subsys, "net") == 0) {
41748c2ecf20Sopenharmony_ci		struct net_device *net = to_net_dev(dev);
41758c2ecf20Sopenharmony_ci
41768c2ecf20Sopenharmony_ci		snprintf(dev_info->device, sizeof(dev_info->device),
41778c2ecf20Sopenharmony_ci			 "n%u", net->ifindex);
41788c2ecf20Sopenharmony_ci	} else {
41798c2ecf20Sopenharmony_ci		snprintf(dev_info->device, sizeof(dev_info->device),
41808c2ecf20Sopenharmony_ci			 "+%s:%s", subsys, dev_name(dev));
41818c2ecf20Sopenharmony_ci	}
41828c2ecf20Sopenharmony_ci}
41838c2ecf20Sopenharmony_ci
41848c2ecf20Sopenharmony_ciint dev_vprintk_emit(int level, const struct device *dev,
41858c2ecf20Sopenharmony_ci		     const char *fmt, va_list args)
41868c2ecf20Sopenharmony_ci{
41878c2ecf20Sopenharmony_ci	struct dev_printk_info dev_info;
41888c2ecf20Sopenharmony_ci
41898c2ecf20Sopenharmony_ci	set_dev_info(dev, &dev_info);
41908c2ecf20Sopenharmony_ci
41918c2ecf20Sopenharmony_ci	return vprintk_emit(0, level, &dev_info, fmt, args);
41928c2ecf20Sopenharmony_ci}
41938c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dev_vprintk_emit);
41948c2ecf20Sopenharmony_ci
41958c2ecf20Sopenharmony_ciint dev_printk_emit(int level, const struct device *dev, const char *fmt, ...)
41968c2ecf20Sopenharmony_ci{
41978c2ecf20Sopenharmony_ci	va_list args;
41988c2ecf20Sopenharmony_ci	int r;
41998c2ecf20Sopenharmony_ci
42008c2ecf20Sopenharmony_ci	va_start(args, fmt);
42018c2ecf20Sopenharmony_ci
42028c2ecf20Sopenharmony_ci	r = dev_vprintk_emit(level, dev, fmt, args);
42038c2ecf20Sopenharmony_ci
42048c2ecf20Sopenharmony_ci	va_end(args);
42058c2ecf20Sopenharmony_ci
42068c2ecf20Sopenharmony_ci	return r;
42078c2ecf20Sopenharmony_ci}
42088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dev_printk_emit);
42098c2ecf20Sopenharmony_ci
42108c2ecf20Sopenharmony_cistatic void __dev_printk(const char *level, const struct device *dev,
42118c2ecf20Sopenharmony_ci			struct va_format *vaf)
42128c2ecf20Sopenharmony_ci{
42138c2ecf20Sopenharmony_ci	if (dev)
42148c2ecf20Sopenharmony_ci		dev_printk_emit(level[1] - '0', dev, "%s %s: %pV",
42158c2ecf20Sopenharmony_ci				dev_driver_string(dev), dev_name(dev), vaf);
42168c2ecf20Sopenharmony_ci	else
42178c2ecf20Sopenharmony_ci		printk("%s(NULL device *): %pV", level, vaf);
42188c2ecf20Sopenharmony_ci}
42198c2ecf20Sopenharmony_ci
42208c2ecf20Sopenharmony_civoid dev_printk(const char *level, const struct device *dev,
42218c2ecf20Sopenharmony_ci		const char *fmt, ...)
42228c2ecf20Sopenharmony_ci{
42238c2ecf20Sopenharmony_ci	struct va_format vaf;
42248c2ecf20Sopenharmony_ci	va_list args;
42258c2ecf20Sopenharmony_ci
42268c2ecf20Sopenharmony_ci	va_start(args, fmt);
42278c2ecf20Sopenharmony_ci
42288c2ecf20Sopenharmony_ci	vaf.fmt = fmt;
42298c2ecf20Sopenharmony_ci	vaf.va = &args;
42308c2ecf20Sopenharmony_ci
42318c2ecf20Sopenharmony_ci	__dev_printk(level, dev, &vaf);
42328c2ecf20Sopenharmony_ci
42338c2ecf20Sopenharmony_ci	va_end(args);
42348c2ecf20Sopenharmony_ci}
42358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dev_printk);
42368c2ecf20Sopenharmony_ci
42378c2ecf20Sopenharmony_ci#define define_dev_printk_level(func, kern_level)		\
42388c2ecf20Sopenharmony_civoid func(const struct device *dev, const char *fmt, ...)	\
42398c2ecf20Sopenharmony_ci{								\
42408c2ecf20Sopenharmony_ci	struct va_format vaf;					\
42418c2ecf20Sopenharmony_ci	va_list args;						\
42428c2ecf20Sopenharmony_ci								\
42438c2ecf20Sopenharmony_ci	va_start(args, fmt);					\
42448c2ecf20Sopenharmony_ci								\
42458c2ecf20Sopenharmony_ci	vaf.fmt = fmt;						\
42468c2ecf20Sopenharmony_ci	vaf.va = &args;						\
42478c2ecf20Sopenharmony_ci								\
42488c2ecf20Sopenharmony_ci	__dev_printk(kern_level, dev, &vaf);			\
42498c2ecf20Sopenharmony_ci								\
42508c2ecf20Sopenharmony_ci	va_end(args);						\
42518c2ecf20Sopenharmony_ci}								\
42528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(func);
42538c2ecf20Sopenharmony_ci
42548c2ecf20Sopenharmony_cidefine_dev_printk_level(_dev_emerg, KERN_EMERG);
42558c2ecf20Sopenharmony_cidefine_dev_printk_level(_dev_alert, KERN_ALERT);
42568c2ecf20Sopenharmony_cidefine_dev_printk_level(_dev_crit, KERN_CRIT);
42578c2ecf20Sopenharmony_cidefine_dev_printk_level(_dev_err, KERN_ERR);
42588c2ecf20Sopenharmony_cidefine_dev_printk_level(_dev_warn, KERN_WARNING);
42598c2ecf20Sopenharmony_cidefine_dev_printk_level(_dev_notice, KERN_NOTICE);
42608c2ecf20Sopenharmony_cidefine_dev_printk_level(_dev_info, KERN_INFO);
42618c2ecf20Sopenharmony_ci
42628c2ecf20Sopenharmony_ci#endif
42638c2ecf20Sopenharmony_ci
42648c2ecf20Sopenharmony_ci/**
42658c2ecf20Sopenharmony_ci * dev_err_probe - probe error check and log helper
42668c2ecf20Sopenharmony_ci * @dev: the pointer to the struct device
42678c2ecf20Sopenharmony_ci * @err: error value to test
42688c2ecf20Sopenharmony_ci * @fmt: printf-style format string
42698c2ecf20Sopenharmony_ci * @...: arguments as specified in the format string
42708c2ecf20Sopenharmony_ci *
42718c2ecf20Sopenharmony_ci * This helper implements common pattern present in probe functions for error
42728c2ecf20Sopenharmony_ci * checking: print debug or error message depending if the error value is
42738c2ecf20Sopenharmony_ci * -EPROBE_DEFER and propagate error upwards.
42748c2ecf20Sopenharmony_ci * In case of -EPROBE_DEFER it sets also defer probe reason, which can be
42758c2ecf20Sopenharmony_ci * checked later by reading devices_deferred debugfs attribute.
42768c2ecf20Sopenharmony_ci * It replaces code sequence::
42778c2ecf20Sopenharmony_ci *
42788c2ecf20Sopenharmony_ci * 	if (err != -EPROBE_DEFER)
42798c2ecf20Sopenharmony_ci * 		dev_err(dev, ...);
42808c2ecf20Sopenharmony_ci * 	else
42818c2ecf20Sopenharmony_ci * 		dev_dbg(dev, ...);
42828c2ecf20Sopenharmony_ci * 	return err;
42838c2ecf20Sopenharmony_ci *
42848c2ecf20Sopenharmony_ci * with::
42858c2ecf20Sopenharmony_ci *
42868c2ecf20Sopenharmony_ci * 	return dev_err_probe(dev, err, ...);
42878c2ecf20Sopenharmony_ci *
42888c2ecf20Sopenharmony_ci * Returns @err.
42898c2ecf20Sopenharmony_ci *
42908c2ecf20Sopenharmony_ci */
42918c2ecf20Sopenharmony_ciint dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
42928c2ecf20Sopenharmony_ci{
42938c2ecf20Sopenharmony_ci	struct va_format vaf;
42948c2ecf20Sopenharmony_ci	va_list args;
42958c2ecf20Sopenharmony_ci
42968c2ecf20Sopenharmony_ci	va_start(args, fmt);
42978c2ecf20Sopenharmony_ci	vaf.fmt = fmt;
42988c2ecf20Sopenharmony_ci	vaf.va = &args;
42998c2ecf20Sopenharmony_ci
43008c2ecf20Sopenharmony_ci	if (err != -EPROBE_DEFER) {
43018c2ecf20Sopenharmony_ci		dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
43028c2ecf20Sopenharmony_ci	} else {
43038c2ecf20Sopenharmony_ci		device_set_deferred_probe_reason(dev, &vaf);
43048c2ecf20Sopenharmony_ci		dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
43058c2ecf20Sopenharmony_ci	}
43068c2ecf20Sopenharmony_ci
43078c2ecf20Sopenharmony_ci	va_end(args);
43088c2ecf20Sopenharmony_ci
43098c2ecf20Sopenharmony_ci	return err;
43108c2ecf20Sopenharmony_ci}
43118c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_err_probe);
43128c2ecf20Sopenharmony_ci
43138c2ecf20Sopenharmony_cistatic inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
43148c2ecf20Sopenharmony_ci{
43158c2ecf20Sopenharmony_ci	return fwnode && !IS_ERR(fwnode->secondary);
43168c2ecf20Sopenharmony_ci}
43178c2ecf20Sopenharmony_ci
43188c2ecf20Sopenharmony_ci/**
43198c2ecf20Sopenharmony_ci * set_primary_fwnode - Change the primary firmware node of a given device.
43208c2ecf20Sopenharmony_ci * @dev: Device to handle.
43218c2ecf20Sopenharmony_ci * @fwnode: New primary firmware node of the device.
43228c2ecf20Sopenharmony_ci *
43238c2ecf20Sopenharmony_ci * Set the device's firmware node pointer to @fwnode, but if a secondary
43248c2ecf20Sopenharmony_ci * firmware node of the device is present, preserve it.
43258c2ecf20Sopenharmony_ci */
43268c2ecf20Sopenharmony_civoid set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
43278c2ecf20Sopenharmony_ci{
43288c2ecf20Sopenharmony_ci	struct device *parent = dev->parent;
43298c2ecf20Sopenharmony_ci	struct fwnode_handle *fn = dev->fwnode;
43308c2ecf20Sopenharmony_ci
43318c2ecf20Sopenharmony_ci	if (fwnode) {
43328c2ecf20Sopenharmony_ci		if (fwnode_is_primary(fn))
43338c2ecf20Sopenharmony_ci			fn = fn->secondary;
43348c2ecf20Sopenharmony_ci
43358c2ecf20Sopenharmony_ci		if (fn) {
43368c2ecf20Sopenharmony_ci			WARN_ON(fwnode->secondary);
43378c2ecf20Sopenharmony_ci			fwnode->secondary = fn;
43388c2ecf20Sopenharmony_ci		}
43398c2ecf20Sopenharmony_ci		dev->fwnode = fwnode;
43408c2ecf20Sopenharmony_ci	} else {
43418c2ecf20Sopenharmony_ci		if (fwnode_is_primary(fn)) {
43428c2ecf20Sopenharmony_ci			dev->fwnode = fn->secondary;
43438c2ecf20Sopenharmony_ci			if (!(parent && fn == parent->fwnode))
43448c2ecf20Sopenharmony_ci				fn->secondary = NULL;
43458c2ecf20Sopenharmony_ci		} else {
43468c2ecf20Sopenharmony_ci			dev->fwnode = NULL;
43478c2ecf20Sopenharmony_ci		}
43488c2ecf20Sopenharmony_ci	}
43498c2ecf20Sopenharmony_ci}
43508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(set_primary_fwnode);
43518c2ecf20Sopenharmony_ci
43528c2ecf20Sopenharmony_ci/**
43538c2ecf20Sopenharmony_ci * set_secondary_fwnode - Change the secondary firmware node of a given device.
43548c2ecf20Sopenharmony_ci * @dev: Device to handle.
43558c2ecf20Sopenharmony_ci * @fwnode: New secondary firmware node of the device.
43568c2ecf20Sopenharmony_ci *
43578c2ecf20Sopenharmony_ci * If a primary firmware node of the device is present, set its secondary
43588c2ecf20Sopenharmony_ci * pointer to @fwnode.  Otherwise, set the device's firmware node pointer to
43598c2ecf20Sopenharmony_ci * @fwnode.
43608c2ecf20Sopenharmony_ci */
43618c2ecf20Sopenharmony_civoid set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
43628c2ecf20Sopenharmony_ci{
43638c2ecf20Sopenharmony_ci	if (fwnode)
43648c2ecf20Sopenharmony_ci		fwnode->secondary = ERR_PTR(-ENODEV);
43658c2ecf20Sopenharmony_ci
43668c2ecf20Sopenharmony_ci	if (fwnode_is_primary(dev->fwnode))
43678c2ecf20Sopenharmony_ci		dev->fwnode->secondary = fwnode;
43688c2ecf20Sopenharmony_ci	else
43698c2ecf20Sopenharmony_ci		dev->fwnode = fwnode;
43708c2ecf20Sopenharmony_ci}
43718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(set_secondary_fwnode);
43728c2ecf20Sopenharmony_ci
43738c2ecf20Sopenharmony_ci/**
43748c2ecf20Sopenharmony_ci * device_set_of_node_from_dev - reuse device-tree node of another device
43758c2ecf20Sopenharmony_ci * @dev: device whose device-tree node is being set
43768c2ecf20Sopenharmony_ci * @dev2: device whose device-tree node is being reused
43778c2ecf20Sopenharmony_ci *
43788c2ecf20Sopenharmony_ci * Takes another reference to the new device-tree node after first dropping
43798c2ecf20Sopenharmony_ci * any reference held to the old node.
43808c2ecf20Sopenharmony_ci */
43818c2ecf20Sopenharmony_civoid device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
43828c2ecf20Sopenharmony_ci{
43838c2ecf20Sopenharmony_ci	of_node_put(dev->of_node);
43848c2ecf20Sopenharmony_ci	dev->of_node = of_node_get(dev2->of_node);
43858c2ecf20Sopenharmony_ci	dev->of_node_reused = true;
43868c2ecf20Sopenharmony_ci}
43878c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
43888c2ecf20Sopenharmony_ci
43898c2ecf20Sopenharmony_civoid device_set_node(struct device *dev, struct fwnode_handle *fwnode)
43908c2ecf20Sopenharmony_ci{
43918c2ecf20Sopenharmony_ci	dev->fwnode = fwnode;
43928c2ecf20Sopenharmony_ci	dev->of_node = to_of_node(fwnode);
43938c2ecf20Sopenharmony_ci}
43948c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_set_node);
43958c2ecf20Sopenharmony_ci
43968c2ecf20Sopenharmony_ciint device_match_name(struct device *dev, const void *name)
43978c2ecf20Sopenharmony_ci{
43988c2ecf20Sopenharmony_ci	return sysfs_streq(dev_name(dev), name);
43998c2ecf20Sopenharmony_ci}
44008c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_match_name);
44018c2ecf20Sopenharmony_ci
44028c2ecf20Sopenharmony_ciint device_match_of_node(struct device *dev, const void *np)
44038c2ecf20Sopenharmony_ci{
44048c2ecf20Sopenharmony_ci	return dev->of_node == np;
44058c2ecf20Sopenharmony_ci}
44068c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_match_of_node);
44078c2ecf20Sopenharmony_ci
44088c2ecf20Sopenharmony_ciint device_match_fwnode(struct device *dev, const void *fwnode)
44098c2ecf20Sopenharmony_ci{
44108c2ecf20Sopenharmony_ci	return dev_fwnode(dev) == fwnode;
44118c2ecf20Sopenharmony_ci}
44128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_match_fwnode);
44138c2ecf20Sopenharmony_ci
44148c2ecf20Sopenharmony_ciint device_match_devt(struct device *dev, const void *pdevt)
44158c2ecf20Sopenharmony_ci{
44168c2ecf20Sopenharmony_ci	return dev->devt == *(dev_t *)pdevt;
44178c2ecf20Sopenharmony_ci}
44188c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_match_devt);
44198c2ecf20Sopenharmony_ci
44208c2ecf20Sopenharmony_ciint device_match_acpi_dev(struct device *dev, const void *adev)
44218c2ecf20Sopenharmony_ci{
44228c2ecf20Sopenharmony_ci	return ACPI_COMPANION(dev) == adev;
44238c2ecf20Sopenharmony_ci}
44248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(device_match_acpi_dev);
44258c2ecf20Sopenharmony_ci
44268c2ecf20Sopenharmony_ciint device_match_any(struct device *dev, const void *unused)
44278c2ecf20Sopenharmony_ci{
44288c2ecf20Sopenharmony_ci	return 1;
44298c2ecf20Sopenharmony_ci}
44308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(device_match_any);
4431