11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * drivers/base/core.c - core driver model code (device registration, etc) 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (c) 2002-3 Patrick Mochel 51da177e4SLinus Torvalds * Copyright (c) 2002-3 Open Source Development Labs 664bb5d2cSGreg Kroah-Hartman * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de> 764bb5d2cSGreg Kroah-Hartman * Copyright (c) 2006 Novell, Inc. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * This file is released under the GPLv2 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds #include <linux/device.h> 141da177e4SLinus Torvalds #include <linux/err.h> 1597badf87SRafael J. Wysocki #include <linux/fwnode.h> 161da177e4SLinus Torvalds #include <linux/init.h> 171da177e4SLinus Torvalds #include <linux/module.h> 181da177e4SLinus Torvalds #include <linux/slab.h> 191da177e4SLinus Torvalds #include <linux/string.h> 2023681e47SGreg Kroah-Hartman #include <linux/kdev_t.h> 21116af378SBenjamin Herrenschmidt #include <linux/notifier.h> 2207d57a32SGrant Likely #include <linux/of.h> 2307d57a32SGrant Likely #include <linux/of_device.h> 24da231fd5SKay Sievers #include <linux/genhd.h> 25815d2d50SAndrew Morton #include <linux/kallsyms.h> 26f75b1c60SDave Young #include <linux/mutex.h> 27af8db150SPeter Chen #include <linux/pm_runtime.h> 28c4e00daaSKay Sievers #include <linux/netdevice.h> 2963967685SGreg Kroah-Hartman #include <linux/sysfs.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include "base.h" 321da177e4SLinus Torvalds #include "power/power.h" 331da177e4SLinus Torvalds 34e52eec13SAndi Kleen #ifdef CONFIG_SYSFS_DEPRECATED 35e52eec13SAndi Kleen #ifdef CONFIG_SYSFS_DEPRECATED_V2 36e52eec13SAndi Kleen long sysfs_deprecated = 1; 37e52eec13SAndi Kleen #else 38e52eec13SAndi Kleen long sysfs_deprecated = 0; 39e52eec13SAndi Kleen #endif 403454bf96SHanjun Guo static int __init sysfs_deprecated_setup(char *arg) 41e52eec13SAndi Kleen { 4234da5e67SJingoo Han return kstrtol(arg, 10, &sysfs_deprecated); 43e52eec13SAndi Kleen } 44e52eec13SAndi Kleen early_param("sysfs.deprecated", sysfs_deprecated_setup); 45e52eec13SAndi Kleen #endif 46e52eec13SAndi Kleen 471da177e4SLinus Torvalds int (*platform_notify)(struct device *dev) = NULL; 481da177e4SLinus Torvalds int (*platform_notify_remove)(struct device *dev) = NULL; 49e105b8bfSDan Williams static struct kobject *dev_kobj; 50e105b8bfSDan Williams struct kobject *sysfs_dev_char_kobj; 51e105b8bfSDan Williams struct kobject *sysfs_dev_block_kobj; 521da177e4SLinus Torvalds 535e33bc41SRafael J. Wysocki static DEFINE_MUTEX(device_hotplug_lock); 545e33bc41SRafael J. Wysocki 555e33bc41SRafael J. Wysocki void lock_device_hotplug(void) 565e33bc41SRafael J. Wysocki { 575e33bc41SRafael J. Wysocki mutex_lock(&device_hotplug_lock); 585e33bc41SRafael J. Wysocki } 595e33bc41SRafael J. Wysocki 605e33bc41SRafael J. Wysocki void unlock_device_hotplug(void) 615e33bc41SRafael J. Wysocki { 625e33bc41SRafael J. Wysocki mutex_unlock(&device_hotplug_lock); 635e33bc41SRafael J. Wysocki } 645e33bc41SRafael J. Wysocki 655e33bc41SRafael J. Wysocki int lock_device_hotplug_sysfs(void) 665e33bc41SRafael J. Wysocki { 675e33bc41SRafael J. Wysocki if (mutex_trylock(&device_hotplug_lock)) 685e33bc41SRafael J. Wysocki return 0; 695e33bc41SRafael J. Wysocki 705e33bc41SRafael J. Wysocki /* Avoid busy looping (5 ms of sleep should do). */ 715e33bc41SRafael J. Wysocki msleep(5); 725e33bc41SRafael J. Wysocki return restart_syscall(); 735e33bc41SRafael J. Wysocki } 745e33bc41SRafael J. Wysocki 754e886c29SGreg Kroah-Hartman #ifdef CONFIG_BLOCK 764e886c29SGreg Kroah-Hartman static inline int device_is_not_partition(struct device *dev) 774e886c29SGreg Kroah-Hartman { 784e886c29SGreg Kroah-Hartman return !(dev->type == &part_type); 794e886c29SGreg Kroah-Hartman } 804e886c29SGreg Kroah-Hartman #else 814e886c29SGreg Kroah-Hartman static inline int device_is_not_partition(struct device *dev) 824e886c29SGreg Kroah-Hartman { 834e886c29SGreg Kroah-Hartman return 1; 844e886c29SGreg Kroah-Hartman } 854e886c29SGreg Kroah-Hartman #endif 861da177e4SLinus Torvalds 873e95637aSAlan Stern /** 883e95637aSAlan Stern * dev_driver_string - Return a device's driver name, if at all possible 893e95637aSAlan Stern * @dev: struct device to get the name of 903e95637aSAlan Stern * 913e95637aSAlan Stern * Will return the device's driver's name if it is bound to a device. If 929169c012Syan * the device is not bound to a driver, it will return the name of the bus 933e95637aSAlan Stern * it is attached to. If it is not attached to a bus either, an empty 943e95637aSAlan Stern * string will be returned. 953e95637aSAlan Stern */ 96bf9ca69fSJean Delvare const char *dev_driver_string(const struct device *dev) 973e95637aSAlan Stern { 983589972eSAlan Stern struct device_driver *drv; 993589972eSAlan Stern 1003589972eSAlan Stern /* dev->driver can change to NULL underneath us because of unbinding, 1013589972eSAlan Stern * so be careful about accessing it. dev->bus and dev->class should 1023589972eSAlan Stern * never change once they are set, so they don't need special care. 1033589972eSAlan Stern */ 1043589972eSAlan Stern drv = ACCESS_ONCE(dev->driver); 1053589972eSAlan Stern return drv ? drv->name : 106a456b702SJean Delvare (dev->bus ? dev->bus->name : 107a456b702SJean Delvare (dev->class ? dev->class->name : "")); 1083e95637aSAlan Stern } 109310a922dSMatthew Wilcox EXPORT_SYMBOL(dev_driver_string); 1103e95637aSAlan Stern 1111da177e4SLinus Torvalds #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) 1121da177e4SLinus Torvalds 1134a3ad20cSGreg Kroah-Hartman static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, 1144a3ad20cSGreg Kroah-Hartman char *buf) 1151da177e4SLinus Torvalds { 1161da177e4SLinus Torvalds struct device_attribute *dev_attr = to_dev_attr(attr); 117b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 1184a0c20bfSDmitry Torokhov ssize_t ret = -EIO; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds if (dev_attr->show) 12154b6f35cSYani Ioannou ret = dev_attr->show(dev, dev_attr, buf); 122815d2d50SAndrew Morton if (ret >= (ssize_t)PAGE_SIZE) { 12353a9c87eSGreg Kroah-Hartman print_symbol("dev_attr_show: %s returned bad count\n", 12453a9c87eSGreg Kroah-Hartman (unsigned long)dev_attr->show); 125815d2d50SAndrew Morton } 1261da177e4SLinus Torvalds return ret; 1271da177e4SLinus Torvalds } 1281da177e4SLinus Torvalds 1294a3ad20cSGreg Kroah-Hartman static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, 1301da177e4SLinus Torvalds const char *buf, size_t count) 1311da177e4SLinus Torvalds { 1321da177e4SLinus Torvalds struct device_attribute *dev_attr = to_dev_attr(attr); 133b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 1344a0c20bfSDmitry Torokhov ssize_t ret = -EIO; 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds if (dev_attr->store) 13754b6f35cSYani Ioannou ret = dev_attr->store(dev, dev_attr, buf, count); 1381da177e4SLinus Torvalds return ret; 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds 14152cf25d0SEmese Revfy static const struct sysfs_ops dev_sysfs_ops = { 1421da177e4SLinus Torvalds .show = dev_attr_show, 1431da177e4SLinus Torvalds .store = dev_attr_store, 1441da177e4SLinus Torvalds }; 1451da177e4SLinus Torvalds 146ca22e56dSKay Sievers #define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr) 147ca22e56dSKay Sievers 148ca22e56dSKay Sievers ssize_t device_store_ulong(struct device *dev, 149ca22e56dSKay Sievers struct device_attribute *attr, 150ca22e56dSKay Sievers const char *buf, size_t size) 151ca22e56dSKay Sievers { 152ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 153ca22e56dSKay Sievers char *end; 154ca22e56dSKay Sievers unsigned long new = simple_strtoul(buf, &end, 0); 155ca22e56dSKay Sievers if (end == buf) 156ca22e56dSKay Sievers return -EINVAL; 157ca22e56dSKay Sievers *(unsigned long *)(ea->var) = new; 158ca22e56dSKay Sievers /* Always return full write size even if we didn't consume all */ 159ca22e56dSKay Sievers return size; 160ca22e56dSKay Sievers } 161ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_store_ulong); 162ca22e56dSKay Sievers 163ca22e56dSKay Sievers ssize_t device_show_ulong(struct device *dev, 164ca22e56dSKay Sievers struct device_attribute *attr, 165ca22e56dSKay Sievers char *buf) 166ca22e56dSKay Sievers { 167ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 168ca22e56dSKay Sievers return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); 169ca22e56dSKay Sievers } 170ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_show_ulong); 171ca22e56dSKay Sievers 172ca22e56dSKay Sievers ssize_t device_store_int(struct device *dev, 173ca22e56dSKay Sievers struct device_attribute *attr, 174ca22e56dSKay Sievers const char *buf, size_t size) 175ca22e56dSKay Sievers { 176ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 177ca22e56dSKay Sievers char *end; 178ca22e56dSKay Sievers long new = simple_strtol(buf, &end, 0); 179ca22e56dSKay Sievers if (end == buf || new > INT_MAX || new < INT_MIN) 180ca22e56dSKay Sievers return -EINVAL; 181ca22e56dSKay Sievers *(int *)(ea->var) = new; 182ca22e56dSKay Sievers /* Always return full write size even if we didn't consume all */ 183ca22e56dSKay Sievers return size; 184ca22e56dSKay Sievers } 185ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_store_int); 186ca22e56dSKay Sievers 187ca22e56dSKay Sievers ssize_t device_show_int(struct device *dev, 188ca22e56dSKay Sievers struct device_attribute *attr, 189ca22e56dSKay Sievers char *buf) 190ca22e56dSKay Sievers { 191ca22e56dSKay Sievers struct dev_ext_attribute *ea = to_ext_attr(attr); 192ca22e56dSKay Sievers 193ca22e56dSKay Sievers return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); 194ca22e56dSKay Sievers } 195ca22e56dSKay Sievers EXPORT_SYMBOL_GPL(device_show_int); 1961da177e4SLinus Torvalds 19791872392SBorislav Petkov ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, 19891872392SBorislav Petkov const char *buf, size_t size) 19991872392SBorislav Petkov { 20091872392SBorislav Petkov struct dev_ext_attribute *ea = to_ext_attr(attr); 20191872392SBorislav Petkov 20291872392SBorislav Petkov if (strtobool(buf, ea->var) < 0) 20391872392SBorislav Petkov return -EINVAL; 20491872392SBorislav Petkov 20591872392SBorislav Petkov return size; 20691872392SBorislav Petkov } 20791872392SBorislav Petkov EXPORT_SYMBOL_GPL(device_store_bool); 20891872392SBorislav Petkov 20991872392SBorislav Petkov ssize_t device_show_bool(struct device *dev, struct device_attribute *attr, 21091872392SBorislav Petkov char *buf) 21191872392SBorislav Petkov { 21291872392SBorislav Petkov struct dev_ext_attribute *ea = to_ext_attr(attr); 21391872392SBorislav Petkov 21491872392SBorislav Petkov return snprintf(buf, PAGE_SIZE, "%d\n", *(bool *)(ea->var)); 21591872392SBorislav Petkov } 21691872392SBorislav Petkov EXPORT_SYMBOL_GPL(device_show_bool); 21791872392SBorislav Petkov 2181da177e4SLinus Torvalds /** 2191da177e4SLinus Torvalds * device_release - free device structure. 2201da177e4SLinus Torvalds * @kobj: device's kobject. 2211da177e4SLinus Torvalds * 2221da177e4SLinus Torvalds * This is called once the reference count for the object 2231da177e4SLinus Torvalds * reaches 0. We forward the call to the device's release 2241da177e4SLinus Torvalds * method, which should handle actually freeing the structure. 2251da177e4SLinus Torvalds */ 2261da177e4SLinus Torvalds static void device_release(struct kobject *kobj) 2271da177e4SLinus Torvalds { 228b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 229fb069a5dSGreg Kroah-Hartman struct device_private *p = dev->p; 2301da177e4SLinus Torvalds 231a525a3ddSMing Lei /* 232a525a3ddSMing Lei * Some platform devices are driven without driver attached 233a525a3ddSMing Lei * and managed resources may have been acquired. Make sure 234a525a3ddSMing Lei * all resources are released. 235a525a3ddSMing Lei * 236a525a3ddSMing Lei * Drivers still can add resources into device after device 237a525a3ddSMing Lei * is deleted but alive, so release devres here to avoid 238a525a3ddSMing Lei * possible memory leak. 239a525a3ddSMing Lei */ 240a525a3ddSMing Lei devres_release_all(dev); 241a525a3ddSMing Lei 2421da177e4SLinus Torvalds if (dev->release) 2431da177e4SLinus Torvalds dev->release(dev); 244f9f852dfSKay Sievers else if (dev->type && dev->type->release) 245f9f852dfSKay Sievers dev->type->release(dev); 2462620efefSGreg Kroah-Hartman else if (dev->class && dev->class->dev_release) 2472620efefSGreg Kroah-Hartman dev->class->dev_release(dev); 248f810a5cfSArjan van de Ven else 249f810a5cfSArjan van de Ven WARN(1, KERN_ERR "Device '%s' does not have a release() " 2504a3ad20cSGreg Kroah-Hartman "function, it is broken and must be fixed.\n", 2511e0b2cf9SKay Sievers dev_name(dev)); 252fb069a5dSGreg Kroah-Hartman kfree(p); 2531da177e4SLinus Torvalds } 2541da177e4SLinus Torvalds 255bc451f20SEric W. Biederman static const void *device_namespace(struct kobject *kobj) 256bc451f20SEric W. Biederman { 257b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 258bc451f20SEric W. Biederman const void *ns = NULL; 259bc451f20SEric W. Biederman 260bc451f20SEric W. Biederman if (dev->class && dev->class->ns_type) 261bc451f20SEric W. Biederman ns = dev->class->namespace(dev); 262bc451f20SEric W. Biederman 263bc451f20SEric W. Biederman return ns; 264bc451f20SEric W. Biederman } 265bc451f20SEric W. Biederman 2668f4afc41SGreg Kroah-Hartman static struct kobj_type device_ktype = { 2671da177e4SLinus Torvalds .release = device_release, 2681da177e4SLinus Torvalds .sysfs_ops = &dev_sysfs_ops, 269bc451f20SEric W. Biederman .namespace = device_namespace, 2701da177e4SLinus Torvalds }; 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds 273312c004dSKay Sievers static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) 2741da177e4SLinus Torvalds { 2751da177e4SLinus Torvalds struct kobj_type *ktype = get_ktype(kobj); 2761da177e4SLinus Torvalds 2778f4afc41SGreg Kroah-Hartman if (ktype == &device_ktype) { 278b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 2791da177e4SLinus Torvalds if (dev->bus) 2801da177e4SLinus Torvalds return 1; 28123681e47SGreg Kroah-Hartman if (dev->class) 28223681e47SGreg Kroah-Hartman return 1; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds return 0; 2851da177e4SLinus Torvalds } 2861da177e4SLinus Torvalds 287312c004dSKay Sievers static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) 2881da177e4SLinus Torvalds { 289b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 2901da177e4SLinus Torvalds 29123681e47SGreg Kroah-Hartman if (dev->bus) 2921da177e4SLinus Torvalds return dev->bus->name; 29323681e47SGreg Kroah-Hartman if (dev->class) 29423681e47SGreg Kroah-Hartman return dev->class->name; 29523681e47SGreg Kroah-Hartman return NULL; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2987eff2e7aSKay Sievers static int dev_uevent(struct kset *kset, struct kobject *kobj, 2997eff2e7aSKay Sievers struct kobj_uevent_env *env) 3001da177e4SLinus Torvalds { 301b0d1f807SLars-Peter Clausen struct device *dev = kobj_to_dev(kobj); 3021da177e4SLinus Torvalds int retval = 0; 3031da177e4SLinus Torvalds 3046fcf53acSKay Sievers /* add device node properties if present */ 30523681e47SGreg Kroah-Hartman if (MAJOR(dev->devt)) { 3066fcf53acSKay Sievers const char *tmp; 3076fcf53acSKay Sievers const char *name; 3082c9ede55SAl Viro umode_t mode = 0; 3094e4098a3SGreg Kroah-Hartman kuid_t uid = GLOBAL_ROOT_UID; 3104e4098a3SGreg Kroah-Hartman kgid_t gid = GLOBAL_ROOT_GID; 3116fcf53acSKay Sievers 3127eff2e7aSKay Sievers add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); 3137eff2e7aSKay Sievers add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); 3143c2670e6SKay Sievers name = device_get_devnode(dev, &mode, &uid, &gid, &tmp); 3156fcf53acSKay Sievers if (name) { 3166fcf53acSKay Sievers add_uevent_var(env, "DEVNAME=%s", name); 317e454cea2SKay Sievers if (mode) 318e454cea2SKay Sievers add_uevent_var(env, "DEVMODE=%#o", mode & 0777); 3194e4098a3SGreg Kroah-Hartman if (!uid_eq(uid, GLOBAL_ROOT_UID)) 3204e4098a3SGreg Kroah-Hartman add_uevent_var(env, "DEVUID=%u", from_kuid(&init_user_ns, uid)); 3214e4098a3SGreg Kroah-Hartman if (!gid_eq(gid, GLOBAL_ROOT_GID)) 3224e4098a3SGreg Kroah-Hartman add_uevent_var(env, "DEVGID=%u", from_kgid(&init_user_ns, gid)); 3233c2670e6SKay Sievers kfree(tmp); 3246fcf53acSKay Sievers } 32523681e47SGreg Kroah-Hartman } 32623681e47SGreg Kroah-Hartman 327414264f9SKay Sievers if (dev->type && dev->type->name) 3287eff2e7aSKay Sievers add_uevent_var(env, "DEVTYPE=%s", dev->type->name); 329414264f9SKay Sievers 330239378f1SKay Sievers if (dev->driver) 3317eff2e7aSKay Sievers add_uevent_var(env, "DRIVER=%s", dev->driver->name); 332239378f1SKay Sievers 33307d57a32SGrant Likely /* Add common DT information about the device */ 33407d57a32SGrant Likely of_device_uevent(dev, env); 33507d57a32SGrant Likely 3361da177e4SLinus Torvalds /* have the bus specific function add its stuff */ 3377eff2e7aSKay Sievers if (dev->bus && dev->bus->uevent) { 3387eff2e7aSKay Sievers retval = dev->bus->uevent(dev, env); 339f9f852dfSKay Sievers if (retval) 3407dc72b28SGreg Kroah-Hartman pr_debug("device: '%s': %s: bus uevent() returned %d\n", 3411e0b2cf9SKay Sievers dev_name(dev), __func__, retval); 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds 3442620efefSGreg Kroah-Hartman /* have the class specific function add its stuff */ 3457eff2e7aSKay Sievers if (dev->class && dev->class->dev_uevent) { 3467eff2e7aSKay Sievers retval = dev->class->dev_uevent(dev, env); 347f9f852dfSKay Sievers if (retval) 3487dc72b28SGreg Kroah-Hartman pr_debug("device: '%s': %s: class uevent() " 3491e0b2cf9SKay Sievers "returned %d\n", dev_name(dev), 3502b3a302aSHarvey Harrison __func__, retval); 3512620efefSGreg Kroah-Hartman } 352f9f852dfSKay Sievers 353eef35c2dSStefan Weil /* have the device type specific function add its stuff */ 3547eff2e7aSKay Sievers if (dev->type && dev->type->uevent) { 3557eff2e7aSKay Sievers retval = dev->type->uevent(dev, env); 356f9f852dfSKay Sievers if (retval) 3577dc72b28SGreg Kroah-Hartman pr_debug("device: '%s': %s: dev_type uevent() " 3581e0b2cf9SKay Sievers "returned %d\n", dev_name(dev), 3592b3a302aSHarvey Harrison __func__, retval); 3602620efefSGreg Kroah-Hartman } 3612620efefSGreg Kroah-Hartman 3621da177e4SLinus Torvalds return retval; 3631da177e4SLinus Torvalds } 3641da177e4SLinus Torvalds 3659cd43611SEmese Revfy static const struct kset_uevent_ops device_uevent_ops = { 366312c004dSKay Sievers .filter = dev_uevent_filter, 367312c004dSKay Sievers .name = dev_uevent_name, 368312c004dSKay Sievers .uevent = dev_uevent, 3691da177e4SLinus Torvalds }; 3701da177e4SLinus Torvalds 371c5e064a6SGreg Kroah-Hartman static ssize_t uevent_show(struct device *dev, struct device_attribute *attr, 37216574dccSKay Sievers char *buf) 37316574dccSKay Sievers { 37416574dccSKay Sievers struct kobject *top_kobj; 37516574dccSKay Sievers struct kset *kset; 3767eff2e7aSKay Sievers struct kobj_uevent_env *env = NULL; 37716574dccSKay Sievers int i; 37816574dccSKay Sievers size_t count = 0; 37916574dccSKay Sievers int retval; 38016574dccSKay Sievers 38116574dccSKay Sievers /* search the kset, the device belongs to */ 38216574dccSKay Sievers top_kobj = &dev->kobj; 3835c5daf65SKay Sievers while (!top_kobj->kset && top_kobj->parent) 38416574dccSKay Sievers top_kobj = top_kobj->parent; 38516574dccSKay Sievers if (!top_kobj->kset) 38616574dccSKay Sievers goto out; 3875c5daf65SKay Sievers 38816574dccSKay Sievers kset = top_kobj->kset; 38916574dccSKay Sievers if (!kset->uevent_ops || !kset->uevent_ops->uevent) 39016574dccSKay Sievers goto out; 39116574dccSKay Sievers 39216574dccSKay Sievers /* respect filter */ 39316574dccSKay Sievers if (kset->uevent_ops && kset->uevent_ops->filter) 39416574dccSKay Sievers if (!kset->uevent_ops->filter(kset, &dev->kobj)) 39516574dccSKay Sievers goto out; 39616574dccSKay Sievers 3977eff2e7aSKay Sievers env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); 3987eff2e7aSKay Sievers if (!env) 399c7308c81SGreg Kroah-Hartman return -ENOMEM; 400c7308c81SGreg Kroah-Hartman 40116574dccSKay Sievers /* let the kset specific function add its keys */ 4027eff2e7aSKay Sievers retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); 40316574dccSKay Sievers if (retval) 40416574dccSKay Sievers goto out; 40516574dccSKay Sievers 40616574dccSKay Sievers /* copy keys to file */ 4077eff2e7aSKay Sievers for (i = 0; i < env->envp_idx; i++) 4087eff2e7aSKay Sievers count += sprintf(&buf[count], "%s\n", env->envp[i]); 40916574dccSKay Sievers out: 4107eff2e7aSKay Sievers kfree(env); 41116574dccSKay Sievers return count; 41216574dccSKay Sievers } 41316574dccSKay Sievers 414c5e064a6SGreg Kroah-Hartman static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, 415a7fd6706SKay Sievers const char *buf, size_t count) 416a7fd6706SKay Sievers { 41760a96a59SKay Sievers enum kobject_action action; 41860a96a59SKay Sievers 4193f5468c9SKay Sievers if (kobject_action_type(buf, count, &action) == 0) 42060a96a59SKay Sievers kobject_uevent(&dev->kobj, action); 4213f5468c9SKay Sievers else 4223f5468c9SKay Sievers dev_err(dev, "uevent: unknown action-string\n"); 423a7fd6706SKay Sievers return count; 424a7fd6706SKay Sievers } 425c5e064a6SGreg Kroah-Hartman static DEVICE_ATTR_RW(uevent); 426a7fd6706SKay Sievers 427c5e064a6SGreg Kroah-Hartman static ssize_t online_show(struct device *dev, struct device_attribute *attr, 4284f3549d7SRafael J. Wysocki char *buf) 4294f3549d7SRafael J. Wysocki { 4304f3549d7SRafael J. Wysocki bool val; 4314f3549d7SRafael J. Wysocki 4325e33bc41SRafael J. Wysocki device_lock(dev); 4334f3549d7SRafael J. Wysocki val = !dev->offline; 4345e33bc41SRafael J. Wysocki device_unlock(dev); 4354f3549d7SRafael J. Wysocki return sprintf(buf, "%u\n", val); 4364f3549d7SRafael J. Wysocki } 4374f3549d7SRafael J. Wysocki 438c5e064a6SGreg Kroah-Hartman static ssize_t online_store(struct device *dev, struct device_attribute *attr, 4394f3549d7SRafael J. Wysocki const char *buf, size_t count) 4404f3549d7SRafael J. Wysocki { 4414f3549d7SRafael J. Wysocki bool val; 4424f3549d7SRafael J. Wysocki int ret; 4434f3549d7SRafael J. Wysocki 4444f3549d7SRafael J. Wysocki ret = strtobool(buf, &val); 4454f3549d7SRafael J. Wysocki if (ret < 0) 4464f3549d7SRafael J. Wysocki return ret; 4474f3549d7SRafael J. Wysocki 4485e33bc41SRafael J. Wysocki ret = lock_device_hotplug_sysfs(); 4495e33bc41SRafael J. Wysocki if (ret) 4505e33bc41SRafael J. Wysocki return ret; 4515e33bc41SRafael J. Wysocki 4524f3549d7SRafael J. Wysocki ret = val ? device_online(dev) : device_offline(dev); 4534f3549d7SRafael J. Wysocki unlock_device_hotplug(); 4544f3549d7SRafael J. Wysocki return ret < 0 ? ret : count; 4554f3549d7SRafael J. Wysocki } 456c5e064a6SGreg Kroah-Hartman static DEVICE_ATTR_RW(online); 4574f3549d7SRafael J. Wysocki 458fa6fdb33SGreg Kroah-Hartman int device_add_groups(struct device *dev, const struct attribute_group **groups) 459621a1672SDmitry Torokhov { 4603e9b2baeSGreg Kroah-Hartman return sysfs_create_groups(&dev->kobj, groups); 461621a1672SDmitry Torokhov } 462621a1672SDmitry Torokhov 463fa6fdb33SGreg Kroah-Hartman void device_remove_groups(struct device *dev, 464a4dbd674SDavid Brownell const struct attribute_group **groups) 465621a1672SDmitry Torokhov { 4663e9b2baeSGreg Kroah-Hartman sysfs_remove_groups(&dev->kobj, groups); 467621a1672SDmitry Torokhov } 468de0ff00dSGreg Kroah-Hartman 4692620efefSGreg Kroah-Hartman static int device_add_attrs(struct device *dev) 4702620efefSGreg Kroah-Hartman { 4712620efefSGreg Kroah-Hartman struct class *class = dev->class; 472aed65af1SStephen Hemminger const struct device_type *type = dev->type; 473621a1672SDmitry Torokhov int error; 4742620efefSGreg Kroah-Hartman 475621a1672SDmitry Torokhov if (class) { 476d05a6f96SGreg Kroah-Hartman error = device_add_groups(dev, class->dev_groups); 4772620efefSGreg Kroah-Hartman if (error) 478621a1672SDmitry Torokhov return error; 479f9f852dfSKay Sievers } 480f9f852dfSKay Sievers 481621a1672SDmitry Torokhov if (type) { 482621a1672SDmitry Torokhov error = device_add_groups(dev, type->groups); 483f9f852dfSKay Sievers if (error) 484a6b01dedSGreg Kroah-Hartman goto err_remove_class_groups; 485f9f852dfSKay Sievers } 486621a1672SDmitry Torokhov 487621a1672SDmitry Torokhov error = device_add_groups(dev, dev->groups); 488f9f852dfSKay Sievers if (error) 489621a1672SDmitry Torokhov goto err_remove_type_groups; 490621a1672SDmitry Torokhov 4914f3549d7SRafael J. Wysocki if (device_supports_offline(dev) && !dev->offline_disabled) { 492c5e064a6SGreg Kroah-Hartman error = device_create_file(dev, &dev_attr_online); 4934f3549d7SRafael J. Wysocki if (error) 494ecfbf6fdSRafael J. Wysocki goto err_remove_dev_groups; 4954f3549d7SRafael J. Wysocki } 4964f3549d7SRafael J. Wysocki 497621a1672SDmitry Torokhov return 0; 498621a1672SDmitry Torokhov 499ecfbf6fdSRafael J. Wysocki err_remove_dev_groups: 500ecfbf6fdSRafael J. Wysocki device_remove_groups(dev, dev->groups); 501621a1672SDmitry Torokhov err_remove_type_groups: 502621a1672SDmitry Torokhov if (type) 503621a1672SDmitry Torokhov device_remove_groups(dev, type->groups); 504d05a6f96SGreg Kroah-Hartman err_remove_class_groups: 505d05a6f96SGreg Kroah-Hartman if (class) 506d05a6f96SGreg Kroah-Hartman device_remove_groups(dev, class->dev_groups); 507f9f852dfSKay Sievers 5082620efefSGreg Kroah-Hartman return error; 5092620efefSGreg Kroah-Hartman } 5102620efefSGreg Kroah-Hartman 5112620efefSGreg Kroah-Hartman static void device_remove_attrs(struct device *dev) 5122620efefSGreg Kroah-Hartman { 5132620efefSGreg Kroah-Hartman struct class *class = dev->class; 514aed65af1SStephen Hemminger const struct device_type *type = dev->type; 5152620efefSGreg Kroah-Hartman 516c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_online); 517621a1672SDmitry Torokhov device_remove_groups(dev, dev->groups); 518f9f852dfSKay Sievers 519621a1672SDmitry Torokhov if (type) 520621a1672SDmitry Torokhov device_remove_groups(dev, type->groups); 521621a1672SDmitry Torokhov 522a6b01dedSGreg Kroah-Hartman if (class) 523d05a6f96SGreg Kroah-Hartman device_remove_groups(dev, class->dev_groups); 524c97415a7SStefan Achatz } 5252620efefSGreg Kroah-Hartman 526c5e064a6SGreg Kroah-Hartman static ssize_t dev_show(struct device *dev, struct device_attribute *attr, 52723681e47SGreg Kroah-Hartman char *buf) 52823681e47SGreg Kroah-Hartman { 52923681e47SGreg Kroah-Hartman return print_dev_t(buf, dev->devt); 53023681e47SGreg Kroah-Hartman } 531c5e064a6SGreg Kroah-Hartman static DEVICE_ATTR_RO(dev); 532ad6a1e1cSTejun Heo 533ca22e56dSKay Sievers /* /sys/devices/ */ 534881c6cfdSGreg Kroah-Hartman struct kset *devices_kset; 5351da177e4SLinus Torvalds 5361da177e4SLinus Torvalds /** 53752cdbdd4SGrygorii Strashko * devices_kset_move_before - Move device in the devices_kset's list. 53852cdbdd4SGrygorii Strashko * @deva: Device to move. 53952cdbdd4SGrygorii Strashko * @devb: Device @deva should come before. 54052cdbdd4SGrygorii Strashko */ 54152cdbdd4SGrygorii Strashko static void devices_kset_move_before(struct device *deva, struct device *devb) 54252cdbdd4SGrygorii Strashko { 54352cdbdd4SGrygorii Strashko if (!devices_kset) 54452cdbdd4SGrygorii Strashko return; 54552cdbdd4SGrygorii Strashko pr_debug("devices_kset: Moving %s before %s\n", 54652cdbdd4SGrygorii Strashko dev_name(deva), dev_name(devb)); 54752cdbdd4SGrygorii Strashko spin_lock(&devices_kset->list_lock); 54852cdbdd4SGrygorii Strashko list_move_tail(&deva->kobj.entry, &devb->kobj.entry); 54952cdbdd4SGrygorii Strashko spin_unlock(&devices_kset->list_lock); 55052cdbdd4SGrygorii Strashko } 55152cdbdd4SGrygorii Strashko 55252cdbdd4SGrygorii Strashko /** 55352cdbdd4SGrygorii Strashko * devices_kset_move_after - Move device in the devices_kset's list. 55452cdbdd4SGrygorii Strashko * @deva: Device to move 55552cdbdd4SGrygorii Strashko * @devb: Device @deva should come after. 55652cdbdd4SGrygorii Strashko */ 55752cdbdd4SGrygorii Strashko static void devices_kset_move_after(struct device *deva, struct device *devb) 55852cdbdd4SGrygorii Strashko { 55952cdbdd4SGrygorii Strashko if (!devices_kset) 56052cdbdd4SGrygorii Strashko return; 56152cdbdd4SGrygorii Strashko pr_debug("devices_kset: Moving %s after %s\n", 56252cdbdd4SGrygorii Strashko dev_name(deva), dev_name(devb)); 56352cdbdd4SGrygorii Strashko spin_lock(&devices_kset->list_lock); 56452cdbdd4SGrygorii Strashko list_move(&deva->kobj.entry, &devb->kobj.entry); 56552cdbdd4SGrygorii Strashko spin_unlock(&devices_kset->list_lock); 56652cdbdd4SGrygorii Strashko } 56752cdbdd4SGrygorii Strashko 56852cdbdd4SGrygorii Strashko /** 56952cdbdd4SGrygorii Strashko * devices_kset_move_last - move the device to the end of devices_kset's list. 57052cdbdd4SGrygorii Strashko * @dev: device to move 57152cdbdd4SGrygorii Strashko */ 57252cdbdd4SGrygorii Strashko void devices_kset_move_last(struct device *dev) 57352cdbdd4SGrygorii Strashko { 57452cdbdd4SGrygorii Strashko if (!devices_kset) 57552cdbdd4SGrygorii Strashko return; 57652cdbdd4SGrygorii Strashko pr_debug("devices_kset: Moving %s to end of list\n", dev_name(dev)); 57752cdbdd4SGrygorii Strashko spin_lock(&devices_kset->list_lock); 57852cdbdd4SGrygorii Strashko list_move_tail(&dev->kobj.entry, &devices_kset->list); 57952cdbdd4SGrygorii Strashko spin_unlock(&devices_kset->list_lock); 58052cdbdd4SGrygorii Strashko } 58152cdbdd4SGrygorii Strashko 58252cdbdd4SGrygorii Strashko /** 5831da177e4SLinus Torvalds * device_create_file - create sysfs attribute file for device. 5841da177e4SLinus Torvalds * @dev: device. 5851da177e4SLinus Torvalds * @attr: device attribute descriptor. 5861da177e4SLinus Torvalds */ 58726579ab7SPhil Carmody int device_create_file(struct device *dev, 58826579ab7SPhil Carmody const struct device_attribute *attr) 5891da177e4SLinus Torvalds { 5901da177e4SLinus Torvalds int error = 0; 5918f46baaaSFelipe Balbi 5928f46baaaSFelipe Balbi if (dev) { 5938f46baaaSFelipe Balbi WARN(((attr->attr.mode & S_IWUGO) && !attr->store), 59497521978Sdyoung@redhat.com "Attribute %s: write permission without 'store'\n", 59597521978Sdyoung@redhat.com attr->attr.name); 5968f46baaaSFelipe Balbi WARN(((attr->attr.mode & S_IRUGO) && !attr->show), 59797521978Sdyoung@redhat.com "Attribute %s: read permission without 'show'\n", 59897521978Sdyoung@redhat.com attr->attr.name); 5991da177e4SLinus Torvalds error = sysfs_create_file(&dev->kobj, &attr->attr); 6008f46baaaSFelipe Balbi } 6018f46baaaSFelipe Balbi 6021da177e4SLinus Torvalds return error; 6031da177e4SLinus Torvalds } 60486df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_create_file); 6051da177e4SLinus Torvalds 6061da177e4SLinus Torvalds /** 6071da177e4SLinus Torvalds * device_remove_file - remove sysfs attribute file. 6081da177e4SLinus Torvalds * @dev: device. 6091da177e4SLinus Torvalds * @attr: device attribute descriptor. 6101da177e4SLinus Torvalds */ 61126579ab7SPhil Carmody void device_remove_file(struct device *dev, 61226579ab7SPhil Carmody const struct device_attribute *attr) 6131da177e4SLinus Torvalds { 6140c98b19fSCornelia Huck if (dev) 6151da177e4SLinus Torvalds sysfs_remove_file(&dev->kobj, &attr->attr); 6161da177e4SLinus Torvalds } 61786df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_remove_file); 6181da177e4SLinus Torvalds 6192589f188SGreg Kroah-Hartman /** 6206b0afc2aSTejun Heo * device_remove_file_self - remove sysfs attribute file from its own method. 6216b0afc2aSTejun Heo * @dev: device. 6226b0afc2aSTejun Heo * @attr: device attribute descriptor. 6236b0afc2aSTejun Heo * 6246b0afc2aSTejun Heo * See kernfs_remove_self() for details. 6256b0afc2aSTejun Heo */ 6266b0afc2aSTejun Heo bool device_remove_file_self(struct device *dev, 6276b0afc2aSTejun Heo const struct device_attribute *attr) 6286b0afc2aSTejun Heo { 6296b0afc2aSTejun Heo if (dev) 6306b0afc2aSTejun Heo return sysfs_remove_file_self(&dev->kobj, &attr->attr); 6316b0afc2aSTejun Heo else 6326b0afc2aSTejun Heo return false; 6336b0afc2aSTejun Heo } 6346b0afc2aSTejun Heo EXPORT_SYMBOL_GPL(device_remove_file_self); 6356b0afc2aSTejun Heo 6366b0afc2aSTejun Heo /** 6372589f188SGreg Kroah-Hartman * device_create_bin_file - create sysfs binary attribute file for device. 6382589f188SGreg Kroah-Hartman * @dev: device. 6392589f188SGreg Kroah-Hartman * @attr: device binary attribute descriptor. 6402589f188SGreg Kroah-Hartman */ 64166ecb92bSPhil Carmody int device_create_bin_file(struct device *dev, 64266ecb92bSPhil Carmody const struct bin_attribute *attr) 6432589f188SGreg Kroah-Hartman { 6442589f188SGreg Kroah-Hartman int error = -EINVAL; 6452589f188SGreg Kroah-Hartman if (dev) 6462589f188SGreg Kroah-Hartman error = sysfs_create_bin_file(&dev->kobj, attr); 6472589f188SGreg Kroah-Hartman return error; 6482589f188SGreg Kroah-Hartman } 6492589f188SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_create_bin_file); 6502589f188SGreg Kroah-Hartman 6512589f188SGreg Kroah-Hartman /** 6522589f188SGreg Kroah-Hartman * device_remove_bin_file - remove sysfs binary attribute file 6532589f188SGreg Kroah-Hartman * @dev: device. 6542589f188SGreg Kroah-Hartman * @attr: device binary attribute descriptor. 6552589f188SGreg Kroah-Hartman */ 65666ecb92bSPhil Carmody void device_remove_bin_file(struct device *dev, 65766ecb92bSPhil Carmody const struct bin_attribute *attr) 6582589f188SGreg Kroah-Hartman { 6592589f188SGreg Kroah-Hartman if (dev) 6602589f188SGreg Kroah-Hartman sysfs_remove_bin_file(&dev->kobj, attr); 6612589f188SGreg Kroah-Hartman } 6622589f188SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_remove_bin_file); 6632589f188SGreg Kroah-Hartman 66434bb61f9SJames Bottomley static void klist_children_get(struct klist_node *n) 66534bb61f9SJames Bottomley { 666f791b8c8SGreg Kroah-Hartman struct device_private *p = to_device_private_parent(n); 667f791b8c8SGreg Kroah-Hartman struct device *dev = p->device; 66834bb61f9SJames Bottomley 66934bb61f9SJames Bottomley get_device(dev); 67034bb61f9SJames Bottomley } 67134bb61f9SJames Bottomley 67234bb61f9SJames Bottomley static void klist_children_put(struct klist_node *n) 67334bb61f9SJames Bottomley { 674f791b8c8SGreg Kroah-Hartman struct device_private *p = to_device_private_parent(n); 675f791b8c8SGreg Kroah-Hartman struct device *dev = p->device; 67634bb61f9SJames Bottomley 67734bb61f9SJames Bottomley put_device(dev); 67834bb61f9SJames Bottomley } 67934bb61f9SJames Bottomley 6801da177e4SLinus Torvalds /** 6811da177e4SLinus Torvalds * device_initialize - init device structure. 6821da177e4SLinus Torvalds * @dev: device. 6831da177e4SLinus Torvalds * 6845739411aSCornelia Huck * This prepares the device for use by other layers by initializing 6855739411aSCornelia Huck * its fields. 6861da177e4SLinus Torvalds * It is the first half of device_register(), if called by 6875739411aSCornelia Huck * that function, though it can also be called separately, so one 6885739411aSCornelia Huck * may use @dev's fields. In particular, get_device()/put_device() 6895739411aSCornelia Huck * may be used for reference counting of @dev after calling this 6905739411aSCornelia Huck * function. 6915739411aSCornelia Huck * 692b10d5efdSAlan Stern * All fields in @dev must be initialized by the caller to 0, except 693b10d5efdSAlan Stern * for those explicitly set to some other value. The simplest 694b10d5efdSAlan Stern * approach is to use kzalloc() to allocate the structure containing 695b10d5efdSAlan Stern * @dev. 696b10d5efdSAlan Stern * 6975739411aSCornelia Huck * NOTE: Use put_device() to give up your reference instead of freeing 6985739411aSCornelia Huck * @dev directly once you have called this function. 6991da177e4SLinus Torvalds */ 7001da177e4SLinus Torvalds void device_initialize(struct device *dev) 7011da177e4SLinus Torvalds { 702881c6cfdSGreg Kroah-Hartman dev->kobj.kset = devices_kset; 703f9cb074bSGreg Kroah-Hartman kobject_init(&dev->kobj, &device_ktype); 7041da177e4SLinus Torvalds INIT_LIST_HEAD(&dev->dma_pools); 7053142788bSThomas Gleixner mutex_init(&dev->mutex); 7061704f47bSPeter Zijlstra lockdep_set_novalidate_class(&dev->mutex); 7079ac7849eSTejun Heo spin_lock_init(&dev->devres_lock); 7089ac7849eSTejun Heo INIT_LIST_HEAD(&dev->devres_head); 7093b98aeafSAlan Stern device_pm_init(dev); 71087348136SChristoph Hellwig set_dev_node(dev, -1); 7114a7cc831SJiang Liu #ifdef CONFIG_GENERIC_MSI_IRQ 7124a7cc831SJiang Liu INIT_LIST_HEAD(&dev->msi_list); 7134a7cc831SJiang Liu #endif 7141da177e4SLinus Torvalds } 71586df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_initialize); 7161da177e4SLinus Torvalds 717d73ce004STejun Heo struct kobject *virtual_device_parent(struct device *dev) 718f0ee61a6SGreg Kroah-Hartman { 719f0ee61a6SGreg Kroah-Hartman static struct kobject *virtual_dir = NULL; 720f0ee61a6SGreg Kroah-Hartman 721f0ee61a6SGreg Kroah-Hartman if (!virtual_dir) 7224ff6abffSGreg Kroah-Hartman virtual_dir = kobject_create_and_add("virtual", 723881c6cfdSGreg Kroah-Hartman &devices_kset->kobj); 724f0ee61a6SGreg Kroah-Hartman 72586406245SKay Sievers return virtual_dir; 726f0ee61a6SGreg Kroah-Hartman } 727f0ee61a6SGreg Kroah-Hartman 728bc451f20SEric W. Biederman struct class_dir { 729bc451f20SEric W. Biederman struct kobject kobj; 730bc451f20SEric W. Biederman struct class *class; 731bc451f20SEric W. Biederman }; 732bc451f20SEric W. Biederman 733bc451f20SEric W. Biederman #define to_class_dir(obj) container_of(obj, struct class_dir, kobj) 734bc451f20SEric W. Biederman 735bc451f20SEric W. Biederman static void class_dir_release(struct kobject *kobj) 736bc451f20SEric W. Biederman { 737bc451f20SEric W. Biederman struct class_dir *dir = to_class_dir(kobj); 738bc451f20SEric W. Biederman kfree(dir); 739bc451f20SEric W. Biederman } 740bc451f20SEric W. Biederman 741bc451f20SEric W. Biederman static const 742bc451f20SEric W. Biederman struct kobj_ns_type_operations *class_dir_child_ns_type(struct kobject *kobj) 743bc451f20SEric W. Biederman { 744bc451f20SEric W. Biederman struct class_dir *dir = to_class_dir(kobj); 745bc451f20SEric W. Biederman return dir->class->ns_type; 746bc451f20SEric W. Biederman } 747bc451f20SEric W. Biederman 748bc451f20SEric W. Biederman static struct kobj_type class_dir_ktype = { 749bc451f20SEric W. Biederman .release = class_dir_release, 750bc451f20SEric W. Biederman .sysfs_ops = &kobj_sysfs_ops, 751bc451f20SEric W. Biederman .child_ns_type = class_dir_child_ns_type 752bc451f20SEric W. Biederman }; 753bc451f20SEric W. Biederman 754bc451f20SEric W. Biederman static struct kobject * 755bc451f20SEric W. Biederman class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) 756bc451f20SEric W. Biederman { 757bc451f20SEric W. Biederman struct class_dir *dir; 758bc451f20SEric W. Biederman int retval; 759bc451f20SEric W. Biederman 760bc451f20SEric W. Biederman dir = kzalloc(sizeof(*dir), GFP_KERNEL); 761bc451f20SEric W. Biederman if (!dir) 762bc451f20SEric W. Biederman return NULL; 763bc451f20SEric W. Biederman 764bc451f20SEric W. Biederman dir->class = class; 765bc451f20SEric W. Biederman kobject_init(&dir->kobj, &class_dir_ktype); 766bc451f20SEric W. Biederman 7676b6e39a6SKay Sievers dir->kobj.kset = &class->p->glue_dirs; 768bc451f20SEric W. Biederman 769bc451f20SEric W. Biederman retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name); 770bc451f20SEric W. Biederman if (retval < 0) { 771bc451f20SEric W. Biederman kobject_put(&dir->kobj); 772bc451f20SEric W. Biederman return NULL; 773bc451f20SEric W. Biederman } 774bc451f20SEric W. Biederman return &dir->kobj; 775bc451f20SEric W. Biederman } 776bc451f20SEric W. Biederman 777e4a60d13SYijing Wang static DEFINE_MUTEX(gdp_mutex); 778bc451f20SEric W. Biederman 779c744aeaeSCornelia Huck static struct kobject *get_device_parent(struct device *dev, 780c744aeaeSCornelia Huck struct device *parent) 78140fa5422SGreg Kroah-Hartman { 78286406245SKay Sievers if (dev->class) { 78386406245SKay Sievers struct kobject *kobj = NULL; 78486406245SKay Sievers struct kobject *parent_kobj; 78586406245SKay Sievers struct kobject *k; 78686406245SKay Sievers 787ead454feSRandy Dunlap #ifdef CONFIG_BLOCK 78839aba963SKay Sievers /* block disks show up in /sys/block */ 789e52eec13SAndi Kleen if (sysfs_deprecated && dev->class == &block_class) { 79039aba963SKay Sievers if (parent && parent->class == &block_class) 79139aba963SKay Sievers return &parent->kobj; 7926b6e39a6SKay Sievers return &block_class.p->subsys.kobj; 79339aba963SKay Sievers } 794ead454feSRandy Dunlap #endif 795e52eec13SAndi Kleen 79686406245SKay Sievers /* 79786406245SKay Sievers * If we have no parent, we live in "virtual". 7980f4dafc0SKay Sievers * Class-devices with a non class-device as parent, live 7990f4dafc0SKay Sievers * in a "glue" directory to prevent namespace collisions. 80086406245SKay Sievers */ 80186406245SKay Sievers if (parent == NULL) 80286406245SKay Sievers parent_kobj = virtual_device_parent(dev); 80324b1442dSEric W. Biederman else if (parent->class && !dev->class->ns_type) 80486406245SKay Sievers return &parent->kobj; 80586406245SKay Sievers else 80686406245SKay Sievers parent_kobj = &parent->kobj; 80786406245SKay Sievers 80877d3d7c1STejun Heo mutex_lock(&gdp_mutex); 80977d3d7c1STejun Heo 81086406245SKay Sievers /* find our class-directory at the parent and reference it */ 8116b6e39a6SKay Sievers spin_lock(&dev->class->p->glue_dirs.list_lock); 8126b6e39a6SKay Sievers list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry) 81386406245SKay Sievers if (k->parent == parent_kobj) { 81486406245SKay Sievers kobj = kobject_get(k); 81586406245SKay Sievers break; 81686406245SKay Sievers } 8176b6e39a6SKay Sievers spin_unlock(&dev->class->p->glue_dirs.list_lock); 81877d3d7c1STejun Heo if (kobj) { 81977d3d7c1STejun Heo mutex_unlock(&gdp_mutex); 82086406245SKay Sievers return kobj; 82177d3d7c1STejun Heo } 82286406245SKay Sievers 82386406245SKay Sievers /* or create a new class-directory at the parent device */ 824bc451f20SEric W. Biederman k = class_dir_create_and_add(dev->class, parent_kobj); 8250f4dafc0SKay Sievers /* do not emit an uevent for this simple "glue" directory */ 82677d3d7c1STejun Heo mutex_unlock(&gdp_mutex); 82743968d2fSGreg Kroah-Hartman return k; 82886406245SKay Sievers } 82986406245SKay Sievers 830ca22e56dSKay Sievers /* subsystems can specify a default root directory for their devices */ 831ca22e56dSKay Sievers if (!parent && dev->bus && dev->bus->dev_root) 832ca22e56dSKay Sievers return &dev->bus->dev_root->kobj; 833ca22e56dSKay Sievers 83486406245SKay Sievers if (parent) 835c744aeaeSCornelia Huck return &parent->kobj; 836c744aeaeSCornelia Huck return NULL; 837c744aeaeSCornelia Huck } 838da231fd5SKay Sievers 839cebf8fd1SMing Lei static inline bool live_in_glue_dir(struct kobject *kobj, 840cebf8fd1SMing Lei struct device *dev) 841cebf8fd1SMing Lei { 842cebf8fd1SMing Lei if (!kobj || !dev->class || 843cebf8fd1SMing Lei kobj->kset != &dev->class->p->glue_dirs) 844cebf8fd1SMing Lei return false; 845cebf8fd1SMing Lei return true; 846cebf8fd1SMing Lei } 847cebf8fd1SMing Lei 848cebf8fd1SMing Lei static inline struct kobject *get_glue_dir(struct device *dev) 849cebf8fd1SMing Lei { 850cebf8fd1SMing Lei return dev->kobj.parent; 851cebf8fd1SMing Lei } 852cebf8fd1SMing Lei 853cebf8fd1SMing Lei /* 854cebf8fd1SMing Lei * make sure cleaning up dir as the last step, we need to make 855cebf8fd1SMing Lei * sure .release handler of kobject is run with holding the 856cebf8fd1SMing Lei * global lock 857cebf8fd1SMing Lei */ 85863b6971aSCornelia Huck static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) 859da231fd5SKay Sievers { 8600f4dafc0SKay Sievers /* see if we live in a "glue" directory */ 861cebf8fd1SMing Lei if (!live_in_glue_dir(glue_dir, dev)) 862da231fd5SKay Sievers return; 863da231fd5SKay Sievers 864e4a60d13SYijing Wang mutex_lock(&gdp_mutex); 8650f4dafc0SKay Sievers kobject_put(glue_dir); 866e4a60d13SYijing Wang mutex_unlock(&gdp_mutex); 867da231fd5SKay Sievers } 86863b6971aSCornelia Huck 8692ee97cafSCornelia Huck static int device_add_class_symlinks(struct device *dev) 8702ee97cafSCornelia Huck { 8715590f319SBenjamin Herrenschmidt struct device_node *of_node = dev_of_node(dev); 8722ee97cafSCornelia Huck int error; 8732ee97cafSCornelia Huck 8745590f319SBenjamin Herrenschmidt if (of_node) { 8755590f319SBenjamin Herrenschmidt error = sysfs_create_link(&dev->kobj, &of_node->kobj,"of_node"); 8765590f319SBenjamin Herrenschmidt if (error) 8775590f319SBenjamin Herrenschmidt dev_warn(dev, "Error %d creating of_node link\n",error); 8785590f319SBenjamin Herrenschmidt /* An error here doesn't warrant bringing down the device */ 8795590f319SBenjamin Herrenschmidt } 8805590f319SBenjamin Herrenschmidt 8812ee97cafSCornelia Huck if (!dev->class) 8822ee97cafSCornelia Huck return 0; 883da231fd5SKay Sievers 8841fbfee6cSGreg Kroah-Hartman error = sysfs_create_link(&dev->kobj, 8856b6e39a6SKay Sievers &dev->class->p->subsys.kobj, 8862ee97cafSCornelia Huck "subsystem"); 8872ee97cafSCornelia Huck if (error) 8885590f319SBenjamin Herrenschmidt goto out_devnode; 889da231fd5SKay Sievers 8904e886c29SGreg Kroah-Hartman if (dev->parent && device_is_not_partition(dev)) { 8914f01a757SDmitry Torokhov error = sysfs_create_link(&dev->kobj, &dev->parent->kobj, 8924f01a757SDmitry Torokhov "device"); 8934f01a757SDmitry Torokhov if (error) 89439aba963SKay Sievers goto out_subsys; 8952ee97cafSCornelia Huck } 89639aba963SKay Sievers 897ead454feSRandy Dunlap #ifdef CONFIG_BLOCK 89839aba963SKay Sievers /* /sys/block has directories and does not need symlinks */ 899e52eec13SAndi Kleen if (sysfs_deprecated && dev->class == &block_class) 90039aba963SKay Sievers return 0; 901ead454feSRandy Dunlap #endif 90239aba963SKay Sievers 90339aba963SKay Sievers /* link in the class directory pointing to the device */ 9046b6e39a6SKay Sievers error = sysfs_create_link(&dev->class->p->subsys.kobj, 90539aba963SKay Sievers &dev->kobj, dev_name(dev)); 90639aba963SKay Sievers if (error) 90739aba963SKay Sievers goto out_device; 90839aba963SKay Sievers 9092ee97cafSCornelia Huck return 0; 9102ee97cafSCornelia Huck 91139aba963SKay Sievers out_device: 91239aba963SKay Sievers sysfs_remove_link(&dev->kobj, "device"); 913da231fd5SKay Sievers 9142ee97cafSCornelia Huck out_subsys: 9152ee97cafSCornelia Huck sysfs_remove_link(&dev->kobj, "subsystem"); 9165590f319SBenjamin Herrenschmidt out_devnode: 9175590f319SBenjamin Herrenschmidt sysfs_remove_link(&dev->kobj, "of_node"); 9182ee97cafSCornelia Huck return error; 9192ee97cafSCornelia Huck } 9202ee97cafSCornelia Huck 9212ee97cafSCornelia Huck static void device_remove_class_symlinks(struct device *dev) 9222ee97cafSCornelia Huck { 9235590f319SBenjamin Herrenschmidt if (dev_of_node(dev)) 9245590f319SBenjamin Herrenschmidt sysfs_remove_link(&dev->kobj, "of_node"); 9255590f319SBenjamin Herrenschmidt 9262ee97cafSCornelia Huck if (!dev->class) 9272ee97cafSCornelia Huck return; 928da231fd5SKay Sievers 9294e886c29SGreg Kroah-Hartman if (dev->parent && device_is_not_partition(dev)) 930da231fd5SKay Sievers sysfs_remove_link(&dev->kobj, "device"); 9312ee97cafSCornelia Huck sysfs_remove_link(&dev->kobj, "subsystem"); 932ead454feSRandy Dunlap #ifdef CONFIG_BLOCK 933e52eec13SAndi Kleen if (sysfs_deprecated && dev->class == &block_class) 93439aba963SKay Sievers return; 935ead454feSRandy Dunlap #endif 9366b6e39a6SKay Sievers sysfs_delete_link(&dev->class->p->subsys.kobj, &dev->kobj, dev_name(dev)); 9372ee97cafSCornelia Huck } 9382ee97cafSCornelia Huck 9391da177e4SLinus Torvalds /** 940413c239fSStephen Rothwell * dev_set_name - set a device name 941413c239fSStephen Rothwell * @dev: device 94246232366SRandy Dunlap * @fmt: format string for the device's name 943413c239fSStephen Rothwell */ 944413c239fSStephen Rothwell int dev_set_name(struct device *dev, const char *fmt, ...) 945413c239fSStephen Rothwell { 946413c239fSStephen Rothwell va_list vargs; 9471fa5ae85SKay Sievers int err; 948413c239fSStephen Rothwell 949413c239fSStephen Rothwell va_start(vargs, fmt); 9501fa5ae85SKay Sievers err = kobject_set_name_vargs(&dev->kobj, fmt, vargs); 951413c239fSStephen Rothwell va_end(vargs); 9521fa5ae85SKay Sievers return err; 953413c239fSStephen Rothwell } 954413c239fSStephen Rothwell EXPORT_SYMBOL_GPL(dev_set_name); 955413c239fSStephen Rothwell 956413c239fSStephen Rothwell /** 957e105b8bfSDan Williams * device_to_dev_kobj - select a /sys/dev/ directory for the device 958e105b8bfSDan Williams * @dev: device 959e105b8bfSDan Williams * 960e105b8bfSDan Williams * By default we select char/ for new entries. Setting class->dev_obj 961e105b8bfSDan Williams * to NULL prevents an entry from being created. class->dev_kobj must 962e105b8bfSDan Williams * be set (or cleared) before any devices are registered to the class 963e105b8bfSDan Williams * otherwise device_create_sys_dev_entry() and 9640d4e293cSPeter Korsgaard * device_remove_sys_dev_entry() will disagree about the presence of 9650d4e293cSPeter Korsgaard * the link. 966e105b8bfSDan Williams */ 967e105b8bfSDan Williams static struct kobject *device_to_dev_kobj(struct device *dev) 968e105b8bfSDan Williams { 969e105b8bfSDan Williams struct kobject *kobj; 970e105b8bfSDan Williams 971e105b8bfSDan Williams if (dev->class) 972e105b8bfSDan Williams kobj = dev->class->dev_kobj; 973e105b8bfSDan Williams else 974e105b8bfSDan Williams kobj = sysfs_dev_char_kobj; 975e105b8bfSDan Williams 976e105b8bfSDan Williams return kobj; 977e105b8bfSDan Williams } 978e105b8bfSDan Williams 979e105b8bfSDan Williams static int device_create_sys_dev_entry(struct device *dev) 980e105b8bfSDan Williams { 981e105b8bfSDan Williams struct kobject *kobj = device_to_dev_kobj(dev); 982e105b8bfSDan Williams int error = 0; 983e105b8bfSDan Williams char devt_str[15]; 984e105b8bfSDan Williams 985e105b8bfSDan Williams if (kobj) { 986e105b8bfSDan Williams format_dev_t(devt_str, dev->devt); 987e105b8bfSDan Williams error = sysfs_create_link(kobj, &dev->kobj, devt_str); 988e105b8bfSDan Williams } 989e105b8bfSDan Williams 990e105b8bfSDan Williams return error; 991e105b8bfSDan Williams } 992e105b8bfSDan Williams 993e105b8bfSDan Williams static void device_remove_sys_dev_entry(struct device *dev) 994e105b8bfSDan Williams { 995e105b8bfSDan Williams struct kobject *kobj = device_to_dev_kobj(dev); 996e105b8bfSDan Williams char devt_str[15]; 997e105b8bfSDan Williams 998e105b8bfSDan Williams if (kobj) { 999e105b8bfSDan Williams format_dev_t(devt_str, dev->devt); 1000e105b8bfSDan Williams sysfs_remove_link(kobj, devt_str); 1001e105b8bfSDan Williams } 1002e105b8bfSDan Williams } 1003e105b8bfSDan Williams 1004b4028437SGreg Kroah-Hartman int device_private_init(struct device *dev) 1005b4028437SGreg Kroah-Hartman { 1006b4028437SGreg Kroah-Hartman dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL); 1007b4028437SGreg Kroah-Hartman if (!dev->p) 1008b4028437SGreg Kroah-Hartman return -ENOMEM; 1009b4028437SGreg Kroah-Hartman dev->p->device = dev; 1010b4028437SGreg Kroah-Hartman klist_init(&dev->p->klist_children, klist_children_get, 1011b4028437SGreg Kroah-Hartman klist_children_put); 1012ef8a3fd6SGreg Kroah-Hartman INIT_LIST_HEAD(&dev->p->deferred_probe); 1013b4028437SGreg Kroah-Hartman return 0; 1014b4028437SGreg Kroah-Hartman } 1015b4028437SGreg Kroah-Hartman 1016e105b8bfSDan Williams /** 10171da177e4SLinus Torvalds * device_add - add device to device hierarchy. 10181da177e4SLinus Torvalds * @dev: device. 10191da177e4SLinus Torvalds * 10201da177e4SLinus Torvalds * This is part 2 of device_register(), though may be called 10211da177e4SLinus Torvalds * separately _iff_ device_initialize() has been called separately. 10221da177e4SLinus Torvalds * 10235739411aSCornelia Huck * This adds @dev to the kobject hierarchy via kobject_add(), adds it 10241da177e4SLinus Torvalds * to the global and sibling lists for the device, then 10251da177e4SLinus Torvalds * adds it to the other relevant subsystems of the driver model. 10265739411aSCornelia Huck * 1027b10d5efdSAlan Stern * Do not call this routine or device_register() more than once for 1028b10d5efdSAlan Stern * any device structure. The driver model core is not designed to work 1029b10d5efdSAlan Stern * with devices that get unregistered and then spring back to life. 1030b10d5efdSAlan Stern * (Among other things, it's very hard to guarantee that all references 1031b10d5efdSAlan Stern * to the previous incarnation of @dev have been dropped.) Allocate 1032b10d5efdSAlan Stern * and register a fresh new struct device instead. 1033b10d5efdSAlan Stern * 10345739411aSCornelia Huck * NOTE: _Never_ directly free @dev after calling this function, even 10355739411aSCornelia Huck * if it returned an error! Always use put_device() to give up your 10365739411aSCornelia Huck * reference instead. 10371da177e4SLinus Torvalds */ 10381da177e4SLinus Torvalds int device_add(struct device *dev) 10391da177e4SLinus Torvalds { 10401da177e4SLinus Torvalds struct device *parent = NULL; 1041ca22e56dSKay Sievers struct kobject *kobj; 1042c47ed219SGreg Kroah-Hartman struct class_interface *class_intf; 1043c906a48aSGreg Kroah-Hartman int error = -EINVAL; 1044cebf8fd1SMing Lei struct kobject *glue_dir = NULL; 1045775b64d2SRafael J. Wysocki 10461da177e4SLinus Torvalds dev = get_device(dev); 1047c906a48aSGreg Kroah-Hartman if (!dev) 1048c906a48aSGreg Kroah-Hartman goto done; 1049c906a48aSGreg Kroah-Hartman 1050fb069a5dSGreg Kroah-Hartman if (!dev->p) { 1051b4028437SGreg Kroah-Hartman error = device_private_init(dev); 1052b4028437SGreg Kroah-Hartman if (error) 1053fb069a5dSGreg Kroah-Hartman goto done; 1054fb069a5dSGreg Kroah-Hartman } 1055fb069a5dSGreg Kroah-Hartman 10561fa5ae85SKay Sievers /* 10571fa5ae85SKay Sievers * for statically allocated devices, which should all be converted 10581fa5ae85SKay Sievers * some day, we need to initialize the name. We prevent reading back 10591fa5ae85SKay Sievers * the name, and force the use of dev_name() 10601fa5ae85SKay Sievers */ 10611fa5ae85SKay Sievers if (dev->init_name) { 1062acc0e90fSGreg Kroah-Hartman dev_set_name(dev, "%s", dev->init_name); 10631fa5ae85SKay Sievers dev->init_name = NULL; 10641fa5ae85SKay Sievers } 1065c906a48aSGreg Kroah-Hartman 1066ca22e56dSKay Sievers /* subsystems can specify simple device enumeration */ 1067ca22e56dSKay Sievers if (!dev_name(dev) && dev->bus && dev->bus->dev_name) 1068ca22e56dSKay Sievers dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); 1069ca22e56dSKay Sievers 1070e6309e75SThomas Gleixner if (!dev_name(dev)) { 1071e6309e75SThomas Gleixner error = -EINVAL; 10725c8563d7SKay Sievers goto name_error; 1073e6309e75SThomas Gleixner } 10741da177e4SLinus Torvalds 10751e0b2cf9SKay Sievers pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 1076c205ef48SGreg Kroah-Hartman 10771da177e4SLinus Torvalds parent = get_device(dev->parent); 1078ca22e56dSKay Sievers kobj = get_device_parent(dev, parent); 1079ca22e56dSKay Sievers if (kobj) 1080ca22e56dSKay Sievers dev->kobj.parent = kobj; 10811da177e4SLinus Torvalds 10820d358f22SYinghai Lu /* use parent numa_node */ 108356f2de81SZhen Lei if (parent && (dev_to_node(dev) == NUMA_NO_NODE)) 10840d358f22SYinghai Lu set_dev_node(dev, dev_to_node(parent)); 10850d358f22SYinghai Lu 10861da177e4SLinus Torvalds /* first, register with generic layer. */ 10878a577ffcSKay Sievers /* we require the name to be set before, and pass NULL */ 10888a577ffcSKay Sievers error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); 1089cebf8fd1SMing Lei if (error) { 1090cebf8fd1SMing Lei glue_dir = get_glue_dir(dev); 10911da177e4SLinus Torvalds goto Error; 1092cebf8fd1SMing Lei } 1093a7fd6706SKay Sievers 109437022644SBrian Walsh /* notify platform of device entry */ 109537022644SBrian Walsh if (platform_notify) 109637022644SBrian Walsh platform_notify(dev); 109737022644SBrian Walsh 1098c5e064a6SGreg Kroah-Hartman error = device_create_file(dev, &dev_attr_uevent); 1099a306eea4SCornelia Huck if (error) 1100a306eea4SCornelia Huck goto attrError; 1101a7fd6706SKay Sievers 11022ee97cafSCornelia Huck error = device_add_class_symlinks(dev); 11032ee97cafSCornelia Huck if (error) 11042ee97cafSCornelia Huck goto SymlinkError; 1105dc0afa83SCornelia Huck error = device_add_attrs(dev); 1106dc0afa83SCornelia Huck if (error) 11072620efefSGreg Kroah-Hartman goto AttrsError; 1108dc0afa83SCornelia Huck error = bus_add_device(dev); 1109dc0afa83SCornelia Huck if (error) 11101da177e4SLinus Torvalds goto BusError; 11113b98aeafSAlan Stern error = dpm_sysfs_add(dev); 111257eee3d2SRafael J. Wysocki if (error) 11133b98aeafSAlan Stern goto DPMError; 11143b98aeafSAlan Stern device_pm_add(dev); 1115ec0676eeSAlan Stern 11160cd75047SSergey Klyaus if (MAJOR(dev->devt)) { 11170cd75047SSergey Klyaus error = device_create_file(dev, &dev_attr_dev); 11180cd75047SSergey Klyaus if (error) 11190cd75047SSergey Klyaus goto DevAttrError; 11200cd75047SSergey Klyaus 11210cd75047SSergey Klyaus error = device_create_sys_dev_entry(dev); 11220cd75047SSergey Klyaus if (error) 11230cd75047SSergey Klyaus goto SysEntryError; 11240cd75047SSergey Klyaus 11250cd75047SSergey Klyaus devtmpfs_create_node(dev); 11260cd75047SSergey Klyaus } 11270cd75047SSergey Klyaus 1128ec0676eeSAlan Stern /* Notify clients of device addition. This call must come 1129268863f4Smajianpeng * after dpm_sysfs_add() and before kobject_uevent(). 1130ec0676eeSAlan Stern */ 1131ec0676eeSAlan Stern if (dev->bus) 1132ec0676eeSAlan Stern blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 1133ec0676eeSAlan Stern BUS_NOTIFY_ADD_DEVICE, dev); 1134ec0676eeSAlan Stern 113553877d06SKay Sievers kobject_uevent(&dev->kobj, KOBJ_ADD); 11362023c610SAlan Stern bus_probe_device(dev); 11371da177e4SLinus Torvalds if (parent) 1138f791b8c8SGreg Kroah-Hartman klist_add_tail(&dev->p->knode_parent, 1139f791b8c8SGreg Kroah-Hartman &parent->p->klist_children); 11401da177e4SLinus Torvalds 11415d9fd169SGreg Kroah-Hartman if (dev->class) { 1142ca22e56dSKay Sievers mutex_lock(&dev->class->p->mutex); 1143c47ed219SGreg Kroah-Hartman /* tie the class to the device */ 11445a3ceb86STejun Heo klist_add_tail(&dev->knode_class, 11456b6e39a6SKay Sievers &dev->class->p->klist_devices); 1146c47ed219SGreg Kroah-Hartman 1147c47ed219SGreg Kroah-Hartman /* notify any interfaces that the device is here */ 1148184f1f77SGreg Kroah-Hartman list_for_each_entry(class_intf, 1149ca22e56dSKay Sievers &dev->class->p->interfaces, node) 1150c47ed219SGreg Kroah-Hartman if (class_intf->add_dev) 1151c47ed219SGreg Kroah-Hartman class_intf->add_dev(dev, class_intf); 1152ca22e56dSKay Sievers mutex_unlock(&dev->class->p->mutex); 11535d9fd169SGreg Kroah-Hartman } 1154c906a48aSGreg Kroah-Hartman done: 11551da177e4SLinus Torvalds put_device(dev); 11561da177e4SLinus Torvalds return error; 11570cd75047SSergey Klyaus SysEntryError: 11580cd75047SSergey Klyaus if (MAJOR(dev->devt)) 11590cd75047SSergey Klyaus device_remove_file(dev, &dev_attr_dev); 11600cd75047SSergey Klyaus DevAttrError: 11610cd75047SSergey Klyaus device_pm_remove(dev); 11620cd75047SSergey Klyaus dpm_sysfs_remove(dev); 11633b98aeafSAlan Stern DPMError: 116457eee3d2SRafael J. Wysocki bus_remove_device(dev); 116557eee3d2SRafael J. Wysocki BusError: 11662620efefSGreg Kroah-Hartman device_remove_attrs(dev); 11672620efefSGreg Kroah-Hartman AttrsError: 11682ee97cafSCornelia Huck device_remove_class_symlinks(dev); 11692ee97cafSCornelia Huck SymlinkError: 1170c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_uevent); 117123681e47SGreg Kroah-Hartman attrError: 1172312c004dSKay Sievers kobject_uevent(&dev->kobj, KOBJ_REMOVE); 1173cebf8fd1SMing Lei glue_dir = get_glue_dir(dev); 11741da177e4SLinus Torvalds kobject_del(&dev->kobj); 11751da177e4SLinus Torvalds Error: 1176cebf8fd1SMing Lei cleanup_glue_dir(dev, glue_dir); 11771da177e4SLinus Torvalds put_device(parent); 11785c8563d7SKay Sievers name_error: 11795c8563d7SKay Sievers kfree(dev->p); 11805c8563d7SKay Sievers dev->p = NULL; 1181c906a48aSGreg Kroah-Hartman goto done; 11821da177e4SLinus Torvalds } 118386df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_add); 11841da177e4SLinus Torvalds 11851da177e4SLinus Torvalds /** 11861da177e4SLinus Torvalds * device_register - register a device with the system. 11871da177e4SLinus Torvalds * @dev: pointer to the device structure 11881da177e4SLinus Torvalds * 11891da177e4SLinus Torvalds * This happens in two clean steps - initialize the device 11901da177e4SLinus Torvalds * and add it to the system. The two steps can be called 11911da177e4SLinus Torvalds * separately, but this is the easiest and most common. 11921da177e4SLinus Torvalds * I.e. you should only call the two helpers separately if 11931da177e4SLinus Torvalds * have a clearly defined need to use and refcount the device 11941da177e4SLinus Torvalds * before it is added to the hierarchy. 11955739411aSCornelia Huck * 1196b10d5efdSAlan Stern * For more information, see the kerneldoc for device_initialize() 1197b10d5efdSAlan Stern * and device_add(). 1198b10d5efdSAlan Stern * 11995739411aSCornelia Huck * NOTE: _Never_ directly free @dev after calling this function, even 12005739411aSCornelia Huck * if it returned an error! Always use put_device() to give up the 12015739411aSCornelia Huck * reference initialized in this function instead. 12021da177e4SLinus Torvalds */ 12031da177e4SLinus Torvalds int device_register(struct device *dev) 12041da177e4SLinus Torvalds { 12051da177e4SLinus Torvalds device_initialize(dev); 12061da177e4SLinus Torvalds return device_add(dev); 12071da177e4SLinus Torvalds } 120886df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_register); 12091da177e4SLinus Torvalds 12101da177e4SLinus Torvalds /** 12111da177e4SLinus Torvalds * get_device - increment reference count for device. 12121da177e4SLinus Torvalds * @dev: device. 12131da177e4SLinus Torvalds * 12141da177e4SLinus Torvalds * This simply forwards the call to kobject_get(), though 12151da177e4SLinus Torvalds * we do take care to provide for the case that we get a NULL 12161da177e4SLinus Torvalds * pointer passed in. 12171da177e4SLinus Torvalds */ 12181da177e4SLinus Torvalds struct device *get_device(struct device *dev) 12191da177e4SLinus Torvalds { 1220b0d1f807SLars-Peter Clausen return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL; 12211da177e4SLinus Torvalds } 122286df2687SDavid Graham White EXPORT_SYMBOL_GPL(get_device); 12231da177e4SLinus Torvalds 12241da177e4SLinus Torvalds /** 12251da177e4SLinus Torvalds * put_device - decrement reference count. 12261da177e4SLinus Torvalds * @dev: device in question. 12271da177e4SLinus Torvalds */ 12281da177e4SLinus Torvalds void put_device(struct device *dev) 12291da177e4SLinus Torvalds { 1230edfaa7c3SKay Sievers /* might_sleep(); */ 12311da177e4SLinus Torvalds if (dev) 12321da177e4SLinus Torvalds kobject_put(&dev->kobj); 12331da177e4SLinus Torvalds } 123486df2687SDavid Graham White EXPORT_SYMBOL_GPL(put_device); 12351da177e4SLinus Torvalds 12361da177e4SLinus Torvalds /** 12371da177e4SLinus Torvalds * device_del - delete device from system. 12381da177e4SLinus Torvalds * @dev: device. 12391da177e4SLinus Torvalds * 12401da177e4SLinus Torvalds * This is the first part of the device unregistration 12411da177e4SLinus Torvalds * sequence. This removes the device from the lists we control 12421da177e4SLinus Torvalds * from here, has it removed from the other driver model 12431da177e4SLinus Torvalds * subsystems it was added to in device_add(), and removes it 12441da177e4SLinus Torvalds * from the kobject hierarchy. 12451da177e4SLinus Torvalds * 12461da177e4SLinus Torvalds * NOTE: this should be called manually _iff_ device_add() was 12471da177e4SLinus Torvalds * also called manually. 12481da177e4SLinus Torvalds */ 12491da177e4SLinus Torvalds void device_del(struct device *dev) 12501da177e4SLinus Torvalds { 12511da177e4SLinus Torvalds struct device *parent = dev->parent; 1252cebf8fd1SMing Lei struct kobject *glue_dir = NULL; 1253c47ed219SGreg Kroah-Hartman struct class_interface *class_intf; 12541da177e4SLinus Torvalds 1255ec0676eeSAlan Stern /* Notify clients of device removal. This call must come 1256ec0676eeSAlan Stern * before dpm_sysfs_remove(). 1257ec0676eeSAlan Stern */ 1258ec0676eeSAlan Stern if (dev->bus) 1259ec0676eeSAlan Stern blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 1260ec0676eeSAlan Stern BUS_NOTIFY_DEL_DEVICE, dev); 12613b98aeafSAlan Stern dpm_sysfs_remove(dev); 12621da177e4SLinus Torvalds if (parent) 1263f791b8c8SGreg Kroah-Hartman klist_del(&dev->p->knode_parent); 1264e105b8bfSDan Williams if (MAJOR(dev->devt)) { 12652b2af54aSKay Sievers devtmpfs_delete_node(dev); 1266e105b8bfSDan Williams device_remove_sys_dev_entry(dev); 1267c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_dev); 1268e105b8bfSDan Williams } 1269b9d9c82bSKay Sievers if (dev->class) { 1270da231fd5SKay Sievers device_remove_class_symlinks(dev); 127199ef3ef8SKay Sievers 1272ca22e56dSKay Sievers mutex_lock(&dev->class->p->mutex); 1273c47ed219SGreg Kroah-Hartman /* notify any interfaces that the device is now gone */ 1274184f1f77SGreg Kroah-Hartman list_for_each_entry(class_intf, 1275ca22e56dSKay Sievers &dev->class->p->interfaces, node) 1276c47ed219SGreg Kroah-Hartman if (class_intf->remove_dev) 1277c47ed219SGreg Kroah-Hartman class_intf->remove_dev(dev, class_intf); 1278c47ed219SGreg Kroah-Hartman /* remove the device from the class list */ 12795a3ceb86STejun Heo klist_del(&dev->knode_class); 1280ca22e56dSKay Sievers mutex_unlock(&dev->class->p->mutex); 1281b9d9c82bSKay Sievers } 1282c5e064a6SGreg Kroah-Hartman device_remove_file(dev, &dev_attr_uevent); 12832620efefSGreg Kroah-Hartman device_remove_attrs(dev); 128428953533SBenjamin Herrenschmidt bus_remove_device(dev); 12854b6d1f12SLongX Zhang device_pm_remove(dev); 1286d1c3414cSGrant Likely driver_deferred_probe_del(dev); 12871da177e4SLinus Torvalds 12881da177e4SLinus Torvalds /* Notify the platform of the removal, in case they 12891da177e4SLinus Torvalds * need to do anything... 12901da177e4SLinus Torvalds */ 12911da177e4SLinus Torvalds if (platform_notify_remove) 12921da177e4SLinus Torvalds platform_notify_remove(dev); 1293599bad38SJoerg Roedel if (dev->bus) 1294599bad38SJoerg Roedel blocking_notifier_call_chain(&dev->bus->p->bus_notifier, 1295599bad38SJoerg Roedel BUS_NOTIFY_REMOVED_DEVICE, dev); 1296312c004dSKay Sievers kobject_uevent(&dev->kobj, KOBJ_REMOVE); 1297cebf8fd1SMing Lei glue_dir = get_glue_dir(dev); 12981da177e4SLinus Torvalds kobject_del(&dev->kobj); 1299cebf8fd1SMing Lei cleanup_glue_dir(dev, glue_dir); 13001da177e4SLinus Torvalds put_device(parent); 13011da177e4SLinus Torvalds } 130286df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_del); 13031da177e4SLinus Torvalds 13041da177e4SLinus Torvalds /** 13051da177e4SLinus Torvalds * device_unregister - unregister device from system. 13061da177e4SLinus Torvalds * @dev: device going away. 13071da177e4SLinus Torvalds * 13081da177e4SLinus Torvalds * We do this in two parts, like we do device_register(). First, 13091da177e4SLinus Torvalds * we remove it from all the subsystems with device_del(), then 13101da177e4SLinus Torvalds * we decrement the reference count via put_device(). If that 13111da177e4SLinus Torvalds * is the final reference count, the device will be cleaned up 13121da177e4SLinus Torvalds * via device_release() above. Otherwise, the structure will 13131da177e4SLinus Torvalds * stick around until the final reference to the device is dropped. 13141da177e4SLinus Torvalds */ 13151da177e4SLinus Torvalds void device_unregister(struct device *dev) 13161da177e4SLinus Torvalds { 13171e0b2cf9SKay Sievers pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 13181da177e4SLinus Torvalds device_del(dev); 13191da177e4SLinus Torvalds put_device(dev); 13201da177e4SLinus Torvalds } 132186df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_unregister); 13221da177e4SLinus Torvalds 13233d060aebSAndy Shevchenko static struct device *prev_device(struct klist_iter *i) 13243d060aebSAndy Shevchenko { 13253d060aebSAndy Shevchenko struct klist_node *n = klist_prev(i); 13263d060aebSAndy Shevchenko struct device *dev = NULL; 13273d060aebSAndy Shevchenko struct device_private *p; 13283d060aebSAndy Shevchenko 13293d060aebSAndy Shevchenko if (n) { 13303d060aebSAndy Shevchenko p = to_device_private_parent(n); 13313d060aebSAndy Shevchenko dev = p->device; 13323d060aebSAndy Shevchenko } 13333d060aebSAndy Shevchenko return dev; 13343d060aebSAndy Shevchenko } 13353d060aebSAndy Shevchenko 133636239577Smochel@digitalimplant.org static struct device *next_device(struct klist_iter *i) 133736239577Smochel@digitalimplant.org { 133836239577Smochel@digitalimplant.org struct klist_node *n = klist_next(i); 1339f791b8c8SGreg Kroah-Hartman struct device *dev = NULL; 1340f791b8c8SGreg Kroah-Hartman struct device_private *p; 1341f791b8c8SGreg Kroah-Hartman 1342f791b8c8SGreg Kroah-Hartman if (n) { 1343f791b8c8SGreg Kroah-Hartman p = to_device_private_parent(n); 1344f791b8c8SGreg Kroah-Hartman dev = p->device; 1345f791b8c8SGreg Kroah-Hartman } 1346f791b8c8SGreg Kroah-Hartman return dev; 134736239577Smochel@digitalimplant.org } 134836239577Smochel@digitalimplant.org 13491da177e4SLinus Torvalds /** 1350e454cea2SKay Sievers * device_get_devnode - path of device node file 13516fcf53acSKay Sievers * @dev: device 1352e454cea2SKay Sievers * @mode: returned file access mode 13533c2670e6SKay Sievers * @uid: returned file owner 13543c2670e6SKay Sievers * @gid: returned file group 13556fcf53acSKay Sievers * @tmp: possibly allocated string 13566fcf53acSKay Sievers * 13576fcf53acSKay Sievers * Return the relative path of a possible device node. 13586fcf53acSKay Sievers * Non-default names may need to allocate a memory to compose 13596fcf53acSKay Sievers * a name. This memory is returned in tmp and needs to be 13606fcf53acSKay Sievers * freed by the caller. 13616fcf53acSKay Sievers */ 1362e454cea2SKay Sievers const char *device_get_devnode(struct device *dev, 13634e4098a3SGreg Kroah-Hartman umode_t *mode, kuid_t *uid, kgid_t *gid, 13643c2670e6SKay Sievers const char **tmp) 13656fcf53acSKay Sievers { 13666fcf53acSKay Sievers char *s; 13676fcf53acSKay Sievers 13686fcf53acSKay Sievers *tmp = NULL; 13696fcf53acSKay Sievers 13706fcf53acSKay Sievers /* the device type may provide a specific name */ 1371e454cea2SKay Sievers if (dev->type && dev->type->devnode) 13723c2670e6SKay Sievers *tmp = dev->type->devnode(dev, mode, uid, gid); 13736fcf53acSKay Sievers if (*tmp) 13746fcf53acSKay Sievers return *tmp; 13756fcf53acSKay Sievers 13766fcf53acSKay Sievers /* the class may provide a specific name */ 1377e454cea2SKay Sievers if (dev->class && dev->class->devnode) 1378e454cea2SKay Sievers *tmp = dev->class->devnode(dev, mode); 13796fcf53acSKay Sievers if (*tmp) 13806fcf53acSKay Sievers return *tmp; 13816fcf53acSKay Sievers 13826fcf53acSKay Sievers /* return name without allocation, tmp == NULL */ 13836fcf53acSKay Sievers if (strchr(dev_name(dev), '!') == NULL) 13846fcf53acSKay Sievers return dev_name(dev); 13856fcf53acSKay Sievers 13866fcf53acSKay Sievers /* replace '!' in the name with '/' */ 1387a29fd614SRasmus Villemoes s = kstrdup(dev_name(dev), GFP_KERNEL); 1388a29fd614SRasmus Villemoes if (!s) 13896fcf53acSKay Sievers return NULL; 1390a29fd614SRasmus Villemoes strreplace(s, '!', '/'); 1391a29fd614SRasmus Villemoes return *tmp = s; 13926fcf53acSKay Sievers } 13936fcf53acSKay Sievers 13946fcf53acSKay Sievers /** 13951da177e4SLinus Torvalds * device_for_each_child - device child iterator. 1396c41455fbSRandy Dunlap * @parent: parent struct device. 13971da177e4SLinus Torvalds * @fn: function to be called for each device. 1398f8878dcbSRobert P. J. Day * @data: data for the callback. 13991da177e4SLinus Torvalds * 1400c41455fbSRandy Dunlap * Iterate over @parent's child devices, and call @fn for each, 14011da177e4SLinus Torvalds * passing it @data. 14021da177e4SLinus Torvalds * 14031da177e4SLinus Torvalds * We check the return of @fn each time. If it returns anything 14041da177e4SLinus Torvalds * other than 0, we break out and return that value. 14051da177e4SLinus Torvalds */ 140636239577Smochel@digitalimplant.org int device_for_each_child(struct device *parent, void *data, 14074a3ad20cSGreg Kroah-Hartman int (*fn)(struct device *dev, void *data)) 14081da177e4SLinus Torvalds { 140936239577Smochel@digitalimplant.org struct klist_iter i; 14101da177e4SLinus Torvalds struct device *child; 14111da177e4SLinus Torvalds int error = 0; 14121da177e4SLinus Torvalds 1413014c90dbSGreg Kroah-Hartman if (!parent->p) 1414014c90dbSGreg Kroah-Hartman return 0; 1415014c90dbSGreg Kroah-Hartman 1416f791b8c8SGreg Kroah-Hartman klist_iter_init(&parent->p->klist_children, &i); 141736239577Smochel@digitalimplant.org while ((child = next_device(&i)) && !error) 141836239577Smochel@digitalimplant.org error = fn(child, data); 141936239577Smochel@digitalimplant.org klist_iter_exit(&i); 14201da177e4SLinus Torvalds return error; 14211da177e4SLinus Torvalds } 142286df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_for_each_child); 14231da177e4SLinus Torvalds 14245ab69981SCornelia Huck /** 14253d060aebSAndy Shevchenko * device_for_each_child_reverse - device child iterator in reversed order. 14263d060aebSAndy Shevchenko * @parent: parent struct device. 14273d060aebSAndy Shevchenko * @fn: function to be called for each device. 14283d060aebSAndy Shevchenko * @data: data for the callback. 14293d060aebSAndy Shevchenko * 14303d060aebSAndy Shevchenko * Iterate over @parent's child devices, and call @fn for each, 14313d060aebSAndy Shevchenko * passing it @data. 14323d060aebSAndy Shevchenko * 14333d060aebSAndy Shevchenko * We check the return of @fn each time. If it returns anything 14343d060aebSAndy Shevchenko * other than 0, we break out and return that value. 14353d060aebSAndy Shevchenko */ 14363d060aebSAndy Shevchenko int device_for_each_child_reverse(struct device *parent, void *data, 14373d060aebSAndy Shevchenko int (*fn)(struct device *dev, void *data)) 14383d060aebSAndy Shevchenko { 14393d060aebSAndy Shevchenko struct klist_iter i; 14403d060aebSAndy Shevchenko struct device *child; 14413d060aebSAndy Shevchenko int error = 0; 14423d060aebSAndy Shevchenko 14433d060aebSAndy Shevchenko if (!parent->p) 14443d060aebSAndy Shevchenko return 0; 14453d060aebSAndy Shevchenko 14463d060aebSAndy Shevchenko klist_iter_init(&parent->p->klist_children, &i); 14473d060aebSAndy Shevchenko while ((child = prev_device(&i)) && !error) 14483d060aebSAndy Shevchenko error = fn(child, data); 14493d060aebSAndy Shevchenko klist_iter_exit(&i); 14503d060aebSAndy Shevchenko return error; 14513d060aebSAndy Shevchenko } 14523d060aebSAndy Shevchenko EXPORT_SYMBOL_GPL(device_for_each_child_reverse); 14533d060aebSAndy Shevchenko 14543d060aebSAndy Shevchenko /** 14555ab69981SCornelia Huck * device_find_child - device iterator for locating a particular device. 14565ab69981SCornelia Huck * @parent: parent struct device 14575ab69981SCornelia Huck * @match: Callback function to check device 1458f8878dcbSRobert P. J. Day * @data: Data to pass to match function 14595ab69981SCornelia Huck * 14605ab69981SCornelia Huck * This is similar to the device_for_each_child() function above, but it 14615ab69981SCornelia Huck * returns a reference to a device that is 'found' for later use, as 14625ab69981SCornelia Huck * determined by the @match callback. 14635ab69981SCornelia Huck * 14645ab69981SCornelia Huck * The callback should return 0 if the device doesn't match and non-zero 14655ab69981SCornelia Huck * if it does. If the callback returns non-zero and a reference to the 14665ab69981SCornelia Huck * current device can be obtained, this function will return to the caller 14675ab69981SCornelia Huck * and not iterate over any more devices. 1468a4e2400aSFederico Vaga * 1469a4e2400aSFederico Vaga * NOTE: you will need to drop the reference with put_device() after use. 14705ab69981SCornelia Huck */ 14715ab69981SCornelia Huck struct device *device_find_child(struct device *parent, void *data, 14724a3ad20cSGreg Kroah-Hartman int (*match)(struct device *dev, void *data)) 14735ab69981SCornelia Huck { 14745ab69981SCornelia Huck struct klist_iter i; 14755ab69981SCornelia Huck struct device *child; 14765ab69981SCornelia Huck 14775ab69981SCornelia Huck if (!parent) 14785ab69981SCornelia Huck return NULL; 14795ab69981SCornelia Huck 1480f791b8c8SGreg Kroah-Hartman klist_iter_init(&parent->p->klist_children, &i); 14815ab69981SCornelia Huck while ((child = next_device(&i))) 14825ab69981SCornelia Huck if (match(child, data) && get_device(child)) 14835ab69981SCornelia Huck break; 14845ab69981SCornelia Huck klist_iter_exit(&i); 14855ab69981SCornelia Huck return child; 14865ab69981SCornelia Huck } 148786df2687SDavid Graham White EXPORT_SYMBOL_GPL(device_find_child); 14885ab69981SCornelia Huck 14891da177e4SLinus Torvalds int __init devices_init(void) 14901da177e4SLinus Torvalds { 1491881c6cfdSGreg Kroah-Hartman devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); 1492881c6cfdSGreg Kroah-Hartman if (!devices_kset) 1493881c6cfdSGreg Kroah-Hartman return -ENOMEM; 1494e105b8bfSDan Williams dev_kobj = kobject_create_and_add("dev", NULL); 1495e105b8bfSDan Williams if (!dev_kobj) 1496e105b8bfSDan Williams goto dev_kobj_err; 1497e105b8bfSDan Williams sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); 1498e105b8bfSDan Williams if (!sysfs_dev_block_kobj) 1499e105b8bfSDan Williams goto block_kobj_err; 1500e105b8bfSDan Williams sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); 1501e105b8bfSDan Williams if (!sysfs_dev_char_kobj) 1502e105b8bfSDan Williams goto char_kobj_err; 1503e105b8bfSDan Williams 1504881c6cfdSGreg Kroah-Hartman return 0; 1505e105b8bfSDan Williams 1506e105b8bfSDan Williams char_kobj_err: 1507e105b8bfSDan Williams kobject_put(sysfs_dev_block_kobj); 1508e105b8bfSDan Williams block_kobj_err: 1509e105b8bfSDan Williams kobject_put(dev_kobj); 1510e105b8bfSDan Williams dev_kobj_err: 1511e105b8bfSDan Williams kset_unregister(devices_kset); 1512e105b8bfSDan Williams return -ENOMEM; 15131da177e4SLinus Torvalds } 15141da177e4SLinus Torvalds 15154f3549d7SRafael J. Wysocki static int device_check_offline(struct device *dev, void *not_used) 15164f3549d7SRafael J. Wysocki { 15174f3549d7SRafael J. Wysocki int ret; 15184f3549d7SRafael J. Wysocki 15194f3549d7SRafael J. Wysocki ret = device_for_each_child(dev, NULL, device_check_offline); 15204f3549d7SRafael J. Wysocki if (ret) 15214f3549d7SRafael J. Wysocki return ret; 15224f3549d7SRafael J. Wysocki 15234f3549d7SRafael J. Wysocki return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0; 15244f3549d7SRafael J. Wysocki } 15254f3549d7SRafael J. Wysocki 15264f3549d7SRafael J. Wysocki /** 15274f3549d7SRafael J. Wysocki * device_offline - Prepare the device for hot-removal. 15284f3549d7SRafael J. Wysocki * @dev: Device to be put offline. 15294f3549d7SRafael J. Wysocki * 15304f3549d7SRafael J. Wysocki * Execute the device bus type's .offline() callback, if present, to prepare 15314f3549d7SRafael J. Wysocki * the device for a subsequent hot-removal. If that succeeds, the device must 15324f3549d7SRafael J. Wysocki * not be used until either it is removed or its bus type's .online() callback 15334f3549d7SRafael J. Wysocki * is executed. 15344f3549d7SRafael J. Wysocki * 15354f3549d7SRafael J. Wysocki * Call under device_hotplug_lock. 15364f3549d7SRafael J. Wysocki */ 15374f3549d7SRafael J. Wysocki int device_offline(struct device *dev) 15384f3549d7SRafael J. Wysocki { 15394f3549d7SRafael J. Wysocki int ret; 15404f3549d7SRafael J. Wysocki 15414f3549d7SRafael J. Wysocki if (dev->offline_disabled) 15424f3549d7SRafael J. Wysocki return -EPERM; 15434f3549d7SRafael J. Wysocki 15444f3549d7SRafael J. Wysocki ret = device_for_each_child(dev, NULL, device_check_offline); 15454f3549d7SRafael J. Wysocki if (ret) 15464f3549d7SRafael J. Wysocki return ret; 15474f3549d7SRafael J. Wysocki 15484f3549d7SRafael J. Wysocki device_lock(dev); 15494f3549d7SRafael J. Wysocki if (device_supports_offline(dev)) { 15504f3549d7SRafael J. Wysocki if (dev->offline) { 15514f3549d7SRafael J. Wysocki ret = 1; 15524f3549d7SRafael J. Wysocki } else { 15534f3549d7SRafael J. Wysocki ret = dev->bus->offline(dev); 15544f3549d7SRafael J. Wysocki if (!ret) { 15554f3549d7SRafael J. Wysocki kobject_uevent(&dev->kobj, KOBJ_OFFLINE); 15564f3549d7SRafael J. Wysocki dev->offline = true; 15574f3549d7SRafael J. Wysocki } 15584f3549d7SRafael J. Wysocki } 15594f3549d7SRafael J. Wysocki } 15604f3549d7SRafael J. Wysocki device_unlock(dev); 15614f3549d7SRafael J. Wysocki 15624f3549d7SRafael J. Wysocki return ret; 15634f3549d7SRafael J. Wysocki } 15644f3549d7SRafael J. Wysocki 15654f3549d7SRafael J. Wysocki /** 15664f3549d7SRafael J. Wysocki * device_online - Put the device back online after successful device_offline(). 15674f3549d7SRafael J. Wysocki * @dev: Device to be put back online. 15684f3549d7SRafael J. Wysocki * 15694f3549d7SRafael J. Wysocki * If device_offline() has been successfully executed for @dev, but the device 15704f3549d7SRafael J. Wysocki * has not been removed subsequently, execute its bus type's .online() callback 15714f3549d7SRafael J. Wysocki * to indicate that the device can be used again. 15724f3549d7SRafael J. Wysocki * 15734f3549d7SRafael J. Wysocki * Call under device_hotplug_lock. 15744f3549d7SRafael J. Wysocki */ 15754f3549d7SRafael J. Wysocki int device_online(struct device *dev) 15764f3549d7SRafael J. Wysocki { 15774f3549d7SRafael J. Wysocki int ret = 0; 15784f3549d7SRafael J. Wysocki 15794f3549d7SRafael J. Wysocki device_lock(dev); 15804f3549d7SRafael J. Wysocki if (device_supports_offline(dev)) { 15814f3549d7SRafael J. Wysocki if (dev->offline) { 15824f3549d7SRafael J. Wysocki ret = dev->bus->online(dev); 15834f3549d7SRafael J. Wysocki if (!ret) { 15844f3549d7SRafael J. Wysocki kobject_uevent(&dev->kobj, KOBJ_ONLINE); 15854f3549d7SRafael J. Wysocki dev->offline = false; 15864f3549d7SRafael J. Wysocki } 15874f3549d7SRafael J. Wysocki } else { 15884f3549d7SRafael J. Wysocki ret = 1; 15894f3549d7SRafael J. Wysocki } 15904f3549d7SRafael J. Wysocki } 15914f3549d7SRafael J. Wysocki device_unlock(dev); 15924f3549d7SRafael J. Wysocki 15934f3549d7SRafael J. Wysocki return ret; 15944f3549d7SRafael J. Wysocki } 15954f3549d7SRafael J. Wysocki 15967f100d15SKarthigan Srinivasan struct root_device { 15970aa0dc41SMark McLoughlin struct device dev; 15980aa0dc41SMark McLoughlin struct module *owner; 15990aa0dc41SMark McLoughlin }; 16000aa0dc41SMark McLoughlin 160193058424SJosh Triplett static inline struct root_device *to_root_device(struct device *d) 1602481e2079SFerenc Wagner { 1603481e2079SFerenc Wagner return container_of(d, struct root_device, dev); 1604481e2079SFerenc Wagner } 16050aa0dc41SMark McLoughlin 16060aa0dc41SMark McLoughlin static void root_device_release(struct device *dev) 16070aa0dc41SMark McLoughlin { 16080aa0dc41SMark McLoughlin kfree(to_root_device(dev)); 16090aa0dc41SMark McLoughlin } 16100aa0dc41SMark McLoughlin 16110aa0dc41SMark McLoughlin /** 16120aa0dc41SMark McLoughlin * __root_device_register - allocate and register a root device 16130aa0dc41SMark McLoughlin * @name: root device name 16140aa0dc41SMark McLoughlin * @owner: owner module of the root device, usually THIS_MODULE 16150aa0dc41SMark McLoughlin * 16160aa0dc41SMark McLoughlin * This function allocates a root device and registers it 16170aa0dc41SMark McLoughlin * using device_register(). In order to free the returned 16180aa0dc41SMark McLoughlin * device, use root_device_unregister(). 16190aa0dc41SMark McLoughlin * 16200aa0dc41SMark McLoughlin * Root devices are dummy devices which allow other devices 16210aa0dc41SMark McLoughlin * to be grouped under /sys/devices. Use this function to 16220aa0dc41SMark McLoughlin * allocate a root device and then use it as the parent of 16230aa0dc41SMark McLoughlin * any device which should appear under /sys/devices/{name} 16240aa0dc41SMark McLoughlin * 16250aa0dc41SMark McLoughlin * The /sys/devices/{name} directory will also contain a 16260aa0dc41SMark McLoughlin * 'module' symlink which points to the @owner directory 16270aa0dc41SMark McLoughlin * in sysfs. 16280aa0dc41SMark McLoughlin * 1629f0eae0edSJani Nikula * Returns &struct device pointer on success, or ERR_PTR() on error. 1630f0eae0edSJani Nikula * 16310aa0dc41SMark McLoughlin * Note: You probably want to use root_device_register(). 16320aa0dc41SMark McLoughlin */ 16330aa0dc41SMark McLoughlin struct device *__root_device_register(const char *name, struct module *owner) 16340aa0dc41SMark McLoughlin { 16350aa0dc41SMark McLoughlin struct root_device *root; 16360aa0dc41SMark McLoughlin int err = -ENOMEM; 16370aa0dc41SMark McLoughlin 16380aa0dc41SMark McLoughlin root = kzalloc(sizeof(struct root_device), GFP_KERNEL); 16390aa0dc41SMark McLoughlin if (!root) 16400aa0dc41SMark McLoughlin return ERR_PTR(err); 16410aa0dc41SMark McLoughlin 1642acc0e90fSGreg Kroah-Hartman err = dev_set_name(&root->dev, "%s", name); 16430aa0dc41SMark McLoughlin if (err) { 16440aa0dc41SMark McLoughlin kfree(root); 16450aa0dc41SMark McLoughlin return ERR_PTR(err); 16460aa0dc41SMark McLoughlin } 16470aa0dc41SMark McLoughlin 16480aa0dc41SMark McLoughlin root->dev.release = root_device_release; 16490aa0dc41SMark McLoughlin 16500aa0dc41SMark McLoughlin err = device_register(&root->dev); 16510aa0dc41SMark McLoughlin if (err) { 16520aa0dc41SMark McLoughlin put_device(&root->dev); 16530aa0dc41SMark McLoughlin return ERR_PTR(err); 16540aa0dc41SMark McLoughlin } 16550aa0dc41SMark McLoughlin 16561d9e882bSChristoph Egger #ifdef CONFIG_MODULES /* gotta find a "cleaner" way to do this */ 16570aa0dc41SMark McLoughlin if (owner) { 16580aa0dc41SMark McLoughlin struct module_kobject *mk = &owner->mkobj; 16590aa0dc41SMark McLoughlin 16600aa0dc41SMark McLoughlin err = sysfs_create_link(&root->dev.kobj, &mk->kobj, "module"); 16610aa0dc41SMark McLoughlin if (err) { 16620aa0dc41SMark McLoughlin device_unregister(&root->dev); 16630aa0dc41SMark McLoughlin return ERR_PTR(err); 16640aa0dc41SMark McLoughlin } 16650aa0dc41SMark McLoughlin root->owner = owner; 16660aa0dc41SMark McLoughlin } 16670aa0dc41SMark McLoughlin #endif 16680aa0dc41SMark McLoughlin 16690aa0dc41SMark McLoughlin return &root->dev; 16700aa0dc41SMark McLoughlin } 16710aa0dc41SMark McLoughlin EXPORT_SYMBOL_GPL(__root_device_register); 16720aa0dc41SMark McLoughlin 16730aa0dc41SMark McLoughlin /** 16740aa0dc41SMark McLoughlin * root_device_unregister - unregister and free a root device 16757cbcf225SRandy Dunlap * @dev: device going away 16760aa0dc41SMark McLoughlin * 16770aa0dc41SMark McLoughlin * This function unregisters and cleans up a device that was created by 16780aa0dc41SMark McLoughlin * root_device_register(). 16790aa0dc41SMark McLoughlin */ 16800aa0dc41SMark McLoughlin void root_device_unregister(struct device *dev) 16810aa0dc41SMark McLoughlin { 16820aa0dc41SMark McLoughlin struct root_device *root = to_root_device(dev); 16830aa0dc41SMark McLoughlin 16840aa0dc41SMark McLoughlin if (root->owner) 16850aa0dc41SMark McLoughlin sysfs_remove_link(&root->dev.kobj, "module"); 16860aa0dc41SMark McLoughlin 16870aa0dc41SMark McLoughlin device_unregister(dev); 16880aa0dc41SMark McLoughlin } 16890aa0dc41SMark McLoughlin EXPORT_SYMBOL_GPL(root_device_unregister); 16900aa0dc41SMark McLoughlin 169123681e47SGreg Kroah-Hartman 169223681e47SGreg Kroah-Hartman static void device_create_release(struct device *dev) 169323681e47SGreg Kroah-Hartman { 16941e0b2cf9SKay Sievers pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 169523681e47SGreg Kroah-Hartman kfree(dev); 169623681e47SGreg Kroah-Hartman } 169723681e47SGreg Kroah-Hartman 169839ef3112SGuenter Roeck static struct device * 169939ef3112SGuenter Roeck device_create_groups_vargs(struct class *class, struct device *parent, 170039ef3112SGuenter Roeck dev_t devt, void *drvdata, 170139ef3112SGuenter Roeck const struct attribute_group **groups, 170239ef3112SGuenter Roeck const char *fmt, va_list args) 170339ef3112SGuenter Roeck { 170439ef3112SGuenter Roeck struct device *dev = NULL; 170539ef3112SGuenter Roeck int retval = -ENODEV; 170639ef3112SGuenter Roeck 170739ef3112SGuenter Roeck if (class == NULL || IS_ERR(class)) 170839ef3112SGuenter Roeck goto error; 170939ef3112SGuenter Roeck 171039ef3112SGuenter Roeck dev = kzalloc(sizeof(*dev), GFP_KERNEL); 171139ef3112SGuenter Roeck if (!dev) { 171239ef3112SGuenter Roeck retval = -ENOMEM; 171339ef3112SGuenter Roeck goto error; 171439ef3112SGuenter Roeck } 171539ef3112SGuenter Roeck 1716bbc780f8SDavid Herrmann device_initialize(dev); 171739ef3112SGuenter Roeck dev->devt = devt; 171839ef3112SGuenter Roeck dev->class = class; 171939ef3112SGuenter Roeck dev->parent = parent; 172039ef3112SGuenter Roeck dev->groups = groups; 172139ef3112SGuenter Roeck dev->release = device_create_release; 172239ef3112SGuenter Roeck dev_set_drvdata(dev, drvdata); 172339ef3112SGuenter Roeck 172439ef3112SGuenter Roeck retval = kobject_set_name_vargs(&dev->kobj, fmt, args); 172539ef3112SGuenter Roeck if (retval) 172639ef3112SGuenter Roeck goto error; 172739ef3112SGuenter Roeck 1728bbc780f8SDavid Herrmann retval = device_add(dev); 172939ef3112SGuenter Roeck if (retval) 173039ef3112SGuenter Roeck goto error; 173139ef3112SGuenter Roeck 173239ef3112SGuenter Roeck return dev; 173339ef3112SGuenter Roeck 173439ef3112SGuenter Roeck error: 173539ef3112SGuenter Roeck put_device(dev); 173639ef3112SGuenter Roeck return ERR_PTR(retval); 173739ef3112SGuenter Roeck } 173839ef3112SGuenter Roeck 173923681e47SGreg Kroah-Hartman /** 17408882b394SGreg Kroah-Hartman * device_create_vargs - creates a device and registers it with sysfs 17418882b394SGreg Kroah-Hartman * @class: pointer to the struct class that this device should be registered to 17428882b394SGreg Kroah-Hartman * @parent: pointer to the parent struct device of this new device, if any 17438882b394SGreg Kroah-Hartman * @devt: the dev_t for the char device to be added 17448882b394SGreg Kroah-Hartman * @drvdata: the data to be added to the device for callbacks 17458882b394SGreg Kroah-Hartman * @fmt: string for the device's name 17468882b394SGreg Kroah-Hartman * @args: va_list for the device's name 17478882b394SGreg Kroah-Hartman * 17488882b394SGreg Kroah-Hartman * This function can be used by char device classes. A struct device 17498882b394SGreg Kroah-Hartman * will be created in sysfs, registered to the specified class. 17508882b394SGreg Kroah-Hartman * 17518882b394SGreg Kroah-Hartman * A "dev" file will be created, showing the dev_t for the device, if 17528882b394SGreg Kroah-Hartman * the dev_t is not 0,0. 17538882b394SGreg Kroah-Hartman * If a pointer to a parent struct device is passed in, the newly created 17548882b394SGreg Kroah-Hartman * struct device will be a child of that device in sysfs. 17558882b394SGreg Kroah-Hartman * The pointer to the struct device will be returned from the call. 17568882b394SGreg Kroah-Hartman * Any further sysfs files that might be required can be created using this 17578882b394SGreg Kroah-Hartman * pointer. 17588882b394SGreg Kroah-Hartman * 1759f0eae0edSJani Nikula * Returns &struct device pointer on success, or ERR_PTR() on error. 1760f0eae0edSJani Nikula * 17618882b394SGreg Kroah-Hartman * Note: the struct class passed to this function must have previously 17628882b394SGreg Kroah-Hartman * been created with a call to class_create(). 17638882b394SGreg Kroah-Hartman */ 17648882b394SGreg Kroah-Hartman struct device *device_create_vargs(struct class *class, struct device *parent, 17658882b394SGreg Kroah-Hartman dev_t devt, void *drvdata, const char *fmt, 17668882b394SGreg Kroah-Hartman va_list args) 17678882b394SGreg Kroah-Hartman { 176839ef3112SGuenter Roeck return device_create_groups_vargs(class, parent, devt, drvdata, NULL, 176939ef3112SGuenter Roeck fmt, args); 17708882b394SGreg Kroah-Hartman } 17718882b394SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_create_vargs); 17728882b394SGreg Kroah-Hartman 17738882b394SGreg Kroah-Hartman /** 17744e106739SGreg Kroah-Hartman * device_create - creates a device and registers it with sysfs 17758882b394SGreg Kroah-Hartman * @class: pointer to the struct class that this device should be registered to 17768882b394SGreg Kroah-Hartman * @parent: pointer to the parent struct device of this new device, if any 17778882b394SGreg Kroah-Hartman * @devt: the dev_t for the char device to be added 17788882b394SGreg Kroah-Hartman * @drvdata: the data to be added to the device for callbacks 17798882b394SGreg Kroah-Hartman * @fmt: string for the device's name 17808882b394SGreg Kroah-Hartman * 17818882b394SGreg Kroah-Hartman * This function can be used by char device classes. A struct device 17828882b394SGreg Kroah-Hartman * will be created in sysfs, registered to the specified class. 17838882b394SGreg Kroah-Hartman * 17848882b394SGreg Kroah-Hartman * A "dev" file will be created, showing the dev_t for the device, if 17858882b394SGreg Kroah-Hartman * the dev_t is not 0,0. 17868882b394SGreg Kroah-Hartman * If a pointer to a parent struct device is passed in, the newly created 17878882b394SGreg Kroah-Hartman * struct device will be a child of that device in sysfs. 17888882b394SGreg Kroah-Hartman * The pointer to the struct device will be returned from the call. 17898882b394SGreg Kroah-Hartman * Any further sysfs files that might be required can be created using this 17908882b394SGreg Kroah-Hartman * pointer. 17918882b394SGreg Kroah-Hartman * 1792f0eae0edSJani Nikula * Returns &struct device pointer on success, or ERR_PTR() on error. 1793f0eae0edSJani Nikula * 17948882b394SGreg Kroah-Hartman * Note: the struct class passed to this function must have previously 17958882b394SGreg Kroah-Hartman * been created with a call to class_create(). 17968882b394SGreg Kroah-Hartman */ 17974e106739SGreg Kroah-Hartman struct device *device_create(struct class *class, struct device *parent, 17984e106739SGreg Kroah-Hartman dev_t devt, void *drvdata, const char *fmt, ...) 17998882b394SGreg Kroah-Hartman { 18008882b394SGreg Kroah-Hartman va_list vargs; 18018882b394SGreg Kroah-Hartman struct device *dev; 18028882b394SGreg Kroah-Hartman 18038882b394SGreg Kroah-Hartman va_start(vargs, fmt); 18048882b394SGreg Kroah-Hartman dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs); 18058882b394SGreg Kroah-Hartman va_end(vargs); 18068882b394SGreg Kroah-Hartman return dev; 18078882b394SGreg Kroah-Hartman } 18084e106739SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_create); 18098882b394SGreg Kroah-Hartman 181039ef3112SGuenter Roeck /** 181139ef3112SGuenter Roeck * device_create_with_groups - creates a device and registers it with sysfs 181239ef3112SGuenter Roeck * @class: pointer to the struct class that this device should be registered to 181339ef3112SGuenter Roeck * @parent: pointer to the parent struct device of this new device, if any 181439ef3112SGuenter Roeck * @devt: the dev_t for the char device to be added 181539ef3112SGuenter Roeck * @drvdata: the data to be added to the device for callbacks 181639ef3112SGuenter Roeck * @groups: NULL-terminated list of attribute groups to be created 181739ef3112SGuenter Roeck * @fmt: string for the device's name 181839ef3112SGuenter Roeck * 181939ef3112SGuenter Roeck * This function can be used by char device classes. A struct device 182039ef3112SGuenter Roeck * will be created in sysfs, registered to the specified class. 182139ef3112SGuenter Roeck * Additional attributes specified in the groups parameter will also 182239ef3112SGuenter Roeck * be created automatically. 182339ef3112SGuenter Roeck * 182439ef3112SGuenter Roeck * A "dev" file will be created, showing the dev_t for the device, if 182539ef3112SGuenter Roeck * the dev_t is not 0,0. 182639ef3112SGuenter Roeck * If a pointer to a parent struct device is passed in, the newly created 182739ef3112SGuenter Roeck * struct device will be a child of that device in sysfs. 182839ef3112SGuenter Roeck * The pointer to the struct device will be returned from the call. 182939ef3112SGuenter Roeck * Any further sysfs files that might be required can be created using this 183039ef3112SGuenter Roeck * pointer. 183139ef3112SGuenter Roeck * 183239ef3112SGuenter Roeck * Returns &struct device pointer on success, or ERR_PTR() on error. 183339ef3112SGuenter Roeck * 183439ef3112SGuenter Roeck * Note: the struct class passed to this function must have previously 183539ef3112SGuenter Roeck * been created with a call to class_create(). 183639ef3112SGuenter Roeck */ 183739ef3112SGuenter Roeck struct device *device_create_with_groups(struct class *class, 183839ef3112SGuenter Roeck struct device *parent, dev_t devt, 183939ef3112SGuenter Roeck void *drvdata, 184039ef3112SGuenter Roeck const struct attribute_group **groups, 184139ef3112SGuenter Roeck const char *fmt, ...) 184239ef3112SGuenter Roeck { 184339ef3112SGuenter Roeck va_list vargs; 184439ef3112SGuenter Roeck struct device *dev; 184539ef3112SGuenter Roeck 184639ef3112SGuenter Roeck va_start(vargs, fmt); 184739ef3112SGuenter Roeck dev = device_create_groups_vargs(class, parent, devt, drvdata, groups, 184839ef3112SGuenter Roeck fmt, vargs); 184939ef3112SGuenter Roeck va_end(vargs); 185039ef3112SGuenter Roeck return dev; 185139ef3112SGuenter Roeck } 185239ef3112SGuenter Roeck EXPORT_SYMBOL_GPL(device_create_with_groups); 185339ef3112SGuenter Roeck 18549f3b795aSMichał Mirosław static int __match_devt(struct device *dev, const void *data) 185523681e47SGreg Kroah-Hartman { 18569f3b795aSMichał Mirosław const dev_t *devt = data; 185723681e47SGreg Kroah-Hartman 1858cd35449bSDave Young return dev->devt == *devt; 1859775b64d2SRafael J. Wysocki } 186023681e47SGreg Kroah-Hartman 1861775b64d2SRafael J. Wysocki /** 1862775b64d2SRafael J. Wysocki * device_destroy - removes a device that was created with device_create() 1863775b64d2SRafael J. Wysocki * @class: pointer to the struct class that this device was registered with 1864775b64d2SRafael J. Wysocki * @devt: the dev_t of the device that was previously registered 1865775b64d2SRafael J. Wysocki * 1866775b64d2SRafael J. Wysocki * This call unregisters and cleans up a device that was created with a 1867775b64d2SRafael J. Wysocki * call to device_create(). 1868775b64d2SRafael J. Wysocki */ 1869775b64d2SRafael J. Wysocki void device_destroy(struct class *class, dev_t devt) 1870775b64d2SRafael J. Wysocki { 1871775b64d2SRafael J. Wysocki struct device *dev; 1872775b64d2SRafael J. Wysocki 1873695794aeSGreg Kroah-Hartman dev = class_find_device(class, NULL, &devt, __match_devt); 1874cd35449bSDave Young if (dev) { 1875cd35449bSDave Young put_device(dev); 187623681e47SGreg Kroah-Hartman device_unregister(dev); 187723681e47SGreg Kroah-Hartman } 1878cd35449bSDave Young } 187923681e47SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(device_destroy); 1880a2de48caSGreg Kroah-Hartman 1881a2de48caSGreg Kroah-Hartman /** 1882a2de48caSGreg Kroah-Hartman * device_rename - renames a device 1883a2de48caSGreg Kroah-Hartman * @dev: the pointer to the struct device to be renamed 1884a2de48caSGreg Kroah-Hartman * @new_name: the new name of the device 1885030c1d2bSEric W. Biederman * 1886030c1d2bSEric W. Biederman * It is the responsibility of the caller to provide mutual 1887030c1d2bSEric W. Biederman * exclusion between two different calls of device_rename 1888030c1d2bSEric W. Biederman * on the same device to ensure that new_name is valid and 1889030c1d2bSEric W. Biederman * won't conflict with other devices. 1890c6c0ac66SMichael Ellerman * 1891a5462516STimur Tabi * Note: Don't call this function. Currently, the networking layer calls this 1892a5462516STimur Tabi * function, but that will change. The following text from Kay Sievers offers 1893a5462516STimur Tabi * some insight: 1894a5462516STimur Tabi * 1895a5462516STimur Tabi * Renaming devices is racy at many levels, symlinks and other stuff are not 1896a5462516STimur Tabi * replaced atomically, and you get a "move" uevent, but it's not easy to 1897a5462516STimur Tabi * connect the event to the old and new device. Device nodes are not renamed at 1898a5462516STimur Tabi * all, there isn't even support for that in the kernel now. 1899a5462516STimur Tabi * 1900a5462516STimur Tabi * In the meantime, during renaming, your target name might be taken by another 1901a5462516STimur Tabi * driver, creating conflicts. Or the old name is taken directly after you 1902a5462516STimur Tabi * renamed it -- then you get events for the same DEVPATH, before you even see 1903a5462516STimur Tabi * the "move" event. It's just a mess, and nothing new should ever rely on 1904a5462516STimur Tabi * kernel device renaming. Besides that, it's not even implemented now for 1905a5462516STimur Tabi * other things than (driver-core wise very simple) network devices. 1906a5462516STimur Tabi * 1907a5462516STimur Tabi * We are currently about to change network renaming in udev to completely 1908a5462516STimur Tabi * disallow renaming of devices in the same namespace as the kernel uses, 1909a5462516STimur Tabi * because we can't solve the problems properly, that arise with swapping names 1910a5462516STimur Tabi * of multiple interfaces without races. Means, renaming of eth[0-9]* will only 1911a5462516STimur Tabi * be allowed to some other name than eth[0-9]*, for the aforementioned 1912a5462516STimur Tabi * reasons. 1913a5462516STimur Tabi * 1914a5462516STimur Tabi * Make up a "real" name in the driver before you register anything, or add 1915a5462516STimur Tabi * some other attributes for userspace to find the device, or use udev to add 1916a5462516STimur Tabi * symlinks -- but never rename kernel devices later, it's a complete mess. We 1917a5462516STimur Tabi * don't even want to get into that and try to implement the missing pieces in 1918a5462516STimur Tabi * the core. We really have other pieces to fix in the driver core mess. :) 1919a2de48caSGreg Kroah-Hartman */ 19206937e8f8SJohannes Berg int device_rename(struct device *dev, const char *new_name) 1921a2de48caSGreg Kroah-Hartman { 19224b30ee58STejun Heo struct kobject *kobj = &dev->kobj; 19232ee97cafSCornelia Huck char *old_device_name = NULL; 1924a2de48caSGreg Kroah-Hartman int error; 1925a2de48caSGreg Kroah-Hartman 1926a2de48caSGreg Kroah-Hartman dev = get_device(dev); 1927a2de48caSGreg Kroah-Hartman if (!dev) 1928a2de48caSGreg Kroah-Hartman return -EINVAL; 1929a2de48caSGreg Kroah-Hartman 193069df7533Sethan.zhao dev_dbg(dev, "renaming to %s\n", new_name); 1931a2de48caSGreg Kroah-Hartman 19321fa5ae85SKay Sievers old_device_name = kstrdup(dev_name(dev), GFP_KERNEL); 19332ee97cafSCornelia Huck if (!old_device_name) { 1934952ab431SJesper Juhl error = -ENOMEM; 19352ee97cafSCornelia Huck goto out; 1936952ab431SJesper Juhl } 1937a2de48caSGreg Kroah-Hartman 1938f349cf34SEric W. Biederman if (dev->class) { 19394b30ee58STejun Heo error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj, 19404b30ee58STejun Heo kobj, old_device_name, 19414b30ee58STejun Heo new_name, kobject_namespace(kobj)); 1942f349cf34SEric W. Biederman if (error) 1943f349cf34SEric W. Biederman goto out; 1944f349cf34SEric W. Biederman } 194539aba963SKay Sievers 19464b30ee58STejun Heo error = kobject_rename(kobj, new_name); 19471fa5ae85SKay Sievers if (error) 19482ee97cafSCornelia Huck goto out; 1949a2de48caSGreg Kroah-Hartman 19502ee97cafSCornelia Huck out: 1951a2de48caSGreg Kroah-Hartman put_device(dev); 1952a2de48caSGreg Kroah-Hartman 19532ee97cafSCornelia Huck kfree(old_device_name); 1954a2de48caSGreg Kroah-Hartman 1955a2de48caSGreg Kroah-Hartman return error; 1956a2de48caSGreg Kroah-Hartman } 1957a2807dbcSJohannes Berg EXPORT_SYMBOL_GPL(device_rename); 19588a82472fSCornelia Huck 19598a82472fSCornelia Huck static int device_move_class_links(struct device *dev, 19608a82472fSCornelia Huck struct device *old_parent, 19618a82472fSCornelia Huck struct device *new_parent) 19628a82472fSCornelia Huck { 1963f7f3461dSGreg Kroah-Hartman int error = 0; 19648a82472fSCornelia Huck 1965f7f3461dSGreg Kroah-Hartman if (old_parent) 1966f7f3461dSGreg Kroah-Hartman sysfs_remove_link(&dev->kobj, "device"); 1967f7f3461dSGreg Kroah-Hartman if (new_parent) 1968f7f3461dSGreg Kroah-Hartman error = sysfs_create_link(&dev->kobj, &new_parent->kobj, 1969f7f3461dSGreg Kroah-Hartman "device"); 1970f7f3461dSGreg Kroah-Hartman return error; 19718a82472fSCornelia Huck } 19728a82472fSCornelia Huck 19738a82472fSCornelia Huck /** 19748a82472fSCornelia Huck * device_move - moves a device to a new parent 19758a82472fSCornelia Huck * @dev: the pointer to the struct device to be moved 1976c744aeaeSCornelia Huck * @new_parent: the new parent of the device (can by NULL) 1977ffa6a705SCornelia Huck * @dpm_order: how to reorder the dpm_list 19788a82472fSCornelia Huck */ 1979ffa6a705SCornelia Huck int device_move(struct device *dev, struct device *new_parent, 1980ffa6a705SCornelia Huck enum dpm_order dpm_order) 19818a82472fSCornelia Huck { 19828a82472fSCornelia Huck int error; 19838a82472fSCornelia Huck struct device *old_parent; 1984c744aeaeSCornelia Huck struct kobject *new_parent_kobj; 19858a82472fSCornelia Huck 19868a82472fSCornelia Huck dev = get_device(dev); 19878a82472fSCornelia Huck if (!dev) 19888a82472fSCornelia Huck return -EINVAL; 19898a82472fSCornelia Huck 1990ffa6a705SCornelia Huck device_pm_lock(); 19918a82472fSCornelia Huck new_parent = get_device(new_parent); 1992c744aeaeSCornelia Huck new_parent_kobj = get_device_parent(dev, new_parent); 199363b6971aSCornelia Huck 19941e0b2cf9SKay Sievers pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev), 19951e0b2cf9SKay Sievers __func__, new_parent ? dev_name(new_parent) : "<NULL>"); 1996c744aeaeSCornelia Huck error = kobject_move(&dev->kobj, new_parent_kobj); 19978a82472fSCornelia Huck if (error) { 199863b6971aSCornelia Huck cleanup_glue_dir(dev, new_parent_kobj); 19998a82472fSCornelia Huck put_device(new_parent); 20008a82472fSCornelia Huck goto out; 20018a82472fSCornelia Huck } 20028a82472fSCornelia Huck old_parent = dev->parent; 20038a82472fSCornelia Huck dev->parent = new_parent; 20048a82472fSCornelia Huck if (old_parent) 2005f791b8c8SGreg Kroah-Hartman klist_remove(&dev->p->knode_parent); 20060d358f22SYinghai Lu if (new_parent) { 2007f791b8c8SGreg Kroah-Hartman klist_add_tail(&dev->p->knode_parent, 2008f791b8c8SGreg Kroah-Hartman &new_parent->p->klist_children); 20090d358f22SYinghai Lu set_dev_node(dev, dev_to_node(new_parent)); 20100d358f22SYinghai Lu } 20110d358f22SYinghai Lu 2012bdd4034dSRabin Vincent if (dev->class) { 20138a82472fSCornelia Huck error = device_move_class_links(dev, old_parent, new_parent); 20148a82472fSCornelia Huck if (error) { 20158a82472fSCornelia Huck /* We ignore errors on cleanup since we're hosed anyway... */ 20168a82472fSCornelia Huck device_move_class_links(dev, new_parent, old_parent); 20178a82472fSCornelia Huck if (!kobject_move(&dev->kobj, &old_parent->kobj)) { 2018c744aeaeSCornelia Huck if (new_parent) 2019f791b8c8SGreg Kroah-Hartman klist_remove(&dev->p->knode_parent); 20200d358f22SYinghai Lu dev->parent = old_parent; 20210d358f22SYinghai Lu if (old_parent) { 2022f791b8c8SGreg Kroah-Hartman klist_add_tail(&dev->p->knode_parent, 2023f791b8c8SGreg Kroah-Hartman &old_parent->p->klist_children); 20240d358f22SYinghai Lu set_dev_node(dev, dev_to_node(old_parent)); 20250d358f22SYinghai Lu } 20268a82472fSCornelia Huck } 202763b6971aSCornelia Huck cleanup_glue_dir(dev, new_parent_kobj); 20288a82472fSCornelia Huck put_device(new_parent); 20298a82472fSCornelia Huck goto out; 20308a82472fSCornelia Huck } 2031bdd4034dSRabin Vincent } 2032ffa6a705SCornelia Huck switch (dpm_order) { 2033ffa6a705SCornelia Huck case DPM_ORDER_NONE: 2034ffa6a705SCornelia Huck break; 2035ffa6a705SCornelia Huck case DPM_ORDER_DEV_AFTER_PARENT: 2036ffa6a705SCornelia Huck device_pm_move_after(dev, new_parent); 203752cdbdd4SGrygorii Strashko devices_kset_move_after(dev, new_parent); 2038ffa6a705SCornelia Huck break; 2039ffa6a705SCornelia Huck case DPM_ORDER_PARENT_BEFORE_DEV: 2040ffa6a705SCornelia Huck device_pm_move_before(new_parent, dev); 204152cdbdd4SGrygorii Strashko devices_kset_move_before(new_parent, dev); 2042ffa6a705SCornelia Huck break; 2043ffa6a705SCornelia Huck case DPM_ORDER_DEV_LAST: 2044ffa6a705SCornelia Huck device_pm_move_last(dev); 204552cdbdd4SGrygorii Strashko devices_kset_move_last(dev); 2046ffa6a705SCornelia Huck break; 2047ffa6a705SCornelia Huck } 2048bdd4034dSRabin Vincent 20498a82472fSCornelia Huck put_device(old_parent); 20508a82472fSCornelia Huck out: 2051ffa6a705SCornelia Huck device_pm_unlock(); 20528a82472fSCornelia Huck put_device(dev); 20538a82472fSCornelia Huck return error; 20548a82472fSCornelia Huck } 20558a82472fSCornelia Huck EXPORT_SYMBOL_GPL(device_move); 205637b0c020SGreg Kroah-Hartman 205737b0c020SGreg Kroah-Hartman /** 205837b0c020SGreg Kroah-Hartman * device_shutdown - call ->shutdown() on each device to shutdown. 205937b0c020SGreg Kroah-Hartman */ 206037b0c020SGreg Kroah-Hartman void device_shutdown(void) 206137b0c020SGreg Kroah-Hartman { 2062f123db8eSBenson Leung struct device *dev, *parent; 206337b0c020SGreg Kroah-Hartman 20646245838fSHugh Daschbach spin_lock(&devices_kset->list_lock); 20656245838fSHugh Daschbach /* 20666245838fSHugh Daschbach * Walk the devices list backward, shutting down each in turn. 20676245838fSHugh Daschbach * Beware that device unplug events may also start pulling 20686245838fSHugh Daschbach * devices offline, even as the system is shutting down. 20696245838fSHugh Daschbach */ 20706245838fSHugh Daschbach while (!list_empty(&devices_kset->list)) { 20716245838fSHugh Daschbach dev = list_entry(devices_kset->list.prev, struct device, 20726245838fSHugh Daschbach kobj.entry); 2073d1c6c030SMing Lei 2074d1c6c030SMing Lei /* 2075d1c6c030SMing Lei * hold reference count of device's parent to 2076d1c6c030SMing Lei * prevent it from being freed because parent's 2077d1c6c030SMing Lei * lock is to be held 2078d1c6c030SMing Lei */ 2079f123db8eSBenson Leung parent = get_device(dev->parent); 20806245838fSHugh Daschbach get_device(dev); 20816245838fSHugh Daschbach /* 20826245838fSHugh Daschbach * Make sure the device is off the kset list, in the 20836245838fSHugh Daschbach * event that dev->*->shutdown() doesn't remove it. 20846245838fSHugh Daschbach */ 20856245838fSHugh Daschbach list_del_init(&dev->kobj.entry); 20866245838fSHugh Daschbach spin_unlock(&devices_kset->list_lock); 2087fe6b91f4SAlan Stern 2088d1c6c030SMing Lei /* hold lock to avoid race with probe/release */ 2089f123db8eSBenson Leung if (parent) 2090f123db8eSBenson Leung device_lock(parent); 2091d1c6c030SMing Lei device_lock(dev); 2092d1c6c030SMing Lei 2093fe6b91f4SAlan Stern /* Don't allow any more runtime suspends */ 2094fe6b91f4SAlan Stern pm_runtime_get_noresume(dev); 2095fe6b91f4SAlan Stern pm_runtime_barrier(dev); 20966245838fSHugh Daschbach 209737b0c020SGreg Kroah-Hartman if (dev->bus && dev->bus->shutdown) { 20980246c4faSShuoX Liu if (initcall_debug) 20990246c4faSShuoX Liu dev_info(dev, "shutdown\n"); 210037b0c020SGreg Kroah-Hartman dev->bus->shutdown(dev); 210137b0c020SGreg Kroah-Hartman } else if (dev->driver && dev->driver->shutdown) { 21020246c4faSShuoX Liu if (initcall_debug) 21030246c4faSShuoX Liu dev_info(dev, "shutdown\n"); 210437b0c020SGreg Kroah-Hartman dev->driver->shutdown(dev); 210537b0c020SGreg Kroah-Hartman } 2106d1c6c030SMing Lei 2107d1c6c030SMing Lei device_unlock(dev); 2108f123db8eSBenson Leung if (parent) 2109f123db8eSBenson Leung device_unlock(parent); 2110d1c6c030SMing Lei 21116245838fSHugh Daschbach put_device(dev); 2112f123db8eSBenson Leung put_device(parent); 21136245838fSHugh Daschbach 21146245838fSHugh Daschbach spin_lock(&devices_kset->list_lock); 211537b0c020SGreg Kroah-Hartman } 21166245838fSHugh Daschbach spin_unlock(&devices_kset->list_lock); 211737b0c020SGreg Kroah-Hartman } 211899bcf217SJoe Perches 211999bcf217SJoe Perches /* 212099bcf217SJoe Perches * Device logging functions 212199bcf217SJoe Perches */ 212299bcf217SJoe Perches 212399bcf217SJoe Perches #ifdef CONFIG_PRINTK 2124666f355fSJoe Perches static int 2125666f355fSJoe Perches create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) 212699bcf217SJoe Perches { 2127c4e00daaSKay Sievers const char *subsys; 2128798efc60SJoe Perches size_t pos = 0; 212999bcf217SJoe Perches 2130c4e00daaSKay Sievers if (dev->class) 2131c4e00daaSKay Sievers subsys = dev->class->name; 2132c4e00daaSKay Sievers else if (dev->bus) 2133c4e00daaSKay Sievers subsys = dev->bus->name; 2134c4e00daaSKay Sievers else 2135798efc60SJoe Perches return 0; 2136c4e00daaSKay Sievers 2137798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys); 2138655e5b7cSBen Hutchings if (pos >= hdrlen) 2139655e5b7cSBen Hutchings goto overflow; 2140c4e00daaSKay Sievers 2141c4e00daaSKay Sievers /* 2142c4e00daaSKay Sievers * Add device identifier DEVICE=: 2143c4e00daaSKay Sievers * b12:8 block dev_t 2144c4e00daaSKay Sievers * c127:3 char dev_t 2145c4e00daaSKay Sievers * n8 netdev ifindex 2146c4e00daaSKay Sievers * +sound:card0 subsystem:devname 2147c4e00daaSKay Sievers */ 2148c4e00daaSKay Sievers if (MAJOR(dev->devt)) { 2149c4e00daaSKay Sievers char c; 2150c4e00daaSKay Sievers 2151c4e00daaSKay Sievers if (strcmp(subsys, "block") == 0) 2152c4e00daaSKay Sievers c = 'b'; 2153c4e00daaSKay Sievers else 2154c4e00daaSKay Sievers c = 'c'; 2155798efc60SJoe Perches pos++; 2156798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, 2157c4e00daaSKay Sievers "DEVICE=%c%u:%u", 2158c4e00daaSKay Sievers c, MAJOR(dev->devt), MINOR(dev->devt)); 2159c4e00daaSKay Sievers } else if (strcmp(subsys, "net") == 0) { 2160c4e00daaSKay Sievers struct net_device *net = to_net_dev(dev); 2161c4e00daaSKay Sievers 2162798efc60SJoe Perches pos++; 2163798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, 2164c4e00daaSKay Sievers "DEVICE=n%u", net->ifindex); 2165c4e00daaSKay Sievers } else { 2166798efc60SJoe Perches pos++; 2167798efc60SJoe Perches pos += snprintf(hdr + pos, hdrlen - pos, 2168c4e00daaSKay Sievers "DEVICE=+%s:%s", subsys, dev_name(dev)); 2169c4e00daaSKay Sievers } 2170af7f2158SJim Cromie 2171655e5b7cSBen Hutchings if (pos >= hdrlen) 2172655e5b7cSBen Hutchings goto overflow; 2173655e5b7cSBen Hutchings 2174798efc60SJoe Perches return pos; 2175655e5b7cSBen Hutchings 2176655e5b7cSBen Hutchings overflow: 2177655e5b7cSBen Hutchings dev_WARN(dev, "device/subsystem name too long"); 2178655e5b7cSBen Hutchings return 0; 217999bcf217SJoe Perches } 2180798efc60SJoe Perches 218105e4e5b8SJoe Perches int dev_vprintk_emit(int level, const struct device *dev, 218205e4e5b8SJoe Perches const char *fmt, va_list args) 218305e4e5b8SJoe Perches { 218405e4e5b8SJoe Perches char hdr[128]; 218505e4e5b8SJoe Perches size_t hdrlen; 218605e4e5b8SJoe Perches 218705e4e5b8SJoe Perches hdrlen = create_syslog_header(dev, hdr, sizeof(hdr)); 218805e4e5b8SJoe Perches 218905e4e5b8SJoe Perches return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args); 219005e4e5b8SJoe Perches } 219105e4e5b8SJoe Perches EXPORT_SYMBOL(dev_vprintk_emit); 219205e4e5b8SJoe Perches 219305e4e5b8SJoe Perches int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...) 219405e4e5b8SJoe Perches { 219505e4e5b8SJoe Perches va_list args; 219605e4e5b8SJoe Perches int r; 219705e4e5b8SJoe Perches 219805e4e5b8SJoe Perches va_start(args, fmt); 219905e4e5b8SJoe Perches 220005e4e5b8SJoe Perches r = dev_vprintk_emit(level, dev, fmt, args); 220105e4e5b8SJoe Perches 220205e4e5b8SJoe Perches va_end(args); 220305e4e5b8SJoe Perches 220405e4e5b8SJoe Perches return r; 220505e4e5b8SJoe Perches } 220605e4e5b8SJoe Perches EXPORT_SYMBOL(dev_printk_emit); 220705e4e5b8SJoe Perches 2208d1f1052cSJoe Perches static void __dev_printk(const char *level, const struct device *dev, 2209798efc60SJoe Perches struct va_format *vaf) 2210798efc60SJoe Perches { 2211d1f1052cSJoe Perches if (dev) 2212d1f1052cSJoe Perches dev_printk_emit(level[1] - '0', dev, "%s %s: %pV", 2213798efc60SJoe Perches dev_driver_string(dev), dev_name(dev), vaf); 2214d1f1052cSJoe Perches else 2215d1f1052cSJoe Perches printk("%s(NULL device *): %pV", level, vaf); 2216798efc60SJoe Perches } 221799bcf217SJoe Perches 2218d1f1052cSJoe Perches void dev_printk(const char *level, const struct device *dev, 221999bcf217SJoe Perches const char *fmt, ...) 222099bcf217SJoe Perches { 222199bcf217SJoe Perches struct va_format vaf; 222299bcf217SJoe Perches va_list args; 222399bcf217SJoe Perches 222499bcf217SJoe Perches va_start(args, fmt); 222599bcf217SJoe Perches 222699bcf217SJoe Perches vaf.fmt = fmt; 222799bcf217SJoe Perches vaf.va = &args; 222899bcf217SJoe Perches 2229d1f1052cSJoe Perches __dev_printk(level, dev, &vaf); 2230798efc60SJoe Perches 223199bcf217SJoe Perches va_end(args); 223299bcf217SJoe Perches } 223399bcf217SJoe Perches EXPORT_SYMBOL(dev_printk); 223499bcf217SJoe Perches 223599bcf217SJoe Perches #define define_dev_printk_level(func, kern_level) \ 2236d1f1052cSJoe Perches void func(const struct device *dev, const char *fmt, ...) \ 223799bcf217SJoe Perches { \ 223899bcf217SJoe Perches struct va_format vaf; \ 223999bcf217SJoe Perches va_list args; \ 224099bcf217SJoe Perches \ 224199bcf217SJoe Perches va_start(args, fmt); \ 224299bcf217SJoe Perches \ 224399bcf217SJoe Perches vaf.fmt = fmt; \ 224499bcf217SJoe Perches vaf.va = &args; \ 224599bcf217SJoe Perches \ 2246d1f1052cSJoe Perches __dev_printk(kern_level, dev, &vaf); \ 2247798efc60SJoe Perches \ 224899bcf217SJoe Perches va_end(args); \ 224999bcf217SJoe Perches } \ 225099bcf217SJoe Perches EXPORT_SYMBOL(func); 225199bcf217SJoe Perches 225299bcf217SJoe Perches define_dev_printk_level(dev_emerg, KERN_EMERG); 225399bcf217SJoe Perches define_dev_printk_level(dev_alert, KERN_ALERT); 225499bcf217SJoe Perches define_dev_printk_level(dev_crit, KERN_CRIT); 225599bcf217SJoe Perches define_dev_printk_level(dev_err, KERN_ERR); 225699bcf217SJoe Perches define_dev_printk_level(dev_warn, KERN_WARNING); 225799bcf217SJoe Perches define_dev_printk_level(dev_notice, KERN_NOTICE); 225899bcf217SJoe Perches define_dev_printk_level(_dev_info, KERN_INFO); 225999bcf217SJoe Perches 226099bcf217SJoe Perches #endif 226197badf87SRafael J. Wysocki 226297badf87SRafael J. Wysocki static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) 226397badf87SRafael J. Wysocki { 226497badf87SRafael J. Wysocki return fwnode && !IS_ERR(fwnode->secondary); 226597badf87SRafael J. Wysocki } 226697badf87SRafael J. Wysocki 226797badf87SRafael J. Wysocki /** 226897badf87SRafael J. Wysocki * set_primary_fwnode - Change the primary firmware node of a given device. 226997badf87SRafael J. Wysocki * @dev: Device to handle. 227097badf87SRafael J. Wysocki * @fwnode: New primary firmware node of the device. 227197badf87SRafael J. Wysocki * 227297badf87SRafael J. Wysocki * Set the device's firmware node pointer to @fwnode, but if a secondary 227397badf87SRafael J. Wysocki * firmware node of the device is present, preserve it. 227497badf87SRafael J. Wysocki */ 227597badf87SRafael J. Wysocki void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) 227697badf87SRafael J. Wysocki { 227797badf87SRafael J. Wysocki if (fwnode) { 227897badf87SRafael J. Wysocki struct fwnode_handle *fn = dev->fwnode; 227997badf87SRafael J. Wysocki 228097badf87SRafael J. Wysocki if (fwnode_is_primary(fn)) 228197badf87SRafael J. Wysocki fn = fn->secondary; 228297badf87SRafael J. Wysocki 228355f89a8aSMika Westerberg if (fn) { 228455f89a8aSMika Westerberg WARN_ON(fwnode->secondary); 228597badf87SRafael J. Wysocki fwnode->secondary = fn; 228655f89a8aSMika Westerberg } 228797badf87SRafael J. Wysocki dev->fwnode = fwnode; 228897badf87SRafael J. Wysocki } else { 228997badf87SRafael J. Wysocki dev->fwnode = fwnode_is_primary(dev->fwnode) ? 229097badf87SRafael J. Wysocki dev->fwnode->secondary : NULL; 229197badf87SRafael J. Wysocki } 229297badf87SRafael J. Wysocki } 229397badf87SRafael J. Wysocki EXPORT_SYMBOL_GPL(set_primary_fwnode); 229497badf87SRafael J. Wysocki 229597badf87SRafael J. Wysocki /** 229697badf87SRafael J. Wysocki * set_secondary_fwnode - Change the secondary firmware node of a given device. 229797badf87SRafael J. Wysocki * @dev: Device to handle. 229897badf87SRafael J. Wysocki * @fwnode: New secondary firmware node of the device. 229997badf87SRafael J. Wysocki * 230097badf87SRafael J. Wysocki * If a primary firmware node of the device is present, set its secondary 230197badf87SRafael J. Wysocki * pointer to @fwnode. Otherwise, set the device's firmware node pointer to 230297badf87SRafael J. Wysocki * @fwnode. 230397badf87SRafael J. Wysocki */ 230497badf87SRafael J. Wysocki void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode) 230597badf87SRafael J. Wysocki { 230697badf87SRafael J. Wysocki if (fwnode) 230797badf87SRafael J. Wysocki fwnode->secondary = ERR_PTR(-ENODEV); 230897badf87SRafael J. Wysocki 230997badf87SRafael J. Wysocki if (fwnode_is_primary(dev->fwnode)) 231097badf87SRafael J. Wysocki dev->fwnode->secondary = fwnode; 231197badf87SRafael J. Wysocki else 231297badf87SRafael J. Wysocki dev->fwnode = fwnode; 231397badf87SRafael J. Wysocki } 2314