diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Makefile | 4 | ||||
-rw-r--r-- | drivers/base/base.h | 12 | ||||
-rw-r--r-- | drivers/base/bus.c | 293 | ||||
-rw-r--r-- | drivers/base/class.c | 14 | ||||
-rw-r--r-- | drivers/base/core.c | 85 | ||||
-rw-r--r-- | drivers/base/cpu.c | 150 | ||||
-rw-r--r-- | drivers/base/devtmpfs.c | 3 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 14 | ||||
-rw-r--r-- | drivers/base/init.c | 1 | ||||
-rw-r--r-- | drivers/base/memory.c | 160 | ||||
-rw-r--r-- | drivers/base/node.c | 154 | ||||
-rw-r--r-- | drivers/base/platform.c | 2 | ||||
-rw-r--r-- | drivers/base/sys.c | 10 | ||||
-rw-r--r-- | drivers/base/topology.c | 51 |
14 files changed, 618 insertions, 335 deletions
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 99a375ad2cc9..1334d893b560 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -3,7 +3,8 @@ obj-y := core.o sys.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o devres.o \ - attribute_container.o transport_class.o + attribute_container.o transport_class.o \ + topology.o obj-$(CONFIG_DEVTMPFS) += devtmpfs.o obj-y += power/ obj-$(CONFIG_HAS_DMA) += dma-mapping.o @@ -12,7 +13,6 @@ obj-$(CONFIG_ISA) += isa.o obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o -obj-$(CONFIG_SMP) += topology.o ifeq ($(CONFIG_SYSFS),y) obj-$(CONFIG_MODULES) += module.o endif diff --git a/drivers/base/base.h b/drivers/base/base.h index 21c1b96c34c6..7a6ae4228761 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -4,7 +4,9 @@ * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure. * * @subsys - the struct kset that defines this subsystem - * @devices_kset - the list of devices associated + * @devices_kset - the subsystem's 'devices' directory + * @interfaces - list of subsystem interfaces associated + * @mutex - protect the devices, and interfaces lists. * * @drivers_kset - the list of drivers associated * @klist_devices - the klist to iterate over the @devices_kset @@ -14,10 +16,8 @@ * @bus - pointer back to the struct bus_type that this structure is associated * with. * - * @class_interfaces - list of class_interfaces associated * @glue_dirs - "glue" directory to put in-between the parent device to * avoid namespace conflicts - * @class_mutex - mutex to protect the children, devices, and interfaces lists. * @class - pointer back to the struct class that this structure is associated * with. * @@ -28,6 +28,8 @@ struct subsys_private { struct kset subsys; struct kset *devices_kset; + struct list_head interfaces; + struct mutex mutex; struct kset *drivers_kset; struct klist klist_devices; @@ -36,9 +38,7 @@ struct subsys_private { unsigned int drivers_autoprobe:1; struct bus_type *bus; - struct list_head class_interfaces; struct kset glue_dirs; - struct mutex class_mutex; struct class *class; }; #define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj) @@ -94,7 +94,6 @@ extern int hypervisor_init(void); static inline int hypervisor_init(void) { return 0; } #endif extern int platform_bus_init(void); -extern int system_bus_init(void); extern int cpu_dev_init(void); extern int bus_add_device(struct device *dev); @@ -116,6 +115,7 @@ extern char *make_class_name(const char *name, struct kobject *kobj); extern int devres_release_all(struct device *dev); +/* /sys/devices directory */ extern struct kset *devices_kset; #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 000e7b2006f8..99dc5921e1dd 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -16,9 +16,14 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/string.h> +#include <linux/mutex.h> #include "base.h" #include "power/power.h" +/* /sys/devices/system */ +/* FIXME: make static after drivers/base/sys.c is deleted */ +struct kset *system_kset; + #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) /* @@ -360,6 +365,47 @@ struct device *bus_find_device_by_name(struct bus_type *bus, } EXPORT_SYMBOL_GPL(bus_find_device_by_name); +/** + * subsys_find_device_by_id - find a device with a specific enumeration number + * @subsys: subsystem + * @id: index 'id' in struct device + * @hint: device to check first + * + * Check the hint's next object and if it is a match return it directly, + * otherwise, fall back to a full list search. Either way a reference for + * the returned object is taken. + */ +struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id, + struct device *hint) +{ + struct klist_iter i; + struct device *dev; + + if (!subsys) + return NULL; + + if (hint) { + klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus); + dev = next_device(&i); + if (dev && dev->id == id && get_device(dev)) { + klist_iter_exit(&i); + return dev; + } + klist_iter_exit(&i); + } + + klist_iter_init_node(&subsys->p->klist_devices, &i, NULL); + while ((dev = next_device(&i))) { + if (dev->id == id && get_device(dev)) { + klist_iter_exit(&i); + return dev; + } + } + klist_iter_exit(&i); + return NULL; +} +EXPORT_SYMBOL_GPL(subsys_find_device_by_id); + static struct device_driver *next_driver(struct klist_iter *i) { struct klist_node *n = klist_next(i); @@ -487,38 +533,59 @@ out_put: void bus_probe_device(struct device *dev) { struct bus_type *bus = dev->bus; + struct subsys_interface *sif; int ret; - if (bus && bus->p->drivers_autoprobe) { + if (!bus) + return; + + if (bus->p->drivers_autoprobe) { ret = device_attach(dev); WARN_ON(ret < 0); } + + mutex_lock(&bus->p->mutex); + list_for_each_entry(sif, &bus->p->interfaces, node) + if (sif->add_dev) + sif->add_dev(dev, sif); + mutex_unlock(&bus->p->mutex); } /** * bus_remove_device - remove device from bus * @dev: device to be removed * - * - Remove symlink from bus's directory. + * - Remove device from all interfaces. + * - Remove symlink from bus' directory. * - Delete device from bus's list. * - Detach from its driver. * - Drop reference taken in bus_add_device(). */ void bus_remove_device(struct device *dev) { - if (dev->bus) { - sysfs_remove_link(&dev->kobj, "subsystem"); - sysfs_remove_link(&dev->bus->p->devices_kset->kobj, - dev_name(dev)); - device_remove_attrs(dev->bus, dev); - if (klist_node_attached(&dev->p->knode_bus)) - klist_del(&dev->p->knode_bus); - - pr_debug("bus: '%s': remove device %s\n", - dev->bus->name, dev_name(dev)); - device_release_driver(dev); - bus_put(dev->bus); - } + struct bus_type *bus = dev->bus; + struct subsys_interface *sif; + + if (!bus) + return; + + mutex_lock(&bus->p->mutex); + list_for_each_entry(sif, &bus->p->interfaces, node) + if (sif->remove_dev) + sif->remove_dev(dev, sif); + mutex_unlock(&bus->p->mutex); + + sysfs_remove_link(&dev->kobj, "subsystem"); + sysfs_remove_link(&dev->bus->p->devices_kset->kobj, + dev_name(dev)); + device_remove_attrs(dev->bus, dev); + if (klist_node_attached(&dev->p->knode_bus)) + klist_del(&dev->p->knode_bus); + + pr_debug("bus: '%s': remove device %s\n", + dev->bus->name, dev_name(dev)); + device_release_driver(dev); + bus_put(dev->bus); } static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) @@ -847,14 +914,14 @@ static ssize_t bus_uevent_store(struct bus_type *bus, static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); /** - * bus_register - register a bus with the system. + * __bus_register - register a driver-core subsystem * @bus: bus. * * Once we have that, we registered the bus with the kobject * infrastructure, then register the children subsystems it has: - * the devices and drivers that belong to the bus. + * the devices and drivers that belong to the subsystem. */ -int bus_register(struct bus_type *bus) +int __bus_register(struct bus_type *bus, struct lock_class_key *key) { int retval; struct subsys_private *priv; @@ -898,6 +965,8 @@ int bus_register(struct bus_type *bus) goto bus_drivers_fail; } + INIT_LIST_HEAD(&priv->interfaces); + __mutex_init(&priv->mutex, "subsys mutex", key); klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); klist_init(&priv->klist_drivers, NULL, NULL); @@ -927,7 +996,7 @@ out: bus->p = NULL; return retval; } -EXPORT_SYMBOL_GPL(bus_register); +EXPORT_SYMBOL_GPL(__bus_register); /** * bus_unregister - remove a bus from the system @@ -939,6 +1008,8 @@ EXPORT_SYMBOL_GPL(bus_register); void bus_unregister(struct bus_type *bus) { pr_debug("bus: '%s': unregistering\n", bus->name); + if (bus->dev_root) + device_unregister(bus->dev_root); bus_remove_attrs(bus); remove_probe_files(bus); kset_unregister(bus->p->drivers_kset); @@ -1028,10 +1099,194 @@ void bus_sort_breadthfirst(struct bus_type *bus, } EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); +/** + * subsys_dev_iter_init - initialize subsys device iterator + * @iter: subsys iterator to initialize + * @subsys: the subsys we wanna iterate over + * @start: the device to start iterating from, if any + * @type: device_type of the devices to iterate over, NULL for all + * + * Initialize subsys iterator @iter such that it iterates over devices + * of @subsys. If @start is set, the list iteration will start there, + * otherwise if it is NULL, the iteration starts at the beginning of + * the list. + */ +void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys, + struct device *start, const struct device_type *type) +{ + struct klist_node *start_knode = NULL; + + if (start) + start_knode = &start->p->knode_bus; + klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode); + iter->type = type; +} +EXPORT_SYMBOL_GPL(subsys_dev_iter_init); + +/** + * subsys_dev_iter_next - iterate to the next device + * @iter: subsys iterator to proceed + * + * Proceed @iter to the next device and return it. Returns NULL if + * iteration is complete. + * + * The returned device is referenced and won't be released till + * iterator is proceed to the next device or exited. The caller is + * free to do whatever it wants to do with the device including + * calling back into subsys code. + */ +struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) +{ + struct klist_node *knode; + struct device *dev; + + for (;;) { + knode = klist_next(&iter->ki); + if (!knode) + return NULL; + dev = container_of(knode, struct device_private, knode_bus)->device; + if (!iter->type || iter->type == dev->type) + return dev; + } +} +EXPORT_SYMBOL_GPL(subsys_dev_iter_next); + +/** + * subsys_dev_iter_exit - finish iteration + * @iter: subsys iterator to finish + * + * Finish an iteration. Always call this function after iteration is + * complete whether the iteration ran till the end or not. + */ +void subsys_dev_iter_exit(struct subsys_dev_iter *iter) +{ + klist_iter_exit(&iter->ki); +} +EXPORT_SYMBOL_GPL(subsys_dev_iter_exit); + +int subsys_interface_register(struct subsys_interface *sif) +{ + struct bus_type *subsys; + struct subsys_dev_iter iter; + struct device *dev; + + if (!sif || !sif->subsys) + return -ENODEV; + + subsys = bus_get(sif->subsys); + if (!subsys) + return -EINVAL; + + mutex_lock(&subsys->p->mutex); + list_add_tail(&sif->node, &subsys->p->interfaces); + if (sif->add_dev) { + subsys_dev_iter_init(&iter, subsys, NULL, NULL); + while ((dev = subsys_dev_iter_next(&iter))) + sif->add_dev(dev, sif); + subsys_dev_iter_exit(&iter); + } + mutex_unlock(&subsys->p->mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(subsys_interface_register); + +void subsys_interface_unregister(struct subsys_interface *sif) +{ + struct bus_type *subsys = sif->subsys; + struct subsys_dev_iter iter; + struct device *dev; + + if (!sif) + return; + + mutex_lock(&subsys->p->mutex); + list_del_init(&sif->node); + if (sif->remove_dev) { + subsys_dev_iter_init(&iter, subsys, NULL, NULL); + while ((dev = subsys_dev_iter_next(&iter))) + sif->remove_dev(dev, sif); + subsys_dev_iter_exit(&iter); + } + mutex_unlock(&subsys->p->mutex); + + bus_put(subsys); +} +EXPORT_SYMBOL_GPL(subsys_interface_unregister); + +static void system_root_device_release(struct device *dev) +{ + kfree(dev); +} +/** + * subsys_system_register - register a subsystem at /sys/devices/system/ + * @subsys - system subsystem + * @groups - default attributes for the root device + * + * All 'system' subsystems have a /sys/devices/system/<name> root device + * with the name of the subsystem. The root device can carry subsystem- + * wide attributes. All registered devices are below this single root + * device and are named after the subsystem with a simple enumeration + * number appended. The registered devices are not explicitely named; + * only 'id' in the device needs to be set. + * + * Do not use this interface for anything new, it exists for compatibility + * with bad ideas only. New subsystems should use plain subsystems; and + * add the subsystem-wide attributes should be added to the subsystem + * directory itself and not some create fake root-device placed in + * /sys/devices/system/<name>. + */ +int subsys_system_register(struct bus_type *subsys, + const struct attribute_group **groups) +{ + struct device *dev; + int err; + + err = bus_register(subsys); + if (err < 0) + return err; + + dev = kzalloc(sizeof(struct device), GFP_KERNEL); + if (!dev) { + err = -ENOMEM; + goto err_dev; + } + + err = dev_set_name(dev, "%s", subsys->name); + if (err < 0) + goto err_name; + + dev->kobj.parent = &system_kset->kobj; + dev->groups = groups; + dev->release = system_root_device_release; + + err = device_register(dev); + if (err < 0) + goto err_dev_reg; + + subsys->dev_root = dev; + return 0; + +err_dev_reg: + put_device(dev); + dev = NULL; +err_name: + kfree(dev); +err_dev: + bus_unregister(subsys); + return err; +} +EXPORT_SYMBOL_GPL(subsys_system_register); + int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); if (!bus_kset) return -ENOMEM; + + system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); + if (!system_kset) + return -ENOMEM; + return 0; } diff --git a/drivers/base/class.c b/drivers/base/class.c index b80d91cc8c3a..03243d4002fd 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key) if (!cp) return -ENOMEM; klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put); - INIT_LIST_HEAD(&cp->class_interfaces); + INIT_LIST_HEAD(&cp->interfaces); kset_init(&cp->glue_dirs); - __mutex_init(&cp->class_mutex, "struct class mutex", key); + __mutex_init(&cp->mutex, "subsys mutex", key); error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); if (error) { kfree(cp); @@ -460,15 +460,15 @@ int class_interface_register(struct class_interface *class_intf) if (!parent) return -EINVAL; - mutex_lock(&parent->p->class_mutex); - list_add_tail(&class_intf->node, &parent->p->class_interfaces); + mutex_lock(&parent->p->mutex); + list_add_tail(&class_intf->node, &parent->p->interfaces); if (class_intf->add_dev) { class_dev_iter_init(&iter, parent, NULL, NULL); while ((dev = class_dev_iter_next(&iter))) class_intf->add_dev(dev, class_intf); class_dev_iter_exit(&iter); } - mutex_unlock(&parent->p->class_mutex); + mutex_unlock(&parent->p->mutex); return 0; } @@ -482,7 +482,7 @@ void class_interface_unregister(struct class_interface *class_intf) if (!parent) return; - mutex_lock(&parent->p->class_mutex); + mutex_lock(&parent->p->mutex); list_del_init(&class_intf->node); if (class_intf->remove_dev) { class_dev_iter_init(&iter, parent, NULL, NULL); @@ -490,7 +490,7 @@ void class_interface_unregister(struct class_interface *class_intf) class_intf->remove_dev(dev, class_intf); class_dev_iter_exit(&iter); } - mutex_unlock(&parent->p->class_mutex); + mutex_unlock(&parent->p->mutex); class_put(parent); } diff --git a/drivers/base/core.c b/drivers/base/core.c index 919daa7cd5b1..4dac58aa4a0a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -118,6 +118,56 @@ static const struct sysfs_ops dev_sysfs_ops = { .store = dev_attr_store, }; +#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr) + +ssize_t device_store_ulong(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + char *end; + unsigned long new = simple_strtoul(buf, &end, 0); + if (end == buf) + return -EINVAL; + *(unsigned long *)(ea->var) = new; + /* Always return full write size even if we didn't consume all */ + return size; +} +EXPORT_SYMBOL_GPL(device_store_ulong); + +ssize_t device_show_ulong(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); +} +EXPORT_SYMBOL_GPL(device_show_ulong); + +ssize_t device_store_int(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + char *end; + long new = simple_strtol(buf, &end, 0); + if (end == buf || new > INT_MAX || new < INT_MIN) + return -EINVAL; + *(int *)(ea->var) = new; + /* Always return full write size even if we didn't consume all */ + return size; +} +EXPORT_SYMBOL_GPL(device_store_int); + +ssize_t device_show_int(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + + return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); +} +EXPORT_SYMBOL_GPL(device_show_int); /** * device_release - free device structure. @@ -464,7 +514,7 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr, static struct device_attribute devt_attr = __ATTR(dev, S_IRUGO, show_dev, NULL); -/* kset to create /sys/devices/ */ +/* /sys/devices/ */ struct kset *devices_kset; /** @@ -711,6 +761,10 @@ static struct kobject *get_device_parent(struct device *dev, return k; } + /* subsystems can specify a default root directory for their devices */ + if (!parent && dev->bus && dev->bus->dev_root) + return &dev->bus->dev_root->kobj; + if (parent) return &parent->kobj; return NULL; @@ -731,14 +785,6 @@ static void cleanup_device_parent(struct device *dev) cleanup_glue_dir(dev, dev->kobj.parent); } -static void setup_parent(struct device *dev, struct device *parent) -{ - struct kobject *kobj; - kobj = get_device_parent(dev, parent); - if (kobj) - dev->kobj.parent = kobj; -} - static int device_add_class_symlinks(struct device *dev) { int error; @@ -891,6 +937,7 @@ int device_private_init(struct device *dev) int device_add(struct device *dev) { struct device *parent = NULL; + struct kobject *kobj; struct class_interface *class_intf; int error = -EINVAL; @@ -914,6 +961,10 @@ int device_add(struct device *dev) dev->init_name = NULL; } + /* subsystems can specify simple device enumeration */ + if (!dev_name(dev) && dev->bus && dev->bus->dev_name) + dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); + if (!dev_name(dev)) { error = -EINVAL; goto name_error; @@ -922,7 +973,9 @@ int device_add(struct device *dev) pr_debug("device: '%s': %s\n", dev_name(dev), __func__); parent = get_device(dev->parent); - setup_parent(dev, parent); + kobj = get_device_parent(dev, parent); + if (kobj) + dev->kobj.parent = kobj; /* use parent numa_node */ if (parent) @@ -982,17 +1035,17 @@ int device_add(struct device *dev) &parent->p->klist_children); if (dev->class) { - mutex_lock(&dev->class->p->class_mutex); + mutex_lock(&dev->class->p->mutex); /* tie the class to the device */ klist_add_tail(&dev->knode_class, &dev->class->p->klist_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, - &dev->class->p->class_interfaces, node) + &dev->class->p->interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); - mutex_unlock(&dev->class->p->class_mutex); + mutex_unlock(&dev->class->p->mutex); } done: put_device(dev); @@ -1107,15 +1160,15 @@ void device_del(struct device *dev) if (dev->class) { device_remove_class_symlinks(dev); - mutex_lock(&dev->class->p->class_mutex); + mutex_lock(&dev->class->p->mutex); /* notify any interfaces that the device is now gone */ list_for_each_entry(class_intf, - &dev->class->p->class_interfaces, node) + &dev->class->p->interfaces, node) if (class_intf->remove_dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ klist_del(&dev->knode_class); - mutex_unlock(&dev->class->p->class_mutex); + mutex_unlock(&dev->class->p->mutex); } device_remove_file(dev, &uevent_attr); device_remove_attrs(dev); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 3991502b21e5..9a5578efbc93 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -1,8 +1,7 @@ /* - * drivers/base/cpu.c - basic CPU class support + * CPU subsystem support */ -#include <linux/sysdev.h> #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> @@ -14,40 +13,40 @@ #include "base.h" -static struct sysdev_class_attribute *cpu_sysdev_class_attrs[]; - -struct sysdev_class cpu_sysdev_class = { +struct bus_type cpu_subsys = { .name = "cpu", - .attrs = cpu_sysdev_class_attrs, + .dev_name = "cpu", }; -EXPORT_SYMBOL(cpu_sysdev_class); +EXPORT_SYMBOL_GPL(cpu_subsys); -static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); +static DEFINE_PER_CPU(struct device *, cpu_sys_devices); #ifdef CONFIG_HOTPLUG_CPU -static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr, +static ssize_t show_online(struct device *dev, + struct device_attribute *attr, char *buf) { - struct cpu *cpu = container_of(dev, struct cpu, sysdev); + struct cpu *cpu = container_of(dev, struct cpu, dev); - return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); + return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id)); } -static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr, - const char *buf, size_t count) +static ssize_t __ref store_online(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - struct cpu *cpu = container_of(dev, struct cpu, sysdev); + struct cpu *cpu = container_of(dev, struct cpu, dev); ssize_t ret; cpu_hotplug_driver_lock(); switch (buf[0]) { case '0': - ret = cpu_down(cpu->sysdev.id); + ret = cpu_down(cpu->dev.id); if (!ret) kobject_uevent(&dev->kobj, KOBJ_OFFLINE); break; case '1': - ret = cpu_up(cpu->sysdev.id); + ret = cpu_up(cpu->dev.id); if (!ret) kobject_uevent(&dev->kobj, KOBJ_ONLINE); break; @@ -60,44 +59,44 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut ret = count; return ret; } -static SYSDEV_ATTR(online, 0644, show_online, store_online); +static DEVICE_ATTR(online, 0644, show_online, store_online); static void __cpuinit register_cpu_control(struct cpu *cpu) { - sysdev_create_file(&cpu->sysdev, &attr_online); + device_create_file(&cpu->dev, &dev_attr_online); } void unregister_cpu(struct cpu *cpu) { - int logical_cpu = cpu->sysdev.id; + int logical_cpu = cpu->dev.id; unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); - sysdev_remove_file(&cpu->sysdev, &attr_online); + device_remove_file(&cpu->dev, &dev_attr_online); - sysdev_unregister(&cpu->sysdev); + device_unregister(&cpu->dev); per_cpu(cpu_sys_devices, logical_cpu) = NULL; return; } #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE -static ssize_t cpu_probe_store(struct sysdev_class *class, - struct sysdev_class_attribute *attr, +static ssize_t cpu_probe_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { return arch_cpu_probe(buf, count); } -static ssize_t cpu_release_store(struct sysdev_class *class, - struct sysdev_class_attribute *attr, +static ssize_t cpu_release_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { return arch_cpu_release(buf, count); } -static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); -static SYSDEV_CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); +static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); +static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ #else /* ... !CONFIG_HOTPLUG_CPU */ @@ -109,15 +108,15 @@ static inline void register_cpu_control(struct cpu *cpu) #ifdef CONFIG_KEXEC #include <linux/kexec.h> -static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr, +static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr, char *buf) { - struct cpu *cpu = container_of(dev, struct cpu, sysdev); + struct cpu *cpu = container_of(dev, struct cpu, dev); ssize_t rc; unsigned long long addr; int cpunum; - cpunum = cpu->sysdev.id; + cpunum = cpu->dev.id; /* * Might be reading other cpu's data based on which cpu read thread @@ -129,7 +128,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute rc = sprintf(buf, "%Lx\n", addr); return rc; } -static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); +static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL); #endif /* @@ -137,12 +136,12 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); */ struct cpu_attr { - struct sysdev_class_attribute attr; + struct device_attribute attr; const struct cpumask *const * const map; }; -static ssize_t show_cpus_attr(struct sysdev_class *class, - struct sysdev_class_attribute *attr, +static ssize_t show_cpus_attr(struct device *dev, + struct device_attribute *attr, char *buf) { struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); @@ -153,10 +152,10 @@ static ssize_t show_cpus_attr(struct sysdev_class *class, return n; } -#define _CPU_ATTR(name, map) \ - { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } +#define _CPU_ATTR(name, map) \ + { __ATTR(name, 0444, show_cpus_attr, NULL), map } -/* Keep in sync with cpu_sysdev_class_attrs */ +/* Keep in sync with cpu_subsys_attrs */ static struct cpu_attr cpu_attrs[] = { _CPU_ATTR(online, &cpu_online_mask), _CPU_ATTR(possible, &cpu_possible_mask), @@ -166,19 +165,19 @@ static struct cpu_attr cpu_attrs[] = { /* * Print values for NR_CPUS and offlined cpus */ -static ssize_t print_cpus_kernel_max(struct sysdev_class *class, - struct sysdev_class_attribute *attr, char *buf) +static ssize_t print_cpus_kernel_max(struct device *dev, + struct device_attribute *attr, char *buf) { int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); return n; } -static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); +static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ unsigned int total_cpus; -static ssize_t print_cpus_offline(struct sysdev_class *class, - struct sysdev_class_attribute *attr, char *buf) +static ssize_t print_cpus_offline(struct device *dev, + struct device_attribute *attr, char *buf) { int n = 0, len = PAGE_SIZE-2; cpumask_var_t offline; @@ -205,7 +204,7 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, n += snprintf(&buf[n], len - n, "\n"); return n; } -static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); +static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); /* * register_cpu - Setup a sysfs device for a CPU. @@ -218,39 +217,60 @@ static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); int __cpuinit register_cpu(struct cpu *cpu, int num) { int error; - cpu->node_id = cpu_to_node(num); - cpu->sysdev.id = num; - cpu->sysdev.cls = &cpu_sysdev_class; - - error = sysdev_register(&cpu->sysdev); + cpu->node_id = cpu_to_node(num); + cpu->dev.id = num; + cpu->dev.bus = &cpu_subsys; + error = device_register(&cpu->dev); if (!error && cpu->hotpluggable) register_cpu_control(cpu); if (!error) - per_cpu(cpu_sys_devices, num) = &cpu->sysdev; + per_cpu(cpu_sys_devices, num) = &cpu->dev; if (!error) register_cpu_under_node(num, cpu_to_node(num)); #ifdef CONFIG_KEXEC if (!error) - error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); + error = device_create_file(&cpu->dev, &dev_attr_crash_notes); #endif return error; } -struct sys_device *get_cpu_sysdev(unsigned cpu) +struct device *get_cpu_device(unsigned cpu) { if (cpu < nr_cpu_ids && cpu_possible(cpu)) return per_cpu(cpu_sys_devices, cpu); else return NULL; } -EXPORT_SYMBOL_GPL(get_cpu_sysdev); +EXPORT_SYMBOL_GPL(get_cpu_device); + +static struct attribute *cpu_root_attrs[] = { +#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE + &dev_attr_probe.attr, + &dev_attr_release.attr, +#endif + &cpu_attrs[0].attr.attr, + &cpu_attrs[1].attr.attr, + &cpu_attrs[2].attr.attr, + &dev_attr_kernel_max.attr, + &dev_attr_offline.attr, + NULL +}; + +static struct attribute_group cpu_root_attr_group = { + .attrs = cpu_root_attrs, +}; + +static const struct attribute_group *cpu_root_attr_groups[] = { + &cpu_root_attr_group, + NULL, +}; bool cpu_is_hotpluggable(unsigned cpu) { - struct sys_device *dev = get_cpu_sysdev(cpu); - return dev && container_of(dev, struct cpu, sysdev)->hotpluggable; + struct device *dev = get_cpu_device(cpu); + return dev && container_of(dev, struct cpu, dev)->hotpluggable; } EXPORT_SYMBOL_GPL(cpu_is_hotpluggable); @@ -258,24 +278,12 @@ int __init cpu_dev_init(void) { int err; - err = sysdev_class_register(&cpu_sysdev_class); + err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups); + if (err) + return err; + #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - if (!err) - err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); + err = sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root); #endif - return err; } - -static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = { -#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE - &attr_probe, - &attr_release, -#endif - &cpu_attrs[0].attr, - &cpu_attrs[1].attr, - &cpu_attrs[2].attr, - &attr_kernel_max, - &attr_offline, - NULL -}; diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index a4760e095ff5..2bb4bff3af7d 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -413,10 +413,9 @@ static int devtmpfsd(void *p) } spin_lock(&req_lock); } - set_current_state(TASK_INTERRUPTIBLE); + __set_current_state(TASK_INTERRUPTIBLE); spin_unlock(&req_lock); schedule(); - __set_current_state(TASK_RUNNING); } return 0; out: diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 06ed6b4e7df5..3719c94be19c 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -226,13 +226,13 @@ static ssize_t firmware_loading_store(struct device *dev, int loading = simple_strtol(buf, NULL, 10); int i; + mutex_lock(&fw_lock); + + if (!fw_priv->fw) + goto out; + switch (loading) { case 1: - mutex_lock(&fw_lock); - if (!fw_priv->fw) { - mutex_unlock(&fw_lock); - break; - } firmware_free_data(fw_priv->fw); memset(fw_priv->fw, 0, sizeof(struct firmware)); /* If the pages are not owned by 'struct firmware' */ @@ -243,7 +243,6 @@ static ssize_t firmware_loading_store(struct device *dev, fw_priv->page_array_size = 0; fw_priv->nr_pages = 0; set_bit(FW_STATUS_LOADING, &fw_priv->status); - mutex_unlock(&fw_lock); break; case 0: if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { @@ -274,7 +273,8 @@ static ssize_t firmware_loading_store(struct device *dev, fw_load_abort(fw_priv); break; } - +out: + mutex_unlock(&fw_lock); return count; } diff --git a/drivers/base/init.c b/drivers/base/init.c index c8a934e79421..c16f0b808a17 100644 --- a/drivers/base/init.c +++ b/drivers/base/init.c @@ -31,7 +31,6 @@ void __init driver_init(void) * core core pieces. */ platform_bus_init(); - system_bus_init(); cpu_dev_init(); memory_dev_init(); } diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 8272d92d22c0..f17e3ea041c0 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -1,5 +1,5 @@ /* - * drivers/base/memory.c - basic Memory class support + * Memory subsystem support * * Written by Matt Tolentino <matthew.e.tolentino@intel.com> * Dave Hansen <haveblue@us.ibm.com> @@ -10,7 +10,6 @@ * SPARSEMEM should be contained here, or in mm/memory_hotplug.c. */ -#include <linux/sysdev.h> #include <linux/module.h> #include <linux/init.h> #include <linux/topology.h> @@ -38,26 +37,9 @@ static inline int base_memory_block_id(int section_nr) return section_nr / sections_per_block; } -static struct sysdev_class memory_sysdev_class = { +static struct bus_type memory_subsys = { .name = MEMORY_CLASS_NAME, -}; - -static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj) -{ - return MEMORY_CLASS_NAME; -} - -static int memory_uevent(struct kset *kset, struct kobject *obj, - struct kobj_uevent_env *env) -{ - int retval = 0; - - return retval; -} - -static const struct kset_uevent_ops memory_uevent_ops = { - .name = memory_uevent_name, - .uevent = memory_uevent, + .dev_name = MEMORY_CLASS_NAME, }; static BLOCKING_NOTIFIER_HEAD(memory_chain); @@ -96,21 +78,21 @@ int register_memory(struct memory_block *memory) { int error; - memory->sysdev.cls = &memory_sysdev_class; - memory->sysdev.id = memory->start_section_nr / sections_per_block; + memory->dev.bus = &memory_subsys; + memory->dev.id = memory->start_section_nr / sections_per_block; - error = sysdev_register(&memory->sysdev); + error = device_register(&memory->dev); return error; } static void unregister_memory(struct memory_block *memory) { - BUG_ON(memory->sysdev.cls != &memory_sysdev_class); + BUG_ON(memory->dev.bus != &memory_subsys); /* drop the ref. we got in remove_memory_block() */ - kobject_put(&memory->sysdev.kobj); - sysdev_unregister(&memory->sysdev); + kobject_put(&memory->dev.kobj); + device_unregister(&memory->dev); } unsigned long __weak memory_block_size_bytes(void) @@ -138,22 +120,22 @@ static unsigned long get_memory_block_size(void) * uses. */ -static ssize_t show_mem_start_phys_index(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +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, sysdev); + container_of(dev, struct memory_block, dev); unsigned long phys_index; phys_index = mem->start_section_nr / sections_per_block; return sprintf(buf, "%08lx\n", phys_index); } -static ssize_t show_mem_end_phys_index(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +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, sysdev); + container_of(dev, struct memory_block, dev); unsigned long phys_index; phys_index = mem->end_section_nr / sections_per_block; @@ -163,13 +145,13 @@ static ssize_t show_mem_end_phys_index(struct sys_device *dev, /* * Show whether the section of memory is likely to be hot-removable */ -static ssize_t show_mem_removable(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t show_mem_removable(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long i, pfn; int ret = 1; struct memory_block *mem = - container_of(dev, struct memory_block, sysdev); + container_of(dev, struct memory_block, dev); for (i = 0; i < sections_per_block; i++) { pfn = section_nr_to_pfn(mem->start_section_nr + i); @@ -182,11 +164,11 @@ static ssize_t show_mem_removable(struct sys_device *dev, /* * online, offline, going offline, etc. */ -static ssize_t show_mem_state(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +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, sysdev); + container_of(dev, struct memory_block, dev); ssize_t len = 0; /* @@ -324,13 +306,13 @@ out: } static ssize_t -store_mem_state(struct sys_device *dev, - struct sysdev_attribute *attr, const char *buf, size_t count) +store_mem_state(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { struct memory_block *mem; int ret = -EINVAL; - mem = container_of(dev, struct memory_block, sysdev); + mem = container_of(dev, struct memory_block, dev); if (!strncmp(buf, "online", min((int)count, 6))) ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE); @@ -351,41 +333,41 @@ store_mem_state(struct sys_device *dev, * s.t. if I offline all of these sections I can then * remove the physical device? */ -static ssize_t show_phys_device(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +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, sysdev); + container_of(dev, struct memory_block, dev); return sprintf(buf, "%d\n", mem->phys_device); } -static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL); -static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL); -static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); -static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); -static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); +static DEVICE_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL); +static DEVICE_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL); +static DEVICE_ATTR(state, 0644, show_mem_state, store_mem_state); +static DEVICE_ATTR(phys_device, 0444, show_phys_device, NULL); +static DEVICE_ATTR(removable, 0444, show_mem_removable, NULL); #define mem_create_simple_file(mem, attr_name) \ - sysdev_create_file(&mem->sysdev, &attr_##attr_name) + device_create_file(&mem->dev, &dev_attr_##attr_name) #define mem_remove_simple_file(mem, attr_name) \ - sysdev_remove_file(&mem->sysdev, &attr_##attr_name) + device_remove_file(&mem->dev, &dev_attr_##attr_name) /* * Block size attribute stuff */ static ssize_t -print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr, +print_block_size(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%lx\n", get_memory_block_size()); } -static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static DEVICE_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { - return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_block_size_bytes.attr); + return device_create_file(memory_subsys.dev_root, + &dev_attr_block_size_bytes); } /* @@ -396,7 +378,7 @@ static int block_size_init(void) */ #ifdef CONFIG_ARCH_MEMORY_PROBE static ssize_t -memory_probe_store(struct class *class, struct class_attribute *attr, +memory_probe_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u64 phys_addr; @@ -423,12 +405,11 @@ memory_probe_store(struct class *class, struct class_attribute *attr, out: return ret; } -static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); +static DEVICE_ATTR(probe, S_IWUSR, NULL, memory_probe_store); static int memory_probe_init(void) { - return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_probe.attr); + return device_create_file(memory_subsys.dev_root, &dev_attr_probe); } #else static inline int memory_probe_init(void) @@ -444,8 +425,8 @@ static inline int memory_probe_init(void) /* Soft offline a page */ static ssize_t -store_soft_offline_page(struct class *class, - struct class_attribute *attr, +store_soft_offline_page(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { int ret; @@ -463,8 +444,8 @@ store_soft_offline_page(struct class *class, /* Forcibly offline a page, including killing processes. */ static ssize_t -store_hard_offline_page(struct class *class, - struct class_attribute *attr, +store_hard_offline_page(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { int ret; @@ -478,18 +459,18 @@ store_hard_offline_page(struct class *class, return ret ? ret : count; } -static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); -static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); +static DEVICE_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); +static DEVICE_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); static __init int memory_fail_init(void) { int err; - err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_soft_offline_page.attr); + err = device_create_file(memory_subsys.dev_root, + &dev_attr_soft_offline_page); if (!err) - err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_hard_offline_page.attr); + err = device_create_file(memory_subsys.dev_root, + &dev_attr_hard_offline_page); return err; } #else @@ -509,31 +490,23 @@ int __weak arch_get_memory_phys_device(unsigned long start_pfn) return 0; } +/* + * A reference for the returned object is held and the reference for the + * hinted object is released. + */ struct memory_block *find_memory_block_hinted(struct mem_section *section, struct memory_block *hint) { - struct kobject *kobj; - struct sys_device *sysdev; - struct memory_block *mem; - char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1]; int block_id = base_memory_block_id(__section_nr(section)); + struct device *hintdev = hint ? &hint->dev : NULL; + struct device *dev; - kobj = hint ? &hint->sysdev.kobj : NULL; - - /* - * This only works because we know that section == sysdev->id - * slightly redundant with sysdev_register() - */ - sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id); - - kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj); - if (!kobj) + dev = subsys_find_device_by_id(&memory_subsys, block_id, hintdev); + if (hint) + put_device(&hint->dev); + if (!dev) return NULL; - - sysdev = container_of(kobj, struct sys_device, kobj); - mem = container_of(sysdev, struct memory_block, sysdev); - - return mem; + return container_of(dev, struct memory_block, dev); } /* @@ -542,7 +515,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section, * this gets to be a real problem, we can always use a radix * tree or something here. * - * This could be made generic for all sysdev classes. + * This could be made generic for all device subsystems. */ struct memory_block *find_memory_block(struct mem_section *section) { @@ -598,7 +571,7 @@ static int add_memory_section(int nid, struct mem_section *section, mem = find_memory_block(section); if (mem) { mem->section_count++; - kobject_put(&mem->sysdev.kobj); + kobject_put(&mem->dev.kobj); } else ret = init_memory_block(&mem, section, state); @@ -631,7 +604,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section, unregister_memory(mem); kfree(mem); } else - kobject_put(&mem->sysdev.kobj); + kobject_put(&mem->dev.kobj); mutex_unlock(&mem_sysfs_mutex); return 0; @@ -664,8 +637,7 @@ int __init memory_dev_init(void) int err; unsigned long block_sz; - memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops; - ret = sysdev_class_register(&memory_sysdev_class); + ret = subsys_system_register(&memory_subsys, NULL); if (ret) goto out; diff --git a/drivers/base/node.c b/drivers/base/node.c index 5693ecee9a40..44f427a66117 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -1,8 +1,7 @@ /* - * drivers/base/node.c - basic Node class support + * Basic Node interface support */ -#include <linux/sysdev.h> #include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> @@ -19,18 +18,16 @@ #include <linux/swap.h> #include <linux/slab.h> -static struct sysdev_class_attribute *node_state_attrs[]; - -static struct sysdev_class node_class = { +static struct bus_type node_subsys = { .name = "node", - .attrs = node_state_attrs, + .dev_name = "node", }; -static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf) +static ssize_t node_read_cpumap(struct device *dev, int type, char *buf) { struct node *node_dev = to_node(dev); - const struct cpumask *mask = cpumask_of_node(node_dev->sysdev.id); + const struct cpumask *mask = cpumask_of_node(node_dev->dev.id); int len; /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */ @@ -44,23 +41,23 @@ static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf) return len; } -static inline ssize_t node_read_cpumask(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static inline ssize_t node_read_cpumask(struct device *dev, + struct device_attribute *attr, char *buf) { return node_read_cpumap(dev, 0, buf); } -static inline ssize_t node_read_cpulist(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static inline ssize_t node_read_cpulist(struct device *dev, + struct device_attribute *attr, char *buf) { return node_read_cpumap(dev, 1, buf); } -static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL); -static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL); +static DEVICE_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL); +static DEVICE_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL); #define K(x) ((x) << (PAGE_SHIFT - 10)) -static ssize_t node_read_meminfo(struct sys_device * dev, - struct sysdev_attribute *attr, char * buf) +static ssize_t node_read_meminfo(struct device *dev, + struct device_attribute *attr, char *buf) { int n; int nid = dev->id; @@ -157,10 +154,10 @@ static ssize_t node_read_meminfo(struct sys_device * dev, } #undef K -static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); +static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); -static ssize_t node_read_numastat(struct sys_device * dev, - struct sysdev_attribute *attr, char * buf) +static ssize_t node_read_numastat(struct device *dev, + struct device_attribute *attr, char *buf) { return sprintf(buf, "numa_hit %lu\n" @@ -176,10 +173,10 @@ static ssize_t node_read_numastat(struct sys_device * dev, node_page_state(dev->id, NUMA_LOCAL), node_page_state(dev->id, NUMA_OTHER)); } -static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); +static DEVICE_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); -static ssize_t node_read_vmstat(struct sys_device *dev, - struct sysdev_attribute *attr, char *buf) +static ssize_t node_read_vmstat(struct device *dev, + struct device_attribute *attr, char *buf) { int nid = dev->id; int i; @@ -191,10 +188,10 @@ static ssize_t node_read_vmstat(struct sys_device *dev, return n; } -static SYSDEV_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL); +static DEVICE_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL); -static ssize_t node_read_distance(struct sys_device * dev, - struct sysdev_attribute *attr, char * buf) +static ssize_t node_read_distance(struct device *dev, + struct device_attribute *attr, char * buf) { int nid = dev->id; int len = 0; @@ -212,7 +209,7 @@ static ssize_t node_read_distance(struct sys_device * dev, len += sprintf(buf + len, "\n"); return len; } -static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL); +static DEVICE_ATTR(distance, S_IRUGO, node_read_distance, NULL); #ifdef CONFIG_HUGETLBFS /* @@ -230,7 +227,7 @@ static node_registration_func_t __hugetlb_unregister_node; static inline bool hugetlb_register_node(struct node *node) { if (__hugetlb_register_node && - node_state(node->sysdev.id, N_HIGH_MEMORY)) { + node_state(node->dev.id, N_HIGH_MEMORY)) { __hugetlb_register_node(node); return true; } @@ -266,17 +263,17 @@ int register_node(struct node *node, int num, struct node *parent) { int error; - node->sysdev.id = num; - node->sysdev.cls = &node_class; - error = sysdev_register(&node->sysdev); + node->dev.id = num; + node->dev.bus = &node_subsys; + error = device_register(&node->dev); if (!error){ - sysdev_create_file(&node->sysdev, &attr_cpumap); - sysdev_create_file(&node->sysdev, &attr_cpulist); - sysdev_create_file(&node->sysdev, &attr_meminfo); - sysdev_create_file(&node->sysdev, &attr_numastat); - sysdev_create_file(&node->sysdev, &attr_distance); - sysdev_create_file(&node->sysdev, &attr_vmstat); + device_create_file(&node->dev, &dev_attr_cpumap); + device_create_file(&node->dev, &dev_attr_cpulist); + device_create_file(&node->dev, &dev_attr_meminfo); + device_create_file(&node->dev, &dev_attr_numastat); + device_create_file(&node->dev, &dev_attr_distance); + device_create_file(&node->dev, &dev_attr_vmstat); scan_unevictable_register_node(node); @@ -296,17 +293,17 @@ int register_node(struct node *node, int num, struct node *parent) */ void unregister_node(struct node *node) { - sysdev_remove_file(&node->sysdev, &attr_cpumap); - sysdev_remove_file(&node->sysdev, &attr_cpulist); - sysdev_remove_file(&node->sysdev, &attr_meminfo); - sysdev_remove_file(&node->sysdev, &attr_numastat); - sysdev_remove_file(&node->sysdev, &attr_distance); - sysdev_remove_file(&node->sysdev, &attr_vmstat); + device_remove_file(&node->dev, &dev_attr_cpumap); + device_remove_file(&node->dev, &dev_attr_cpulist); + device_remove_file(&node->dev, &dev_attr_meminfo); + device_remove_file(&node->dev, &dev_attr_numastat); + device_remove_file(&node->dev, &dev_attr_distance); + device_remove_file(&node->dev, &dev_attr_vmstat); scan_unevictable_unregister_node(node); hugetlb_unregister_node(node); /* no-op, if memoryless node */ - sysdev_unregister(&node->sysdev); + device_unregister(&node->dev); } struct node node_devices[MAX_NUMNODES]; @@ -317,41 +314,41 @@ struct node node_devices[MAX_NUMNODES]; int register_cpu_under_node(unsigned int cpu, unsigned int nid) { int ret; - struct sys_device *obj; + struct device *obj; if (!node_online(nid)) return 0; - obj = get_cpu_sysdev(cpu); + obj = get_cpu_device(cpu); if (!obj) return 0; - ret = sysfs_create_link(&node_devices[nid].sysdev.kobj, + ret = sysfs_create_link(&node_devices[nid].dev.kobj, &obj->kobj, kobject_name(&obj->kobj)); if (ret) return ret; return sysfs_create_link(&obj->kobj, - &node_devices[nid].sysdev.kobj, - kobject_name(&node_devices[nid].sysdev.kobj)); + &node_devices[nid].dev.kobj, + kobject_name(&node_devices[nid].dev.kobj)); } int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) { - struct sys_device *obj; + struct device *obj; if (!node_online(nid)) return 0; - obj = get_cpu_sysdev(cpu); + obj = get_cpu_device(cpu); if (!obj) return 0; - sysfs_remove_link(&node_devices[nid].sysdev.kobj, + sysfs_remove_link(&node_devices[nid].dev.kobj, kobject_name(&obj->kobj)); sysfs_remove_link(&obj->kobj, - kobject_name(&node_devices[nid].sysdev.kobj)); + kobject_name(&node_devices[nid].dev.kobj)); return 0; } @@ -393,15 +390,15 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) continue; if (page_nid != nid) continue; - ret = sysfs_create_link_nowarn(&node_devices[nid].sysdev.kobj, - &mem_blk->sysdev.kobj, - kobject_name(&mem_blk->sysdev.kobj)); + ret = sysfs_create_link_nowarn(&node_devices[nid].dev.kobj, + &mem_blk->dev.kobj, + kobject_name(&mem_blk->dev.kobj)); if (ret) return ret; - return sysfs_create_link_nowarn(&mem_blk->sysdev.kobj, - &node_devices[nid].sysdev.kobj, - kobject_name(&node_devices[nid].sysdev.kobj)); + return sysfs_create_link_nowarn(&mem_blk->dev.kobj, + &node_devices[nid].dev.kobj, + kobject_name(&node_devices[nid].dev.kobj)); } /* mem section does not span the specified node */ return 0; @@ -434,10 +431,10 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk, continue; if (node_test_and_set(nid, *unlinked_nodes)) continue; - sysfs_remove_link(&node_devices[nid].sysdev.kobj, - kobject_name(&mem_blk->sysdev.kobj)); - sysfs_remove_link(&mem_blk->sysdev.kobj, - kobject_name(&node_devices[nid].sysdev.kobj)); + sysfs_remove_link(&node_devices[nid].dev.kobj, + kobject_name(&mem_blk->dev.kobj)); + sysfs_remove_link(&mem_blk->dev.kobj, + kobject_name(&node_devices[nid].dev.kobj)); } NODEMASK_FREE(unlinked_nodes); return 0; @@ -468,7 +465,7 @@ static int link_mem_sections(int nid) } if (mem_blk) - kobject_put(&mem_blk->sysdev.kobj); + kobject_put(&mem_blk->dev.kobj); return err; } @@ -596,19 +593,19 @@ static ssize_t print_nodes_state(enum node_states state, char *buf) } struct node_attr { - struct sysdev_class_attribute attr; + struct device_attribute attr; enum node_states state; }; -static ssize_t show_node_state(struct sysdev_class *class, - struct sysdev_class_attribute *attr, char *buf) +static ssize_t show_node_state(struct device *dev, + struct device_attribute *attr, char *buf) { struct node_attr *na = container_of(attr, struct node_attr, attr); return print_nodes_state(na->state, buf); } #define _NODE_ATTR(name, state) \ - { _SYSDEV_CLASS_ATTR(name, 0444, show_node_state, NULL), state } + { __ATTR(name, 0444, show_node_state, NULL), state } static struct node_attr node_state_attr[] = { _NODE_ATTR(possible, N_POSSIBLE), @@ -620,17 +617,26 @@ static struct node_attr node_state_attr[] = { #endif }; -static struct sysdev_class_attribute *node_state_attrs[] = { - &node_state_attr[0].attr, - &node_state_attr[1].attr, - &node_state_attr[2].attr, - &node_state_attr[3].attr, +static struct attribute *node_state_attrs[] = { + &node_state_attr[0].attr.attr, + &node_state_attr[1].attr.attr, + &node_state_attr[2].attr.attr, + &node_state_attr[3].attr.attr, #ifdef CONFIG_HIGHMEM - &node_state_attr[4].attr, + &node_state_attr[4].attr.attr, #endif NULL }; +static struct attribute_group memory_root_attr_group = { + .attrs = node_state_attrs, +}; + +static const struct attribute_group *cpu_root_attr_groups[] = { + &memory_root_attr_group, + NULL, +}; + #define NODE_CALLBACK_PRI 2 /* lower than SLAB */ static int __init register_node_type(void) { @@ -639,7 +645,7 @@ static int __init register_node_type(void) BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES); BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES); - ret = sysdev_class_register(&node_class); + ret = subsys_system_register(&node_subsys, cpu_root_attr_groups); if (!ret) { hotplug_memory_notifier(node_memory_callback, NODE_CALLBACK_PRI); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 7a24895543e7..a7c06374062e 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -383,7 +383,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); * Returns &struct platform_device pointer on success, or ERR_PTR() on error. */ struct platform_device *platform_device_register_full( - struct platform_device_info *pdevinfo) + const struct platform_device_info *pdevinfo) { int ret = -ENOMEM; struct platform_device *pdev; diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 9dff77bfe1e3..409f5ce78829 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -126,7 +126,7 @@ void sysdev_class_remove_file(struct sysdev_class *c, } EXPORT_SYMBOL_GPL(sysdev_class_remove_file); -static struct kset *system_kset; +extern struct kset *system_kset; int sysdev_class_register(struct sysdev_class *cls) { @@ -331,14 +331,6 @@ void sysdev_unregister(struct sys_device *sysdev) EXPORT_SYMBOL_GPL(sysdev_register); EXPORT_SYMBOL_GPL(sysdev_unregister); -int __init system_bus_init(void) -{ - system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); - if (!system_kset) - return -ENOMEM; - return 0; -} - #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) ssize_t sysdev_store_ulong(struct sys_device *sysdev, diff --git a/drivers/base/topology.c b/drivers/base/topology.c index f6f37a05a0c3..ae989c57cd5e 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -23,7 +23,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ -#include <linux/sysdev.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/cpu.h> @@ -32,14 +31,14 @@ #include <linux/topology.h> #define define_one_ro_named(_name, _func) \ -static SYSDEV_ATTR(_name, 0444, _func, NULL) + static DEVICE_ATTR(_name, 0444, _func, NULL) #define define_one_ro(_name) \ -static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) + static DEVICE_ATTR(_name, 0444, show_##_name, NULL) #define define_id_show_func(name) \ -static ssize_t show_##name(struct sys_device *dev, \ - struct sysdev_attribute *attr, char *buf) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ unsigned int cpu = dev->id; \ return sprintf(buf, "%d\n", topology_##name(cpu)); \ @@ -65,16 +64,16 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) #ifdef arch_provides_topology_pointers #define define_siblings_show_map(name) \ -static ssize_t show_##name(struct sys_device *dev, \ - struct sysdev_attribute *attr, char *buf) \ +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 sys_device *dev, \ - struct sysdev_attribute *attr, \ +static ssize_t show_##name##_list(struct device *dev, \ + struct device_attribute *attr, \ char *buf) \ { \ unsigned int cpu = dev->id; \ @@ -83,15 +82,15 @@ static ssize_t show_##name##_list(struct sys_device *dev, \ #else #define define_siblings_show_map(name) \ -static ssize_t show_##name(struct sys_device *dev, \ - struct sysdev_attribute *attr, char *buf) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ return show_cpumap(0, topology_##name(dev->id), buf); \ } #define define_siblings_show_list(name) \ -static ssize_t show_##name##_list(struct sys_device *dev, \ - struct sysdev_attribute *attr, \ +static ssize_t show_##name##_list(struct device *dev, \ + struct device_attribute *attr, \ char *buf) \ { \ return show_cpumap(1, topology_##name(dev->id), buf); \ @@ -124,16 +123,16 @@ define_one_ro_named(book_siblings_list, show_book_cpumask_list); #endif static struct attribute *default_attrs[] = { - &attr_physical_package_id.attr, - &attr_core_id.attr, - &attr_thread_siblings.attr, - &attr_thread_siblings_list.attr, - &attr_core_siblings.attr, - &attr_core_siblings_list.attr, + &dev_attr_physical_package_id.attr, + &dev_attr_core_id.attr, + &dev_attr_thread_siblings.attr, + &dev_attr_thread_siblings_list.attr, + &dev_attr_core_siblings.attr, + &dev_attr_core_siblings_list.attr, #ifdef CONFIG_SCHED_BOOK - &attr_book_id.attr, - &attr_book_siblings.attr, - &attr_book_siblings_list.attr, + &dev_attr_book_id.attr, + &dev_attr_book_siblings.attr, + &dev_attr_book_siblings_list.attr, #endif NULL }; @@ -146,16 +145,16 @@ static struct attribute_group topology_attr_group = { /* Add/Remove cpu_topology interface for CPU device */ static int __cpuinit topology_add_dev(unsigned int cpu) { - struct sys_device *sys_dev = get_cpu_sysdev(cpu); + struct device *dev = get_cpu_device(cpu); - return sysfs_create_group(&sys_dev->kobj, &topology_attr_group); + return sysfs_create_group(&dev->kobj, &topology_attr_group); } static void __cpuinit topology_remove_dev(unsigned int cpu) { - struct sys_device *sys_dev = get_cpu_sysdev(cpu); + struct device *dev = get_cpu_device(cpu); - sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); + sysfs_remove_group(&dev->kobj, &topology_attr_group); } static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, |