diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 11:37:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 11:37:15 -0700 |
commit | 542a086ac72fb193cbc1b996963a572269e57743 (patch) | |
tree | b137c08037cca4ffc8a156a891a01113b3b8edce /drivers/base | |
parent | 1d1fdd95df681f0c065d90ffaafa215a0e8825e2 (diff) | |
parent | 1eeeef153c02f5856ec109fa532eb5f31c39f85c (diff) | |
download | linux-542a086ac72fb193cbc1b996963a572269e57743.tar.bz2 |
Merge tag 'driver-core-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core patches from Greg KH:
"Here's the big driver core pull request for 3.12-rc1.
Lots of tiny changes here fixing up the way sysfs attributes are
created, to try to make drivers simpler, and fix a whole class race
conditions with creations of device attributes after the device was
announced to userspace.
All the various pieces are acked by the different subsystem
maintainers"
* tag 'driver-core-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (119 commits)
firmware loader: fix pending_fw_head list corruption
drivers/base/memory.c: introduce help macro to_memory_block
dynamic debug: line queries failing due to uninitialized local variable
sysfs: sysfs_create_groups returns a value.
debugfs: provide debugfs_create_x64() when disabled
rbd: convert bus code to use bus_groups
firmware: dcdbas: use binary attribute groups
sysfs: add sysfs_create/remove_groups for when SYSFS is not enabled
driver core: add #include <linux/sysfs.h> to core files.
HID: convert bus code to use dev_groups
Input: serio: convert bus code to use drv_groups
Input: gameport: convert bus code to use drv_groups
driver core: firmware: use __ATTR_RW()
driver core: core: use DEVICE_ATTR_RO
driver core: bus: use DRIVER_ATTR_WO()
driver core: create write-only attribute macros for devices and drivers
sysfs: create __ATTR_WO()
driver-core: platform: convert bus code to use dev_groups
workqueue: convert bus code to use dev_groups
MEI: convert bus code to use dev_groups
...
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/base.h | 10 | ||||
-rw-r--r-- | drivers/base/bus.c | 60 | ||||
-rw-r--r-- | drivers/base/class.c | 4 | ||||
-rw-r--r-- | drivers/base/core.c | 107 | ||||
-rw-r--r-- | drivers/base/cpu.c | 6 | ||||
-rw-r--r-- | drivers/base/dma-contiguous.c | 4 | ||||
-rw-r--r-- | drivers/base/driver.c | 31 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 24 | ||||
-rw-r--r-- | drivers/base/memory.c | 258 | ||||
-rw-r--r-- | drivers/base/platform.c | 14 | ||||
-rw-r--r-- | drivers/base/power/sysfs.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 2 | ||||
-rw-r--r-- | drivers/base/topology.c | 20 |
13 files changed, 247 insertions, 295 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h index b8bdfe61daa6..2cbc6774f4cd 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -119,6 +119,16 @@ static inline int driver_match_device(struct device_driver *drv, return drv->bus->match ? drv->bus->match(dev, drv) : 1; } +extern int driver_add_groups(struct device_driver *drv, + const struct attribute_group **groups); +extern void driver_remove_groups(struct device_driver *drv, + const struct attribute_group **groups); + +extern int device_add_groups(struct device *dev, + const struct attribute_group **groups); +extern void device_remove_groups(struct device *dev, + const struct attribute_group **groups); + extern char *make_class_name(const char *name, struct kobject *kobj); extern int devres_release_all(struct device *dev); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d414331b480e..4c289ab91357 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/string.h> #include <linux/mutex.h> +#include <linux/sysfs.h> #include "base.h" #include "power/power.h" @@ -165,8 +166,8 @@ static const struct kset_uevent_ops bus_uevent_ops = { static struct kset *bus_kset; /* Manually detach a device from its associated driver. */ -static ssize_t driver_unbind(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t unbind_store(struct device_driver *drv, const char *buf, + size_t count) { struct bus_type *bus = bus_get(drv->bus); struct device *dev; @@ -185,15 +186,15 @@ static ssize_t driver_unbind(struct device_driver *drv, bus_put(bus); return err; } -static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); +static DRIVER_ATTR_WO(unbind); /* * Manually attach a device to a driver. * Note: the driver must want to bind to the device, * it is not possible to override the driver's id table. */ -static ssize_t driver_bind(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t bind_store(struct device_driver *drv, const char *buf, + size_t count) { struct bus_type *bus = bus_get(drv->bus); struct device *dev; @@ -221,7 +222,7 @@ static ssize_t driver_bind(struct device_driver *drv, bus_put(bus); return err; } -static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); +static DRIVER_ATTR_WO(bind); static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf) { @@ -460,7 +461,7 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev) if (!bus->dev_attrs) return 0; - for (i = 0; attr_name(bus->dev_attrs[i]); i++) { + for (i = 0; bus->dev_attrs[i].attr.name; i++) { error = device_create_file(dev, &bus->dev_attrs[i]); if (error) { while (--i >= 0) @@ -476,7 +477,7 @@ static void device_remove_attrs(struct bus_type *bus, struct device *dev) int i; if (bus->dev_attrs) { - for (i = 0; attr_name(bus->dev_attrs[i]); i++) + for (i = 0; bus->dev_attrs[i].attr.name; i++) device_remove_file(dev, &bus->dev_attrs[i]); } } @@ -499,6 +500,9 @@ int bus_add_device(struct device *dev) error = device_add_attrs(bus, dev); if (error) goto out_put; + error = device_add_groups(dev, bus->dev_groups); + if (error) + goto out_groups; error = sysfs_create_link(&bus->p->devices_kset->kobj, &dev->kobj, dev_name(dev)); if (error) @@ -513,6 +517,8 @@ int bus_add_device(struct device *dev) out_subsys: sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev)); +out_groups: + device_remove_groups(dev, bus->dev_groups); out_id: device_remove_attrs(bus, dev); out_put: @@ -575,6 +581,7 @@ void bus_remove_device(struct device *dev) sysfs_remove_link(&dev->bus->p->devices_kset->kobj, dev_name(dev)); device_remove_attrs(dev->bus, dev); + device_remove_groups(dev, dev->bus->dev_groups); if (klist_node_attached(&dev->p->knode_bus)) klist_del(&dev->p->knode_bus); @@ -590,7 +597,7 @@ static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) int i; if (bus->drv_attrs) { - for (i = 0; attr_name(bus->drv_attrs[i]); i++) { + for (i = 0; bus->drv_attrs[i].attr.name; i++) { error = driver_create_file(drv, &bus->drv_attrs[i]); if (error) goto err; @@ -610,7 +617,7 @@ static void driver_remove_attrs(struct bus_type *bus, int i; if (bus->drv_attrs) { - for (i = 0; attr_name(bus->drv_attrs[i]); i++) + for (i = 0; bus->drv_attrs[i].attr.name; i++) driver_remove_file(drv, &bus->drv_attrs[i]); } } @@ -659,8 +666,8 @@ static void remove_probe_files(struct bus_type *bus) bus_remove_file(bus, &bus_attr_drivers_probe); } -static ssize_t driver_uevent_store(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t uevent_store(struct device_driver *drv, const char *buf, + size_t count) { enum kobject_action action; @@ -668,7 +675,7 @@ static ssize_t driver_uevent_store(struct device_driver *drv, kobject_uevent(&drv->p->kobj, action); return count; } -static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store); +static DRIVER_ATTR_WO(uevent); /** * bus_add_driver - Add a driver to the bus. @@ -719,6 +726,10 @@ int bus_add_driver(struct device_driver *drv) printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", __func__, drv->name); } + error = driver_add_groups(drv, bus->drv_groups); + if (error) + printk(KERN_ERR "%s: driver_create_groups(%s) failed\n", + __func__, drv->name); if (!drv->suppress_bind_attrs) { error = add_bind_files(drv); @@ -756,6 +767,7 @@ void bus_remove_driver(struct device_driver *drv) if (!drv->suppress_bind_attrs) remove_bind_files(drv); driver_remove_attrs(drv->bus, drv); + driver_remove_groups(drv, drv->bus->drv_groups); driver_remove_file(drv, &driver_attr_uevent); klist_remove(&drv->p->knode_bus); pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name); @@ -846,7 +858,7 @@ static int bus_add_attrs(struct bus_type *bus) int i; if (bus->bus_attrs) { - for (i = 0; attr_name(bus->bus_attrs[i]); i++) { + for (i = 0; bus->bus_attrs[i].attr.name; i++) { error = bus_create_file(bus, &bus->bus_attrs[i]); if (error) goto err; @@ -865,11 +877,23 @@ static void bus_remove_attrs(struct bus_type *bus) int i; if (bus->bus_attrs) { - for (i = 0; attr_name(bus->bus_attrs[i]); i++) + for (i = 0; bus->bus_attrs[i].attr.name; i++) bus_remove_file(bus, &bus->bus_attrs[i]); } } +static int bus_add_groups(struct bus_type *bus, + const struct attribute_group **groups) +{ + return sysfs_create_groups(&bus->p->subsys.kobj, groups); +} + +static void bus_remove_groups(struct bus_type *bus, + const struct attribute_group **groups) +{ + sysfs_remove_groups(&bus->p->subsys.kobj, groups); +} + static void klist_devices_get(struct klist_node *n) { struct device_private *dev_prv = to_device_private_bus(n); @@ -962,10 +986,15 @@ int bus_register(struct bus_type *bus) retval = bus_add_attrs(bus); if (retval) goto bus_attrs_fail; + retval = bus_add_groups(bus, bus->bus_groups); + if (retval) + goto bus_groups_fail; pr_debug("bus: '%s': registered\n", bus->name); return 0; +bus_groups_fail: + bus_remove_attrs(bus); bus_attrs_fail: remove_probe_files(bus); bus_probe_files_fail: @@ -996,6 +1025,7 @@ void bus_unregister(struct bus_type *bus) if (bus->dev_root) device_unregister(bus->dev_root); bus_remove_attrs(bus); + bus_remove_groups(bus, bus->bus_groups); remove_probe_files(bus); kset_unregister(bus->p->drivers_kset); kset_unregister(bus->p->devices_kset); diff --git a/drivers/base/class.c b/drivers/base/class.c index 3ce845471327..8b7818b80056 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -135,7 +135,7 @@ static int add_class_attrs(struct class *cls) int error = 0; if (cls->class_attrs) { - for (i = 0; attr_name(cls->class_attrs[i]); i++) { + for (i = 0; cls->class_attrs[i].attr.name; i++) { error = class_create_file(cls, &cls->class_attrs[i]); if (error) goto error; @@ -154,7 +154,7 @@ static void remove_class_attrs(struct class *cls) int i; if (cls->class_attrs) { - for (i = 0; attr_name(cls->class_attrs[i]); i++) + for (i = 0; cls->class_attrs[i].attr.name; i++) class_remove_file(cls, &cls->class_attrs[i]); } } diff --git a/drivers/base/core.c b/drivers/base/core.c index 8856d74545d9..c7b0925f627a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -26,6 +26,7 @@ #include <linux/async.h> #include <linux/pm_runtime.h> #include <linux/netdevice.h> +#include <linux/sysfs.h> #include "base.h" #include "power/power.h" @@ -36,9 +37,9 @@ long sysfs_deprecated = 1; #else long sysfs_deprecated = 0; #endif -static __init int sysfs_deprecated_setup(char *arg) +static int __init sysfs_deprecated_setup(char *arg) { - return strict_strtol(arg, 10, &sysfs_deprecated); + return kstrtol(arg, 10, &sysfs_deprecated); } early_param("sysfs.deprecated", sysfs_deprecated_setup); #endif @@ -345,7 +346,7 @@ static const struct kset_uevent_ops device_uevent_ops = { .uevent = dev_uevent, }; -static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, +static ssize_t uevent_show(struct device *dev, struct device_attribute *attr, char *buf) { struct kobject *top_kobj; @@ -388,7 +389,7 @@ out: return count; } -static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, +static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { enum kobject_action action; @@ -399,11 +400,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, dev_err(dev, "uevent: unknown action-string\n"); return count; } +static DEVICE_ATTR_RW(uevent); -static struct device_attribute uevent_attr = - __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent); - -static ssize_t show_online(struct device *dev, struct device_attribute *attr, +static ssize_t online_show(struct device *dev, struct device_attribute *attr, char *buf) { bool val; @@ -414,7 +413,7 @@ static ssize_t show_online(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", val); } -static ssize_t store_online(struct device *dev, struct device_attribute *attr, +static ssize_t online_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { bool val; @@ -429,9 +428,7 @@ static ssize_t store_online(struct device *dev, struct device_attribute *attr, unlock_device_hotplug(); return ret < 0 ? ret : count; } - -static struct device_attribute online_attr = - __ATTR(online, S_IRUGO | S_IWUSR, show_online, store_online); +static DEVICE_ATTR_RW(online); static int device_add_attributes(struct device *dev, struct device_attribute *attrs) @@ -440,7 +437,7 @@ static int device_add_attributes(struct device *dev, int i; if (attrs) { - for (i = 0; attr_name(attrs[i]); i++) { + for (i = 0; attrs[i].attr.name; i++) { error = device_create_file(dev, &attrs[i]); if (error) break; @@ -458,7 +455,7 @@ static void device_remove_attributes(struct device *dev, int i; if (attrs) - for (i = 0; attr_name(attrs[i]); i++) + for (i = 0; attrs[i].attr.name; i++) device_remove_file(dev, &attrs[i]); } @@ -469,7 +466,7 @@ static int device_add_bin_attributes(struct device *dev, int i; if (attrs) { - for (i = 0; attr_name(attrs[i]); i++) { + for (i = 0; attrs[i].attr.name; i++) { error = device_create_bin_file(dev, &attrs[i]); if (error) break; @@ -487,38 +484,19 @@ static void device_remove_bin_attributes(struct device *dev, int i; if (attrs) - for (i = 0; attr_name(attrs[i]); i++) + for (i = 0; attrs[i].attr.name; i++) device_remove_bin_file(dev, &attrs[i]); } -static int device_add_groups(struct device *dev, - const struct attribute_group **groups) +int device_add_groups(struct device *dev, const struct attribute_group **groups) { - int error = 0; - int i; - - if (groups) { - for (i = 0; groups[i]; i++) { - error = sysfs_create_group(&dev->kobj, groups[i]); - if (error) { - while (--i >= 0) - sysfs_remove_group(&dev->kobj, - groups[i]); - break; - } - } - } - return error; + return sysfs_create_groups(&dev->kobj, groups); } -static void device_remove_groups(struct device *dev, - const struct attribute_group **groups) +void device_remove_groups(struct device *dev, + const struct attribute_group **groups) { - int i; - - if (groups) - for (i = 0; groups[i]; i++) - sysfs_remove_group(&dev->kobj, groups[i]); + sysfs_remove_groups(&dev->kobj, groups); } static int device_add_attrs(struct device *dev) @@ -550,7 +528,7 @@ static int device_add_attrs(struct device *dev) goto err_remove_type_groups; if (device_supports_offline(dev) && !dev->offline_disabled) { - error = device_create_file(dev, &online_attr); + error = device_create_file(dev, &dev_attr_online); if (error) goto err_remove_type_groups; } @@ -578,7 +556,7 @@ static void device_remove_attrs(struct device *dev) struct class *class = dev->class; const struct device_type *type = dev->type; - device_remove_file(dev, &online_attr); + device_remove_file(dev, &dev_attr_online); device_remove_groups(dev, dev->groups); if (type) @@ -591,15 +569,12 @@ static void device_remove_attrs(struct device *dev) } } - -static ssize_t show_dev(struct device *dev, struct device_attribute *attr, +static ssize_t dev_show(struct device *dev, struct device_attribute *attr, char *buf) { return print_dev_t(buf, dev->devt); } - -static struct device_attribute devt_attr = - __ATTR(dev, S_IRUGO, show_dev, NULL); +static DEVICE_ATTR_RO(dev); /* /sys/devices/ */ struct kset *devices_kset; @@ -626,6 +601,7 @@ int device_create_file(struct device *dev, return error; } +EXPORT_SYMBOL_GPL(device_create_file); /** * device_remove_file - remove sysfs attribute file. @@ -638,6 +614,7 @@ void device_remove_file(struct device *dev, if (dev) sysfs_remove_file(&dev->kobj, &attr->attr); } +EXPORT_SYMBOL_GPL(device_remove_file); /** * device_create_bin_file - create sysfs binary attribute file for device. @@ -748,6 +725,7 @@ void device_initialize(struct device *dev) device_pm_init(dev); set_dev_node(dev, -1); } +EXPORT_SYMBOL_GPL(device_initialize); struct kobject *virtual_device_parent(struct device *dev) { @@ -1100,12 +1078,12 @@ int device_add(struct device *dev) if (platform_notify) platform_notify(dev); - error = device_create_file(dev, &uevent_attr); + error = device_create_file(dev, &dev_attr_uevent); if (error) goto attrError; if (MAJOR(dev->devt)) { - error = device_create_file(dev, &devt_attr); + error = device_create_file(dev, &dev_attr_dev); if (error) goto ueventattrError; @@ -1172,9 +1150,9 @@ done: device_remove_sys_dev_entry(dev); devtattrError: if (MAJOR(dev->devt)) - device_remove_file(dev, &devt_attr); + device_remove_file(dev, &dev_attr_dev); ueventattrError: - device_remove_file(dev, &uevent_attr); + device_remove_file(dev, &dev_attr_uevent); attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); @@ -1187,6 +1165,7 @@ name_error: dev->p = NULL; goto done; } +EXPORT_SYMBOL_GPL(device_add); /** * device_register - register a device with the system. @@ -1211,6 +1190,7 @@ int device_register(struct device *dev) device_initialize(dev); return device_add(dev); } +EXPORT_SYMBOL_GPL(device_register); /** * get_device - increment reference count for device. @@ -1224,6 +1204,7 @@ struct device *get_device(struct device *dev) { return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL; } +EXPORT_SYMBOL_GPL(get_device); /** * put_device - decrement reference count. @@ -1235,6 +1216,7 @@ void put_device(struct device *dev) if (dev) kobject_put(&dev->kobj); } +EXPORT_SYMBOL_GPL(put_device); /** * device_del - delete device from system. @@ -1266,7 +1248,7 @@ void device_del(struct device *dev) if (MAJOR(dev->devt)) { devtmpfs_delete_node(dev); device_remove_sys_dev_entry(dev); - device_remove_file(dev, &devt_attr); + device_remove_file(dev, &dev_attr_dev); } if (dev->class) { device_remove_class_symlinks(dev); @@ -1281,7 +1263,7 @@ void device_del(struct device *dev) klist_del(&dev->knode_class); mutex_unlock(&dev->class->p->mutex); } - device_remove_file(dev, &uevent_attr); + device_remove_file(dev, &dev_attr_uevent); device_remove_attrs(dev); bus_remove_device(dev); device_pm_remove(dev); @@ -1297,6 +1279,7 @@ void device_del(struct device *dev) kobject_del(&dev->kobj); put_device(parent); } +EXPORT_SYMBOL_GPL(device_del); /** * device_unregister - unregister device from system. @@ -1315,6 +1298,7 @@ void device_unregister(struct device *dev) device_del(dev); put_device(dev); } +EXPORT_SYMBOL_GPL(device_unregister); static struct device *next_device(struct klist_iter *i) { @@ -1403,6 +1387,7 @@ int device_for_each_child(struct device *parent, void *data, klist_iter_exit(&i); return error; } +EXPORT_SYMBOL_GPL(device_for_each_child); /** * device_find_child - device iterator for locating a particular device. @@ -1437,6 +1422,7 @@ struct device *device_find_child(struct device *parent, void *data, klist_iter_exit(&i); return child; } +EXPORT_SYMBOL_GPL(device_find_child); int __init devices_init(void) { @@ -1464,21 +1450,6 @@ int __init devices_init(void) return -ENOMEM; } -EXPORT_SYMBOL_GPL(device_for_each_child); -EXPORT_SYMBOL_GPL(device_find_child); - -EXPORT_SYMBOL_GPL(device_initialize); -EXPORT_SYMBOL_GPL(device_add); -EXPORT_SYMBOL_GPL(device_register); - -EXPORT_SYMBOL_GPL(device_del); -EXPORT_SYMBOL_GPL(device_unregister); -EXPORT_SYMBOL_GPL(get_device); -EXPORT_SYMBOL_GPL(put_device); - -EXPORT_SYMBOL_GPL(device_create_file); -EXPORT_SYMBOL_GPL(device_remove_file); - static DEFINE_MUTEX(device_hotplug_lock); void lock_device_hotplug(void) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 4c358bc44c72..6bfaaca6955e 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -43,11 +43,14 @@ static int __ref cpu_subsys_online(struct device *dev) struct cpu *cpu = container_of(dev, struct cpu, dev); int cpuid = dev->id; int from_nid, to_nid; - int ret; + int ret = -ENODEV; cpu_hotplug_driver_lock(); from_nid = cpu_to_node(cpuid); + if (from_nid == NUMA_NO_NODE) + goto out; + ret = cpu_up(cpuid); /* * When hot adding memory to memoryless node and enabling a cpu @@ -57,6 +60,7 @@ static int __ref cpu_subsys_online(struct device *dev) if (from_nid != to_nid) change_cpu_under_node(cpu, from_nid, to_nid); + out: cpu_hotplug_driver_unlock(); return ret; } diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 0ca54421ce97..6c9cdaa9200d 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -134,7 +134,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit) static DEFINE_MUTEX(cma_mutex); -static __init int cma_activate_area(unsigned long base_pfn, unsigned long count) +static int __init cma_activate_area(unsigned long base_pfn, unsigned long count) { unsigned long pfn = base_pfn; unsigned i = count >> pageblock_order; @@ -156,7 +156,7 @@ static __init int cma_activate_area(unsigned long base_pfn, unsigned long count) return 0; } -static __init struct cma *cma_create_area(unsigned long base_pfn, +static struct cma * __init cma_create_area(unsigned long base_pfn, unsigned long count) { int bitmap_size = BITS_TO_LONGS(count) * sizeof(long); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 974e301a1ef0..9e29943e56ca 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -15,6 +15,7 @@ #include <linux/errno.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/sysfs.h> #include "base.h" static struct device *next_device(struct klist_iter *i) @@ -123,34 +124,16 @@ void driver_remove_file(struct device_driver *drv, } EXPORT_SYMBOL_GPL(driver_remove_file); -static int driver_add_groups(struct device_driver *drv, - const struct attribute_group **groups) +int driver_add_groups(struct device_driver *drv, + const struct attribute_group **groups) { - int error = 0; - int i; - - if (groups) { - for (i = 0; groups[i]; i++) { - error = sysfs_create_group(&drv->p->kobj, groups[i]); - if (error) { - while (--i >= 0) - sysfs_remove_group(&drv->p->kobj, - groups[i]); - break; - } - } - } - return error; + return sysfs_create_groups(&drv->p->kobj, groups); } -static void driver_remove_groups(struct device_driver *drv, - const struct attribute_group **groups) +void driver_remove_groups(struct device_driver *drv, + const struct attribute_group **groups) { - int i; - - if (groups) - for (i = 0; groups[i]; i++) - sysfs_remove_group(&drv->p->kobj, groups[i]); + sysfs_remove_groups(&drv->p->kobj, groups); } /** diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index a439602ea919..10a4467c63f1 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -486,9 +486,8 @@ static struct notifier_block fw_shutdown_nb = { .notifier_call = fw_shutdown_notify, }; -static ssize_t firmware_timeout_show(struct class *class, - struct class_attribute *attr, - char *buf) +static ssize_t timeout_show(struct class *class, struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", loading_timeout); } @@ -506,9 +505,8 @@ static ssize_t firmware_timeout_show(struct class *class, * * Note: zero means 'wait forever'. **/ -static ssize_t firmware_timeout_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t count) +static ssize_t timeout_store(struct class *class, struct class_attribute *attr, + const char *buf, size_t count) { loading_timeout = simple_strtol(buf, NULL, 10); if (loading_timeout < 0) @@ -518,8 +516,7 @@ static ssize_t firmware_timeout_store(struct class *class, } static struct class_attribute firmware_class_attrs[] = { - __ATTR(timeout, S_IWUSR | S_IRUGO, - firmware_timeout_show, firmware_timeout_store), + __ATTR_RW(timeout), __ATTR_NULL }; @@ -868,8 +865,15 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, goto err_del_dev; } + mutex_lock(&fw_lock); + list_add(&buf->pending_list, &pending_fw_head); + mutex_unlock(&fw_lock); + retval = device_create_file(f_dev, &dev_attr_loading); if (retval) { + mutex_lock(&fw_lock); + list_del_init(&buf->pending_list); + mutex_unlock(&fw_lock); dev_err(f_dev, "%s: device_create_file failed\n", __func__); goto err_del_bin_attr; } @@ -884,10 +888,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); } - mutex_lock(&fw_lock); - list_add(&buf->pending_list, &pending_fw_head); - mutex_unlock(&fw_lock); - wait_for_completion(&buf->completion); cancel_delayed_work_sync(&fw_priv->timeout_work); diff --git a/drivers/base/memory.c b/drivers/base/memory.c index ec386ee9cb22..1c617623c8ae 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -16,7 +16,6 @@ #include <linux/capability.h> #include <linux/device.h> #include <linux/memory.h> -#include <linux/kobject.h> #include <linux/memory_hotplug.h> #include <linux/mm.h> #include <linux/mutex.h> @@ -30,6 +29,8 @@ static DEFINE_MUTEX(mem_sysfs_mutex); #define MEMORY_CLASS_NAME "memory" +#define to_memory_block(dev) container_of(dev, struct memory_block, dev) + static int sections_per_block; static inline int base_memory_block_id(int section_nr) @@ -77,7 +78,7 @@ EXPORT_SYMBOL(unregister_memory_isolate_notifier); static void memory_block_release(struct device *dev) { - struct memory_block *mem = container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); kfree(mem); } @@ -110,8 +111,7 @@ static unsigned long get_memory_block_size(void) static ssize_t show_mem_start_phys_index(struct device *dev, struct device_attribute *attr, char *buf) { - struct memory_block *mem = - container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); unsigned long phys_index; phys_index = mem->start_section_nr / sections_per_block; @@ -121,8 +121,7 @@ static ssize_t show_mem_start_phys_index(struct device *dev, static ssize_t show_mem_end_phys_index(struct device *dev, struct device_attribute *attr, char *buf) { - struct memory_block *mem = - container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); unsigned long phys_index; phys_index = mem->end_section_nr / sections_per_block; @@ -137,8 +136,7 @@ static ssize_t show_mem_removable(struct device *dev, { unsigned long i, pfn; int ret = 1; - struct memory_block *mem = - container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); for (i = 0; i < sections_per_block; i++) { if (!present_section_nr(mem->start_section_nr + i)) @@ -156,8 +154,7 @@ static ssize_t show_mem_removable(struct device *dev, static ssize_t show_mem_state(struct device *dev, struct device_attribute *attr, char *buf) { - struct memory_block *mem = - container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); ssize_t len = 0; /* @@ -263,9 +260,8 @@ memory_block_action(unsigned long phys_index, unsigned long action, int online_t return ret; } -static int __memory_block_change_state(struct memory_block *mem, - unsigned long to_state, unsigned long from_state_req, - int online_type) +static int memory_block_change_state(struct memory_block *mem, + unsigned long to_state, unsigned long from_state_req) { int ret = 0; @@ -275,105 +271,89 @@ static int __memory_block_change_state(struct memory_block *mem, if (to_state == MEM_OFFLINE) mem->state = MEM_GOING_OFFLINE; - ret = memory_block_action(mem->start_section_nr, to_state, online_type); + ret = memory_block_action(mem->start_section_nr, to_state, + mem->online_type); + mem->state = ret ? from_state_req : to_state; + return ret; } +/* The device lock serializes operations on memory_subsys_[online|offline] */ static int memory_subsys_online(struct device *dev) { - struct memory_block *mem = container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); int ret; - mutex_lock(&mem->state_mutex); - - ret = mem->state == MEM_ONLINE ? 0 : - __memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE, - ONLINE_KEEP); + if (mem->state == MEM_ONLINE) + return 0; - mutex_unlock(&mem->state_mutex); - return ret; -} - -static int memory_subsys_offline(struct device *dev) -{ - struct memory_block *mem = container_of(dev, struct memory_block, dev); - int ret; + /* + * If we are called from store_mem_state(), online_type will be + * set >= 0 Otherwise we were called from the device online + * attribute and need to set the online_type. + */ + if (mem->online_type < 0) + mem->online_type = ONLINE_KEEP; - mutex_lock(&mem->state_mutex); + ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); - ret = mem->state == MEM_OFFLINE ? 0 : - __memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1); + /* clear online_type */ + mem->online_type = -1; - mutex_unlock(&mem->state_mutex); return ret; } -static int __memory_block_change_state_uevent(struct memory_block *mem, - unsigned long to_state, unsigned long from_state_req, - int online_type) -{ - int ret = __memory_block_change_state(mem, to_state, from_state_req, - online_type); - if (!ret) { - switch (mem->state) { - case MEM_OFFLINE: - kobject_uevent(&mem->dev.kobj, KOBJ_OFFLINE); - break; - case MEM_ONLINE: - kobject_uevent(&mem->dev.kobj, KOBJ_ONLINE); - break; - default: - break; - } - } - return ret; -} - -static int memory_block_change_state(struct memory_block *mem, - unsigned long to_state, unsigned long from_state_req, - int online_type) +static int memory_subsys_offline(struct device *dev) { - int ret; + struct memory_block *mem = to_memory_block(dev); - mutex_lock(&mem->state_mutex); - ret = __memory_block_change_state_uevent(mem, to_state, from_state_req, - online_type); - mutex_unlock(&mem->state_mutex); + if (mem->state == MEM_OFFLINE) + return 0; - return ret; + return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); } + static ssize_t store_mem_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct memory_block *mem; - bool offline; - int ret = -EINVAL; - - mem = container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); + int ret, online_type; lock_device_hotplug(); - if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) { - offline = false; - ret = memory_block_change_state(mem, MEM_ONLINE, - MEM_OFFLINE, ONLINE_KERNEL); - } else if (!strncmp(buf, "online_movable", min_t(int, count, 14))) { - offline = false; - ret = memory_block_change_state(mem, MEM_ONLINE, - MEM_OFFLINE, ONLINE_MOVABLE); - } else if (!strncmp(buf, "online", min_t(int, count, 6))) { - offline = false; - ret = memory_block_change_state(mem, MEM_ONLINE, - MEM_OFFLINE, ONLINE_KEEP); - } else if(!strncmp(buf, "offline", min_t(int, count, 7))) { - offline = true; - ret = memory_block_change_state(mem, MEM_OFFLINE, - MEM_ONLINE, -1); + if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) + online_type = ONLINE_KERNEL; + else if (!strncmp(buf, "online_movable", min_t(int, count, 14))) + online_type = ONLINE_MOVABLE; + else if (!strncmp(buf, "online", min_t(int, count, 6))) + online_type = ONLINE_KEEP; + else if (!strncmp(buf, "offline", min_t(int, count, 7))) + online_type = -1; + else + return -EINVAL; + + switch (online_type) { + case ONLINE_KERNEL: + case ONLINE_MOVABLE: + case ONLINE_KEEP: + /* + * mem->online_type is not protected so there can be a + * race here. However, when racing online, the first + * will succeed and the second will just return as the + * block will already be online. The online type + * could be either one, but that is expected. + */ + mem->online_type = online_type; + ret = device_online(&mem->dev); + break; + case -1: + ret = device_offline(&mem->dev); + break; + default: + ret = -EINVAL; /* should never happen */ } - if (!ret) - dev->offline = offline; unlock_device_hotplug(); @@ -394,8 +374,7 @@ store_mem_state(struct device *dev, static ssize_t show_phys_device(struct device *dev, struct device_attribute *attr, char *buf) { - struct memory_block *mem = - container_of(dev, struct memory_block, dev); + struct memory_block *mem = to_memory_block(dev); return sprintf(buf, "%d\n", mem->phys_device); } @@ -471,7 +450,7 @@ store_soft_offline_page(struct device *dev, u64 pfn; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (strict_strtoull(buf, 0, &pfn) < 0) + if (kstrtoull(buf, 0, &pfn) < 0) return -EINVAL; pfn >>= PAGE_SHIFT; if (!pfn_valid(pfn)) @@ -490,7 +469,7 @@ store_hard_offline_page(struct device *dev, u64 pfn; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (strict_strtoull(buf, 0, &pfn) < 0) + if (kstrtoull(buf, 0, &pfn) < 0) return -EINVAL; pfn >>= PAGE_SHIFT; ret = memory_failure(pfn, 0, 0); @@ -527,7 +506,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section, put_device(&hint->dev); if (!dev) return NULL; - return container_of(dev, struct memory_block, dev); + return to_memory_block(dev); } /* @@ -567,16 +546,13 @@ static const struct attribute_group *memory_memblk_attr_groups[] = { static int register_memory(struct memory_block *memory) { - int error; - memory->dev.bus = &memory_subsys; memory->dev.id = memory->start_section_nr / sections_per_block; memory->dev.release = memory_block_release; memory->dev.groups = memory_memblk_attr_groups; memory->dev.offline = memory->state == MEM_OFFLINE; - error = device_register(&memory->dev); - return error; + return device_register(&memory->dev); } static int init_memory_block(struct memory_block **memory, @@ -597,7 +573,6 @@ static int init_memory_block(struct memory_block **memory, mem->end_section_nr = mem->start_section_nr + sections_per_block - 1; mem->state = state; mem->section_count++; - mutex_init(&mem->state_mutex); start_pfn = section_nr_to_pfn(mem->start_section_nr); mem->phys_device = arch_get_memory_phys_device(start_pfn); @@ -607,55 +582,57 @@ static int init_memory_block(struct memory_block **memory, return ret; } -static int add_memory_section(int nid, struct mem_section *section, - struct memory_block **mem_p, - unsigned long state, enum mem_add_context context) +static int add_memory_block(int base_section_nr) { - struct memory_block *mem = NULL; - int scn_nr = __section_nr(section); - int ret = 0; - - mutex_lock(&mem_sysfs_mutex); - - if (context == BOOT) { - /* same memory block ? */ - if (mem_p && *mem_p) - if (scn_nr >= (*mem_p)->start_section_nr && - scn_nr <= (*mem_p)->end_section_nr) { - mem = *mem_p; - kobject_get(&mem->dev.kobj); - } - } else - mem = find_memory_block(section); - - if (mem) { - mem->section_count++; - kobject_put(&mem->dev.kobj); - } else { - ret = init_memory_block(&mem, section, state); - /* store memory_block pointer for next loop */ - if (!ret && context == BOOT) - if (mem_p) - *mem_p = mem; - } + struct memory_block *mem; + int i, ret, section_count = 0, section_nr; - if (!ret) { - if (context == HOTPLUG && - mem->section_count == sections_per_block) - ret = register_mem_sect_under_node(mem, nid); + for (i = base_section_nr; + (i < base_section_nr + sections_per_block) && i < NR_MEM_SECTIONS; + i++) { + if (!present_section_nr(i)) + continue; + if (section_count == 0) + section_nr = i; + section_count++; } - mutex_unlock(&mem_sysfs_mutex); - return ret; + if (section_count == 0) + return 0; + ret = init_memory_block(&mem, __nr_to_section(section_nr), MEM_ONLINE); + if (ret) + return ret; + mem->section_count = section_count; + return 0; } + /* * need an interface for the VM to add new memory regions, * but without onlining it. */ int register_new_memory(int nid, struct mem_section *section) { - return add_memory_section(nid, section, NULL, MEM_OFFLINE, HOTPLUG); + int ret = 0; + struct memory_block *mem; + + mutex_lock(&mem_sysfs_mutex); + + mem = find_memory_block(section); + if (mem) { + mem->section_count++; + put_device(&mem->dev); + } else { + ret = init_memory_block(&mem, section, MEM_OFFLINE); + if (ret) + goto out; + } + + if (mem->section_count == sections_per_block) + ret = register_mem_sect_under_node(mem, nid); +out: + mutex_unlock(&mem_sysfs_mutex); + return ret; } #ifdef CONFIG_MEMORY_HOTREMOVE @@ -665,7 +642,7 @@ unregister_memory(struct memory_block *memory) BUG_ON(memory->dev.bus != &memory_subsys); /* drop the ref. we got in remove_memory_block() */ - kobject_put(&memory->dev.kobj); + put_device(&memory->dev); device_unregister(&memory->dev); } @@ -682,7 +659,7 @@ static int remove_memory_block(unsigned long node_id, if (mem->section_count == 0) unregister_memory(mem); else - kobject_put(&mem->dev.kobj); + put_device(&mem->dev); mutex_unlock(&mem_sysfs_mutex); return 0; @@ -735,7 +712,6 @@ int __init memory_dev_init(void) int ret; int err; unsigned long block_sz; - struct memory_block *mem = NULL; ret = subsys_system_register(&memory_subsys, memory_root_attr_groups); if (ret) @@ -748,17 +724,13 @@ int __init memory_dev_init(void) * Create entries for memory sections that were found * during boot and have been initialized */ - for (i = 0; i < NR_MEM_SECTIONS; i++) { - if (!present_section_nr(i)) - continue; - /* don't need to reuse memory_block if only one per block */ - err = add_memory_section(0, __nr_to_section(i), - (sections_per_block == 1) ? NULL : &mem, - MEM_ONLINE, - BOOT); + mutex_lock(&mem_sysfs_mutex); + for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) { + err = add_memory_block(i); if (!ret) ret = err; } + mutex_unlock(&mem_sysfs_mutex); out: if (ret) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 3c3197a8de41..4f8bef3eb5a8 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -672,11 +672,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; } +static DEVICE_ATTR_RO(modalias); -static struct device_attribute platform_dev_attrs[] = { - __ATTR_RO(modalias), - __ATTR_NULL, +static struct attribute *platform_dev_attrs[] = { + &dev_attr_modalias.attr, + NULL, }; +ATTRIBUTE_GROUPS(platform_dev); static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) { @@ -893,7 +895,7 @@ static const struct dev_pm_ops platform_dev_pm_ops = { struct bus_type platform_bus_type = { .name = "platform", - .dev_attrs = platform_dev_attrs, + .dev_groups = platform_dev_groups, .match = platform_match, .uevent = platform_uevent, .pm = &platform_dev_pm_ops, @@ -1054,7 +1056,7 @@ void __init early_platform_driver_register_all(char *class_str) * @epdrv: early platform driver structure * @id: id to match against */ -static __init struct platform_device * +static struct platform_device * __init early_platform_match(struct early_platform_driver *epdrv, int id) { struct platform_device *pd; @@ -1072,7 +1074,7 @@ early_platform_match(struct early_platform_driver *epdrv, int id) * @epdrv: early platform driver structure * @id: return true if id or above exists */ -static __init int early_platform_left(struct early_platform_driver *epdrv, +static int __init early_platform_left(struct early_platform_driver *epdrv, int id) { struct platform_device *pd; diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index a53ebd265701..03e089ade5ce 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -206,7 +206,7 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev, if (!dev->power.use_autosuspend) return -EIO; - if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay) + if (kstrtol(buf, 10, &delay) != 0 || delay != (int) delay) return -EINVAL; device_lock(dev); diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 6c2652a8ad50..de11ecaf3833 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -281,7 +281,7 @@ static ssize_t regmap_map_write_file(struct file *file, reg = simple_strtoul(start, &start, 16); while (*start == ' ') start++; - if (strict_strtoul(start, 16, &value)) + if (kstrtoul(start, 16, &value)) return -EINVAL; /* Userspace has been fiddling around behind the kernel's back */ diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 2f5919ed91ab..94ffee378f10 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -62,25 +62,6 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) } #endif -#ifdef arch_provides_topology_pointers -#define define_siblings_show_map(name) \ -static ssize_t show_##name(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - unsigned int cpu = dev->id; \ - return show_cpumap(0, topology_##name(cpu), buf); \ -} - -#define define_siblings_show_list(name) \ -static ssize_t show_##name##_list(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - unsigned int cpu = dev->id; \ - return show_cpumap(1, topology_##name(cpu), buf); \ -} - -#else #define define_siblings_show_map(name) \ static ssize_t show_##name(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -95,7 +76,6 @@ static ssize_t show_##name##_list(struct device *dev, \ { \ return show_cpumap(1, topology_##name(dev->id), buf); \ } -#endif #define define_siblings_show_func(name) \ define_siblings_show_map(name); define_siblings_show_list(name) |