diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 20:27:48 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 20:27:48 -0700 |
commit | 974668417b74ec5f68df2411f53b3d3812565059 (patch) | |
tree | c76be88bc72bf6b0abe8843f418e4e2518053947 /drivers | |
parent | 9a715cd54347948e74f1a597da22884af287727d (diff) | |
parent | d565ed38d045793b76f022565a50793a3535bdbd (diff) | |
download | linux-974668417b74ec5f68df2411f53b3d3812565059.tar.bz2 |
Merge tag 'driver-core-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH:
"Here is the big driver core update for 4.13-rc1.
The large majority of this is a lot of cleanup of old fields in the
driver core structures and their remaining usages in random drivers.
All of those fixes have been reviewed by the various subsystem
maintainers. There's also some small firmware updates in here, a new
kobject uevent api interface that makes userspace interaction easier,
and a few other minor things.
All of these have been in linux-next for a long while with no reported
issues"
* tag 'driver-core-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (56 commits)
arm: mach-rpc: ecard: fix build error
zram: convert remaining CLASS_ATTR() to CLASS_ATTR_RO()
driver-core: remove struct bus_type.dev_attrs
powerpc: vio_cmo: use dev_groups and not dev_attrs for bus_type
powerpc: vio: use dev_groups and not dev_attrs for bus_type
USB: usbip: convert to use DRIVER_ATTR_RW
s390: drivers: convert to use DRIVER_ATTR_RO/WO
platform: thinkpad_acpi: convert to use DRIVER_ATTR_RO/RW
pcmcia: ds: convert to use DRIVER_ATTR_RO
wireless: ipw2x00: convert to use DRIVER_ATTR_RW
net: ehea: convert to use DRIVER_ATTR_RO
net: caif: convert to use DRIVER_ATTR_RO
TTY: hvc: convert to use DRIVER_ATTR_RW
PCI: pci-driver: convert to use DRIVER_ATTR_WO
IB: nes: convert to use DRIVER_ATTR_RW
HID: hid-core: convert to use DRIVER_ATTR_RO and drv_groups
arm: ecard: fix dev_groups patch typo
tty: serdev: use dev_groups and not dev_attrs for bus_type
sparc: vio: use dev_groups and not dev_attrs for bus_type
hid: intel-ish-hid: use dev_groups and not dev_attrs for bus_type
...
Diffstat (limited to 'drivers')
41 files changed, 748 insertions, 490 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index a56fa2a1e9aa..e0f74ddc22b7 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -105,6 +105,7 @@ static ssize_t driver_override_store(struct device *_dev, return count; } +static DEVICE_ATTR_RW(driver_override); #define amba_attr_func(name,fmt,arg...) \ static ssize_t name##_show(struct device *_dev, \ @@ -112,25 +113,23 @@ static ssize_t name##_show(struct device *_dev, \ { \ struct amba_device *dev = to_amba_device(_dev); \ return sprintf(buf, fmt, arg); \ -} - -#define amba_attr(name,fmt,arg...) \ -amba_attr_func(name,fmt,arg) \ -static DEVICE_ATTR(name, S_IRUGO, name##_show, NULL) +} \ +static DEVICE_ATTR_RO(name) amba_attr_func(id, "%08x\n", dev->periphid); -amba_attr(irq0, "%u\n", dev->irq[0]); -amba_attr(irq1, "%u\n", dev->irq[1]); +amba_attr_func(irq0, "%u\n", dev->irq[0]); +amba_attr_func(irq1, "%u\n", dev->irq[1]); amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n", (unsigned long long)dev->res.start, (unsigned long long)dev->res.end, dev->res.flags); -static struct device_attribute amba_dev_attrs[] = { - __ATTR_RO(id), - __ATTR_RO(resource), - __ATTR_RW(driver_override), - __ATTR_NULL, +static struct attribute *amba_dev_attrs[] = { + &dev_attr_id.attr, + &dev_attr_resource.attr, + &dev_attr_driver_override.attr, + NULL, }; +ATTRIBUTE_GROUPS(amba_dev); #ifdef CONFIG_PM /* @@ -192,7 +191,7 @@ static const struct dev_pm_ops amba_pm = { */ struct bus_type amba_bustype = { .name = "amba", - .dev_attrs = amba_dev_attrs, + .dev_groups = amba_dev_groups, .match = amba_match, .uevent = amba_uevent, .pm = &amba_pm, diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index d718ae4b907a..f046d21de57d 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -339,4 +339,12 @@ config CMA_ALIGNMENT endif +config GENERIC_ARCH_TOPOLOGY + bool + help + Enable support for architectures common topology code: e.g., parsing + CPU capacity information from DT, usage of such information for + appropriate scaling, sysfs interface for changing capacity values at + runtime. + endmenu diff --git a/drivers/base/Makefile b/drivers/base/Makefile index f2816f6ff76a..397e5c344e6a 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_SOC_BUS) += soc.o obj-$(CONFIG_PINCTRL) += pinctrl.o obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o +obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o obj-y += test/ diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c new file mode 100644 index 000000000000..d1c33a85059e --- /dev/null +++ b/drivers/base/arch_topology.c @@ -0,0 +1,243 @@ +/* + * Arch specific cpu topology information + * + * Copyright (C) 2016, ARM Ltd. + * Written by: Juri Lelli, ARM Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Released under the GPLv2 only. + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <linux/acpi.h> +#include <linux/arch_topology.h> +#include <linux/cpu.h> +#include <linux/cpufreq.h> +#include <linux/device.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/sched/topology.h> + +static DEFINE_MUTEX(cpu_scale_mutex); +static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; + +unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu) +{ + return per_cpu(cpu_scale, cpu); +} + +void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity) +{ + per_cpu(cpu_scale, cpu) = capacity; +} + +static ssize_t cpu_capacity_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cpu *cpu = container_of(dev, struct cpu, dev); + + return sprintf(buf, "%lu\n", + topology_get_cpu_scale(NULL, cpu->dev.id)); +} + +static ssize_t cpu_capacity_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct cpu *cpu = container_of(dev, struct cpu, dev); + int this_cpu = cpu->dev.id; + int i; + unsigned long new_capacity; + ssize_t ret; + + if (!count) + return 0; + + ret = kstrtoul(buf, 0, &new_capacity); + if (ret) + return ret; + if (new_capacity > SCHED_CAPACITY_SCALE) + return -EINVAL; + + mutex_lock(&cpu_scale_mutex); + for_each_cpu(i, &cpu_topology[this_cpu].core_sibling) + topology_set_cpu_scale(i, new_capacity); + mutex_unlock(&cpu_scale_mutex); + + return count; +} + +static DEVICE_ATTR_RW(cpu_capacity); + +static int register_cpu_capacity_sysctl(void) +{ + int i; + struct device *cpu; + + for_each_possible_cpu(i) { + cpu = get_cpu_device(i); + if (!cpu) { + pr_err("%s: too early to get CPU%d device!\n", + __func__, i); + continue; + } + device_create_file(cpu, &dev_attr_cpu_capacity); + } + + return 0; +} +subsys_initcall(register_cpu_capacity_sysctl); + +static u32 capacity_scale; +static u32 *raw_capacity; +static bool cap_parsing_failed; + +void topology_normalize_cpu_scale(void) +{ + u64 capacity; + int cpu; + + if (!raw_capacity || cap_parsing_failed) + return; + + pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale); + mutex_lock(&cpu_scale_mutex); + for_each_possible_cpu(cpu) { + pr_debug("cpu_capacity: cpu=%d raw_capacity=%u\n", + cpu, raw_capacity[cpu]); + capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT) + / capacity_scale; + topology_set_cpu_scale(cpu, capacity); + pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n", + cpu, topology_get_cpu_scale(NULL, cpu)); + } + mutex_unlock(&cpu_scale_mutex); +} + +int __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) +{ + int ret = 1; + u32 cpu_capacity; + + if (cap_parsing_failed) + return !ret; + + ret = of_property_read_u32(cpu_node, + "capacity-dmips-mhz", + &cpu_capacity); + if (!ret) { + if (!raw_capacity) { + raw_capacity = kcalloc(num_possible_cpus(), + sizeof(*raw_capacity), + GFP_KERNEL); + if (!raw_capacity) { + pr_err("cpu_capacity: failed to allocate memory for raw capacities\n"); + cap_parsing_failed = true; + return 0; + } + } + capacity_scale = max(cpu_capacity, capacity_scale); + raw_capacity[cpu] = cpu_capacity; + pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n", + cpu_node->full_name, raw_capacity[cpu]); + } else { + if (raw_capacity) { + pr_err("cpu_capacity: missing %s raw capacity\n", + cpu_node->full_name); + pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n"); + } + cap_parsing_failed = true; + kfree(raw_capacity); + } + + return !ret; +} + +#ifdef CONFIG_CPU_FREQ +static cpumask_var_t cpus_to_visit; +static bool cap_parsing_done; +static void parsing_done_workfn(struct work_struct *work); +static DECLARE_WORK(parsing_done_work, parsing_done_workfn); + +static int +init_cpu_capacity_callback(struct notifier_block *nb, + unsigned long val, + void *data) +{ + struct cpufreq_policy *policy = data; + int cpu; + + if (cap_parsing_failed || cap_parsing_done) + return 0; + + switch (val) { + case CPUFREQ_NOTIFY: + pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n", + cpumask_pr_args(policy->related_cpus), + cpumask_pr_args(cpus_to_visit)); + cpumask_andnot(cpus_to_visit, + cpus_to_visit, + policy->related_cpus); + for_each_cpu(cpu, policy->related_cpus) { + raw_capacity[cpu] = topology_get_cpu_scale(NULL, cpu) * + policy->cpuinfo.max_freq / 1000UL; + capacity_scale = max(raw_capacity[cpu], capacity_scale); + } + if (cpumask_empty(cpus_to_visit)) { + topology_normalize_cpu_scale(); + kfree(raw_capacity); + pr_debug("cpu_capacity: parsing done\n"); + cap_parsing_done = true; + schedule_work(&parsing_done_work); + } + } + return 0; +} + +static struct notifier_block init_cpu_capacity_notifier = { + .notifier_call = init_cpu_capacity_callback, +}; + +static int __init register_cpufreq_notifier(void) +{ + /* + * on ACPI-based systems we need to use the default cpu capacity + * until we have the necessary code to parse the cpu capacity, so + * skip registering cpufreq notifier. + */ + if (!acpi_disabled || !raw_capacity) + return -EINVAL; + + if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) { + pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n"); + return -ENOMEM; + } + + cpumask_copy(cpus_to_visit, cpu_possible_mask); + + return cpufreq_register_notifier(&init_cpu_capacity_notifier, + CPUFREQ_POLICY_NOTIFIER); +} +core_initcall(register_cpufreq_notifier); + +static void parsing_done_workfn(struct work_struct *work) +{ + cpufreq_unregister_notifier(&init_cpu_capacity_notifier, + CPUFREQ_POLICY_NOTIFIER); +} + +#else +static int __init free_raw_capacity(void) +{ + kfree(raw_capacity); + + return 0; +} +core_initcall(free_raw_capacity); +#endif diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 6470eb8088f4..e162c9a789ba 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -466,35 +466,6 @@ int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, } EXPORT_SYMBOL_GPL(bus_for_each_drv); -static int device_add_attrs(struct bus_type *bus, struct device *dev) -{ - int error = 0; - int i; - - if (!bus->dev_attrs) - return 0; - - for (i = 0; bus->dev_attrs[i].attr.name; i++) { - error = device_create_file(dev, &bus->dev_attrs[i]); - if (error) { - while (--i >= 0) - device_remove_file(dev, &bus->dev_attrs[i]); - break; - } - } - return error; -} - -static void device_remove_attrs(struct bus_type *bus, struct device *dev) -{ - int i; - - if (bus->dev_attrs) { - for (i = 0; bus->dev_attrs[i].attr.name; i++) - device_remove_file(dev, &bus->dev_attrs[i]); - } -} - /** * bus_add_device - add device to bus * @dev: device being added @@ -510,12 +481,9 @@ int bus_add_device(struct device *dev) if (bus) { pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev)); - error = device_add_attrs(bus, dev); - if (error) - goto out_put; error = device_add_groups(dev, bus->dev_groups); if (error) - goto out_id; + goto out_put; error = sysfs_create_link(&bus->p->devices_kset->kobj, &dev->kobj, dev_name(dev)); if (error) @@ -532,8 +500,6 @@ 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: bus_put(dev->bus); return error; @@ -590,7 +556,6 @@ void bus_remove_device(struct device *dev) sysfs_remove_link(&dev->kobj, "subsystem"); 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); @@ -648,10 +613,7 @@ static void remove_probe_files(struct bus_type *bus) static ssize_t uevent_store(struct device_driver *drv, const char *buf, size_t count) { - enum kobject_action action; - - if (kobject_action_type(buf, count, &action) == 0) - kobject_uevent(&drv->p->kobj, action); + kobject_synth_uevent(&drv->p->kobj, buf, count); return count; } static DRIVER_ATTR_WO(uevent); @@ -868,10 +830,7 @@ static void klist_devices_put(struct klist_node *n) static ssize_t bus_uevent_store(struct bus_type *bus, const char *buf, size_t count) { - enum kobject_action action; - - if (kobject_action_type(buf, count, &action) == 0) - kobject_uevent(&bus->p->subsys.kobj, action); + kobject_synth_uevent(&bus->p->subsys.kobj, buf, count); return count; } static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); diff --git a/drivers/base/class.c b/drivers/base/class.c index a2b2896693d6..52eb8e644acd 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -119,36 +119,6 @@ static void class_put(struct class *cls) kset_put(&cls->p->subsys); } -static int add_class_attrs(struct class *cls) -{ - int i; - int error = 0; - - if (cls->class_attrs) { - for (i = 0; cls->class_attrs[i].attr.name; i++) { - error = class_create_file(cls, &cls->class_attrs[i]); - if (error) - goto error; - } - } -done: - return error; -error: - while (--i >= 0) - class_remove_file(cls, &cls->class_attrs[i]); - goto done; -} - -static void remove_class_attrs(struct class *cls) -{ - int i; - - if (cls->class_attrs) { - for (i = 0; cls->class_attrs[i].attr.name; i++) - class_remove_file(cls, &cls->class_attrs[i]); - } -} - static void klist_class_dev_get(struct klist_node *n) { struct device *dev = container_of(n, struct device, knode_class); @@ -217,8 +187,6 @@ int __class_register(struct class *cls, struct lock_class_key *key) } error = class_add_groups(class_get(cls), cls->class_groups); class_put(cls); - error = add_class_attrs(class_get(cls)); - class_put(cls); return error; } EXPORT_SYMBOL_GPL(__class_register); @@ -226,7 +194,6 @@ EXPORT_SYMBOL_GPL(__class_register); void class_unregister(struct class *cls) { pr_debug("device class '%s': unregistering\n", cls->name); - remove_class_attrs(cls); class_remove_groups(cls, cls->class_groups); kset_unregister(&cls->p->subsys); } diff --git a/drivers/base/core.c b/drivers/base/core.c index c3064ff09af5..8dde934f8d15 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -981,12 +981,9 @@ out: static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - enum kobject_action action; + if (kobject_synth_uevent(&dev->kobj, buf, count)) + dev_err(dev, "uevent: failed to send synthetic uevent\n"); - if (kobject_action_type(buf, count, &action) == 0) - kobject_uevent(&dev->kobj, action); - else - dev_err(dev, "uevent: unknown action-string\n"); return count; } static DEVICE_ATTR_RW(uevent); diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index f3deb6af42ad..9dbef4d1baa4 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c @@ -275,6 +275,24 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, EXPORT_SYMBOL(dma_common_mmap); #ifdef CONFIG_MMU +static struct vm_struct *__dma_common_pages_remap(struct page **pages, + size_t size, unsigned long vm_flags, pgprot_t prot, + const void *caller) +{ + struct vm_struct *area; + + area = get_vm_area_caller(size, vm_flags, caller); + if (!area) + return NULL; + + if (map_vm_area(area, prot, pages)) { + vunmap(area->addr); + return NULL; + } + + return area; +} + /* * remaps an array of PAGE_SIZE pages into another vm_area * Cannot be used in non-sleeping contexts @@ -285,17 +303,12 @@ void *dma_common_pages_remap(struct page **pages, size_t size, { struct vm_struct *area; - area = get_vm_area_caller(size, vm_flags, caller); + area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller); if (!area) return NULL; area->pages = pages; - if (map_vm_area(area, prot, pages)) { - vunmap(area->addr); - return NULL; - } - return area->addr; } @@ -310,7 +323,7 @@ void *dma_common_contiguous_remap(struct page *page, size_t size, { int i; struct page **pages; - void *ptr; + struct vm_struct *area; pages = kmalloc(sizeof(struct page *) << get_order(size), GFP_KERNEL); if (!pages) @@ -319,11 +332,13 @@ void *dma_common_contiguous_remap(struct page *page, size_t size, for (i = 0; i < (size >> PAGE_SHIFT); i++) pages[i] = nth_page(page, i); - ptr = dma_common_pages_remap(pages, size, vm_flags, prot, caller); + area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller); kfree(pages); - return ptr; + if (!area) + return NULL; + return area->addr; } /* diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index ac350c518e0c..b9f907eedbf7 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -260,6 +260,38 @@ static int fw_cache_piggyback_on_request(const char *name); * guarding for corner cases a global lock should be OK */ static DEFINE_MUTEX(fw_lock); +static bool __enable_firmware = false; + +static void enable_firmware(void) +{ + mutex_lock(&fw_lock); + __enable_firmware = true; + mutex_unlock(&fw_lock); +} + +static void disable_firmware(void) +{ + mutex_lock(&fw_lock); + __enable_firmware = false; + mutex_unlock(&fw_lock); +} + +/* + * When disabled only the built-in firmware and the firmware cache will be + * used to look for firmware. + */ +static bool firmware_enabled(void) +{ + bool enabled = false; + + mutex_lock(&fw_lock); + if (__enable_firmware) + enabled = true; + mutex_unlock(&fw_lock); + + return enabled; +} + static struct firmware_cache fw_cache; static struct firmware_buf *__allocate_fw_buf(const char *fw_name, @@ -523,6 +555,44 @@ static int fw_add_devm_name(struct device *dev, const char *name) } #endif +static int assign_firmware_buf(struct firmware *fw, struct device *device, + unsigned int opt_flags) +{ + struct firmware_buf *buf = fw->priv; + + mutex_lock(&fw_lock); + if (!buf->size || fw_state_is_aborted(&buf->fw_st)) { + mutex_unlock(&fw_lock); + return -ENOENT; + } + + /* + * add firmware name into devres list so that we can auto cache + * and uncache firmware for device. + * + * device may has been deleted already, but the problem + * should be fixed in devres or driver core. + */ + /* don't cache firmware handled without uevent */ + if (device && (opt_flags & FW_OPT_UEVENT) && + !(opt_flags & FW_OPT_NOCACHE)) + fw_add_devm_name(device, buf->fw_id); + + /* + * After caching firmware image is started, let it piggyback + * on request firmware. + */ + if (!(opt_flags & FW_OPT_NOCACHE) && + buf->fwc->state == FW_LOADER_START_CACHE) { + if (fw_cache_piggyback_on_request(buf->fw_id)) + kref_get(&buf->ref); + } + + /* pass the pages buffer to driver at the last minute */ + fw_set_page_data(buf, fw); + mutex_unlock(&fw_lock); + return 0; +} /* * user-mode helper code @@ -562,23 +632,19 @@ static void fw_load_abort(struct firmware_priv *fw_priv) static LIST_HEAD(pending_fw_head); -/* reboot notifier for avoid deadlock with usermode_lock */ -static int fw_shutdown_notify(struct notifier_block *unused1, - unsigned long unused2, void *unused3) +static void kill_pending_fw_fallback_reqs(bool only_kill_custom) { + struct firmware_buf *buf; + struct firmware_buf *next; + mutex_lock(&fw_lock); - while (!list_empty(&pending_fw_head)) - __fw_load_abort(list_first_entry(&pending_fw_head, - struct firmware_buf, - pending_list)); + list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) { + if (!buf->need_uevent || !only_kill_custom) + __fw_load_abort(buf); + } mutex_unlock(&fw_lock); - return NOTIFY_DONE; } -static struct notifier_block fw_shutdown_nb = { - .notifier_call = fw_shutdown_notify, -}; - static ssize_t timeout_show(struct class *class, struct class_attribute *attr, char *buf) { @@ -1036,46 +1102,56 @@ err_put_dev: static int fw_load_from_user_helper(struct firmware *firmware, const char *name, struct device *device, - unsigned int opt_flags, long timeout) + unsigned int opt_flags) { struct firmware_priv *fw_priv; + long timeout; + int ret; + + timeout = firmware_loading_timeout(); + if (opt_flags & FW_OPT_NOWAIT) { + timeout = usermodehelper_read_lock_wait(timeout); + if (!timeout) { + dev_dbg(device, "firmware: %s loading timed out\n", + name); + return -EBUSY; + } + } else { + ret = usermodehelper_read_trylock(); + if (WARN_ON(ret)) { + dev_err(device, "firmware: %s will not be loaded\n", + name); + return ret; + } + } fw_priv = fw_create_instance(firmware, name, device, opt_flags); - if (IS_ERR(fw_priv)) - return PTR_ERR(fw_priv); + if (IS_ERR(fw_priv)) { + ret = PTR_ERR(fw_priv); + goto out_unlock; + } fw_priv->buf = firmware->priv; - return _request_firmware_load(fw_priv, opt_flags, timeout); -} + ret = _request_firmware_load(fw_priv, opt_flags, timeout); -#ifdef CONFIG_PM_SLEEP -/* kill pending requests without uevent to avoid blocking suspend */ -static void kill_requests_without_uevent(void) -{ - struct firmware_buf *buf; - struct firmware_buf *next; + if (!ret) + ret = assign_firmware_buf(firmware, device, opt_flags); - mutex_lock(&fw_lock); - list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) { - if (!buf->need_uevent) - __fw_load_abort(buf); - } - mutex_unlock(&fw_lock); +out_unlock: + usermodehelper_read_unlock(); + + return ret; } -#endif #else /* CONFIG_FW_LOADER_USER_HELPER */ static inline int fw_load_from_user_helper(struct firmware *firmware, const char *name, - struct device *device, unsigned int opt_flags, - long timeout) + struct device *device, unsigned int opt_flags) { return -ENOENT; } -#ifdef CONFIG_PM_SLEEP -static inline void kill_requests_without_uevent(void) { } -#endif +static inline void kill_pending_fw_fallback_reqs(bool only_kill_custom) { } #endif /* CONFIG_FW_LOADER_USER_HELPER */ @@ -1124,45 +1200,6 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name, return 1; /* need to load */ } -static int assign_firmware_buf(struct firmware *fw, struct device *device, - unsigned int opt_flags) -{ - struct firmware_buf *buf = fw->priv; - - mutex_lock(&fw_lock); - if (!buf->size || fw_state_is_aborted(&buf->fw_st)) { - mutex_unlock(&fw_lock); - return -ENOENT; - } - - /* - * add firmware name into devres list so that we can auto cache - * and uncache firmware for device. - * - * device may has been deleted already, but the problem - * should be fixed in devres or driver core. - */ - /* don't cache firmware handled without uevent */ - if (device && (opt_flags & FW_OPT_UEVENT) && - !(opt_flags & FW_OPT_NOCACHE)) - fw_add_devm_name(device, buf->fw_id); - - /* - * After caching firmware image is started, let it piggyback - * on request firmware. - */ - if (!(opt_flags & FW_OPT_NOCACHE) && - buf->fwc->state == FW_LOADER_START_CACHE) { - if (fw_cache_piggyback_on_request(buf->fw_id)) - kref_get(&buf->ref); - } - - /* pass the pages buffer to driver at the last minute */ - fw_set_page_data(buf, fw); - mutex_unlock(&fw_lock); - return 0; -} - /* called from request_firmware() and request_firmware_work_func() */ static int _request_firmware(const struct firmware **firmware_p, const char *name, @@ -1170,7 +1207,6 @@ _request_firmware(const struct firmware **firmware_p, const char *name, unsigned int opt_flags) { struct firmware *fw = NULL; - long timeout; int ret; if (!firmware_p) @@ -1185,23 +1221,10 @@ _request_firmware(const struct firmware **firmware_p, const char *name, if (ret <= 0) /* error or already assigned */ goto out; - ret = 0; - timeout = firmware_loading_timeout(); - if (opt_flags & FW_OPT_NOWAIT) { - timeout = usermodehelper_read_lock_wait(timeout); - if (!timeout) { - dev_dbg(device, "firmware: %s loading timed out\n", - name); - ret = -EBUSY; - goto out; - } - } else { - ret = usermodehelper_read_trylock(); - if (WARN_ON(ret)) { - dev_err(device, "firmware: %s will not be loaded\n", - name); - goto out; - } + if (!firmware_enabled()) { + WARN(1, "firmware request while host is not available\n"); + ret = -EHOSTDOWN; + goto out; } ret = fw_get_filesystem_firmware(device, fw->priv); @@ -1213,15 +1236,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name, if (opt_flags & FW_OPT_USERHELPER) { dev_warn(device, "Falling back to user helper\n"); ret = fw_load_from_user_helper(fw, name, device, - opt_flags, timeout); + opt_flags); } - } - - if (!ret) + } else ret = assign_firmware_buf(fw, device, opt_flags); - usermodehelper_read_unlock(); - out: if (ret < 0) { release_firmware(fw); @@ -1717,6 +1736,62 @@ static void device_uncache_fw_images_delay(unsigned long delay) msecs_to_jiffies(delay)); } +/** + * fw_pm_notify - notifier for suspend/resume + * @notify_block: unused + * @mode: mode we are switching to + * @unused: unused + * + * Used to modify the firmware_class state as we move in between states. + * The firmware_class implements a firmware cache to enable device driver + * to fetch firmware upon resume before the root filesystem is ready. We + * disable API calls which do not use the built-in firmware or the firmware + * cache when we know these calls will not work. + * + * The inner logic behind all this is a bit complex so it is worth summarizing + * the kernel's own suspend/resume process with context and focus on how this + * can impact the firmware API. + * + * First a review on how we go to suspend:: + * + * pm_suspend() --> enter_state() --> + * sys_sync() + * suspend_prepare() --> + * __pm_notifier_call_chain(PM_SUSPEND_PREPARE, ...); + * suspend_freeze_processes() --> + * freeze_processes() --> + * __usermodehelper_set_disable_depth(UMH_DISABLED); + * freeze all tasks ... + * freeze_kernel_threads() + * suspend_devices_and_enter() --> + * dpm_suspend_start() --> + * dpm_prepare() + * dpm_suspend() + * suspend_enter() --> + * platform_suspend_prepare() + * dpm_suspend_late() + * freeze_enter() + * syscore_suspend() + * + * When we resume we bail out of a loop from suspend_devices_and_enter() and + * unwind back out to the caller enter_state() where we were before as follows:: + * + * enter_state() --> + * suspend_devices_and_enter() --> (bail from loop) + * dpm_resume_end() --> + * dpm_resume() + * dpm_complete() + * suspend_finish() --> + * suspend_thaw_processes() --> + * thaw_processes() --> + * __usermodehelper_set_disable_depth(UMH_FREEZING); + * thaw_workqueues(); + * thaw all processes ... + * usermodehelper_enable(); + * pm_notifier_call_chain(PM_POST_SUSPEND); + * + * fw_pm_notify() works through pm_notifier_call_chain(). + */ static int fw_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused) { @@ -1724,8 +1799,13 @@ static int fw_pm_notify(struct notifier_block *notify_block, case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: case PM_RESTORE_PREPARE: - kill_requests_without_uevent(); + /* + * kill pending fallback requests with a custom fallback + * to avoid stalling suspend. + */ + kill_pending_fw_fallback_reqs(true); device_cache_fw_images(); + disable_firmware(); break; case PM_POST_SUSPEND: @@ -1738,6 +1818,7 @@ static int fw_pm_notify(struct notifier_block *notify_block, mutex_lock(&fw_lock); fw_cache.state = FW_LOADER_NO_CACHE; mutex_unlock(&fw_lock); + enable_firmware(); device_uncache_fw_images_delay(10 * MSEC_PER_SEC); break; @@ -1783,11 +1864,29 @@ static void __init fw_cache_init(void) #endif } +static int fw_shutdown_notify(struct notifier_block *unused1, + unsigned long unused2, void *unused3) +{ + disable_firmware(); + /* + * Kill all pending fallback requests to avoid both stalling shutdown, + * and avoid a deadlock with the usermode_lock. + */ + kill_pending_fw_fallback_reqs(false); + + return NOTIFY_DONE; +} + +static struct notifier_block fw_shutdown_nb = { + .notifier_call = fw_shutdown_notify, +}; + static int __init firmware_class_init(void) { + enable_firmware(); fw_cache_init(); -#ifdef CONFIG_FW_LOADER_USER_HELPER register_reboot_notifier(&fw_shutdown_nb); +#ifdef CONFIG_FW_LOADER_USER_HELPER return class_register(&firmware_class); #else return 0; @@ -1796,12 +1895,13 @@ static int __init firmware_class_init(void) static void __exit firmware_class_exit(void) { + disable_firmware(); #ifdef CONFIG_PM_SLEEP unregister_syscore_ops(&fw_syscore_ops); unregister_pm_notifier(&fw_cache.pm_notify); #endif -#ifdef CONFIG_FW_LOADER_USER_HELPER unregister_reboot_notifier(&fw_shutdown_nb); +#ifdef CONFIG_FW_LOADER_USER_HELPER class_unregister(&firmware_class); #endif } diff --git a/drivers/base/platform.c b/drivers/base/platform.c index a102152301c8..97332d094fe2 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -866,7 +866,7 @@ static ssize_t driver_override_store(struct device *dev, const char *buf, size_t count) { struct platform_device *pdev = to_platform_device(dev); - char *driver_override, *old = pdev->driver_override, *cp; + char *driver_override, *old, *cp; if (count > PATH_MAX) return -EINVAL; @@ -879,12 +879,15 @@ static ssize_t driver_override_store(struct device *dev, if (cp) *cp = '\0'; + device_lock(dev); + old = pdev->driver_override; if (strlen(driver_override)) { pdev->driver_override = driver_override; } else { kfree(driver_override); pdev->driver_override = NULL; } + device_unlock(dev); kfree(old); @@ -895,8 +898,12 @@ static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr, char *buf) { struct platform_device *pdev = to_platform_device(dev); + ssize_t len; - return sprintf(buf, "%s\n", pdev->driver_override); + device_lock(dev); + len = sprintf(buf, "%s\n", pdev->driver_override); + device_unlock(dev); + return len; } static DEVICE_ATTR_RW(driver_override); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 467beca397a2..6b8b097abbb9 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -349,9 +349,9 @@ static void class_pktcdvd_release(struct class *cls) { kfree(cls); } -static ssize_t class_pktcdvd_show_map(struct class *c, - struct class_attribute *attr, - char *data) + +static ssize_t device_map_show(struct class *c, struct class_attribute *attr, + char *data) { int n = 0; int idx; @@ -369,11 +369,10 @@ static ssize_t class_pktcdvd_show_map(struct class *c, mutex_unlock(&ctl_mutex); return n; } +static CLASS_ATTR_RO(device_map); -static ssize_t class_pktcdvd_store_add(struct class *c, - struct class_attribute *attr, - const char *buf, - size_t count) +static ssize_t add_store(struct class *c, struct class_attribute *attr, + const char *buf, size_t count) { unsigned int major, minor; @@ -391,11 +390,10 @@ static ssize_t class_pktcdvd_store_add(struct class *c, return -EINVAL; } +static CLASS_ATTR_WO(add); -static ssize_t class_pktcdvd_store_remove(struct class *c, - struct class_attribute *attr, - const char *buf, - size_t count) +static ssize_t remove_store(struct class *c, struct class_attribute *attr, + const char *buf, size_t count) { unsigned int major, minor; if (sscanf(buf, "%u:%u", &major, &minor) == 2) { @@ -404,14 +402,15 @@ static ssize_t class_pktcdvd_store_remove(struct class *c, } return -EINVAL; } +static CLASS_ATTR_WO(remove); -static struct class_attribute class_pktcdvd_attrs[] = { - __ATTR(add, 0200, NULL, class_pktcdvd_store_add), - __ATTR(remove, 0200, NULL, class_pktcdvd_store_remove), - __ATTR(device_map, 0444, class_pktcdvd_show_map, NULL), - __ATTR_NULL +static struct attribute *class_pktcdvd_attrs[] = { + &class_attr_add.attr, + &class_attr_remove.attr, + &class_attr_device_map.attr, + NULL, }; - +ATTRIBUTE_GROUPS(class_pktcdvd); static int pkt_sysfs_init(void) { @@ -427,7 +426,7 @@ static int pkt_sysfs_init(void) class_pktcdvd->name = DRIVER_NAME; class_pktcdvd->owner = THIS_MODULE; class_pktcdvd->class_release = class_pktcdvd_release; - class_pktcdvd->class_attrs = class_pktcdvd_attrs; + class_pktcdvd->class_groups = class_pktcdvd_groups; ret = class_register(class_pktcdvd); if (ret) { kfree(class_pktcdvd); diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index debee952dcc1..558e245fab0c 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1272,6 +1272,13 @@ static int zram_remove(struct zram *zram) } /* zram-control sysfs attributes */ + +/* + * NOTE: hot_add attribute is not the usual read-only sysfs attribute. In a + * sense that reading from this file does alter the state of your system -- it + * creates a new un-initialized zram device and returns back this device's + * device_id (or an error code if it fails to create a new device). + */ static ssize_t hot_add_show(struct class *class, struct class_attribute *attr, char *buf) @@ -1286,6 +1293,7 @@ static ssize_t hot_add_show(struct class *class, return ret; return scnprintf(buf, PAGE_SIZE, "%d\n", ret); } +static CLASS_ATTR_RO(hot_add); static ssize_t hot_remove_store(struct class *class, struct class_attribute *attr, @@ -1316,23 +1324,19 @@ static ssize_t hot_remove_store(struct class *class, mutex_unlock(&zram_index_mutex); return ret ? ret : count; } +static CLASS_ATTR_WO(hot_remove); -/* - * NOTE: hot_add attribute is not the usual read-only sysfs attribute. In a - * sense that reading from this file does alter the state of your system -- it - * creates a new un-initialized zram device and returns back this device's - * device_id (or an error code if it fails to create a new device). - */ -static struct class_attribute zram_control_class_attrs[] = { - __ATTR(hot_add, 0400, hot_add_show, NULL), - __ATTR_WO(hot_remove), - __ATTR_NULL, +static struct attribute *zram_control_class_attrs[] = { + &class_attr_hot_add.attr, + &class_attr_hot_remove.attr, + NULL, }; +ATTRIBUTE_GROUPS(zram_control_class); static struct class zram_control_class = { .name = "zram-control", .owner = THIS_MODULE, - .class_attrs = zram_control_class_attrs, + .class_groups = zram_control_class_groups, }; static int zram_remove_cb(int id, void *ptr, void *data) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 4b44dd97c07f..16fe9742597b 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -479,6 +479,7 @@ done: pr_debug("%s: status %d\n", __func__, status); return status ? : len; } +static CLASS_ATTR_WO(export); static ssize_t unexport_store(struct class *class, struct class_attribute *attr, @@ -514,18 +515,20 @@ done: pr_debug("%s: status %d\n", __func__, status); return status ? : len; } +static CLASS_ATTR_WO(unexport); -static struct class_attribute gpio_class_attrs[] = { - __ATTR(export, 0200, NULL, export_store), - __ATTR(unexport, 0200, NULL, unexport_store), - __ATTR_NULL, +static struct attribute *gpio_class_attrs[] = { + &class_attr_export.attr, + &class_attr_unexport.attr, + NULL, }; +ATTRIBUTE_GROUPS(gpio_class); static struct class gpio_class = { .name = "gpio", .owner = THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_groups = gpio_class_groups, }; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 6e040692f1d8..2241e7913c0d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2307,7 +2307,7 @@ struct hid_dynid { * Adds a new dynamic hid device ID to this driver, * and causes the driver to probe for all devices again. */ -static ssize_t store_new_id(struct device_driver *drv, const char *buf, +static ssize_t new_id_store(struct device_driver *drv, const char *buf, size_t count) { struct hid_driver *hdrv = to_hid_driver(drv); @@ -2339,7 +2339,13 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf, return ret ? : count; } -static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); +static DRIVER_ATTR_WO(new_id); + +static struct attribute *hid_drv_attrs[] = { + &driver_attr_new_id.attr, + NULL, +}; +ATTRIBUTE_GROUPS(hid_drv); static void hid_free_dynids(struct hid_driver *hdrv) { @@ -2503,6 +2509,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) static struct bus_type hid_bus_type = { .name = "hid", .dev_groups = hid_dev_groups, + .drv_groups = hid_drv_groups, .match = hid_bus_match, .probe = hid_device_probe, .remove = hid_device_remove, @@ -2942,8 +2949,6 @@ EXPORT_SYMBOL_GPL(hid_destroy_device); int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, const char *mod_name) { - int ret; - hdrv->driver.name = hdrv->name; hdrv->driver.bus = &hid_bus_type; hdrv->driver.owner = owner; @@ -2952,21 +2957,12 @@ int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, INIT_LIST_HEAD(&hdrv->dyn_list); spin_lock_init(&hdrv->dyn_lock); - ret = driver_register(&hdrv->driver); - if (ret) - return ret; - - ret = driver_create_file(&hdrv->driver, &driver_attr_new_id); - if (ret) - driver_unregister(&hdrv->driver); - - return ret; + return driver_register(&hdrv->driver); } EXPORT_SYMBOL_GPL(__hid_register_driver); void hid_unregister_driver(struct hid_driver *hdrv) { - driver_remove_file(&hdrv->driver, &driver_attr_new_id); driver_unregister(&hdrv->driver); hid_free_dynids(hdrv); } diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c index 5f382fedc2ab..f272cdd9bd55 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.c +++ b/drivers/hid/intel-ish-hid/ishtp/bus.c @@ -321,11 +321,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, len = snprintf(buf, PAGE_SIZE, "ishtp:%s\n", dev_name(dev)); return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; } +static DEVICE_ATTR_RO(modalias); -static struct device_attribute ishtp_cl_dev_attrs[] = { - __ATTR_RO(modalias), - __ATTR_NULL, +static struct attribute *ishtp_cl_dev_attrs[] = { + &dev_attr_modalias.attr, + NULL, }; +ATTRIBUTE_GROUPS(ishtp_cl_dev); static int ishtp_cl_uevent(struct device *dev, struct kobj_uevent_env *env) { @@ -346,7 +348,7 @@ static const struct dev_pm_ops ishtp_cl_bus_dev_pm_ops = { static struct bus_type ishtp_cl_bus_type = { .name = "ishtp", - .dev_attrs = ishtp_cl_dev_attrs, + .dev_groups = ishtp_cl_dev_groups, .probe = ishtp_cl_device_probe, .remove = ishtp_cl_device_remove, .pm = &ishtp_cl_bus_dev_pm_ops, diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index 7563eceeaaea..8da567abc0ce 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -139,7 +139,6 @@ static int intel_th_remove(struct device *dev) static struct bus_type intel_th_bus = { .name = "intel_th", - .dev_attrs = NULL, .match = intel_th_match, .probe = intel_th_probe, .remove = intel_th_remove, diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 5b9601014f0c..a30aa6527f7e 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -815,7 +815,7 @@ static struct pci_driver nes_pci_driver = { .remove = nes_remove, }; -static ssize_t nes_show_adapter(struct device_driver *ddp, char *buf) +static ssize_t adapter_show(struct device_driver *ddp, char *buf) { unsigned int devfn = 0xffffffff; unsigned char bus_number = 0xff; @@ -834,7 +834,7 @@ static ssize_t nes_show_adapter(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "%x:%x\n", bus_number, devfn); } -static ssize_t nes_store_adapter(struct device_driver *ddp, +static ssize_t adapter_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -843,7 +843,7 @@ static ssize_t nes_store_adapter(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf) +static ssize_t eeprom_cmd_show(struct device_driver *ddp, char *buf) { u32 eeprom_cmd = 0xdead; u32 i = 0; @@ -859,7 +859,7 @@ static ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_cmd); } -static ssize_t nes_store_ee_cmd(struct device_driver *ddp, +static ssize_t eeprom_cmd_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -880,7 +880,7 @@ static ssize_t nes_store_ee_cmd(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf) +static ssize_t eeprom_data_show(struct device_driver *ddp, char *buf) { u32 eeprom_data = 0xdead; u32 i = 0; @@ -897,7 +897,7 @@ static ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_data); } -static ssize_t nes_store_ee_data(struct device_driver *ddp, +static ssize_t eeprom_data_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -918,7 +918,7 @@ static ssize_t nes_store_ee_data(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf) +static ssize_t flash_cmd_show(struct device_driver *ddp, char *buf) { u32 flash_cmd = 0xdead; u32 i = 0; @@ -935,7 +935,7 @@ static ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_cmd); } -static ssize_t nes_store_flash_cmd(struct device_driver *ddp, +static ssize_t flash_cmd_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -956,7 +956,7 @@ static ssize_t nes_store_flash_cmd(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf) +static ssize_t flash_data_show(struct device_driver *ddp, char *buf) { u32 flash_data = 0xdead; u32 i = 0; @@ -973,7 +973,7 @@ static ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_data); } -static ssize_t nes_store_flash_data(struct device_driver *ddp, +static ssize_t flash_data_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -994,12 +994,12 @@ static ssize_t nes_store_flash_data(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_nonidx_addr(struct device_driver *ddp, char *buf) +static ssize_t nonidx_addr_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_nonidx_addr); } -static ssize_t nes_store_nonidx_addr(struct device_driver *ddp, +static ssize_t nonidx_addr_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -1010,7 +1010,7 @@ static ssize_t nes_store_nonidx_addr(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_nonidx_data(struct device_driver *ddp, char *buf) +static ssize_t nonidx_data_show(struct device_driver *ddp, char *buf) { u32 nonidx_data = 0xdead; u32 i = 0; @@ -1027,7 +1027,7 @@ static ssize_t nes_show_nonidx_data(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "0x%x\n", nonidx_data); } -static ssize_t nes_store_nonidx_data(struct device_driver *ddp, +static ssize_t nonidx_data_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -1048,12 +1048,12 @@ static ssize_t nes_store_nonidx_data(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_idx_addr(struct device_driver *ddp, char *buf) +static ssize_t idx_addr_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_idx_addr); } -static ssize_t nes_store_idx_addr(struct device_driver *ddp, +static ssize_t idx_addr_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -1064,7 +1064,7 @@ static ssize_t nes_store_idx_addr(struct device_driver *ddp, return strnlen(buf, count); } -static ssize_t nes_show_idx_data(struct device_driver *ddp, char *buf) +static ssize_t idx_data_show(struct device_driver *ddp, char *buf) { u32 idx_data = 0xdead; u32 i = 0; @@ -1081,7 +1081,7 @@ static ssize_t nes_show_idx_data(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "0x%x\n", idx_data); } -static ssize_t nes_store_idx_data(struct device_driver *ddp, +static ssize_t idx_data_store(struct device_driver *ddp, const char *buf, size_t count) { char *p = (char *)buf; @@ -1102,11 +1102,7 @@ static ssize_t nes_store_idx_data(struct device_driver *ddp, return strnlen(buf, count); } - -/** - * nes_show_wqm_quanta - */ -static ssize_t nes_show_wqm_quanta(struct device_driver *ddp, char *buf) +static ssize_t wqm_quanta_show(struct device_driver *ddp, char *buf) { u32 wqm_quanta_value = 0xdead; u32 i = 0; @@ -1123,12 +1119,8 @@ static ssize_t nes_show_wqm_quanta(struct device_driver *ddp, char *buf) return snprintf(buf, PAGE_SIZE, "0x%X\n", wqm_quanta_value); } - -/** - * nes_store_wqm_quanta - */ -static ssize_t nes_store_wqm_quanta(struct device_driver *ddp, - const char *buf, size_t count) +static ssize_t wqm_quanta_store(struct device_driver *ddp, const char *buf, + size_t count) { unsigned long wqm_quanta_value; u32 wqm_config1; @@ -1153,26 +1145,16 @@ static ssize_t nes_store_wqm_quanta(struct device_driver *ddp, return strnlen(buf, count); } -static DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR, - nes_show_adapter, nes_store_adapter); -static DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR, - nes_show_ee_cmd, nes_store_ee_cmd); -static DRIVER_ATTR(eeprom_data, S_IRUSR | S_IWUSR, - nes_show_ee_data, nes_store_ee_data); -static DRIVER_ATTR(flash_cmd, S_IRUSR | S_IWUSR, - nes_show_flash_cmd, nes_store_flash_cmd); -static DRIVER_ATTR(flash_data, S_IRUSR | S_IWUSR, - nes_show_flash_data, nes_store_flash_data); -static DRIVER_ATTR(nonidx_addr, S_IRUSR | S_IWUSR, - nes_show_nonidx_addr, nes_store_nonidx_addr); -static DRIVER_ATTR(nonidx_data, S_IRUSR | S_IWUSR, - nes_show_nonidx_data, nes_store_nonidx_data); -static DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR, - nes_show_idx_addr, nes_store_idx_addr); -static DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR, - nes_show_idx_data, nes_store_idx_data); -static DRIVER_ATTR(wqm_quanta, S_IRUSR | S_IWUSR, - nes_show_wqm_quanta, nes_store_wqm_quanta); +static DRIVER_ATTR_RW(adapter); +static DRIVER_ATTR_RW(eeprom_cmd); +static DRIVER_ATTR_RW(eeprom_data); +static DRIVER_ATTR_RW(flash_cmd); +static DRIVER_ATTR_RW(flash_data); +static DRIVER_ATTR_RW(nonidx_addr); +static DRIVER_ATTR_RW(nonidx_data); +static DRIVER_ATTR_RW(idx_addr); +static DRIVER_ATTR_RW(idx_data); +static DRIVER_ATTR_RW(wqm_quanta); static int nes_create_driver_sysfs(struct pci_driver *drv) { diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index f757cef293f8..62f541f968f6 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -133,7 +133,7 @@ static int macio_device_resume(struct device * dev) return 0; } -extern struct device_attribute macio_dev_attrs[]; +extern const struct attribute_group *macio_dev_groups[]; struct bus_type macio_bus_type = { .name = "macio", @@ -144,7 +144,7 @@ struct bus_type macio_bus_type = { .shutdown = macio_device_shutdown, .suspend = macio_device_suspend, .resume = macio_device_resume, - .dev_attrs = macio_dev_attrs, + .dev_groups = macio_dev_groups, }; static int __init macio_bus_driver_init(void) diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 0b1f9c76c68d..2445274f7e4b 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c @@ -10,7 +10,8 @@ field##_show (struct device *dev, struct device_attribute *attr, \ { \ struct macio_dev *mdev = to_macio_device (dev); \ return sprintf (buf, format_string, mdev->ofdev.dev.of_node->field); \ -} +} \ +static DEVICE_ATTR_RO(field); static ssize_t compatible_show (struct device *dev, struct device_attribute *attr, char *buf) @@ -37,6 +38,7 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf) return length; } +static DEVICE_ATTR_RO(compatible); static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, char *buf) @@ -52,15 +54,26 @@ static ssize_t devspec_show(struct device *dev, ofdev = to_platform_device(dev); return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); } +static DEVICE_ATTR_RO(modalias); +static DEVICE_ATTR_RO(devspec); macio_config_of_attr (name, "%s\n"); macio_config_of_attr (type, "%s\n"); -struct device_attribute macio_dev_attrs[] = { - __ATTR_RO(name), - __ATTR_RO(type), - __ATTR_RO(compatible), - __ATTR_RO(modalias), - __ATTR_RO(devspec), - __ATTR_NULL +static struct attribute *macio_dev_attrs[] = { + &dev_attr_name.attr, + &dev_attr_type.attr, + &dev_attr_compatible.attr, + &dev_attr_modalias.attr, + &dev_attr_devspec.attr, + NULL, +}; + +static const struct attribute_group macio_dev_group = { + .attrs = macio_dev_attrs, +}; + +const struct attribute_group *macio_dev_groups[] = { + &macio_dev_group, + NULL, }; diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 93e5d251a9e4..d854521962ef 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -104,23 +104,25 @@ DEFINE_MUTEX(ubi_devices_mutex); static DEFINE_SPINLOCK(ubi_devices_lock); /* "Show" method for files in '/<sysfs>/class/ubi/' */ -static ssize_t ubi_version_show(struct class *class, - struct class_attribute *attr, char *buf) +/* UBI version attribute ('/<sysfs>/class/ubi/version') */ +static ssize_t version_show(struct class *class, struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", UBI_VERSION); } +static CLASS_ATTR_RO(version); -/* UBI version attribute ('/<sysfs>/class/ubi/version') */ -static struct class_attribute ubi_class_attrs[] = { - __ATTR(version, S_IRUGO, ubi_version_show, NULL), - __ATTR_NULL +static struct attribute *ubi_class_attrs[] = { + &class_attr_version.attr, + NULL, }; +ATTRIBUTE_GROUPS(ubi_class); /* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ struct class ubi_class = { .name = UBI_NAME_STR, .owner = THIS_MODULE, - .class_attrs = ubi_class_attrs, + .class_groups = ubi_class_groups, }; static ssize_t dev_attribute_show(struct device *dev, diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index fc21afe852b9..cb0dcc99fb4f 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -289,44 +289,44 @@ static LIST_HEAD(cfspi_list); static spinlock_t cfspi_list_lock; /* SPI uplink head alignment. */ -static ssize_t show_up_head_align(struct device_driver *driver, char *buf) +static ssize_t up_head_align_show(struct device_driver *driver, char *buf) { return sprintf(buf, "%d\n", spi_up_head_align); } -static DRIVER_ATTR(up_head_align, S_IRUSR, show_up_head_align, NULL); +static DRIVER_ATTR_RO(up_head_align); /* SPI uplink tail alignment. */ -static ssize_t show_up_tail_align(struct device_driver *driver, char *buf) +static ssize_t up_tail_align_show(struct device_driver *driver, char *buf) { return sprintf(buf, "%d\n", spi_up_tail_align); } -static DRIVER_ATTR(up_tail_align, S_IRUSR, show_up_tail_align, NULL); +static DRIVER_ATTR_RO(up_tail_align); /* SPI downlink head alignment. */ -static ssize_t show_down_head_align(struct device_driver *driver, char *buf) +static ssize_t down_head_align_show(struct device_driver *driver, char *buf) { return sprintf(buf, "%d\n", spi_down_head_align); } -static DRIVER_ATTR(down_head_align, S_IRUSR, show_down_head_align, NULL); +static DRIVER_ATTR_RO(down_head_align); /* SPI downlink tail alignment. */ -static ssize_t show_down_tail_align(struct device_driver *driver, char *buf) +static ssize_t down_tail_align_show(struct device_driver *driver, char *buf) { return sprintf(buf, "%d\n", spi_down_tail_align); } -static DRIVER_ATTR(down_tail_align, S_IRUSR, show_down_tail_align, NULL); +static DRIVER_ATTR_RO(down_tail_align); /* SPI frame alignment. */ -static ssize_t show_frame_align(struct device_driver *driver, char *buf) +static ssize_t frame_align_show(struct device_driver *driver, char *buf) { return sprintf(buf, "%d\n", spi_frm_align); } -static DRIVER_ATTR(frame_align, S_IRUSR, show_frame_align, NULL); +static DRIVER_ATTR_RO(frame_align); int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) { diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 1e53d7a82675..b9d310f20bcc 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -3553,14 +3553,12 @@ static int check_module_parm(void) return ret; } -static ssize_t ehea_show_capabilities(struct device_driver *drv, - char *buf) +static ssize_t capabilities_show(struct device_driver *drv, char *buf) { return sprintf(buf, "%d", EHEA_CAPABILITIES); } -static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH, - ehea_show_capabilities, NULL); +static DRIVER_ATTR_RO(capabilities); static int __init ehea_module_init(void) { diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index f922859acf40..aaaca4d08e2b 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -4160,12 +4160,12 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL); #ifdef CONFIG_IPW2100_DEBUG -static ssize_t show_debug_level(struct device_driver *d, char *buf) +static ssize_t debug_level_show(struct device_driver *d, char *buf) { return sprintf(buf, "0x%08X\n", ipw2100_debug_level); } -static ssize_t store_debug_level(struct device_driver *d, +static ssize_t debug_level_store(struct device_driver *d, const char *buf, size_t count) { u32 val; @@ -4179,9 +4179,7 @@ static ssize_t store_debug_level(struct device_driver *d, return strnlen(buf, count); } - -static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, - store_debug_level); +static DRIVER_ATTR_RW(debug_level); #endif /* CONFIG_IPW2100_DEBUG */ static ssize_t show_fatal_error(struct device *d, diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index bbc579b647b6..5b79e2ec3a16 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -1195,12 +1195,12 @@ static void ipw_led_shutdown(struct ipw_priv *priv) * * See the level definitions in ipw for details. */ -static ssize_t show_debug_level(struct device_driver *d, char *buf) +static ssize_t debug_level_show(struct device_driver *d, char *buf) { return sprintf(buf, "0x%08X\n", ipw_debug_level); } -static ssize_t store_debug_level(struct device_driver *d, const char *buf, +static ssize_t debug_level_store(struct device_driver *d, const char *buf, size_t count) { char *p = (char *)buf; @@ -1221,9 +1221,7 @@ static ssize_t store_debug_level(struct device_driver *d, const char *buf, return strnlen(buf, count); } - -static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, - show_debug_level, store_debug_level); +static DRIVER_ATTR_RW(debug_level); static inline u32 ipw_get_event_log_len(struct ipw_priv *priv) { diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index fe6be6382505..00e10bf7f6a2 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -96,7 +96,7 @@ static void pci_free_dynids(struct pci_driver *drv) * * Allow PCI IDs to be added to an existing driver via sysfs. */ -static ssize_t store_new_id(struct device_driver *driver, const char *buf, +static ssize_t new_id_store(struct device_driver *driver, const char *buf, size_t count) { struct pci_driver *pdrv = to_pci_driver(driver); @@ -154,7 +154,7 @@ static ssize_t store_new_id(struct device_driver *driver, const char *buf, return retval; return count; } -static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); +static DRIVER_ATTR_WO(new_id); /** * store_remove_id - remove a PCI device ID from this driver @@ -164,7 +164,7 @@ static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); * * Removes a dynamic pci device ID to this driver. */ -static ssize_t store_remove_id(struct device_driver *driver, const char *buf, +static ssize_t remove_id_store(struct device_driver *driver, const char *buf, size_t count) { struct pci_dynid *dynid, *n; @@ -198,7 +198,7 @@ static ssize_t store_remove_id(struct device_driver *driver, const char *buf, return retval; } -static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); +static DRIVER_ATTR_WO(remove_id); static struct attribute *pci_drv_attrs[] = { &driver_attr_new_id.attr, diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 69b5e811ea2b..a9258f641cee 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -95,7 +95,7 @@ struct pcmcia_dynid { * and causes the driver to probe for all devices again. */ static ssize_t -pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count) +new_id_store(struct device_driver *driver, const char *buf, size_t count) { struct pcmcia_dynid *dynid; struct pcmcia_driver *pdrv = to_pcmcia_drv(driver); @@ -133,7 +133,7 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count) return retval; return count; } -static DRIVER_ATTR(new_id, S_IWUSR, NULL, pcmcia_store_new_id); +static DRIVER_ATTR_WO(new_id); static void pcmcia_free_dynids(struct pcmcia_driver *drv) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 7b6cb0c69b02..f6861b551178 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -1438,25 +1438,20 @@ static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf) */ /* interface_version --------------------------------------------------- */ -static ssize_t tpacpi_driver_interface_version_show( - struct device_driver *drv, - char *buf) +static ssize_t interface_version_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION); } - -static DRIVER_ATTR(interface_version, S_IRUGO, - tpacpi_driver_interface_version_show, NULL); +static DRIVER_ATTR_RO(interface_version); /* debug_level --------------------------------------------------------- */ -static ssize_t tpacpi_driver_debug_show(struct device_driver *drv, - char *buf) +static ssize_t debug_level_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level); } -static ssize_t tpacpi_driver_debug_store(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t debug_level_store(struct device_driver *drv, const char *buf, + size_t count) { unsigned long t; @@ -1467,34 +1462,28 @@ static ssize_t tpacpi_driver_debug_store(struct device_driver *drv, return count; } - -static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, - tpacpi_driver_debug_show, tpacpi_driver_debug_store); +static DRIVER_ATTR_RW(debug_level); /* version ------------------------------------------------------------- */ -static ssize_t tpacpi_driver_version_show(struct device_driver *drv, - char *buf) +static ssize_t version_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "%s v%s\n", TPACPI_DESC, TPACPI_VERSION); } - -static DRIVER_ATTR(version, S_IRUGO, - tpacpi_driver_version_show, NULL); +static DRIVER_ATTR_RO(version); /* --------------------------------------------------------------------- */ #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES /* wlsw_emulstate ------------------------------------------------------ */ -static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv, - char *buf) +static ssize_t wlsw_emulstate_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wlsw_emulstate); } -static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t wlsw_emulstate_store(struct device_driver *drv, const char *buf, + size_t count) { unsigned long t; @@ -1508,22 +1497,16 @@ static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv, return count; } - -static DRIVER_ATTR(wlsw_emulstate, S_IWUSR | S_IRUGO, - tpacpi_driver_wlsw_emulstate_show, - tpacpi_driver_wlsw_emulstate_store); +static DRIVER_ATTR_RW(wlsw_emulstate); /* bluetooth_emulstate ------------------------------------------------- */ -static ssize_t tpacpi_driver_bluetooth_emulstate_show( - struct device_driver *drv, - char *buf) +static ssize_t bluetooth_emulstate_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_bluetooth_emulstate); } -static ssize_t tpacpi_driver_bluetooth_emulstate_store( - struct device_driver *drv, - const char *buf, size_t count) +static ssize_t bluetooth_emulstate_store(struct device_driver *drv, + const char *buf, size_t count) { unsigned long t; @@ -1534,22 +1517,16 @@ static ssize_t tpacpi_driver_bluetooth_emulstate_store( return count; } - -static DRIVER_ATTR(bluetooth_emulstate, S_IWUSR | S_IRUGO, - tpacpi_driver_bluetooth_emulstate_show, - tpacpi_driver_bluetooth_emulstate_store); +static DRIVER_ATTR_RW(bluetooth_emulstate); /* wwan_emulstate ------------------------------------------------- */ -static ssize_t tpacpi_driver_wwan_emulstate_show( - struct device_driver *drv, - char *buf) +static ssize_t wwan_emulstate_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wwan_emulstate); } -static ssize_t tpacpi_driver_wwan_emulstate_store( - struct device_driver *drv, - const char *buf, size_t count) +static ssize_t wwan_emulstate_store(struct device_driver *drv, const char *buf, + size_t count) { unsigned long t; @@ -1560,22 +1537,16 @@ static ssize_t tpacpi_driver_wwan_emulstate_store( return count; } - -static DRIVER_ATTR(wwan_emulstate, S_IWUSR | S_IRUGO, - tpacpi_driver_wwan_emulstate_show, - tpacpi_driver_wwan_emulstate_store); +static DRIVER_ATTR_RW(wwan_emulstate); /* uwb_emulstate ------------------------------------------------- */ -static ssize_t tpacpi_driver_uwb_emulstate_show( - struct device_driver *drv, - char *buf) +static ssize_t uwb_emulstate_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_uwb_emulstate); } -static ssize_t tpacpi_driver_uwb_emulstate_store( - struct device_driver *drv, - const char *buf, size_t count) +static ssize_t uwb_emulstate_store(struct device_driver *drv, const char *buf, + size_t count) { unsigned long t; @@ -1586,10 +1557,7 @@ static ssize_t tpacpi_driver_uwb_emulstate_store( return count; } - -static DRIVER_ATTR(uwb_emulstate, S_IWUSR | S_IRUGO, - tpacpi_driver_uwb_emulstate_show, - tpacpi_driver_uwb_emulstate_store); +static DRIVER_ATTR_RW(uwb_emulstate); #endif /* --------------------------------------------------------------------- */ @@ -8606,14 +8574,13 @@ static ssize_t fan_fan2_input_show(struct device *dev, static DEVICE_ATTR(fan2_input, S_IRUGO, fan_fan2_input_show, NULL); /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ -static ssize_t fan_fan_watchdog_show(struct device_driver *drv, - char *buf) +static ssize_t fan_watchdog_show(struct device_driver *drv, char *buf) { return snprintf(buf, PAGE_SIZE, "%u\n", fan_watchdog_maxinterval); } -static ssize_t fan_fan_watchdog_store(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t fan_watchdog_store(struct device_driver *drv, const char *buf, + size_t count) { unsigned long t; @@ -8630,9 +8597,7 @@ static ssize_t fan_fan_watchdog_store(struct device_driver *drv, return count; } - -static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO, - fan_fan_watchdog_show, fan_fan_watchdog_store); +static DRIVER_ATTR_RW(fan_watchdog); /* --------------------------------------------------------------------- */ static struct attribute *fan_attributes[] = { diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 600f5f9f7431..ad3d2a9df287 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -330,7 +330,8 @@ field##_show(struct device *dev, \ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ \ return sprintf(buf, format_string, rpdev->path); \ -} +} \ +static DEVICE_ATTR_RO(field); /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ rpmsg_show_attr(name, id.name, "%s\n"); @@ -345,15 +346,17 @@ static ssize_t modalias_show(struct device *dev, return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); } - -static struct device_attribute rpmsg_dev_attrs[] = { - __ATTR_RO(name), - __ATTR_RO(modalias), - __ATTR_RO(dst), - __ATTR_RO(src), - __ATTR_RO(announce), - __ATTR_NULL +static DEVICE_ATTR_RO(modalias); + +static struct attribute *rpmsg_dev_attrs[] = { + &dev_attr_name.attr, + &dev_attr_modalias.attr, + &dev_attr_dst.attr, + &dev_attr_src.attr, + &dev_attr_announce.attr, + NULL, }; +ATTRIBUTE_GROUPS(rpmsg_dev); /* rpmsg devices and drivers are matched using the service name */ static inline int rpmsg_id_match(const struct rpmsg_device *rpdev, @@ -455,7 +458,7 @@ static int rpmsg_dev_remove(struct device *dev) static struct bus_type rpmsg_bus = { .name = "rpmsg", .match = rpmsg_dev_match, - .dev_attrs = rpmsg_dev_attrs, + .dev_groups = rpmsg_dev_groups, .uevent = rpmsg_uevent, .probe = rpmsg_dev_probe, .remove = rpmsg_dev_remove, diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 9c471ea1b99c..6111c1fa2d1e 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -1096,26 +1096,26 @@ static const struct dev_pm_ops sclp_pm_ops = { .restore = sclp_restore, }; -static ssize_t sclp_show_console_pages(struct device_driver *dev, char *buf) +static ssize_t con_pages_show(struct device_driver *dev, char *buf) { return sprintf(buf, "%i\n", sclp_console_pages); } -static DRIVER_ATTR(con_pages, S_IRUSR, sclp_show_console_pages, NULL); +static DRIVER_ATTR_RO(con_pages); -static ssize_t sclp_show_con_drop(struct device_driver *dev, char *buf) +static ssize_t con_drop_show(struct device_driver *dev, char *buf) { return sprintf(buf, "%i\n", sclp_console_drop); } -static DRIVER_ATTR(con_drop, S_IRUSR, sclp_show_con_drop, NULL); +static DRIVER_ATTR_RO(con_drop); -static ssize_t sclp_show_console_full(struct device_driver *dev, char *buf) +static ssize_t con_full_show(struct device_driver *dev, char *buf) { return sprintf(buf, "%lu\n", sclp_console_full); } -static DRIVER_ATTR(con_full, S_IRUSR, sclp_show_console_full, NULL); +static DRIVER_ATTR_RO(con_full); static struct attribute *sclp_drv_attrs[] = { &driver_attr_con_pages.attr, diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 57974a1e0e03..b19020b9efff 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -641,10 +641,8 @@ static ssize_t vmlogrdr_recording_store(struct device * dev, static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store); -static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver, - char *buf) +static ssize_t recording_status_show(struct device_driver *driver, char *buf) { - static const char cp_command[] = "QUERY RECORDING "; int len; @@ -652,8 +650,7 @@ static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver, len = strlen(buf); return len; } -static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show, - NULL); +static DRIVER_ATTR_RO(recording_status); static struct attribute *vmlogrdr_drv_attrs[] = { &driver_attr_recording_status.attr, NULL, diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 198842ce6876..b1fa38a6733f 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1770,15 +1770,15 @@ static struct ccwgroup_driver ctcm_group_driver = { .restore = ctcm_pm_resume, }; -static ssize_t ctcm_driver_group_store(struct device_driver *ddrv, - const char *buf, size_t count) +static ssize_t group_store(struct device_driver *ddrv, const char *buf, + size_t count) { int err; err = ccwgroup_create_dev(ctcm_root_dev, &ctcm_group_driver, 2, buf); return err ? err : count; } -static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); +static DRIVER_ATTR_WO(group); static struct attribute *ctcm_drv_attrs[] = { &driver_attr_group.attr, diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 211b31d9f157..589dba69db17 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -2411,14 +2411,14 @@ static struct ccwgroup_driver lcs_group_driver = { .restore = lcs_restore, }; -static ssize_t lcs_driver_group_store(struct device_driver *ddrv, - const char *buf, size_t count) +static ssize_t group_store(struct device_driver *ddrv, const char *buf, + size_t count) { int err; err = ccwgroup_create_dev(lcs_root_dev, &lcs_group_driver, 2, buf); return err ? err : count; } -static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); +static DRIVER_ATTR_WO(group); static struct attribute *lcs_drv_attrs[] = { &driver_attr_group.attr, diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index fa732bd86729..f1f6eb112531 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -2020,8 +2020,8 @@ out_netdev: return NULL; } -static ssize_t conn_write(struct device_driver *drv, - const char *buf, size_t count) +static ssize_t connection_store(struct device_driver *drv, const char *buf, + size_t count) { char username[9]; char userdata[17]; @@ -2082,11 +2082,10 @@ out_free_ndev: netiucv_free_netdevice(dev); return rc; } +static DRIVER_ATTR_WO(connection); -static DRIVER_ATTR(connection, 0200, NULL, conn_write); - -static ssize_t remove_write (struct device_driver *drv, - const char *buf, size_t count) +static ssize_t remove_store(struct device_driver *drv, const char *buf, + size_t count) { struct iucv_connection *cp; struct net_device *ndev; @@ -2132,8 +2131,7 @@ static ssize_t remove_write (struct device_driver *drv, IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n"); return -EINVAL; } - -static DRIVER_ATTR(remove, 0200, NULL, remove_write); +static DRIVER_ATTR_WO(remove); static struct attribute * netiucv_drv_attrs[] = { &driver_attr_connection.attr, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index fc6d85f2b38d..462b82eb17a9 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5800,8 +5800,8 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = { .restore = qeth_core_restore, }; -static ssize_t qeth_core_driver_group_store(struct device_driver *ddrv, - const char *buf, size_t count) +static ssize_t group_store(struct device_driver *ddrv, const char *buf, + size_t count) { int err; @@ -5810,7 +5810,7 @@ static ssize_t qeth_core_driver_group_store(struct device_driver *ddrv, return err ? err : count; } -static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store); +static DRIVER_ATTR_WO(group); static struct attribute *qeth_drv_attrs[] = { &driver_attr_group.attr, diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index abf6026645dd..659ab483d716 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -3934,10 +3934,6 @@ static const struct target_core_fabric_ops ibmvscsis_ops = { static void ibmvscsis_dev_release(struct device *dev) {}; -static struct class_attribute ibmvscsis_class_attrs[] = { - __ATTR_NULL, -}; - static struct device_attribute dev_attr_system_id = __ATTR(system_id, S_IRUGO, system_id_show, NULL); @@ -3957,7 +3953,6 @@ ATTRIBUTE_GROUPS(ibmvscsis_dev); static struct class ibmvscsis_class = { .name = "ibmvscsis", .dev_release = ibmvscsis_dev_release, - .class_attrs = ibmvscsis_class_attrs, .dev_groups = ibmvscsis_dev_groups, }; diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c index 55434330867b..774f31b564f8 100644 --- a/drivers/sh/superhyway/superhyway-sysfs.c +++ b/drivers/sh/superhyway/superhyway-sysfs.c @@ -19,7 +19,8 @@ static ssize_t name##_show(struct device *dev, struct device_attribute *attr, ch { \ struct superhyway_device *s = to_superhyway_device(dev); \ return sprintf(buf, fmt, s->field); \ -} +} \ +static DEVICE_ATTR_RO(name); /* VCR flags */ superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags); @@ -32,14 +33,22 @@ superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb); /* Misc */ superhyway_ro_attr(resource, "0x%08lx\n", resource[0].start); -struct device_attribute superhyway_dev_attrs[] = { - __ATTR_RO(perr_flags), - __ATTR_RO(merr_flags), - __ATTR_RO(mod_vers), - __ATTR_RO(mod_id), - __ATTR_RO(bot_mb), - __ATTR_RO(top_mb), - __ATTR_RO(resource), - __ATTR_NULL, +static struct attribute *superhyway_dev_attrs[] = { + &dev_attr_perr_flags.attr, + &dev_attr_merr_flags.attr, + &dev_attr_mod_vers.attr, + &dev_attr_mod_id.attr, + &dev_attr_bot_mb.attr, + &dev_attr_top_mb.attr, + &dev_attr_resource.attr, + NULL, }; +static const struct attribute_group superhyway_dev_group = { + .attrs = superhyway_dev_attrs, +}; + +const struct attribute_group *superhyway_dev_groups[] = { + &superhyway_dev_group, + NULL, +}; diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index bb1fb7712134..348836b90605 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -209,7 +209,7 @@ struct bus_type superhyway_bus_type = { .name = "superhyway", .match = superhyway_bus_match, #ifdef CONFIG_SYSFS - .dev_attrs = superhyway_dev_attrs, + .dev_groups = superhyway_dev_groups, #endif .probe = superhyway_device_probe, .remove = superhyway_device_remove, diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 423e28ec27fb..79cc5beea2da 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -484,13 +484,13 @@ static struct attribute_group hvcs_attr_group = { .attrs = hvcs_attrs, }; -static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf) +static ssize_t rescan_show(struct device_driver *ddp, char *buf) { /* A 1 means it is updating, a 0 means it is done updating */ return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status); } -static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf, +static ssize_t rescan_store(struct device_driver *ddp, const char * buf, size_t count) { if ((simple_strtol(buf, NULL, 0) != 1) @@ -505,8 +505,7 @@ static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf, return count; } -static DRIVER_ATTR(rescan, - S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store); +static DRIVER_ATTR_RW(rescan); static void hvcs_kick(void) { diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index f71b47334149..ae1aaa0075d1 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -262,11 +262,13 @@ static ssize_t modalias_show(struct device *dev, { return of_device_modalias(dev, buf, PAGE_SIZE); } +DEVICE_ATTR_RO(modalias); -static struct device_attribute serdev_device_attrs[] = { - __ATTR_RO(modalias), - __ATTR_NULL +static struct attribute *serdev_device_attrs[] = { + &dev_attr_modalias.attr, + NULL, }; +ATTRIBUTE_GROUPS(serdev_device); static struct bus_type serdev_bus_type = { .name = "serial", @@ -274,7 +276,7 @@ static struct bus_type serdev_bus_type = { .probe = serdev_drv_probe, .remove = serdev_drv_remove, .uevent = serdev_uevent, - .dev_attrs = serdev_device_attrs, + .dev_groups = serdev_device_groups, }; /** diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c index af10f7b131a4..660180a5d5c4 100644 --- a/drivers/usb/usbip/stub_main.c +++ b/drivers/usb/usbip/stub_main.c @@ -134,7 +134,7 @@ out: return ret; } -static ssize_t show_match_busid(struct device_driver *drv, char *buf) +static ssize_t match_busid_show(struct device_driver *drv, char *buf) { int i; char *out = buf; @@ -149,7 +149,7 @@ static ssize_t show_match_busid(struct device_driver *drv, char *buf) return out - buf; } -static ssize_t store_match_busid(struct device_driver *dev, const char *buf, +static ssize_t match_busid_store(struct device_driver *dev, const char *buf, size_t count) { int len; @@ -181,8 +181,7 @@ static ssize_t store_match_busid(struct device_driver *dev, const char *buf, return -EINVAL; } -static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid, - store_match_busid); +static DRIVER_ATTR_RW(match_busid); static ssize_t rebind_store(struct device_driver *dev, const char *buf, size_t count) diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index 776bcb3c2140..ff2d4240b24a 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c @@ -94,17 +94,18 @@ ssize_t beacon_timeout_ms_store(struct class *class, beacon_timeout_ms = bt; return size; } +static CLASS_ATTR_RW(beacon_timeout_ms); -static struct class_attribute uwb_class_attrs[] = { - __ATTR(beacon_timeout_ms, S_IWUSR | S_IRUGO, - beacon_timeout_ms_show, beacon_timeout_ms_store), - __ATTR_NULL, +static struct attribute *uwb_class_attrs[] = { + &class_attr_beacon_timeout_ms.attr, + NULL, }; +ATTRIBUTE_GROUPS(uwb_class); /** Device model classes */ struct class uwb_rc_class = { .name = "uwb_rc", - .class_attrs = uwb_class_attrs, + .class_groups = uwb_class_groups, }; |