1989d42e8SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * drivers/base/core.c - core driver model code (device registration, etc) 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (c) 2002-3 Patrick Mochel 61da177e4SLinus Torvalds * Copyright (c) 2002-3 Open Source Development Labs 764bb5d2cSGreg Kroah-Hartman * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de> 864bb5d2cSGreg Kroah-Hartman * Copyright (c) 2006 Novell, Inc. 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #include <linux/device.h> 121da177e4SLinus Torvalds #include <linux/err.h> 1397badf87SRafael J. Wysocki #include <linux/fwnode.h> 141da177e4SLinus Torvalds #include <linux/init.h> 151da177e4SLinus Torvalds #include <linux/module.h> 161da177e4SLinus Torvalds #include <linux/slab.h> 171da177e4SLinus Torvalds #include <linux/string.h> 1823681e47SGreg Kroah-Hartman #include <linux/kdev_t.h> 19116af378SBenjamin Herrenschmidt #include <linux/notifier.h> 2007d57a32SGrant Likely #include <linux/of.h> 2107d57a32SGrant Likely #include <linux/of_device.h> 22da231fd5SKay Sievers #include <linux/genhd.h> 23f75b1c60SDave Young #include <linux/mutex.h> 24af8db150SPeter Chen #include <linux/pm_runtime.h> 25c4e00daaSKay Sievers #include <linux/netdevice.h> 26174cd4b1SIngo Molnar #include <linux/sched/signal.h> 2763967685SGreg Kroah-Hartman #include <linux/sysfs.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include "base.h" 301da177e4SLinus Torvalds #include "power/power.h" 311da177e4SLinus Torvalds 32e52eec13SAndi Kleen #ifdef CONFIG_SYSFS_DEPRECATED 33e52eec13SAndi Kleen #ifdef CONFIG_SYSFS_DEPRECATED_V2 34e52eec13SAndi Kleen long sysfs_deprecated = 1; 35e52eec13SAndi Kleen #else 36e52eec13SAndi Kleen long sysfs_deprecated = 0; 37e52eec13SAndi Kleen #endif 383454bf96SHanjun Guo static int __init sysfs_deprecated_setup(char *arg) 39e52eec13SAndi Kleen { 4034da5e67SJingoo Han return kstrtol(arg, 10, &sysfs_deprecated); 41e52eec13SAndi Kleen } 42e52eec13SAndi Kleen early_param("sysfs.deprecated", sysfs_deprecated_setup); 43e52eec13SAndi Kleen #endif 44e52eec13SAndi Kleen 459ed98953SRafael J. Wysocki /* Device links support. */ 469ed98953SRafael J. Wysocki 479ed98953SRafael J. Wysocki #ifdef CONFIG_SRCU 489ed98953SRafael J. Wysocki static DEFINE_MUTEX(device_links_lock); 499ed98953SRafael J. Wysocki DEFINE_STATIC_SRCU(device_links_srcu); 509ed98953SRafael J. Wysocki 519ed98953SRafael J. Wysocki static inline void device_links_write_lock(void) 529ed98953SRafael J. Wysocki { 539ed98953SRafael J. Wysocki mutex_lock(&device_links_lock); 549ed98953SRafael J. Wysocki } 559ed98953SRafael J. Wysocki 569ed98953SRafael J. Wysocki static inline void device_links_write_unlock(void) 579ed98953SRafael J. Wysocki { 589ed98953SRafael J. Wysocki mutex_unlock(&device_links_lock); 599ed98953SRafael J. Wysocki } 609ed98953SRafael J. Wysocki 619ed98953SRafael J. Wysocki int device_links_read_lock(void) 629ed98953SRafael J. Wysocki { 639ed98953SRafael J. Wysocki return srcu_read_lock(&device_links_srcu); 649ed98953SRafael J. Wysocki } 659ed98953SRafael J. Wysocki 669ed98953SRafael J. Wysocki void device_links_read_unlock(int idx) 679ed98953SRafael J. Wysocki { 689ed98953SRafael J. Wysocki srcu_read_unlock(&device_links_srcu, idx); 699ed98953SRafael J. Wysocki } 709ed98953SRafael J. Wysocki #else /* !CONFIG_SRCU */ 719ed98953SRafael J. Wysocki static DECLARE_RWSEM(device_links_lock); 729ed98953SRafael J. Wysocki 739ed98953SRafael J. Wysocki static inline void device_links_write_lock(void) 749ed98953SRafael J. Wysocki { 759ed98953SRafael J. Wysocki down_write(&device_links_lock); 769ed98953SRafael J. Wysocki } 779ed98953SRafael J. Wysocki 789ed98953SRafael J. Wysocki static inline void device_links_write_unlock(void) 799ed98953SRafael J. Wysocki { 809ed98953SRafael J. Wysocki up_write(&device_links_lock); 819ed98953SRafael J. Wysocki } 829ed98953SRafael J. Wysocki 839ed98953SRafael J. Wysocki int device_links_read_lock(void) 849ed98953SRafael J. Wysocki { 859ed98953SRafael J. Wysocki down_read(&device_links_lock); 869ed98953SRafael J. Wysocki return 0; 879ed98953SRafael J. Wysocki } 889ed98953SRafael J. Wysocki 899ed98953SRafael J. Wysocki void device_links_read_unlock(int not_used) 909ed98953SRafael J. Wysocki { 919ed98953SRafael J. Wysocki up_read(&device_links_lock); 929ed98953SRafael J. Wysocki } 939ed98953SRafael J. Wysocki #endif /* !CONFIG_SRCU */ 949ed98953SRafael J. Wysocki 959ed98953SRafael J. Wysocki /** 969ed98953SRafael J. Wysocki * device_is_dependent - Check if one device depends on another one 979ed98953SRafael J. Wysocki * @dev: Device to check dependencies for. 989ed98953SRafael J. Wysocki * @target: Device to check against. 999ed98953SRafael J. Wysocki * 1009ed98953SRafael J. Wysocki * Check if @target depends on @dev or any device dependent on it (its child or 1019ed98953SRafael J. Wysocki * its consumer etc). Return 1 if that is the case or 0 otherwise. 1029ed98953SRafael J. Wysocki */ 1039ed98953SRafael J. Wysocki static int device_is_dependent(struct device *dev, void *target) 1049ed98953SRafael J. Wysocki { 1059ed98953SRafael J. Wysocki struct device_link *link; 1069ed98953SRafael J. Wysocki int ret; 1079ed98953SRafael J. Wysocki 1089ed98953SRafael J. Wysocki if (WARN_ON(dev == target)) 1099ed98953SRafael J. Wysocki return 1; 1109ed98953SRafael J. Wysocki 1119ed98953SRafael J. Wysocki ret = device_for_each_child(dev, target, device_is_dependent); 1129ed98953SRafael J. Wysocki if (ret) 1139ed98953SRafael J. Wysocki return ret; 1149ed98953SRafael J. Wysocki 1159ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.consumers, s_node) { 1169ed98953SRafael J. Wysocki if (WARN_ON(link->consumer == target)) 1179ed98953SRafael J. Wysocki return 1; 1189ed98953SRafael J. Wysocki 1199ed98953SRafael J. Wysocki ret = device_is_dependent(link->consumer, target); 1209ed98953SRafael J. Wysocki if (ret) 1219ed98953SRafael J. Wysocki break; 1229ed98953SRafael J. Wysocki } 1239ed98953SRafael J. Wysocki return ret; 1249ed98953SRafael J. Wysocki } 1259ed98953SRafael J. Wysocki 1269ed98953SRafael J. Wysocki static int device_reorder_to_tail(struct device *dev, void *not_used) 1279ed98953SRafael J. Wysocki { 1289ed98953SRafael J. Wysocki struct device_link *link; 1299ed98953SRafael J. Wysocki 1309ed98953SRafael J. Wysocki /* 1319ed98953SRafael J. Wysocki * Devices that have not been registered yet will be put to the ends 1329ed98953SRafael J. Wysocki * of the lists during the registration, so skip them here. 1339ed98953SRafael J. Wysocki */ 1349ed98953SRafael J. Wysocki if (device_is_registered(dev)) 1359ed98953SRafael J. Wysocki devices_kset_move_last(dev); 1369ed98953SRafael J. Wysocki 1379ed98953SRafael J. Wysocki if (device_pm_initialized(dev)) 1389ed98953SRafael J. Wysocki device_pm_move_last(dev); 1399ed98953SRafael J. Wysocki 1409ed98953SRafael J. Wysocki device_for_each_child(dev, NULL, device_reorder_to_tail); 1419ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.consumers, s_node) 1429ed98953SRafael J. Wysocki device_reorder_to_tail(link->consumer, NULL); 1439ed98953SRafael J. Wysocki 1449ed98953SRafael J. Wysocki return 0; 1459ed98953SRafael J. Wysocki } 1469ed98953SRafael J. Wysocki 1479ed98953SRafael J. Wysocki /** 1489ed98953SRafael J. Wysocki * device_link_add - Create a link between two devices. 1499ed98953SRafael J. Wysocki * @consumer: Consumer end of the link. 1509ed98953SRafael J. Wysocki * @supplier: Supplier end of the link. 1519ed98953SRafael J. Wysocki * @flags: Link flags. 1529ed98953SRafael J. Wysocki * 15321d5c57bSRafael J. Wysocki * The caller is responsible for the proper synchronization of the link creation 15421d5c57bSRafael J. Wysocki * with runtime PM. First, setting the DL_FLAG_PM_RUNTIME flag will cause the 15521d5c57bSRafael J. Wysocki * runtime PM framework to take the link into account. Second, if the 15621d5c57bSRafael J. Wysocki * DL_FLAG_RPM_ACTIVE flag is set in addition to it, the supplier devices will 15721d5c57bSRafael J. Wysocki * be forced into the active metastate and reference-counted upon the creation 15821d5c57bSRafael J. Wysocki * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be 15921d5c57bSRafael J. Wysocki * ignored. 16021d5c57bSRafael J. Wysocki * 1619ed98953SRafael J. Wysocki * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically 1629ed98953SRafael J. Wysocki * when the consumer device driver unbinds from it. The combination of both 1639ed98953SRafael J. Wysocki * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL 1649ed98953SRafael J. Wysocki * to be returned. 1659ed98953SRafael J. Wysocki * 1669ed98953SRafael J. Wysocki * A side effect of the link creation is re-ordering of dpm_list and the 1679ed98953SRafael J. Wysocki * devices_kset list by moving the consumer device and all devices depending 1689ed98953SRafael J. Wysocki * on it to the ends of these lists (that does not happen to devices that have 1699ed98953SRafael J. Wysocki * not been registered when this function is called). 1709ed98953SRafael J. Wysocki * 1719ed98953SRafael J. Wysocki * The supplier device is required to be registered when this function is called 1729ed98953SRafael J. Wysocki * and NULL will be returned if that is not the case. The consumer device need 17364df1148SLukas Wunner * not be registered, however. 1749ed98953SRafael J. Wysocki */ 1759ed98953SRafael J. Wysocki struct device_link *device_link_add(struct device *consumer, 1769ed98953SRafael J. Wysocki struct device *supplier, u32 flags) 1779ed98953SRafael J. Wysocki { 1789ed98953SRafael J. Wysocki struct device_link *link; 1799ed98953SRafael J. Wysocki 1809ed98953SRafael J. Wysocki if (!consumer || !supplier || 1819ed98953SRafael J. Wysocki ((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_AUTOREMOVE))) 1829ed98953SRafael J. Wysocki return NULL; 1839ed98953SRafael J. Wysocki 1849ed98953SRafael J. Wysocki device_links_write_lock(); 1859ed98953SRafael J. Wysocki device_pm_lock(); 1869ed98953SRafael J. Wysocki 1879ed98953SRafael J. Wysocki /* 1889ed98953SRafael J. Wysocki * If the supplier has not been fully registered yet or there is a 1899ed98953SRafael J. Wysocki * reverse dependency between the consumer and the supplier already in 1909ed98953SRafael J. Wysocki * the graph, return NULL. 1919ed98953SRafael J. Wysocki */ 1929ed98953SRafael J. Wysocki if (!device_pm_initialized(supplier) 1939ed98953SRafael J. Wysocki || device_is_dependent(consumer, supplier)) { 1949ed98953SRafael J. Wysocki link = NULL; 1959ed98953SRafael J. Wysocki goto out; 1969ed98953SRafael J. Wysocki } 1979ed98953SRafael J. Wysocki 1989ed98953SRafael J. Wysocki list_for_each_entry(link, &supplier->links.consumers, s_node) 199ead18c23SLukas Wunner if (link->consumer == consumer) { 200ead18c23SLukas Wunner kref_get(&link->kref); 2019ed98953SRafael J. Wysocki goto out; 202ead18c23SLukas Wunner } 2039ed98953SRafael J. Wysocki 20421d5c57bSRafael J. Wysocki link = kzalloc(sizeof(*link), GFP_KERNEL); 2059ed98953SRafael J. Wysocki if (!link) 2069ed98953SRafael J. Wysocki goto out; 2079ed98953SRafael J. Wysocki 208baa8809fSRafael J. Wysocki if (flags & DL_FLAG_PM_RUNTIME) { 209baa8809fSRafael J. Wysocki if (flags & DL_FLAG_RPM_ACTIVE) { 21021d5c57bSRafael J. Wysocki if (pm_runtime_get_sync(supplier) < 0) { 21121d5c57bSRafael J. Wysocki pm_runtime_put_noidle(supplier); 21221d5c57bSRafael J. Wysocki kfree(link); 21321d5c57bSRafael J. Wysocki link = NULL; 21421d5c57bSRafael J. Wysocki goto out; 21521d5c57bSRafael J. Wysocki } 21621d5c57bSRafael J. Wysocki link->rpm_active = true; 21721d5c57bSRafael J. Wysocki } 218baa8809fSRafael J. Wysocki pm_runtime_new_link(consumer); 219baa8809fSRafael J. Wysocki } 2209ed98953SRafael J. Wysocki get_device(supplier); 2219ed98953SRafael J. Wysocki link->supplier = supplier; 2229ed98953SRafael J. Wysocki INIT_LIST_HEAD(&link->s_node); 2239ed98953SRafael J. Wysocki get_device(consumer); 2249ed98953SRafael J. Wysocki link->consumer = consumer; 2259ed98953SRafael J. Wysocki INIT_LIST_HEAD(&link->c_node); 2269ed98953SRafael J. Wysocki link->flags = flags; 227ead18c23SLukas Wunner kref_init(&link->kref); 2289ed98953SRafael J. Wysocki 22964df1148SLukas Wunner /* Determine the initial link state. */ 2309ed98953SRafael J. Wysocki if (flags & DL_FLAG_STATELESS) { 2319ed98953SRafael J. Wysocki link->status = DL_STATE_NONE; 2329ed98953SRafael J. Wysocki } else { 2339ed98953SRafael J. Wysocki switch (supplier->links.status) { 2349ed98953SRafael J. Wysocki case DL_DEV_DRIVER_BOUND: 2359ed98953SRafael J. Wysocki switch (consumer->links.status) { 2369ed98953SRafael J. Wysocki case DL_DEV_PROBING: 23721d5c57bSRafael J. Wysocki /* 23821d5c57bSRafael J. Wysocki * Balance the decrementation of the supplier's 23921d5c57bSRafael J. Wysocki * runtime PM usage counter after consumer probe 24021d5c57bSRafael J. Wysocki * in driver_probe_device(). 24121d5c57bSRafael J. Wysocki */ 24221d5c57bSRafael J. Wysocki if (flags & DL_FLAG_PM_RUNTIME) 24321d5c57bSRafael J. Wysocki pm_runtime_get_sync(supplier); 24421d5c57bSRafael J. Wysocki 2459ed98953SRafael J. Wysocki link->status = DL_STATE_CONSUMER_PROBE; 2469ed98953SRafael J. Wysocki break; 2479ed98953SRafael J. Wysocki case DL_DEV_DRIVER_BOUND: 2489ed98953SRafael J. Wysocki link->status = DL_STATE_ACTIVE; 2499ed98953SRafael J. Wysocki break; 2509ed98953SRafael J. Wysocki default: 2519ed98953SRafael J. Wysocki link->status = DL_STATE_AVAILABLE; 2529ed98953SRafael J. Wysocki break; 2539ed98953SRafael J. Wysocki } 2549ed98953SRafael J. Wysocki break; 2559ed98953SRafael J. Wysocki case DL_DEV_UNBINDING: 2569ed98953SRafael J. Wysocki link->status = DL_STATE_SUPPLIER_UNBIND; 2579ed98953SRafael J. Wysocki break; 2589ed98953SRafael J. Wysocki default: 2599ed98953SRafael J. Wysocki link->status = DL_STATE_DORMANT; 2609ed98953SRafael J. Wysocki break; 2619ed98953SRafael J. Wysocki } 2629ed98953SRafael J. Wysocki } 2639ed98953SRafael J. Wysocki 2649ed98953SRafael J. Wysocki /* 2659ed98953SRafael J. Wysocki * Move the consumer and all of the devices depending on it to the end 2669ed98953SRafael J. Wysocki * of dpm_list and the devices_kset list. 2679ed98953SRafael J. Wysocki * 2689ed98953SRafael J. Wysocki * It is necessary to hold dpm_list locked throughout all that or else 2699ed98953SRafael J. Wysocki * we may end up suspending with a wrong ordering of it. 2709ed98953SRafael J. Wysocki */ 2719ed98953SRafael J. Wysocki device_reorder_to_tail(consumer, NULL); 2729ed98953SRafael J. Wysocki 2739ed98953SRafael J. Wysocki list_add_tail_rcu(&link->s_node, &supplier->links.consumers); 2749ed98953SRafael J. Wysocki list_add_tail_rcu(&link->c_node, &consumer->links.suppliers); 2759ed98953SRafael J. Wysocki 2769ed98953SRafael J. Wysocki dev_info(consumer, "Linked as a consumer to %s\n", dev_name(supplier)); 2779ed98953SRafael J. Wysocki 2789ed98953SRafael J. Wysocki out: 2799ed98953SRafael J. Wysocki device_pm_unlock(); 2809ed98953SRafael J. Wysocki device_links_write_unlock(); 2819ed98953SRafael J. Wysocki return link; 2829ed98953SRafael J. Wysocki } 2839ed98953SRafael J. Wysocki EXPORT_SYMBOL_GPL(device_link_add); 2849ed98953SRafael J. Wysocki 2859ed98953SRafael J. Wysocki static void device_link_free(struct device_link *link) 2869ed98953SRafael J. Wysocki { 2879ed98953SRafael J. Wysocki put_device(link->consumer); 2889ed98953SRafael J. Wysocki put_device(link->supplier); 2899ed98953SRafael J. Wysocki kfree(link); 2909ed98953SRafael J. Wysocki } 2919ed98953SRafael J. Wysocki 2929ed98953SRafael J. Wysocki #ifdef CONFIG_SRCU 2939ed98953SRafael J. Wysocki static void __device_link_free_srcu(struct rcu_head *rhead) 2949ed98953SRafael J. Wysocki { 2959ed98953SRafael J. Wysocki device_link_free(container_of(rhead, struct device_link, rcu_head)); 2969ed98953SRafael J. Wysocki } 2979ed98953SRafael J. Wysocki 298ead18c23SLukas Wunner static void __device_link_del(struct kref *kref) 2999ed98953SRafael J. Wysocki { 300ead18c23SLukas Wunner struct device_link *link = container_of(kref, struct device_link, kref); 301ead18c23SLukas Wunner 3029ed98953SRafael J. Wysocki dev_info(link->consumer, "Dropping the link to %s\n", 3039ed98953SRafael J. Wysocki dev_name(link->supplier)); 3049ed98953SRafael J. Wysocki 305baa8809fSRafael J. Wysocki if (link->flags & DL_FLAG_PM_RUNTIME) 306baa8809fSRafael J. Wysocki pm_runtime_drop_link(link->consumer); 307baa8809fSRafael J. Wysocki 3089ed98953SRafael J. Wysocki list_del_rcu(&link->s_node); 3099ed98953SRafael J. Wysocki list_del_rcu(&link->c_node); 3109ed98953SRafael J. Wysocki call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu); 3119ed98953SRafael J. Wysocki } 3129ed98953SRafael J. Wysocki #else /* !CONFIG_SRCU */ 313ead18c23SLukas Wunner static void __device_link_del(struct kref *kref) 3149ed98953SRafael J. Wysocki { 315ead18c23SLukas Wunner struct device_link *link = container_of(kref, struct device_link, kref); 316ead18c23SLukas Wunner 3179ed98953SRafael J. Wysocki dev_info(link->consumer, "Dropping the link to %s\n", 3189ed98953SRafael J. Wysocki dev_name(link->supplier)); 3199ed98953SRafael J. Wysocki 320433986c2SLukas Wunner if (link->flags & DL_FLAG_PM_RUNTIME) 321433986c2SLukas Wunner pm_runtime_drop_link(link->consumer); 322433986c2SLukas Wunner 3239ed98953SRafael J. Wysocki list_del(&link->s_node); 3249ed98953SRafael J. Wysocki list_del(&link->c_node); 3259ed98953SRafael J. Wysocki device_link_free(link); 3269ed98953SRafael J. Wysocki } 3279ed98953SRafael J. Wysocki #endif /* !CONFIG_SRCU */ 3289ed98953SRafael J. Wysocki 3299ed98953SRafael J. Wysocki /** 3309ed98953SRafael J. Wysocki * device_link_del - Delete a link between two devices. 3319ed98953SRafael J. Wysocki * @link: Device link to delete. 3329ed98953SRafael J. Wysocki * 3339ed98953SRafael J. Wysocki * The caller must ensure proper synchronization of this function with runtime 334ead18c23SLukas Wunner * PM. If the link was added multiple times, it needs to be deleted as often. 335ead18c23SLukas Wunner * Care is required for hotplugged devices: Their links are purged on removal 336ead18c23SLukas Wunner * and calling device_link_del() is then no longer allowed. 3379ed98953SRafael J. Wysocki */ 3389ed98953SRafael J. Wysocki void device_link_del(struct device_link *link) 3399ed98953SRafael J. Wysocki { 3409ed98953SRafael J. Wysocki device_links_write_lock(); 3419ed98953SRafael J. Wysocki device_pm_lock(); 342ead18c23SLukas Wunner kref_put(&link->kref, __device_link_del); 3439ed98953SRafael J. Wysocki device_pm_unlock(); 3449ed98953SRafael J. Wysocki device_links_write_unlock(); 3459ed98953SRafael J. Wysocki } 3469ed98953SRafael J. Wysocki EXPORT_SYMBOL_GPL(device_link_del); 3479ed98953SRafael J. Wysocki 3489ed98953SRafael J. Wysocki static void device_links_missing_supplier(struct device *dev) 3499ed98953SRafael J. Wysocki { 3509ed98953SRafael J. Wysocki struct device_link *link; 3519ed98953SRafael J. Wysocki 3529ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.suppliers, c_node) 3539ed98953SRafael J. Wysocki if (link->status == DL_STATE_CONSUMER_PROBE) 3549ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_AVAILABLE); 3559ed98953SRafael J. Wysocki } 3569ed98953SRafael J. Wysocki 3579ed98953SRafael J. Wysocki /** 3589ed98953SRafael J. Wysocki * device_links_check_suppliers - Check presence of supplier drivers. 3599ed98953SRafael J. Wysocki * @dev: Consumer device. 3609ed98953SRafael J. Wysocki * 3619ed98953SRafael J. Wysocki * Check links from this device to any suppliers. Walk the list of the device's 3629ed98953SRafael J. Wysocki * links to suppliers and see if all of them are available. If not, simply 3639ed98953SRafael J. Wysocki * return -EPROBE_DEFER. 3649ed98953SRafael J. Wysocki * 3659ed98953SRafael J. Wysocki * We need to guarantee that the supplier will not go away after the check has 3669ed98953SRafael J. Wysocki * been positive here. It only can go away in __device_release_driver() and 3679ed98953SRafael J. Wysocki * that function checks the device's links to consumers. This means we need to 3689ed98953SRafael J. Wysocki * mark the link as "consumer probe in progress" to make the supplier removal 3699ed98953SRafael J. Wysocki * wait for us to complete (or bad things may happen). 3709ed98953SRafael J. Wysocki * 3719ed98953SRafael J. Wysocki * Links with the DL_FLAG_STATELESS flag set are ignored. 3729ed98953SRafael J. Wysocki */ 3739ed98953SRafael J. Wysocki int device_links_check_suppliers(struct device *dev) 3749ed98953SRafael J. Wysocki { 3759ed98953SRafael J. Wysocki struct device_link *link; 3769ed98953SRafael J. Wysocki int ret = 0; 3779ed98953SRafael J. Wysocki 3789ed98953SRafael J. Wysocki device_links_write_lock(); 3799ed98953SRafael J. Wysocki 3809ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.suppliers, c_node) { 3819ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_STATELESS) 3829ed98953SRafael J. Wysocki continue; 3839ed98953SRafael J. Wysocki 3849ed98953SRafael J. Wysocki if (link->status != DL_STATE_AVAILABLE) { 3859ed98953SRafael J. Wysocki device_links_missing_supplier(dev); 3869ed98953SRafael J. Wysocki ret = -EPROBE_DEFER; 3879ed98953SRafael J. Wysocki break; 3889ed98953SRafael J. Wysocki } 3899ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE); 3909ed98953SRafael J. Wysocki } 3919ed98953SRafael J. Wysocki dev->links.status = DL_DEV_PROBING; 3929ed98953SRafael J. Wysocki 3939ed98953SRafael J. Wysocki device_links_write_unlock(); 3949ed98953SRafael J. Wysocki return ret; 3959ed98953SRafael J. Wysocki } 3969ed98953SRafael J. Wysocki 3979ed98953SRafael J. Wysocki /** 3989ed98953SRafael J. Wysocki * device_links_driver_bound - Update device links after probing its driver. 3999ed98953SRafael J. Wysocki * @dev: Device to update the links for. 4009ed98953SRafael J. Wysocki * 4019ed98953SRafael J. Wysocki * The probe has been successful, so update links from this device to any 4029ed98953SRafael J. Wysocki * consumers by changing their status to "available". 4039ed98953SRafael J. Wysocki * 4049ed98953SRafael J. Wysocki * Also change the status of @dev's links to suppliers to "active". 4059ed98953SRafael J. Wysocki * 4069ed98953SRafael J. Wysocki * Links with the DL_FLAG_STATELESS flag set are ignored. 4079ed98953SRafael J. Wysocki */ 4089ed98953SRafael J. Wysocki void device_links_driver_bound(struct device *dev) 4099ed98953SRafael J. Wysocki { 4109ed98953SRafael J. Wysocki struct device_link *link; 4119ed98953SRafael J. Wysocki 4129ed98953SRafael J. Wysocki device_links_write_lock(); 4139ed98953SRafael J. Wysocki 4149ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.consumers, s_node) { 4159ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_STATELESS) 4169ed98953SRafael J. Wysocki continue; 4179ed98953SRafael J. Wysocki 4189ed98953SRafael J. Wysocki WARN_ON(link->status != DL_STATE_DORMANT); 4199ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_AVAILABLE); 4209ed98953SRafael J. Wysocki } 4219ed98953SRafael J. Wysocki 4229ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.suppliers, c_node) { 4239ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_STATELESS) 4249ed98953SRafael J. Wysocki continue; 4259ed98953SRafael J. Wysocki 4269ed98953SRafael J. Wysocki WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); 4279ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_ACTIVE); 4289ed98953SRafael J. Wysocki } 4299ed98953SRafael J. Wysocki 4309ed98953SRafael J. Wysocki dev->links.status = DL_DEV_DRIVER_BOUND; 4319ed98953SRafael J. Wysocki 4329ed98953SRafael J. Wysocki device_links_write_unlock(); 4339ed98953SRafael J. Wysocki } 4349ed98953SRafael J. Wysocki 4359ed98953SRafael J. Wysocki /** 4369ed98953SRafael J. Wysocki * __device_links_no_driver - Update links of a device without a driver. 4379ed98953SRafael J. Wysocki * @dev: Device without a drvier. 4389ed98953SRafael J. Wysocki * 4399ed98953SRafael J. Wysocki * Delete all non-persistent links from this device to any suppliers. 4409ed98953SRafael J. Wysocki * 4419ed98953SRafael J. Wysocki * Persistent links stay around, but their status is changed to "available", 4429ed98953SRafael J. Wysocki * unless they already are in the "supplier unbind in progress" state in which 4439ed98953SRafael J. Wysocki * case they need not be updated. 4449ed98953SRafael J. Wysocki * 4459ed98953SRafael J. Wysocki * Links with the DL_FLAG_STATELESS flag set are ignored. 4469ed98953SRafael J. Wysocki */ 4479ed98953SRafael J. Wysocki static void __device_links_no_driver(struct device *dev) 4489ed98953SRafael J. Wysocki { 4499ed98953SRafael J. Wysocki struct device_link *link, *ln; 4509ed98953SRafael J. Wysocki 4519ed98953SRafael J. Wysocki list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { 4529ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_STATELESS) 4539ed98953SRafael J. Wysocki continue; 4549ed98953SRafael J. Wysocki 4559ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_AUTOREMOVE) 456ead18c23SLukas Wunner kref_put(&link->kref, __device_link_del); 4579ed98953SRafael J. Wysocki else if (link->status != DL_STATE_SUPPLIER_UNBIND) 4589ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_AVAILABLE); 4599ed98953SRafael J. Wysocki } 4609ed98953SRafael J. Wysocki 4619ed98953SRafael J. Wysocki dev->links.status = DL_DEV_NO_DRIVER; 4629ed98953SRafael J. Wysocki } 4639ed98953SRafael J. Wysocki 4649ed98953SRafael J. Wysocki void device_links_no_driver(struct device *dev) 4659ed98953SRafael J. Wysocki { 4669ed98953SRafael J. Wysocki device_links_write_lock(); 4679ed98953SRafael J. Wysocki __device_links_no_driver(dev); 4689ed98953SRafael J. Wysocki device_links_write_unlock(); 4699ed98953SRafael J. Wysocki } 4709ed98953SRafael J. Wysocki 4719ed98953SRafael J. Wysocki /** 4729ed98953SRafael J. Wysocki * device_links_driver_cleanup - Update links after driver removal. 4739ed98953SRafael J. Wysocki * @dev: Device whose driver has just gone away. 4749ed98953SRafael J. Wysocki * 4759ed98953SRafael J. Wysocki * Update links to consumers for @dev by changing their status to "dormant" and 4769ed98953SRafael J. Wysocki * invoke %__device_links_no_driver() to update links to suppliers for it as 4779ed98953SRafael J. Wysocki * appropriate. 4789ed98953SRafael J. Wysocki * 4799ed98953SRafael J. Wysocki * Links with the DL_FLAG_STATELESS flag set are ignored. 4809ed98953SRafael J. Wysocki */ 4819ed98953SRafael J. Wysocki void device_links_driver_cleanup(struct device *dev) 4829ed98953SRafael J. Wysocki { 4839ed98953SRafael J. Wysocki struct device_link *link; 4849ed98953SRafael J. Wysocki 4859ed98953SRafael J. Wysocki device_links_write_lock(); 4869ed98953SRafael J. Wysocki 4879ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.consumers, s_node) { 4889ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_STATELESS) 4899ed98953SRafael J. Wysocki continue; 4909ed98953SRafael J. Wysocki 4919ed98953SRafael J. Wysocki WARN_ON(link->flags & DL_FLAG_AUTOREMOVE); 4929ed98953SRafael J. Wysocki WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); 4939ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_DORMANT); 4949ed98953SRafael J. Wysocki } 4959ed98953SRafael J. Wysocki 4969ed98953SRafael J. Wysocki __device_links_no_driver(dev); 4979ed98953SRafael J. Wysocki 4989ed98953SRafael J. Wysocki device_links_write_unlock(); 4999ed98953SRafael J. Wysocki } 5009ed98953SRafael J. Wysocki 5019ed98953SRafael J. Wysocki /** 5029ed98953SRafael J. Wysocki * device_links_busy - Check if there are any busy links to consumers. 5039ed98953SRafael J. Wysocki * @dev: Device to check. 5049ed98953SRafael J. Wysocki * 5059ed98953SRafael J. Wysocki * Check each consumer of the device and return 'true' if its link's status 5069ed98953SRafael J. Wysocki * is one of "consumer probe" or "active" (meaning that the given consumer is 5079ed98953SRafael J. Wysocki * probing right now or its driver is present). Otherwise, change the link 5089ed98953SRafael J. Wysocki * state to "supplier unbind" to prevent the consumer from being probed 5099ed98953SRafael J. Wysocki * successfully going forward. 5109ed98953SRafael J. Wysocki * 5119ed98953SRafael J. Wysocki * Return 'false' if there are no probing or active consumers. 5129ed98953SRafael J. Wysocki * 5139ed98953SRafael J. Wysocki * Links with the DL_FLAG_STATELESS flag set are ignored. 5149ed98953SRafael J. Wysocki */ 5159ed98953SRafael J. Wysocki bool device_links_busy(struct device *dev) 5169ed98953SRafael J. Wysocki { 5179ed98953SRafael J. Wysocki struct device_link *link; 5189ed98953SRafael J. Wysocki bool ret = false; 5199ed98953SRafael J. Wysocki 5209ed98953SRafael J. Wysocki device_links_write_lock(); 5219ed98953SRafael J. Wysocki 5229ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.consumers, s_node) { 5239ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_STATELESS) 5249ed98953SRafael J. Wysocki continue; 5259ed98953SRafael J. Wysocki 5269ed98953SRafael J. Wysocki if (link->status == DL_STATE_CONSUMER_PROBE 5279ed98953SRafael J. Wysocki || link->status == DL_STATE_ACTIVE) { 5289ed98953SRafael J. Wysocki ret = true; 5299ed98953SRafael J. Wysocki break; 5309ed98953SRafael J. Wysocki } 5319ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND); 5329ed98953SRafael J. Wysocki } 5339ed98953SRafael J. Wysocki 5349ed98953SRafael J. Wysocki dev->links.status = DL_DEV_UNBINDING; 5359ed98953SRafael J. Wysocki 5369ed98953SRafael J. Wysocki device_links_write_unlock(); 5379ed98953SRafael J. Wysocki return ret; 5389ed98953SRafael J. Wysocki } 5399ed98953SRafael J. Wysocki 5409ed98953SRafael J. Wysocki /** 5419ed98953SRafael J. Wysocki * device_links_unbind_consumers - Force unbind consumers of the given device. 5429ed98953SRafael J. Wysocki * @dev: Device to unbind the consumers of. 5439ed98953SRafael J. Wysocki * 5449ed98953SRafael J. Wysocki * Walk the list of links to consumers for @dev and if any of them is in the 5459ed98953SRafael J. Wysocki * "consumer probe" state, wait for all device probes in progress to complete 5469ed98953SRafael J. Wysocki * and start over. 5479ed98953SRafael J. Wysocki * 5489ed98953SRafael J. Wysocki * If that's not the case, change the status of the link to "supplier unbind" 5499ed98953SRafael J. Wysocki * and check if the link was in the "active" state. If so, force the consumer 5509ed98953SRafael J. Wysocki * driver to unbind and start over (the consumer will not re-probe as we have 5519ed98953SRafael J. Wysocki * changed the state of the link already). 5529ed98953SRafael J. Wysocki * 5539ed98953SRafael J. Wysocki * Links with the DL_FLAG_STATELESS flag set are ignored. 5549ed98953SRafael J. Wysocki */ 5559ed98953SRafael J. Wysocki void device_links_unbind_consumers(struct device *dev) 5569ed98953SRafael J. Wysocki { 5579ed98953SRafael J. Wysocki struct device_link *link; 5589ed98953SRafael J. Wysocki 5599ed98953SRafael J. Wysocki start: 5609ed98953SRafael J. Wysocki device_links_write_lock(); 5619ed98953SRafael J. Wysocki 5629ed98953SRafael J. Wysocki list_for_each_entry(link, &dev->links.consumers, s_node) { 5639ed98953SRafael J. Wysocki enum device_link_state status; 5649ed98953SRafael J. Wysocki 5659ed98953SRafael J. Wysocki if (link->flags & DL_FLAG_STATELESS) 5669ed98953SRafael J. Wysocki continue; 5679ed98953SRafael J. Wysocki 5689ed98953SRafael J. Wysocki status = link->status; 5699ed98953SRafael J. Wysocki if (status == DL_STATE_CONSUMER_PROBE) { 5709ed98953SRafael J. Wysocki device_links_write_unlock(); 5719ed98953SRafael J. Wysocki 5729ed98953SRafael J. Wysocki wait_for_device_probe(); 5739ed98953SRafael J. Wysocki goto start; 5749ed98953SRafael J. Wysocki } 5759ed98953SRafael J. Wysocki WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND); 5769ed98953SRafael J. Wysocki if (status == DL_STATE_ACTIVE) { 5779ed98953SRafael J. Wysocki struct device *consumer = link->consumer; 5789ed98953SRafael J. Wysocki 5799ed98953SRafael J. Wysocki get_device(consumer); 5809ed98953SRafael J. Wysocki 5819ed98953SRafael J. Wysocki device_links_write_unlock(); 5829ed98953SRafael J. Wysocki 5839ed98953SRafael J. Wysocki device_release_driver_internal(consumer, NULL, 5849ed98953SRafael J. Wysocki consumer->parent); 5859ed98953SRafael J. Wysocki put_device(consumer); 5869ed98953SRafael J. Wysocki goto start; 5879ed98953SRafael J. Wysocki } 5889ed98953SRafael J. Wysocki } 5899ed98953SRafael J. Wysocki 5909ed98953SRafael J. Wysocki device_links_write_unlock(); 5919ed98953SRafael J. Wysocki } 5929ed98953SRafael J. Wysocki 5939ed98953SRafael J. Wysocki /** 5949ed98953SRafael J. Wysocki * device_links_purge - Delete existing links to other devices. 5959ed98953SRafael J. Wysocki * @dev: Target device. 5969ed98953SRafael J. Wysocki */ 5979ed98953SRafael J. Wysocki static void device_links_purge(struct device *dev) 5989ed98953SRafael J. Wysocki { 5999ed98953SRafael J. Wysocki struct device_link *link, *ln; 6009ed98953SRafael J. Wysocki 6019ed98953SRafael J. Wysocki /* 6029ed98953SRafael J. Wysocki * Delete all of the remaining links from this device to any other 6039ed98953SRafael J. Wysocki * devices (either consumers or suppliers). 6049ed98953SRafael J. Wysocki */ 6059ed98953SRafael J. Wysocki device_links_write_lock(); 6069ed98953SRafael J. Wysocki 6079ed98953SRafael J. Wysocki list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { 6089ed98953SRafael J. Wysocki WARN_ON(link->status == DL_STATE_ACTIVE); 609ead18c23SLukas Wunner __device_link_del(&link->kref); 6109ed98953SRafael J. Wysocki } 6119ed98953SRafael J. Wysocki 6129ed98953SRafael J. Wysocki list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) { 6139ed98953SRafael J. Wysocki WARN_ON(link->status != DL_STATE_DORMANT && 6149ed98953SRafael J. Wysocki link->status != DL_STATE_NONE); 615ead18c23SLukas Wunner __device_link_del(&link->kref); 6169ed98953SRafael J. Wysocki } 6179ed98953SRafael J. Wysocki 6189ed98953SRafael J. Wysocki device_links_write_unlock(); 6199ed98953SRafael J. Wysocki } 6209ed98953SRafael J. Wysocki 6219ed98953SRafael J. Wysocki /* Device links support end. */ 6229ed98953SRafael J. Wysocki 6231da177e4SLinus Torvalds int (*platform_notify)(struct device *dev) = NULL; 6241da177e4SLinus Torvalds int (*platform_notify_remove)(struct device *dev) = NULL; 625e105b8bfSDan Williams static struct kobject *dev_kobj; 626e105b8bfSDan Williams struct kobject *sysfs_dev_char_kobj; 627e105b8bfSDan Williams struct kobject *sysfs_dev_block_kobj; 6281da177e4SLinus Torvalds 6295e33bc41SRafael J. Wysocki static DEFINE_MUTEX(device_hotplug_lock); 6305e33bc41SRafael J. Wysocki 6315e33bc41SRafael J. Wysocki void lock_device_hotplug(void) 6325e33bc41SRafael J. Wysocki { 6335e33bc41SRafael J. Wysocki mutex_lock(&device_hotplug_lock); 6345e33bc41SRafael J. Wysocki } 6355e33bc41SRafael J. Wysocki 6365e33bc41SRafael J. Wysocki void unlock_device_hotplug(void) 6375e33bc41SRafael J. Wysocki { 6385e33bc41SRafael J. Wysocki mutex_unlock(&device_hotplug_lock); 6395e33bc41SRafael J. Wysocki } 6405e33bc41SRafael J. Wysocki 6415e33bc41SRafael J. Wysocki int lock_device_hotplug_sysfs(void) 6425e33bc41SRafael J. Wysocki { 6435e33bc41SRafael J. Wysocki if (mutex_trylock(&device_hotplug_lock)) 6445e33bc41SRafael J. Wysocki return 0; 6455e33bc41SRafael J. Wysocki 6465e33bc41SRafael J. Wysocki /* Avoid busy looping (5 ms of sleep should do). */ 6475e33bc41SRafael J. Wysocki msleep(5); 6485e33bc41SRafael J. Wysocki return restart_syscall(); 6495e33bc41SRafael J. Wysocki } 6505e33bc41SRafael J. Wysocki 6514e886c29SGreg Kroah-Hartman #ifdef CONFIG_BLOCK 6524e886c29SGreg Kroah-Hartman static inline int device_is_not_partition(struct device *dev) 6534e886c29SGreg Kroah-Hartman { 6544e886c29SGreg Kroah-Hartman return !(dev->type == &part_type); 6554e886c29SGreg Kroah-Hartman } 6564e886c29SGreg Kroah-Hartman #else 6574e886c29SGreg Kroah-Hartman static inline int device_is_not_partition(struct device *dev) 6584e886c29SGreg Kroah-Hartman { 6594e886c29SGreg Kroah-Hartman return 1; 6604e886c29SGreg Kroah-Hartman } 6614e886c29SGreg Kroah-Hartman #endif 6621da177e4SLinus Torvalds 6633e95637aSAlan Stern /** 6643e95637aSAlan Stern * dev_driver_string - Return a device's driver name, if at all possible 6653e95637aSAlan Stern * @dev: struct device to get the name of 6663e95637aSAlan Stern * 6673e95637aSAlan Stern * Will return the device's driver's name if it is bound to a device. If 6689169c012Syan * the device is not bound to a driver, it will return the name of the bus 6693e95637aSAlan Stern * it is attached to. If it is not attached to a bus either, an empty 6703e95637aSAlan Stern * string will be returned. 6713e95637aSAlan Stern */ 672bf9ca69fSJean Delvare const char *dev_driver_string(const struct device *dev) 6733e95637aSAlan Stern { 6743589972eSAlan Stern struct device_driver *drv; 6753589972eSAlan Stern 6763589972eSAlan Stern /* dev->driver can change to NULL underneath us because of unbinding, 6773589972eSAlan Stern * so be careful about accessing it. dev->bus and dev->class should 6783589972eSAlan Stern * never change once they are set, so they don't need special care. 6793589972eSAlan Stern */ 6806aa7de05SMark Rutland drv = READ_ONCE(dev->driver); 6813589972eSAlan Stern return drv ? drv->name : 682a456b702SJean Delvare (dev->bus ? dev->bus->name : 683a456b702SJean Delvare (dev->class ? dev->class->name : "")); 6843e95637aSAlan Stern } 685310a922dSMatthew Wilcox EXPORT_SYMBOL(dev_driver_string); 6863e95637aSAlan Stern 6871da177e4SLinus Torvalds #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) 6881da177e4SLinus Torvalds 6894a3ad20cSGreg Kroah-Hartman static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, 6904a3ad20cSGreg Kroah-Hartman char *buf) 6911da177e4SLinus Torvalds { 6921da177e4SLinus Torvalds struct device_attribute *dev_attr = to_dev_attr(attr); 693b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 6944a0c20bfSDmitry Torokhov ssize_t ret = -EIO; 6951da177e4SLinus Torvalds 6961da177e4SLinus Torvalds if (dev_attr->show) 69754b6f35cSYani Ioannou ret = dev_attr->show(dev, dev_attr, buf); 698815d2d50SAndrew Morton if (ret >= (ssize_t)PAGE_SIZE) { 699a52668c6SSergey Senozhatsky printk("dev_attr_show: %pS returned bad count\n", 700a52668c6SSergey Senozhatsky dev_attr->show); 701815d2d50SAndrew Morton } 7021da177e4SLinus Torvalds return ret; 7031da177e4SLinus Torvalds } 7041da177e4SLinus Torvalds 7054a3ad20cSGreg Kroah-Hartman static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, 7061da177e4SLinus Torvalds const char *buf, size_t count) 7071da177e4SLinus Torvalds { 7081da177e4SLinus Torvalds struct device_attribute *dev_attr = to_dev_attr(attr); 709b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 7104a0c20bfSDmitry Torokhov ssize_t ret = -EIO; 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds if (dev_attr->store) 71354b6f35cSYani Ioannou ret = dev_attr->store(dev, dev_attr, buf, count); 7141da177e4SLinus Torvalds return ret; 7151da177e4SLinus Torvalds } 7161da177e4SLinus Torvalds 71752cf25d0SEmese Revfy static const struct sysfs_ops dev_sysfs_ops = { 7181da177e4SLinus Torvalds .show = dev_attr_show, 7191da177e4SLinus Torvalds .store = dev_attr_store, 7201da177e4SLinus Torvalds }; 7211da177e4SLinus Torvalds 722ca22e56dSKay Sievers #define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr) 723ca22e56dSKay Sievers 724ca22e56dSKay Sievers ssize_t device_store_ulong(struct device *dev, 725ca22e56dSKay Sievers struct device_attribute *attr, 726ca22e56dSKay Sievers const char *buf, size_t size) 727ca22e56dSKay Sievers { 728ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 729ca22e56dSKay Sievers char *end; 730ca22e56dSKay Sievers unsigned long new = simple_strtoul(buf, &end, 0); 731ca22e56dSKay Sievers if (end == buf) 732ca22e56dSKay Sievers return -EINVAL; 733ca22e56dSKay Sievers *(unsigned long *)(ea->var) = new; 734ca22e56dSKay Sievers /* Always return full write size even if we didn't consume all */ 735ca22e56dSKay Sievers return size; 736ca22e56dSKay Sievers } 737ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_store_ulong); 738ca22e56dSKay Sievers 739ca22e56dSKay Sievers ssize_t device_show_ulong(struct device *dev, 740ca22e56dSKay Sievers struct device_attribute *attr, 741ca22e56dSKay Sievers char *buf) 742ca22e56dSKay Sievers { 743ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 744ca22e56dSKay Sievers return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); 745ca22e56dSKay Sievers } 746ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_show_ulong); 747ca22e56dSKay Sievers 748ca22e56dSKay Sievers ssize_t device_store_int(struct device *dev, 749ca22e56dSKay Sievers struct device_attribute *attr, 750ca22e56dSKay Sievers const char *buf, size_t size) 751ca22e56dSKay Sievers { 752ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 753ca22e56dSKay Sievers char *end; 754ca22e56dSKay Sievers long new = simple_strtol(buf, &end, 0); 755ca22e56dSKay Sievers if (end == buf || new > INT_MAX || new < INT_MIN) 756ca22e56dSKay Sievers return -EINVAL; 757ca22e56dSKay Sievers *(int *)(ea->var) = new; 758ca22e56dSKay Sievers /* Always return full write size even if we didn't consume all */ 759ca22e56dSKay Sievers return size; 760ca22e56dSKay Sievers } 761ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_store_int); 762ca22e56dSKay Sievers 763ca22e56dSKay Sievers ssize_t device_show_int(struct device *dev, 764ca22e56dSKay Sievers struct device_attribute *attr, 765ca22e56dSKay Sievers char *buf) 766ca22e56dSKay Sievers { 767ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 768ca22e56dSKay Sievers 769ca22e56dSKay Sievers return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); 770ca22e56dSKay Sievers } 771ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_show_int); 7721da177e4SLinus Torvalds 77391872392SBorislav Petkov ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, 77491872392SBorislav Petkov const char *buf, size_t size) 77591872392SBorislav Petkov { 77691872392SBorislav Petkov struct dev_ext_attribute *ea = to_ext_attr(attr); 77791872392SBorislav Petkov 77891872392SBorislav Petkov if (strtobool(buf, ea->var) < 0) 77991872392SBorislav Petkov return -EINVAL; 78091872392SBorislav Petkov 78191872392SBorislav Petkov return size; 78291872392SBorislav Petkov } 78391872392SBorislav Petkov EXPORT_SYMBOL_GPL(device_store_bool); 78491872392SBorislav Petkov 78591872392SBorislav Petkov ssize_t device_show_bool(struct device *dev, struct device_attribute *attr, 78691872392SBorislav Petkov char *buf) 78791872392SBorislav Petkov { 78891872392SBorislav Petkov struct dev_ext_attribute *ea = to_ext_attr(attr); 78991872392SBorislav Petkov 79091872392SBorislav Petkov return snprintf(buf, PAGE_SIZE, "%d\n", *(bool *)(ea->var)); 79191872392SBorislav Petkov } 79291872392SBorislav Petkov EXPORT_SYMBOL_GPL(device_show_bool); 79391872392SBorislav Petkov 7941da177e4SLinus Torvalds /** 7951da177e4SLinus Torvalds * device_release - free device structure. 7961da177e4SLinus Torvalds * @kobj: device's kobject. 7971da177e4SLinus Torvalds * 7981da177e4SLinus Torvalds * This is called once the reference count for the object 7991da177e4SLinus Torvalds * reaches 0. We forward the call to the device's release 8001da177e4SLinus Torvalds * method, which should handle actually freeing the structure. 8011da177e4SLinus Torvalds */ 8021da177e4SLinus Torvalds static void device_release(struct kobject *kobj) 8031da177e4SLinus Torvalds { 804b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 805fb069a5dSGreg Kroah-Hartman struct device_private *p = dev->p; 8061da177e4SLinus Torvalds 807a525a3ddSMing Lei /* 808a525a3ddSMing Lei * Some platform devices are driven without driver attached 809a525a3ddSMing Lei * and managed resources may have been acquired. Make sure 810a525a3ddSMing Lei * all resources are released. 811a525a3ddSMing Lei * 812a525a3ddSMing Lei * Drivers still can add resources into device after device 813a525a3ddSMing Lei * is deleted but alive, so release devres here to avoid 814a525a3ddSMing Lei * possible memory leak. 815a525a3ddSMing Lei */ 816a525a3ddSMing Lei devres_release_all(dev); 817a525a3ddSMing Lei 8181da177e4SLinus Torvalds if (dev->release) 8191da177e4SLinus Torvalds dev->release(dev); 820f9f852dfSKay Sievers else if (dev->type && dev->type->release) 821f9f852dfSKay Sievers dev->type->release(dev); 8222620efefSGreg Kroah-Hartman else if (dev->class && dev->class->dev_release) 8232620efefSGreg Kroah-Hartman dev->class->dev_release(dev); 824f810a5cfSArjan van de Ven else 825f810a5cfSArjan van de Ven WARN(1, KERN_ERR "Device '%s' does not have a release() " 8264a3ad20cSGreg Kroah-Hartman "function, it is broken and must be fixed.\n", 8271e0b2cf9SKay Sievers dev_name(dev)); 828fb069a5dSGreg Kroah-Hartman kfree(p); 8291da177e4SLinus Torvalds } 8301da177e4SLinus Torvalds 831bc451f20SEric W. Biederman static const void *device_namespace(struct kobject *kobj) 832bc451f20SEric W. Biederman { 833b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 834bc451f20SEric W. Biederman const void *ns = NULL; 835bc451f20SEric W. Biederman 836bc451f20SEric W. Biederman if (dev->class && dev->class->ns_type) 837bc451f20SEric W. Biederman ns = dev->class->namespace(dev); 838bc451f20SEric W. Biederman 839bc451f20SEric W. Biederman return ns; 840bc451f20SEric W. Biederman } 841bc451f20SEric W. Biederman 8428f4afc41SGreg Kroah-Hartman static struct kobj_type device_ktype = { 8431da177e4SLinus Torvalds .release = device_release, 8441da177e4SLinus Torvalds .sysfs_ops = &dev_sysfs_ops, 845bc451f20SEric W. Biederman .namespace = device_namespace, 8461da177e4SLinus Torvalds }; 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds 849312c004dSKay Sievers static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) 8501da177e4SLinus Torvalds { 8511da177e4SLinus Torvalds struct kobj_type *ktype = get_ktype(kobj); 8521da177e4SLinus Torvalds 8538f4afc41SGreg Kroah-Hartman if (ktype == &device_ktype) { 854b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 8551da177e4SLinus Torvalds if (dev->bus) 8561da177e4SLinus Torvalds return 1; 85723681e47SGreg Kroah-Hartman if (dev->class) 85823681e47SGreg Kroah-Hartman return 1; 8591da177e4SLinus Torvalds } 8601da177e4SLinus Torvalds return 0; 8611da177e4SLinus Torvalds } 8621da177e4SLinus Torvalds 863312c004dSKay Sievers static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) 8641da177e4SLinus Torvalds { 865b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 8661da177e4SLinus Torvalds 86723681e47SGreg Kroah-Hartman if (dev->bus) 8681da177e4SLinus Torvalds return dev->bus->name; 86923681e47SGreg Kroah-Hartman if (dev->class) 87023681e47SGreg Kroah-Hartman return dev->class->name; 87123681e47SGreg Kroah-Hartman return NULL; 8721da177e4SLinus Torvalds } 8731da177e4SLinus Torvalds 8747eff2e7aSKay Sievers static int dev_uevent(struct kset *kset, struct kobject *kobj, 8757eff2e7aSKay Sievers struct kobj_uevent_env *env) 8761da177e4SLinus Torvalds { 877b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 8781da177e4SLinus Torvalds int retval = 0; 8791da177e4SLinus Torvalds 8806fcf53acSKay Sievers /* add device node properties if present */ 88123681e47SGreg Kroah-Hartman if (MAJOR(dev->devt)) { 8826fcf53acSKay Sievers const char *tmp; 8836fcf53acSKay Sievers const char *name; 8842c9ede55SAl Viro umode_t mode = 0; 8854e4098a3SGreg Kroah-Hartman kuid_t uid = GLOBAL_ROOT_UID; 8864e4098a3SGreg Kroah-Hartman kgid_t gid = GLOBAL_ROOT_GID; 8876fcf53acSKay Sievers 8887eff2e7aSKay Sievers add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); 8897eff2e7aSKay Sievers add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); 8903c2670e6SKay Sievers name = device_get_devnode(dev, &mode, &uid, &gid, &tmp); 8916fcf53acSKay Sievers if (name) { 8926fcf53acSKay Sievers add_uevent_var(env, "DEVNAME=%s", name); 893e454cea2SKay Sievers if (mode) 894e454cea2SKay Sievers add_uevent_var(env, "DEVMODE=%#o", mode & 0777); 8954e4098a3SGreg Kroah-Hartman if (!uid_eq(uid, GLOBAL_ROOT_UID)) 8964e4098a3SGreg Kroah-Hartman add_uevent_var(env, "DEVUID=%u", from_kuid(&init_user_ns, uid)); 8974e4098a3SGreg Kroah-Hartman if (!gid_eq(gid, GLOBAL_ROOT_GID)) 8984e4098a3SGreg Kroah-Hartman add_uevent_var(env, "DEVGID=%u", from_kgid(&init_user_ns, gid)); 8993c2670e6SKay Sievers kfree(tmp); 9006fcf53acSKay Sievers } 90123681e47SGreg Kroah-Hartman } 90223681e47SGreg Kroah-Hartman 903414264f9SKay Sievers if (dev->type && dev->type->name) 9047eff2e7aSKay Sievers add_uevent_var(env, "DEVTYPE=%s", dev->type->name); 905414264f9SKay Sievers 906239378f1SKay Sievers if (dev->driver) 9077eff2e7aSKay Sievers add_uevent_var(env, "DRIVER=%s", dev->driver->name); 908239378f1SKay Sievers 90907d57a32SGrant Likely /* Add common DT information about the device */ 91007d57a32SGrant Likely of_device_uevent(dev, env); 91107d57a32SGrant Likely 9121da177e4SLinus Torvalds /* have the bus specific function add its stuff */ 9137eff2e7aSKay Sievers if (dev->bus && dev->bus->uevent) { 9147eff2e7aSKay Sievers retval = dev->bus->uevent(dev, env); 915f9f852dfSKay Sievers if (retval) 9167dc72b28SGreg Kroah-Hartman pr_debug("device: '%s': %s: bus uevent() returned %d\n", 9171e0b2cf9SKay Sievers dev_name(dev), __func__, retval); 9181da177e4SLinus Torvalds } 9191da177e4SLinus Torvalds 9202620efefSGreg Kroah-Hartman /* have the class specific function add its stuff */ 9217eff2e7aSKay Sievers if (dev->class && dev->class->dev_uevent) { 9227eff2e7aSKay Sievers retval = dev->class->dev_uevent(dev, env); 923f9f852dfSKay Sievers if (retval) 9247dc72b28SGreg Kroah-Hartman pr_debug("device: '%s': %s: class uevent() " 9251e0b2cf9SKay Sievers "returned %d\n", dev_name(dev), 9262b3a302aSHarvey Harrison __func__, retval); 9272620efefSGreg Kroah-Hartman } 928f9f852dfSKay Sievers 929eef35c2dSStefan Weil /* have the device type specific function add its stuff */ 9307eff2e7aSKay Sievers if (dev->type && dev->type->uevent) { 9317eff2e7aSKay Sievers retval = dev->type->uevent(dev, env); 932f9f852dfSKay Sievers if (retval) 9337dc72b28SGreg Kroah-Hartman pr_debug("device: '%s': %s: dev_type uevent() " 9341e0b2cf9SKay Sievers "returned %d\n", dev_name(dev), 9352b3a302aSHarvey Harrison __func__, retval); 9362620efefSGreg Kroah-Hartman } 9372620efefSGreg Kroah-Hartman 9381da177e4SLinus Torvalds return retval; 9391da177e4SLinus Torvalds } 9401da177e4SLinus Torvalds 9419cd43611SEmese Revfy static const struct kset_uevent_ops device_uevent_ops = { 942312c004dSKay Sievers .filter = dev_uevent_filter, 943312c004dSKay Sievers .name = dev_uevent_name, 944312c004dSKay Sievers .uevent = dev_uevent, 9451da177e4SLinus Torvalds }; 9461da177e4SLinus Torvalds 947c5e064a6SGreg Kroah-Hartman static ssize_t uevent_show(struct device *dev, struct device_attribute *attr, 94816574dccSKay Sievers char *buf) 94916574dccSKay Sievers { 95016574dccSKay Sievers struct kobject *top_kobj; 95116574dccSKay Sievers struct kset *kset; 9527eff2e7aSKay Sievers struct kobj_uevent_env *env = NULL; 95316574dccSKay Sievers int i; 95416574dccSKay Sievers size_t count = 0; 95516574dccSKay Sievers int retval; 95616574dccSKay Sievers 95716574dccSKay Sievers /* search the kset, the device belongs to */ 95816574dccSKay Sievers top_kobj = &dev->kobj; 9595c5daf65SKay Sievers while (!top_kobj->kset && top_kobj->parent) 96016574dccSKay Sievers top_kobj = top_kobj->parent; 96116574dccSKay Sievers if (!top_kobj->kset) 96216574dccSKay Sievers goto out; 9635c5daf65SKay Sievers 96416574dccSKay Sievers kset = top_kobj->kset; 96516574dccSKay Sievers if (!kset->uevent_ops || !kset->uevent_ops->uevent) 96616574dccSKay Sievers goto out; 96716574dccSKay Sievers 96816574dccSKay Sievers /* respect filter */ 96916574dccSKay Sievers if (kset->uevent_ops && kset->uevent_ops->filter) 97016574dccSKay Sievers if (!kset->uevent_ops->filter(kset, &dev->kobj)) 97116574dccSKay Sievers goto out; 97216574dccSKay Sievers 9737eff2e7aSKay Sievers env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); 9747eff2e7aSKay Sievers if (!env) 975c7308c81SGreg Kroah-Hartman return -ENOMEM; 976c7308c81SGreg Kroah-Hartman 97716574dccSKay Sievers /* let the kset specific function add its keys */ 9787eff2e7aSKay Sievers retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); 97916574dccSKay Sievers if (retval) 98016574dccSKay Sievers goto out; 98116574dccSKay Sievers 98216574dccSKay Sievers /* copy keys to file */ 9837eff2e7aSKay Sievers for (i = 0; i < env->envp_idx; i++) 9847eff2e7aSKay Sievers count += sprintf(&buf[count], "%s\n", env->envp[i]); 98516574dccSKay Sievers out: 9867eff2e7aSKay Sievers kfree(env); 98716574dccSKay Sievers return count; 98816574dccSKay Sievers } 98916574dccSKay Sievers 990c5e064a6SGreg Kroah-Hartman static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, 991a7fd6706SKay Sievers const char *buf, size_t count) 992a7fd6706SKay Sievers { 993f36776faSPeter Rajnoha if (kobject_synth_uevent(&dev->kobj, buf, count)) 994f36776faSPeter Rajnoha dev_err(dev, "uevent: failed to send synthetic uevent\n"); 99560a96a59SKay Sievers 996a7fd6706SKay Sievers return count; 997a7fd6706SKay Sievers } 998c5e064a6SGreg Kroah-Hartman static DEVICE_ATTR_RW(uevent); 999a7fd6706SKay Sievers 1000c5e064a6SGreg Kroah-Hartman static ssize_t online_show(struct device *dev, struct device_attribute *attr, 10014f3549d7SRafael J. Wysocki char *buf) 10024f3549d7SRafael J. Wysocki { 10034f3549d7SRafael J. Wysocki bool val; 10044f3549d7SRafael J. Wysocki 10055e33bc41SRafael J. Wysocki device_lock(dev); 10064f3549d7SRafael J. Wysocki val = !dev->offline; 10075e33bc41SRafael J. Wysocki device_unlock(dev); 10084f3549d7SRafael J. Wysocki return sprintf(buf, "%u\n", val); 10094f3549d7SRafael J. Wysocki } 10104f3549d7SRafael J. Wysocki 1011c5e064a6SGreg Kroah-Hartman static ssize_t online_store(struct device *dev, struct device_attribute *attr, 10124f3549d7SRafael J. Wysocki const char *buf, size_t count) 10134f3549d7SRafael J. Wysocki { 10144f3549d7SRafael J. Wysocki bool val; 10154f3549d7SRafael J. Wysocki int ret; 10164f3549d7SRafael J. Wysocki 10174f3549d7SRafael J. Wysocki ret = strtobool(buf, &val); 10184f3549d7SRafael J. Wysocki if (ret < 0) 10194f3549d7SRafael J. Wysocki return ret; 10204f3549d7SRafael J. Wysocki 10215e33bc41SRafael J. Wysocki ret = lock_device_hotplug_sysfs(); 10225e33bc41SRafael J. Wysocki if (ret) 10235e33bc41SRafael J. Wysocki return ret; 10245e33bc41SRafael J. Wysocki 10254f3549d7SRafael J. Wysocki ret = val ? device_online(dev) : device_offline(dev); 10264f3549d7SRafael J. Wysocki unlock_device_hotplug(); 10274f3549d7SRafael J. Wysocki return ret < 0 ? ret : count; 10284f3549d7SRafael J. Wysocki } 1029c5e064a6SGreg Kroah-Hartman static DEVICE_ATTR_RW(online); 10304f3549d7SRafael J. Wysocki 1031fa6fdb33SGreg Kroah-Hartman int device_add_groups(struct device *dev, const struct attribute_group **groups) 1032621a1672SDmitry Torokhov { 10333e9b2baeSGreg Kroah-Hartman return sysfs_create_groups(&dev->kobj, groups); 1034621a1672SDmitry Torokhov } 1035a7670d42SDmitry Torokhov EXPORT_SYMBOL_GPL(device_add_groups); 1036621a1672SDmitry Torokhov 1037fa6fdb33SGreg Kroah-Hartman void device_remove_groups(struct device *dev, 1038a4dbd674SDavid Brownell const struct attribute_group **groups) 1039621a1672SDmitry Torokhov { 10403e9b2baeSGreg Kroah-Hartman sysfs_remove_groups(&dev->kobj, groups); 1041621a1672SDmitry Torokhov } 1042a7670d42SDmitry Torokhov EXPORT_SYMBOL_GPL(device_remove_groups); 1043de0ff00dSGreg Kroah-Hartman 104457b8ff07SDmitry Torokhov union device_attr_group_devres { 104557b8ff07SDmitry Torokhov const struct attribute_group *group; 104657b8ff07SDmitry Torokhov const struct attribute_group **groups; 104757b8ff07SDmitry Torokhov }; 104857b8ff07SDmitry Torokhov 104957b8ff07SDmitry Torokhov static int devm_attr_group_match(struct device *dev, void *res, void *data) 105057b8ff07SDmitry Torokhov { 105157b8ff07SDmitry Torokhov return ((union device_attr_group_devres *)res)->group == data; 105257b8ff07SDmitry Torokhov } 105357b8ff07SDmitry Torokhov 105457b8ff07SDmitry Torokhov static void devm_attr_group_remove(struct device *dev, void *res) 105557b8ff07SDmitry Torokhov { 105657b8ff07SDmitry Torokhov union device_attr_group_devres *devres = res; 105757b8ff07SDmitry Torokhov const struct attribute_group *group = devres->group; 105857b8ff07SDmitry Torokhov 105957b8ff07SDmitry Torokhov dev_dbg(dev, "%s: removing group %p\n", __func__, group); 106057b8ff07SDmitry Torokhov sysfs_remove_group(&dev->kobj, group); 106157b8ff07SDmitry Torokhov } 106257b8ff07SDmitry Torokhov 106357b8ff07SDmitry Torokhov static void devm_attr_groups_remove(struct device *dev, void *res) 106457b8ff07SDmitry Torokhov { 106557b8ff07SDmitry Torokhov union device_attr_group_devres *devres = res; 106657b8ff07SDmitry Torokhov const struct attribute_group **groups = devres->groups; 106757b8ff07SDmitry Torokhov 106857b8ff07SDmitry Torokhov dev_dbg(dev, "%s: removing groups %p\n", __func__, groups); 106957b8ff07SDmitry Torokhov sysfs_remove_groups(&dev->kobj, groups); 107057b8ff07SDmitry Torokhov } 107157b8ff07SDmitry Torokhov 107257b8ff07SDmitry Torokhov /** 107357b8ff07SDmitry Torokhov * devm_device_add_group - given a device, create a managed attribute group 107457b8ff07SDmitry Torokhov * @dev: The device to create the group for 107557b8ff07SDmitry Torokhov * @grp: The attribute group to create 107657b8ff07SDmitry Torokhov * 107757b8ff07SDmitry Torokhov * This function creates a group for the first time. It will explicitly 107857b8ff07SDmitry Torokhov * warn and error if any of the attribute files being created already exist. 107957b8ff07SDmitry Torokhov * 108057b8ff07SDmitry Torokhov * Returns 0 on success or error code on failure. 108157b8ff07SDmitry Torokhov */ 108257b8ff07SDmitry Torokhov int devm_device_add_group(struct device *dev, const struct attribute_group *grp) 108357b8ff07SDmitry Torokhov { 108457b8ff07SDmitry Torokhov union device_attr_group_devres *devres; 108557b8ff07SDmitry Torokhov int error; 108657b8ff07SDmitry Torokhov 108757b8ff07SDmitry Torokhov devres = devres_alloc(devm_attr_group_remove, 108857b8ff07SDmitry Torokhov sizeof(*devres), GFP_KERNEL); 108957b8ff07SDmitry Torokhov if (!devres) 109057b8ff07SDmitry Torokhov return -ENOMEM; 109157b8ff07SDmitry Torokhov 109257b8ff07SDmitry Torokhov error = sysfs_create_group(&dev->kobj, grp); 109357b8ff07SDmitry Torokhov if (error) { 109457b8ff07SDmitry Torokhov devres_free(devres); 109557b8ff07SDmitry Torokhov return error; 109657b8ff07SDmitry Torokhov } 109757b8ff07SDmitry Torokhov 109857b8ff07SDmitry Torokhov devres->group = grp; 109957b8ff07SDmitry Torokhov devres_add(dev, devres); 110057b8ff07SDmitry Torokhov return 0; 110157b8ff07SDmitry Torokhov } 110257b8ff07SDmitry Torokhov EXPORT_SYMBOL_GPL(devm_device_add_group); 110357b8ff07SDmitry Torokhov 110457b8ff07SDmitry Torokhov /** 110557b8ff07SDmitry Torokhov * devm_device_remove_group: remove a managed group from a device 110657b8ff07SDmitry Torokhov * @dev: device to remove the group from 110757b8ff07SDmitry Torokhov * @grp: group to remove 110857b8ff07SDmitry Torokhov * 110957b8ff07SDmitry Torokhov * This function removes a group of attributes from a device. The attributes 111057b8ff07SDmitry Torokhov * previously have to have been created for this group, otherwise it will fail. 111157b8ff07SDmitry Torokhov */ 111257b8ff07SDmitry Torokhov void devm_device_remove_group(struct device *dev, 111357b8ff07SDmitry Torokhov const struct attribute_group *grp) 111457b8ff07SDmitry Torokhov { 111557b8ff07SDmitry Torokhov WARN_ON(devres_release(dev, devm_attr_group_remove, 111657b8ff07SDmitry Torokhov devm_attr_group_match, 111757b8ff07SDmitry Torokhov /* cast away const */ (void *)grp)); 111857b8ff07SDmitry Torokhov } 111957b8ff07SDmitry Torokhov EXPORT_SYMBOL_GPL(devm_device_remove_group); 112057b8ff07SDmitry Torokhov 112157b8ff07SDmitry Torokhov /** 112257b8ff07SDmitry Torokhov * devm_device_add_groups - create a bunch of managed attribute groups 112357b8ff07SDmitry Torokhov * @dev: The device to create the group for 112457b8ff07SDmitry Torokhov * @groups: The attribute groups to create, NULL terminated 112557b8ff07SDmitry Torokhov * 112657b8ff07SDmitry Torokhov * This function creates a bunch of managed attribute groups. If an error 112757b8ff07SDmitry Torokhov * occurs when creating a group, all previously created groups will be 112857b8ff07SDmitry Torokhov * removed, unwinding everything back to the original state when this 112957b8ff07SDmitry Torokhov * function was called. It will explicitly warn and error if any of the 113057b8ff07SDmitry Torokhov * attribute files being created already exist. 113157b8ff07SDmitry Torokhov * 113257b8ff07SDmitry Torokhov * Returns 0 on success or error code from sysfs_create_group on failure. 113357b8ff07SDmitry Torokhov */ 113457b8ff07SDmitry Torokhov int devm_device_add_groups(struct device *dev, 113557b8ff07SDmitry Torokhov const struct attribute_group **groups) 113657b8ff07SDmitry Torokhov { 113757b8ff07SDmitry Torokhov union device_attr_group_devres *devres; 113857b8ff07SDmitry Torokhov int error; 113957b8ff07SDmitry Torokhov 114057b8ff07SDmitry Torokhov devres = devres_alloc(devm_attr_groups_remove, 114157b8ff07SDmitry Torokhov sizeof(*devres), GFP_KERNEL); 114257b8ff07SDmitry Torokhov if (!devres) 114357b8ff07SDmitry Torokhov return -ENOMEM; 114457b8ff07SDmitry Torokhov 114557b8ff07SDmitry Torokhov error = sysfs_create_groups(&dev->kobj, groups); 114657b8ff07SDmitry Torokhov if (error) { 114757b8ff07SDmitry Torokhov devres_free(devres); 114857b8ff07SDmitry Torokhov return error; 114957b8ff07SDmitry Torokhov } 115057b8ff07SDmitry Torokhov 115157b8ff07SDmitry Torokhov devres->groups = groups; 115257b8ff07SDmitry Torokhov devres_add(dev, devres); 115357b8ff07SDmitry Torokhov return 0; 115457b8ff07SDmitry Torokhov } 115557b8ff07SDmitry Torokhov EXPORT_SYMBOL_GPL(devm_device_add_groups); 115657b8ff07SDmitry Torokhov 115757b8ff07SDmitry Torokhov /** 115857b8ff07SDmitry Torokhov * devm_device_remove_groups - remove a list of managed groups 115957b8ff07SDmitry Torokhov * 116057b8ff07SDmitry Torokhov * @dev: The device for the groups to be removed from 116157b8ff07SDmitry Torokhov * @groups: NULL terminated list of groups to be removed 116257b8ff07SDmitry Torokhov * 116357b8ff07SDmitry Torokhov * If groups is not NULL, remove the specified groups from the device. 116457b8ff07SDmitry Torokhov */ 116557b8ff07SDmitry Torokhov void devm_device_remove_groups(struct device *dev, 116657b8ff07SDmitry Torokhov const struct attribute_group **groups) 116757b8ff07SDmitry Torokhov { 116857b8ff07SDmitry Torokhov WARN_ON(devres_release(dev, devm_attr_groups_remove, 116957b8ff07SDmitry Torokhov devm_attr_group_match, 117057b8ff07SDmitry Torokhov /* cast away const */ (void *)groups)); 117157b8ff07SDmitry Torokhov } 117257b8ff07SDmitry Torokhov EXPORT_SYMBOL_GPL(devm_device_remove_groups); 11731da177e4SLinus Torvalds 11742620efefSGreg Kroah-Hartman static int device_add_attrs(struct device *dev) 11752620efefSGreg Kroah-Hartman { 11762620efefSGreg Kroah-Hartman struct class *class = dev->class; 1177aed65af1SStephen Hemminger const struct device_type *type = dev->type; 1178621a1672SDmitry Torokhov int error; 11792620efefSGreg Kroah-Hartman 1180621a1672SDmitry Torokhov if (class) { 1181d05a6f96SGreg Kroah-Hartman error = device_add_groups(dev, class->dev_groups); 11822620efefSGreg Kroah-Hartman if (error) 1183621a1672SDmitry Torokhov return error; 1184f9f852dfSKay Sievers } 1185f9f852dfSKay Sievers 1186621a1672SDmitry Torokhov if (type) { 1187621a1672SDmitry Torokhov error = device_add_groups(dev, type->groups); 1188f9f852dfSKay Sievers if (error) 1189a6b01dedSGreg Kroah-Hartman goto err_remove_class_groups; 1190f9f852dfSKay Sievers } 1191621a1672SDmitry Torokhov 1192621a1672SDmitry Torokhov error = device_add_groups(dev, dev->groups); 1193f9f852dfSKay Sievers if (error) 1194621a1672SDmitry Torokhov goto err_remove_type_groups; 1195621a1672SDmitry Torokhov 11964f3549d7SRafael J. Wysocki if (device_supports_offline(dev) && !dev->offline_disabled) { 1197c5e064a6SGreg Kroah-Hartman error = device_create_file(dev, &dev_attr_online); 11984f3549d7SRafael J. Wysocki if (error) 1199ecfbf6fdSRafael J. Wysocki goto err_remove_dev_groups; 12004f3549d7SRafael J. Wysocki } 12014f3549d7SRafael J. Wysocki 1202621a1672SDmitry Torokhov return 0; 1203621a1672SDmitry Torokhov 1204ecfbf6fdSRafael J. Wysocki err_remove_dev_groups: 1205ecfbf6fdSRafael J. Wysocki device_remove_groups(dev, dev->groups); 1206621a1672SDmitry Torokhov err_remove_type_groups: 1207621a1672SDmitry Torokhov if (type) 1208621a1672SDmitry Torokhov device_remove_groups(dev, type->groups); 1209d05a6f96SGreg Kroah-Hartman err_remove_class_groups: 1210d05a6f96SGreg Kroah-Hartman if (class) 1211d05a6f96SGreg Kroah-Hartman device_remove_groups(dev, class->dev_groups); 1212f9f852dfSKay Sievers 12132620efefSGreg Kroah-Hartman return error; 12142620efefSGreg Kroah-Hartman } 12152620efefSGreg Kroah-Hartman 12162620efefSGreg Kroah-Hartman static void device_remove_attrs(struct device *dev) 12172620efefSGreg Kroah-Hartman { 12182620efefSGreg Kroah-Hartman struct class *class = dev->class; 1219aed65af1SStephen Hemminger const struct device_type *type = dev->type; 12202620efefSGreg Kroah-Hartman 1221c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_online); 1222621a1672SDmitry Torokhov device_remove_groups(dev, dev->groups); 1223f9f852dfSKay Sievers 1224621a1672SDmitry Torokhov if (type) 1225621a1672SDmitry Torokhov device_remove_groups(dev, type->groups); 1226621a1672SDmitry Torokhov 1227a6b01dedSGreg Kroah-Hartman if (class) 1228d05a6f96SGreg Kroah-Hartman device_remove_groups(dev, class->dev_groups); 1229c97415a7SStefan Achatz } 12302620efefSGreg Kroah-Hartman 1231c5e064a6SGreg Kroah-Hartman static ssize_t dev_show(struct device *dev, struct device_attribute *attr, 123223681e47SGreg Kroah-Hartman char *buf) 123323681e47SGreg Kroah-Hartman { 123423681e47SGreg Kroah-Hartman return print_dev_t(buf, dev->devt); 123523681e47SGreg Kroah-Hartman } 1236c5e064a6SGreg Kroah-Hartman static DEVICE_ATTR_RO(dev); 1237ad6a1e1cSTejun Heo 1238ca22e56dSKay Sievers /* /sys/devices/ */ 1239881c6cfdSGreg Kroah-Hartman struct kset *devices_kset; 12401da177e4SLinus Torvalds 12411da177e4SLinus Torvalds /** 124252cdbdd4SGrygorii Strashko * devices_kset_move_before - Move device in the devices_kset's list. 124352cdbdd4SGrygorii Strashko * @deva: Device to move. 124452cdbdd4SGrygorii Strashko * @devb: Device @deva should come before. 124552cdbdd4SGrygorii Strashko */ 124652cdbdd4SGrygorii Strashko static void devices_kset_move_before(struct device *deva, struct device *devb) 124752cdbdd4SGrygorii Strashko { 124852cdbdd4SGrygorii Strashko if (!devices_kset) 124952cdbdd4SGrygorii Strashko return; 125052cdbdd4SGrygorii Strashko pr_debug("devices_kset: Moving %s before %s\n", 125152cdbdd4SGrygorii Strashko dev_name(deva), dev_name(devb)); 125252cdbdd4SGrygorii Strashko spin_lock(&devices_kset->list_lock); 125352cdbdd4SGrygorii Strashko list_move_tail(&deva->kobj.entry, &devb->kobj.entry); 125452cdbdd4SGrygorii Strashko spin_unlock(&devices_kset->list_lock); 125552cdbdd4SGrygorii Strashko } 125652cdbdd4SGrygorii Strashko 125752cdbdd4SGrygorii Strashko /** 125852cdbdd4SGrygorii Strashko * devices_kset_move_after - Move device in the devices_kset's list. 125952cdbdd4SGrygorii Strashko * @deva: Device to move 126052cdbdd4SGrygorii Strashko * @devb: Device @deva should come after. 126152cdbdd4SGrygorii Strashko */ 126252cdbdd4SGrygorii Strashko static void devices_kset_move_after(struct device *deva, struct device *devb) 126352cdbdd4SGrygorii Strashko { 126452cdbdd4SGrygorii Strashko if (!devices_kset) 126552cdbdd4SGrygorii Strashko return; 126652cdbdd4SGrygorii Strashko pr_debug("devices_kset: Moving %s after %s\n", 126752cdbdd4SGrygorii Strashko dev_name(deva), dev_name(devb)); 126852cdbdd4SGrygorii Strashko spin_lock(&devices_kset->list_lock); 126952cdbdd4SGrygorii Strashko list_move(&deva->kobj.entry, &devb->kobj.entry); 127052cdbdd4SGrygorii Strashko spin_unlock(&devices_kset->list_lock); 127152cdbdd4SGrygorii Strashko } 127252cdbdd4SGrygorii Strashko 127352cdbdd4SGrygorii Strashko /** 127452cdbdd4SGrygorii Strashko * devices_kset_move_last - move the device to the end of devices_kset's list. 127552cdbdd4SGrygorii Strashko * @dev: device to move 127652cdbdd4SGrygorii Strashko */ 127752cdbdd4SGrygorii Strashko void devices_kset_move_last(struct device *dev) 127852cdbdd4SGrygorii Strashko { 127952cdbdd4SGrygorii Strashko if (!devices_kset) 128052cdbdd4SGrygorii Strashko return; 128152cdbdd4SGrygorii Strashko pr_debug("devices_kset: Moving %s to end of list\n", dev_name(dev)); 128252cdbdd4SGrygorii Strashko spin_lock(&devices_kset->list_lock); 128352cdbdd4SGrygorii Strashko list_move_tail(&dev->kobj.entry, &devices_kset->list); 128452cdbdd4SGrygorii Strashko spin_unlock(&devices_kset->list_lock); 128552cdbdd4SGrygorii Strashko } 128652cdbdd4SGrygorii Strashko 128752cdbdd4SGrygorii Strashko /** 12881da177e4SLinus Torvalds * device_create_file - create sysfs attribute file for device. 12891da177e4SLinus Torvalds * @dev: device. 12901da177e4SLinus Torvalds * @attr: device attribute descriptor. 12911da177e4SLinus Torvalds */ 129226579ab7SPhil Carmody int device_create_file(struct device *dev, 129326579ab7SPhil Carmody const struct device_attribute *attr) 12941da177e4SLinus Torvalds { 12951da177e4SLinus Torvalds int error = 0; 12968f46baaaSFelipe Balbi 12978f46baaaSFelipe Balbi if (dev) { 12988f46baaaSFelipe Balbi WARN(((attr->attr.mode & S_IWUGO) && !attr->store), 129997521978Sdyoung@redhat.com "Attribute %s: write permission without 'store'\n", 130097521978Sdyoung@redhat.com attr->attr.name); 13018f46baaaSFelipe Balbi WARN(((attr->attr.mode & S_IRUGO) && !attr->show), 130297521978Sdyoung@redhat.com "Attribute %s: read permission without 'show'\n", 130397521978Sdyoung@redhat.com attr->attr.name); 13041da177e4SLinus Torvalds error = sysfs_create_file(&dev->kobj, &attr->attr); 13058f46baaaSFelipe Balbi } 13068f46baaaSFelipe Balbi 13071da177e4SLinus Torvalds return error; 13081da177e4SLinus Torvalds } 130986df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_create_file); 13101da177e4SLinus Torvalds 13111da177e4SLinus Torvalds /** 13121da177e4SLinus Torvalds * device_remove_file - remove sysfs attribute file. 13131da177e4SLinus Torvalds * @dev: device. 13141da177e4SLinus Torvalds * @attr: device attribute descriptor. 13151da177e4SLinus Torvalds */ 131626579ab7SPhil Carmody void device_remove_file(struct device *dev, 131726579ab7SPhil Carmody const struct device_attribute *attr) 13181da177e4SLinus Torvalds { 13190c98b19fSCornelia Huck if (dev) 13201da177e4SLinus Torvalds sysfs_remove_file(&dev->kobj, &attr->attr); 13211da177e4SLinus Torvalds } 132286df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_remove_file); 13231da177e4SLinus Torvalds 13242589f188SGreg Kroah-Hartman /** 13256b0afc2aSTejun Heo * device_remove_file_self - remove sysfs attribute file from its own method. 13266b0afc2aSTejun Heo * @dev: device. 13276b0afc2aSTejun Heo * @attr: device attribute descriptor. 13286b0afc2aSTejun Heo * 13296b0afc2aSTejun Heo * See kernfs_remove_self() for details. 13306b0afc2aSTejun Heo */ 13316b0afc2aSTejun Heo bool device_remove_file_self(struct device *dev, 13326b0afc2aSTejun Heo const struct device_attribute *attr) 13336b0afc2aSTejun Heo { 13346b0afc2aSTejun Heo if (dev) 13356b0afc2aSTejun Heo return sysfs_remove_file_self(&dev->kobj, &attr->attr); 13366b0afc2aSTejun Heo else 13376b0afc2aSTejun Heo return false; 13386b0afc2aSTejun Heo } 13396b0afc2aSTejun Heo EXPORT_SYMBOL_GPL(device_remove_file_self); 13406b0afc2aSTejun Heo 13416b0afc2aSTejun Heo /** 13422589f188SGreg Kroah-Hartman * device_create_bin_file - create sysfs binary attribute file for device. 13432589f188SGreg Kroah-Hartman * @dev: device. 13442589f188SGreg Kroah-Hartman * @attr: device binary attribute descriptor. 13452589f188SGreg Kroah-Hartman */ 134666ecb92bSPhil Carmody int device_create_bin_file(struct device *dev, 134766ecb92bSPhil Carmody const struct bin_attribute *attr) 13482589f188SGreg Kroah-Hartman { 13492589f188SGreg Kroah-Hartman int error = -EINVAL; 13502589f188SGreg Kroah-Hartman if (dev) 13512589f188SGreg Kroah-Hartman error = sysfs_create_bin_file(&dev->kobj, attr); 13522589f188SGreg Kroah-Hartman return error; 13532589f188SGreg Kroah-Hartman } 13542589f188SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_create_bin_file); 13552589f188SGreg Kroah-Hartman 13562589f188SGreg Kroah-Hartman /** 13572589f188SGreg Kroah-Hartman * device_remove_bin_file - remove sysfs binary attribute file 13582589f188SGreg Kroah-Hartman * @dev: device. 13592589f188SGreg Kroah-Hartman * @attr: device binary attribute descriptor. 13602589f188SGreg Kroah-Hartman */ 136166ecb92bSPhil Carmody void device_remove_bin_file(struct device *dev, 136266ecb92bSPhil Carmody const struct bin_attribute *attr) 13632589f188SGreg Kroah-Hartman { 13642589f188SGreg Kroah-Hartman if (dev) 13652589f188SGreg Kroah-Hartman sysfs_remove_bin_file(&dev->kobj, attr); 13662589f188SGreg Kroah-Hartman } 13672589f188SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_remove_bin_file); 13682589f188SGreg Kroah-Hartman 136934bb61f9SJames Bottomley static void klist_children_get(struct klist_node *n) 137034bb61f9SJames Bottomley { 1371f791b8c8SGreg Kroah-Hartman struct device_private *p = to_device_private_parent(n); 1372f791b8c8SGreg Kroah-Hartman struct device *dev = p->device; 137334bb61f9SJames Bottomley 137434bb61f9SJames Bottomley get_device(dev); 137534bb61f9SJames Bottomley } 137634bb61f9SJames Bottomley 137734bb61f9SJames Bottomley static void klist_children_put(struct klist_node *n) 137834bb61f9SJames Bottomley { 1379f791b8c8SGreg Kroah-Hartman struct device_private *p = to_device_private_parent(n); 1380f791b8c8SGreg Kroah-Hartman struct device *dev = p->device; 138134bb61f9SJames Bottomley 138234bb61f9SJames Bottomley put_device(dev); 138334bb61f9SJames Bottomley } 138434bb61f9SJames Bottomley 13851da177e4SLinus Torvalds /** 13861da177e4SLinus Torvalds * device_initialize - init device structure. 13871da177e4SLinus Torvalds * @dev: device. 13881da177e4SLinus Torvalds * 13895739411aSCornelia Huck * This prepares the device for use by other layers by initializing 13905739411aSCornelia Huck * its fields. 13911da177e4SLinus Torvalds * It is the first half of device_register(), if called by 13925739411aSCornelia Huck * that function, though it can also be called separately, so one 13935739411aSCornelia Huck * may use @dev's fields. In particular, get_device()/put_device() 13945739411aSCornelia Huck * may be used for reference counting of @dev after calling this 13955739411aSCornelia Huck * function. 13965739411aSCornelia Huck * 1397b10d5efdSAlan Stern * All fields in @dev must be initialized by the caller to 0, except 1398b10d5efdSAlan Stern * for those explicitly set to some other value. The simplest 1399b10d5efdSAlan Stern * approach is to use kzalloc() to allocate the structure containing 1400b10d5efdSAlan Stern * @dev. 1401b10d5efdSAlan Stern * 14025739411aSCornelia Huck * NOTE: Use put_device() to give up your reference instead of freeing 14035739411aSCornelia Huck * @dev directly once you have called this function. 14041da177e4SLinus Torvalds */ 14051da177e4SLinus Torvalds void device_initialize(struct device *dev) 14061da177e4SLinus Torvalds { 1407881c6cfdSGreg Kroah-Hartman dev->kobj.kset = devices_kset; 1408f9cb074bSGreg Kroah-Hartman kobject_init(&dev->kobj, &device_ktype); 14091da177e4SLinus Torvalds INIT_LIST_HEAD(&dev->dma_pools); 14103142788bSThomas Gleixner mutex_init(&dev->mutex); 14111704f47bSPeter Zijlstra lockdep_set_novalidate_class(&dev->mutex); 14129ac7849eSTejun Heo spin_lock_init(&dev->devres_lock); 14139ac7849eSTejun Heo INIT_LIST_HEAD(&dev->devres_head); 14143b98aeafSAlan Stern device_pm_init(dev); 141587348136SChristoph Hellwig set_dev_node(dev, -1); 14164a7cc831SJiang Liu #ifdef CONFIG_GENERIC_MSI_IRQ 14174a7cc831SJiang Liu INIT_LIST_HEAD(&dev->msi_list); 14184a7cc831SJiang Liu #endif 14199ed98953SRafael J. Wysocki INIT_LIST_HEAD(&dev->links.consumers); 14209ed98953SRafael J. Wysocki INIT_LIST_HEAD(&dev->links.suppliers); 14219ed98953SRafael J. Wysocki dev->links.status = DL_DEV_NO_DRIVER; 14221da177e4SLinus Torvalds } 142386df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_initialize); 14241da177e4SLinus Torvalds 1425d73ce004STejun Heo struct kobject *virtual_device_parent(struct device *dev) 1426f0ee61a6SGreg Kroah-Hartman { 1427f0ee61a6SGreg Kroah-Hartman static struct kobject *virtual_dir = NULL; 1428f0ee61a6SGreg Kroah-Hartman 1429f0ee61a6SGreg Kroah-Hartman if (!virtual_dir) 14304ff6abffSGreg Kroah-Hartman virtual_dir = kobject_create_and_add("virtual", 1431881c6cfdSGreg Kroah-Hartman &devices_kset->kobj); 1432f0ee61a6SGreg Kroah-Hartman 143386406245SKay Sievers return virtual_dir; 1434f0ee61a6SGreg Kroah-Hartman } 1435f0ee61a6SGreg Kroah-Hartman 1436bc451f20SEric W. Biederman struct class_dir { 1437bc451f20SEric W. Biederman struct kobject kobj; 1438bc451f20SEric W. Biederman struct class *class; 1439bc451f20SEric W. Biederman }; 1440bc451f20SEric W. Biederman 1441bc451f20SEric W. Biederman #define to_class_dir(obj) container_of(obj, struct class_dir, kobj) 1442bc451f20SEric W. Biederman 1443bc451f20SEric W. Biederman static void class_dir_release(struct kobject *kobj) 1444bc451f20SEric W. Biederman { 1445bc451f20SEric W. Biederman struct class_dir *dir = to_class_dir(kobj); 1446bc451f20SEric W. Biederman kfree(dir); 1447bc451f20SEric W. Biederman } 1448bc451f20SEric W. Biederman 1449bc451f20SEric W. Biederman static const 1450bc451f20SEric W. Biederman struct kobj_ns_type_operations *class_dir_child_ns_type(struct kobject *kobj) 1451bc451f20SEric W. Biederman { 1452bc451f20SEric W. Biederman struct class_dir *dir = to_class_dir(kobj); 1453bc451f20SEric W. Biederman return dir->class->ns_type; 1454bc451f20SEric W. Biederman } 1455bc451f20SEric W. Biederman 1456bc451f20SEric W. Biederman static struct kobj_type class_dir_ktype = { 1457bc451f20SEric W. Biederman .release = class_dir_release, 1458bc451f20SEric W. Biederman .sysfs_ops = &kobj_sysfs_ops, 1459bc451f20SEric W. Biederman .child_ns_type = class_dir_child_ns_type 1460bc451f20SEric W. Biederman }; 1461bc451f20SEric W. Biederman 1462bc451f20SEric W. Biederman static struct kobject * 1463bc451f20SEric W. Biederman class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) 1464bc451f20SEric W. Biederman { 1465bc451f20SEric W. Biederman struct class_dir *dir; 1466bc451f20SEric W. Biederman int retval; 1467bc451f20SEric W. Biederman 1468bc451f20SEric W. Biederman dir = kzalloc(sizeof(*dir), GFP_KERNEL); 1469bc451f20SEric W. Biederman if (!dir) 147084d0c27dSTetsuo Handa return ERR_PTR(-ENOMEM); 1471bc451f20SEric W. Biederman 1472bc451f20SEric W. Biederman dir->class = class; 1473bc451f20SEric W. Biederman kobject_init(&dir->kobj, &class_dir_ktype); 1474bc451f20SEric W. Biederman 14756b6e39a6SKay Sievers dir->kobj.kset = &class->p->glue_dirs; 1476bc451f20SEric W. Biederman 1477bc451f20SEric W. Biederman retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name); 1478bc451f20SEric W. Biederman if (retval < 0) { 1479bc451f20SEric W. Biederman kobject_put(&dir->kobj); 148084d0c27dSTetsuo Handa return ERR_PTR(retval); 1481bc451f20SEric W. Biederman } 1482bc451f20SEric W. Biederman return &dir->kobj; 1483bc451f20SEric W. Biederman } 1484bc451f20SEric W. Biederman 1485e4a60d13SYijing Wang static DEFINE_MUTEX(gdp_mutex); 1486bc451f20SEric W. Biederman 1487c744aeaeSCornelia Huck static struct kobject *get_device_parent(struct device *dev, 1488c744aeaeSCornelia Huck struct device *parent) 148940fa5422SGreg Kroah-Hartman { 149086406245SKay Sievers if (dev->class) { 149186406245SKay Sievers struct kobject *kobj = NULL; 149286406245SKay Sievers struct kobject *parent_kobj; 149386406245SKay Sievers struct kobject *k; 149486406245SKay Sievers 1495ead454feSRandy Dunlap #ifdef CONFIG_BLOCK 149639aba963SKay Sievers /* block disks show up in /sys/block */ 1497e52eec13SAndi Kleen if (sysfs_deprecated && dev->class == &block_class) { 149839aba963SKay Sievers if (parent && parent->class == &block_class) 149939aba963SKay Sievers return &parent->kobj; 15006b6e39a6SKay Sievers return &block_class.p->subsys.kobj; 150139aba963SKay Sievers } 1502ead454feSRandy Dunlap #endif 1503e52eec13SAndi Kleen 150486406245SKay Sievers /* 150586406245SKay Sievers * If we have no parent, we live in "virtual". 15060f4dafc0SKay Sievers * Class-devices with a non class-device as parent, live 15070f4dafc0SKay Sievers * in a "glue" directory to prevent namespace collisions. 150886406245SKay Sievers */ 150986406245SKay Sievers if (parent == NULL) 151086406245SKay Sievers parent_kobj = virtual_device_parent(dev); 151124b1442dSEric W. Biederman else if (parent->class && !dev->class->ns_type) 151286406245SKay Sievers return &parent->kobj; 151386406245SKay Sievers else 151486406245SKay Sievers parent_kobj = &parent->kobj; 151586406245SKay Sievers 151677d3d7c1STejun Heo mutex_lock(&gdp_mutex); 151777d3d7c1STejun Heo 151886406245SKay Sievers /* find our class-directory at the parent and reference it */ 15196b6e39a6SKay Sievers spin_lock(&dev->class->p->glue_dirs.list_lock); 15206b6e39a6SKay Sievers list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry) 152186406245SKay Sievers if (k->parent == parent_kobj) { 152286406245SKay Sievers kobj = kobject_get(k); 152386406245SKay Sievers break; 152486406245SKay Sievers } 15256b6e39a6SKay Sievers spin_unlock(&dev->class->p->glue_dirs.list_lock); 152677d3d7c1STejun Heo if (kobj) { 152777d3d7c1STejun Heo mutex_unlock(&gdp_mutex); 152886406245SKay Sievers return kobj; 152977d3d7c1STejun Heo } 153086406245SKay Sievers 153186406245SKay Sievers /* or create a new class-directory at the parent device */ 1532bc451f20SEric W. Biederman k = class_dir_create_and_add(dev->class, parent_kobj); 15330f4dafc0SKay Sievers /* do not emit an uevent for this simple "glue" directory */ 153477d3d7c1STejun Heo mutex_unlock(&gdp_mutex); 153543968d2fSGreg Kroah-Hartman return k; 153686406245SKay Sievers } 153786406245SKay Sievers 1538ca22e56dSKay Sievers /* subsystems can specify a default root directory for their devices */ 1539ca22e56dSKay Sievers if (!parent && dev->bus && dev->bus->dev_root) 1540ca22e56dSKay Sievers return &dev->bus->dev_root->kobj; 1541ca22e56dSKay Sievers 154286406245SKay Sievers if (parent) 1543c744aeaeSCornelia Huck return &parent->kobj; 1544c744aeaeSCornelia Huck return NULL; 1545c744aeaeSCornelia Huck } 1546da231fd5SKay Sievers 1547cebf8fd1SMing Lei static inline bool live_in_glue_dir(struct kobject *kobj, 1548cebf8fd1SMing Lei struct device *dev) 1549cebf8fd1SMing Lei { 1550cebf8fd1SMing Lei if (!kobj || !dev->class || 1551cebf8fd1SMing Lei kobj->kset != &dev->class->p->glue_dirs) 1552cebf8fd1SMing Lei return false; 1553cebf8fd1SMing Lei return true; 1554cebf8fd1SMing Lei } 1555cebf8fd1SMing Lei 1556cebf8fd1SMing Lei static inline struct kobject *get_glue_dir(struct device *dev) 1557cebf8fd1SMing Lei { 1558cebf8fd1SMing Lei return dev->kobj.parent; 1559cebf8fd1SMing Lei } 1560cebf8fd1SMing Lei 1561cebf8fd1SMing Lei /* 1562cebf8fd1SMing Lei * make sure cleaning up dir as the last step, we need to make 1563cebf8fd1SMing Lei * sure .release handler of kobject is run with holding the 1564cebf8fd1SMing Lei * global lock 1565cebf8fd1SMing Lei */ 156663b6971aSCornelia Huck static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) 1567da231fd5SKay Sievers { 15680f4dafc0SKay Sievers /* see if we live in a "glue" directory */ 1569cebf8fd1SMing Lei if (!live_in_glue_dir(glue_dir, dev)) 1570da231fd5SKay Sievers return; 1571da231fd5SKay Sievers 1572e4a60d13SYijing Wang mutex_lock(&gdp_mutex); 15730f4dafc0SKay Sievers kobject_put(glue_dir); 1574e4a60d13SYijing Wang mutex_unlock(&gdp_mutex); 1575da231fd5SKay Sievers } 157663b6971aSCornelia Huck 15772ee97cafSCornelia Huck static int device_add_class_symlinks(struct device *dev) 15782ee97cafSCornelia Huck { 15795590f319SBenjamin Herrenschmidt struct device_node *of_node = dev_of_node(dev); 15802ee97cafSCornelia Huck int error; 15812ee97cafSCornelia Huck 15825590f319SBenjamin Herrenschmidt if (of_node) { 15830c3c234bSRob Herring error = sysfs_create_link(&dev->kobj, of_node_kobj(of_node), "of_node"); 15845590f319SBenjamin Herrenschmidt if (error) 15855590f319SBenjamin Herrenschmidt dev_warn(dev, "Error %d creating of_node link\n",error); 15865590f319SBenjamin Herrenschmidt /* An error here doesn't warrant bringing down the device */ 15875590f319SBenjamin Herrenschmidt } 15885590f319SBenjamin Herrenschmidt 15892ee97cafSCornelia Huck if (!dev->class) 15902ee97cafSCornelia Huck return 0; 1591da231fd5SKay Sievers 15921fbfee6cSGreg Kroah-Hartman error = sysfs_create_link(&dev->kobj, 15936b6e39a6SKay Sievers &dev->class->p->subsys.kobj, 15942ee97cafSCornelia Huck "subsystem"); 15952ee97cafSCornelia Huck if (error) 15965590f319SBenjamin Herrenschmidt goto out_devnode; 1597da231fd5SKay Sievers 15984e886c29SGreg Kroah-Hartman if (dev->parent && device_is_not_partition(dev)) { 15994f01a757SDmitry Torokhov error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, 16004f01a757SDmitry Torokhov "device"); 16014f01a757SDmitry Torokhov if (error) 160239aba963SKay Sievers goto out_subsys; 16032ee97cafSCornelia Huck } 160439aba963SKay Sievers 1605ead454feSRandy Dunlap #ifdef CONFIG_BLOCK 160639aba963SKay Sievers /* /sys/block has directories and does not need symlinks */ 1607e52eec13SAndi Kleen if (sysfs_deprecated && dev->class == &block_class) 160839aba963SKay Sievers return 0; 1609ead454feSRandy Dunlap #endif 161039aba963SKay Sievers 161139aba963SKay Sievers /* link in the class directory pointing to the device */ 16126b6e39a6SKay Sievers error = sysfs_create_link(&dev->class->p->subsys.kobj, 161339aba963SKay Sievers &dev->kobj, dev_name(dev)); 161439aba963SKay Sievers if (error) 161539aba963SKay Sievers goto out_device; 161639aba963SKay Sievers 16172ee97cafSCornelia Huck return 0; 16182ee97cafSCornelia Huck 161939aba963SKay Sievers out_device: 162039aba963SKay Sievers sysfs_remove_link(&dev->kobj, "device"); 1621da231fd5SKay Sievers 16222ee97cafSCornelia Huck out_subsys: 16232ee97cafSCornelia Huck sysfs_remove_link(&dev->kobj, "subsystem"); 16245590f319SBenjamin Herrenschmidt out_devnode: 16255590f319SBenjamin Herrenschmidt sysfs_remove_link(&dev->kobj, "of_node"); 16262ee97cafSCornelia Huck return error; 16272ee97cafSCornelia Huck } 16282ee97cafSCornelia Huck 16292ee97cafSCornelia Huck static void device_remove_class_symlinks(struct device *dev) 16302ee97cafSCornelia Huck { 16315590f319SBenjamin Herrenschmidt if (dev_of_node(dev)) 16325590f319SBenjamin Herrenschmidt sysfs_remove_link(&dev->kobj, "of_node"); 16335590f319SBenjamin Herrenschmidt 16342ee97cafSCornelia Huck if (!dev->class) 16352ee97cafSCornelia Huck return; 1636da231fd5SKay Sievers 16374e886c29SGreg Kroah-Hartman if (dev->parent && device_is_not_partition(dev)) 1638da231fd5SKay Sievers sysfs_remove_link(&dev->kobj, "device"); 16392ee97cafSCornelia Huck sysfs_remove_link(&dev->kobj, "subsystem"); 1640ead454feSRandy Dunlap #ifdef CONFIG_BLOCK 1641e52eec13SAndi Kleen if (sysfs_deprecated && dev->class == &block_class) 164239aba963SKay Sievers return; 1643ead454feSRandy Dunlap #endif 16446b6e39a6SKay Sievers sysfs_delete_link(&dev->class->p->subsys.kobj, &dev->kobj, dev_name(dev)); 16452ee97cafSCornelia Huck } 16462ee97cafSCornelia Huck 16471da177e4SLinus Torvalds /** 1648413c239fSStephen Rothwell * dev_set_name - set a device name 1649413c239fSStephen Rothwell * @dev: device 165046232366SRandy Dunlap * @fmt: format string for the device's name 1651413c239fSStephen Rothwell */ 1652413c239fSStephen Rothwell int dev_set_name(struct device *dev, const char *fmt, ...) 1653413c239fSStephen Rothwell { 1654413c239fSStephen Rothwell va_list vargs; 16551fa5ae85SKay Sievers int err; 1656413c239fSStephen Rothwell 1657413c239fSStephen Rothwell va_start(vargs, fmt); 16581fa5ae85SKay Sievers err = kobject_set_name_vargs(&dev->kobj, fmt, vargs); 1659413c239fSStephen Rothwell va_end(vargs); 16601fa5ae85SKay Sievers return err; 1661413c239fSStephen Rothwell } 1662413c239fSStephen Rothwell EXPORT_SYMBOL_GPL(dev_set_name); 1663413c239fSStephen Rothwell 1664413c239fSStephen Rothwell /** 1665e105b8bfSDan Williams * device_to_dev_kobj - select a /sys/dev/ directory for the device 1666e105b8bfSDan Williams * @dev: device 1667e105b8bfSDan Williams * 1668e105b8bfSDan Williams * By default we select char/ for new entries. Setting class->dev_obj 1669e105b8bfSDan Williams * to NULL prevents an entry from being created. class->dev_kobj must 1670e105b8bfSDan Williams * be set (or cleared) before any devices are registered to the class 1671e105b8bfSDan Williams * otherwise device_create_sys_dev_entry() and 16720d4e293cSPeter Korsgaard * device_remove_sys_dev_entry() will disagree about the presence of 16730d4e293cSPeter Korsgaard * the link. 1674e105b8bfSDan Williams */ 1675e105b8bfSDan Williams static struct kobject *device_to_dev_kobj(struct device *dev) 1676e105b8bfSDan Williams { 1677e105b8bfSDan Williams struct kobject *kobj; 1678e105b8bfSDan Williams 1679e105b8bfSDan Williams if (dev->class) 1680e105b8bfSDan Williams kobj = dev->class->dev_kobj; 1681e105b8bfSDan Williams else 1682e105b8bfSDan Williams kobj = sysfs_dev_char_kobj; 1683e105b8bfSDan Williams 1684e105b8bfSDan Williams return kobj; 1685e105b8bfSDan Williams } 1686e105b8bfSDan Williams 1687e105b8bfSDan Williams static int device_create_sys_dev_entry(struct device *dev) 1688e105b8bfSDan Williams { 1689e105b8bfSDan Williams struct kobject *kobj = device_to_dev_kobj(dev); 1690e105b8bfSDan Williams int error = 0; 1691e105b8bfSDan Williams char devt_str[15]; 1692e105b8bfSDan Williams 1693e105b8bfSDan Williams if (kobj) { 1694e105b8bfSDan Williams format_dev_t(devt_str, dev->devt); 1695e105b8bfSDan Williams error = sysfs_create_link(kobj, &dev->kobj, devt_str); 1696e105b8bfSDan Williams } 1697e105b8bfSDan Williams 1698e105b8bfSDan Williams return error; 1699e105b8bfSDan Williams } 1700e105b8bfSDan Williams 1701e105b8bfSDan Williams static void device_remove_sys_dev_entry(struct device *dev) 1702e105b8bfSDan Williams { 1703e105b8bfSDan Williams struct kobject *kobj = device_to_dev_kobj(dev); 1704e105b8bfSDan Williams char devt_str[15]; 1705e105b8bfSDan Williams 1706e105b8bfSDan Williams if (kobj) { 1707e105b8bfSDan Williams format_dev_t(devt_str, dev->devt); 1708e105b8bfSDan Williams sysfs_remove_link(kobj, devt_str); 1709e105b8bfSDan Williams } 1710e105b8bfSDan Williams } 1711e105b8bfSDan Williams 1712b4028437SGreg Kroah-Hartman int device_private_init(struct device *dev) 1713b4028437SGreg Kroah-Hartman { 1714b4028437SGreg Kroah-Hartman dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL); 1715b4028437SGreg Kroah-Hartman if (!dev->p) 1716b4028437SGreg Kroah-Hartman return -ENOMEM; 1717b4028437SGreg Kroah-Hartman dev->p->device = dev; 1718b4028437SGreg Kroah-Hartman klist_init(&dev->p->klist_children, klist_children_get, 1719b4028437SGreg Kroah-Hartman klist_children_put); 1720ef8a3fd6SGreg Kroah-Hartman INIT_LIST_HEAD(&dev->p->deferred_probe); 1721b4028437SGreg Kroah-Hartman return 0; 1722b4028437SGreg Kroah-Hartman } 1723b4028437SGreg Kroah-Hartman 1724e105b8bfSDan Williams /** 17251da177e4SLinus Torvalds * device_add - add device to device hierarchy. 17261da177e4SLinus Torvalds * @dev: device. 17271da177e4SLinus Torvalds * 17281da177e4SLinus Torvalds * This is part 2 of device_register(), though may be called 17291da177e4SLinus Torvalds * separately _iff_ device_initialize() has been called separately. 17301da177e4SLinus Torvalds * 17315739411aSCornelia Huck * This adds @dev to the kobject hierarchy via kobject_add(), adds it 17321da177e4SLinus Torvalds * to the global and sibling lists for the device, then 17331da177e4SLinus Torvalds * adds it to the other relevant subsystems of the driver model. 17345739411aSCornelia Huck * 1735b10d5efdSAlan Stern * Do not call this routine or device_register() more than once for 1736b10d5efdSAlan Stern * any device structure. The driver model core is not designed to work 1737b10d5efdSAlan Stern * with devices that get unregistered and then spring back to life. 1738b10d5efdSAlan Stern * (Among other things, it's very hard to guarantee that all references 1739b10d5efdSAlan Stern * to the previous incarnation of @dev have been dropped.) Allocate 1740b10d5efdSAlan Stern * and register a fresh new struct device instead. 1741b10d5efdSAlan Stern * 17425739411aSCornelia Huck * NOTE: _Never_ directly free @dev after calling this function, even 17435739411aSCornelia Huck * if it returned an error! Always use put_device() to give up your 17445739411aSCornelia Huck * reference instead. 17451da177e4SLinus Torvalds */ 17461da177e4SLinus Torvalds int device_add(struct device *dev) 17471da177e4SLinus Torvalds { 174835dbf4efSViresh Kumar struct device *parent; 1749ca22e56dSKay Sievers struct kobject *kobj; 1750c47ed219SGreg Kroah-Hartman struct class_interface *class_intf; 1751c906a48aSGreg Kroah-Hartman int error = -EINVAL; 1752cebf8fd1SMing Lei struct kobject *glue_dir = NULL; 1753775b64d2SRafael J. Wysocki 17541da177e4SLinus Torvalds dev = get_device(dev); 1755c906a48aSGreg Kroah-Hartman if (!dev) 1756c906a48aSGreg Kroah-Hartman goto done; 1757c906a48aSGreg Kroah-Hartman 1758fb069a5dSGreg Kroah-Hartman if (!dev->p) { 1759b4028437SGreg Kroah-Hartman error = device_private_init(dev); 1760b4028437SGreg Kroah-Hartman if (error) 1761fb069a5dSGreg Kroah-Hartman goto done; 1762fb069a5dSGreg Kroah-Hartman } 1763fb069a5dSGreg Kroah-Hartman 17641fa5ae85SKay Sievers /* 17651fa5ae85SKay Sievers * for statically allocated devices, which should all be converted 17661fa5ae85SKay Sievers * some day, we need to initialize the name. We prevent reading back 17671fa5ae85SKay Sievers * the name, and force the use of dev_name() 17681fa5ae85SKay Sievers */ 17691fa5ae85SKay Sievers if (dev->init_name) { 1770acc0e90fSGreg Kroah-Hartman dev_set_name(dev, "%s", dev->init_name); 17711fa5ae85SKay Sievers dev->init_name = NULL; 17721fa5ae85SKay Sievers } 1773c906a48aSGreg Kroah-Hartman 1774ca22e56dSKay Sievers /* subsystems can specify simple device enumeration */ 1775ca22e56dSKay Sievers if (!dev_name(dev) && dev->bus && dev->bus->dev_name) 1776ca22e56dSKay Sievers dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); 1777ca22e56dSKay Sievers 1778e6309e75SThomas Gleixner if (!dev_name(dev)) { 1779e6309e75SThomas Gleixner error = -EINVAL; 17805c8563d7SKay Sievers goto name_error; 1781e6309e75SThomas Gleixner } 17821da177e4SLinus Torvalds 17831e0b2cf9SKay Sievers pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 1784c205ef48SGreg Kroah-Hartman 17851da177e4SLinus Torvalds parent = get_device(dev->parent); 1786ca22e56dSKay Sievers kobj = get_device_parent(dev, parent); 178784d0c27dSTetsuo Handa if (IS_ERR(kobj)) { 178884d0c27dSTetsuo Handa error = PTR_ERR(kobj); 178984d0c27dSTetsuo Handa goto parent_error; 179084d0c27dSTetsuo Handa } 1791ca22e56dSKay Sievers if (kobj) 1792ca22e56dSKay Sievers dev->kobj.parent = kobj; 17931da177e4SLinus Torvalds 17940d358f22SYinghai Lu /* use parent numa_node */ 179556f2de81SZhen Lei if (parent && (dev_to_node(dev) == NUMA_NO_NODE)) 17960d358f22SYinghai Lu set_dev_node(dev, dev_to_node(parent)); 17970d358f22SYinghai Lu 17981da177e4SLinus Torvalds /* first, register with generic layer. */ 17998a577ffcSKay Sievers /* we require the name to be set before, and pass NULL */ 18008a577ffcSKay Sievers error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); 1801cebf8fd1SMing Lei if (error) { 1802cebf8fd1SMing Lei glue_dir = get_glue_dir(dev); 18031da177e4SLinus Torvalds goto Error; 1804cebf8fd1SMing Lei } 1805a7fd6706SKay Sievers 180637022644SBrian Walsh /* notify platform of device entry */ 180737022644SBrian Walsh if (platform_notify) 180837022644SBrian Walsh platform_notify(dev); 180937022644SBrian Walsh 1810c5e064a6SGreg Kroah-Hartman error = device_create_file(dev, &dev_attr_uevent); 1811a306eea4SCornelia Huck if (error) 1812a306eea4SCornelia Huck goto attrError; 1813a7fd6706SKay Sievers 18142ee97cafSCornelia Huck error = device_add_class_symlinks(dev); 18152ee97cafSCornelia Huck if (error) 18162ee97cafSCornelia Huck goto SymlinkError; 1817dc0afa83SCornelia Huck error = device_add_attrs(dev); 1818dc0afa83SCornelia Huck if (error) 18192620efefSGreg Kroah-Hartman goto AttrsError; 1820dc0afa83SCornelia Huck error = bus_add_device(dev); 1821dc0afa83SCornelia Huck if (error) 18221da177e4SLinus Torvalds goto BusError; 18233b98aeafSAlan Stern error = dpm_sysfs_add(dev); 182457eee3d2SRafael J. Wysocki if (error) 18253b98aeafSAlan Stern goto DPMError; 18263b98aeafSAlan Stern device_pm_add(dev); 1827ec0676eeSAlan Stern 18280cd75047SSergey Klyaus if (MAJOR(dev->devt)) { 18290cd75047SSergey Klyaus error = device_create_file(dev, &dev_attr_dev); 18300cd75047SSergey Klyaus if (error) 18310cd75047SSergey Klyaus goto DevAttrError; 18320cd75047SSergey Klyaus 18330cd75047SSergey Klyaus error = device_create_sys_dev_entry(dev); 18340cd75047SSergey Klyaus if (error) 18350cd75047SSergey Klyaus goto SysEntryError; 18360cd75047SSergey Klyaus 18370cd75047SSergey Klyaus devtmpfs_create_node(dev); 18380cd75047SSergey Klyaus } 18390cd75047SSergey Klyaus 1840ec0676eeSAlan Stern /* Notify clients of device addition. This call must come 1841268863f4Smajianpeng * after dpm_sysfs_add() and before kobject_uevent(). 1842ec0676eeSAlan Stern */ 1843ec0676eeSAlan Stern if (dev->bus) 1844ec0676eeSAlan Stern blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 1845ec0676eeSAlan Stern BUS_NOTIFY_ADD_DEVICE, dev); 1846ec0676eeSAlan Stern 184753877d06SKay Sievers kobject_uevent(&dev->kobj, KOBJ_ADD); 18482023c610SAlan Stern bus_probe_device(dev); 18491da177e4SLinus Torvalds if (parent) 1850f791b8c8SGreg Kroah-Hartman klist_add_tail(&dev->p->knode_parent, 1851f791b8c8SGreg Kroah-Hartman &parent->p->klist_children); 18521da177e4SLinus Torvalds 18535d9fd169SGreg Kroah-Hartman if (dev->class) { 1854ca22e56dSKay Sievers mutex_lock(&dev->class->p->mutex); 1855c47ed219SGreg Kroah-Hartman /* tie the class to the device */ 18565a3ceb86STejun Heo klist_add_tail(&dev->knode_class, 18576b6e39a6SKay Sievers &dev->class->p->klist_devices); 1858c47ed219SGreg Kroah-Hartman 1859c47ed219SGreg Kroah-Hartman /* notify any interfaces that the device is here */ 1860184f1f77SGreg Kroah-Hartman list_for_each_entry(class_intf, 1861ca22e56dSKay Sievers &dev->class->p->interfaces, node) 1862c47ed219SGreg Kroah-Hartman if (class_intf->add_dev) 1863c47ed219SGreg Kroah-Hartman class_intf->add_dev(dev, class_intf); 1864ca22e56dSKay Sievers mutex_unlock(&dev->class->p->mutex); 18655d9fd169SGreg Kroah-Hartman } 1866c906a48aSGreg Kroah-Hartman done: 18671da177e4SLinus Torvalds put_device(dev); 18681da177e4SLinus Torvalds return error; 18690cd75047SSergey Klyaus SysEntryError: 18700cd75047SSergey Klyaus if (MAJOR(dev->devt)) 18710cd75047SSergey Klyaus device_remove_file(dev, &dev_attr_dev); 18720cd75047SSergey Klyaus DevAttrError: 18730cd75047SSergey Klyaus device_pm_remove(dev); 18740cd75047SSergey Klyaus dpm_sysfs_remove(dev); 18753b98aeafSAlan Stern DPMError: 187657eee3d2SRafael J. Wysocki bus_remove_device(dev); 187757eee3d2SRafael J. Wysocki BusError: 18782620efefSGreg Kroah-Hartman device_remove_attrs(dev); 18792620efefSGreg Kroah-Hartman AttrsError: 18802ee97cafSCornelia Huck device_remove_class_symlinks(dev); 18812ee97cafSCornelia Huck SymlinkError: 1882c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_uevent); 188323681e47SGreg Kroah-Hartman attrError: 1884312c004dSKay Sievers kobject_uevent(&dev->kobj, KOBJ_REMOVE); 1885cebf8fd1SMing Lei glue_dir = get_glue_dir(dev); 18861da177e4SLinus Torvalds kobject_del(&dev->kobj); 18871da177e4SLinus Torvalds Error: 1888cebf8fd1SMing Lei cleanup_glue_dir(dev, glue_dir); 188984d0c27dSTetsuo Handa parent_error: 18901da177e4SLinus Torvalds put_device(parent); 18915c8563d7SKay Sievers name_error: 18925c8563d7SKay Sievers kfree(dev->p); 18935c8563d7SKay Sievers dev->p = NULL; 1894c906a48aSGreg Kroah-Hartman goto done; 18951da177e4SLinus Torvalds } 189686df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_add); 18971da177e4SLinus Torvalds 18981da177e4SLinus Torvalds /** 18991da177e4SLinus Torvalds * device_register - register a device with the system. 19001da177e4SLinus Torvalds * @dev: pointer to the device structure 19011da177e4SLinus Torvalds * 19021da177e4SLinus Torvalds * This happens in two clean steps - initialize the device 19031da177e4SLinus Torvalds * and add it to the system. The two steps can be called 19041da177e4SLinus Torvalds * separately, but this is the easiest and most common. 19051da177e4SLinus Torvalds * I.e. you should only call the two helpers separately if 19061da177e4SLinus Torvalds * have a clearly defined need to use and refcount the device 19071da177e4SLinus Torvalds * before it is added to the hierarchy. 19085739411aSCornelia Huck * 1909b10d5efdSAlan Stern * For more information, see the kerneldoc for device_initialize() 1910b10d5efdSAlan Stern * and device_add(). 1911b10d5efdSAlan Stern * 19125739411aSCornelia Huck * NOTE: _Never_ directly free @dev after calling this function, even 19135739411aSCornelia Huck * if it returned an error! Always use put_device() to give up the 19145739411aSCornelia Huck * reference initialized in this function instead. 19151da177e4SLinus Torvalds */ 19161da177e4SLinus Torvalds int device_register(struct device *dev) 19171da177e4SLinus Torvalds { 19181da177e4SLinus Torvalds device_initialize(dev); 19191da177e4SLinus Torvalds return device_add(dev); 19201da177e4SLinus Torvalds } 192186df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_register); 19221da177e4SLinus Torvalds 19231da177e4SLinus Torvalds /** 19241da177e4SLinus Torvalds * get_device - increment reference count for device. 19251da177e4SLinus Torvalds * @dev: device. 19261da177e4SLinus Torvalds * 19271da177e4SLinus Torvalds * This simply forwards the call to kobject_get(), though 19281da177e4SLinus Torvalds * we do take care to provide for the case that we get a NULL 19291da177e4SLinus Torvalds * pointer passed in. 19301da177e4SLinus Torvalds */ 19311da177e4SLinus Torvalds struct device *get_device(struct device *dev) 19321da177e4SLinus Torvalds { 1933b0d1f807SLars-Peter Clausen return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL; 19341da177e4SLinus Torvalds } 193586df2687SDavid Graham White EXPORT_SYMBOL_GPL(get_device); 19361da177e4SLinus Torvalds 19371da177e4SLinus Torvalds /** 19381da177e4SLinus Torvalds * put_device - decrement reference count. 19391da177e4SLinus Torvalds * @dev: device in question. 19401da177e4SLinus Torvalds */ 19411da177e4SLinus Torvalds void put_device(struct device *dev) 19421da177e4SLinus Torvalds { 1943edfaa7c3SKay Sievers /* might_sleep(); */ 19441da177e4SLinus Torvalds if (dev) 19451da177e4SLinus Torvalds kobject_put(&dev->kobj); 19461da177e4SLinus Torvalds } 194786df2687SDavid Graham White EXPORT_SYMBOL_GPL(put_device); 19481da177e4SLinus Torvalds 19491da177e4SLinus Torvalds /** 19501da177e4SLinus Torvalds * device_del - delete device from system. 19511da177e4SLinus Torvalds * @dev: device. 19521da177e4SLinus Torvalds * 19531da177e4SLinus Torvalds * This is the first part of the device unregistration 19541da177e4SLinus Torvalds * sequence. This removes the device from the lists we control 19551da177e4SLinus Torvalds * from here, has it removed from the other driver model 19561da177e4SLinus Torvalds * subsystems it was added to in device_add(), and removes it 19571da177e4SLinus Torvalds * from the kobject hierarchy. 19581da177e4SLinus Torvalds * 19591da177e4SLinus Torvalds * NOTE: this should be called manually _iff_ device_add() was 19601da177e4SLinus Torvalds * also called manually. 19611da177e4SLinus Torvalds */ 19621da177e4SLinus Torvalds void device_del(struct device *dev) 19631da177e4SLinus Torvalds { 19641da177e4SLinus Torvalds struct device *parent = dev->parent; 1965cebf8fd1SMing Lei struct kobject *glue_dir = NULL; 1966c47ed219SGreg Kroah-Hartman struct class_interface *class_intf; 19671da177e4SLinus Torvalds 1968ec0676eeSAlan Stern /* Notify clients of device removal. This call must come 1969ec0676eeSAlan Stern * before dpm_sysfs_remove(). 1970ec0676eeSAlan Stern */ 1971ec0676eeSAlan Stern if (dev->bus) 1972ec0676eeSAlan Stern blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 1973ec0676eeSAlan Stern BUS_NOTIFY_DEL_DEVICE, dev); 19749ed98953SRafael J. Wysocki 19753b98aeafSAlan Stern dpm_sysfs_remove(dev); 19761da177e4SLinus Torvalds if (parent) 1977f791b8c8SGreg Kroah-Hartman klist_del(&dev->p->knode_parent); 1978e105b8bfSDan Williams if (MAJOR(dev->devt)) { 19792b2af54aSKay Sievers devtmpfs_delete_node(dev); 1980e105b8bfSDan Williams device_remove_sys_dev_entry(dev); 1981c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_dev); 1982e105b8bfSDan Williams } 1983b9d9c82bSKay Sievers if (dev->class) { 1984da231fd5SKay Sievers device_remove_class_symlinks(dev); 198599ef3ef8SKay Sievers 1986ca22e56dSKay Sievers mutex_lock(&dev->class->p->mutex); 1987c47ed219SGreg Kroah-Hartman /* notify any interfaces that the device is now gone */ 1988184f1f77SGreg Kroah-Hartman list_for_each_entry(class_intf, 1989ca22e56dSKay Sievers &dev->class->p->interfaces, node) 1990c47ed219SGreg Kroah-Hartman if (class_intf->remove_dev) 1991c47ed219SGreg Kroah-Hartman class_intf->remove_dev(dev, class_intf); 1992c47ed219SGreg Kroah-Hartman /* remove the device from the class list */ 19935a3ceb86STejun Heo klist_del(&dev->knode_class); 1994ca22e56dSKay Sievers mutex_unlock(&dev->class->p->mutex); 1995b9d9c82bSKay Sievers } 1996c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_uevent); 19972620efefSGreg Kroah-Hartman device_remove_attrs(dev); 199828953533SBenjamin Herrenschmidt bus_remove_device(dev); 19994b6d1f12SLongX Zhang device_pm_remove(dev); 2000d1c3414cSGrant Likely driver_deferred_probe_del(dev); 2001478573c9SLukas Wunner device_remove_properties(dev); 20022ec16150SJeffy Chen device_links_purge(dev); 20031da177e4SLinus Torvalds 20041da177e4SLinus Torvalds /* Notify the platform of the removal, in case they 20051da177e4SLinus Torvalds * need to do anything... 20061da177e4SLinus Torvalds */ 20071da177e4SLinus Torvalds if (platform_notify_remove) 20081da177e4SLinus Torvalds platform_notify_remove(dev); 2009599bad38SJoerg Roedel if (dev->bus) 2010599bad38SJoerg Roedel blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 2011599bad38SJoerg Roedel BUS_NOTIFY_REMOVED_DEVICE, dev); 2012312c004dSKay Sievers kobject_uevent(&dev->kobj, KOBJ_REMOVE); 2013cebf8fd1SMing Lei glue_dir = get_glue_dir(dev); 20141da177e4SLinus Torvalds kobject_del(&dev->kobj); 2015cebf8fd1SMing Lei cleanup_glue_dir(dev, glue_dir); 20161da177e4SLinus Torvalds put_device(parent); 20171da177e4SLinus Torvalds } 201886df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_del); 20191da177e4SLinus Torvalds 20201da177e4SLinus Torvalds /** 20211da177e4SLinus Torvalds * device_unregister - unregister device from system. 20221da177e4SLinus Torvalds * @dev: device going away. 20231da177e4SLinus Torvalds * 20241da177e4SLinus Torvalds * We do this in two parts, like we do device_register(). First, 20251da177e4SLinus Torvalds * we remove it from all the subsystems with device_del(), then 20261da177e4SLinus Torvalds * we decrement the reference count via put_device(). If that 20271da177e4SLinus Torvalds * is the final reference count, the device will be cleaned up 20281da177e4SLinus Torvalds * via device_release() above. Otherwise, the structure will 20291da177e4SLinus Torvalds * stick around until the final reference to the device is dropped. 20301da177e4SLinus Torvalds */ 20311da177e4SLinus Torvalds void device_unregister(struct device *dev) 20321da177e4SLinus Torvalds { 20331e0b2cf9SKay Sievers pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 20341da177e4SLinus Torvalds device_del(dev); 20351da177e4SLinus Torvalds put_device(dev); 20361da177e4SLinus Torvalds } 203786df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_unregister); 20381da177e4SLinus Torvalds 20393d060aebSAndy Shevchenko static struct device *prev_device(struct klist_iter *i) 20403d060aebSAndy Shevchenko { 20413d060aebSAndy Shevchenko struct klist_node *n = klist_prev(i); 20423d060aebSAndy Shevchenko struct device *dev = NULL; 20433d060aebSAndy Shevchenko struct device_private *p; 20443d060aebSAndy Shevchenko 20453d060aebSAndy Shevchenko if (n) { 20463d060aebSAndy Shevchenko p = to_device_private_parent(n); 20473d060aebSAndy Shevchenko dev = p->device; 20483d060aebSAndy Shevchenko } 20493d060aebSAndy Shevchenko return dev; 20503d060aebSAndy Shevchenko } 20513d060aebSAndy Shevchenko 205236239577Smochel@digitalimplant.org static struct device *next_device(struct klist_iter *i) 205336239577Smochel@digitalimplant.org { 205436239577Smochel@digitalimplant.org struct klist_node *n = klist_next(i); 2055f791b8c8SGreg Kroah-Hartman struct device *dev = NULL; 2056f791b8c8SGreg Kroah-Hartman struct device_private *p; 2057f791b8c8SGreg Kroah-Hartman 2058f791b8c8SGreg Kroah-Hartman if (n) { 2059f791b8c8SGreg Kroah-Hartman p = to_device_private_parent(n); 2060f791b8c8SGreg Kroah-Hartman dev = p->device; 2061f791b8c8SGreg Kroah-Hartman } 2062f791b8c8SGreg Kroah-Hartman return dev; 206336239577Smochel@digitalimplant.org } 206436239577Smochel@digitalimplant.org 20651da177e4SLinus Torvalds /** 2066e454cea2SKay Sievers * device_get_devnode - path of device node file 20676fcf53acSKay Sievers * @dev: device 2068e454cea2SKay Sievers * @mode: returned file access mode 20693c2670e6SKay Sievers * @uid: returned file owner 20703c2670e6SKay Sievers * @gid: returned file group 20716fcf53acSKay Sievers * @tmp: possibly allocated string 20726fcf53acSKay Sievers * 20736fcf53acSKay Sievers * Return the relative path of a possible device node. 20746fcf53acSKay Sievers * Non-default names may need to allocate a memory to compose 20756fcf53acSKay Sievers * a name. This memory is returned in tmp and needs to be 20766fcf53acSKay Sievers * freed by the caller. 20776fcf53acSKay Sievers */ 2078e454cea2SKay Sievers const char *device_get_devnode(struct device *dev, 20794e4098a3SGreg Kroah-Hartman umode_t *mode, kuid_t *uid, kgid_t *gid, 20803c2670e6SKay Sievers const char **tmp) 20816fcf53acSKay Sievers { 20826fcf53acSKay Sievers char *s; 20836fcf53acSKay Sievers 20846fcf53acSKay Sievers *tmp = NULL; 20856fcf53acSKay Sievers 20866fcf53acSKay Sievers /* the device type may provide a specific name */ 2087e454cea2SKay Sievers if (dev->type && dev->type->devnode) 20883c2670e6SKay Sievers *tmp = dev->type->devnode(dev, mode, uid, gid); 20896fcf53acSKay Sievers if (*tmp) 20906fcf53acSKay Sievers return *tmp; 20916fcf53acSKay Sievers 20926fcf53acSKay Sievers /* the class may provide a specific name */ 2093e454cea2SKay Sievers if (dev->class && dev->class->devnode) 2094e454cea2SKay Sievers *tmp = dev->class->devnode(dev, mode); 20956fcf53acSKay Sievers if (*tmp) 20966fcf53acSKay Sievers return *tmp; 20976fcf53acSKay Sievers 20986fcf53acSKay Sievers /* return name without allocation, tmp == NULL */ 20996fcf53acSKay Sievers if (strchr(dev_name(dev), '!') == NULL) 21006fcf53acSKay Sievers return dev_name(dev); 21016fcf53acSKay Sievers 21026fcf53acSKay Sievers /* replace '!' in the name with '/' */ 2103a29fd614SRasmus Villemoes s = kstrdup(dev_name(dev), GFP_KERNEL); 2104a29fd614SRasmus Villemoes if (!s) 21056fcf53acSKay Sievers return NULL; 2106a29fd614SRasmus Villemoes strreplace(s, '!', '/'); 2107a29fd614SRasmus Villemoes return *tmp = s; 21086fcf53acSKay Sievers } 21096fcf53acSKay Sievers 21106fcf53acSKay Sievers /** 21111da177e4SLinus Torvalds * device_for_each_child - device child iterator. 2112c41455fbSRandy Dunlap * @parent: parent struct device. 21131da177e4SLinus Torvalds * @fn: function to be called for each device. 2114f8878dcbSRobert P. J. Day * @data: data for the callback. 21151da177e4SLinus Torvalds * 2116c41455fbSRandy Dunlap * Iterate over @parent's child devices, and call @fn for each, 21171da177e4SLinus Torvalds * passing it @data. 21181da177e4SLinus Torvalds * 21191da177e4SLinus Torvalds * We check the return of @fn each time. If it returns anything 21201da177e4SLinus Torvalds * other than 0, we break out and return that value. 21211da177e4SLinus Torvalds */ 212236239577Smochel@digitalimplant.org int device_for_each_child(struct device *parent, void *data, 21234a3ad20cSGreg Kroah-Hartman int (*fn)(struct device *dev, void *data)) 21241da177e4SLinus Torvalds { 212536239577Smochel@digitalimplant.org struct klist_iter i; 21261da177e4SLinus Torvalds struct device *child; 21271da177e4SLinus Torvalds int error = 0; 21281da177e4SLinus Torvalds 2129014c90dbSGreg Kroah-Hartman if (!parent->p) 2130014c90dbSGreg Kroah-Hartman return 0; 2131014c90dbSGreg Kroah-Hartman 2132f791b8c8SGreg Kroah-Hartman klist_iter_init(&parent->p->klist_children, &i); 213393ead7c9SGimcuan Hui while (!error && (child = next_device(&i))) 213436239577Smochel@digitalimplant.org error = fn(child, data); 213536239577Smochel@digitalimplant.org klist_iter_exit(&i); 21361da177e4SLinus Torvalds return error; 21371da177e4SLinus Torvalds } 213886df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_for_each_child); 21391da177e4SLinus Torvalds 21405ab69981SCornelia Huck /** 21413d060aebSAndy Shevchenko * device_for_each_child_reverse - device child iterator in reversed order. 21423d060aebSAndy Shevchenko * @parent: parent struct device. 21433d060aebSAndy Shevchenko * @fn: function to be called for each device. 21443d060aebSAndy Shevchenko * @data: data for the callback. 21453d060aebSAndy Shevchenko * 21463d060aebSAndy Shevchenko * Iterate over @parent's child devices, and call @fn for each, 21473d060aebSAndy Shevchenko * passing it @data. 21483d060aebSAndy Shevchenko * 21493d060aebSAndy Shevchenko * We check the return of @fn each time. If it returns anything 21503d060aebSAndy Shevchenko * other than 0, we break out and return that value. 21513d060aebSAndy Shevchenko */ 21523d060aebSAndy Shevchenko int device_for_each_child_reverse(struct device *parent, void *data, 21533d060aebSAndy Shevchenko int (*fn)(struct device *dev, void *data)) 21543d060aebSAndy Shevchenko { 21553d060aebSAndy Shevchenko struct klist_iter i; 21563d060aebSAndy Shevchenko struct device *child; 21573d060aebSAndy Shevchenko int error = 0; 21583d060aebSAndy Shevchenko 21593d060aebSAndy Shevchenko if (!parent->p) 21603d060aebSAndy Shevchenko return 0; 21613d060aebSAndy Shevchenko 21623d060aebSAndy Shevchenko klist_iter_init(&parent->p->klist_children, &i); 21633d060aebSAndy Shevchenko while ((child = prev_device(&i)) && !error) 21643d060aebSAndy Shevchenko error = fn(child, data); 21653d060aebSAndy Shevchenko klist_iter_exit(&i); 21663d060aebSAndy Shevchenko return error; 21673d060aebSAndy Shevchenko } 21683d060aebSAndy Shevchenko EXPORT_SYMBOL_GPL(device_for_each_child_reverse); 21693d060aebSAndy Shevchenko 21703d060aebSAndy Shevchenko /** 21715ab69981SCornelia Huck * device_find_child - device iterator for locating a particular device. 21725ab69981SCornelia Huck * @parent: parent struct device 21735ab69981SCornelia Huck * @match: Callback function to check device 2174f8878dcbSRobert P. J. Day * @data: Data to pass to match function 21755ab69981SCornelia Huck * 21765ab69981SCornelia Huck * This is similar to the device_for_each_child() function above, but it 21775ab69981SCornelia Huck * returns a reference to a device that is 'found' for later use, as 21785ab69981SCornelia Huck * determined by the @match callback. 21795ab69981SCornelia Huck * 21805ab69981SCornelia Huck * The callback should return 0 if the device doesn't match and non-zero 21815ab69981SCornelia Huck * if it does. If the callback returns non-zero and a reference to the 21825ab69981SCornelia Huck * current device can be obtained, this function will return to the caller 21835ab69981SCornelia Huck * and not iterate over any more devices. 2184a4e2400aSFederico Vaga * 2185a4e2400aSFederico Vaga * NOTE: you will need to drop the reference with put_device() after use. 21865ab69981SCornelia Huck */ 21875ab69981SCornelia Huck struct device *device_find_child(struct device *parent, void *data, 21884a3ad20cSGreg Kroah-Hartman int (*match)(struct device *dev, void *data)) 21895ab69981SCornelia Huck { 21905ab69981SCornelia Huck struct klist_iter i; 21915ab69981SCornelia Huck struct device *child; 21925ab69981SCornelia Huck 21935ab69981SCornelia Huck if (!parent) 21945ab69981SCornelia Huck return NULL; 21955ab69981SCornelia Huck 2196f791b8c8SGreg Kroah-Hartman klist_iter_init(&parent->p->klist_children, &i); 21975ab69981SCornelia Huck while ((child = next_device(&i))) 21985ab69981SCornelia Huck if (match(child, data) && get_device(child)) 21995ab69981SCornelia Huck break; 22005ab69981SCornelia Huck klist_iter_exit(&i); 22015ab69981SCornelia Huck return child; 22025ab69981SCornelia Huck } 220386df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_find_child); 22045ab69981SCornelia Huck 22051da177e4SLinus Torvalds int __init devices_init(void) 22061da177e4SLinus Torvalds { 2207881c6cfdSGreg Kroah-Hartman devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); 2208881c6cfdSGreg Kroah-Hartman if (!devices_kset) 2209881c6cfdSGreg Kroah-Hartman return -ENOMEM; 2210e105b8bfSDan Williams dev_kobj = kobject_create_and_add("dev", NULL); 2211e105b8bfSDan Williams if (!dev_kobj) 2212e105b8bfSDan Williams goto dev_kobj_err; 2213e105b8bfSDan Williams sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); 2214e105b8bfSDan Williams if (!sysfs_dev_block_kobj) 2215e105b8bfSDan Williams goto block_kobj_err; 2216e105b8bfSDan Williams sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); 2217e105b8bfSDan Williams if (!sysfs_dev_char_kobj) 2218e105b8bfSDan Williams goto char_kobj_err; 2219e105b8bfSDan Williams 2220881c6cfdSGreg Kroah-Hartman return 0; 2221e105b8bfSDan Williams 2222e105b8bfSDan Williams char_kobj_err: 2223e105b8bfSDan Williams kobject_put(sysfs_dev_block_kobj); 2224e105b8bfSDan Williams block_kobj_err: 2225e105b8bfSDan Williams kobject_put(dev_kobj); 2226e105b8bfSDan Williams dev_kobj_err: 2227e105b8bfSDan Williams kset_unregister(devices_kset); 2228e105b8bfSDan Williams return -ENOMEM; 22291da177e4SLinus Torvalds } 22301da177e4SLinus Torvalds 22314f3549d7SRafael J. Wysocki static int device_check_offline(struct device *dev, void *not_used) 22324f3549d7SRafael J. Wysocki { 22334f3549d7SRafael J. Wysocki int ret; 22344f3549d7SRafael J. Wysocki 22354f3549d7SRafael J. Wysocki ret = device_for_each_child(dev, NULL, device_check_offline); 22364f3549d7SRafael J. Wysocki if (ret) 22374f3549d7SRafael J. Wysocki return ret; 22384f3549d7SRafael J. Wysocki 22394f3549d7SRafael J. Wysocki return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0; 22404f3549d7SRafael J. Wysocki } 22414f3549d7SRafael J. Wysocki 22424f3549d7SRafael J. Wysocki /** 22434f3549d7SRafael J. Wysocki * device_offline - Prepare the device for hot-removal. 22444f3549d7SRafael J. Wysocki * @dev: Device to be put offline. 22454f3549d7SRafael J. Wysocki * 22464f3549d7SRafael J. Wysocki * Execute the device bus type's .offline() callback, if present, to prepare 22474f3549d7SRafael J. Wysocki * the device for a subsequent hot-removal. If that succeeds, the device must 22484f3549d7SRafael J. Wysocki * not be used until either it is removed or its bus type's .online() callback 22494f3549d7SRafael J. Wysocki * is executed. 22504f3549d7SRafael J. Wysocki * 22514f3549d7SRafael J. Wysocki * Call under device_hotplug_lock. 22524f3549d7SRafael J. Wysocki */ 22534f3549d7SRafael J. Wysocki int device_offline(struct device *dev) 22544f3549d7SRafael J. Wysocki { 22554f3549d7SRafael J. Wysocki int ret; 22564f3549d7SRafael J. Wysocki 22574f3549d7SRafael J. Wysocki if (dev->offline_disabled) 22584f3549d7SRafael J. Wysocki return -EPERM; 22594f3549d7SRafael J. Wysocki 22604f3549d7SRafael J. Wysocki ret = device_for_each_child(dev, NULL, device_check_offline); 22614f3549d7SRafael J. Wysocki if (ret) 22624f3549d7SRafael J. Wysocki return ret; 22634f3549d7SRafael J. Wysocki 22644f3549d7SRafael J. Wysocki device_lock(dev); 22654f3549d7SRafael J. Wysocki if (device_supports_offline(dev)) { 22664f3549d7SRafael J. Wysocki if (dev->offline) { 22674f3549d7SRafael J. Wysocki ret = 1; 22684f3549d7SRafael J. Wysocki } else { 22694f3549d7SRafael J. Wysocki ret = dev->bus->offline(dev); 22704f3549d7SRafael J. Wysocki if (!ret) { 22714f3549d7SRafael J. Wysocki kobject_uevent(&dev->kobj, KOBJ_OFFLINE); 22724f3549d7SRafael J. Wysocki dev->offline = true; 22734f3549d7SRafael J. Wysocki } 22744f3549d7SRafael J. Wysocki } 22754f3549d7SRafael J. Wysocki } 22764f3549d7SRafael J. Wysocki device_unlock(dev); 22774f3549d7SRafael J. Wysocki 22784f3549d7SRafael J. Wysocki return ret; 22794f3549d7SRafael J. Wysocki } 22804f3549d7SRafael J. Wysocki 22814f3549d7SRafael J. Wysocki /** 22824f3549d7SRafael J. Wysocki * device_online - Put the device back online after successful device_offline(). 22834f3549d7SRafael J. Wysocki * @dev: Device to be put back online. 22844f3549d7SRafael J. Wysocki * 22854f3549d7SRafael J. Wysocki * If device_offline() has been successfully executed for @dev, but the device 22864f3549d7SRafael J. Wysocki * has not been removed subsequently, execute its bus type's .online() callback 22874f3549d7SRafael J. Wysocki * to indicate that the device can be used again. 22884f3549d7SRafael J. Wysocki * 22894f3549d7SRafael J. Wysocki * Call under device_hotplug_lock. 22904f3549d7SRafael J. Wysocki */ 22914f3549d7SRafael J. Wysocki int device_online(struct device *dev) 22924f3549d7SRafael J. Wysocki { 22934f3549d7SRafael J. Wysocki int ret = 0; 22944f3549d7SRafael J. Wysocki 22954f3549d7SRafael J. Wysocki device_lock(dev); 22964f3549d7SRafael J. Wysocki if (device_supports_offline(dev)) { 22974f3549d7SRafael J. Wysocki if (dev->offline) { 22984f3549d7SRafael J. Wysocki ret = dev->bus->online(dev); 22994f3549d7SRafael J. Wysocki if (!ret) { 23004f3549d7SRafael J. Wysocki kobject_uevent(&dev->kobj, KOBJ_ONLINE); 23014f3549d7SRafael J. Wysocki dev->offline = false; 23024f3549d7SRafael J. Wysocki } 23034f3549d7SRafael J. Wysocki } else { 23044f3549d7SRafael J. Wysocki ret = 1; 23054f3549d7SRafael J. Wysocki } 23064f3549d7SRafael J. Wysocki } 23074f3549d7SRafael J. Wysocki device_unlock(dev); 23084f3549d7SRafael J. Wysocki 23094f3549d7SRafael J. Wysocki return ret; 23104f3549d7SRafael J. Wysocki } 23114f3549d7SRafael J. Wysocki 23127f100d15SKarthigan Srinivasan struct root_device { 23130aa0dc41SMark McLoughlin struct device dev; 23140aa0dc41SMark McLoughlin struct module *owner; 23150aa0dc41SMark McLoughlin }; 23160aa0dc41SMark McLoughlin 231793058424SJosh Triplett static inline struct root_device *to_root_device(struct device *d) 2318481e2079SFerenc Wagner { 2319481e2079SFerenc Wagner return container_of(d, struct root_device, dev); 2320481e2079SFerenc Wagner } 23210aa0dc41SMark McLoughlin 23220aa0dc41SMark McLoughlin static void root_device_release(struct device *dev) 23230aa0dc41SMark McLoughlin { 23240aa0dc41SMark McLoughlin kfree(to_root_device(dev)); 23250aa0dc41SMark McLoughlin } 23260aa0dc41SMark McLoughlin 23270aa0dc41SMark McLoughlin /** 23280aa0dc41SMark McLoughlin * __root_device_register - allocate and register a root device 23290aa0dc41SMark McLoughlin * @name: root device name 23300aa0dc41SMark McLoughlin * @owner: owner module of the root device, usually THIS_MODULE 23310aa0dc41SMark McLoughlin * 23320aa0dc41SMark McLoughlin * This function allocates a root device and registers it 23330aa0dc41SMark McLoughlin * using device_register(). In order to free the returned 23340aa0dc41SMark McLoughlin * device, use root_device_unregister(). 23350aa0dc41SMark McLoughlin * 23360aa0dc41SMark McLoughlin * Root devices are dummy devices which allow other devices 23370aa0dc41SMark McLoughlin * to be grouped under /sys/devices. Use this function to 23380aa0dc41SMark McLoughlin * allocate a root device and then use it as the parent of 23390aa0dc41SMark McLoughlin * any device which should appear under /sys/devices/{name} 23400aa0dc41SMark McLoughlin * 23410aa0dc41SMark McLoughlin * The /sys/devices/{name} directory will also contain a 23420aa0dc41SMark McLoughlin * 'module' symlink which points to the @owner directory 23430aa0dc41SMark McLoughlin * in sysfs. 23440aa0dc41SMark McLoughlin * 2345f0eae0edSJani Nikula * Returns &struct device pointer on success, or ERR_PTR() on error. 2346f0eae0edSJani Nikula * 23470aa0dc41SMark McLoughlin * Note: You probably want to use root_device_register(). 23480aa0dc41SMark McLoughlin */ 23490aa0dc41SMark McLoughlin struct device *__root_device_register(const char *name, struct module *owner) 23500aa0dc41SMark McLoughlin { 23510aa0dc41SMark McLoughlin struct root_device *root; 23520aa0dc41SMark McLoughlin int err = -ENOMEM; 23530aa0dc41SMark McLoughlin 23540aa0dc41SMark McLoughlin root = kzalloc(sizeof(struct root_device), GFP_KERNEL); 23550aa0dc41SMark McLoughlin if (!root) 23560aa0dc41SMark McLoughlin return ERR_PTR(err); 23570aa0dc41SMark McLoughlin 2358acc0e90fSGreg Kroah-Hartman err = dev_set_name(&root->dev, "%s", name); 23590aa0dc41SMark McLoughlin if (err) { 23600aa0dc41SMark McLoughlin kfree(root); 23610aa0dc41SMark McLoughlin return ERR_PTR(err); 23620aa0dc41SMark McLoughlin } 23630aa0dc41SMark McLoughlin 23640aa0dc41SMark McLoughlin root->dev.release = root_device_release; 23650aa0dc41SMark McLoughlin 23660aa0dc41SMark McLoughlin err = device_register(&root->dev); 23670aa0dc41SMark McLoughlin if (err) { 23680aa0dc41SMark McLoughlin put_device(&root->dev); 23690aa0dc41SMark McLoughlin return ERR_PTR(err); 23700aa0dc41SMark McLoughlin } 23710aa0dc41SMark McLoughlin 23721d9e882bSChristoph Egger #ifdef CONFIG_MODULES /* gotta find a "cleaner" way to do this */ 23730aa0dc41SMark McLoughlin if (owner) { 23740aa0dc41SMark McLoughlin struct module_kobject *mk = &owner->mkobj; 23750aa0dc41SMark McLoughlin 23760aa0dc41SMark McLoughlin err = sysfs_create_link(&root->dev.kobj, &mk->kobj, "module"); 23770aa0dc41SMark McLoughlin if (err) { 23780aa0dc41SMark McLoughlin device_unregister(&root->dev); 23790aa0dc41SMark McLoughlin return ERR_PTR(err); 23800aa0dc41SMark McLoughlin } 23810aa0dc41SMark McLoughlin root->owner = owner; 23820aa0dc41SMark McLoughlin } 23830aa0dc41SMark McLoughlin #endif 23840aa0dc41SMark McLoughlin 23850aa0dc41SMark McLoughlin return &root->dev; 23860aa0dc41SMark McLoughlin } 23870aa0dc41SMark McLoughlin EXPORT_SYMBOL_GPL(__root_device_register); 23880aa0dc41SMark McLoughlin 23890aa0dc41SMark McLoughlin /** 23900aa0dc41SMark McLoughlin * root_device_unregister - unregister and free a root device 23917cbcf225SRandy Dunlap * @dev: device going away 23920aa0dc41SMark McLoughlin * 23930aa0dc41SMark McLoughlin * This function unregisters and cleans up a device that was created by 23940aa0dc41SMark McLoughlin * root_device_register(). 23950aa0dc41SMark McLoughlin */ 23960aa0dc41SMark McLoughlin void root_device_unregister(struct device *dev) 23970aa0dc41SMark McLoughlin { 23980aa0dc41SMark McLoughlin struct root_device *root = to_root_device(dev); 23990aa0dc41SMark McLoughlin 24000aa0dc41SMark McLoughlin if (root->owner) 24010aa0dc41SMark McLoughlin sysfs_remove_link(&root->dev.kobj, "module"); 24020aa0dc41SMark McLoughlin 24030aa0dc41SMark McLoughlin device_unregister(dev); 24040aa0dc41SMark McLoughlin } 24050aa0dc41SMark McLoughlin EXPORT_SYMBOL_GPL(root_device_unregister); 24060aa0dc41SMark McLoughlin 240723681e47SGreg Kroah-Hartman 240823681e47SGreg Kroah-Hartman static void device_create_release(struct device *dev) 240923681e47SGreg Kroah-Hartman { 24101e0b2cf9SKay Sievers pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 241123681e47SGreg Kroah-Hartman kfree(dev); 241223681e47SGreg Kroah-Hartman } 241323681e47SGreg Kroah-Hartman 241439ef3112SGuenter Roeck static struct device * 241539ef3112SGuenter Roeck device_create_groups_vargs(struct class *class, struct device *parent, 241639ef3112SGuenter Roeck dev_t devt, void *drvdata, 241739ef3112SGuenter Roeck const struct attribute_group **groups, 241839ef3112SGuenter Roeck const char *fmt, va_list args) 241939ef3112SGuenter Roeck { 242039ef3112SGuenter Roeck struct device *dev = NULL; 242139ef3112SGuenter Roeck int retval = -ENODEV; 242239ef3112SGuenter Roeck 242339ef3112SGuenter Roeck if (class == NULL || IS_ERR(class)) 242439ef3112SGuenter Roeck goto error; 242539ef3112SGuenter Roeck 242639ef3112SGuenter Roeck dev = kzalloc(sizeof(*dev), GFP_KERNEL); 242739ef3112SGuenter Roeck if (!dev) { 242839ef3112SGuenter Roeck retval = -ENOMEM; 242939ef3112SGuenter Roeck goto error; 243039ef3112SGuenter Roeck } 243139ef3112SGuenter Roeck 2432bbc780f8SDavid Herrmann device_initialize(dev); 243339ef3112SGuenter Roeck dev->devt = devt; 243439ef3112SGuenter Roeck dev->class = class; 243539ef3112SGuenter Roeck dev->parent = parent; 243639ef3112SGuenter Roeck dev->groups = groups; 243739ef3112SGuenter Roeck dev->release = device_create_release; 243839ef3112SGuenter Roeck dev_set_drvdata(dev, drvdata); 243939ef3112SGuenter Roeck 244039ef3112SGuenter Roeck retval = kobject_set_name_vargs(&dev->kobj, fmt, args); 244139ef3112SGuenter Roeck if (retval) 244239ef3112SGuenter Roeck goto error; 244339ef3112SGuenter Roeck 2444bbc780f8SDavid Herrmann retval = device_add(dev); 244539ef3112SGuenter Roeck if (retval) 244639ef3112SGuenter Roeck goto error; 244739ef3112SGuenter Roeck 244839ef3112SGuenter Roeck return dev; 244939ef3112SGuenter Roeck 245039ef3112SGuenter Roeck error: 245139ef3112SGuenter Roeck put_device(dev); 245239ef3112SGuenter Roeck return ERR_PTR(retval); 245339ef3112SGuenter Roeck } 245439ef3112SGuenter Roeck 245523681e47SGreg Kroah-Hartman /** 24568882b394SGreg Kroah-Hartman * device_create_vargs - creates a device and registers it with sysfs 24578882b394SGreg Kroah-Hartman * @class: pointer to the struct class that this device should be registered to 24588882b394SGreg Kroah-Hartman * @parent: pointer to the parent struct device of this new device, if any 24598882b394SGreg Kroah-Hartman * @devt: the dev_t for the char device to be added 24608882b394SGreg Kroah-Hartman * @drvdata: the data to be added to the device for callbacks 24618882b394SGreg Kroah-Hartman * @fmt: string for the device's name 24628882b394SGreg Kroah-Hartman * @args: va_list for the device's name 24638882b394SGreg Kroah-Hartman * 24648882b394SGreg Kroah-Hartman * This function can be used by char device classes. A struct device 24658882b394SGreg Kroah-Hartman * will be created in sysfs, registered to the specified class. 24668882b394SGreg Kroah-Hartman * 24678882b394SGreg Kroah-Hartman * A "dev" file will be created, showing the dev_t for the device, if 24688882b394SGreg Kroah-Hartman * the dev_t is not 0,0. 24698882b394SGreg Kroah-Hartman * If a pointer to a parent struct device is passed in, the newly created 24708882b394SGreg Kroah-Hartman * struct device will be a child of that device in sysfs. 24718882b394SGreg Kroah-Hartman * The pointer to the struct device will be returned from the call. 24728882b394SGreg Kroah-Hartman * Any further sysfs files that might be required can be created using this 24738882b394SGreg Kroah-Hartman * pointer. 24748882b394SGreg Kroah-Hartman * 2475f0eae0edSJani Nikula * Returns &struct device pointer on success, or ERR_PTR() on error. 2476f0eae0edSJani Nikula * 24778882b394SGreg Kroah-Hartman * Note: the struct class passed to this function must have previously 24788882b394SGreg Kroah-Hartman * been created with a call to class_create(). 24798882b394SGreg Kroah-Hartman */ 24808882b394SGreg Kroah-Hartman struct device *device_create_vargs(struct class *class, struct device *parent, 24818882b394SGreg Kroah-Hartman dev_t devt, void *drvdata, const char *fmt, 24828882b394SGreg Kroah-Hartman va_list args) 24838882b394SGreg Kroah-Hartman { 248439ef3112SGuenter Roeck return device_create_groups_vargs(class, parent, devt, drvdata, NULL, 248539ef3112SGuenter Roeck fmt, args); 24868882b394SGreg Kroah-Hartman } 24878882b394SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_create_vargs); 24888882b394SGreg Kroah-Hartman 24898882b394SGreg Kroah-Hartman /** 24904e106739SGreg Kroah-Hartman * device_create - creates a device and registers it with sysfs 24918882b394SGreg Kroah-Hartman * @class: pointer to the struct class that this device should be registered to 24928882b394SGreg Kroah-Hartman * @parent: pointer to the parent struct device of this new device, if any 24938882b394SGreg Kroah-Hartman * @devt: the dev_t for the char device to be added 24948882b394SGreg Kroah-Hartman * @drvdata: the data to be added to the device for callbacks 24958882b394SGreg Kroah-Hartman * @fmt: string for the device's name 24968882b394SGreg Kroah-Hartman * 24978882b394SGreg Kroah-Hartman * This function can be used by char device classes. A struct device 24988882b394SGreg Kroah-Hartman * will be created in sysfs, registered to the specified class. 24998882b394SGreg Kroah-Hartman * 25008882b394SGreg Kroah-Hartman * A "dev" file will be created, showing the dev_t for the device, if 25018882b394SGreg Kroah-Hartman * the dev_t is not 0,0. 25028882b394SGreg Kroah-Hartman * If a pointer to a parent struct device is passed in, the newly created 25038882b394SGreg Kroah-Hartman * struct device will be a child of that device in sysfs. 25048882b394SGreg Kroah-Hartman * The pointer to the struct device will be returned from the call. 25058882b394SGreg Kroah-Hartman * Any further sysfs files that might be required can be created using this 25068882b394SGreg Kroah-Hartman * pointer. 25078882b394SGreg Kroah-Hartman * 2508f0eae0edSJani Nikula * Returns &struct device pointer on success, or ERR_PTR() on error. 2509f0eae0edSJani Nikula * 25108882b394SGreg Kroah-Hartman * Note: the struct class passed to this function must have previously 25118882b394SGreg Kroah-Hartman * been created with a call to class_create(). 25128882b394SGreg Kroah-Hartman */ 25134e106739SGreg Kroah-Hartman struct device *device_create(struct class *class, struct device *parent, 25144e106739SGreg Kroah-Hartman dev_t devt, void *drvdata, const char *fmt, ...) 25158882b394SGreg Kroah-Hartman { 25168882b394SGreg Kroah-Hartman va_list vargs; 25178882b394SGreg Kroah-Hartman struct device *dev; 25188882b394SGreg Kroah-Hartman 25198882b394SGreg Kroah-Hartman va_start(vargs, fmt); 25208882b394SGreg Kroah-Hartman dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs); 25218882b394SGreg Kroah-Hartman va_end(vargs); 25228882b394SGreg Kroah-Hartman return dev; 25238882b394SGreg Kroah-Hartman } 25244e106739SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_create); 25258882b394SGreg Kroah-Hartman 252639ef3112SGuenter Roeck /** 252739ef3112SGuenter Roeck * device_create_with_groups - creates a device and registers it with sysfs 252839ef3112SGuenter Roeck * @class: pointer to the struct class that this device should be registered to 252939ef3112SGuenter Roeck * @parent: pointer to the parent struct device of this new device, if any 253039ef3112SGuenter Roeck * @devt: the dev_t for the char device to be added 253139ef3112SGuenter Roeck * @drvdata: the data to be added to the device for callbacks 253239ef3112SGuenter Roeck * @groups: NULL-terminated list of attribute groups to be created 253339ef3112SGuenter Roeck * @fmt: string for the device's name 253439ef3112SGuenter Roeck * 253539ef3112SGuenter Roeck * This function can be used by char device classes. A struct device 253639ef3112SGuenter Roeck * will be created in sysfs, registered to the specified class. 253739ef3112SGuenter Roeck * Additional attributes specified in the groups parameter will also 253839ef3112SGuenter Roeck * be created automatically. 253939ef3112SGuenter Roeck * 254039ef3112SGuenter Roeck * A "dev" file will be created, showing the dev_t for the device, if 254139ef3112SGuenter Roeck * the dev_t is not 0,0. 254239ef3112SGuenter Roeck * If a pointer to a parent struct device is passed in, the newly created 254339ef3112SGuenter Roeck * struct device will be a child of that device in sysfs. 254439ef3112SGuenter Roeck * The pointer to the struct device will be returned from the call. 254539ef3112SGuenter Roeck * Any further sysfs files that might be required can be created using this 254639ef3112SGuenter Roeck * pointer. 254739ef3112SGuenter Roeck * 254839ef3112SGuenter Roeck * Returns &struct device pointer on success, or ERR_PTR() on error. 254939ef3112SGuenter Roeck * 255039ef3112SGuenter Roeck * Note: the struct class passed to this function must have previously 255139ef3112SGuenter Roeck * been created with a call to class_create(). 255239ef3112SGuenter Roeck */ 255339ef3112SGuenter Roeck struct device *device_create_with_groups(struct class *class, 255439ef3112SGuenter Roeck struct device *parent, dev_t devt, 255539ef3112SGuenter Roeck void *drvdata, 255639ef3112SGuenter Roeck const struct attribute_group **groups, 255739ef3112SGuenter Roeck const char *fmt, ...) 255839ef3112SGuenter Roeck { 255939ef3112SGuenter Roeck va_list vargs; 256039ef3112SGuenter Roeck struct device *dev; 256139ef3112SGuenter Roeck 256239ef3112SGuenter Roeck va_start(vargs, fmt); 256339ef3112SGuenter Roeck dev = device_create_groups_vargs(class, parent, devt, drvdata, groups, 256439ef3112SGuenter Roeck fmt, vargs); 256539ef3112SGuenter Roeck va_end(vargs); 256639ef3112SGuenter Roeck return dev; 256739ef3112SGuenter Roeck } 256839ef3112SGuenter Roeck EXPORT_SYMBOL_GPL(device_create_with_groups); 256939ef3112SGuenter Roeck 25709f3b795aSMichał Mirosław static int __match_devt(struct device *dev, const void *data) 257123681e47SGreg Kroah-Hartman { 25729f3b795aSMichał Mirosław const dev_t *devt = data; 257323681e47SGreg Kroah-Hartman 2574cd35449bSDave Young return dev->devt == *devt; 2575775b64d2SRafael J. Wysocki } 257623681e47SGreg Kroah-Hartman 2577775b64d2SRafael J. Wysocki /** 2578775b64d2SRafael J. Wysocki * device_destroy - removes a device that was created with device_create() 2579775b64d2SRafael J. Wysocki * @class: pointer to the struct class that this device was registered with 2580775b64d2SRafael J. Wysocki * @devt: the dev_t of the device that was previously registered 2581775b64d2SRafael J. Wysocki * 2582775b64d2SRafael J. Wysocki * This call unregisters and cleans up a device that was created with a 2583775b64d2SRafael J. Wysocki * call to device_create(). 2584775b64d2SRafael J. Wysocki */ 2585775b64d2SRafael J. Wysocki void device_destroy(struct class *class, dev_t devt) 2586775b64d2SRafael J. Wysocki { 2587775b64d2SRafael J. Wysocki struct device *dev; 2588775b64d2SRafael J. Wysocki 2589695794aeSGreg Kroah-Hartman dev = class_find_device(class, NULL, &devt, __match_devt); 2590cd35449bSDave Young if (dev) { 2591cd35449bSDave Young put_device(dev); 259223681e47SGreg Kroah-Hartman device_unregister(dev); 259323681e47SGreg Kroah-Hartman } 2594cd35449bSDave Young } 259523681e47SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_destroy); 2596a2de48caSGreg Kroah-Hartman 2597a2de48caSGreg Kroah-Hartman /** 2598a2de48caSGreg Kroah-Hartman * device_rename - renames a device 2599a2de48caSGreg Kroah-Hartman * @dev: the pointer to the struct device to be renamed 2600a2de48caSGreg Kroah-Hartman * @new_name: the new name of the device 2601030c1d2bSEric W. Biederman * 2602030c1d2bSEric W. Biederman * It is the responsibility of the caller to provide mutual 2603030c1d2bSEric W. Biederman * exclusion between two different calls of device_rename 2604030c1d2bSEric W. Biederman * on the same device to ensure that new_name is valid and 2605030c1d2bSEric W. Biederman * won't conflict with other devices. 2606c6c0ac66SMichael Ellerman * 2607a5462516STimur Tabi * Note: Don't call this function. Currently, the networking layer calls this 2608a5462516STimur Tabi * function, but that will change. The following text from Kay Sievers offers 2609a5462516STimur Tabi * some insight: 2610a5462516STimur Tabi * 2611a5462516STimur Tabi * Renaming devices is racy at many levels, symlinks and other stuff are not 2612a5462516STimur Tabi * replaced atomically, and you get a "move" uevent, but it's not easy to 2613a5462516STimur Tabi * connect the event to the old and new device. Device nodes are not renamed at 2614a5462516STimur Tabi * all, there isn't even support for that in the kernel now. 2615a5462516STimur Tabi * 2616a5462516STimur Tabi * In the meantime, during renaming, your target name might be taken by another 2617a5462516STimur Tabi * driver, creating conflicts. Or the old name is taken directly after you 2618a5462516STimur Tabi * renamed it -- then you get events for the same DEVPATH, before you even see 2619a5462516STimur Tabi * the "move" event. It's just a mess, and nothing new should ever rely on 2620a5462516STimur Tabi * kernel device renaming. Besides that, it's not even implemented now for 2621a5462516STimur Tabi * other things than (driver-core wise very simple) network devices. 2622a5462516STimur Tabi * 2623a5462516STimur Tabi * We are currently about to change network renaming in udev to completely 2624a5462516STimur Tabi * disallow renaming of devices in the same namespace as the kernel uses, 2625a5462516STimur Tabi * because we can't solve the problems properly, that arise with swapping names 2626a5462516STimur Tabi * of multiple interfaces without races. Means, renaming of eth[0-9]* will only 2627a5462516STimur Tabi * be allowed to some other name than eth[0-9]*, for the aforementioned 2628a5462516STimur Tabi * reasons. 2629a5462516STimur Tabi * 2630a5462516STimur Tabi * Make up a "real" name in the driver before you register anything, or add 2631a5462516STimur Tabi * some other attributes for userspace to find the device, or use udev to add 2632a5462516STimur Tabi * symlinks -- but never rename kernel devices later, it's a complete mess. We 2633a5462516STimur Tabi * don't even want to get into that and try to implement the missing pieces in 2634a5462516STimur Tabi * the core. We really have other pieces to fix in the driver core mess. :) 2635a2de48caSGreg Kroah-Hartman */ 26366937e8f8SJohannes Berg int device_rename(struct device *dev, const char *new_name) 2637a2de48caSGreg Kroah-Hartman { 26384b30ee58STejun Heo struct kobject *kobj = &dev->kobj; 26392ee97cafSCornelia Huck char *old_device_name = NULL; 2640a2de48caSGreg Kroah-Hartman int error; 2641a2de48caSGreg Kroah-Hartman 2642a2de48caSGreg Kroah-Hartman dev = get_device(dev); 2643a2de48caSGreg Kroah-Hartman if (!dev) 2644a2de48caSGreg Kroah-Hartman return -EINVAL; 2645a2de48caSGreg Kroah-Hartman 264669df7533Sethan.zhao dev_dbg(dev, "renaming to %s\n", new_name); 2647a2de48caSGreg Kroah-Hartman 26481fa5ae85SKay Sievers old_device_name = kstrdup(dev_name(dev), GFP_KERNEL); 26492ee97cafSCornelia Huck if (!old_device_name) { 2650952ab431SJesper Juhl error = -ENOMEM; 26512ee97cafSCornelia Huck goto out; 2652952ab431SJesper Juhl } 2653a2de48caSGreg Kroah-Hartman 2654f349cf34SEric W. Biederman if (dev->class) { 26554b30ee58STejun Heo error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj, 26564b30ee58STejun Heo kobj, old_device_name, 26574b30ee58STejun Heo new_name, kobject_namespace(kobj)); 2658f349cf34SEric W. Biederman if (error) 2659f349cf34SEric W. Biederman goto out; 2660f349cf34SEric W. Biederman } 266139aba963SKay Sievers 26624b30ee58STejun Heo error = kobject_rename(kobj, new_name); 26631fa5ae85SKay Sievers if (error) 26642ee97cafSCornelia Huck goto out; 2665a2de48caSGreg Kroah-Hartman 26662ee97cafSCornelia Huck out: 2667a2de48caSGreg Kroah-Hartman put_device(dev); 2668a2de48caSGreg Kroah-Hartman 26692ee97cafSCornelia Huck kfree(old_device_name); 2670a2de48caSGreg Kroah-Hartman 2671a2de48caSGreg Kroah-Hartman return error; 2672a2de48caSGreg Kroah-Hartman } 2673a2807dbcSJohannes Berg EXPORT_SYMBOL_GPL(device_rename); 26748a82472fSCornelia Huck 26758a82472fSCornelia Huck static int device_move_class_links(struct device *dev, 26768a82472fSCornelia Huck struct device *old_parent, 26778a82472fSCornelia Huck struct device *new_parent) 26788a82472fSCornelia Huck { 2679f7f3461dSGreg Kroah-Hartman int error = 0; 26808a82472fSCornelia Huck 2681f7f3461dSGreg Kroah-Hartman if (old_parent) 2682f7f3461dSGreg Kroah-Hartman sysfs_remove_link(&dev->kobj, "device"); 2683f7f3461dSGreg Kroah-Hartman if (new_parent) 2684f7f3461dSGreg Kroah-Hartman error = sysfs_create_link(&dev->kobj, &new_parent->kobj, 2685f7f3461dSGreg Kroah-Hartman "device"); 2686f7f3461dSGreg Kroah-Hartman return error; 26878a82472fSCornelia Huck } 26888a82472fSCornelia Huck 26898a82472fSCornelia Huck /** 26908a82472fSCornelia Huck * device_move - moves a device to a new parent 26918a82472fSCornelia Huck * @dev: the pointer to the struct device to be moved 2692c744aeaeSCornelia Huck * @new_parent: the new parent of the device (can by NULL) 2693ffa6a705SCornelia Huck * @dpm_order: how to reorder the dpm_list 26948a82472fSCornelia Huck */ 2695ffa6a705SCornelia Huck int device_move(struct device *dev, struct device *new_parent, 2696ffa6a705SCornelia Huck enum dpm_order dpm_order) 26978a82472fSCornelia Huck { 26988a82472fSCornelia Huck int error; 26998a82472fSCornelia Huck struct device *old_parent; 2700c744aeaeSCornelia Huck struct kobject *new_parent_kobj; 27018a82472fSCornelia Huck 27028a82472fSCornelia Huck dev = get_device(dev); 27038a82472fSCornelia Huck if (!dev) 27048a82472fSCornelia Huck return -EINVAL; 27058a82472fSCornelia Huck 2706ffa6a705SCornelia Huck device_pm_lock(); 27078a82472fSCornelia Huck new_parent = get_device(new_parent); 2708c744aeaeSCornelia Huck new_parent_kobj = get_device_parent(dev, new_parent); 270984d0c27dSTetsuo Handa if (IS_ERR(new_parent_kobj)) { 271084d0c27dSTetsuo Handa error = PTR_ERR(new_parent_kobj); 271184d0c27dSTetsuo Handa put_device(new_parent); 271284d0c27dSTetsuo Handa goto out; 271384d0c27dSTetsuo Handa } 271463b6971aSCornelia Huck 27151e0b2cf9SKay Sievers pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev), 27161e0b2cf9SKay Sievers __func__, new_parent ? dev_name(new_parent) : "<NULL>"); 2717c744aeaeSCornelia Huck error = kobject_move(&dev->kobj, new_parent_kobj); 27188a82472fSCornelia Huck if (error) { 271963b6971aSCornelia Huck cleanup_glue_dir(dev, new_parent_kobj); 27208a82472fSCornelia Huck put_device(new_parent); 27218a82472fSCornelia Huck goto out; 27228a82472fSCornelia Huck } 27238a82472fSCornelia Huck old_parent = dev->parent; 27248a82472fSCornelia Huck dev->parent = new_parent; 27258a82472fSCornelia Huck if (old_parent) 2726f791b8c8SGreg Kroah-Hartman klist_remove(&dev->p->knode_parent); 27270d358f22SYinghai Lu if (new_parent) { 2728f791b8c8SGreg Kroah-Hartman klist_add_tail(&dev->p->knode_parent, 2729f791b8c8SGreg Kroah-Hartman &new_parent->p->klist_children); 27300d358f22SYinghai Lu set_dev_node(dev, dev_to_node(new_parent)); 27310d358f22SYinghai Lu } 27320d358f22SYinghai Lu 2733bdd4034dSRabin Vincent if (dev->class) { 27348a82472fSCornelia Huck error = device_move_class_links(dev, old_parent, new_parent); 27358a82472fSCornelia Huck if (error) { 27368a82472fSCornelia Huck /* We ignore errors on cleanup since we're hosed anyway... */ 27378a82472fSCornelia Huck device_move_class_links(dev, new_parent, old_parent); 27388a82472fSCornelia Huck if (!kobject_move(&dev->kobj, &old_parent->kobj)) { 2739c744aeaeSCornelia Huck if (new_parent) 2740f791b8c8SGreg Kroah-Hartman klist_remove(&dev->p->knode_parent); 27410d358f22SYinghai Lu dev->parent = old_parent; 27420d358f22SYinghai Lu if (old_parent) { 2743f791b8c8SGreg Kroah-Hartman klist_add_tail(&dev->p->knode_parent, 2744f791b8c8SGreg Kroah-Hartman &old_parent->p->klist_children); 27450d358f22SYinghai Lu set_dev_node(dev, dev_to_node(old_parent)); 27460d358f22SYinghai Lu } 27478a82472fSCornelia Huck } 274863b6971aSCornelia Huck cleanup_glue_dir(dev, new_parent_kobj); 27498a82472fSCornelia Huck put_device(new_parent); 27508a82472fSCornelia Huck goto out; 27518a82472fSCornelia Huck } 2752bdd4034dSRabin Vincent } 2753ffa6a705SCornelia Huck switch (dpm_order) { 2754ffa6a705SCornelia Huck case DPM_ORDER_NONE: 2755ffa6a705SCornelia Huck break; 2756ffa6a705SCornelia Huck case DPM_ORDER_DEV_AFTER_PARENT: 2757ffa6a705SCornelia Huck device_pm_move_after(dev, new_parent); 275852cdbdd4SGrygorii Strashko devices_kset_move_after(dev, new_parent); 2759ffa6a705SCornelia Huck break; 2760ffa6a705SCornelia Huck case DPM_ORDER_PARENT_BEFORE_DEV: 2761ffa6a705SCornelia Huck device_pm_move_before(new_parent, dev); 276252cdbdd4SGrygorii Strashko devices_kset_move_before(new_parent, dev); 2763ffa6a705SCornelia Huck break; 2764ffa6a705SCornelia Huck case DPM_ORDER_DEV_LAST: 2765ffa6a705SCornelia Huck device_pm_move_last(dev); 276652cdbdd4SGrygorii Strashko devices_kset_move_last(dev); 2767ffa6a705SCornelia Huck break; 2768ffa6a705SCornelia Huck } 2769bdd4034dSRabin Vincent 27708a82472fSCornelia Huck put_device(old_parent); 27718a82472fSCornelia Huck out: 2772ffa6a705SCornelia Huck device_pm_unlock(); 27738a82472fSCornelia Huck put_device(dev); 27748a82472fSCornelia Huck return error; 27758a82472fSCornelia Huck } 27768a82472fSCornelia Huck EXPORT_SYMBOL_GPL(device_move); 277737b0c020SGreg Kroah-Hartman 277837b0c020SGreg Kroah-Hartman /** 277937b0c020SGreg Kroah-Hartman * device_shutdown - call ->shutdown() on each device to shutdown. 278037b0c020SGreg Kroah-Hartman */ 278137b0c020SGreg Kroah-Hartman void device_shutdown(void) 278237b0c020SGreg Kroah-Hartman { 2783f123db8eSBenson Leung struct device *dev, *parent; 278437b0c020SGreg Kroah-Hartman 27856245838fSHugh Daschbach spin_lock(&devices_kset->list_lock); 27866245838fSHugh Daschbach /* 27876245838fSHugh Daschbach * Walk the devices list backward, shutting down each in turn. 27886245838fSHugh Daschbach * Beware that device unplug events may also start pulling 27896245838fSHugh Daschbach * devices offline, even as the system is shutting down. 27906245838fSHugh Daschbach */ 27916245838fSHugh Daschbach while (!list_empty(&devices_kset->list)) { 27926245838fSHugh Daschbach dev = list_entry(devices_kset->list.prev, struct device, 27936245838fSHugh Daschbach kobj.entry); 2794d1c6c030SMing Lei 2795d1c6c030SMing Lei /* 2796d1c6c030SMing Lei * hold reference count of device's parent to 2797d1c6c030SMing Lei * prevent it from being freed because parent's 2798d1c6c030SMing Lei * lock is to be held 2799d1c6c030SMing Lei */ 2800f123db8eSBenson Leung parent = get_device(dev->parent); 28016245838fSHugh Daschbach get_device(dev); 28026245838fSHugh Daschbach /* 28036245838fSHugh Daschbach * Make sure the device is off the kset list, in the 28046245838fSHugh Daschbach * event that dev->*->shutdown() doesn't remove it. 28056245838fSHugh Daschbach */ 28066245838fSHugh Daschbach list_del_init(&dev->kobj.entry); 28076245838fSHugh Daschbach spin_unlock(&devices_kset->list_lock); 2808fe6b91f4SAlan Stern 2809d1c6c030SMing Lei /* hold lock to avoid race with probe/release */ 2810f123db8eSBenson Leung if (parent) 2811f123db8eSBenson Leung device_lock(parent); 2812d1c6c030SMing Lei device_lock(dev); 2813d1c6c030SMing Lei 2814fe6b91f4SAlan Stern /* Don't allow any more runtime suspends */ 2815fe6b91f4SAlan Stern pm_runtime_get_noresume(dev); 2816fe6b91f4SAlan Stern pm_runtime_barrier(dev); 28176245838fSHugh Daschbach 28187521621eSMichal Suchanek if (dev->class && dev->class->shutdown_pre) { 2819f77af151SJosh Zimmerman if (initcall_debug) 28207521621eSMichal Suchanek dev_info(dev, "shutdown_pre\n"); 28217521621eSMichal Suchanek dev->class->shutdown_pre(dev); 28227521621eSMichal Suchanek } 28237521621eSMichal Suchanek if (dev->bus && dev->bus->shutdown) { 28240246c4faSShuoX Liu if (initcall_debug) 28250246c4faSShuoX Liu dev_info(dev, "shutdown\n"); 282637b0c020SGreg Kroah-Hartman dev->bus->shutdown(dev); 282737b0c020SGreg Kroah-Hartman } else if (dev->driver && dev->driver->shutdown) { 28280246c4faSShuoX Liu if (initcall_debug) 28290246c4faSShuoX Liu dev_info(dev, "shutdown\n"); 283037b0c020SGreg Kroah-Hartman dev->driver->shutdown(dev); 283137b0c020SGreg Kroah-Hartman } 2832d1c6c030SMing Lei 2833d1c6c030SMing Lei device_unlock(dev); 2834f123db8eSBenson Leung if (parent) 2835f123db8eSBenson Leung device_unlock(parent); 2836d1c6c030SMing Lei 28376245838fSHugh Daschbach put_device(dev); 2838f123db8eSBenson Leung put_device(parent); 28396245838fSHugh Daschbach 28406245838fSHugh Daschbach spin_lock(&devices_kset->list_lock); 284137b0c020SGreg Kroah-Hartman } 28426245838fSHugh Daschbach spin_unlock(&devices_kset->list_lock); 284337b0c020SGreg Kroah-Hartman } 284499bcf217SJoe Perches 284599bcf217SJoe Perches /* 284699bcf217SJoe Perches * Device logging functions 284799bcf217SJoe Perches */ 284899bcf217SJoe Perches 284999bcf217SJoe Perches #ifdef CONFIG_PRINTK 2850666f355fSJoe Perches static int 2851666f355fSJoe Perches create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) 285299bcf217SJoe Perches { 2853c4e00daaSKay Sievers const char *subsys; 2854798efc60SJoe Perches size_t pos = 0; 285599bcf217SJoe Perches 2856c4e00daaSKay Sievers if (dev->class) 2857c4e00daaSKay Sievers subsys = dev->class->name; 2858c4e00daaSKay Sievers else if (dev->bus) 2859c4e00daaSKay Sievers subsys = dev->bus->name; 2860c4e00daaSKay Sievers else 2861798efc60SJoe Perches return 0; 2862c4e00daaSKay Sievers 2863798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys); 2864655e5b7cSBen Hutchings if (pos >= hdrlen) 2865655e5b7cSBen Hutchings goto overflow; 2866c4e00daaSKay Sievers 2867c4e00daaSKay Sievers /* 2868c4e00daaSKay Sievers * Add device identifier DEVICE=: 2869c4e00daaSKay Sievers * b12:8 block dev_t 2870c4e00daaSKay Sievers * c127:3 char dev_t 2871c4e00daaSKay Sievers * n8 netdev ifindex 2872c4e00daaSKay Sievers * +sound:card0 subsystem:devname 2873c4e00daaSKay Sievers */ 2874c4e00daaSKay Sievers if (MAJOR(dev->devt)) { 2875c4e00daaSKay Sievers char c; 2876c4e00daaSKay Sievers 2877c4e00daaSKay Sievers if (strcmp(subsys, "block") == 0) 2878c4e00daaSKay Sievers c = 'b'; 2879c4e00daaSKay Sievers else 2880c4e00daaSKay Sievers c = 'c'; 2881798efc60SJoe Perches pos++; 2882798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, 2883c4e00daaSKay Sievers "DEVICE=%c%u:%u", 2884c4e00daaSKay Sievers c, MAJOR(dev->devt), MINOR(dev->devt)); 2885c4e00daaSKay Sievers } else if (strcmp(subsys, "net") == 0) { 2886c4e00daaSKay Sievers struct net_device *net = to_net_dev(dev); 2887c4e00daaSKay Sievers 2888798efc60SJoe Perches pos++; 2889798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, 2890c4e00daaSKay Sievers "DEVICE=n%u", net->ifindex); 2891c4e00daaSKay Sievers } else { 2892798efc60SJoe Perches pos++; 2893798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, 2894c4e00daaSKay Sievers "DEVICE=+%s:%s", subsys, dev_name(dev)); 2895c4e00daaSKay Sievers } 2896af7f2158SJim Cromie 2897655e5b7cSBen Hutchings if (pos >= hdrlen) 2898655e5b7cSBen Hutchings goto overflow; 2899655e5b7cSBen Hutchings 2900798efc60SJoe Perches return pos; 2901655e5b7cSBen Hutchings 2902655e5b7cSBen Hutchings overflow: 2903655e5b7cSBen Hutchings dev_WARN(dev, "device/subsystem name too long"); 2904655e5b7cSBen Hutchings return 0; 290599bcf217SJoe Perches } 2906798efc60SJoe Perches 290705e4e5b8SJoe Perches int dev_vprintk_emit(int level, const struct device *dev, 290805e4e5b8SJoe Perches const char *fmt, va_list args) 290905e4e5b8SJoe Perches { 291005e4e5b8SJoe Perches char hdr[128]; 291105e4e5b8SJoe Perches size_t hdrlen; 291205e4e5b8SJoe Perches 291305e4e5b8SJoe Perches hdrlen = create_syslog_header(dev, hdr, sizeof(hdr)); 291405e4e5b8SJoe Perches 291505e4e5b8SJoe Perches return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args); 291605e4e5b8SJoe Perches } 291705e4e5b8SJoe Perches EXPORT_SYMBOL(dev_vprintk_emit); 291805e4e5b8SJoe Perches 291905e4e5b8SJoe Perches int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...) 292005e4e5b8SJoe Perches { 292105e4e5b8SJoe Perches va_list args; 292205e4e5b8SJoe Perches int r; 292305e4e5b8SJoe Perches 292405e4e5b8SJoe Perches va_start(args, fmt); 292505e4e5b8SJoe Perches 292605e4e5b8SJoe Perches r = dev_vprintk_emit(level, dev, fmt, args); 292705e4e5b8SJoe Perches 292805e4e5b8SJoe Perches va_end(args); 292905e4e5b8SJoe Perches 293005e4e5b8SJoe Perches return r; 293105e4e5b8SJoe Perches } 293205e4e5b8SJoe Perches EXPORT_SYMBOL(dev_printk_emit); 293305e4e5b8SJoe Perches 2934d1f1052cSJoe Perches static void __dev_printk(const char *level, const struct device *dev, 2935798efc60SJoe Perches struct va_format *vaf) 2936798efc60SJoe Perches { 2937d1f1052cSJoe Perches if (dev) 2938d1f1052cSJoe Perches dev_printk_emit(level[1] - '0', dev, "%s %s: %pV", 2939798efc60SJoe Perches dev_driver_string(dev), dev_name(dev), vaf); 2940d1f1052cSJoe Perches else 2941d1f1052cSJoe Perches printk("%s(NULL device *): %pV", level, vaf); 2942798efc60SJoe Perches } 294399bcf217SJoe Perches 2944d1f1052cSJoe Perches void dev_printk(const char *level, const struct device *dev, 294599bcf217SJoe Perches const char *fmt, ...) 294699bcf217SJoe Perches { 294799bcf217SJoe Perches struct va_format vaf; 294899bcf217SJoe Perches va_list args; 294999bcf217SJoe Perches 295099bcf217SJoe Perches va_start(args, fmt); 295199bcf217SJoe Perches 295299bcf217SJoe Perches vaf.fmt = fmt; 295399bcf217SJoe Perches vaf.va = &args; 295499bcf217SJoe Perches 2955d1f1052cSJoe Perches __dev_printk(level, dev, &vaf); 2956798efc60SJoe Perches 295799bcf217SJoe Perches va_end(args); 295899bcf217SJoe Perches } 295999bcf217SJoe Perches EXPORT_SYMBOL(dev_printk); 296099bcf217SJoe Perches 296199bcf217SJoe Perches #define define_dev_printk_level(func, kern_level) \ 2962d1f1052cSJoe Perches void func(const struct device *dev, const char *fmt, ...) \ 296399bcf217SJoe Perches { \ 296499bcf217SJoe Perches struct va_format vaf; \ 296599bcf217SJoe Perches va_list args; \ 296699bcf217SJoe Perches \ 296799bcf217SJoe Perches va_start(args, fmt); \ 296899bcf217SJoe Perches \ 296999bcf217SJoe Perches vaf.fmt = fmt; \ 297099bcf217SJoe Perches vaf.va = &args; \ 297199bcf217SJoe Perches \ 2972d1f1052cSJoe Perches __dev_printk(kern_level, dev, &vaf); \ 2973798efc60SJoe Perches \ 297499bcf217SJoe Perches va_end(args); \ 297599bcf217SJoe Perches } \ 297699bcf217SJoe Perches EXPORT_SYMBOL(func); 297799bcf217SJoe Perches 297899bcf217SJoe Perches define_dev_printk_level(dev_emerg, KERN_EMERG); 297999bcf217SJoe Perches define_dev_printk_level(dev_alert, KERN_ALERT); 298099bcf217SJoe Perches define_dev_printk_level(dev_crit, KERN_CRIT); 298199bcf217SJoe Perches define_dev_printk_level(dev_err, KERN_ERR); 298299bcf217SJoe Perches define_dev_printk_level(dev_warn, KERN_WARNING); 298399bcf217SJoe Perches define_dev_printk_level(dev_notice, KERN_NOTICE); 298499bcf217SJoe Perches define_dev_printk_level(_dev_info, KERN_INFO); 298599bcf217SJoe Perches 298699bcf217SJoe Perches #endif 298797badf87SRafael J. Wysocki 298897badf87SRafael J. Wysocki static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) 298997badf87SRafael J. Wysocki { 299097badf87SRafael J. Wysocki return fwnode && !IS_ERR(fwnode->secondary); 299197badf87SRafael J. Wysocki } 299297badf87SRafael J. Wysocki 299397badf87SRafael J. Wysocki /** 299497badf87SRafael J. Wysocki * set_primary_fwnode - Change the primary firmware node of a given device. 299597badf87SRafael J. Wysocki * @dev: Device to handle. 299697badf87SRafael J. Wysocki * @fwnode: New primary firmware node of the device. 299797badf87SRafael J. Wysocki * 299897badf87SRafael J. Wysocki * Set the device's firmware node pointer to @fwnode, but if a secondary 299997badf87SRafael J. Wysocki * firmware node of the device is present, preserve it. 300097badf87SRafael J. Wysocki */ 300197badf87SRafael J. Wysocki void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) 300297badf87SRafael J. Wysocki { 300397badf87SRafael J. Wysocki if (fwnode) { 300497badf87SRafael J. Wysocki struct fwnode_handle *fn = dev->fwnode; 300597badf87SRafael J. Wysocki 300697badf87SRafael J. Wysocki if (fwnode_is_primary(fn)) 300797badf87SRafael J. Wysocki fn = fn->secondary; 300897badf87SRafael J. Wysocki 300955f89a8aSMika Westerberg if (fn) { 301055f89a8aSMika Westerberg WARN_ON(fwnode->secondary); 301197badf87SRafael J. Wysocki fwnode->secondary = fn; 301255f89a8aSMika Westerberg } 301397badf87SRafael J. Wysocki dev->fwnode = fwnode; 301497badf87SRafael J. Wysocki } else { 301597badf87SRafael J. Wysocki dev->fwnode = fwnode_is_primary(dev->fwnode) ? 301697badf87SRafael J. Wysocki dev->fwnode->secondary : NULL; 301797badf87SRafael J. Wysocki } 301897badf87SRafael J. Wysocki } 301997badf87SRafael J. Wysocki EXPORT_SYMBOL_GPL(set_primary_fwnode); 302097badf87SRafael J. Wysocki 302197badf87SRafael J. Wysocki /** 302297badf87SRafael J. Wysocki * set_secondary_fwnode - Change the secondary firmware node of a given device. 302397badf87SRafael J. Wysocki * @dev: Device to handle. 302497badf87SRafael J. Wysocki * @fwnode: New secondary firmware node of the device. 302597badf87SRafael J. Wysocki * 302697badf87SRafael J. Wysocki * If a primary firmware node of the device is present, set its secondary 302797badf87SRafael J. Wysocki * pointer to @fwnode. Otherwise, set the device's firmware node pointer to 302897badf87SRafael J. Wysocki * @fwnode. 302997badf87SRafael J. Wysocki */ 303097badf87SRafael J. Wysocki void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode) 303197badf87SRafael J. Wysocki { 303297badf87SRafael J. Wysocki if (fwnode) 303397badf87SRafael J. Wysocki fwnode->secondary = ERR_PTR(-ENODEV); 303497badf87SRafael J. Wysocki 303597badf87SRafael J. Wysocki if (fwnode_is_primary(dev->fwnode)) 303697badf87SRafael J. Wysocki dev->fwnode->secondary = fwnode; 303797badf87SRafael J. Wysocki else 303897badf87SRafael J. Wysocki dev->fwnode = fwnode; 303997badf87SRafael J. Wysocki } 30404e75e1d7SJohan Hovold 30414e75e1d7SJohan Hovold /** 30424e75e1d7SJohan Hovold * device_set_of_node_from_dev - reuse device-tree node of another device 30434e75e1d7SJohan Hovold * @dev: device whose device-tree node is being set 30444e75e1d7SJohan Hovold * @dev2: device whose device-tree node is being reused 30454e75e1d7SJohan Hovold * 30464e75e1d7SJohan Hovold * Takes another reference to the new device-tree node after first dropping 30474e75e1d7SJohan Hovold * any reference held to the old node. 30484e75e1d7SJohan Hovold */ 30494e75e1d7SJohan Hovold void device_set_of_node_from_dev(struct device *dev, const struct device *dev2) 30504e75e1d7SJohan Hovold { 30514e75e1d7SJohan Hovold of_node_put(dev->of_node); 30524e75e1d7SJohan Hovold dev->of_node = of_node_get(dev2->of_node); 30534e75e1d7SJohan Hovold dev->of_node_reused = true; 30544e75e1d7SJohan Hovold } 30554e75e1d7SJohan Hovold EXPORT_SYMBOL_GPL(device_set_of_node_from_dev); 3056