diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-05-03 11:28:58 +0800 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2010-05-03 11:28:58 +0800 |
commit | df2071bd081408318d659cd14a9cf6ff23d874c9 (patch) | |
tree | b31291b5fd4b9f84c629833afbfaa8d431857475 /drivers/base | |
parent | 97e3d94aac1c3e95bd04d1b186479a4df3663ab8 (diff) | |
parent | be1066bbcd443a65df312fdecea7e4959adedb45 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Kconfig | 51 | ||||
-rw-r--r-- | drivers/base/attribute_container.c | 1 | ||||
-rw-r--r-- | drivers/base/bus.c | 27 | ||||
-rw-r--r-- | drivers/base/class.c | 18 | ||||
-rw-r--r-- | drivers/base/core.c | 52 | ||||
-rw-r--r-- | drivers/base/cpu.c | 106 | ||||
-rw-r--r-- | drivers/base/dd.c | 38 | ||||
-rw-r--r-- | drivers/base/devres.c | 1 | ||||
-rw-r--r-- | drivers/base/devtmpfs.c | 14 | ||||
-rw-r--r-- | drivers/base/dma-coherent.c | 1 | ||||
-rw-r--r-- | drivers/base/dma-mapping.c | 1 | ||||
-rw-r--r-- | drivers/base/driver.c | 1 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 14 | ||||
-rw-r--r-- | drivers/base/memory.c | 38 | ||||
-rw-r--r-- | drivers/base/module.c | 1 | ||||
-rw-r--r-- | drivers/base/node.c | 89 | ||||
-rw-r--r-- | drivers/base/platform.c | 109 | ||||
-rw-r--r-- | drivers/base/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/base/power/generic_ops.c | 233 | ||||
-rw-r--r-- | drivers/base/power/main.c | 51 | ||||
-rw-r--r-- | drivers/base/sys.c | 18 |
21 files changed, 628 insertions, 237 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index ee377270beb..fd52c48ee76 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -3,35 +3,50 @@ menu "Generic Driver Options" config UEVENT_HELPER_PATH string "path to uevent helper" depends on HOTPLUG - default "/sbin/hotplug" + default "" help Path to uevent helper program forked by the kernel for every uevent. + Before the switch to the netlink-based uevent source, this was + used to hook hotplug scripts into kernel device events. It + usually pointed to a shell script at /sbin/hotplug. + This should not be used today, because usual systems create + many events at bootup or device discovery in a very short time + frame. One forked process per event can create so many processes + that it creates a high system load, or on smaller systems + it is known to create out-of-memory situations during bootup. config DEVTMPFS - bool "Create a kernel maintained /dev tmpfs (EXPERIMENTAL)" + bool "Maintain a devtmpfs filesystem to mount at /dev" depends on HOTPLUG && SHMEM && TMPFS help - This creates a tmpfs filesystem, and mounts it at bootup - and mounts it at /dev. The kernel driver core creates device - nodes for all registered devices in that filesystem. All device - nodes are owned by root and have the default mode of 0600. - Userspace can add and delete the nodes as needed. This is - intended to simplify bootup, and make it possible to delay - the initial coldplug at bootup done by udev in userspace. - It should also provide a simpler way for rescue systems - to bring up a kernel with dynamic major/minor numbers. - Meaningful symlinks, permissions and device ownership must - still be handled by userspace. - If unsure, say N here. + This creates a tmpfs filesystem instance early at bootup. + In this filesystem, the kernel driver core maintains device + nodes with their default names and permissions for all + registered devices with an assigned major/minor number. + Userspace can modify the filesystem content as needed, add + symlinks, and apply needed permissions. + It provides a fully functional /dev directory, where usually + udev runs on top, managing permissions and adding meaningful + symlinks. + In very limited environments, it may provide a sufficient + functional /dev without any further help. It also allows simple + rescue systems, and reliably handles dynamic major/minor numbers. config DEVTMPFS_MOUNT - bool "Automount devtmpfs at /dev" + bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs" depends on DEVTMPFS help - This will mount devtmpfs at /dev if the kernel mounts the root - filesystem. It will not affect initramfs based mounting. - If unsure, say N here. + This will instruct the kernel to automatically mount the + devtmpfs filesystem at /dev, directly after the kernel has + mounted the root filesystem. The behavior can be overridden + with the commandline parameter: devtmpfs.mount=0|1. + This option does not affect initramfs based booting, here + the devtmpfs filesystem always needs to be mounted manually + after the roots is mounted. + With this option enabled, it allows to bring up a system in + rescue mode with init=/bin/sh, even when the /dev directory + on the rootfs is completely empty. config STANDALONE bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index b9cda053d3c..8fc200b2e2c 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -328,6 +328,7 @@ attribute_container_add_attrs(struct device *classdev) return sysfs_create_group(&classdev->kobj, cont->grp); for (i = 0; attrs[i]; i++) { + sysfs_attr_init(&attrs[i]->attr); error = device_create_file(classdev, attrs[i]); if (error) return error; diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c0c5a43d9fb..12eec3f633b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -13,6 +13,7 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/errno.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/string.h> #include "base.h" @@ -70,7 +71,7 @@ static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops driver_sysfs_ops = { +static const struct sysfs_ops driver_sysfs_ops = { .show = drv_attr_show, .store = drv_attr_store, }; @@ -115,7 +116,7 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops bus_sysfs_ops = { +static const struct sysfs_ops bus_sysfs_ops = { .show = bus_attr_show, .store = bus_attr_store, }; @@ -154,7 +155,7 @@ static int bus_uevent_filter(struct kset *kset, struct kobject *kobj) return 0; } -static struct kset_uevent_ops bus_uevent_ops = { +static const struct kset_uevent_ops bus_uevent_ops = { .filter = bus_uevent_filter, }; @@ -173,10 +174,10 @@ static ssize_t driver_unbind(struct device_driver *drv, dev = bus_find_device_by_name(bus, NULL, buf); if (dev && dev->driver == drv) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); + device_lock(dev->parent); device_release_driver(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); err = count; } put_device(dev); @@ -200,12 +201,12 @@ static ssize_t driver_bind(struct device_driver *drv, dev = bus_find_device_by_name(bus, NULL, buf); if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); - down(&dev->sem); + device_lock(dev->parent); + device_lock(dev); err = driver_probe_device(drv, dev); - up(&dev->sem); + device_unlock(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); if (err > 0) { /* success */ @@ -744,10 +745,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, if (!dev->driver) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); + device_lock(dev->parent); ret = device_attach(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); } return ret < 0 ? ret : 0; } @@ -779,10 +780,10 @@ int device_reprobe(struct device *dev) { if (dev->driver) { if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); + device_lock(dev->parent); device_release_driver(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); } return bus_rescan_devices_helper(dev, NULL); } diff --git a/drivers/base/class.c b/drivers/base/class.c index 6e2c3b064f5..9c6a0d6408e 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -31,7 +31,7 @@ static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, ssize_t ret = -EIO; if (class_attr->show) - ret = class_attr->show(cp->class, buf); + ret = class_attr->show(cp->class, class_attr, buf); return ret; } @@ -43,7 +43,7 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, ssize_t ret = -EIO; if (class_attr->store) - ret = class_attr->store(cp->class, buf, count); + ret = class_attr->store(cp->class, class_attr, buf, count); return ret; } @@ -63,7 +63,7 @@ static void class_release(struct kobject *kobj) kfree(cp); } -static struct sysfs_ops class_sysfs_ops = { +static const struct sysfs_ops class_sysfs_ops = { .show = class_attr_show, .store = class_attr_store, }; @@ -219,6 +219,8 @@ static void class_create_release(struct class *cls) * This is used to create a struct class pointer that can then be used * in calls to device_create(). * + * Returns &struct class pointer on success, or ERR_PTR() on error. + * * Note, the pointer created here is to be destroyed when finished by * making a call to class_destroy(). */ @@ -490,6 +492,16 @@ void class_interface_unregister(struct class_interface *class_intf) class_put(parent); } +ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr, + char *buf) +{ + struct class_attribute_string *cs; + cs = container_of(attr, struct class_attribute_string, attr); + return snprintf(buf, PAGE_SIZE, "%s\n", cs->str); +} + +EXPORT_SYMBOL_GPL(show_class_attr_string); + struct class_compat { struct kobject *kobj; }; diff --git a/drivers/base/core.c b/drivers/base/core.c index 28202577042..b56a0ba31d4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -100,7 +100,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, return ret; } -static struct sysfs_ops dev_sysfs_ops = { +static const struct sysfs_ops dev_sysfs_ops = { .show = dev_attr_show, .store = dev_attr_store, }; @@ -252,7 +252,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, return retval; } -static struct kset_uevent_ops device_uevent_ops = { +static const struct kset_uevent_ops device_uevent_ops = { .filter = dev_uevent_filter, .name = dev_uevent_name, .uevent = dev_uevent, @@ -306,15 +306,10 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, { enum kobject_action action; - if (kobject_action_type(buf, count, &action) == 0) { + if (kobject_action_type(buf, count, &action) == 0) kobject_uevent(&dev->kobj, action); - goto out; - } - - dev_err(dev, "uevent: unsupported action-string; this will " - "be ignored in a future kernel version\n"); - kobject_uevent(&dev->kobj, KOBJ_ADD); -out: + else + dev_err(dev, "uevent: unknown action-string\n"); return count; } @@ -607,6 +602,7 @@ static struct kobject *get_device_parent(struct device *dev, int retval; if (dev->class) { + static DEFINE_MUTEX(gdp_mutex); struct kobject *kobj = NULL; struct kobject *parent_kobj; struct kobject *k; @@ -623,6 +619,8 @@ static struct kobject *get_device_parent(struct device *dev, else parent_kobj = &parent->kobj; + mutex_lock(&gdp_mutex); + /* find our class-directory at the parent and reference it */ spin_lock(&dev->class->p->class_dirs.list_lock); list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) @@ -631,20 +629,26 @@ static struct kobject *get_device_parent(struct device *dev, break; } spin_unlock(&dev->class->p->class_dirs.list_lock); - if (kobj) + if (kobj) { + mutex_unlock(&gdp_mutex); return kobj; + } /* or create a new class-directory at the parent device */ k = kobject_create(); - if (!k) + if (!k) { + mutex_unlock(&gdp_mutex); return NULL; + } k->kset = &dev->class->p->class_dirs; retval = kobject_add(k, parent_kobj, "%s", dev->class->name); if (retval < 0) { + mutex_unlock(&gdp_mutex); kobject_put(k); return NULL; } /* do not emit an uevent for this simple "glue" directory */ + mutex_unlock(&gdp_mutex); return k; } @@ -1341,6 +1345,8 @@ static void root_device_release(struct device *dev) * 'module' symlink which points to the @owner directory * in sysfs. * + * Returns &struct device pointer on success, or ERR_PTR() on error. + * * Note: You probably want to use root_device_register(). */ struct device *__root_device_register(const char *name, struct module *owner) @@ -1428,6 +1434,8 @@ static void device_create_release(struct device *dev) * Any further sysfs files that might be required can be created using this * pointer. * + * Returns &struct device pointer on success, or ERR_PTR() on error. + * * Note: the struct class passed to this function must have previously * been created with a call to class_create(). */ @@ -1488,6 +1496,8 @@ EXPORT_SYMBOL_GPL(device_create_vargs); * Any further sysfs files that might be required can be created using this * pointer. * + * Returns &struct device pointer on success, or ERR_PTR() on error. + * * Note: the struct class passed to this function must have previously * been created with a call to class_create(). */ @@ -1574,22 +1584,16 @@ int device_rename(struct device *dev, char *new_name) if (old_class_name) { new_class_name = make_class_name(dev->class->name, &dev->kobj); if (new_class_name) { - error = sysfs_create_link_nowarn(&dev->parent->kobj, - &dev->kobj, - new_class_name); - if (error) - goto out; - sysfs_remove_link(&dev->parent->kobj, old_class_name); + error = sysfs_rename_link(&dev->parent->kobj, + &dev->kobj, + old_class_name, + new_class_name); } } #else if (dev->class) { - error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj, - &dev->kobj, dev_name(dev)); - if (error) - goto out; - sysfs_remove_link(&dev->class->p->class_subsys.kobj, - old_device_name); + error = sysfs_rename_link(&dev->class->p->class_subsys.kobj, + &dev->kobj, old_device_name, new_name); } #endif diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 958bd1540c3..f35719aab3c 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -10,11 +10,15 @@ #include <linux/topology.h> #include <linux/device.h> #include <linux/node.h> +#include <linux/gfp.h> #include "base.h" +static struct sysdev_class_attribute *cpu_sysdev_class_attrs[]; + struct sysdev_class cpu_sysdev_class = { .name = "cpu", + .attrs = cpu_sysdev_class_attrs, }; EXPORT_SYMBOL(cpu_sysdev_class); @@ -76,34 +80,24 @@ void unregister_cpu(struct cpu *cpu) } #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE -static ssize_t cpu_probe_store(struct class *class, const char *buf, +static ssize_t cpu_probe_store(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) { return arch_cpu_probe(buf, count); } -static ssize_t cpu_release_store(struct class *class, const char *buf, +static ssize_t cpu_release_store(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) { return arch_cpu_release(buf, count); } -static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); -static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); - -int __init cpu_probe_release_init(void) -{ - int rc; - - rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, - &class_attr_probe.attr); - if (!rc) - rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, - &class_attr_release.attr); - - return rc; -} -device_initcall(cpu_probe_release_init); +static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); +static SYSDEV_CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ #else /* ... !CONFIG_HOTPLUG_CPU */ @@ -141,31 +135,39 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); /* * Print cpu online, possible, present, and system maps */ -static ssize_t print_cpus_map(char *buf, const struct cpumask *map) + +struct cpu_attr { + struct sysdev_class_attribute attr; + const struct cpumask *const * const map; +}; + +static ssize_t show_cpus_attr(struct sysdev_class *class, + struct sysdev_class_attribute *attr, + char *buf) { - int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map); + struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); + int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map)); buf[n++] = '\n'; buf[n] = '\0'; return n; } -#define print_cpus_func(type) \ -static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \ -{ \ - return print_cpus_map(buf, cpu_##type##_mask); \ -} \ -static struct sysdev_class_attribute attr_##type##_map = \ - _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) +#define _CPU_ATTR(name, map) \ + { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } -print_cpus_func(online); -print_cpus_func(possible); -print_cpus_func(present); +/* Keep in sync with cpu_sysdev_class_attrs */ +static struct cpu_attr cpu_attrs[] = { + _CPU_ATTR(online, &cpu_online_mask), + _CPU_ATTR(possible, &cpu_possible_mask), + _CPU_ATTR(present, &cpu_present_mask), +}; /* * Print values for NR_CPUS and offlined cpus */ -static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf) +static ssize_t print_cpus_kernel_max(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); return n; @@ -175,7 +177,8 @@ static SYSDEV_CLASS_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, char *buf) +static ssize_t print_cpus_offline(struct sysdev_class *class, + struct sysdev_class_attribute *attr, char *buf) { int n = 0, len = PAGE_SIZE-2; cpumask_var_t offline; @@ -204,29 +207,6 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf) } static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); -static struct sysdev_class_attribute *cpu_state_attr[] = { - &attr_online_map, - &attr_possible_map, - &attr_present_map, - &attr_kernel_max, - &attr_offline, -}; - -static int cpu_states_init(void) -{ - int i; - int err = 0; - - for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) { - int ret; - ret = sysdev_class_create_file(&cpu_sysdev_class, - cpu_state_attr[i]); - if (!err) - err = ret; - } - return err; -} - /* * register_cpu - Setup a sysfs device for a CPU. * @cpu - cpu->hotpluggable field set to 1 will generate a control file in @@ -272,9 +252,6 @@ int __init cpu_dev_init(void) int err; err = sysdev_class_register(&cpu_sysdev_class); - if (!err) - err = cpu_states_init(); - #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) if (!err) err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); @@ -282,3 +259,16 @@ int __init cpu_dev_init(void) 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/dd.c b/drivers/base/dd.c index ee95c76bfd3..c89291f8a16 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -85,7 +85,7 @@ static void driver_sysfs_remove(struct device *dev) * for before calling this. (It is ok to call with no other effort * from a driver's probe() method.) * - * This function must be called with @dev->sem held. + * This function must be called with the device lock held. */ int device_bind_driver(struct device *dev) { @@ -190,8 +190,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe); * This function returns -ENODEV if the device is not registered, * 1 if the device is bound successfully and 0 otherwise. * - * This function must be called with @dev->sem held. When called for a - * USB interface, @dev->parent->sem must be held as well. + * This function must be called with @dev lock held. When called for a + * USB interface, @dev->parent lock must be held as well. */ int driver_probe_device(struct device_driver *drv, struct device *dev) { @@ -233,13 +233,13 @@ static int __device_attach(struct device_driver *drv, void *data) * 0 if no matching driver was found; * -ENODEV if the device is not registered. * - * When called for a USB interface, @dev->parent->sem must be held. + * When called for a USB interface, @dev->parent lock must be held. */ int device_attach(struct device *dev) { int ret = 0; - down(&dev->sem); + device_lock(dev); if (dev->driver) { ret = device_bind_driver(dev); if (ret == 0) @@ -253,7 +253,7 @@ int device_attach(struct device *dev) ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); pm_runtime_put_sync(dev); } - up(&dev->sem); + device_unlock(dev); return ret; } EXPORT_SYMBOL_GPL(device_attach); @@ -276,13 +276,13 @@ static int __driver_attach(struct device *dev, void *data) return 0; if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); - down(&dev->sem); + device_lock(dev->parent); + device_lock(dev); if (!dev->driver) driver_probe_device(drv, dev); - up(&dev->sem); + device_unlock(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); return 0; } @@ -303,8 +303,8 @@ int driver_attach(struct device_driver *drv) EXPORT_SYMBOL_GPL(driver_attach); /* - * __device_release_driver() must be called with @dev->sem held. - * When called for a USB interface, @dev->parent->sem must be held as well. + * __device_release_driver() must be called with @dev lock held. + * When called for a USB interface, @dev->parent lock must be held as well. */ static void __device_release_driver(struct device *dev) { @@ -343,7 +343,7 @@ static void __device_release_driver(struct device *dev) * @dev: device. * * Manually detach device from driver. - * When called for a USB interface, @dev->parent->sem must be held. + * When called for a USB interface, @dev->parent lock must be held. */ void device_release_driver(struct device *dev) { @@ -352,9 +352,9 @@ void device_release_driver(struct device *dev) * within their ->remove callback for the same device, they * will deadlock right here. */ - down(&dev->sem); + device_lock(dev); __device_release_driver(dev); - up(&dev->sem); + device_unlock(dev); } EXPORT_SYMBOL_GPL(device_release_driver); @@ -381,13 +381,13 @@ void driver_detach(struct device_driver *drv) spin_unlock(&drv->p->klist_devices.k_lock); if (dev->parent) /* Needed for USB */ - down(&dev->parent->sem); - down(&dev->sem); + device_lock(dev->parent); + device_lock(dev); if (dev->driver == drv) __device_release_driver(dev); - up(&dev->sem); + device_unlock(dev); if (dev->parent) - up(&dev->parent->sem); + device_unlock(dev->parent); put_device(dev); } } diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 05dd307e8f0..cf7a0c78805 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -9,6 +9,7 @@ #include <linux/device.h> #include <linux/module.h> +#include <linux/slab.h> #include "base.h" diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 42ae452b36b..057cf11326b 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -23,6 +23,7 @@ #include <linux/cred.h> #include <linux/sched.h> #include <linux/init_task.h> +#include <linux/slab.h> static struct vfsmount *dev_mnt; @@ -301,6 +302,19 @@ int devtmpfs_delete_node(struct device *dev) if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { + struct iattr newattrs; + /* + * before unlinking this node, reset permissions + * of possible references like hardlinks + */ + newattrs.ia_uid = 0; + newattrs.ia_gid = 0; + newattrs.ia_mode = stat.mode & ~0777; + newattrs.ia_valid = + ATTR_UID|ATTR_GID|ATTR_MODE; + mutex_lock(&dentry->d_inode->i_mutex); + notify_change(dentry, &newattrs); + mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 962a3b574f2..d4d8ce53886 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -2,6 +2,7 @@ * Coherent per-device memory handling. * Borrowed from i386 */ +#include <linux/slab.h> #include <linux/kernel.h> #include <linux/dma-mapping.h> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index ca9186f70a6..763d59c1eb6 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c @@ -8,6 +8,7 @@ */ #include <linux/dma-mapping.h> +#include <linux/gfp.h> /* * Managed DMA API diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 90c9fff09ea..b631f7c5945 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -13,6 +13,7 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/errno.h> +#include <linux/slab.h> #include <linux/string.h> #include "base.h" diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index a95024166b6..985da11174e 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -19,7 +19,7 @@ #include <linux/kthread.h> #include <linux/highmem.h> #include <linux/firmware.h> -#include "base.h" +#include <linux/slab.h> #define to_dev(obj) container_of(obj, struct device, kobj) @@ -69,7 +69,9 @@ fw_load_abort(struct firmware_priv *fw_priv) } static ssize_t -firmware_timeout_show(struct class *class, char *buf) +firmware_timeout_show(struct class *class, + struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", loading_timeout); } @@ -77,6 +79,7 @@ firmware_timeout_show(struct class *class, char *buf) /** * firmware_timeout_store - set number of seconds to wait for firmware * @class: device class pointer + * @attr: device attribute pointer * @buf: buffer to scan for timeout value * @count: number of bytes in @buf * @@ -87,7 +90,9 @@ firmware_timeout_show(struct class *class, char *buf) * Note: zero means 'wait forever'. **/ static ssize_t -firmware_timeout_store(struct class *class, const char *buf, size_t count) +firmware_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) @@ -439,6 +444,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, fw_priv = dev_get_drvdata(f_dev); fw_priv->fw = fw; + sysfs_bin_attr_init(&fw_priv->attr_data); retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); if (retval) { dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__); @@ -610,7 +616,7 @@ request_firmware_work_func(void *arg) } /** - * request_firmware_nowait: asynchronous version of request_firmware + * request_firmware_nowait - asynchronous version of request_firmware * @module: module requesting the firmware * @uevent: sends uevent to copy the firmware image if this flag * is non-zero else the firmware copy must be done manually. diff --git a/drivers/base/memory.c b/drivers/base/memory.c index bd025059711..933442f4032 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -22,6 +22,7 @@ #include <linux/mm.h> #include <linux/mutex.h> #include <linux/stat.h> +#include <linux/slab.h> #include <asm/atomic.h> #include <asm/uaccess.h> @@ -44,7 +45,7 @@ static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uev return retval; } -static struct kset_uevent_ops memory_uevent_ops = { +static const struct kset_uevent_ops memory_uevent_ops = { .name = memory_uevent_name, .uevent = memory_uevent, }; @@ -309,17 +310,18 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); * Block size attribute stuff */ static ssize_t -print_block_size(struct class *class, char *buf) +print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr, + char *buf) { - return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); + return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } -static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_block_size_bytes.attr); + &attr_block_size_bytes.attr); } /* @@ -330,7 +332,8 @@ static int block_size_init(void) */ < |