Merge tag 'driver-core-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core patches from Greg KH:
 "Here's the big driver core pull request for 3.12-rc1.

  Lots of tiny changes here fixing up the way sysfs attributes are
  created, to try to make drivers simpler, and fix a whole class race
  conditions with creations of device attributes after the device was
  announced to userspace.

  All the various pieces are acked by the different subsystem
  maintainers"

* tag 'driver-core-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (119 commits)
  firmware loader: fix pending_fw_head list corruption
  drivers/base/memory.c: introduce help macro to_memory_block
  dynamic debug: line queries failing due to uninitialized local variable
  sysfs: sysfs_create_groups returns a value.
  debugfs: provide debugfs_create_x64() when disabled
  rbd: convert bus code to use bus_groups
  firmware: dcdbas: use binary attribute groups
  sysfs: add sysfs_create/remove_groups for when SYSFS is not enabled
  driver core: add #include <linux/sysfs.h> to core files.
  HID: convert bus code to use dev_groups
  Input: serio: convert bus code to use drv_groups
  Input: gameport: convert bus code to use drv_groups
  driver core: firmware: use __ATTR_RW()
  driver core: core: use DEVICE_ATTR_RO
  driver core: bus: use DRIVER_ATTR_WO()
  driver core: create write-only attribute macros for devices and drivers
  sysfs: create __ATTR_WO()
  driver-core: platform: convert bus code to use dev_groups
  workqueue: convert bus code to use dev_groups
  MEI: convert bus code to use dev_groups
  ...
diff --git a/Documentation/ko_KR/HOWTO b/Documentation/ko_KR/HOWTO
index 2f48f205..680e646 100644
--- a/Documentation/ko_KR/HOWTO
+++ b/Documentation/ko_KR/HOWTO
@@ -182,8 +182,8 @@
 프로젝트를 봐야 한다.
     http://kernelnewbies.org
 그곳은 거의 모든 종류의 기본적인 커널 개발 질문들(질문하기 전에 먼저
-아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할수있는 도움이
-될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할수 있는 IRC 채널도
+아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할 수 있는 도움이
+될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할 수 있는 IRC 채널도
 가지고 있으며 리눅스 커널 개발을 배우는 데 유용한 문서들을 보유하고 있다.
 
 웹사이트는 코드구성, 서브시스템들, 그리고 현재 프로젝트들
@@ -245,7 +245,7 @@
     것을 기억해라. 왜냐하면 변경이 자체내에서만 발생하고 추가된 코드가
     드라이버 외부의 다른 부분에는 영향을 주지 않으므로 그런 변경은
     회귀(역자주: 이전에는 존재하지 않았지만 새로운 기능추가나 변경으로 인해
-		생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이
+    생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이
     배포된 이후에 git를 사용하여 패치들을 Linus에게 보낼수 있지만 패치들은
     공식적인 메일링 리스트로 보내서 검토를 받을 필요가 있다.
   - 새로운 -rc는 Linus가 현재 git tree가 테스트 하기에 충분히 안정된 상태에
@@ -455,7 +455,7 @@
  - 의견
  - 변경을 위한 요구
  - 당위성을 위한 요구
- - 고요
+ - 침묵
 
 기억하라. 이것들은 여러분의 패치가 커널로 들어가기 위한 과정이다. 여러분의
 패치들은 비판과 다른 의견을 받을 수 있고 그것들을 기술적인 레벨로 평가하고
@@ -472,7 +472,7 @@
 가능한한 가장 좋은 기술적인 해답을 찾고 있는 커뮤니티에서는 항상
 어떤 패치가 얼마나 좋은지에 관하여 다른 의견들이 있을 수 있다. 여러분은
 협조적이어야 하고 기꺼이 여러분의 생각을 커널 내에 맞추어야 한다. 아니면
-적어도 여러분의 것이 가치있다는 것을 중명하여야 한다. 잘못된 것도 여러분이
+적어도 여러분의 것이 가치있다는 것을 증명하여야 한다. 잘못된 것도 여러분이
 올바른 방향의 해결책으로 이끌어갈 의지가 있다면 받아들여질 것이라는 점을
 기억하라.
 
@@ -488,21 +488,21 @@
 커널 커뮤니티는 가장 전통적인 회사의 개발 환경과는 다르다. 여기에 여러분들의
 문제를 피하기 위한 목록이 있다.
   여러분들이 제안한 변경들에 관하여 말할 때 좋은 것들 :
-    - "이것은 여러 문제들을 해겹합니다."
-    - "이것은 2000 라인의 코드를 제거합니다."
+    - "이것은 여러 문제들을 해결합니다."
+    - "이것은 2000 라인의 코드를 줄입니다."
     - "이것은 내가 말하려는 것에 관해 설명하는 패치입니다."
-    - "나는 5개의 다른 아키텍쳐에서 그것을 테스트했슴으로..."
-    - "여기에 일련의 작은 패치들이 있슴음로..."
-    - "이것은 일반적인 머신에서 성능을 향상시킴으로..."
+    - "나는 5개의 다른 아키텍쳐에서 그것을 테스트 했으므로..."
+    - "여기에 일련의 작은 패치들이 있으므로..."
+    - "이것은 일반적인 머신에서 성능을 향상함으로..."
 
   여러분들이 말할 때 피해야 할 좋지 않은 것들 :
-    - "우리를 그것을 AIT/ptx/Solaris에서 이러한 방법으로 했다. 그러므로 그것은 좋은 것임에 틀립없다..."
+    - "우리는 그것을 AIX/ptx/Solaris에서 이러한 방법으로 했다. 그러므로 그것은 좋은 것임에 틀림없다..."
     - "나는 20년동안 이것을 해왔다. 그러므로..."
     - "이것은 돈을 벌기위해 나의 회사가 필요로 하는 것이다."
     - "이것은 우리의 엔터프라이즈 상품 라인을 위한 것이다."
     - "여기에 나의 생각을 말하고 있는 1000 페이지 설계 문서가 있다."
     - "나는 6달동안 이것을 했으니..."
-    - "여기에 5000라인 짜리 패치가 있으니..."
+    - "여기에 5000 라인 짜리 패치가 있으니..."
     - "나는 현재 뒤죽박죽인 것을 재작성했다. 그리고 여기에..."
     - "나는 마감시한을 가지고 있으므로 이 패치는 지금 적용될 필요가 있다."
 
@@ -574,6 +574,7 @@
 또한 완성되지 않았고 "나중에 수정될 것이다." 와 같은 것들을 포함하는
 패치들은 받아들여지지 않을 것이라는 점을 유념하라.
 
+
 변경을 정당화해라
 -----------------
 
diff --git a/Documentation/ko_KR/stable_api_nonsense.txt b/Documentation/ko_KR/stable_api_nonsense.txt
index 8f2b0e1..51f85ad 100644
--- a/Documentation/ko_KR/stable_api_nonsense.txt
+++ b/Documentation/ko_KR/stable_api_nonsense.txt
@@ -106,12 +106,12 @@
 ---------------------------------
 
 리눅스 커널 드라이버를 계속해서 메인 커널 트리에 반영하지 않고
-유지보수하려고 하는 사름들과 이 문제를 논의하게 되면 훨씬 더
+유지보수하려고 하는 사람들과 이 문제를 논의하게 되면 훨씬 더
 "논란의 여지가 많은" 주제가 될 것이다.
 
 리눅스 커널 개발은 끊임없이 빠른 속도로 이루어지고 있으며 결코
 느슨해진 적이 없다. 커널 개발자들이 현재 인터페이스들에서 버그를
-발견하거나 무엇인가 할수 있는 더 좋은 방법을 찾게 되었다고 하자.
+발견하거나 무엇인가 할 수 있는 더 좋은 방법을 찾게 되었다고 하자.
 그들이 발견한 것을 실행한다면 아마도 더 잘 동작하도록 현재 인터페이스들을
 수정하게 될 것이다. 그들이 그런 일을 하게되면 함수 이름들은 변하게 되고,
 구조체들은 늘어나거나 줄어들게 되고, 함수 파라미터들은 재작업될 것이다.
@@ -174,7 +174,7 @@
 동작하는 것을 보장한다.
 
 메인 커널 트리에 여러분의 드라이버를 반영하면 얻게 되는 장점들은 다음과 같다.
-   - 관리의 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다.
+   - 관리에 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다.
    - 다른 개발자들이 여러분의 드라이버에 기능들을 추가 할 것이다.
    - 다른 사람들은 여러분의 드라이버에 버그를 발견하고 수정할 것이다.
    - 다른 사람들은 여러분의 드라이버의 개선점을 찾을 줄 것이다.
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 43594d5..cd5c1c9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2064,8 +2064,7 @@
 
 	  It is an ongoing process to be certain the hardware in a machine
 	  is properly shutdown, so do not be surprised if this code does not
-	  initially work for you.  It may help to enable device hotplugging
-	  support.
+	  initially work for you.
 
 config ATAGS_PROC
 	bool "Export atags in procfs"
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 5a768ad..b36370d 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -565,9 +565,9 @@
 
 	  It is an ongoing process to be certain the hardware in a machine
 	  is properly shutdown, so do not be surprised if this code does not
-	  initially work for you.  It may help to enable device hotplugging
-	  support.  As of this writing the exact hardware interface is
-	  strongly in flux, so no good recommendation can be made.
+	  initially work for you.  As of this writing the exact hardware
+	  interface is strongly in flux, so no good recommendation can be
+	  made.
 
 config CRASH_DUMP
 	  bool "kernel crash dumps"
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e12764c..dccd7ce 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2305,9 +2305,9 @@
 
 	  It is an ongoing process to be certain the hardware in a machine
 	  is properly shutdown, so do not be surprised if this code does not
-	  initially work for you.  It may help to enable device hotplugging
-	  support.  As of this writing the exact hardware interface is
-	  strongly in flux, so no good recommendation can be made.
+	  initially work for you.  As of this writing the exact hardware
+	  interface is strongly in flux, so no good recommendation can be
+	  made.
 
 config CRASH_DUMP
 	  bool "Kernel crash dumps"
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 1765bab..faf84c5 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1335,8 +1335,9 @@
 
 	return len;
 }
+static DEVICE_ATTR(kill, S_IWUSR, NULL, store_kill);
 
-static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr,
+static ssize_t ntcs_show(struct device *cd, struct device_attribute *attr,
 			 char *buf)
 {
 	struct vpe *vpe = get_vpe(tclimit);
@@ -1344,7 +1345,7 @@
 	return sprintf(buf, "%d\n", vpe->ntcs);
 }
 
-static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
+static ssize_t ntcs_store(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t len)
 {
 	struct vpe *vpe = get_vpe(tclimit);
@@ -1365,12 +1366,14 @@
 out_einval:
 	return -EINVAL;
 }
+static DEVICE_ATTR_RW(ntcs);
 
-static struct device_attribute vpe_class_attributes[] = {
-	__ATTR(kill, S_IWUSR, NULL, store_kill),
-	__ATTR(ntcs, S_IRUGO | S_IWUSR, show_ntcs, store_ntcs),
-	{}
+static struct attribute vpe_attrs[] = {
+	&dev_attr_kill.attr,
+	&dev_attr_ntcs.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(vpe);
 
 static void vpe_device_release(struct device *cd)
 {
@@ -1381,7 +1384,7 @@
 	.name = "vpe",
 	.owner = THIS_MODULE,
 	.dev_release = vpe_device_release,
-	.dev_attrs = vpe_class_attributes,
+	.dev_groups = vpe_groups,
 };
 
 struct device vpe_device;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 9cf59816d..5aecda0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -369,9 +369,9 @@
 
 	  It is an ongoing process to be certain the hardware in a machine
 	  is properly shutdown, so do not be surprised if this code does not
-	  initially work for you.  It may help to enable device hotplugging
-	  support.  As of this writing the exact hardware interface is
-	  strongly in flux, so no good recommendation can be made.
+	  initially work for you.  As of this writing the exact hardware
+	  interface is strongly in flux, so no good recommendation can be
+	  made.
 
 config CRASH_DUMP
 	bool "Build a kdump crash kernel"
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 1020dd8..1018ed3 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -643,9 +643,9 @@
 
 	  It is an ongoing process to be certain the hardware in a machine
 	  is properly shutdown, so do not be surprised if this code does not
-	  initially work for you.  It may help to enable device hotplugging
-	  support.  As of this writing the exact hardware interface is
-	  strongly in flux, so no good recommendation can be made.
+	  initially work for you.  As of this writing the exact hardware
+	  interface is strongly in flux, so no good recommendation can be
+	  made.
 
 config CRASH_DUMP
 	bool "kernel crash dumps (EXPERIMENTAL)"
diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h
index d5e86c9..d15c0d8 100644
--- a/arch/tile/include/asm/topology.h
+++ b/arch/tile/include/asm/topology.h
@@ -89,9 +89,6 @@
 #define topology_core_id(cpu)                   (cpu)
 #define topology_core_cpumask(cpu)              ((void)(cpu), cpu_online_mask)
 #define topology_thread_cpumask(cpu)            cpumask_of(cpu)
-
-/* indicates that pointers to the topology struct cpumask maps are valid */
-#define arch_provides_topology_pointers         yes
 #endif
 
 #endif /* _ASM_TILE_TOPOLOGY_H */
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 67e0074..27457379 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1628,9 +1628,9 @@
 
 	  It is an ongoing process to be certain the hardware in a machine
 	  is properly shutdown, so do not be surprised if this code does not
-	  initially work for you.  It may help to enable device hotplugging
-	  support.  As of this writing the exact hardware interface is
-	  strongly in flux, so no good recommendation can be made.
+	  initially work for you.  As of this writing the exact hardware
+	  interface is strongly in flux, so no good recommendation can be
+	  made.
 
 config CRASH_DUMP
 	bool "kernel crash dumps"
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 095b215..d35f24e 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -124,9 +124,6 @@
 #define topology_core_id(cpu)			(cpu_data(cpu).cpu_core_id)
 #define topology_core_cpumask(cpu)		(per_cpu(cpu_core_map, cpu))
 #define topology_thread_cpumask(cpu)		(per_cpu(cpu_sibling_map, cpu))
-
-/* indicates that pointers to the topology cpumask_t maps are valid */
-#define arch_provides_topology_pointers		yes
 #endif
 
 static inline void arch_fix_phys_package_id(int num, u32 slot)
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
index be60399..a83e3c6 100644
--- a/drivers/acpi/bgrt.c
+++ b/drivers/acpi/bgrt.c
@@ -51,20 +51,14 @@
 }
 static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
 
-static ssize_t show_image(struct file *file, struct kobject *kobj,
+static ssize_t image_read(struct file *file, struct kobject *kobj,
 	       struct bin_attribute *attr, char *buf, loff_t off, size_t count)
 {
 	memcpy(buf, attr->private + off, count);
 	return count;
 }
 
-static struct bin_attribute image_attr = {
-	.attr = {
-		.name = "image",
-		.mode = S_IRUGO,
-	},
-	.read = show_image,
-};
+static BIN_ATTR_RO(image, 0);	/* size gets filled in later */
 
 static struct attribute *bgrt_attributes[] = {
 	&dev_attr_version.attr,
@@ -75,8 +69,14 @@
 	NULL,
 };
 
+static struct bin_attribute *bgrt_bin_attributes[] = {
+	&bin_attr_image,
+	NULL,
+};
+
 static struct attribute_group bgrt_attribute_group = {
 	.attrs = bgrt_attributes,
+	.bin_attrs = bgrt_bin_attributes,
 };
 
 static int __init bgrt_init(void)
@@ -86,9 +86,8 @@
 	if (!bgrt_image)
 		return -ENODEV;
 
-	sysfs_bin_attr_init(&image_attr);
-	image_attr.private = bgrt_image;
-	image_attr.size = bgrt_image_size;
+	bin_attr_image.private = bgrt_image;
+	bin_attr_image.size = bgrt_image_size;
 
 	bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
 	if (!bgrt_kobj)
@@ -98,14 +97,8 @@
 	if (ret)
 		goto out_kobject;
 
-	ret = sysfs_create_bin_file(bgrt_kobj, &image_attr);
-	if (ret)
-		goto out_group;
-
 	return 0;
 
-out_group:
-	sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
 out_kobject:
 	kobject_put(bgrt_kobj);
 	return ret;
diff --git a/drivers/base/base.h b/drivers/base/base.h
index b8bdfe6..2cbc677 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -119,6 +119,16 @@
 	return drv->bus->match ? drv->bus->match(dev, drv) : 1;
 }
 
+extern int driver_add_groups(struct device_driver *drv,
+			     const struct attribute_group **groups);
+extern void driver_remove_groups(struct device_driver *drv,
+				 const struct attribute_group **groups);
+
+extern int device_add_groups(struct device *dev,
+			     const struct attribute_group **groups);
+extern void device_remove_groups(struct device *dev,
+				 const struct attribute_group **groups);
+
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
 extern int devres_release_all(struct device *dev);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index d414331..4c289ab 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include "base.h"
 #include "power/power.h"
 
@@ -165,8 +166,8 @@
 static struct kset *bus_kset;
 
 /* Manually detach a device from its associated driver. */
-static ssize_t driver_unbind(struct device_driver *drv,
-			     const char *buf, size_t count)
+static ssize_t unbind_store(struct device_driver *drv, const char *buf,
+			    size_t count)
 {
 	struct bus_type *bus = bus_get(drv->bus);
 	struct device *dev;
@@ -185,15 +186,15 @@
 	bus_put(bus);
 	return err;
 }
-static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
+static DRIVER_ATTR_WO(unbind);
 
 /*
  * Manually attach a device to a driver.
  * Note: the driver must want to bind to the device,
  * it is not possible to override the driver's id table.
  */
-static ssize_t driver_bind(struct device_driver *drv,
-			   const char *buf, size_t count)
+static ssize_t bind_store(struct device_driver *drv, const char *buf,
+			  size_t count)
 {
 	struct bus_type *bus = bus_get(drv->bus);
 	struct device *dev;
@@ -221,7 +222,7 @@
 	bus_put(bus);
 	return err;
 }
-static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+static DRIVER_ATTR_WO(bind);
 
 static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
 {
@@ -460,7 +461,7 @@
 	if (!bus->dev_attrs)
 		return 0;
 
-	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+	for (i = 0; bus->dev_attrs[i].attr.name; i++) {
 		error = device_create_file(dev, &bus->dev_attrs[i]);
 		if (error) {
 			while (--i >= 0)
@@ -476,7 +477,7 @@
 	int i;
 
 	if (bus->dev_attrs) {
-		for (i = 0; attr_name(bus->dev_attrs[i]); i++)
+		for (i = 0; bus->dev_attrs[i].attr.name; i++)
 			device_remove_file(dev, &bus->dev_attrs[i]);
 	}
 }
@@ -499,6 +500,9 @@
 		error = device_add_attrs(bus, dev);
 		if (error)
 			goto out_put;
+		error = device_add_groups(dev, bus->dev_groups);
+		if (error)
+			goto out_groups;
 		error = sysfs_create_link(&bus->p->devices_kset->kobj,
 						&dev->kobj, dev_name(dev));
 		if (error)
@@ -513,6 +517,8 @@
 
 out_subsys:
 	sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
+out_groups:
+	device_remove_groups(dev, bus->dev_groups);
 out_id:
 	device_remove_attrs(bus, dev);
 out_put:
@@ -575,6 +581,7 @@
 	sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
 			  dev_name(dev));
 	device_remove_attrs(dev->bus, dev);
+	device_remove_groups(dev, dev->bus->dev_groups);
 	if (klist_node_attached(&dev->p->knode_bus))
 		klist_del(&dev->p->knode_bus);
 
@@ -590,7 +597,7 @@
 	int i;
 
 	if (bus->drv_attrs) {
-		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
+		for (i = 0; bus->drv_attrs[i].attr.name; i++) {
 			error = driver_create_file(drv, &bus->drv_attrs[i]);
 			if (error)
 				goto err;
@@ -610,7 +617,7 @@
 	int i;
 
 	if (bus->drv_attrs) {
-		for (i = 0; attr_name(bus->drv_attrs[i]); i++)
+		for (i = 0; bus->drv_attrs[i].attr.name; i++)
 			driver_remove_file(drv, &bus->drv_attrs[i]);
 	}
 }
@@ -659,8 +666,8 @@
 	bus_remove_file(bus, &bus_attr_drivers_probe);
 }
 
-static ssize_t driver_uevent_store(struct device_driver *drv,
-				   const char *buf, size_t count)
+static ssize_t uevent_store(struct device_driver *drv, const char *buf,
+			    size_t count)
 {
 	enum kobject_action action;
 
@@ -668,7 +675,7 @@
 		kobject_uevent(&drv->p->kobj, action);
 	return count;
 }
-static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
+static DRIVER_ATTR_WO(uevent);
 
 /**
  * bus_add_driver - Add a driver to the bus.
@@ -719,6 +726,10 @@
 		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
 			__func__, drv->name);
 	}
+	error = driver_add_groups(drv, bus->drv_groups);
+	if (error)
+		printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
+			__func__, drv->name);
 
 	if (!drv->suppress_bind_attrs) {
 		error = add_bind_files(drv);
@@ -756,6 +767,7 @@
 	if (!drv->suppress_bind_attrs)
 		remove_bind_files(drv);
 	driver_remove_attrs(drv->bus, drv);
+	driver_remove_groups(drv, drv->bus->drv_groups);
 	driver_remove_file(drv, &driver_attr_uevent);
 	klist_remove(&drv->p->knode_bus);
 	pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);
@@ -846,7 +858,7 @@
 	int i;
 
 	if (bus->bus_attrs) {
-		for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
+		for (i = 0; bus->bus_attrs[i].attr.name; i++) {
 			error = bus_create_file(bus, &bus->bus_attrs[i]);
 			if (error)
 				goto err;
@@ -865,11 +877,23 @@
 	int i;
 
 	if (bus->bus_attrs) {
-		for (i = 0; attr_name(bus->bus_attrs[i]); i++)
+		for (i = 0; bus->bus_attrs[i].attr.name; i++)
 			bus_remove_file(bus, &bus->bus_attrs[i]);
 	}
 }
 
+static int bus_add_groups(struct bus_type *bus,
+			  const struct attribute_group **groups)
+{
+	return sysfs_create_groups(&bus->p->subsys.kobj, groups);
+}
+
+static void bus_remove_groups(struct bus_type *bus,
+			      const struct attribute_group **groups)
+{
+	sysfs_remove_groups(&bus->p->subsys.kobj, groups);
+}
+
 static void klist_devices_get(struct klist_node *n)
 {
 	struct device_private *dev_prv = to_device_private_bus(n);
@@ -962,10 +986,15 @@
 	retval = bus_add_attrs(bus);
 	if (retval)
 		goto bus_attrs_fail;
+	retval = bus_add_groups(bus, bus->bus_groups);
+	if (retval)
+		goto bus_groups_fail;
 
 	pr_debug("bus: '%s': registered\n", bus->name);
 	return 0;
 
+bus_groups_fail:
+	bus_remove_attrs(bus);
 bus_attrs_fail:
 	remove_probe_files(bus);
 bus_probe_files_fail:
@@ -996,6 +1025,7 @@
 	if (bus->dev_root)
 		device_unregister(bus->dev_root);
 	bus_remove_attrs(bus);
+	bus_remove_groups(bus, bus->bus_groups);
 	remove_probe_files(bus);
 	kset_unregister(bus->p->drivers_kset);
 	kset_unregister(bus->p->devices_kset);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 3ce8454..8b7818b 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -135,7 +135,7 @@
 	int error = 0;
 
 	if (cls->class_attrs) {
-		for (i = 0; attr_name(cls->class_attrs[i]); i++) {
+		for (i = 0; cls->class_attrs[i].attr.name; i++) {
 			error = class_create_file(cls, &cls->class_attrs[i]);
 			if (error)
 				goto error;
@@ -154,7 +154,7 @@
 	int i;
 
 	if (cls->class_attrs) {
-		for (i = 0; attr_name(cls->class_attrs[i]); i++)
+		for (i = 0; cls->class_attrs[i].attr.name; i++)
 			class_remove_file(cls, &cls->class_attrs[i]);
 	}
 }
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8856d74..c7b0925 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -26,6 +26,7 @@
 #include <linux/async.h>
 #include <linux/pm_runtime.h>
 #include <linux/netdevice.h>
+#include <linux/sysfs.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -36,9 +37,9 @@
 #else
 long sysfs_deprecated = 0;
 #endif
-static __init int sysfs_deprecated_setup(char *arg)
+static int __init sysfs_deprecated_setup(char *arg)
 {
-	return strict_strtol(arg, 10, &sysfs_deprecated);
+	return kstrtol(arg, 10, &sysfs_deprecated);
 }
 early_param("sysfs.deprecated", sysfs_deprecated_setup);
 #endif
@@ -345,7 +346,7 @@
 	.uevent =	dev_uevent,
 };
 
-static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
+static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
 	struct kobject *top_kobj;
@@ -388,7 +389,7 @@
 	return count;
 }
 
-static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
+static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
 	enum kobject_action action;
@@ -399,11 +400,9 @@
 		dev_err(dev, "uevent: unknown action-string\n");
 	return count;
 }
+static DEVICE_ATTR_RW(uevent);
 
-static struct device_attribute uevent_attr =
-	__ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
-
-static ssize_t show_online(struct device *dev, struct device_attribute *attr,
+static ssize_t online_show(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
 	bool val;
@@ -414,7 +413,7 @@
 	return sprintf(buf, "%u\n", val);
 }
 
-static ssize_t store_online(struct device *dev, struct device_attribute *attr,
+static ssize_t online_store(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
 	bool val;
@@ -429,9 +428,7 @@
 	unlock_device_hotplug();
 	return ret < 0 ? ret : count;
 }
-
-static struct device_attribute online_attr =
-	__ATTR(online, S_IRUGO | S_IWUSR, show_online, store_online);
+static DEVICE_ATTR_RW(online);
 
 static int device_add_attributes(struct device *dev,
 				 struct device_attribute *attrs)
@@ -440,7 +437,7 @@
 	int i;
 
 	if (attrs) {
-		for (i = 0; attr_name(attrs[i]); i++) {
+		for (i = 0; attrs[i].attr.name; i++) {
 			error = device_create_file(dev, &attrs[i]);
 			if (error)
 				break;
@@ -458,7 +455,7 @@
 	int i;
 
 	if (attrs)
-		for (i = 0; attr_name(attrs[i]); i++)
+		for (i = 0; attrs[i].attr.name; i++)
 			device_remove_file(dev, &attrs[i]);
 }
 
@@ -469,7 +466,7 @@
 	int i;
 
 	if (attrs) {
-		for (i = 0; attr_name(attrs[i]); i++) {
+		for (i = 0; attrs[i].attr.name; i++) {
 			error = device_create_bin_file(dev, &attrs[i]);
 			if (error)
 				break;
@@ -487,38 +484,19 @@
 	int i;
 
 	if (attrs)
-		for (i = 0; attr_name(attrs[i]); i++)
+		for (i = 0; attrs[i].attr.name; i++)
 			device_remove_bin_file(dev, &attrs[i]);
 }
 
-static int device_add_groups(struct device *dev,
-			     const struct attribute_group **groups)
+int device_add_groups(struct device *dev, const struct attribute_group **groups)
 {
-	int error = 0;
-	int i;
-
-	if (groups) {
-		for (i = 0; groups[i]; i++) {
-			error = sysfs_create_group(&dev->kobj, groups[i]);
-			if (error) {
-				while (--i >= 0)
-					sysfs_remove_group(&dev->kobj,
-							   groups[i]);
-				break;
-			}
-		}
-	}
-	return error;
+	return sysfs_create_groups(&dev->kobj, groups);
 }
 
-static void device_remove_groups(struct device *dev,
-				 const struct attribute_group **groups)
+void device_remove_groups(struct device *dev,
+			  const struct attribute_group **groups)
 {
-	int i;
-
-	if (groups)
-		for (i = 0; groups[i]; i++)
-			sysfs_remove_group(&dev->kobj, groups[i]);
+	sysfs_remove_groups(&dev->kobj, groups);
 }
 
 static int device_add_attrs(struct device *dev)
@@ -550,7 +528,7 @@
 		goto err_remove_type_groups;
 
 	if (device_supports_offline(dev) && !dev->offline_disabled) {
-		error = device_create_file(dev, &online_attr);
+		error = device_create_file(dev, &dev_attr_online);
 		if (error)
 			goto err_remove_type_groups;
 	}
@@ -578,7 +556,7 @@
 	struct class *class = dev->class;
 	const struct device_type *type = dev->type;
 
-	device_remove_file(dev, &online_attr);
+	device_remove_file(dev, &dev_attr_online);
 	device_remove_groups(dev, dev->groups);
 
 	if (type)
@@ -591,15 +569,12 @@
 	}
 }
 
-
-static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
+static ssize_t dev_show(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
 	return print_dev_t(buf, dev->devt);
 }
-
-static struct device_attribute devt_attr =
-	__ATTR(dev, S_IRUGO, show_dev, NULL);
+static DEVICE_ATTR_RO(dev);
 
 /* /sys/devices/ */
 struct kset *devices_kset;
@@ -626,6 +601,7 @@
 
 	return error;
 }
+EXPORT_SYMBOL_GPL(device_create_file);
 
 /**
  * device_remove_file - remove sysfs attribute file.
@@ -638,6 +614,7 @@
 	if (dev)
 		sysfs_remove_file(&dev->kobj, &attr->attr);
 }
+EXPORT_SYMBOL_GPL(device_remove_file);
 
 /**
  * device_create_bin_file - create sysfs binary attribute file for device.
@@ -748,6 +725,7 @@
 	device_pm_init(dev);
 	set_dev_node(dev, -1);
 }
+EXPORT_SYMBOL_GPL(device_initialize);
 
 struct kobject *virtual_device_parent(struct device *dev)
 {
@@ -1100,12 +1078,12 @@
 	if (platform_notify)
 		platform_notify(dev);
 
-	error = device_create_file(dev, &uevent_attr);
+	error = device_create_file(dev, &dev_attr_uevent);
 	if (error)
 		goto attrError;
 
 	if (MAJOR(dev->devt)) {
-		error = device_create_file(dev, &devt_attr);
+		error = device_create_file(dev, &dev_attr_dev);
 		if (error)
 			goto ueventattrError;
 
@@ -1172,9 +1150,9 @@
 		device_remove_sys_dev_entry(dev);
  devtattrError:
 	if (MAJOR(dev->devt))
-		device_remove_file(dev, &devt_attr);
+		device_remove_file(dev, &dev_attr_dev);
  ueventattrError:
-	device_remove_file(dev, &uevent_attr);
+	device_remove_file(dev, &dev_attr_uevent);
  attrError:
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
 	kobject_del(&dev->kobj);
@@ -1187,6 +1165,7 @@
 	dev->p = NULL;
 	goto done;
 }
+EXPORT_SYMBOL_GPL(device_add);
 
 /**
  * device_register - register a device with the system.
@@ -1211,6 +1190,7 @@
 	device_initialize(dev);
 	return device_add(dev);
 }
+EXPORT_SYMBOL_GPL(device_register);
 
 /**
  * get_device - increment reference count for device.
@@ -1224,6 +1204,7 @@
 {
 	return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL;
 }
+EXPORT_SYMBOL_GPL(get_device);
 
 /**
  * put_device - decrement reference count.
@@ -1235,6 +1216,7 @@
 	if (dev)
 		kobject_put(&dev->kobj);
 }
+EXPORT_SYMBOL_GPL(put_device);
 
 /**
  * device_del - delete device from system.
@@ -1266,7 +1248,7 @@
 	if (MAJOR(dev->devt)) {
 		devtmpfs_delete_node(dev);
 		device_remove_sys_dev_entry(dev);
-		device_remove_file(dev, &devt_attr);
+		device_remove_file(dev, &dev_attr_dev);
 	}
 	if (dev->class) {
 		device_remove_class_symlinks(dev);
@@ -1281,7 +1263,7 @@
 		klist_del(&dev->knode_class);
 		mutex_unlock(&dev->class->p->mutex);
 	}
-	device_remove_file(dev, &uevent_attr);
+	device_remove_file(dev, &dev_attr_uevent);
 	device_remove_attrs(dev);
 	bus_remove_device(dev);
 	device_pm_remove(dev);
@@ -1297,6 +1279,7 @@
 	kobject_del(&dev->kobj);
 	put_device(parent);
 }
+EXPORT_SYMBOL_GPL(device_del);
 
 /**
  * device_unregister - unregister device from system.
@@ -1315,6 +1298,7 @@
 	device_del(dev);
 	put_device(dev);
 }
+EXPORT_SYMBOL_GPL(device_unregister);
 
 static struct device *next_device(struct klist_iter *i)
 {
@@ -1403,6 +1387,7 @@
 	klist_iter_exit(&i);
 	return error;
 }
+EXPORT_SYMBOL_GPL(device_for_each_child);
 
 /**
  * device_find_child - device iterator for locating a particular device.
@@ -1437,6 +1422,7 @@
 	klist_iter_exit(&i);
 	return child;
 }
+EXPORT_SYMBOL_GPL(device_find_child);
 
 int __init devices_init(void)
 {
@@ -1464,21 +1450,6 @@
 	return -ENOMEM;
 }
 
-EXPORT_SYMBOL_GPL(device_for_each_child);
-EXPORT_SYMBOL_GPL(device_find_child);
-
-EXPORT_SYMBOL_GPL(device_initialize);
-EXPORT_SYMBOL_GPL(device_add);
-EXPORT_SYMBOL_GPL(device_register);
-
-EXPORT_SYMBOL_GPL(device_del);
-EXPORT_SYMBOL_GPL(device_unregister);
-EXPORT_SYMBOL_GPL(get_device);
-EXPORT_SYMBOL_GPL(put_device);
-
-EXPORT_SYMBOL_GPL(device_create_file);
-EXPORT_SYMBOL_GPL(device_remove_file);
-
 static DEFINE_MUTEX(device_hotplug_lock);
 
 void lock_device_hotplug(void)
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 4c358bc..6bfaaca 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -43,11 +43,14 @@
 	struct cpu *cpu = container_of(dev, struct cpu, dev);
 	int cpuid = dev->id;
 	int from_nid, to_nid;
-	int ret;
+	int ret = -ENODEV;
 
 	cpu_hotplug_driver_lock();
 
 	from_nid = cpu_to_node(cpuid);
+	if (from_nid == NUMA_NO_NODE)
+		goto out;
+
 	ret = cpu_up(cpuid);
 	/*
 	 * When hot adding memory to memoryless node and enabling a cpu
@@ -57,6 +60,7 @@
 	if (from_nid != to_nid)
 		change_cpu_under_node(cpu, from_nid, to_nid);
 
+ out:
 	cpu_hotplug_driver_unlock();
 	return ret;
 }
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 0ca5442..6c9cdaa 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -134,7 +134,7 @@
 
 static DEFINE_MUTEX(cma_mutex);
 
-static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
+static int __init cma_activate_area(unsigned long base_pfn, unsigned long count)
 {
 	unsigned long pfn = base_pfn;
 	unsigned i = count >> pageblock_order;
@@ -156,7 +156,7 @@
 	return 0;
 }
 
-static __init struct cma *cma_create_area(unsigned long base_pfn,
+static struct cma * __init cma_create_area(unsigned long base_pfn,
 				     unsigned long count)
 {
 	int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 974e301..9e29943 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/sysfs.h>
 #include "base.h"
 
 static struct device *next_device(struct klist_iter *i)
@@ -123,34 +124,16 @@
 }
 EXPORT_SYMBOL_GPL(driver_remove_file);
 
-static int driver_add_groups(struct device_driver *drv,
-			     const struct attribute_group **groups)
+int driver_add_groups(struct device_driver *drv,
+		      const struct attribute_group **groups)
 {
-	int error = 0;
-	int i;
-
-	if (groups) {
-		for (i = 0; groups[i]; i++) {
-			error = sysfs_create_group(&drv->p->kobj, groups[i]);
-			if (error) {
-				while (--i >= 0)
-					sysfs_remove_group(&drv->p->kobj,
-							   groups[i]);
-				break;
-			}
-		}
-	}
-	return error;
+	return sysfs_create_groups(&drv->p->kobj, groups);
 }
 
-static void driver_remove_groups(struct device_driver *drv,
-				 const struct attribute_group **groups)
+void driver_remove_groups(struct device_driver *drv,
+			  const struct attribute_group **groups)
 {
-	int i;
-
-	if (groups)
-		for (i = 0; groups[i]; i++)
-			sysfs_remove_group(&drv->p->kobj, groups[i]);
+	sysfs_remove_groups(&drv->p->kobj, groups);
 }
 
 /**
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index a439602..10a4467 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -486,9 +486,8 @@
 	.notifier_call = fw_shutdown_notify,
 };
 
-static ssize_t firmware_timeout_show(struct class *class,
-				     struct class_attribute *attr,
-				     char *buf)
+static ssize_t timeout_show(struct class *class, struct class_attribute *attr,
+			    char *buf)
 {
 	return sprintf(buf, "%d\n", loading_timeout);
 }
@@ -506,9 +505,8 @@
  *
  *	Note: zero means 'wait forever'.
  **/
-static ssize_t firmware_timeout_store(struct class *class,
-				      struct class_attribute *attr,
-				      const char *buf, size_t count)
+static ssize_t timeout_store(struct class *class, struct class_attribute *attr,
+			     const char *buf, size_t count)
 {
 	loading_timeout = simple_strtol(buf, NULL, 10);
 	if (loading_timeout < 0)
@@ -518,8 +516,7 @@
 }
 
 static struct class_attribute firmware_class_attrs[] = {
-	__ATTR(timeout, S_IWUSR | S_IRUGO,
-		firmware_timeout_show, firmware_timeout_store),
+	__ATTR_RW(timeout),
 	__ATTR_NULL
 };
 
@@ -868,8 +865,15 @@
 		goto err_del_dev;
 	}
 
+	mutex_lock(&fw_lock);
+	list_add(&buf->pending_list, &pending_fw_head);
+	mutex_unlock(&fw_lock);
+
 	retval = device_create_file(f_dev, &dev_attr_loading);
 	if (retval) {
+		mutex_lock(&fw_lock);
+		list_del_init(&buf->pending_list);
+		mutex_unlock(&fw_lock);
 		dev_err(f_dev, "%s: device_create_file failed\n", __func__);
 		goto err_del_bin_attr;
 	}
@@ -884,10 +888,6 @@
 		kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
 	}
 
-	mutex_lock(&fw_lock);
-	list_add(&buf->pending_list, &pending_fw_head);
-	mutex_unlock(&fw_lock);
-
 	wait_for_completion(&buf->completion);
 
 	cancel_delayed_work_sync(&fw_priv->timeout_work);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index ec386ee..1c61762 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -16,7 +16,6 @@
 #include <linux/capability.h>
 #include <linux/device.h>
 #include <linux/memory.h>
-#include <linux/kobject.h>
 #include <linux/memory_hotplug.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
@@ -30,6 +29,8 @@
 
 #define MEMORY_CLASS_NAME	"memory"
 
+#define to_memory_block(dev) container_of(dev, struct memory_block, dev)
+
 static int sections_per_block;
 
 static inline int base_memory_block_id(int section_nr)
@@ -77,7 +78,7 @@
 
 static void memory_block_release(struct device *dev)
 {
-	struct memory_block *mem = container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
 
 	kfree(mem);
 }
@@ -110,8 +111,7 @@
 static ssize_t show_mem_start_phys_index(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct memory_block *mem =
-		container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
 	unsigned long phys_index;
 
 	phys_index = mem->start_section_nr / sections_per_block;
@@ -121,8 +121,7 @@
 static ssize_t show_mem_end_phys_index(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct memory_block *mem =
-		container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
 	unsigned long phys_index;
 
 	phys_index = mem->end_section_nr / sections_per_block;
@@ -137,8 +136,7 @@
 {
 	unsigned long i, pfn;
 	int ret = 1;
-	struct memory_block *mem =
-		container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
 
 	for (i = 0; i < sections_per_block; i++) {
 		if (!present_section_nr(mem->start_section_nr + i))
@@ -156,8 +154,7 @@
 static ssize_t show_mem_state(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct memory_block *mem =
-		container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
 	ssize_t len = 0;
 
 	/*
@@ -263,9 +260,8 @@
 	return ret;
 }
 
-static int __memory_block_change_state(struct memory_block *mem,
-		unsigned long to_state, unsigned long from_state_req,
-		int online_type)
+static int memory_block_change_state(struct memory_block *mem,
+		unsigned long to_state, unsigned long from_state_req)
 {
 	int ret = 0;
 
@@ -275,105 +271,89 @@
 	if (to_state == MEM_OFFLINE)
 		mem->state = MEM_GOING_OFFLINE;
 
-	ret = memory_block_action(mem->start_section_nr, to_state, online_type);
+	ret = memory_block_action(mem->start_section_nr, to_state,
+				mem->online_type);
+
 	mem->state = ret ? from_state_req : to_state;
+
 	return ret;
 }
 
+/* The device lock serializes operations on memory_subsys_[online|offline] */
 static int memory_subsys_online(struct device *dev)
 {
-	struct memory_block *mem = container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
 	int ret;
 
-	mutex_lock(&mem->state_mutex);
+	if (mem->state == MEM_ONLINE)
+		return 0;
 
-	ret = mem->state == MEM_ONLINE ? 0 :
-		__memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE,
-					    ONLINE_KEEP);
+	/*
+	 * If we are called from store_mem_state(), online_type will be
+	 * set >= 0 Otherwise we were called from the device online
+	 * attribute and need to set the online_type.
+	 */
+	if (mem->online_type < 0)
+		mem->online_type = ONLINE_KEEP;
 
-	mutex_unlock(&mem->state_mutex);
+	ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+
+	/* clear online_type */
+	mem->online_type = -1;
+
 	return ret;
 }
 
 static int memory_subsys_offline(struct device *dev)
 {
-	struct memory_block *mem = container_of(dev, struct memory_block, dev);
-	int ret;
+	struct memory_block *mem = to_memory_block(dev);
 
-	mutex_lock(&mem->state_mutex);
+	if (mem->state == MEM_OFFLINE)
+		return 0;
 
-	ret = mem->state == MEM_OFFLINE ? 0 :
-		__memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, -1);
-
-	mutex_unlock(&mem->state_mutex);
-	return ret;
+	return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
 }
 
-static int __memory_block_change_state_uevent(struct memory_block *mem,
-		unsigned long to_state, unsigned long from_state_req,
-		int online_type)
-{
-	int ret = __memory_block_change_state(mem, to_state, from_state_req,
-					      online_type);
-	if (!ret) {
-		switch (mem->state) {
-		case MEM_OFFLINE:
-			kobject_uevent(&mem->dev.kobj, KOBJ_OFFLINE);
-			break;
-		case MEM_ONLINE:
-			kobject_uevent(&mem->dev.kobj, KOBJ_ONLINE);
-			break;
-		default:
-			break;
-		}
-	}
-	return ret;
-}
-
-static int memory_block_change_state(struct memory_block *mem,
-		unsigned long to_state, unsigned long from_state_req,
-		int online_type)
-{
-	int ret;
-
-	mutex_lock(&mem->state_mutex);
-	ret = __memory_block_change_state_uevent(mem, to_state, from_state_req,
-						 online_type);
-	mutex_unlock(&mem->state_mutex);
-
-	return ret;
-}
 static ssize_t
 store_mem_state(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct memory_block *mem;
-	bool offline;
-	int ret = -EINVAL;
-
-	mem = container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
+	int ret, online_type;
 
 	lock_device_hotplug();
 
-	if (!strncmp(buf, "online_kernel", min_t(int, count, 13))) {
-		offline = false;
-		ret = memory_block_change_state(mem, MEM_ONLINE,
-						MEM_OFFLINE, ONLINE_KERNEL);
-	} else if (!strncmp(buf, "online_movable", min_t(int, count, 14))) {
-		offline = false;
-		ret = memory_block_change_state(mem, MEM_ONLINE,
-						MEM_OFFLINE, ONLINE_MOVABLE);
-	} else if (!strncmp(buf, "online", min_t(int, count, 6))) {
-		offline = false;
-		ret = memory_block_change_state(mem, MEM_ONLINE,
-						MEM_OFFLINE, ONLINE_KEEP);
-	} else if(!strncmp(buf, "offline", min_t(int, count, 7))) {
-		offline = true;
-		ret = memory_block_change_state(mem, MEM_OFFLINE,
-						MEM_ONLINE, -1);
+	if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
+		online_type = ONLINE_KERNEL;
+	else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
+		online_type = ONLINE_MOVABLE;
+	else if (!strncmp(buf, "online", min_t(int, count, 6)))
+		online_type = ONLINE_KEEP;
+	else if (!strncmp(buf, "offline", min_t(int, count, 7)))
+		online_type = -1;
+	else
+		return -EINVAL;
+
+	switch (online_type) {
+	case ONLINE_KERNEL:
+	case ONLINE_MOVABLE:
+	case ONLINE_KEEP:
+		/*
+		 * mem->online_type is not protected so there can be a
+		 * race here.  However, when racing online, the first
+		 * will succeed and the second will just return as the
+		 * block will already be online.  The online type
+		 * could be either one, but that is expected.
+		 */
+		mem->online_type = online_type;
+		ret = device_online(&mem->dev);
+		break;
+	case -1:
+		ret = device_offline(&mem->dev);
+		break;
+	default:
+		ret = -EINVAL; /* should never happen */
 	}
-	if (!ret)
-		dev->offline = offline;
 
 	unlock_device_hotplug();
 
@@ -394,8 +374,7 @@
 static ssize_t show_phys_device(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct memory_block *mem =
-		container_of(dev, struct memory_block, dev);
+	struct memory_block *mem = to_memory_block(dev);
 	return sprintf(buf, "%d\n", mem->phys_device);
 }
 
@@ -471,7 +450,7 @@
 	u64 pfn;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (strict_strtoull(buf, 0, &pfn) < 0)
+	if (kstrtoull(buf, 0, &pfn) < 0)
 		return -EINVAL;
 	pfn >>= PAGE_SHIFT;
 	if (!pfn_valid(pfn))
@@ -490,7 +469,7 @@
 	u64 pfn;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (strict_strtoull(buf, 0, &pfn) < 0)
+	if (kstrtoull(buf, 0, &pfn) < 0)
 		return -EINVAL;
 	pfn >>= PAGE_SHIFT;
 	ret = memory_failure(pfn, 0, 0);
@@ -527,7 +506,7 @@
 		put_device(&hint->dev);
 	if (!dev)
 		return NULL;
-	return container_of(dev, struct memory_block, dev);
+	return to_memory_block(dev);
 }
 
 /*
@@ -567,16 +546,13 @@
 static
 int register_memory(struct memory_block *memory)
 {
-	int error;
-
 	memory->dev.bus = &memory_subsys;
 	memory->dev.id = memory->start_section_nr / sections_per_block;
 	memory->dev.release = memory_block_release;
 	memory->dev.groups = memory_memblk_attr_groups;
 	memory->dev.offline = memory->state == MEM_OFFLINE;
 
-	error = device_register(&memory->dev);
-	return error;
+	return device_register(&memory->dev);
 }
 
 static int init_memory_block(struct memory_block **memory,
@@ -597,7 +573,6 @@
 	mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
 	mem->state = state;
 	mem->section_count++;
-	mutex_init(&mem->state_mutex);
 	start_pfn = section_nr_to_pfn(mem->start_section_nr);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
 
@@ -607,55 +582,57 @@
 	return ret;
 }
 
-static int add_memory_section(int nid, struct mem_section *section,
-			struct memory_block **mem_p,
-			unsigned long state, enum mem_add_context context)
+static int add_memory_block(int base_section_nr)
 {
-	struct memory_block *mem = NULL;
-	int scn_nr = __section_nr(section);
-	int ret = 0;
+	struct memory_block *mem;
+	int i, ret, section_count = 0, section_nr;
 
-	mutex_lock(&mem_sysfs_mutex);
-
-	if (context == BOOT) {
-		/* same memory block ? */
-		if (mem_p && *mem_p)
-			if (scn_nr >= (*mem_p)->start_section_nr &&
-			    scn_nr <= (*mem_p)->end_section_nr) {
-				mem = *mem_p;
-				kobject_get(&mem->dev.kobj);
-			}
-	} else
-		mem = find_memory_block(section);
-
-	if (mem) {
-		mem->section_count++;
-		kobject_put(&mem->dev.kobj);
-	} else {
-		ret = init_memory_block(&mem, section, state);
-		/* store memory_block pointer for next loop */
-		if (!ret && context == BOOT)
-			if (mem_p)
-				*mem_p = mem;
+	for (i = base_section_nr;
+	     (i < base_section_nr + sections_per_block) && i < NR_MEM_SECTIONS;
+	     i++) {
+		if (!present_section_nr(i))
+			continue;
+		if (section_count == 0)
+			section_nr = i;
+		section_count++;
 	}
 
-	if (!ret) {
-		if (context == HOTPLUG &&
-		    mem->section_count == sections_per_block)
-			ret = register_mem_sect_under_node(mem, nid);
-	}
-
-	mutex_unlock(&mem_sysfs_mutex);
-	return ret;
+	if (section_count == 0)
+		return 0;
+	ret = init_memory_block(&mem, __nr_to_section(section_nr), MEM_ONLINE);
+	if (ret)
+		return ret;
+	mem->section_count = section_count;
+	return 0;
 }
 
+
 /*
  * need an interface for the VM to add new memory regions,
  * but without onlining it.
  */
 int register_new_memory(int nid, struct mem_section *section)
 {
-	return add_memory_section(nid, section, NULL, MEM_OFFLINE, HOTPLUG);
+	int ret = 0;
+	struct memory_block *mem;
+
+	mutex_lock(&mem_sysfs_mutex);
+
+	mem = find_memory_block(section);
+	if (mem) {
+		mem->section_count++;
+		put_device(&mem->dev);
+	} else {
+		ret = init_memory_block(&mem, section, MEM_OFFLINE);
+		if (ret)
+			goto out;
+	}
+
+	if (mem->section_count == sections_per_block)
+		ret = register_mem_sect_under_node(mem, nid);
+out:
+	mutex_unlock(&mem_sysfs_mutex);
+	return ret;
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
@@ -665,7 +642,7 @@
 	BUG_ON(memory->dev.bus != &memory_subsys);
 
 	/* drop the ref. we got in remove_memory_block() */
-	kobject_put(&memory->dev.kobj);
+	put_device(&memory->dev);
 	device_unregister(&memory->dev);
 }
 
@@ -682,7 +659,7 @@
 	if (mem->section_count == 0)
 		unregister_memory(mem);
 	else
-		kobject_put(&mem->dev.kobj);
+		put_device(&mem->dev);
 
 	mutex_unlock(&mem_sysfs_mutex);
 	return 0;
@@ -735,7 +712,6 @@
 	int ret;
 	int err;
 	unsigned long block_sz;
-	struct memory_block *mem = NULL;
 
 	ret = subsys_system_register(&memory_subsys, memory_root_attr_groups);
 	if (ret)
@@ -748,17 +724,13 @@
 	 * Create entries for memory sections that were found
 	 * during boot and have been initialized
 	 */
-	for (i = 0; i < NR_MEM_SECTIONS; i++) {
-		if (!present_section_nr(i))
-			continue;
-		/* don't need to reuse memory_block if only one per block */
-		err = add_memory_section(0, __nr_to_section(i),
-				 (sections_per_block == 1) ? NULL : &mem,
-					 MEM_ONLINE,
-					 BOOT);
+	mutex_lock(&mem_sysfs_mutex);
+	for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) {
+		err = add_memory_block(i);
 		if (!ret)
 			ret = err;
 	}
+	mutex_unlock(&mem_sysfs_mutex);
 
 out:
 	if (ret)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 3c3197a..4f8bef3 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -672,11 +672,13 @@
 
 	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
 }
+static DEVICE_ATTR_RO(modalias);
 
-static struct device_attribute platform_dev_attrs[] = {
-	__ATTR_RO(modalias),
-	__ATTR_NULL,
+static struct attribute *platform_dev_attrs[] = {
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(platform_dev);
 
 static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -893,7 +895,7 @@
 
 struct bus_type platform_bus_type = {
 	.name		= "platform",
-	.dev_attrs	= platform_dev_attrs,
+	.dev_groups	= platform_dev_groups,
 	.match		= platform_match,
 	.uevent		= platform_uevent,
 	.pm		= &platform_dev_pm_ops,
@@ -1054,7 +1056,7 @@
  * @epdrv: early platform driver structure
  * @id: id to match against
  */
-static  __init struct platform_device *
+static struct platform_device * __init
 early_platform_match(struct early_platform_driver *epdrv, int id)
 {
 	struct platform_device *pd;
@@ -1072,7 +1074,7 @@
  * @epdrv: early platform driver structure
  * @id: return true if id or above exists
  */
-static  __init int early_platform_left(struct early_platform_driver *epdrv,
+static int __init early_platform_left(struct early_platform_driver *epdrv,
 				       int id)
 {
 	struct platform_device *pd;
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a53ebd2..03e089a 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -206,7 +206,7 @@
 	if (!dev->power.use_autosuspend)
 		return -EIO;
 
-	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
+	if (kstrtol(buf, 10, &delay) != 0 || delay != (int) delay)
 		return -EINVAL;
 
 	device_lock(dev);
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 6c2652a..de11eca 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -281,7 +281,7 @@
 	reg = simple_strtoul(start, &start, 16);
 	while (*start == ' ')
 		start++;
-	if (strict_strtoul(start, 16, &value))
+	if (kstrtoul(start, 16, &value))
 		return -EINVAL;
 
 	/* Userspace has been fiddling around behind the kernel's back */
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 2f5919e..94ffee3 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -62,25 +62,6 @@
 }
 #endif
 
-#ifdef arch_provides_topology_pointers
-#define define_siblings_show_map(name)					\
-static ssize_t show_##name(struct device *dev,				\
-			   struct device_attribute *attr, char *buf)	\
-{									\
-	unsigned int cpu = dev->id;					\
-	return show_cpumap(0, topology_##name(cpu), buf);		\
-}
-
-#define define_siblings_show_list(name)					\
-static ssize_t show_##name##_list(struct device *dev,			\
-				  struct device_attribute *attr,	\
-				  char *buf)				\
-{									\
-	unsigned int cpu = dev->id;					\
-	return show_cpumap(1, topology_##name(cpu), buf);		\
-}
-
-#else
 #define define_siblings_show_map(name)					\
 static ssize_t show_##name(struct device *dev,				\
 			   struct device_attribute *attr, char *buf)	\
@@ -95,7 +76,6 @@
 {									\
 	return show_cpumap(1, topology_##name(dev->id), buf);		\
 }
-#endif
 
 #define define_siblings_show_func(name)		\
 	define_siblings_show_map(name); define_siblings_show_list(name)
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 4ad2ad9..191cd17 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -397,15 +397,19 @@
 static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
 static void rbd_spec_put(struct rbd_spec *spec);
 
-static struct bus_attribute rbd_bus_attrs[] = {
-	__ATTR(add, S_IWUSR, NULL, rbd_add),
-	__ATTR(remove, S_IWUSR, NULL, rbd_remove),
-	__ATTR_NULL
+static BUS_ATTR(add, S_IWUSR, NULL, rbd_add);
+static BUS_ATTR(remove, S_IWUSR, NULL, rbd_remove);
+
+static struct attribute *rbd_bus_attrs[] = {
+	&bus_attr_add.attr,
+	&bus_attr_remove.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(rbd_bus);
 
 static struct bus_type rbd_bus_type = {
 	.name		= "rbd",
-	.bus_attrs	= rbd_bus_attrs,
+	.bus_groups	= rbd_bus_groups,
 };
 
 static void rbd_root_dev_release(struct device *dev)
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 9746705..0671e45 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -95,6 +95,7 @@
 	struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", bsr_dev->bsr_bytes);
 }
+static DEVICE_ATTR_RO(bsr_size);
 
 static ssize_t
 bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf)
@@ -102,20 +103,23 @@
 	struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", bsr_dev->bsr_stride);
 }
+static DEVICE_ATTR_RO(bsr_stride);
 
 static ssize_t
-bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf)
+bsr_length_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
 	return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
 }
+static DEVICE_ATTR_RO(bsr_length);
 
-static struct device_attribute bsr_dev_attrs[] = {
-	__ATTR(bsr_size, S_IRUGO, bsr_size_show, NULL),
-	__ATTR(bsr_stride, S_IRUGO, bsr_stride_show, NULL),
-	__ATTR(bsr_length, S_IRUGO, bsr_len_show, NULL),
-	__ATTR_NULL
+static struct attribute *bsr_dev_attrs[] = {
+	&dev_attr_bsr_size.attr,
+	&dev_attr_bsr_stride.attr,
+	&dev_attr_bsr_length.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(bsr_dev);
 
 static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
 {
@@ -308,7 +312,7 @@
 		ret = PTR_ERR(bsr_class);
 		goto out_err_1;
 	}
-	bsr_class->dev_attrs = bsr_dev_attrs;
+	bsr_class->dev_groups = bsr_dev_groups;
 
 	ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
 	bsr_major = MAJOR(bsr_dev);
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index 7faeb1c..ae82933 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -279,33 +279,37 @@
 	return fixed_size_llseek(file, offset, origin, srom->total_size);
 }
 
-static ssize_t total_show(struct device *dev,
-			  struct device_attribute *attr, char *buf)
+static ssize_t total_size_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct srom_dev *srom = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", srom->total_size);
 }
+static DEVICE_ATTR_RO(total_size);
 
-static ssize_t sector_show(struct device *dev,
-			   struct device_attribute *attr, char *buf)
+static ssize_t sector_size_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct srom_dev *srom = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", srom->sector_size);
 }
+static DEVICE_ATTR_RO(sector_size);
 
-static ssize_t page_show(struct device *dev,
-			 struct device_attribute *attr, char *buf)
+static ssize_t page_size_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct srom_dev *srom = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", srom->page_size);
 }
+static DEVICE_ATTR_RO(page_size);
 
-static struct device_attribute srom_dev_attrs[] = {
-	__ATTR(total_size, S_IRUGO, total_show, NULL),
-	__ATTR(sector_size, S_IRUGO, sector_show, NULL),
-	__ATTR(page_size, S_IRUGO, page_show, NULL),
-	__ATTR_NULL
+static struct attribute *srom_dev_attrs[] = {
+	&dev_attr_total_size.attr,
+	&dev_attr_sector_size.attr,
+	&dev_attr_page_size.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(srom_dev);
 
 static char *srom_devnode(struct device *dev, umode_t *mode)
 {
@@ -418,7 +422,7 @@
 		result = PTR_ERR(srom_class);
 		goto fail_cdev;
 	}
-	srom_class->dev_attrs = srom_dev_attrs;
+	srom_class->dev_groups = srom_dev_groups;
 	srom_class->devnode = srom_devnode;
 
 	/* Do per-partition initialization */
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index e94e619f..c99c00d 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -703,7 +703,7 @@
 }
 EXPORT_SYMBOL(devfreq_remove_governor);
 
-static ssize_t show_governor(struct device *dev,
+static ssize_t governor_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
 	if (!to_devfreq(dev)->governor)
@@ -712,7 +712,7 @@
 	return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
 }
 
-static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
+static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct devfreq *df = to_devfreq(dev);
@@ -754,9 +754,11 @@
 		ret = count;
 	return ret;
 }
-static ssize_t show_available_governors(struct device *d,
-				    struct device_attribute *attr,
-				    char *buf)
+static DEVICE_ATTR_RW(governor);
+
+static ssize_t available_governors_show(struct device *d,
+					struct device_attribute *attr,
+					char *buf)
 {
 	struct devfreq_governor *tmp_governor;
 	ssize_t count = 0;
@@ -775,9 +777,10 @@
 
 	return count;
 }
+static DEVICE_ATTR_RO(available_governors);
 
-static ssize_t show_freq(struct device *dev,
-			 struct device_attribute *attr, char *buf)
+static ssize_t cur_freq_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	unsigned long freq;
 	struct devfreq *devfreq = to_devfreq(dev);
@@ -788,20 +791,22 @@
 
 	return sprintf(buf, "%lu\n", devfreq->previous_freq);
 }
+static DEVICE_ATTR_RO(cur_freq);
 
-static ssize_t show_target_freq(struct device *dev,
-			struct device_attribute *attr, char *buf)
+static ssize_t target_freq_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
 }
+static DEVICE_ATTR_RO(target_freq);
 
-static ssize_t show_polling_interval(struct device *dev,
+static ssize_t polling_interval_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms);
 }
 
-static ssize_t store_polling_interval(struct device *dev,
+static ssize_t polling_interval_store(struct device *dev,
 				      struct device_attribute *attr,
 				      const char *buf, size_t count)
 {
@@ -821,8 +826,9 @@
 
 	return ret;
 }
+static DEVICE_ATTR_RW(polling_interval);
 
-static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
+static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct devfreq *df = to_devfreq(dev);
@@ -849,13 +855,13 @@
 	return ret;
 }
 
-static ssize_t show_min_freq(struct device *dev, struct device_attribute *attr,
+static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
 	return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq);
 }
 
-static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
+static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct devfreq *df = to_devfreq(dev);
@@ -881,16 +887,18 @@
 	mutex_unlock(&df->lock);
 	return ret;
 }
+static DEVICE_ATTR_RW(min_freq);
 
-static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
+static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
 	return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
 }
+static DEVICE_ATTR_RW(max_freq);
 
-static ssize_t show_available_freqs(struct device *d,
-				    struct device_attribute *attr,
-				    char *buf)
+static ssize_t available_frequencies_show(struct device *d,
+					  struct device_attribute *attr,
+					  char *buf)
 {
 	struct devfreq *df = to_devfreq(d);
 	struct device *dev = df->dev.parent;
@@ -918,9 +926,10 @@
 
 	return count;
 }
+static DEVICE_ATTR_RO(available_frequencies);
 
-static ssize_t show_trans_table(struct device *dev, struct device_attribute *attr,
-				char *buf)
+static ssize_t trans_stat_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct devfreq *devfreq = to_devfreq(dev);
 	ssize_t len;
@@ -959,20 +968,21 @@
 					devfreq->total_trans);
 	return len;
 }
+static DEVICE_ATTR_RO(trans_stat);
 
-static struct device_attribute devfreq_attrs[] = {
-	__ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
-	__ATTR(available_governors, S_IRUGO, show_available_governors, NULL),
-	__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
-	__ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL),
-	__ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
-	__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
-	       store_polling_interval),
-	__ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
-	__ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
-	__ATTR(trans_stat, S_IRUGO, show_trans_table, NULL),
-	{ },
+static struct attribute *devfreq_attrs[] = {
+	&dev_attr_governor.attr,
+	&dev_attr_available_governors.attr,
+	&dev_attr_cur_freq.attr,
+	&dev_attr_available_frequencies.attr,
+	&dev_attr_target_freq.attr,
+	&dev_attr_polling_interval.attr,
+	&dev_attr_min_freq.attr,
+	&dev_attr_max_freq.attr,
+	&dev_attr_trans_stat.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(devfreq);
 
 static int __init devfreq_init(void)
 {
@@ -988,7 +998,7 @@
 		pr_err("%s: couldn't create workqueue\n", __FILE__);
 		return PTR_ERR(devfreq_wq);
 	}
-	devfreq_class->dev_attrs = devfreq_attrs;
+	devfreq_class->dev_groups = devfreq_groups;
 
 	return 0;
 }
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 9e56745..99af4db 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -87,7 +87,8 @@
 	return chan_dev->chan;
 }
 
-static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t memcpy_count_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
 {
 	struct dma_chan *chan;
 	unsigned long count = 0;
@@ -106,9 +107,10 @@
 
 	return err;
 }
+static DEVICE_ATTR_RO(memcpy_count);
 
-static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr,
-				      char *buf)
+static ssize_t bytes_transferred_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
 {
 	struct dma_chan *chan;
 	unsigned long count = 0;
@@ -127,8 +129,10 @@
 
 	return err;
 }
+static DEVICE_ATTR_RO(bytes_transferred);
 
-static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t in_use_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct dma_chan *chan;
 	int err;
@@ -143,13 +147,15 @@
 
 	return err;
 }
+static DEVICE_ATTR_RO(in_use);
 
-static struct device_attribute dma_attrs[] = {
-	__ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
-	__ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
-	__ATTR(in_use, S_IRUGO, show_in_use, NULL),
-	__ATTR_NULL
+static struct attribute *dma_dev_attrs[] = {
+	&dev_attr_memcpy_count.attr,
+	&dev_attr_bytes_transferred.attr,
+	&dev_attr_in_use.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(dma_dev);
 
 static void chan_dev_release(struct device *dev)
 {
@@ -167,7 +173,7 @@
 
 static struct class dma_devclass = {
 	.name		= "dma",
-	.dev_attrs	= dma_attrs,
+	.dev_groups	= dma_dev_groups,
 	.dev_release	= chan_dev_release,
 };
 
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 1446152..148382f 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -148,6 +148,7 @@
 
 	return count;
 }
+static DEVICE_ATTR_RW(state);
 
 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -163,6 +164,7 @@
 
 	return sprintf(buf, "%s\n", dev_name(edev->dev));
 }
+static DEVICE_ATTR_RO(name);
 
 static ssize_t cable_name_show(struct device *dev,
 			       struct device_attribute *attr, char *buf)
@@ -527,11 +529,12 @@
 }
 EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
 
-static struct device_attribute extcon_attrs[] = {
-	__ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store),
-	__ATTR_RO(name),
-	__ATTR_NULL,
+static struct attribute *extcon_attrs[] = {
+	&dev_attr_state.attr,
+	&dev_attr_name.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(extcon);
 
 static int create_extcon_class(void)
 {
@@ -539,7 +542,7 @@
 		extcon_class = class_create(THIS_MODULE, "extcon");
 		if (IS_ERR(extcon_class))
 			return PTR_ERR(extcon_class);
-		extcon_class->dev_attrs = extcon_attrs;
+		extcon_class->dev_groups = extcon_groups;
 
 #if defined(CONFIG_ANDROID)
 		switch_class = class_compat_register("switch");
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 8e77c02..ff080ee 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -535,11 +535,12 @@
 
 static struct attribute_group dcdbas_attr_group = {
 	.attrs = dcdbas_dev_attrs,
+	.bin_attrs = dcdbas_bin_attrs,
 };
 
 static int dcdbas_probe(struct platform_device *dev)
 {
-	int i, error;
+	int error;
 
 	host_control_action = HC_ACTION_NONE;
 	host_control_smi_type = HC_SMITYPE_NONE;
@@ -555,18 +556,6 @@
 	if (error)
 		return error;
 
-	for (i = 0; dcdbas_bin_attrs[i]; i++) {
-		error = sysfs_create_bin_file(&dev->dev.kobj,
-					      dcdbas_bin_attrs[i]);
-		if (error) {
-			while (--i >= 0)
-				sysfs_remove_bin_file(&dev->dev.kobj,
-						      dcdbas_bin_attrs[i]);
-			sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
-			return error;
-		}
-	}
-
 	register_reboot_notifier(&dcdbas_reboot_nb);
 
 	dev_info(&dev->dev, "%s (version %s)\n",
@@ -577,11 +566,7 @@
 
 static int dcdbas_remove(struct platform_device *dev)
 {
-	int i;
-
 	unregister_reboot_notifier(&dcdbas_reboot_nb);
-	for (i = 0; dcdbas_bin_attrs[i]; i++)
-		sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]);
 	sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
 
 	return 0;
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 36668d1..b8f1c77 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1917,11 +1917,13 @@
 
 	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
 }
+static DEVICE_ATTR_RO(modalias);
 
-static struct device_attribute hid_dev_attrs[] = {
-	__ATTR_RO(modalias),
-	__ATTR_NULL,
+static struct attribute *hid_dev_attrs[] = {
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(hid_dev);
 
 static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -1949,7 +1951,7 @@
 
 static struct bus_type hid_bus_type = {
 	.name		= "hid",
-	.dev_attrs	= hid_dev_attrs,
+	.dev_groups	= hid_dev_groups,
 	.match		= hid_bus_match,
 	.probe		= hid_device_probe,
 	.remove		= hid_device_remove,
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
index 327f9b8..eed7f52 100644
--- a/drivers/hid/hid-roccat-arvo.c
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -75,6 +75,8 @@
 
 	return size;
 }
+static DEVICE_ATTR(mode_key, 0660,
+		   arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key);
 
 static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -123,6 +125,8 @@
 
 	return size;
 }
+static DEVICE_ATTR(key_mask, 0660,
+		   arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask);
 
 /* retval is 1-5 on success, < 0 on error */
 static int arvo_get_actual_profile(struct usb_device *usb_dev)
@@ -179,6 +183,9 @@
 	mutex_unlock(&arvo->arvo_lock);
 	return retval;
 }
+static DEVICE_ATTR(actual_profile, 0660,
+		   arvo_sysfs_show_actual_profile,
+		   arvo_sysfs_set_actual_profile);
 
 static ssize_t arvo_sysfs_write(struct file *fp,
 		struct kobject *kobj, void const *buf,
@@ -230,6 +237,8 @@
 	return arvo_sysfs_write(fp, kobj, buf, off, count,
 			sizeof(struct arvo_button), ARVO_COMMAND_BUTTON);
 }
+static BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button,
+		sizeof(struct arvo_button));
 
 static ssize_t arvo_sysfs_read_info(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
@@ -238,31 +247,30 @@
 	return arvo_sysfs_read(fp, kobj, buf, off, count,
 			sizeof(struct arvo_info), ARVO_COMMAND_INFO);
 }
+static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL,
+		sizeof(struct arvo_info));
 
-
-static struct device_attribute arvo_attributes[] = {
-	__ATTR(mode_key, 0660,
-			arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key),
-	__ATTR(key_mask, 0660,
-			arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask),
-	__ATTR(actual_profile, 0660,
-			arvo_sysfs_show_actual_profile,
-			arvo_sysfs_set_actual_profile),
-	__ATTR_NULL
+static struct attribute *arvo_attrs[] = {
+	&dev_attr_mode_key.attr,
+	&dev_attr_key_mask.attr,
+	&dev_attr_actual_profile.attr,
+	NULL,
 };
 
-static struct bin_attribute arvo_bin_attributes[] = {
-	{
-		.attr = { .name = "button", .mode = 0220 },
-		.size = sizeof(struct arvo_button),
-		.write = arvo_sysfs_write_button
-	},
-	{
-		.attr = { .name = "info", .mode = 0440 },
-		.size = sizeof(struct arvo_info),
-		.read = arvo_sysfs_read_info
-	},
-	__ATTR_NULL
+static struct bin_attribute *arvo_bin_attributes[] = {
+	&bin_attr_button,
+	&bin_attr_info,
+	NULL,
+};
+
+static const struct attribute_group arvo_group = {
+	.attrs = arvo_attrs,
+	.bin_attrs = arvo_bin_attributes,
+};
+
+static const struct attribute_group *arvo_groups[] = {
+	&arvo_group,
+	NULL,
 };
 
 static int arvo_init_arvo_device_struct(struct usb_device *usb_dev,
@@ -430,8 +438,7 @@
 	arvo_class = class_create(THIS_MODULE, "arvo");
 	if (IS_ERR(arvo_class))
 		return PTR_ERR(arvo_class);
-	arvo_class->dev_attrs = arvo_attributes;
-	arvo_class->dev_bin_attrs = arvo_bin_attributes;
+	arvo_class->dev_groups = arvo_groups;
 
 	retval = hid_register_driver(&arvo_driver);
 	if (retval)
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index 8023751..b7a4e10 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -109,12 +109,12 @@
 
 	return size;
 }
+static DEVICE_ATTR(actual_profile, 0660, isku_sysfs_show_actual_profile,
+		   isku_sysfs_set_actual_profile);
 
-static struct device_attribute isku_attributes[] = {
-	__ATTR(actual_profile, 0660,
-			isku_sysfs_show_actual_profile,
-			isku_sysfs_set_actual_profile),
-	__ATTR_NULL
+static struct attribute *isku_attrs[] = {
+	&dev_attr_actual_profile.attr,
+	NULL,
 };
 
 static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -184,7 +184,8 @@
 ISKU_SYSFS_W(thingy, THINGY)
 
 #define ISKU_BIN_ATTR_RW(thingy, THINGY) \
-{ \
+ISKU_SYSFS_RW(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0660 }, \
 	.size = ISKU_SIZE_ ## THINGY, \
 	.read = isku_sysfs_read_ ## thingy, \
@@ -192,52 +193,64 @@
 }
 
 #define ISKU_BIN_ATTR_R(thingy, THINGY) \
-{ \
+ISKU_SYSFS_R(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0440 }, \
 	.size = ISKU_SIZE_ ## THINGY, \
 	.read = isku_sysfs_read_ ## thingy, \
 }
 
 #define ISKU_BIN_ATTR_W(thingy, THINGY) \
-{ \
+ISKU_SYSFS_W(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0220 }, \
 	.size = ISKU_SIZE_ ## THINGY, \
 	.write = isku_sysfs_write_ ## thingy \
 }
 
-ISKU_SYSFS_RW(macro, MACRO)
-ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION)
-ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE)
-ISKU_SYSFS_RW(keys_media, KEYS_MEDIA)
-ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER)
-ISKU_SYSFS_RW(keys_macro, KEYS_MACRO)
-ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK)
-ISKU_SYSFS_RW(light, LIGHT)
-ISKU_SYSFS_RW(key_mask, KEY_MASK)
-ISKU_SYSFS_RW(last_set, LAST_SET)
-ISKU_SYSFS_W(talk, TALK)
-ISKU_SYSFS_W(talkfx, TALKFX)
-ISKU_SYSFS_R(info, INFO)
-ISKU_SYSFS_W(control, CONTROL)
-ISKU_SYSFS_W(reset, RESET)
+ISKU_BIN_ATTR_RW(macro, MACRO);
+ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION);
+ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE);
+ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA);
+ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER);
+ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO);
+ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK);
+ISKU_BIN_ATTR_RW(light, LIGHT);
+ISKU_BIN_ATTR_RW(key_mask, KEY_MASK);
+ISKU_BIN_ATTR_RW(last_set, LAST_SET);
+ISKU_BIN_ATTR_W(talk, TALK);
+ISKU_BIN_ATTR_W(talkfx, TALKFX);
+ISKU_BIN_ATTR_W(control, CONTROL);
+ISKU_BIN_ATTR_W(reset, RESET);
+ISKU_BIN_ATTR_R(info, INFO);
 
-static struct bin_attribute isku_bin_attributes[] = {
-	ISKU_BIN_ATTR_RW(macro, MACRO),
-	ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION),
-	ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE),
-	ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA),
-	ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER),
-	ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO),
-	ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK),
-	ISKU_BIN_ATTR_RW(light, LIGHT),
-	ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
-	ISKU_BIN_ATTR_RW(last_set, LAST_SET),
-	ISKU_BIN_ATTR_W(talk, TALK),
-	ISKU_BIN_ATTR_W(talkfx, TALKFX),
-	ISKU_BIN_ATTR_R(info, INFO),
-	ISKU_BIN_ATTR_W(control, CONTROL),
-	ISKU_BIN_ATTR_W(reset, RESET),
-	__ATTR_NULL
+static struct bin_attribute *isku_bin_attributes[] = {
+	&bin_attr_macro,
+	&bin_attr_keys_function,
+	&bin_attr_keys_easyzone,
+	&bin_attr_keys_media,
+	&bin_attr_keys_thumbster,
+	&bin_attr_keys_macro,
+	&bin_attr_keys_capslock,
+	&bin_attr_light,
+	&bin_attr_key_mask,
+	&bin_attr_last_set,
+	&bin_attr_talk,
+	&bin_attr_talkfx,
+	&bin_attr_control,
+	&bin_attr_reset,
+	&bin_attr_info,
+	NULL,
+};
+
+static const struct attribute_group isku_group = {
+	.attrs = isku_attrs,
+	.bin_attrs = isku_bin_attributes,
+};
+
+static const struct attribute_group *isku_groups[] = {
+	&isku_group,
+	NULL,
 };
 
 static int isku_init_isku_device_struct(struct usb_device *usb_dev,
@@ -427,8 +440,7 @@
 	isku_class = class_create(THIS_MODULE, "isku");
 	if (IS_ERR(isku_class))
 		return PTR_ERR(isku_class);
-	isku_class->dev_attrs = isku_attributes;
-	isku_class->dev_bin_attrs = isku_bin_attributes;
+	isku_class->dev_groups = isku_groups;
 
 	retval = hid_register_driver(&isku_driver);
 	if (retval)
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 7fae070..6e614a8 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -324,6 +324,8 @@
 
 	return sizeof(struct kone_settings);
 }
+static BIN_ATTR(settings, 0660, kone_sysfs_read_settings,
+		kone_sysfs_write_settings, sizeof(struct kone_settings));
 
 static ssize_t kone_sysfs_read_profilex(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr,
@@ -378,6 +380,19 @@
 
 	return sizeof(struct kone_profile);
 }
+#define PROFILE_ATTR(number)					\
+static struct bin_attribute bin_attr_profile##number = {	\
+	.attr = { .name = "profile##number", .mode = 0660 },	\
+	.size = sizeof(struct kone_profile),			\
+	.read = kone_sysfs_read_profilex,			\
+	.write = kone_sysfs_write_profilex,			\
+	.private = &profile_numbers[number-1],			\
+};
+PROFILE_ATTR(1);
+PROFILE_ATTR(2);
+PROFILE_ATTR(3);
+PROFILE_ATTR(4);
+PROFILE_ATTR(5);
 
 static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -386,6 +401,7 @@
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
 }
+static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
 
 static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -394,6 +410,7 @@
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
 }
+static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
 
 /* weight is read each time, since we don't get informed when it's changed */
 static ssize_t kone_sysfs_show_weight(struct device *dev,
@@ -416,6 +433,7 @@
 		return retval;
 	return snprintf(buf, PAGE_SIZE, "%d\n", weight);
 }
+static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
 
 static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -424,6 +442,8 @@
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
 }
+static DEVICE_ATTR(firmware_version, 0440, kone_sysfs_show_firmware_version,
+		   NULL);
 
 static ssize_t kone_sysfs_show_tcu(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -524,6 +544,7 @@
 	mutex_unlock(&kone->kone_lock);
 	return retval;
 }
+static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
 
 static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -570,15 +591,17 @@
 	mutex_unlock(&kone->kone_lock);
 	return size;
 }
+static DEVICE_ATTR(startup_profile, 0660, kone_sysfs_show_startup_profile,
+		   kone_sysfs_set_startup_profile);
 
-static struct device_attribute kone_attributes[] = {
+static struct attribute *kone_attrs[] = {
 	/*
 	 * Read actual dpi settings.
 	 * Returns raw value for further processing. Refer to enum
 	 * kone_polling_rates to get real value.
 	 */
-	__ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL),
-	__ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL),
+	&dev_attr_actual_dpi.attr,
+	&dev_attr_actual_profile.attr,
 
 	/*
 	 * The mouse can be equipped with one of four supplied weights from 5
@@ -587,7 +610,7 @@
 	 * by software. Refer to enum kone_weights to get corresponding real
 	 * weight.
 	 */
-	__ATTR(weight, 0440, kone_sysfs_show_weight, NULL),
+	&dev_attr_weight.attr,
 
 	/*
 	 * Prints firmware version stored in mouse as integer.
@@ -595,66 +618,38 @@
 	 * to get the real version number the decimal point has to be shifted 2
 	 * positions to the left. E.g. a value of 138 means 1.38.
 	 */
-	__ATTR(firmware_version, 0440,
-			kone_sysfs_show_firmware_version, NULL),
+	&dev_attr_firmware_version.attr,
 
 	/*
 	 * Prints state of Tracking Control Unit as number where 0 = off and
 	 * 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
 	 * activates the tcu
 	 */
-	__ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu),
+	&dev_attr_tcu.attr,
 
 	/* Prints and takes the number of the profile the mouse starts with */
-	__ATTR(startup_profile, 0660,
-			kone_sysfs_show_startup_profile,
-			kone_sysfs_set_startup_profile),
-	__ATTR_NULL
+	&dev_attr_startup_profile.attr,
+	NULL,
 };
 
-static struct bin_attribute kone_bin_attributes[] = {
-	{
-		.attr = { .name = "settings", .mode = 0660 },
-		.size = sizeof(struct kone_settings),
-		.read = kone_sysfs_read_settings,
-		.write = kone_sysfs_write_settings
-	},
-	{
-		.attr = { .name = "profile1", .mode = 0660 },
-		.size = sizeof(struct kone_profile),
-		.read = kone_sysfs_read_profilex,
-		.write = kone_sysfs_write_profilex,
-		.private = &profile_numbers[0]
-	},
-	{
-		.attr = { .name = "profile2", .mode = 0660 },
-		.size = sizeof(struct kone_profile),
-		.read = kone_sysfs_read_profilex,
-		.write = kone_sysfs_write_profilex,
-		.private = &profile_numbers[1]
-	},
-	{
-		.attr = { .name = "profile3", .mode = 0660 },
-		.size = sizeof(struct kone_profile),
-		.read = kone_sysfs_read_profilex,
-		.write = kone_sysfs_write_profilex,
-		.private = &profile_numbers[2]
-	},
-	{
-		.attr = { .name = "profile4", .mode = 0660 },
-		.size = sizeof(struct kone_profile),
-		.read = kone_sysfs_read_profilex,
-		.write = kone_sysfs_write_profilex,
-		.private = &profile_numbers[3]
-	},
-	{
-		.attr = { .name = "profile5", .mode = 0660 },
-		.size = sizeof(struct kone_profile),
-		.read = kone_sysfs_read_profilex,
-		.write = kone_sysfs_write_profilex,
-		.private = &profile_numbers[4]
-	},
-	__ATTR_NULL
+static struct bin_attribute *kone_bin_attributes[] = {
+	&bin_attr_settings,
+	&bin_attr_profile1,
+	&bin_attr_profile2,
+	&bin_attr_profile3,
+	&bin_attr_profile4,
+	&bin_attr_profile5,
+	NULL,
+};
+
+static const struct attribute_group kone_group = {
+	.attrs = kone_attrs,
+	.bin_attrs = kone_bin_attributes,
+};
+
+static const struct attribute_group *kone_groups[] = {
+	&kone_group,
+	NULL,
 };
 
 static int kone_init_kone_device_struct(struct usb_device *usb_dev,
@@ -891,8 +886,7 @@
 	kone_class = class_create(THIS_MODULE, "kone");
 	if (IS_ERR(kone_class))
 		return PTR_ERR(kone_class);
-	kone_class->dev_attrs = kone_attributes;
-	kone_class->dev_bin_attrs = kone_bin_attributes;
+	kone_class->dev_groups = kone_groups;
 
 	retval = hid_register_driver(&kone_driver);
 	if (retval)
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 6a48fa3..db4d8b6 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -156,7 +156,8 @@
 KONEPLUS_SYSFS_R(thingy, THINGY)
 
 #define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-{ \
+KONEPLUS_SYSFS_RW(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0660 }, \
 	.size = KONEPLUS_SIZE_ ## THINGY, \
 	.read = koneplus_sysfs_read_ ## thingy, \
@@ -164,28 +165,29 @@
 }
 
 #define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
-{ \
+KONEPLUS_SYSFS_R(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0440 }, \
 	.size = KONEPLUS_SIZE_ ## THINGY, \
 	.read = koneplus_sysfs_read_ ## thingy, \
 }
 
 #define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
-{ \
+KONEPLUS_SYSFS_W(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0220 }, \
 	.size = KONEPLUS_SIZE_ ## THINGY, \
 	.write = koneplus_sysfs_write_ ## thingy \
 }
-
-KONEPLUS_SYSFS_W(control, CONTROL)
-KONEPLUS_SYSFS_RW(info, INFO)
-KONEPLUS_SYSFS_W(talk, TALK)
-KONEPLUS_SYSFS_W(macro, MACRO)
-KONEPLUS_SYSFS_RW(sensor, SENSOR)
-KONEPLUS_SYSFS_RW(tcu, TCU)
-KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE)
-KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
-KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
+KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK);
+KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO);
+KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
+KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO);
+KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR);
+KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU);
+KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
+KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
 
 static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
@@ -225,6 +227,25 @@
 			KONEPLUS_COMMAND_PROFILE_BUTTONS);
 }
 
+#define PROFILE_ATTR(number)						\
+static struct bin_attribute bin_attr_profile##number##_settings = {	\
+	.attr = { .name = "profile##number##_settings", .mode = 0440 },	\
+	.size = KONEPLUS_SIZE_PROFILE_SETTINGS,				\
+	.read = koneplus_sysfs_read_profilex_settings,			\
+	.private = &profile_numbers[number-1],				\
+};									\
+static struct bin_attribute bin_attr_profile##number##_buttons = {	\
+	.attr = { .name = "profile##number##_buttons", .mode = 0440 },	\
+	.size = KONEPLUS_SIZE_PROFILE_BUTTONS,				\
+	.read = koneplus_sysfs_read_profilex_buttons,			\
+	.private = &profile_numbers[number-1],				\
+};
+PROFILE_ATTR(1);
+PROFILE_ATTR(2);
+PROFILE_ATTR(3);
+PROFILE_ATTR(4);
+PROFILE_ATTR(5);
+
 static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -274,6 +295,12 @@
 
 	return size;
 }
+static DEVICE_ATTR(actual_profile, 0660,
+		   koneplus_sysfs_show_actual_profile,
+		   koneplus_sysfs_set_actual_profile);
+static DEVICE_ATTR(startup_profile, 0660,
+		   koneplus_sysfs_show_actual_profile,
+		   koneplus_sysfs_set_actual_profile);
 
 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -293,90 +320,47 @@
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
+static DEVICE_ATTR(firmware_version, 0440,
+		   koneplus_sysfs_show_firmware_version, NULL);
 
-static struct device_attribute koneplus_attributes[] = {
-	__ATTR(actual_profile, 0660,
-			koneplus_sysfs_show_actual_profile,
-			koneplus_sysfs_set_actual_profile),
-	__ATTR(startup_profile, 0660,
-			koneplus_sysfs_show_actual_profile,
-			koneplus_sysfs_set_actual_profile),
-	__ATTR(firmware_version, 0440,
-			koneplus_sysfs_show_firmware_version, NULL),
-	__ATTR_NULL
+static struct attribute *koneplus_attrs[] = {
+	&dev_attr_actual_profile.attr,
+	&dev_attr_startup_profile.attr,
+	&dev_attr_firmware_version.attr,
+	NULL,
 };
 
-static struct bin_attribute koneplus_bin_attributes[] = {
-	KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
-	KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO),
-	KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK),
-	KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO),
-	KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR),
-	KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU),
-	KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
-	KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
-	KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
-	{
-		.attr = { .name = "profile1_settings", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
-		.read = koneplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[0]
-	},
-	{
-		.attr = { .name = "profile2_settings", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
-		.read = koneplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[1]
-	},
-	{
-		.attr = { .name = "profile3_settings", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
-		.read = koneplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[2]
-	},
-	{
-		.attr = { .name = "profile4_settings", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
-		.read = koneplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[3]
-	},
-	{
-		.attr = { .name = "profile5_settings", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_SETTINGS,
-		.read = koneplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[4]
-	},
-	{
-		.attr = { .name = "profile1_buttons", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
-		.read = koneplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[0]
-	},
-	{
-		.attr = { .name = "profile2_buttons", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
-		.read = koneplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[1]
-	},
-	{
-		.attr = { .name = "profile3_buttons", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
-		.read = koneplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[2]
-	},
-	{
-		.attr = { .name = "profile4_buttons", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
-		.read = koneplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[3]
-	},
-	{
-		.attr = { .name = "profile5_buttons", .mode = 0440 },
-		.size = KONEPLUS_SIZE_PROFILE_BUTTONS,
-		.read = koneplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[4]
-	},
-	__ATTR_NULL
+static struct bin_attribute *koneplus_bin_attributes[] = {
+	&bin_attr_control,
+	&bin_attr_talk,
+	&bin_attr_macro,
+	&bin_attr_tcu_image,
+	&bin_attr_info,
+	&bin_attr_sensor,
+	&bin_attr_tcu,
+	&bin_attr_profile_settings,
+	&bin_attr_profile_buttons,
+	&bin_attr_profile1_settings,
+	&bin_attr_profile2_settings,
+	&bin_attr_profile3_settings,
+	&bin_attr_profile4_settings,
+	&bin_attr_profile5_settings,
+	&bin_attr_profile1_buttons,
+	&bin_attr_profile2_buttons,
+	&bin_attr_profile3_buttons,
+	&bin_attr_profile4_buttons,
+	&bin_attr_profile5_buttons,
+	NULL,
+};
+
+static const struct attribute_group koneplus_group = {
+	.attrs = koneplus_attrs,
+	.bin_attrs = koneplus_bin_attributes,
+};
+
+static const struct attribute_group *koneplus_groups[] = {
+	&koneplus_group,
+	NULL,
 };
 
 static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
@@ -572,8 +556,7 @@
 	koneplus_class = class_create(THIS_MODULE, "koneplus");
 	if (IS_ERR(koneplus_class))
 		return PTR_ERR(koneplus_class);
-	koneplus_class->dev_attrs = koneplus_attributes;
-	koneplus_class->dev_bin_attrs = koneplus_bin_attributes;
+	koneplus_class->dev_groups = koneplus_groups;
 
 	retval = hid_register_driver(&koneplus_driver);
 	if (retval)
diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c
index c79d0b0..fa02b1f 100644
--- a/drivers/hid/hid-roccat-konepure.c
+++ b/drivers/hid/hid-roccat-konepure.c
@@ -94,7 +94,8 @@
 KONEPURE_SYSFS_R(thingy, THINGY)
 
 #define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-{ \
+KONEPURE_SYSFS_RW(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0660 }, \
 	.size = KONEPURE_SIZE_ ## THINGY, \
 	.read = konepure_sysfs_read_ ## thingy, \
@@ -102,44 +103,56 @@
 }
 
 #define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \
-{ \
+KONEPURE_SYSFS_R(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0440 }, \
 	.size = KONEPURE_SIZE_ ## THINGY, \
 	.read = konepure_sysfs_read_ ## thingy, \
 }
 
 #define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \
-{ \
+KONEPURE_SYSFS_W(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0220 }, \
 	.size = KONEPURE_SIZE_ ## THINGY, \
 	.write = konepure_sysfs_write_ ## thingy \
 }
 
-KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE)
-KONEPURE_SYSFS_W(control, CONTROL)
-KONEPURE_SYSFS_RW(info, INFO)
-KONEPURE_SYSFS_W(talk, TALK)
-KONEPURE_SYSFS_W(macro, MACRO)
-KONEPURE_SYSFS_RW(sensor, SENSOR)
-KONEPURE_SYSFS_RW(tcu, TCU)
-KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE)
-KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
-KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE);
+KONEPURE_BIN_ATTRIBUTE_RW(info, INFO);
+KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR);
+KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU);
+KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
+KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
+KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL);
+KONEPURE_BIN_ATTRIBUTE_W(talk, TALK);
+KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO);
+KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE);
 
-static struct bin_attribute konepure_bin_attributes[] = {
-	KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE),
-	KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL),
-	KONEPURE_BIN_ATTRIBUTE_RW(info, INFO),
-	KONEPURE_BIN_ATTRIBUTE_W(talk, TALK),
-	KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO),
-	KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR),
-	KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU),
-	KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
-	KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
-	KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
-	__ATTR_NULL
+static struct bin_attribute *konepure_bin_attributes[] = {
+	&bin_attr_actual_profile,
+	&bin_attr_info,
+	&bin_attr_sensor,
+	&bin_attr_tcu,
+	&bin_attr_profile_settings,
+	&bin_attr_profile_buttons,
+	&bin_attr_control,
+	&bin_attr_talk,
+	&bin_attr_macro,
+	&bin_attr_tcu_image,
+	NULL,
 };
 
+static const struct attribute_group konepure_group = {
+	.bin_attrs = konepure_bin_attributes,
+};
+
+static const struct attribute_group *konepure_groups[] = {
+	&konepure_group,
+	NULL,
+};
+
+
 static int konepure_init_konepure_device_struct(struct usb_device *usb_dev,
 		struct konepure_device *konepure)
 {
@@ -282,7 +295,7 @@
 	konepure_class = class_create(THIS_MODULE, "konepure");
 	if (IS_ERR(konepure_class))
 		return PTR_ERR(konepure_class);
-	konepure_class->dev_bin_attrs = konepure_bin_attributes;
+	konepure_class->dev_groups = konepure_groups;
 
 	retval = hid_register_driver(&konepure_driver);
 	if (retval)
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index b8b3778..8a0f299 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -197,31 +197,25 @@
 KOVAPLUS_SYSFS_R(thingy, THINGY)
 
 #define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-{ \
+KOVAPLUS_SYSFS_RW(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0660 }, \
 	.size = KOVAPLUS_SIZE_ ## THINGY, \
 	.read = kovaplus_sysfs_read_ ## thingy, \
 	.write = kovaplus_sysfs_write_ ## thingy \
 }
 
-#define KOVAPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \
-{ \
-	.attr = { .name = #thingy, .mode = 0440 }, \
-	.size = KOVAPLUS_SIZE_ ## THINGY, \
-	.read = kovaplus_sysfs_read_ ## thingy, \
-}
-
 #define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \
-{ \
+KOVAPLUS_SYSFS_W(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0220 }, \
 	.size = KOVAPLUS_SIZE_ ## THINGY, \
 	.write = kovaplus_sysfs_write_ ## thingy \
 }
-
-KOVAPLUS_SYSFS_W(control, CONTROL)
-KOVAPLUS_SYSFS_RW(info, INFO)
-KOVAPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
-KOVAPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL);
+KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO);
+KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
+KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
 
 static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
@@ -261,6 +255,25 @@
 			KOVAPLUS_COMMAND_PROFILE_BUTTONS);
 }
 
+#define PROFILE_ATTR(number)						\
+static struct bin_attribute bin_attr_profile##number##_settings = {	\
+	.attr = { .name = "profile##number##_settings", .mode = 0440 },	\
+	.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,				\
+	.read = kovaplus_sysfs_read_profilex_settings,			\
+	.private = &profile_numbers[number-1],				\
+};									\
+static struct bin_attribute bin_attr_profile##number##_buttons = {	\
+	.attr = { .name = "profile##number##_buttons", .mode = 0440 },	\
+	.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,				\
+	.read = kovaplus_sysfs_read_profilex_buttons,			\
+	.private = &profile_numbers[number-1],				\
+};
+PROFILE_ATTR(1);
+PROFILE_ATTR(2);
+PROFILE_ATTR(3);
+PROFILE_ATTR(4);
+PROFILE_ATTR(5);
+
 static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -310,6 +323,9 @@
 
 	return size;
 }
+static DEVICE_ATTR(actual_profile, 0660,
+		   kovaplus_sysfs_show_actual_profile,
+		   kovaplus_sysfs_set_actual_profile);
 
 static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -318,6 +334,7 @@
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi);
 }
+static DEVICE_ATTR(actual_cpi, 0440, kovaplus_sysfs_show_actual_cpi, NULL);
 
 static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -326,6 +343,8 @@
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity);
 }
+static DEVICE_ATTR(actual_sensitivity_x, 0440,
+		   kovaplus_sysfs_show_actual_sensitivity_x, NULL);
 
 static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -334,6 +353,8 @@
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity);
 }
+static DEVICE_ATTR(actual_sensitivity_y, 0440,
+		   kovaplus_sysfs_show_actual_sensitivity_y, NULL);
 
 static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -353,88 +374,44 @@
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
+static DEVICE_ATTR(firmware_version, 0440,
+		   kovaplus_sysfs_show_firmware_version, NULL);
 
-static struct device_attribute kovaplus_attributes[] = {
-	__ATTR(actual_cpi, 0440,
-		kovaplus_sysfs_show_actual_cpi, NULL),
-	__ATTR(firmware_version, 0440,
-		kovaplus_sysfs_show_firmware_version, NULL),
-	__ATTR(actual_profile, 0660,
-		kovaplus_sysfs_show_actual_profile,
-		kovaplus_sysfs_set_actual_profile),
-	__ATTR(actual_sensitivity_x, 0440,
-		kovaplus_sysfs_show_actual_sensitivity_x, NULL),
-	__ATTR(actual_sensitivity_y, 0440,
-		kovaplus_sysfs_show_actual_sensitivity_y, NULL),
-	__ATTR_NULL
+static struct attribute *kovaplus_attrs[] = {
+	&dev_attr_actual_cpi.attr,
+	&dev_attr_firmware_version.attr,
+	&dev_attr_actual_profile.attr,
+	&dev_attr_actual_sensitivity_x.attr,
+	&dev_attr_actual_sensitivity_y.attr,
+	NULL,
 };
 
-static struct bin_attribute kovaplus_bin_attributes[] = {
-	KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL),
-	KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO),
-	KOVAPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
-	KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
-	{
-		.attr = { .name = "profile1_settings", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
-		.read = kovaplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[0]
-	},
-	{
-		.attr = { .name = "profile2_settings", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
-		.read = kovaplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[1]
-	},
-	{
-		.attr = { .name = "profile3_settings", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
-		.read = kovaplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[2]
-	},
-	{
-		.attr = { .name = "profile4_settings", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
-		.read = kovaplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[3]
-	},
-	{
-		.attr = { .name = "profile5_settings", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,
-		.read = kovaplus_sysfs_read_profilex_settings,
-		.private = &profile_numbers[4]
-	},
-	{
-		.attr = { .name = "profile1_buttons", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
-		.read = kovaplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[0]
-	},
-	{
-		.attr = { .name = "profile2_buttons", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
-		.read = kovaplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[1]
-	},
-	{
-		.attr = { .name = "profile3_buttons", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
-		.read = kovaplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[2]
-	},
-	{
-		.attr = { .name = "profile4_buttons", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
-		.read = kovaplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[3]
-	},
-	{
-		.attr = { .name = "profile5_buttons", .mode = 0440 },
-		.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,
-		.read = kovaplus_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[4]
-	},
-	__ATTR_NULL
+static struct bin_attribute *kovaplus_bin_attributes[] = {
+	&bin_attr_control,
+	&bin_attr_info,
+	&bin_attr_profile_settings,
+	&bin_attr_profile_buttons,
+	&bin_attr_profile1_settings,
+	&bin_attr_profile2_settings,
+	&bin_attr_profile3_settings,
+	&bin_attr_profile4_settings,
+	&bin_attr_profile5_settings,
+	&bin_attr_profile1_buttons,
+	&bin_attr_profile2_buttons,
+	&bin_attr_profile3_buttons,
+	&bin_attr_profile4_buttons,
+	&bin_attr_profile5_buttons,
+	NULL,
+};
+
+static const struct attribute_group kovaplus_group = {
+	.attrs = kovaplus_attrs,
+	.bin_attrs = kovaplus_bin_attributes,
+};
+
+static const struct attribute_group *kovaplus_groups[] = {
+	&kovaplus_group,
+	NULL,
 };
 
 static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
@@ -662,8 +639,7 @@
 	kovaplus_class = class_create(THIS_MODULE, "kovaplus");
 	if (IS_ERR(kovaplus_class))
 		return PTR_ERR(kovaplus_class);
-	kovaplus_class->dev_attrs = kovaplus_attributes;
-	kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes;
+	kovaplus_class->dev_groups = kovaplus_groups;
 
 	retval = hid_register_driver(&kovaplus_driver);
 	if (retval)
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index d4f1e3b..5a6dbbe 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -156,7 +156,8 @@
 PYRA_SYSFS_R(thingy, THINGY)
 
 #define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-{ \
+PYRA_SYSFS_RW(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0660 }, \
 	.size = PYRA_SIZE_ ## THINGY, \
 	.read = pyra_sysfs_read_ ## thingy, \
@@ -164,24 +165,25 @@
 }
 
 #define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \
-{ \
+PYRA_SYSFS_R(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0440 }, \
 	.size = PYRA_SIZE_ ## THINGY, \
 	.read = pyra_sysfs_read_ ## thingy, \
 }
 
 #define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \
-{ \
+PYRA_SYSFS_W(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0220 }, \
 	.size = PYRA_SIZE_ ## THINGY, \
 	.write = pyra_sysfs_write_ ## thingy \
 }
 
-PYRA_SYSFS_W(control, CONTROL)
-PYRA_SYSFS_RW(info, INFO)
-PYRA_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
-PYRA_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
-PYRA_SYSFS_R(settings, SETTINGS)
+PYRA_BIN_ATTRIBUTE_W(control, CONTROL);
+PYRA_BIN_ATTRIBUTE_RW(info, INFO);
+PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS);
+PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS);
 
 static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
@@ -221,6 +223,25 @@
 			PYRA_COMMAND_PROFILE_BUTTONS);
 }
 
+#define PROFILE_ATTR(number)						\
+static struct bin_attribute bin_attr_profile##number##_settings = {	\
+	.attr = { .name = "profile##number##_settings", .mode = 0440 },	\
+	.size = PYRA_SIZE_PROFILE_SETTINGS,				\
+	.read = pyra_sysfs_read_profilex_settings,			\
+	.private = &profile_numbers[number-1],				\
+};									\
+static struct bin_attribute bin_attr_profile##number##_buttons = {	\
+	.attr = { .name = "profile##number##_buttons", .mode = 0440 },	\
+	.size = PYRA_SIZE_PROFILE_BUTTONS,				\
+	.read = pyra_sysfs_read_profilex_buttons,			\
+	.private = &profile_numbers[number-1],				\
+};
+PROFILE_ATTR(1);
+PROFILE_ATTR(2);
+PROFILE_ATTR(3);
+PROFILE_ATTR(4);
+PROFILE_ATTR(5);
+
 static ssize_t pyra_sysfs_write_settings(struct file *fp,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
@@ -258,6 +279,11 @@
 	return PYRA_SIZE_SETTINGS;
 }
 
+PYRA_SYSFS_R(settings, SETTINGS);
+static struct bin_attribute bin_attr_settings =
+	__BIN_ATTR(settings, (S_IWUSR | S_IRUGO),
+		   pyra_sysfs_read_settings, pyra_sysfs_write_settings,
+		   PYRA_SIZE_SETTINGS);
 
 static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -266,6 +292,7 @@
 			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
 	return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi);
 }
+static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL);
 
 static ssize_t pyra_sysfs_show_actual_profile(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -282,6 +309,8 @@
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", settings.startup_profile);
 }
+static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
+static DEVICE_ATTR(startup_profile, 0440, pyra_sysfs_show_actual_profile, NULL);
 
 static ssize_t pyra_sysfs_show_firmware_version(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -301,84 +330,44 @@
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version);
 }
+static DEVICE_ATTR(firmware_version, 0440, pyra_sysfs_show_firmware_version,
+		   NULL);
 
-static struct device_attribute pyra_attributes[] = {
-	__ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL),
-	__ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL),
-	__ATTR(firmware_version, 0440,
-			pyra_sysfs_show_firmware_version, NULL),
-	__ATTR(startup_profile, 0440,
-			pyra_sysfs_show_actual_profile, NULL),
-	__ATTR_NULL
+static struct attribute *pyra_attrs[] = {
+	&dev_attr_actual_cpi.attr,
+	&dev_attr_actual_profile.attr,
+	&dev_attr_firmware_version.attr,
+	&dev_attr_startup_profile.attr,
+	NULL,
 };
 
-static struct bin_attribute pyra_bin_attributes[] = {
-	PYRA_BIN_ATTRIBUTE_W(control, CONTROL),
-	PYRA_BIN_ATTRIBUTE_RW(info, INFO),
-	PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
-	PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
-	PYRA_BIN_ATTRIBUTE_RW(settings, SETTINGS),
-	{
-		.attr = { .name = "profile1_settings", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_SETTINGS,
-		.read = pyra_sysfs_read_profilex_settings,
-		.private = &profile_numbers[0]
-	},
-	{
-		.attr = { .name = "profile2_settings", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_SETTINGS,
-		.read = pyra_sysfs_read_profilex_settings,
-		.private = &profile_numbers[1]
-	},
-	{
-		.attr = { .name = "profile3_settings", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_SETTINGS,
-		.read = pyra_sysfs_read_profilex_settings,
-		.private = &profile_numbers[2]
-	},
-	{
-		.attr = { .name = "profile4_settings", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_SETTINGS,
-		.read = pyra_sysfs_read_profilex_settings,
-		.private = &profile_numbers[3]
-	},
-	{
-		.attr = { .name = "profile5_settings", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_SETTINGS,
-		.read = pyra_sysfs_read_profilex_settings,
-		.private = &profile_numbers[4]
-	},
-	{
-		.attr = { .name = "profile1_buttons", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_BUTTONS,
-		.read = pyra_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[0]
-	},
-	{
-		.attr = { .name = "profile2_buttons", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_BUTTONS,
-		.read = pyra_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[1]
-	},
-	{
-		.attr = { .name = "profile3_buttons", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_BUTTONS,
-		.read = pyra_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[2]
-	},
-	{
-		.attr = { .name = "profile4_buttons", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_BUTTONS,
-		.read = pyra_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[3]
-	},
-	{
-		.attr = { .name = "profile5_buttons", .mode = 0440 },
-		.size = PYRA_SIZE_PROFILE_BUTTONS,
-		.read = pyra_sysfs_read_profilex_buttons,
-		.private = &profile_numbers[4]
-	},
-	__ATTR_NULL
+static struct bin_attribute *pyra_bin_attributes[] = {
+	&bin_attr_control,
+	&bin_attr_info,
+	&bin_attr_profile_settings,
+	&bin_attr_profile_buttons,
+	&bin_attr_settings,
+	&bin_attr_profile1_settings,
+	&bin_attr_profile2_settings,
+	&bin_attr_profile3_settings,
+	&bin_attr_profile4_settings,
+	&bin_attr_profile5_settings,
+	&bin_attr_profile1_buttons,
+	&bin_attr_profile2_buttons,
+	&bin_attr_profile3_buttons,
+	&bin_attr_profile4_buttons,
+	&bin_attr_profile5_buttons,
+	NULL,
+};
+
+static const struct attribute_group pyra_group = {
+	.attrs = pyra_attrs,
+	.bin_attrs = pyra_bin_attributes,
+};
+
+static const struct attribute_group *pyra_groups[] = {
+	&pyra_group,
+	NULL,
 };
 
 static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
@@ -600,8 +589,7 @@
 	pyra_class = class_create(THIS_MODULE, "pyra");
 	if (IS_ERR(pyra_class))
 		return PTR_ERR(pyra_class);
-	pyra_class->dev_attrs = pyra_attributes;
-	pyra_class->dev_bin_attrs = pyra_bin_attributes;
+	pyra_class->dev_groups = pyra_groups;
 
 	retval = hid_register_driver(&pyra_driver);
 	if (retval)
diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c
index 31747a2..0332267 100644
--- a/drivers/hid/hid-roccat-savu.c
+++ b/drivers/hid/hid-roccat-savu.c
@@ -94,44 +94,48 @@
 SAVU_SYSFS_R(thingy, THINGY)
 
 #define SAVU_BIN_ATTRIBUTE_RW(thingy, THINGY) \
-{ \
+SAVU_SYSFS_RW(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0660 }, \
 	.size = SAVU_SIZE_ ## THINGY, \
 	.read = savu_sysfs_read_ ## thingy, \
 	.write = savu_sysfs_write_ ## thingy \
 }
 
-#define SAVU_BIN_ATTRIBUTE_R(thingy, THINGY) \
-{ \
-	.attr = { .name = #thingy, .mode = 0440 }, \
-	.size = SAVU_SIZE_ ## THINGY, \
-	.read = savu_sysfs_read_ ## thingy, \
-}
-
 #define SAVU_BIN_ATTRIBUTE_W(thingy, THINGY) \
-{ \
+SAVU_SYSFS_W(thingy, THINGY); \
+static struct bin_attribute bin_attr_##thingy = { \
 	.attr = { .name = #thingy, .mode = 0220 }, \
 	.size = SAVU_SIZE_ ## THINGY, \
 	.write = savu_sysfs_write_ ## thingy \
 }
 
-SAVU_SYSFS_W(control, CONTROL)
-SAVU_SYSFS_RW(profile, PROFILE)
-SAVU_SYSFS_RW(general, GENERAL)
-SAVU_SYSFS_RW(buttons, BUTTONS)
-SAVU_SYSFS_RW(macro, MACRO)
-SAVU_SYSFS_RW(info, INFO)
-SAVU_SYSFS_RW(sensor, SENSOR)
+SAVU_BIN_ATTRIBUTE_W(control, CONTROL);
+SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE);
+SAVU_BIN_ATTRIBUTE_RW(general, GENERAL);
+SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS);
+SAVU_BIN_ATTRIBUTE_RW(macro, MACRO);
+SAVU_BIN_ATTRIBUTE_RW(info, INFO);
+SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR);
 
-static struct bin_attribute savu_bin_attributes[] = {
-	SAVU_BIN_ATTRIBUTE_W(control, CONTROL),
-	SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE),
-	SAVU_BIN_ATTRIBUTE_RW(general, GENERAL),
-	SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS),
-	SAVU_BIN_ATTRIBUTE_RW(macro, MACRO),
-	SAVU_BIN_ATTRIBUTE_RW(info, INFO),
-	SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR),
-	__ATTR_NULL
+static struct bin_attribute *savu_bin_attributes[] = {
+	&bin_attr_control,
+	&bin_attr_profile,
+	&bin_attr_general,
+	&bin_attr_buttons,
+	&bin_attr_macro,
+	&bin_attr_info,
+	&bin_attr_sensor,
+	NULL,
+};
+
+static const struct attribute_group savu_group = {
+	.bin_attrs = savu_bin_attributes,
+};
+
+static const struct attribute_group *savu_groups[] = {
+	&savu_group,
+	NULL,
 };
 
 static int savu_init_savu_device_struct(struct usb_device *usb_dev,
@@ -294,7 +298,7 @@
 	savu_class = class_create(THIS_MODULE, "savu");
 	if (IS_ERR(savu_class))
 		return PTR_ERR(savu_class);
-	savu_class->dev_bin_attrs = savu_bin_attributes;
+	savu_class->dev_groups = savu_groups;
 
 	retval = hid_register_driver(&savu_driver);
 	if (retval)
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index da739d9..922a7fe 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -639,16 +639,18 @@
  * Gameport driver operations
  */
 
-static ssize_t gameport_driver_show_description(struct device_driver *drv, char *buf)
+static ssize_t description_show(struct device_driver *drv, char *buf)
 {
 	struct gameport_driver *driver = to_gameport_driver(drv);
 	return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
 }
+static DRIVER_ATTR_RO(description);
 
-static struct driver_attribute gameport_driver_attrs[] = {
-	__ATTR(description, S_IRUGO, gameport_driver_show_description, NULL),
-	__ATTR_NULL
+static struct attribute *gameport_driver_attrs[] = {
+	&driver_attr_description.attr,
+	NULL
 };
+ATTRIBUTE_GROUPS(gameport_driver);
 
 static int gameport_driver_probe(struct device *dev)
 {
@@ -749,7 +751,7 @@
 static struct bus_type gameport_bus = {
 	.name		= "gameport",
 	.dev_attrs	= gameport_device_attrs,
-	.drv_attrs	= gameport_driver_attrs,
+	.drv_groups	= gameport_driver_groups,
 	.match		= gameport_bus_match,
 	.probe		= gameport_driver_probe,
 	.remove		= gameport_driver_remove,
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 25fc597..2b56855 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -732,19 +732,20 @@
  * Serio driver operations
  */
 
-static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
+static ssize_t description_show(struct device_driver *drv, char *buf)
 {
 	struct serio_driver *driver = to_serio_driver(drv);
 	return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
 }
+static DRIVER_ATTR_RO(description);
 
-static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf)
+static ssize_t bind_mode_show(struct device_driver *drv, char *buf)
 {
 	struct serio_driver *serio_drv = to_serio_driver(drv);
 	return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto");
 }
 
-static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count)
+static ssize_t bind_mode_store(struct device_driver *drv, const char *buf, size_t count)
 {
 	struct serio_driver *serio_drv = to_serio_driver(drv);
 	int retval;
@@ -760,14 +761,14 @@
 
 	return retval;
 }
+static DRIVER_ATTR_RW(bind_mode);
 
-
-static struct driver_attribute serio_driver_attrs[] = {
-	__ATTR(description, S_IRUGO, serio_driver_show_description, NULL),
-	__ATTR(bind_mode, S_IWUSR | S_IRUGO,
-		serio_driver_show_bind_mode, serio_driver_set_bind_mode),
-	__ATTR_NULL
+static struct attribute *serio_driver_attrs[] = {
+	&driver_attr_description.attr,
+	&driver_attr_bind_mode.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(serio_driver);
 
 static int serio_driver_probe(struct device *dev)
 {
@@ -996,7 +997,7 @@
 static struct bus_type serio_bus = {
 	.name		= "serio",
 	.dev_attrs	= serio_device_attrs,
-	.drv_attrs	= serio_driver_attrs,
+	.drv_groups	= serio_driver_groups,
 	.match		= serio_bus_match,
 	.uevent		= serio_uevent,
 	.probe		= serio_driver_probe,
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index da30c5c..faf5054 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -37,8 +37,8 @@
 	/* nothing to do: the device is part of its parent's data structure */
 }
 
-static ssize_t _show_id(struct device *dev,
-			struct device_attribute *attr, char *buf)
+static ssize_t id_show(struct device *dev,
+		       struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -46,9 +46,10 @@
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->id);
 }
+static DEVICE_ATTR_RO(id);
 
-static ssize_t _show_nrbchan(struct device *dev,
-			     struct device_attribute *attr, char *buf)
+static ssize_t nrbchan_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -56,9 +57,10 @@
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->nrbchan);
 }
+static DEVICE_ATTR_RO(nrbchan);
 
-static ssize_t _show_d_protocols(struct device *dev,
-				 struct device_attribute *attr, char *buf)
+static ssize_t d_protocols_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -66,9 +68,10 @@
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->Dprotocols);
 }
+static DEVICE_ATTR_RO(d_protocols);
 
-static ssize_t _show_b_protocols(struct device *dev,
-				 struct device_attribute *attr, char *buf)
+static ssize_t b_protocols_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -76,9 +79,10 @@
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols());
 }
+static DEVICE_ATTR_RO(b_protocols);
 
-static ssize_t _show_protocol(struct device *dev,
-			      struct device_attribute *attr, char *buf)
+static ssize_t protocol_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 
@@ -86,17 +90,19 @@
 		return -ENODEV;
 	return sprintf(buf, "%d\n", mdev->D.protocol);
 }
+static DEVICE_ATTR_RO(protocol);
 
-static ssize_t _show_name(struct device *dev,
-			  struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
 {
 	strcpy(buf, dev_name(dev));
 	return strlen(buf);
 }
+static DEVICE_ATTR_RO(name);
 
 #if 0 /* hangs */
-static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t count)
+static ssize_t name_set(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
 {
 	int err = 0;
 	char *out = kmalloc(count + 1, GFP_KERNEL);
@@ -113,10 +119,11 @@
 
 	return (err < 0) ? err : count;
 }
+static DEVICE_ATTR_RW(name);
 #endif
 
-static ssize_t _show_channelmap(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t channelmap_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct mISDNdevice *mdev = dev_to_mISDN(dev);
 	char *bp = buf;
@@ -127,18 +134,19 @@
 
 	return bp - buf;
 }
+static DEVICE_ATTR_RO(channelmap);
 
-static struct device_attribute mISDN_dev_attrs[] = {
-	__ATTR(id,          S_IRUGO,         _show_id,          NULL),
-	__ATTR(d_protocols, S_IRUGO,         _show_d_protocols, NULL),
-	__ATTR(b_protocols, S_IRUGO,         _show_b_protocols, NULL),
-	__ATTR(protocol,    S_IRUGO,         _show_protocol,    NULL),
-	__ATTR(channelmap,  S_IRUGO,         _show_channelmap,  NULL),
-	__ATTR(nrbchan,     S_IRUGO,         _show_nrbchan,     NULL),
-	__ATTR(name,        S_IRUGO,         _show_name,        NULL),
-/*	__ATTR(name,        S_IRUGO | S_IWUSR, _show_name,      _set_name), */
-	{}
+static struct attribute *mISDN_attrs[] = {
+	&dev_attr_id.attr,
+	&dev_attr_d_protocols.attr,
+	&dev_attr_b_protocols.attr,
+	&dev_attr_protocol.attr,
+	&dev_attr_channelmap.attr,
+	&dev_attr_nrbchan.attr,
+	&dev_attr_name.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(mISDN);
 
 static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -162,7 +170,7 @@
 	.name = "mISDN",
 	.owner = THIS_MODULE,
 	.dev_uevent = mISDN_uevent,
-	.dev_attrs = mISDN_dev_attrs,
+	.dev_groups = mISDN_groups,
 	.dev_release = mISDN_dev_release,
 	.class_release = mISDN_class_release,
 };
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 4336e37..f37d63c 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -29,7 +29,7 @@
 		led_cdev->brightness = led_cdev->brightness_get(led_cdev);
 }
 
-static ssize_t led_brightness_show(struct device *dev,
+static ssize_t brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -40,7 +40,7 @@
 	return sprintf(buf, "%u\n", led_cdev->brightness);
 }
 
-static ssize_t led_brightness_store(struct device *dev,
+static ssize_t brightness_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t size)
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -57,6 +57,7 @@
 
 	return size;
 }
+static DEVICE_ATTR_RW(brightness);
 
 static ssize_t led_max_brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -65,14 +66,35 @@
 
 	return sprintf(buf, "%u\n", led_cdev->max_brightness);
 }
+static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL);
 
-static struct device_attribute led_class_attrs[] = {
-	__ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
-	__ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
 #ifdef CONFIG_LEDS_TRIGGERS
-	__ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
+static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
+static struct attribute *led_trigger_attrs[] = {
+	&dev_attr_trigger.attr,
+	NULL,
+};
+static const struct attribute_group led_trigger_group = {
+	.attrs = led_trigger_attrs,
+};
 #endif
-	__ATTR_NULL,
+
+static struct attribute *led_class_attrs[] = {
+	&dev_attr_brightness.attr,
+	&dev_attr_max_brightness.attr,
+	NULL,
+};
+
+static const struct attribute_group led_group = {
+	.attrs = led_class_attrs,
+};
+
+static const struct attribute_group *led_groups[] = {
+	&led_group,
+#ifdef CONFIG_LEDS_TRIGGERS
+	&led_trigger_group,
+#endif
+	NULL,
 };
 
 static void led_timer_function(unsigned long data)
@@ -258,7 +280,7 @@
 	if (IS_ERR(leds_class))
 		return PTR_ERR(leds_class);
 	leds_class->pm = &leds_class_dev_pm_ops;
-	leds_class->dev_attrs = led_class_attrs;
+	leds_class->dev_groups = led_groups;
 	return 0;
 }
 
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index c8859d6..b0f49b0 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -38,24 +38,25 @@
  *	sysfs stuff
  */
 
-static ssize_t show_index(struct device *cd,
-			 struct device_attribute *attr, char *buf)
+static ssize_t index_show(struct device *cd,
+			  struct device_attribute *attr, char *buf)
 {
 	struct video_device *vdev = to_video_device(cd);
 
 	return sprintf(buf, "%i\n", vdev->index);
 }
+static DEVICE_ATTR_RO(index);
 
-static ssize_t show_debug(struct device *cd,
-			 struct device_attribute *attr, char *buf)
+static ssize_t debug_show(struct device *cd,
+			  struct device_attribute *attr, char *buf)
 {
 	struct video_device *vdev = to_video_device(cd);
 
 	return sprintf(buf, "%i\n", vdev->debug);
 }
 
-static ssize_t set_debug(struct device *cd, struct device_attribute *attr,
-		   const char *buf, size_t len)
+static ssize_t debug_store(struct device *cd, struct device_attribute *attr,
+			  const char *buf, size_t len)
 {
 	struct video_device *vdev = to_video_device(cd);
 	int res = 0;
@@ -68,21 +69,24 @@
 	vdev->debug = value;
 	return len;
 }
+static DEVICE_ATTR_RW(debug);
 
-static ssize_t show_name(struct device *cd,
+static ssize_t name_show(struct device *cd,
 			 struct device_attribute *attr, char *buf)
 {
 	struct video_device *vdev = to_video_device(cd);
 
 	return sprintf(buf, "%.*s\n", (int)sizeof(vdev->name), vdev->name);
 }
+static DEVICE_ATTR_RO(name);
 
-static struct device_attribute video_device_attrs[] = {
-	__ATTR(name, S_IRUGO, show_name, NULL),
-	__ATTR(debug, 0644, show_debug, set_debug),
-	__ATTR(index, S_IRUGO, show_index, NULL),
-	__ATTR_NULL
+static struct attribute *video_device_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_debug.attr,
+	&dev_attr_index.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(video_device);
 
 /*
  *	Active devices
@@ -217,7 +221,7 @@
 
 static struct class video_class = {
 	.name = VIDEO_NAME,
-	.dev_attrs = video_device_attrs,
+	.dev_groups = video_device_groups,
 };
 
 struct video_device *video_devdata(struct file *file)
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
index f32550a..464419b 100644
--- a/drivers/misc/c2port/core.c
+++ b/drivers/misc/c2port/core.c
@@ -311,6 +311,7 @@
 
 	return sprintf(buf, "%s\n", c2dev->name);
 }
+static DEVICE_ATTR(name, 0444, c2port_show_name, NULL);
 
 static ssize_t c2port_show_flash_blocks_num(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -320,6 +321,7 @@
 
 	return sprintf(buf, "%d\n", ops->blocks_num);
 }
+static DEVICE_ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL);
 
 static ssize_t c2port_show_flash_block_size(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -329,6 +331,7 @@
 
 	return sprintf(buf, "%d\n", ops->block_size);
 }
+static DEVICE_ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL);
 
 static ssize_t c2port_show_flash_size(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -338,18 +341,18 @@
 
 	return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size);
 }
+static DEVICE_ATTR(flash_size, 0444, c2port_show_flash_size, NULL);
 
-static ssize_t c2port_show_access(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t access_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct c2port_device *c2dev = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", c2dev->access);
 }
 
-static ssize_t c2port_store_access(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
+static ssize_t access_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct c2port_device *c2dev = dev_get_drvdata(dev);
 	struct c2port_ops *ops = c2dev->ops;
@@ -375,6 +378,7 @@
 
 	return count;
 }
+static DEVICE_ATTR_RW(access);
 
 static ssize_t c2port_store_reset(struct device *dev,
 				struct device_attribute *attr,
@@ -395,6 +399,7 @@
 
 	return count;
 }
+static DEVICE_ATTR(reset, 0200, NULL, c2port_store_reset);
 
 static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf)
 {
@@ -431,6 +436,7 @@
 
 	return ret;
 }
+static DEVICE_ATTR(dev_id, 0444, c2port_show_dev_id, NULL);
 
 static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf)
 {
@@ -467,6 +473,7 @@
 
 	return ret;
 }
+static DEVICE_ATTR(rev_id, 0444, c2port_show_rev_id, NULL);
 
 static ssize_t c2port_show_flash_access(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -536,6 +543,8 @@
 
 	return count;
 }
+static DEVICE_ATTR(flash_access, 0644, c2port_show_flash_access,
+		   c2port_store_flash_access);
 
 static ssize_t __c2port_write_flash_erase(struct c2port_device *dev)
 {
@@ -616,6 +625,7 @@
 
 	return count;
 }
+static DEVICE_ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase);
 
 static ssize_t __c2port_read_flash_data(struct c2port_device *dev,
 				char *buffer, loff_t offset, size_t count)
@@ -846,35 +856,40 @@
 
 	return ret;
 }
+/* size is computed at run-time */
+static BIN_ATTR(flash_data, 0644, c2port_read_flash_data,
+		c2port_write_flash_data, 0);
 
 /*
  * Class attributes
  */
-
-static struct device_attribute c2port_attrs[] = {
-	__ATTR(name, 0444, c2port_show_name, NULL),
-	__ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL),
-	__ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL),
-	__ATTR(flash_size, 0444, c2port_show_flash_size, NULL),
-	__ATTR(access, 0644, c2port_show_access, c2port_store_access),
-	__ATTR(reset, 0200, NULL, c2port_store_reset),
-	__ATTR(dev_id, 0444, c2port_show_dev_id, NULL),
-	__ATTR(rev_id, 0444, c2port_show_rev_id, NULL),
-
-	__ATTR(flash_access, 0644, c2port_show_flash_access,
-					c2port_store_flash_access),
-	__ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase),
-	__ATTR_NULL,
+static struct attribute *c2port_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_flash_blocks_num.attr,
+	&dev_attr_flash_block_size.attr,
+	&dev_attr_flash_size.attr,
+	&dev_attr_access.attr,
+	&dev_attr_reset.attr,
+	&dev_attr_dev_id.attr,
+	&dev_attr_rev_id.attr,
+	&dev_attr_flash_access.attr,
+	&dev_attr_flash_erase.attr,
+	NULL,
 };
 
-static struct bin_attribute c2port_bin_attrs = {
-	.attr	= {
-		.name	= "flash_data",
-		.mode	= 0644
-	},
-	.read	= c2port_read_flash_data,
-	.write	= c2port_write_flash_data,
-	/* .size is computed at run-time */
+static struct bin_attribute *c2port_bin_attrs[] = {
+	&bin_attr_flash_data,
+	NULL,
+};
+
+static const struct attribute_group c2port_group = {
+	.attrs = c2port_attrs,
+	.bin_attrs = c2port_bin_attrs,
+};
+
+static const struct attribute_group *c2port_groups[] = {
+	&c2port_group,
+	NULL,
 };
 
 /*
@@ -907,6 +922,8 @@
 		goto error_idr_alloc;
 	c2dev->id = ret;
 
+	bin_attr_flash_data.size = ops->blocks_num * ops->block_size;
+
 	c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
 				   "c2port%d", c2dev->id);
 	if (unlikely(IS_ERR(c2dev->dev))) {
@@ -919,12 +936,6 @@
 	c2dev->ops = ops;
 	mutex_init(&c2dev->mutex);
 
-	/* Create binary file */
-	c2port_bin_attrs.size = ops->blocks_num * ops->block_size;
-	ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs);
-	if (unlikely(ret))
-		goto error_device_create_bin_file;
-
 	/* By default C2 port access is off */
 	c2dev->access = c2dev->flash_access = 0;
 	ops->access(c2dev, 0);
@@ -937,9 +948,6 @@
 
 	return c2dev;
 
-error_device_create_bin_file:
-	device_destroy(c2port_class, 0);
-
 error_device_create:
 	spin_lock_irq(&c2port_idr_lock);
 	idr_remove(&c2port_idr, c2dev->id);
@@ -959,7 +967,6 @@
 
 	dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name);
 
-	device_remove_bin_file(c2dev->dev, &c2port_bin_attrs);
 	spin_lock_irq(&c2port_idr_lock);
 	idr_remove(&c2port_idr, c2dev->id);
 	spin_unlock_irq(&c2port_idr_lock);
@@ -984,7 +991,7 @@
 		printk(KERN_ERR "c2port: failed to allocate class\n");
 		return PTR_ERR(c2port_class);
 	}
-	c2port_class->dev_attrs = c2port_attrs;
+	c2port_class->dev_groups = c2port_groups;
 
 	return 0;
 }
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 00e5fcac8..0e8df41 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -239,7 +239,7 @@
 	put_device(dev->parent);
 }
 
-static const struct attribute_group *enclosure_groups[];
+static const struct attribute_group *enclosure_component_groups[];
 
 /**
  * enclosure_component_register - add a particular component to an enclosure
@@ -282,7 +282,7 @@
 		dev_set_name(cdev, "%u", number);
 
 	cdev->release = enclosure_component_release;
-	cdev->groups = enclosure_groups;
+	cdev->groups = enclosure_component_groups;
 
 	err = device_register(cdev);
 	if (err) {
@@ -365,25 +365,26 @@
  * sysfs pieces below
  */
 
-static ssize_t enclosure_show_components(struct device *cdev,
-					 struct device_attribute *attr,
-					 char *buf)
+static ssize_t components_show(struct device *cdev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct enclosure_device *edev = to_enclosure_device(cdev);
 
 	return snprintf(buf, 40, "%d\n", edev->components);
 }
+static DEVICE_ATTR_RO(components);
 
-static struct device_attribute enclosure_attrs[] = {
-	__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
-	__ATTR_NULL
+static struct attribute *enclosure_class_attrs[] = {
+	&dev_attr_components.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(enclosure_class);
 
 static struct class enclosure_class = {
 	.name			= "enclosure",
 	.owner			= THIS_MODULE,
 	.dev_release		= enclosure_release,
-	.dev_attrs		= enclosure_attrs,
+	.dev_groups		= enclosure_class_groups,
 };
 
 static const char *const enclosure_status [] = {
@@ -536,15 +537,7 @@
 	&dev_attr_type.attr,
 	NULL
 };
-
-static struct attribute_group enclosure_group = {
-	.attrs = enclosure_component_attrs,
-};
-
-static const struct attribute_group *enclosure_groups[] = {
-	&enclosure_group,
-	NULL
-};
+ATTRIBUTE_GROUPS(enclosure_component);
 
 static int __init enclosure_init(void)
 {
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index a150a42..6d0282c 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -108,11 +108,13 @@
 
 	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
 }
+static DEVICE_ATTR_RO(modalias);
 
-static struct device_attribute mei_cl_dev_attrs[] = {
-	__ATTR_RO(modalias),
-	__ATTR_NULL,
+static struct attribute *mei_cl_dev_attrs[] = {
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(mei_cl_dev);
 
 static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -124,7 +126,7 @@
 
 static struct bus_type mei_cl_bus_type = {
 	.name		= "mei",
-	.dev_attrs	= mei_cl_dev_attrs,
+	.dev_groups	= mei_cl_dev_groups,
 	.match		= mei_cl_device_match,
 	.probe		= mei_cl_device_probe,
 	.remove		= mei_cl_device_remove,
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index fa32240..52b2adf6 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9478,7 +9478,7 @@
 	if (IS_ERR(plat_dev))
 		return NULL;
 
-	for (i = 0; attr_name(niu_parent_attributes[i]); i++) {
+	for (i = 0; niu_parent_attributes[i].attr.name; i++) {
 		int err = device_create_file(&plat_dev->dev,
 					     &niu_parent_attributes[i]);
 		if (err)
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index b13344c..6e02c95 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -693,11 +693,13 @@
 
 	return sprintf(buf, "wmi:%s\n", guid_string);
 }
+static DEVICE_ATTR_RO(modalias);
 
-static struct device_attribute wmi_dev_attrs[] = {
-	__ATTR_RO(modalias),
-	__ATTR_NULL
+static struct attribute *wmi_attrs[] = {
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(wmi);
 
 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -732,7 +734,7 @@
 	.name = "wmi",
 	.dev_release = wmi_dev_free,
 	.dev_uevent = wmi_dev_uevent,
-	.dev_attrs = wmi_dev_attrs,
+	.dev_groups = wmi_groups,
 };
 
 static int wmi_create_device(const struct guid_block *gblock,
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 7173e3a..2f07cd6 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -406,7 +406,7 @@
 		pr_err("failed to allocate class\n");
 		return PTR_ERR(pps_class);
 	}
-	pps_class->dev_attrs = pps_attrs;
+	pps_class->dev_groups = pps_groups;
 
 	err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
 	if (err < 0) {
diff --git a/drivers/pps/sysfs.c b/drivers/pps/sysfs.c
index ef0978c..aefb75d 100644
--- a/drivers/pps/sysfs.c
+++ b/drivers/pps/sysfs.c
@@ -29,8 +29,8 @@
  * Attribute functions
  */
 
-static ssize_t pps_show_assert(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t assert_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
@@ -41,9 +41,10 @@
 			(long long) pps->assert_tu.sec, pps->assert_tu.nsec,
 			pps->assert_sequence);
 }
+static DEVICE_ATTR_RO(assert);
 
-static ssize_t pps_show_clear(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t clear_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
@@ -54,45 +55,59 @@
 			(long long) pps->clear_tu.sec, pps->clear_tu.nsec,
 			pps->clear_sequence);
 }
+static DEVICE_ATTR_RO(clear);
 
-static ssize_t pps_show_mode(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%4x\n", pps->info.mode);
 }
+static DEVICE_ATTR_RO(mode);
 
-static ssize_t pps_show_echo(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t echo_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", !!pps->info.echo);
 }
+static DEVICE_ATTR_RO(echo);
 
-static ssize_t pps_show_name(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%s\n", pps->info.name);
 }
+static DEVICE_ATTR_RO(name);
 
-static ssize_t pps_show_path(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t path_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%s\n", pps->info.path);
 }
+static DEVICE_ATTR_RO(path);
 
-struct device_attribute pps_attrs[] = {
-	__ATTR(assert, S_IRUGO, pps_show_assert, NULL),
-	__ATTR(clear, S_IRUGO, pps_show_clear, NULL),
-	__ATTR(mode, S_IRUGO, pps_show_mode, NULL),
-	__ATTR(echo, S_IRUGO, pps_show_echo, NULL),
-	__ATTR(name, S_IRUGO, pps_show_name, NULL),
-	__ATTR(path, S_IRUGO, pps_show_path, NULL),
-	__ATTR_NULL,
+static struct attribute *pps_attrs[] = {
+	&dev_attr_assert.attr,
+	&dev_attr_clear.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_echo.attr,
+	&dev_attr_name.attr,
+	&dev_attr_path.attr,
+	NULL,
+};
+
+static const struct attribute_group pps_group = {
+	.attrs = pps_attrs,
+};
+
+const struct attribute_group *pps_groups[] = {
+	&pps_group,
+	NULL,
 };
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 4a8c388..a8319b2 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -330,7 +330,7 @@
 		goto no_region;
 	}
 
-	ptp_class->dev_attrs = ptp_dev_attrs;
+	ptp_class->dev_groups = ptp_groups;
 	pr_info("PTP clock support registered\n");
 	return 0;
 
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
index 69d3207..df03f2e 100644
--- a/drivers/ptp/ptp_private.h
+++ b/drivers/ptp/ptp_private.h
@@ -84,7 +84,7 @@
  * see ptp_sysfs.c
  */
 
-extern struct device_attribute ptp_dev_attrs[];
+extern const struct attribute_group *ptp_groups[];
 
 int ptp_cleanup_sysfs(struct ptp_clock *ptp);
 
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
index 2f93926..13ec531 100644
--- a/drivers/ptp/ptp_sysfs.c
+++ b/drivers/ptp/ptp_sysfs.c
@@ -27,36 +27,43 @@
 	struct ptp_clock *ptp = dev_get_drvdata(dev);
 	return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name);
 }
+static DEVICE_ATTR(clock_name, 0444, clock_name_show, NULL);
 
-#define PTP_SHOW_INT(name)						\
-static ssize_t name##_show(struct device *dev,				\
+#define PTP_SHOW_INT(name, var)						\
+static ssize_t var##_show(struct device *dev,				\
 			   struct device_attribute *attr, char *page)	\
 {									\
 	struct ptp_clock *ptp = dev_get_drvdata(dev);			\
-	return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->name);	\
-}
+	return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->var);	\
+}									\
+static DEVICE_ATTR(name, 0444, var##_show, NULL);
 
-PTP_SHOW_INT(max_adj);
-PTP_SHOW_INT(n_alarm);
-PTP_SHOW_INT(n_ext_ts);
-PTP_SHOW_INT(n_per_out);
-PTP_SHOW_INT(pps);
+PTP_SHOW_INT(max_adjustment, max_adj);
+PTP_SHOW_INT(n_alarms, n_alarm);
+PTP_SHOW_INT(n_external_timestamps, n_ext_ts);
+PTP_SHOW_INT(n_periodic_outputs, n_per_out);
+PTP_SHOW_INT(pps_available, pps);
 
-#define PTP_RO_ATTR(_var, _name) {				\
-	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
-	.show	= _var##_show,					\
-}
-
-struct device_attribute ptp_dev_attrs[] = {
-	PTP_RO_ATTR(clock_name,	clock_name),
-	PTP_RO_ATTR(max_adj,	max_adjustment),
-	PTP_RO_ATTR(n_alarm,	n_alarms),
-	PTP_RO_ATTR(n_ext_ts,	n_external_timestamps),
-	PTP_RO_ATTR(n_per_out,	n_periodic_outputs),
-	PTP_RO_ATTR(pps,	pps_available),
-	__ATTR_NULL,
+static struct attribute *ptp_attrs[] = {
+	&dev_attr_clock_name.attr,
+	&dev_attr_max_adjustment.attr,
+	&dev_attr_n_alarms.attr,
+	&dev_attr_n_external_timestamps.attr,
+	&dev_attr_n_periodic_outputs.attr,
+	&dev_attr_pps_available.attr,
+	NULL,
 };
 
+static const struct attribute_group ptp_group = {
+	.attrs = ptp_attrs,
+};
+
+const struct attribute_group *ptp_groups[] = {
+	&ptp_group,
+	NULL,
+};
+
+
 static ssize_t extts_enable_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 4b26f86..babd43b 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -25,15 +25,14 @@
  */
 
 static ssize_t
-rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr,
-		char *buf)
+name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
 }
+static DEVICE_ATTR_RO(name);
 
 static ssize_t
-rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr,
-		char *buf)
+date_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	ssize_t retval;
 	struct rtc_time tm;
@@ -46,10 +45,10 @@
 
 	return retval;
 }
+static DEVICE_ATTR_RO(date);
 
 static ssize_t
-rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr,
-		char *buf)
+time_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	ssize_t retval;
 	struct rtc_time tm;
@@ -62,10 +61,10 @@
 
 	return retval;
 }
+static DEVICE_ATTR_RO(time);
 
 static ssize_t
-rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr,
-		char *buf)
+since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	ssize_t retval;
 	struct rtc_time tm;
@@ -79,16 +78,16 @@
 
 	return retval;
 }
+static DEVICE_ATTR_RO(since_epoch);
 
 static ssize_t
-rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr,
-		char *buf)
+max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq);
 }
 
 static ssize_t
-rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
+max_user_freq_store(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t n)
 {
 	struct rtc_device *rtc = to_rtc_device(dev);
@@ -101,6 +100,7 @@
 
 	return n;
 }
+static DEVICE_ATTR_RW(max_user_freq);
 
 /**
  * rtc_sysfs_show_hctosys - indicate if the given RTC set the system time
@@ -109,8 +109,7 @@
  * boot or resume event.
  */
 static ssize_t
-rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr,
-		char *buf)
+hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 #ifdef CONFIG_RTC_HCTOSYS_DEVICE
 	if (rtc_hctosys_ret == 0 &&
@@ -121,17 +120,18 @@
 #endif
 		return sprintf(buf, "0\n");
 }
+static DEVICE_ATTR_RO(hctosys);
 
-static struct device_attribute rtc_attrs[] = {
-	__ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL),
-	__ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL),
-	__ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL),
-	__ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL),
-	__ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq,
-			rtc_sysfs_set_max_user_freq),
-	__ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL),
-	{ },
+static struct attribute *rtc_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_date.attr,
+	&dev_attr_time.attr,
+	&dev_attr_since_epoch.attr,
+	&dev_attr_max_user_freq.attr,
+	&dev_attr_hctosys.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(rtc);
 
 static ssize_t
 rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
@@ -261,5 +261,5 @@
 
 void __init rtc_sysfs_init(struct class *rtc_class)
 {
-	rtc_class->dev_attrs = rtc_attrs;
+	rtc_class->dev_groups = rtc_groups;
 }
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index 9d86947..e1d9a4c 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -107,6 +107,7 @@
 						   class_dev);
 	return sprintf(buf, "%s\n", ould->odi.osdname);
 }
+static DEVICE_ATTR_RO(osdname);
 
 static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
 			    char *buf)
@@ -117,17 +118,19 @@
 	memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
 	return ould->odi.systemid_len;
 }
+static DEVICE_ATTR_RO(systemid);
 
-static struct device_attribute osd_uld_attrs[] = {
-	__ATTR(osdname, S_IRUGO, osdname_show, NULL),
-	__ATTR(systemid, S_IRUGO, systemid_show, NULL),
-	__ATTR_NULL,
+static struct attribute *osd_uld_attrs[] = {
+	&dev_attr_osdname.attr,
+	&dev_attr_systemid.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(osd_uld);
 
 static struct class osd_uld_class = {
 	.owner		= THIS_MODULE,
 	.name		= "scsi_osd",
-	.dev_attrs	= osd_uld_attrs,
+	.dev_groups	= osd_uld_groups,
 };
 
 /*
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index f4a197b..6d50e30 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -262,7 +262,7 @@
 
 /* sysfs attribute files */
 
-static ssize_t show_max_read_buffer_kb(struct device *csdev,
+static ssize_t max_read_buffer_kb_show(struct device *csdev,
 				       struct device_attribute *attr, char *buf)
 {
 	unsigned int minor = MINOR(csdev->devt);
@@ -283,7 +283,7 @@
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_max_read_buffer_kb(struct device *csdev,
+static ssize_t max_read_buffer_kb_store(struct device *csdev,
 					struct device_attribute *attr,
 					const char *buf, size_t count)
 {
@@ -314,8 +314,9 @@
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(max_read_buffer_kb);
 
-static ssize_t show_read_buffer_kb(struct device *csdev,
+static ssize_t read_buffer_kb_show(struct device *csdev,
 				   struct device_attribute *attr, char *buf)
 {
 	unsigned int minor = MINOR(csdev->devt);
@@ -336,7 +337,7 @@
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_read_buffer_kb(struct device *csdev,
+static ssize_t read_buffer_kb_store(struct device *csdev,
 				    struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
@@ -367,8 +368,9 @@
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(read_buffer_kb);
 
-static ssize_t show_max_write_buffer_kb(struct device *csdev,
+static ssize_t max_write_buffer_kb_show(struct device *csdev,
 					struct device_attribute *attr,
 					char *buf)
 {
@@ -390,7 +392,7 @@
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_max_write_buffer_kb(struct device *csdev,
+static ssize_t max_write_buffer_kb_store(struct device *csdev,
 					 struct device_attribute *attr,
 					 const char *buf, size_t count)
 {
@@ -421,8 +423,9 @@
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(max_write_buffer_kb);
 
-static ssize_t show_write_buffer_kb(struct device *csdev,
+static ssize_t write_buffer_kb_show(struct device *csdev,
 				    struct device_attribute *attr, char *buf)
 {
 	unsigned int minor = MINOR(csdev->devt);
@@ -443,7 +446,7 @@
 	return snprintf(buf, PAGE_SIZE, "%i\n", size);
 }
 
-static ssize_t store_write_buffer_kb(struct device *csdev,
+static ssize_t write_buffer_kb_store(struct device *csdev,
 				     struct device_attribute *attr,
 				     const char *buf, size_t count)
 {
@@ -474,18 +477,16 @@
 
 	return err ? err : count;
 }
+static DEVICE_ATTR_RW(write_buffer_kb);
 
-static struct device_attribute comedi_dev_attrs[] = {
-	__ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR,
-		show_max_read_buffer_kb, store_max_read_buffer_kb),
-	__ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
-		show_read_buffer_kb, store_read_buffer_kb),
-	__ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR,
-		show_max_write_buffer_kb, store_max_write_buffer_kb),
-	__ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
-		show_write_buffer_kb, store_write_buffer_kb),
-	__ATTR_NULL
+static struct attribute *comedi_dev_attrs[] = {
+	&dev_attr_max_read_buffer_kb.attr,
+	&dev_attr_read_buffer_kb.attr,
+	&dev_attr_max_write_buffer_kb.attr,
+	&dev_attr_write_buffer_kb.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(comedi_dev);
 
 static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
 					  unsigned mask, unsigned bits)
@@ -2564,7 +2565,7 @@
 		return PTR_ERR(comedi_class);
 	}
 
-	comedi_class->dev_attrs = comedi_dev_attrs;
+	comedi_class->dev_groups = comedi_dev_groups;
 
 	/* XXX requires /proc interface */
 	comedi_proc_init();
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 8abe78c..ba47563 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -223,38 +223,42 @@
 	.default_attrs	= portio_attrs,
 };
 
-static ssize_t show_name(struct device *dev,
+static ssize_t name_show(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
 	return sprintf(buf, "%s\n", idev->info->name);
 }
+static DEVICE_ATTR_RO(name);
 
-static ssize_t show_version(struct device *dev,
+static ssize_t version_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
 	return sprintf(buf, "%s\n", idev->info->version);
 }
+static DEVICE_ATTR_RO(version);
 
-static ssize_t show_event(struct device *dev,
+static ssize_t event_show(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
 }
+static DEVICE_ATTR_RO(event);
 
-static struct device_attribute uio_class_attributes[] = {
-	__ATTR(name, S_IRUGO, show_name, NULL),
-	__ATTR(version, S_IRUGO, show_version, NULL),
-	__ATTR(event, S_IRUGO, show_event, NULL),
-	{}
+static struct attribute *uio_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_version.attr,
+	&dev_attr_event.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(uio);
 
 /* UIO class infrastructure */
 static struct class uio_class = {
 	.name = "uio",
-	.dev_attrs = uio_class_attributes,
+	.dev_groups = uio_groups,
 };
 
 /*
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 0ce51f2..6335490 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -121,7 +121,7 @@
 	return retval;
 }
 
-static ssize_t store_new_id(struct device_driver *driver,
+static ssize_t new_id_store(struct device_driver *driver,
 			    const char *buf, size_t count)
 {
 	struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
@@ -134,17 +134,19 @@
 	return retval;
 }
 
-static ssize_t show_dynids(struct device_driver *driver, char *buf)
+static ssize_t new_id_show(struct device_driver *driver, char *buf)
 {
 	struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
 
 	return usb_show_dynids(&usb_drv->dynids, buf);
 }
+static DRIVER_ATTR_RW(new_id);
 
-static struct driver_attribute drv_attrs[] = {
-	__ATTR(new_id, S_IRUGO | S_IWUSR, show_dynids, store_new_id),
-	__ATTR_NULL,
+static struct attribute *usb_serial_drv_attrs[] = {
+	&driver_attr_new_id.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(usb_serial_drv);
 
 static void free_dynids(struct usb_serial_driver *drv)
 {
@@ -163,7 +165,7 @@
 	.match =	usb_serial_device_match,
 	.probe =	usb_serial_device_probe,
 	.remove =	usb_serial_device_remove,
-	.drv_attrs = 	drv_attrs,
+	.drv_groups = 	usb_serial_drv_groups,
 };
 
 int usb_serial_bus_register(struct usb_serial_driver *driver)
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 3fccb6d..94a403a 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -103,16 +103,16 @@
 	sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness");
 }
 
-static ssize_t backlight_show_power(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
 	return sprintf(buf, "%d\n", bd->props.power);
 }
 
-static ssize_t backlight_store_power(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	int rc;
 	struct backlight_device *bd = to_backlight_device(dev);
@@ -136,8 +136,9 @@
 
 	return rc;
 }
+static DEVICE_ATTR_RW(bl_power);
 
-static ssize_t backlight_show_brightness(struct device *dev,
+static ssize_t brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
@@ -145,7 +146,7 @@
 	return sprintf(buf, "%d\n", bd->props.brightness);
 }
 
-static ssize_t backlight_store_brightness(struct device *dev,
+static ssize_t brightness_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int rc;
@@ -175,24 +176,27 @@
 
 	return rc;
 }
+static DEVICE_ATTR_RW(brightness);
 
-static ssize_t backlight_show_type(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
 	return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
 }
+static DEVICE_ATTR_RO(type);
 
-static ssize_t backlight_show_max_brightness(struct device *dev,
+static ssize_t max_brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
 	return sprintf(buf, "%d\n", bd->props.max_brightness);
 }
+static DEVICE_ATTR_RO(max_brightness);
 
-static ssize_t backlight_show_actual_brightness(struct device *dev,
+static ssize_t actual_brightness_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	int rc = -ENXIO;
@@ -205,6 +209,7 @@
 
 	return rc;
 }
+static DEVICE_ATTR_RO(actual_brightness);
 
 static struct class *backlight_class;
 
@@ -247,16 +252,15 @@
 	kfree(bd);
 }
 
-static struct device_attribute bl_device_attributes[] = {
-	__ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),
-	__ATTR(brightness, 0644, backlight_show_brightness,
-		     backlight_store_brightness),
-	__ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
-		     NULL),
-	__ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
-	__ATTR(type, 0444, backlight_show_type, NULL),
-	__ATTR_NULL,
+static struct attribute *bl_device_attrs[] = {
+	&dev_attr_bl_power.attr,
+	&dev_attr_brightness.attr,
+	&dev_attr_actual_brightness.attr,
+	&dev_attr_max_brightness.attr,
+	&dev_attr_type.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(bl_device);
 
 /**
  * backlight_force_update - tell the backlight subsystem that hardware state
@@ -493,7 +497,7 @@
 		return PTR_ERR(backlight_class);
 	}
 
-	backlight_class->dev_attrs = bl_device_attributes;
+	backlight_class->dev_groups = bl_device_groups;
 	backlight_class->pm = &backlight_class_dev_pm_ops;
 	return 0;
 }
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 41964a7..93cf15e 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -89,7 +89,7 @@
 }
 #endif /* CONFIG_FB */
 
-static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
+static ssize_t lcd_power_show(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
 	int rc;
@@ -105,7 +105,7 @@
 	return rc;
 }
 
-static ssize_t lcd_store_power(struct device *dev,
+static ssize_t lcd_power_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int rc;
@@ -128,8 +128,9 @@
 
 	return rc;
 }
+static DEVICE_ATTR_RW(lcd_power);
 
-static ssize_t lcd_show_contrast(struct device *dev,
+static ssize_t contrast_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	int rc = -ENXIO;
@@ -143,7 +144,7 @@
 	return rc;
 }
 
-static ssize_t lcd_store_contrast(struct device *dev,
+static ssize_t contrast_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int rc;
@@ -166,14 +167,16 @@
 
 	return rc;
 }
+static DEVICE_ATTR_RW(contrast);
 
-static ssize_t lcd_show_max_contrast(struct device *dev,
+static ssize_t max_contrast_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct lcd_device *ld = to_lcd_device(dev);
 
 	return sprintf(buf, "%d\n", ld->props.max_contrast);
 }
+static DEVICE_ATTR_RO(max_contrast);
 
 static struct class *lcd_class;
 
@@ -183,12 +186,13 @@
 	kfree(ld);
 }
 
-static struct device_attribute lcd_device_attributes[] = {
-	__ATTR(lcd_power, 0644, lcd_show_power, lcd_store_power),
-	__ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast),
-	__ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL),
-	__ATTR_NULL,
+static struct attribute *lcd_device_attrs[] = {
+	&dev_attr_lcd_power.attr,
+	&dev_attr_contrast.attr,
+	&dev_attr_max_contrast.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(lcd_device);
 
 /**
  * lcd_device_register - register a new object of lcd_device class.
@@ -344,7 +348,7 @@
 		return PTR_ERR(lcd_class);
 	}
 
-	lcd_class->dev_attrs = lcd_device_attributes;
+	lcd_class->dev_groups = lcd_device_groups;
 	return 0;
 }
 
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c
index cb8a8e5..7dfa0e1 100644
--- a/drivers/w1/slaves/w1_ds2408.c
+++ b/drivers/w1/slaves/w1_ds2408.c
@@ -72,10 +72,9 @@
 	return 1;
 }
 
-static ssize_t w1_f29_read_state(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t state_read(struct file *filp, struct kobject *kobj,
+			  struct bin_attribute *bin_attr, char *buf, loff_t off,
+			  size_t count)
 {
 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
@@ -85,10 +84,9 @@
 	return _read_reg(kobj_to_w1_slave(kobj), W1_F29_REG_LOGIG_STATE, buf);
 }
 
-static ssize_t w1_f29_read_output(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t output_read(struct file *filp, struct kobject *kobj,
+			   struct bin_attribute *bin_attr, char *buf,
+			   loff_t off, size_t count)
 {
 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
@@ -99,10 +97,9 @@
 					 W1_F29_REG_OUTPUT_LATCH_STATE, buf);
 }
 
-static ssize_t w1_f29_read_activity(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t activity_read(struct file *filp, struct kobject *kobj,
+			     struct bin_attribute *bin_attr, char *buf,
+			     loff_t off, size_t count)
 {
 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
@@ -113,10 +110,9 @@
 					 W1_F29_REG_ACTIVITY_LATCH_STATE, buf);
 }
 
-static ssize_t w1_f29_read_cond_search_mask(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
+				     struct bin_attribute *bin_attr, char *buf,
+				     loff_t off, size_t count)
 {
 	dev_dbg(&kobj_to_w1_slave(kobj)->dev,
 		"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
@@ -127,10 +123,10 @@
 		W1_F29_REG_COND_SEARCH_SELECT_MASK, buf);
 }
 
-static ssize_t w1_f29_read_cond_search_polarity(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t cond_search_polarity_read(struct file *filp,
+					 struct kobject *kobj,
+					 struct bin_attribute *bin_attr,
+					 char *buf, loff_t off, size_t count)
 {
 	if (count != 1 || off != 0)
 		return -EFAULT;
@@ -138,10 +134,9 @@
 		W1_F29_REG_COND_SEARCH_POL_SELECT, buf);
 }
 
-static ssize_t w1_f29_read_status_control(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
+				   struct bin_attribute *bin_attr, char *buf,
+				   loff_t off, size_t count)
 {
 	if (count != 1 || off != 0)
 		return -EFAULT;
@@ -149,13 +144,9 @@
 		W1_F29_REG_CONTROL_AND_STATUS, buf);
 }
 
-
-
-
-static ssize_t w1_f29_write_output(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t output_write(struct file *filp, struct kobject *kobj,
+			    struct bin_attribute *bin_attr, char *buf,
+			    loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	u8 w1_buf[3];
@@ -224,10 +215,9 @@
 /**
  * Writing to the activity file resets the activity latches.
  */
-static ssize_t w1_f29_write_activity(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t activity_write(struct file *filp, struct kobject *kobj,
+			      struct bin_attribute *bin_attr, char *buf,
+			      loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	unsigned int retries = W1_F29_RETRIES;
@@ -255,13 +245,9 @@
 	return -EIO;
 }
 
-static ssize_t w1_f29_write_status_control(
-	struct file *filp,
-	struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf,
-	loff_t off,
-	size_t count)
+static ssize_t status_control_write(struct file *filp, struct kobject *kobj,
+				    struct bin_attribute *bin_attr, char *buf,
+				    loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	u8 w1_buf[4];
@@ -330,91 +316,35 @@
 	return res;
 }
 
-static struct bin_attribute w1_f29_sysfs_bin_files[] = {
-	{
-		.attr =	{
-			.name = "state",
-			.mode = S_IRUGO,
-		},
-		.size = 1,
-		.read = w1_f29_read_state,
-	},
-	{
-		.attr =	{
-			.name = "output",
-			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
-		},
-		.size = 1,
-		.read = w1_f29_read_output,
-		.write = w1_f29_write_output,
-	},
-	{
-		.attr =	{
-			.name = "activity",
-			.mode = S_IRUGO,
-		},
-		.size = 1,
-		.read = w1_f29_read_activity,
-		.write = w1_f29_write_activity,
-	},
-	{
-		.attr =	{
-			.name = "cond_search_mask",
-			.mode = S_IRUGO,
-		},
-		.size = 1,
-		.read = w1_f29_read_cond_search_mask,
-	},
-	{
-		.attr =	{
-			.name = "cond_search_polarity",
-			.mode = S_IRUGO,
-		},
-		.size = 1,
-		.read = w1_f29_read_cond_search_polarity,
-	},
-	{
-		.attr =	{
-			.name = "status_control",
-			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
-		},
-		.size = 1,
-		.read = w1_f29_read_status_control,
-		.write = w1_f29_write_status_control,
-	}
+static BIN_ATTR_RO(state, 1);
+static BIN_ATTR_RW(output, 1);
+static BIN_ATTR_RW(activity, 1);
+static BIN_ATTR_RO(cond_search_mask, 1);
+static BIN_ATTR_RO(cond_search_polarity, 1);
+static BIN_ATTR_RW(status_control, 1);
+
+static struct bin_attribute *w1_f29_bin_attrs[] = {
+	&bin_attr_state,
+	&bin_attr_output,
+	&bin_attr_activity,
+	&bin_attr_cond_search_mask,
+	&bin_attr_cond_search_polarity,
+	&bin_attr_status_control,
+	NULL,
 };
 
-static int w1_f29_add_slave(struct w1_slave *sl)
-{
-	int err = 0;
-	int i;
+static const struct attribute_group w1_f29_group = {
+	.bin_attrs = w1_f29_bin_attrs,
+};
 
-	err = w1_f29_disable_test_mode(sl);
-	if (err)
-		return err;
-
-	for (i = 0; i < ARRAY_SIZE(w1_f29_sysfs_bin_files) && !err; ++i)
-		err = sysfs_create_bin_file(
-			&sl->dev.kobj,
-			&(w1_f29_sysfs_bin_files[i]));
-	if (err)
-		while (--i >= 0)
-			sysfs_remove_bin_file(&sl->dev.kobj,
-				&(w1_f29_sysfs_bin_files[i]));
-	return err;
-}
-
-static void w1_f29_remove_slave(struct w1_slave *sl)
-{
-	int i;
-	for (i = ARRAY_SIZE(w1_f29_sysfs_bin_files) - 1; i >= 0; --i)
-		sysfs_remove_bin_file(&sl->dev.kobj,
-			&(w1_f29_sysfs_bin_files[i]));
-}
+static const struct attribute_group *w1_f29_groups[] = {
+	&w1_f29_group,
+	NULL,
+};
 
 static struct w1_family_ops w1_f29_fops = {
-	.add_slave      = w1_f29_add_slave,
-	.remove_slave   = w1_f29_remove_slave,
+	.add_slave      = w1_f29_disable_test_mode,
+	.groups		= w1_f29_groups,
 };
 
 static struct w1_family w1_family_29 = {
diff --git a/drivers/w1/slaves/w1_ds2413.c b/drivers/w1/slaves/w1_ds2413.c
index 8593777..ee28fc1 100644
--- a/drivers/w1/slaves/w1_ds2413.c
+++ b/drivers/w1/slaves/w1_ds2413.c
@@ -30,10 +30,9 @@
 #define W1_F3A_FUNC_PIO_ACCESS_WRITE       0x5A
 #define W1_F3A_SUCCESS_CONFIRM_BYTE        0xAA
 
-static ssize_t w1_f3a_read_state(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static ssize_t state_read(struct file *filp, struct kobject *kobj,
+			  struct bin_attribute *bin_attr, char *buf, loff_t off,
+			  size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	dev_dbg(&sl->dev,
@@ -66,10 +65,11 @@
 		return 1;
 }
 
-static ssize_t w1_f3a_write_output(
-	struct file *filp, struct kobject *kobj,
-	struct bin_attribute *bin_attr,
-	char *buf, loff_t off, size_t count)
+static BIN_ATTR_RO(state, 1);
+
+static ssize_t output_write(struct file *filp, struct kobject *kobj,
+			    struct bin_attribute *bin_attr, char *buf,
+			    loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	u8 w1_buf[3];
@@ -110,53 +110,25 @@
 	return -EIO;
 }
 
-#define NB_SYSFS_BIN_FILES 2
-static struct bin_attribute w1_f3a_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
-	{
-		.attr = {
-			.name = "state",
-			.mode = S_IRUGO,
-		},
-		.size = 1,
-		.read = w1_f3a_read_state,
-	},
-	{
-		.attr = {
-			.name = "output",
-			.mode = S_IRUGO | S_IWUSR | S_IWGRP,
-		},
-		.size = 1,
-		.write = w1_f3a_write_output,
-	}
+static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
+
+static struct bin_attribute *w1_f3a_bin_attrs[] = {
+	&bin_attr_state,
+	&bin_attr_output,
+	NULL,
 };
 
-static int w1_f3a_add_slave(struct w1_slave *sl)
-{
-	int err = 0;
-	int i;
+static const struct attribute_group w1_f3a_group = {
+	.bin_attrs = w1_f3a_bin_attrs,
+};
 
-	for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
-		err = sysfs_create_bin_file(
-			&sl->dev.kobj,
-			&(w1_f3a_sysfs_bin_files[i]));
-	if (err)
-		while (--i >= 0)
-			sysfs_remove_bin_file(&sl->dev.kobj,
-				&(w1_f3a_sysfs_bin_files[i]));
-	return err;
-}
-
-static void w1_f3a_remove_slave(struct w1_slave *sl)
-{
-	int i;
-	for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
-		sysfs_remove_bin_file(&sl->dev.kobj,
-			&(w1_f3a_sysfs_bin_files[i]));
-}
+static const struct attribute_group *w1_f3a_groups[] = {
+	&w1_f3a_group,
+	NULL,
+};
 
 static struct w1_family_ops w1_f3a_fops = {
-	.add_slave      = w1_f3a_add_slave,
-	.remove_slave   = w1_f3a_remove_slave,
+	.groups		= w1_f3a_groups,
 };
 
 static struct w1_family w1_family_3a = {
diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c
index 7f86aec..7e41b7d 100644
--- a/drivers/w1/slaves/w1_ds2423.c
+++ b/drivers/w1/slaves/w1_ds2423.c
@@ -40,14 +40,8 @@
 #define COUNTER_COUNT 4
 #define READ_BYTE_COUNT 42
 
-static ssize_t w1_counter_read(struct device *device,
-	struct device_attribute *attr, char *buf);
-
-static struct device_attribute w1_counter_attr =
-	__ATTR(w1_slave, S_IRUGO, w1_counter_read, NULL);
-
-static ssize_t w1_counter_read(struct device *device,
-	struct device_attribute *attr, char *out_buf)
+static ssize_t w1_slave_show(struct device *device,
+			     struct device_attribute *attr, char *out_buf)
 {
 	struct w1_slave *sl = dev_to_w1_slave(device);
 	struct w1_master *dev = sl->master;
@@ -128,19 +122,16 @@
 	return PAGE_SIZE - c;
 }
 
-static int w1_f1d_add_slave(struct w1_slave *sl)
-{
-	return device_create_file(&sl->dev, &w1_counter_attr);
-}
+static DEVICE_ATTR_RO(w1_slave);
 
-static void w1_f1d_remove_slave(struct w1_slave *sl)
-{
-	device_remove_file(&sl->dev, &w1_counter_attr);
-}
+static struct attribute *w1_f1d_attrs[] = {
+	&dev_attr_w1_slave.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(w1_f1d);
 
 static struct w1_family_ops w1_f1d_fops = {
-	.add_slave      = w1_f1d_add_slave,
-	.remove_slave   = w1_f1d_remove_slave,
+	.groups		= w1_f1d_groups,
 };
 
 static struct w1_family w1_family_1d = {
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c
index cef8605..9c4ff9d 100644
--- a/drivers/w1/slaves/w1_ds2431.c
+++ b/drivers/w1/slaves/w1_ds2431.c
@@ -96,9 +96,9 @@
 	return -1;
 }
 
-static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj,
-			       struct bin_attribute *bin_attr,
-			       char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
+			   struct bin_attribute *bin_attr, char *buf,
+			   loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	int todo = count;
@@ -202,9 +202,9 @@
 	return 0;
 }
 
-static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj,
-				struct bin_attribute *bin_attr,
-				char *buf, loff_t off, size_t count)
+static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
+			    struct bin_attribute *bin_attr, char *buf,
+			    loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	int addr, len;
@@ -264,29 +264,24 @@
 	return count;
 }
 
-static struct bin_attribute w1_f2d_bin_attr = {
-	.attr = {
-		.name = "eeprom",
-		.mode = S_IRUGO | S_IWUSR,
-	},
-	.size = W1_F2D_EEPROM_SIZE,
-	.read = w1_f2d_read_bin,
-	.write = w1_f2d_write_bin,
+static BIN_ATTR_RW(eeprom, W1_F2D_EEPROM_SIZE);
+
+static struct bin_attribute *w1_f2d_bin_attrs[] = {
+	&bin_attr_eeprom,
+	NULL,
 };
 
-static int w1_f2d_add_slave(struct w1_slave *sl)
-{
-	return sysfs_create_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
-}
+static const struct attribute_group w1_f2d_group = {
+	.bin_attrs = w1_f2d_bin_attrs,
+};
 
-static void w1_f2d_remove_slave(struct w1_slave *sl)
-{
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
-}
+static const struct attribute_group *w1_f2d_groups[] = {
+	&w1_f2d_group,
+	NULL,
+};
 
 static struct w1_family_ops w1_f2d_fops = {
-	.add_slave      = w1_f2d_add_slave,
-	.remove_slave   = w1_f2d_remove_slave,
+	.groups		= w1_f2d_groups,
 };
 
 static struct w1_family w1_family_2d = {
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index 10cc1b6..72319a9 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -93,9 +93,9 @@
 }
 #endif	/* CONFIG_W1_SLAVE_DS2433_CRC */
 
-static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj,
-			       struct bin_attribute *bin_attr,
-			       char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
+			   struct bin_attribute *bin_attr, char *buf,
+			   loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
@@ -207,9 +207,9 @@
 	return 0;
 }
 
-static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj,
-				struct bin_attribute *bin_attr,
-				char *buf, loff_t off, size_t count)
+static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
+			    struct bin_attribute *bin_attr, char *buf,
+			    loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	int addr, len, idx;
@@ -257,19 +257,24 @@
 	return count;
 }
 
-static struct bin_attribute w1_f23_bin_attr = {
-	.attr = {
-		.name = "eeprom",
-		.mode = S_IRUGO | S_IWUSR,
-	},
-	.size = W1_EEPROM_SIZE,
-	.read = w1_f23_read_bin,
-	.write = w1_f23_write_bin,
+static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
+
+static struct bin_attribute *w1_f23_bin_attributes[] = {
+	&bin_attr_eeprom,
+	NULL,
+};
+
+static const struct attribute_group w1_f23_group = {
+	.bin_attrs = w1_f23_bin_attributes,
+};
+
+static const struct attribute_group *w1_f23_groups[] = {
+	&w1_f23_group,
+	NULL,
 };
 
 static int w1_f23_add_slave(struct w1_slave *sl)
 {
-	int err;
 #ifdef CONFIG_W1_SLAVE_DS2433_CRC
 	struct w1_f23_data *data;
 
@@ -279,15 +284,7 @@
 	sl->family_data = data;
 
 #endif	/* CONFIG_W1_SLAVE_DS2433_CRC */
-
-	err = sysfs_create_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
-
-#ifdef CONFIG_W1_SLAVE_DS2433_CRC
-	if (err)
-		kfree(data);
-#endif	/* CONFIG_W1_SLAVE_DS2433_CRC */
-
-	return err;
+	return 0;
 }
 
 static void w1_f23_remove_slave(struct w1_slave *sl)
@@ -296,12 +293,12 @@
 	kfree(sl->family_data);
 	sl->family_data = NULL;
 #endif	/* CONFIG_W1_SLAVE_DS2433_CRC */
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
 }
 
 static struct w1_family_ops w1_f23_fops = {
 	.add_slave      = w1_f23_add_slave,
 	.remove_slave   = w1_f23_remove_slave,
+	.groups		= w1_f23_groups,
 };
 
 static struct w1_family w1_family_23 = {
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
index 93719d25..65f90dc 100644
--- a/drivers/w1/slaves/w1_ds2760.c
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -97,21 +97,28 @@
 	return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA);
 }
 
-static ssize_t w1_ds2760_read_bin(struct file *filp, struct kobject *kobj,
-				  struct bin_attribute *bin_attr,
-				  char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
+			     struct bin_attribute *bin_attr, char *buf,
+			     loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	return w1_ds2760_read(dev, buf, off, count);
 }
 
-static struct bin_attribute w1_ds2760_bin_attr = {
-	.attr = {
-		.name = "w1_slave",
-		.mode = S_IRUGO,
-	},
-	.size = DS2760_DATA_SIZE,
-	.read = w1_ds2760_read_bin,
+static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE);
+
+static struct bin_attribute *w1_ds2760_bin_attrs[] = {
+	&bin_attr_w1_slave,
+	NULL,
+};
+
+static const struct attribute_group w1_ds2760_group = {
+	.bin_attrs = w1_ds2760_bin_attrs,
+};
+
+static const struct attribute_group *w1_ds2760_groups[] = {
+	&w1_ds2760_group,
+	NULL,
 };
 
 static DEFINE_IDA(bat_ida);
@@ -139,16 +146,10 @@
 	if (ret)
 		goto pdev_add_failed;
 
-	ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
-	if (ret)
-		goto bin_attr_failed;
-
 	dev_set_drvdata(&sl->dev, pdev);
 
 	goto success;
 
-bin_attr_failed:
-	platform_device_del(pdev);
 pdev_add_failed:
 	platform_device_put(pdev);
 pdev_alloc_failed:
@@ -165,12 +166,12 @@
 
 	platform_device_unregister(pdev);
 	ida_simple_remove(&bat_ida, id);
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
 }
 
 static struct w1_family_ops w1_ds2760_fops = {
 	.add_slave    = w1_ds2760_add_slave,
 	.remove_slave = w1_ds2760_remove_slave,
+	.groups       = w1_ds2760_groups,
 };
 
 static struct w1_family w1_ds2760_family = {
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c
index 0cd7a27..50e85f7 100644
--- a/drivers/w1/slaves/w1_ds2780.c
+++ b/drivers/w1/slaves/w1_ds2780.c
@@ -89,22 +89,28 @@
 }
 EXPORT_SYMBOL(w1_ds2780_eeprom_cmd);
 
-static ssize_t w1_ds2780_read_bin(struct file *filp,
-				  struct kobject *kobj,
-				  struct bin_attribute *bin_attr,
-				  char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
+			     struct bin_attribute *bin_attr, char *buf,
+			     loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	return w1_ds2780_io(dev, buf, off, count, 0);
 }
 
-static struct bin_attribute w1_ds2780_bin_attr = {
-	.attr = {
-		.name = "w1_slave",
-		.mode = S_IRUGO,
-	},
-	.size = DS2780_DATA_SIZE,
-	.read = w1_ds2780_read_bin,
+static BIN_ATTR_RO(w1_slave, DS2780_DATA_SIZE);
+
+static struct bin_attribute *w1_ds2780_bin_attrs[] = {
+	&bin_attr_w1_slave,
+	NULL,
+};
+
+static const struct attribute_group w1_ds2780_group = {
+	.bin_attrs = w1_ds2780_bin_attrs,
+};
+
+static const struct attribute_group *w1_ds2780_groups[] = {
+	&w1_ds2780_group,
+	NULL,
 };
 
 static DEFINE_IDA(bat_ida);
@@ -132,16 +138,10 @@
 	if (ret)
 		goto pdev_add_failed;
 
-	ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr);
-	if (ret)
-		goto bin_attr_failed;
-
 	dev_set_drvdata(&sl->dev, pdev);
 
 	return 0;
 
-bin_attr_failed:
-	platform_device_del(pdev);
 pdev_add_failed:
 	platform_device_put(pdev);
 pdev_alloc_failed:
@@ -157,12 +157,12 @@
 
 	platform_device_unregister(pdev);
 	ida_simple_remove(&bat_ida, id);
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr);
 }
 
 static struct w1_family_ops w1_ds2780_fops = {
 	.add_slave    = w1_ds2780_add_slave,
 	.remove_slave = w1_ds2780_remove_slave,
+	.groups       = w1_ds2780_groups,
 };
 
 static struct w1_family w1_ds2780_family = {
diff --git a/drivers/w1/slaves/w1_ds2781.c b/drivers/w1/slaves/w1_ds2781.c
index 1aba8e4..1eb98fb 100644
--- a/drivers/w1/slaves/w1_ds2781.c
+++ b/drivers/w1/slaves/w1_ds2781.c
@@ -87,22 +87,28 @@
 }
 EXPORT_SYMBOL(w1_ds2781_eeprom_cmd);
 
-static ssize_t w1_ds2781_read_bin(struct file *filp,
-				  struct kobject *kobj,
-				  struct bin_attribute *bin_attr,
-				  char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
+			     struct bin_attribute *bin_attr, char *buf,
+			     loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	return w1_ds2781_io(dev, buf, off, count, 0);
 }
 
-static struct bin_attribute w1_ds2781_bin_attr = {
-	.attr = {
-		.name = "w1_slave",
-		.mode = S_IRUGO,
-	},
-	.size = DS2781_DATA_SIZE,
-	.read = w1_ds2781_read_bin,
+static BIN_ATTR_RO(w1_slave, DS2781_DATA_SIZE);
+
+static struct bin_attribute *w1_ds2781_bin_attrs[] = {
+	&bin_attr_w1_slave,
+	NULL,
+};
+
+static const struct attribute_group w1_ds2781_group = {
+	.bin_attrs = w1_ds2781_bin_attrs,
+};
+
+static const struct attribute_group *w1_ds2781_groups[] = {
+	&w1_ds2781_group,
+	NULL,
 };
 
 static DEFINE_IDA(bat_ida);
@@ -130,16 +136,10 @@
 	if (ret)
 		goto pdev_add_failed;
 
-	ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2781_bin_attr);
-	if (ret)
-		goto bin_attr_failed;
-
 	dev_set_drvdata(&sl->dev, pdev);
 
 	return 0;
 
-bin_attr_failed:
-	platform_device_del(pdev);
 pdev_add_failed:
 	platform_device_put(pdev);
 pdev_alloc_failed:
@@ -155,12 +155,12 @@
 
 	platform_device_unregister(pdev);
 	ida_simple_remove(&bat_ida, id);
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2781_bin_attr);
 }
 
 static struct w1_family_ops w1_ds2781_fops = {
 	.add_slave    = w1_ds2781_add_slave,
 	.remove_slave = w1_ds2781_remove_slave,
+	.groups       = w1_ds2781_groups,
 };
 
 static struct w1_family w1_ds2781_family = {
diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c
index cd30a6d..365d6df 100644
--- a/drivers/w1/slaves/w1_ds28e04.c
+++ b/drivers/w1/slaves/w1_ds28e04.c
@@ -118,9 +118,9 @@
 	return w1_read_block(sl->master, data, len);
 }
 
-static ssize_t w1_f1C_read_bin(struct file *filp, struct kobject *kobj,
-			       struct bin_attribute *bin_attr,
-			       char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
+			   struct bin_attribute *bin_attr, char *buf,
+			   loff_t off, size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 	struct w1_f1C_data *data = sl->family_data;
@@ -226,9 +226,9 @@
 	return 0;
 }
 
-static ssize_t w1_f1C_write_bin(struct file *filp, struct kobject *kobj,
-			       struct bin_attribute *bin_attr,
-			       char *buf, loff_t off, size_t count)
+static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
+			    struct bin_attribute *bin_attr, char *buf,
+			    loff_t off, size_t count)
 
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -280,9 +280,11 @@
 	return count;
 }
 
-static ssize_t w1_f1C_read_pio(struct file *filp, struct kobject *kobj,
-			       struct bin_attribute *bin_attr,
-			       char *buf, loff_t off, size_t count)
+static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
+
+static ssize_t pio_read(struct file *filp, struct kobject *kobj,
+			struct bin_attribute *bin_attr, char *buf, loff_t off,
+			size_t count)
 
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -299,9 +301,9 @@
 	return ret;
 }
 
-static ssize_t w1_f1C_write_pio(struct file *filp, struct kobject *kobj,
-				struct bin_attribute *bin_attr,
-				char *buf, loff_t off, size_t count)
+static ssize_t pio_write(struct file *filp, struct kobject *kobj,
+			 struct bin_attribute *bin_attr, char *buf, loff_t off,
+			 size_t count)
 
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -339,8 +341,10 @@
 	return count;
 }
 
-static ssize_t w1_f1C_show_crccheck(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+static BIN_ATTR_RW(pio, 1);
+
+static ssize_t crccheck_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	if (put_user(w1_enable_crccheck + 0x30, buf))
 		return -EFAULT;
@@ -348,9 +352,8 @@
 	return sizeof(w1_enable_crccheck);
 }
 
-static ssize_t w1_f1C_store_crccheck(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
+static ssize_t crccheck_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
 {
 	char val;
 
@@ -371,35 +374,31 @@
 	return sizeof(w1_enable_crccheck);
 }
 
-#define NB_SYSFS_BIN_FILES 2
-static struct bin_attribute w1_f1C_bin_attr[NB_SYSFS_BIN_FILES] = {
-	{
-		.attr = {
-			.name = "eeprom",
-			.mode = S_IRUGO | S_IWUSR,
-		},
-		.size = W1_EEPROM_SIZE,
-		.read = w1_f1C_read_bin,
-		.write = w1_f1C_write_bin,
-	},
-	{
-		.attr = {
-			.name = "pio",
-			.mode = S_IRUGO | S_IWUSR,
-		},
-		.size = 1,
-		.read = w1_f1C_read_pio,
-		.write = w1_f1C_write_pio,
-	}
+static DEVICE_ATTR_RW(crccheck);
+
+static struct attribute *w1_f1C_attrs[] = {
+	&dev_attr_crccheck.attr,
+	NULL,
 };
 
-static DEVICE_ATTR(crccheck, S_IWUSR | S_IRUGO,
-		   w1_f1C_show_crccheck, w1_f1C_store_crccheck);
+static struct bin_attribute *w1_f1C_bin_attrs[] = {
+	&bin_attr_eeprom,
+	&bin_attr_pio,
+	NULL,
+};
+
+static const struct attribute_group w1_f1C_group = {
+	.attrs		= w1_f1C_attrs,
+	.bin_attrs	= w1_f1C_bin_attrs,
+};
+
+static const struct attribute_group *w1_f1C_groups[] = {
+	&w1_f1C_group,
+	NULL,
+};
 
 static int w1_f1C_add_slave(struct w1_slave *sl)
 {
-	int err = 0;
-	int i;
 	struct w1_f1C_data *data = NULL;
 
 	if (w1_enable_crccheck) {
@@ -409,46 +408,19 @@
 		sl->family_data = data;
 	}
 
-	/* create binary sysfs attributes */
-	for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i)
-		err = sysfs_create_bin_file(
-			&sl->dev.kobj, &(w1_f1C_bin_attr[i]));
-
-	if (!err) {
-		/* create device attributes */
-		err = device_create_file(&sl->dev, &dev_attr_crccheck);
-	}
-
-	if (err) {
-		/* remove binary sysfs attributes */
-		for (i = 0; i < NB_SYSFS_BIN_FILES; ++i)
-			sysfs_remove_bin_file(
-				&sl->dev.kobj, &(w1_f1C_bin_attr[i]));
-
-		kfree(data);
-	}
-
-	return err;
+	return 0;
 }
 
 static void w1_f1C_remove_slave(struct w1_slave *sl)
 {
-	int i;
-
 	kfree(sl->family_data);
 	sl->family_data = NULL;
-
-	/* remove device attributes */
-	device_remove_file(&sl->dev, &dev_attr_crccheck);
-
-	/* remove binary sysfs attributes */
-	for (i = 0; i < NB_SYSFS_BIN_FILES; ++i)
-		sysfs_remove_bin_file(&sl->dev.kobj, &(w1_f1C_bin_attr[i]));
 }
 
 static struct w1_family_ops w1_f1C_fops = {
 	.add_slave      = w1_f1C_add_slave,
 	.remove_slave   = w1_f1C_remove_slave,
+	.groups		= w1_f1C_groups,
 };
 
 static struct w1_family w1_family_1C = {
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 8978360..8b5ff33 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -59,25 +59,19 @@
 module_param_named(strong_pullup, w1_strong_pullup, int, 0);
 
 
-static ssize_t w1_therm_read(struct device *device,
+static ssize_t w1_slave_show(struct device *device,
 	struct device_attribute *attr, char *buf);
 
-static struct device_attribute w1_therm_attr =
-	__ATTR(w1_slave, S_IRUGO, w1_therm_read, NULL);
+static DEVICE_ATTR_RO(w1_slave);
 
-static int w1_therm_add_slave(struct w1_slave *sl)
-{
-	return device_create_file(&sl->dev, &w1_therm_attr);
-}
-
-static void w1_therm_remove_slave(struct w1_slave *sl)
-{
-	device_remove_file(&sl->dev, &w1_therm_attr);
-}
+static struct attribute *w1_therm_attrs[] = {
+	&dev_attr_w1_slave.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(w1_therm);
 
 static struct w1_family_ops w1_therm_fops = {
-	.add_slave	= w1_therm_add_slave,
-	.remove_slave	= w1_therm_remove_slave,
+	.groups		= w1_therm_groups,
 };
 
 static struct w1_family w1_therm_family_DS18S20 = {
@@ -178,7 +172,7 @@
 }
 
 
-static ssize_t w1_therm_read(struct device *device,
+static ssize_t w1_slave_show(struct device *device,
 	struct device_attribute *attr, char *buf)
 {
 	struct w1_slave *sl = dev_to_w1_slave(device);
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 0459df8..22013ca 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -96,14 +96,15 @@
 	complete(&sl->released);
 }
 
-static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_slave *sl = dev_to_w1_slave(dev);
 
 	return sprintf(buf, "%s\n", sl->name);
 }
+static DEVICE_ATTR_RO(name);
 
-static ssize_t w1_slave_read_id(struct device *dev,
+static ssize_t id_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	struct w1_slave *sl = dev_to_w1_slave(dev);
@@ -112,17 +113,20 @@
 	memcpy(buf, (u8 *)&sl->reg_num, count);
 	return count;
 }
+static DEVICE_ATTR_RO(id);
 
-static struct device_attribute w1_slave_attr_name =
-	__ATTR(name, S_IRUGO, w1_slave_read_name, NULL);
-static struct device_attribute w1_slave_attr_id =
-	__ATTR(id, S_IRUGO, w1_slave_read_id, NULL);
+static struct attribute *w1_slave_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_id.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(w1_slave);
 
 /* Default family */
 
-static ssize_t w1_default_write(struct file *filp, struct kobject *kobj,
-				struct bin_attribute *bin_attr,
-				char *buf, loff_t off, size_t count)
+static ssize_t rw_write(struct file *filp, struct kobject *kobj,
+			struct bin_attribute *bin_attr, char *buf, loff_t off,
+			size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -139,9 +143,9 @@
 	return count;
 }
 
-static ssize_t w1_default_read(struct file *filp, struct kobject *kobj,
-			       struct bin_attribute *bin_attr,
-			       char *buf, loff_t off, size_t count)
+static ssize_t rw_read(struct file *filp, struct kobject *kobj,
+		       struct bin_attribute *bin_attr, char *buf, loff_t off,
+		       size_t count)
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
@@ -151,29 +155,24 @@
 	return count;
 }
 
-static struct bin_attribute w1_default_attr = {
-      .attr = {
-              .name = "rw",
-              .mode = S_IRUGO | S_IWUSR,
-      },
-      .size = PAGE_SIZE,
-      .read = w1_default_read,
-      .write = w1_default_write,
+static BIN_ATTR_RW(rw, PAGE_SIZE);
+
+static struct bin_attribute *w1_slave_bin_attrs[] = {
+	&bin_attr_rw,
+	NULL,
 };
 
-static int w1_default_add_slave(struct w1_slave *sl)
-{
-	return sysfs_create_bin_file(&sl->dev.kobj, &w1_default_attr);
-}
+static const struct attribute_group w1_slave_default_group = {
+	.bin_attrs = w1_slave_bin_attrs,
+};
 
-static void w1_default_remove_slave(struct w1_slave *sl)
-{
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_default_attr);
-}
+static const struct attribute_group *w1_slave_default_groups[] = {
+	&w1_slave_default_group,
+	NULL,
+};
 
 static struct w1_family_ops w1_default_fops = {
-	.add_slave	= w1_default_add_slave,
-	.remove_slave	= w1_default_remove_slave,
+	.groups		= w1_slave_default_groups,
 };
 
 static struct w1_family w1_default_family = {
@@ -587,6 +586,66 @@
 	return err;
 }
 
+/*
+ * Handle sysfs file creation and removal here, before userspace is told that
+ * the device is added / removed from the system
+ */
+static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
+			 void *data)
+{
+	struct device *dev = data;
+	struct w1_slave *sl;
+	struct w1_family_ops *fops;
+	int err;
+
+	/*
+	 * Only care about slave devices at the moment.  Yes, we should use a
+	 * separate "type" for this, but for now, look at the release function
+	 * to know which type it is...
+	 */
+	if (dev->release != w1_slave_release)
+		return 0;
+
+	sl = dev_to_w1_slave(dev);
+	fops = sl->family->fops;
+
+	switch (action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		/* if the family driver needs to initialize something... */
+		if (fops->add_slave) {
+			err = fops->add_slave(sl);
+			if (err < 0) {
+				dev_err(&sl->dev,
+					"add_slave() call failed. err=%d\n",
+					err);
+				return err;
+			}
+		}
+		if (fops->groups) {
+			err = sysfs_create_groups(&sl->dev.kobj, fops->groups);
+			if (err) {
+				dev_err(&sl->dev,
+					"sysfs group creation failed. err=%d\n",
+					err);
+				return err;
+			}
+		}
+
+		break;
+	case BUS_NOTIFY_DEL_DEVICE:
+		if (fops->remove_slave)
+			sl->family->fops->remove_slave(sl);
+		if (fops->groups)
+			sysfs_remove_groups(&sl->dev.kobj, fops->groups);
+		break;
+	}
+	return 0;
+}
+
+static struct notifier_block w1_bus_nb = {
+	.notifier_call = w1_bus_notify,
+};
+
 static int __w1_attach_slave_device(struct w1_slave *sl)
 {
 	int err;
@@ -595,6 +654,7 @@
 	sl->dev.driver = &w1_slave_driver;
 	sl->dev.bus = &w1_bus_type;
 	sl->dev.release = &w1_slave_release;
+	sl->dev.groups = w1_slave_groups;
 
 	dev_set_name(&sl->dev, "%02x-%012llx",
 		 (unsigned int) sl->reg_num.family,
@@ -615,44 +675,13 @@
 		return err;
 	}
 
-	/* Create "name" entry */
-	err = device_create_file(&sl->dev, &w1_slave_attr_name);
-	if (err < 0) {
-		dev_err(&sl->dev,
-			"sysfs file creation for [%s] failed. err=%d\n",
-			dev_name(&sl->dev), err);
-		goto out_unreg;
-	}
 
-	/* Create "id" entry */
-	err = device_create_file(&sl->dev, &w1_slave_attr_id);
-	if (err < 0) {
-		dev_err(&sl->dev,
-			"sysfs file creation for [%s] failed. err=%d\n",
-			dev_name(&sl->dev), err);
-		goto out_rem1;
-	}
-
-	/* if the family driver needs to initialize something... */
-	if (sl->family->fops && sl->family->fops->add_slave &&
-	    ((err = sl->family->fops->add_slave(sl)) < 0)) {
-		dev_err(&sl->dev,
-			"sysfs file creation for [%s] failed. err=%d\n",
-			dev_name(&sl->dev), err);
-		goto out_rem2;
-	}
+	dev_set_uevent_suppress(&sl->dev, false);
+	kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
 
 	list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
 
 	return 0;
-
-out_rem2:
-	device_remove_file(&sl->dev, &w1_slave_attr_id);
-out_rem1:
-	device_remove_file(&sl->dev, &w1_slave_attr_name);
-out_unreg:
-	device_unregister(&sl->dev);
-	return err;
 }
 
 static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
@@ -723,16 +752,11 @@
 
 	list_del(&sl->w1_slave_entry);
 
-	if (sl->family->fops && sl->family->fops->remove_slave)
-		sl->family->fops->remove_slave(sl);
-
 	memset(&msg, 0, sizeof(msg));
 	memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
 	msg.type = W1_SLAVE_REMOVE;
 	w1_netlink_send(sl->master, &msg);
 
-	device_remove_file(&sl->dev, &w1_slave_attr_id);
-	device_remove_file(&sl->dev, &w1_slave_attr_name);
 	device_unregister(&sl->dev);
 
 	wait_for_completion(&sl->released);
@@ -1017,6 +1041,10 @@
 		goto err_out_exit_init;
 	}
 
+	retval = bus_register_notifier(&w1_bus_type, &w1_bus_nb);
+	if (retval)
+		goto err_out_bus_unregister;
+
 	retval = driver_register(&w1_master_driver);
 	if (retval) {
 		printk(KERN_ERR
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 625dd08..4ad0e81 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -52,6 +52,7 @@
 {
 	int  (* add_slave)(struct w1_slave *);
 	void (* remove_slave)(struct w1_slave *);
+	const struct attribute_group **groups;
 };
 
 struct w1_family
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index aef34b1..adbfd66 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -568,6 +568,7 @@
 
 	return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting));
 }
+static DEVICE_ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL);
 
 static ssize_t cuse_class_abort_store(struct device *dev,
 				      struct device_attribute *attr,
@@ -578,12 +579,14 @@
 	fuse_abort_conn(&cc->fc);
 	return count;
 }
+static DEVICE_ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store);
 
-static struct device_attribute cuse_class_dev_attrs[] = {
-	__ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL),
-	__ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store),
-	{ }
+static struct attribute *cuse_class_dev_attrs[] = {
+	&dev_attr_waiting.attr,
+	&dev_attr_abort.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(cuse_class_dev);
 
 static struct miscdevice cuse_miscdev = {
 	.minor		= MISC_DYNAMIC_MINOR,
@@ -609,7 +612,7 @@
 	if (IS_ERR(cuse_class))
 		return PTR_ERR(cuse_class);
 
-	cuse_class->dev_attrs = cuse_class_dev_attrs;
+	cuse_class->dev_groups = cuse_class_dev_groups;
 
 	rc = misc_register(&cuse_miscdev);
 	if (rc) {
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 15c68f9..c590cab 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -22,8 +22,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
-
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "sysfs.h"
 
@@ -391,7 +390,7 @@
 	return rc;
 }
 
-static int open(struct inode * inode, struct file * file)
+static int open(struct inode *inode, struct file *file)
 {
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
@@ -435,7 +434,7 @@
 	return error;
 }
 
-static int release(struct inode * inode, struct file * file)
+static int release(struct inode *inode, struct file *file)
 {
 	struct bin_buffer *bb = file->private_data;
 
@@ -481,7 +480,6 @@
  *	@kobj:	object.
  *	@attr:	attribute descriptor.
  */
-
 int sysfs_create_bin_file(struct kobject *kobj,
 			  const struct bin_attribute *attr)
 {
@@ -489,19 +487,16 @@
 
 	return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
 }
-
+EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
 
 /**
  *	sysfs_remove_bin_file - remove binary file for object.
  *	@kobj:	object.
  *	@attr:	attribute descriptor.
  */
-
 void sysfs_remove_bin_file(struct kobject *kobj,
 			   const struct bin_attribute *attr)
 {
 	sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);
 }
-
-EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
 EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index e068e74..99ec5b4 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -46,7 +46,7 @@
 	unsigned int len = strlen(name);
 	while (len--)
 		hash = partial_name_hash(*name++, hash);
-	hash = ( end_name_hash(hash) ^ hash_ptr( (void *)ns, 31 ) );
+	hash = (end_name_hash(hash) ^ hash_ptr((void *)ns, 31));
 	hash &= 0x7fffffffU;
 	/* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */
 	if (hash < 1)
@@ -258,7 +258,7 @@
 	spin_unlock(&sysfs_ino_lock);
 }
 
-void release_sysfs_dirent(struct sysfs_dirent * sd)
+void release_sysfs_dirent(struct sysfs_dirent *sd)
 {
 	struct sysfs_dirent *parent_sd;
 
@@ -451,7 +451,7 @@
 
 	if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
 		WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
-			sysfs_ns_type(acxt->parent_sd)? "required": "invalid",
+			sysfs_ns_type(acxt->parent_sd) ? "required" : "invalid",
 			acxt->parent_sd->s_name, sd->s_name);
 		return -EINVAL;
 	}
@@ -619,7 +619,7 @@
 
 	if (!!sysfs_ns_type(parent_sd) != !!ns) {
 		WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
-			sysfs_ns_type(parent_sd)? "required": "invalid",
+			sysfs_ns_type(parent_sd) ? "required" : "invalid",
 			parent_sd->s_name, name);
 		return NULL;
 	}
@@ -674,7 +674,7 @@
 	enum kobj_ns_type type, const void *ns, const char *name,
 	struct sysfs_dirent **p_sd)
 {
-	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
+	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
 	struct sysfs_addrm_cxt acxt;
 	struct sysfs_dirent *sd;
 	int rc;
@@ -735,9 +735,9 @@
 
 /**
  *	sysfs_create_dir - create a directory for an object.
- *	@kobj:		object we're creating directory for. 
+ *	@kobj:		object we're creating directory for.
  */
-int sysfs_create_dir(struct kobject * kobj)
+int sysfs_create_dir(struct kobject *kobj)
 {
 	enum kobj_ns_type type;
 	struct sysfs_dirent *parent_sd, *sd;
@@ -764,8 +764,8 @@
 	return error;
 }
 
-static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
-				unsigned int flags)
+static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry,
+				   unsigned int flags)
 {
 	struct dentry *ret = NULL;
 	struct dentry *parent = dentry->d_parent;
@@ -857,7 +857,7 @@
  *	what used to be sysfs_rmdir() below, instead of calling separately.
  */
 
-void sysfs_remove_dir(struct kobject * kobj)
+void sysfs_remove_dir(struct kobject *kobj)
 {
 	struct sysfs_dirent *sd = kobj->sd;
 
@@ -896,7 +896,9 @@
 		sd->s_name = new_name;
 	}
 
-	/* Move to the appropriate place in the appropriate directories rbtree. */
+	/*
+	 * Move to the appropriate place in the appropriate directories rbtree.
+	 */
 	sysfs_unlink_sibling(sd);
 	sysfs_get(new_parent_sd);
 	sysfs_put(sd->s_parent);
@@ -988,20 +990,21 @@
 	struct sysfs_dirent *parent_sd,	ino_t ino, struct sysfs_dirent *pos)
 {
 	pos = sysfs_dir_pos(ns, parent_sd, ino, pos);
-	if (pos) do {
-		struct rb_node *node = rb_next(&pos->s_rb);
-		if (!node)
-			pos = NULL;
-		else
-			pos = to_sysfs_dirent(node);
-	} while (pos && pos->s_ns != ns);
+	if (pos)
+		do {
+			struct rb_node *node = rb_next(&pos->s_rb);
+			if (!node)
+				pos = NULL;
+			else
+				pos = to_sysfs_dirent(node);
+		} while (pos && pos->s_ns != ns);
 	return pos;
 }
 
 static int sysfs_readdir(struct file *file, struct dir_context *ctx)
 {
 	struct dentry *dentry = file->f_path.dentry;
-	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+	struct sysfs_dirent *parent_sd = dentry->d_fsdata;
 	struct sysfs_dirent *pos = file->private_data;
 	enum kobj_ns_type type;
 	const void *ns;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index d2bb7ed..15ef5eb 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -20,7 +20,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/limits.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "sysfs.h"
 
@@ -45,8 +45,8 @@
 struct sysfs_buffer {
 	size_t			count;
 	loff_t			pos;
-	char			* page;
-	const struct sysfs_ops	* ops;
+	char			*page;
+	const struct sysfs_ops	*ops;
 	struct mutex		mutex;
 	int			needs_read_fill;
 	int			event;
@@ -59,16 +59,16 @@
  *	@buffer:	data buffer for file.
  *
  *	Allocate @buffer->page, if it hasn't been already, then call the
- *	kobject's show() method to fill the buffer with this attribute's 
- *	data. 
+ *	kobject's show() method to fill the buffer with this attribute's
+ *	data.
  *	This is called only once, on the file's first read unless an error
  *	is returned.
  */
-static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
+static int fill_read_buffer(struct dentry *dentry, struct sysfs_buffer *buffer)
 {
 	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
 	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	const struct sysfs_ops * ops = buffer->ops;
+	const struct sysfs_ops *ops = buffer->ops;
 	int ret = 0;
 	ssize_t count;
 
@@ -106,7 +106,7 @@
 }
 
 /**
- *	sysfs_read_file - read an attribute. 
+ *	sysfs_read_file - read an attribute.
  *	@file:	file pointer.
  *	@buf:	buffer to fill.
  *	@count:	number of bytes to read.
@@ -127,12 +127,12 @@
 static ssize_t
 sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-	struct sysfs_buffer * buffer = file->private_data;
+	struct sysfs_buffer *buffer = file->private_data;
 	ssize_t retval = 0;
 
 	mutex_lock(&buffer->mutex);
 	if (buffer->needs_read_fill || *ppos == 0) {
-		retval = fill_read_buffer(file->f_path.dentry,buffer);
+		retval = fill_read_buffer(file->f_path.dentry, buffer);
 		if (retval)
 			goto out;
 	}
@@ -154,9 +154,8 @@
  *	Allocate @buffer->page if it hasn't been already, then
  *	copy the user-supplied buffer into it.
  */
-
-static int 
-fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count)
+static int fill_write_buffer(struct sysfs_buffer *buffer,
+			     const char __user *buf, size_t count)
 {
 	int error;
 
@@ -167,7 +166,7 @@
 
 	if (count >= PAGE_SIZE)
 		count = PAGE_SIZE - 1;
-	error = copy_from_user(buffer->page,buf,count);
+	error = copy_from_user(buffer->page, buf, count);
 	buffer->needs_read_fill = 1;
 	/* if buf is assumed to contain a string, terminate it by \0,
 	   so e.g. sscanf() can scan the string easily */
@@ -183,16 +182,15 @@
  *	@count:		number of bytes
  *
  *	Get the correct pointers for the kobject and the attribute we're
- *	dealing with, then call the store() method for the attribute, 
+ *	dealing with, then call the store() method for the attribute,
  *	passing the buffer that we acquired in fill_write_buffer().
  */
-
-static int
-flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
+static int flush_write_buffer(struct dentry *dentry,
+			      struct sysfs_buffer *buffer, size_t count)
 {
 	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
 	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	const struct sysfs_ops * ops = buffer->ops;
+	const struct sysfs_ops *ops = buffer->ops;
 	int rc;
 
 	/* need attr_sd for attr and ops, its parent for kobj */
@@ -219,15 +217,14 @@
  *	then push it to the kobject in flush_write_buffer().
  *	There is no easy way for us to know if userspace is only doing a partial
  *	write, so we don't support them. We expect the entire buffer to come
- *	on the first write. 
+ *	on the first write.
  *	Hint: if you're writing a value, first read the file, modify only the
- *	the value you're changing, then write entire buffer back. 
+ *	the value you're changing, then write entire buffer back.
  */
-
-static ssize_t
-sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+static ssize_t sysfs_write_file(struct file *file, const char __user *buf,
+				size_t count, loff_t *ppos)
 {
-	struct sysfs_buffer * buffer = file->private_data;
+	struct sysfs_buffer *buffer = file->private_data;
 	ssize_t len;
 
 	mutex_lock(&buffer->mutex);
@@ -339,13 +336,14 @@
 	if (kobj->ktype && kobj->ktype->sysfs_ops)
 		ops = kobj->ktype->sysfs_ops;
 	else {
-		WARN(1, KERN_ERR "missing sysfs attribute operations for "
-		       "kobject: %s\n", kobject_name(kobj));
+		WARN(1, KERN_ERR
+		     "missing sysfs attribute operations for kobject: %s\n",
+		     kobject_name(kobj));
 		goto err_out;
 	}
 
 	/* File needs write support.
-	 * The inode's perms must say it's ok, 
+	 * The inode's perms must say it's ok,
 	 * and we must have a store method.
 	 */
 	if (file->f_mode & FMODE_WRITE) {
@@ -420,7 +418,7 @@
  */
 static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
 {
-	struct sysfs_buffer * buffer = filp->private_data;
+	struct sysfs_buffer *buffer = filp->private_data;
 	struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
 	struct sysfs_open_dirent *od = attr_sd->s_attr.open;
 
@@ -518,8 +516,9 @@
 	ns = ops->namespace(kobj, attr);
 out:
 	if (err) {
-		WARN(1, KERN_ERR "missing sysfs namespace attribute operation for "
-		     "kobject: %s\n", kobject_name(kobj));
+		WARN(1, KERN_ERR
+		     "missing sysfs namespace attribute operation for kobject: %s\n",
+		     kobject_name(kobj));
 	}
 	*pns = ns;
 	return err;
@@ -566,17 +565,17 @@
 
 /**
  *	sysfs_create_file - create an attribute file for an object.
- *	@kobj:	object we're creating for. 
+ *	@kobj:	object we're creating for.
  *	@attr:	attribute descriptor.
  */
-
-int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
+int sysfs_create_file(struct kobject *kobj, const struct attribute *attr)
 {
 	BUG_ON(!kobj || !kobj->sd || !attr);
 
 	return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
 
 }
+EXPORT_SYMBOL_GPL(sysfs_create_file);
 
 int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
 {
@@ -590,6 +589,7 @@
 			sysfs_remove_file(kobj, ptr[i]);
 	return err;
 }
+EXPORT_SYMBOL_GPL(sysfs_create_files);
 
 /**
  * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
@@ -654,7 +654,6 @@
 }
 EXPORT_SYMBOL_GPL(sysfs_chmod_file);
 
-
 /**
  *	sysfs_remove_file - remove an object attribute.
  *	@kobj:	object we're acting for.
@@ -662,8 +661,7 @@
  *
  *	Hash the attribute name and kill the victim.
  */
-
-void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
+void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr)
 {
 	const void *ns;
 
@@ -672,13 +670,15 @@
 
 	sysfs_hash_and_remove(kobj->sd, ns, attr->name);
 }
+EXPORT_SYMBOL_GPL(sysfs_remove_file);
 
-void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)
+void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
 {
 	int i;
 	for (i = 0; ptr[i]; i++)
 		sysfs_remove_file(kobj, ptr[i]);
 }
+EXPORT_SYMBOL_GPL(sysfs_remove_files);
 
 /**
  * sysfs_remove_file_from_group - remove an attribute file from a group.
@@ -793,9 +793,3 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
-
-
-EXPORT_SYMBOL_GPL(sysfs_create_file);
-EXPORT_SYMBOL_GPL(sysfs_remove_file);
-EXPORT_SYMBOL_GPL(sysfs_remove_files);
-EXPORT_SYMBOL_GPL(sysfs_create_files);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 09a1a25..5f92cd2 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -3,8 +3,10 @@
  *
  * Copyright (c) 2003 Patrick Mochel
  * Copyright (c) 2003 Open Source Development Lab
+ * Copyright (c) 2013 Greg Kroah-Hartman
+ * Copyright (c) 2013 The Linux Foundation
  *
- * This file is released undert the GPL v2. 
+ * This file is released undert the GPL v2.
  *
  */
 
@@ -19,8 +21,8 @@
 static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
 			 const struct attribute_group *grp)
 {
-	struct attribute *const* attr;
-	struct bin_attribute *const* bin_attr;
+	struct attribute *const *attr;
+	struct bin_attribute *const *bin_attr;
 
 	if (grp->attrs)
 		for (attr = grp->attrs; *attr; attr++)
@@ -33,8 +35,8 @@
 static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
 			const struct attribute_group *grp, int update)
 {
-	struct attribute *const* attr;
-	struct bin_attribute *const* bin_attr;
+	struct attribute *const *attr;
+	struct bin_attribute *const *bin_attr;
 	int error = 0, i;
 
 	if (grp->attrs) {
@@ -129,6 +131,41 @@
 {
 	return internal_create_group(kobj, 0, grp);
 }
+EXPORT_SYMBOL_GPL(sysfs_create_group);
+
+/**
+ * sysfs_create_groups - given a directory kobject, create a bunch of attribute groups
+ * @kobj:	The kobject to create the group on
+ * @groups:	The attribute groups to create, NULL terminated
+ *
+ * This function creates a bunch of attribute groups.  If an error occurs when
+ * creating a group, all previously created groups will be removed, unwinding
+ * everything back to the original state when this function was called.
+ * It will explicitly warn and error if any of the attribute files being
+ * created already exist.
+ *
+ * Returns 0 on success or error code from sysfs_create_group on error.
+ */
+int sysfs_create_groups(struct kobject *kobj,
+			const struct attribute_group **groups)
+{
+	int error = 0;
+	int i;
+
+	if (!groups)
+		return 0;
+
+	for (i = 0; groups[i]; i++) {
+		error = sysfs_create_group(kobj, groups[i]);
+		if (error) {
+			while (--i >= 0)
+				sysfs_remove_group(kobj, groups[i]);
+			break;
+		}
+	}
+	return error;
+}
+EXPORT_SYMBOL_GPL(sysfs_create_groups);
 
 /**
  * sysfs_update_group - given a directory kobject, update an attribute group
@@ -152,11 +189,18 @@
 {
 	return internal_create_group(kobj, 1, grp);
 }
+EXPORT_SYMBOL_GPL(sysfs_update_group);
 
-
-
-void sysfs_remove_group(struct kobject * kobj, 
-			const struct attribute_group * grp)
+/**
+ * sysfs_remove_group: remove a group from a kobject
+ * @kobj:	kobject to remove the group from
+ * @grp:	group to remove
+ *
+ * This function removes a group of attributes from a kobject.  The attributes
+ * previously have to have been created for this group, otherwise it will fail.
+ */
+void sysfs_remove_group(struct kobject *kobj,
+			const struct attribute_group *grp)
 {
 	struct sysfs_dirent *dir_sd = kobj->sd;
 	struct sysfs_dirent *sd;
@@ -164,8 +208,9 @@
 	if (grp->name) {
 		sd = sysfs_get_dirent(dir_sd, NULL, grp->name);
 		if (!sd) {
-			WARN(!sd, KERN_WARNING "sysfs group %p not found for "
-				"kobject '%s'\n", grp, kobject_name(kobj));
+			WARN(!sd, KERN_WARNING
+			     "sysfs group %p not found for kobject '%s'\n",
+			     grp, kobject_name(kobj));
 			return;
 		}
 	} else
@@ -177,6 +222,27 @@
 
 	sysfs_put(sd);
 }
+EXPORT_SYMBOL_GPL(sysfs_remove_group);
+
+/**
+ * sysfs_remove_groups - remove a list of groups
+ *
+ * @kobj:	The kobject for the groups to be removed from
+ * @groups:	NULL terminated list of groups to be removed
+ *
+ * If groups is not NULL, remove the specified groups from the kobject.
+ */
+void sysfs_remove_groups(struct kobject *kobj,
+			 const struct attribute_group **groups)
+{
+	int i;
+
+	if (!groups)
+		return;
+	for (i = 0; groups[i]; i++)
+		sysfs_remove_group(kobj, groups[i]);
+}
+EXPORT_SYMBOL_GPL(sysfs_remove_groups);
 
 /**
  * sysfs_merge_group - merge files into a pre-existing attribute group.
@@ -273,7 +339,3 @@
 	}
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
-
-EXPORT_SYMBOL_GPL(sysfs_create_group);
-EXPORT_SYMBOL_GPL(sysfs_update_group);
-EXPORT_SYMBOL_GPL(sysfs_remove_group);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 3e2837a..963f910 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -10,7 +10,7 @@
  * Please see Documentation/filesystems/sysfs.txt for more information.
  */
 
-#undef DEBUG 
+#undef DEBUG
 
 #include <linux/pagemap.h>
 #include <linux/namei.h>
@@ -36,7 +36,7 @@
 	.capabilities	= BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
-static const struct inode_operations sysfs_inode_operations ={
+static const struct inode_operations sysfs_inode_operations = {
 	.permission	= sysfs_permission,
 	.setattr	= sysfs_setattr,
 	.getattr	= sysfs_getattr,
@@ -67,7 +67,7 @@
 	return attrs;
 }
 
-int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr)
+int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr)
 {
 	struct sysfs_inode_attrs *sd_attrs;
 	struct iattr *iattrs;
@@ -128,7 +128,8 @@
 	return error;
 }
 
-static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len)
+static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata,
+			       u32 *secdata_len)
 {
 	struct sysfs_inode_attrs *iattrs;
 	void *old_secdata;
@@ -186,13 +187,13 @@
 	return error;
 }
 
-static inline void set_default_inode_attr(struct inode * inode, umode_t mode)
+static inline void set_default_inode_attr(struct inode *inode, umode_t mode)
 {
 	inode->i_mode = mode;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 }
 
-static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
+static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
 {
 	inode->i_uid = iattr->ia_uid;
 	inode->i_gid = iattr->ia_gid;
@@ -220,7 +221,8 @@
 		set_nlink(inode, sd->s_dir.subdirs + 2);
 }
 
-int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		  struct kstat *stat)
 {
 	struct sysfs_dirent *sd = dentry->d_fsdata;
 	struct inode *inode = dentry->d_inode;
@@ -285,7 +287,7 @@
  *	RETURNS:
  *	Pointer to allocated inode on success, NULL on failure.
  */
-struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
+struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
 {
 	struct inode *inode;
 
@@ -312,7 +314,8 @@
 	sysfs_put(sd);
 }
 
-int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name)
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
+			  const char *name)
 {
 	struct sysfs_addrm_cxt acxt;
 	struct sysfs_dirent *sd;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index afd8327..fd7ce7a 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -64,7 +64,7 @@
 	/* instantiate and link root dentry */
 	root = d_make_root(inode);
 	if (!root) {
-		pr_debug("%s: could not get root dentry!\n",__func__);
+		pr_debug("%s: could not get root dentry!\n", __func__);
 		return -ENOMEM;
 	}
 	root->d_fsdata = &sysfs_root;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 8c940df..2dd4507 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -125,6 +125,7 @@
 {
 	return sysfs_do_create_link(kobj, target, name, 1);
 }
+EXPORT_SYMBOL_GPL(sysfs_create_link);
 
 /**
  *	sysfs_create_link_nowarn - create symlink between two objects.
@@ -166,8 +167,7 @@
  *	@kobj:	object we're acting for.
  *	@name:	name of the symlink to remove.
  */
-
-void sysfs_remove_link(struct kobject * kobj, const char * name)
+void sysfs_remove_link(struct kobject *kobj, const char *name)
 {
 	struct sysfs_dirent *parent_sd = NULL;
 
@@ -178,6 +178,7 @@
 
 	sysfs_hash_and_remove(parent_sd, NULL, name);
 }
+EXPORT_SYMBOL_GPL(sysfs_remove_link);
 
 /**
  *	sysfs_rename_link - rename symlink in object's directory.
@@ -223,6 +224,7 @@
 	sysfs_put(sd);
 	return result;
 }
+EXPORT_SYMBOL_GPL(sysfs_rename_link);
 
 static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
 				 struct sysfs_dirent *target_sd, char *path)
@@ -276,7 +278,7 @@
 	return 0;
 }
 
-static int sysfs_getlink(struct dentry *dentry, char * path)
+static int sysfs_getlink(struct dentry *dentry, char *path)
 {
 	struct sysfs_dirent *sd = dentry->d_fsdata;
 	struct sysfs_dirent *parent_sd = sd->s_parent;
@@ -295,7 +297,7 @@
 	int error = -ENOMEM;
 	unsigned long page = get_zeroed_page(GFP_KERNEL);
 	if (page) {
-		error = sysfs_getlink(dentry, (char *) page); 
+		error = sysfs_getlink(dentry, (char *) page);
 		if (error < 0)
 			free_page((unsigned long)page);
 	}
@@ -303,7 +305,8 @@
 	return NULL;
 }
 
-static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
+static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd,
+			   void *cookie)
 {
 	char *page = nd_get_link(nd);
 	if (!IS_ERR(page))
@@ -319,8 +322,3 @@
 	.getattr	= sysfs_getattr,
 	.permission	= sysfs_permission,
 };
-
-
-EXPORT_SYMBOL_GPL(sysfs_create_link);
-EXPORT_SYMBOL_GPL(sysfs_remove_link);
-EXPORT_SYMBOL_GPL(sysfs_rename_link);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index d1e4043..b6deca3 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -78,7 +78,7 @@
 	};
 
 	unsigned short		s_flags;
-	umode_t 		s_mode;
+	umode_t			s_mode;
 	unsigned int		s_ino;
 	struct sysfs_inode_attrs *s_iattr;
 };
@@ -123,9 +123,9 @@
 		key = &attr->skey;				\
 								\
 	lockdep_init_map(&sd->dep_map, "s_active", key, 0);	\
-} while(0)
+} while (0)
 #else
-#define sysfs_dirent_init_lockdep(sd) do {} while(0)
+#define sysfs_dirent_init_lockdep(sd) do {} while (0)
 #endif
 
 /*
@@ -186,8 +186,8 @@
 			struct sysfs_dirent **p_sd);
 void sysfs_remove_subdir(struct sysfs_dirent *sd);
 
-int sysfs_rename(struct sysfs_dirent *sd,
-	struct sysfs_dirent *new_parent_sd, const void *ns, const char *new_name);
+int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
+		 const void *ns, const char *new_name);
 
 static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
 {
@@ -214,10 +214,12 @@
 int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
 int sysfs_permission(struct inode *inode, int mask);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
-int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
+int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		  struct kstat *stat);
 int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
-		size_t size, int flags);
-int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const char *name);
+		   size_t size, int flags);
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
+			  const char *name);
 int sysfs_inode_init(void);
 
 /*
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index d68b4ea..263489d 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -192,6 +192,13 @@
 	return ERR_PTR(-ENODEV);
 }
 
+static inline struct dentry *debugfs_create_x64(const char *name, umode_t mode,
+						struct dentry *parent,
+						u64 *value)
+{
+	return ERR_PTR(-ENODEV);
+}
+
 static inline struct dentry *debugfs_create_size_t(const char *name, umode_t mode,
 				     struct dentry *parent,
 				     size_t *value)
diff --git a/include/linux/device.h b/include/linux/device.h
index 7d960d5..389becc 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -66,6 +66,9 @@
  * @bus_attrs:	Default attributes of the bus.
  * @dev_attrs:	Default attributes of the devices on the bus.
  * @drv_attrs:	Default attributes of the device drivers on the bus.
+ * @bus_groups:	Default attributes of the bus.
+ * @dev_groups:	Default attributes of the devices on the bus.
+ * @drv_groups: Default attributes of the device drivers on the bus.
  * @match:	Called, perhaps multiple times, whenever a new device or driver
  *		is added for this bus. It should return a nonzero value if the
  *		given device can be handled by the given driver.
@@ -103,9 +106,12 @@
 	const char		*name;
 	const char		*dev_name;
 	struct device		*dev_root;
-	struct bus_attribute	*bus_attrs;
-	struct device_attribute	*dev_attrs;
-	struct driver_attribute	*drv_attrs;
+	struct bus_attribute	*bus_attrs;	/* use bus_groups instead */
+	struct device_attribute	*dev_attrs;	/* use dev_groups instead */
+	struct driver_attribute	*drv_attrs;	/* use drv_groups instead */
+	const struct attribute_group **bus_groups;
+	const struct attribute_group **dev_groups;
+	const struct attribute_group **drv_groups;
 
 	int (*match)(struct device *dev, struct device_driver *drv);
 	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
@@ -271,6 +277,8 @@
 	struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
 #define DRIVER_ATTR_RO(_name) \
 	struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
+#define DRIVER_ATTR_WO(_name) \
+	struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)
 
 extern int __must_check driver_create_file(struct device_driver *driver,
 					const struct driver_attribute *attr);
@@ -528,6 +536,8 @@
 	struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
 #define DEVICE_ATTR_RO(_name) \
 	struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
+#define DEVICE_ATTR_WO(_name) \
+	struct device_attribute dev_attr_##_name = __ATTR_WO(_name)
 #define DEVICE_ULONG_ATTR(_name, _mode, _var) \
 	struct dev_ext_attribute dev_attr_##_name = \
 		{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 939b112..de6dcbcc 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/wait.h>
 #include <linux/atomic.h>
+#include <linux/workqueue.h>
 
 #define UEVENT_HELPER_PATH_LEN		256
 #define UEVENT_NUM_ENVP			32	/* number of env pointers */
@@ -65,6 +66,9 @@
 	struct kobj_type	*ktype;
 	struct sysfs_dirent	*sd;
 	struct kref		kref;
+#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
+	struct delayed_work	release;
+#endif
 	unsigned int state_initialized:1;
 	unsigned int state_in_sysfs:1;
 	unsigned int state_add_uevent_sent:1;
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 85c31a8..9a6bbf7 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -25,16 +25,9 @@
 struct memory_block {
 	unsigned long start_section_nr;
 	unsigned long end_section_nr;
-	unsigned long state;
-	int section_count;
-
-	/*
-	 * This serializes all state change requests.  It isn't
-	 * held during creation because the control files are
-	 * created long after the critical areas during
-	 * initialization.
-	 */
-	struct mutex state_mutex;
+	unsigned long state;		/* serialized by the dev->lock */
+	int section_count;		/* serialized by mem_sysfs_mutex */
+	int online_type;		/* for passing data to online routine */
 	int phys_device;		/* to which fru does this belong? */
 	void *hw;			/* optional pointer to fw/hw data */
 	int (*phys_callback)(struct memory_block *);
@@ -125,7 +118,6 @@
 							struct memory_block *);
 extern struct memory_block *find_memory_block(struct mem_section *);
 #define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
-enum mem_add_context { BOOT, HOTPLUG };
 #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h
index 7db3eb9..1d2cd21 100644
--- a/include/linux/pps_kernel.h
+++ b/include/linux/pps_kernel.h
@@ -80,7 +80,7 @@
  * Global variables
  */
 
-extern struct device_attribute pps_attrs[];
+extern const struct attribute_group *pps_groups[];
 
 /*
  * Internal functions.
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 9e8a9b5..11baec7 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -51,9 +51,9 @@
 	static struct lock_class_key __key;		\
 							\
 	(attr)->key = &__key;				\
-} while(0)
+} while (0)
 #else
-#define sysfs_attr_init(attr) do {} while(0)
+#define sysfs_attr_init(attr) do {} while (0)
 #endif
 
 struct attribute_group {
@@ -69,7 +69,7 @@
  * for examples..
  */
 
-#define __ATTR(_name,_mode,_show,_store) { 				\
+#define __ATTR(_name, _mode, _show, _store) {				\
 	.attr = {.name = __stringify(_name), .mode = _mode },		\
 	.show	= _show,						\
 	.store	= _store,						\
@@ -80,6 +80,11 @@
 	.show	= _name##_show,						\
 }
 
+#define __ATTR_WO(_name) {						\
+	.attr	= { .name = __stringify(_name), .mode = S_IWUSR },	\
+	.store	= _name##_store,					\
+}
+
 #define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO),		\
 			 _name##_show, _name##_store)
 
@@ -108,8 +113,6 @@
 };								\
 __ATTRIBUTE_GROUPS(_name)
 
-#define attr_name(_attr) (_attr).attr.name
-
 struct file;
 struct vm_area_struct;
 
@@ -119,7 +122,7 @@
 	void			*private;
 	ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
 			char *, loff_t, size_t);
-	ssize_t (*write)(struct file *,struct kobject *, struct bin_attribute *,
+	ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
 			 char *, loff_t, size_t);
 	int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
 		    struct vm_area_struct *vma);
@@ -153,7 +156,7 @@
 
 #define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name,			\
 				   (S_IWUSR | S_IRUGO), _name##_read,	\
-				   _name##_write)
+				   _name##_write, _size)
 
 #define __BIN_ATTR_NULL __ATTR_NULL
 
@@ -168,8 +171,8 @@
 struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
 
 struct sysfs_ops {
-	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
-	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
+	ssize_t	(*show)(struct kobject *, struct attribute *, char *);
+	ssize_t	(*store)(struct kobject *, struct attribute *, const char *, size_t);
 	const void *(*namespace)(struct kobject *, const struct attribute *);
 };
 
@@ -215,10 +218,14 @@
 
 int __must_check sysfs_create_group(struct kobject *kobj,
 				    const struct attribute_group *grp);
+int __must_check sysfs_create_groups(struct kobject *kobj,
+				     const struct attribute_group **groups);
 int sysfs_update_group(struct kobject *kobj,
 		       const struct attribute_group *grp);
 void sysfs_remove_group(struct kobject *kobj,
 			const struct attribute_group *grp);
+void sysfs_remove_groups(struct kobject *kobj,
+			 const struct attribute_group **groups);
 int sysfs_add_file_to_group(struct kobject *kobj,
 			const struct attribute *attr, const char *group);
 void sysfs_remove_file_from_group(struct kobject *kobj,
@@ -343,6 +350,12 @@
 	return 0;
 }
 
+static inline int sysfs_create_groups(struct kobject *kobj,
+				      const struct attribute_group **groups)
+{
+	return 0;
+}
+
 static inline int sysfs_update_group(struct kobject *kobj,
 				const struct attribute_group *grp)
 {
@@ -354,6 +367,11 @@
 {
 }
 
+static inline void sysfs_remove_groups(struct kobject *kobj,
+				       const struct attribute_group **groups)
+{
+}
+
 static inline int sysfs_add_file_to_group(struct kobject *kobj,
 		const struct attribute *attr, const char *group)
 {
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index e93f7b9..5f8ee91 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3095,25 +3095,26 @@
 	return wq_dev->wq;
 }
 
-static ssize_t wq_per_cpu_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
+static ssize_t per_cpu_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct workqueue_struct *wq = dev_to_wq(dev);
 
 	return scnprintf(buf, PAGE_SIZE, "%d\n", (bool)!(wq->flags & WQ_UNBOUND));
 }
+static DEVICE_ATTR_RO(per_cpu);
 
-static ssize_t wq_max_active_show(struct device *dev,
-				  struct device_attribute *attr, char *buf)
+static ssize_t max_active_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct workqueue_struct *wq = dev_to_wq(dev);
 
 	return scnprintf(buf, PAGE_SIZE, "%d\n", wq->saved_max_active);
 }
 
-static ssize_t wq_max_active_store(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t count)
+static ssize_t max_active_store(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count)
 {
 	struct workqueue_struct *wq = dev_to_wq(dev);
 	int val;
@@ -3124,12 +3125,14 @@
 	workqueue_set_max_active(wq, val);
 	return count;
 }
+static DEVICE_ATTR_RW(max_active);
 
-static struct device_attribute wq_sysfs_attrs[] = {
-	__ATTR(per_cpu, 0444, wq_per_cpu_show, NULL),
-	__ATTR(max_active, 0644, wq_max_active_show, wq_max_active_store),
-	__ATTR_NULL,
+static struct attribute *wq_sysfs_attrs[] = {
+	&dev_attr_per_cpu.attr,
+	&dev_attr_max_active.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(wq_sysfs);
 
 static ssize_t wq_pool_ids_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
@@ -3279,7 +3282,7 @@
 
 static struct bus_type wq_subsys = {
 	.name				= "workqueue",
-	.dev_attrs			= wq_sysfs_attrs,
+	.dev_groups			= wq_sysfs_groups,
 };
 
 static int __init wq_sysfs_init(void)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1501aa5..444e1c1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -981,6 +981,25 @@
 	  If you say Y here, some extra kobject debugging messages will be sent
 	  to the syslog. 
 
+config DEBUG_KOBJECT_RELEASE
+	bool "kobject release debugging"
+	depends on DEBUG_KERNEL
+	help
+	  kobjects are reference counted objects.  This means that their
+	  last reference count put is not predictable, and the kobject can
+	  live on past the point at which a driver decides to drop it's
+	  initial reference to the kobject gained on allocation.  An
+	  example of this would be a struct device which has just been
+	  unregistered.
+
+	  However, some buggy drivers assume that after such an operation,
+	  the memory backing the kobject can be immediately freed.  This
+	  goes completely against the principles of a refcounted object.
+
+	  If you say Y here, the kernel will delay the release of kobjects
+	  on the last reference count to improve the visibility of this
+	  kind of kobject release bug.
+
 config HAVE_DEBUG_BUGVERBOSE
 	bool
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 99fec3a..c37aeac 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -309,7 +309,7 @@
 			struct ddebug_query *query, const char *modname)
 {
 	unsigned int i;
-	int rc;
+	int rc = 0;
 
 	/* check we have an even number of words */
 	if (nwords % 2 != 0) {
diff --git a/lib/kobject.c b/lib/kobject.c
index 4a1f33d..1d46c15 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -545,8 +545,8 @@
 	struct kobj_type *t = get_ktype(kobj);
 	const char *name = kobj->name;
 
-	pr_debug("kobject: '%s' (%p): %s\n",
-		 kobject_name(kobj), kobj, __func__);
+	pr_debug("kobject: '%s' (%p): %s, parent %p\n",
+		 kobject_name(kobj), kobj, __func__, kobj->parent);
 
 	if (t && !t->release)
 		pr_debug("kobject: '%s' (%p): does not have a release() "
@@ -580,9 +580,25 @@
 	}
 }
 
+#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
+static void kobject_delayed_cleanup(struct work_struct *work)
+{
+	kobject_cleanup(container_of(to_delayed_work(work),
+				     struct kobject, release));
+}
+#endif
+
 static void kobject_release(struct kref *kref)
 {
-	kobject_cleanup(container_of(kref, struct kobject, kref));
+	struct kobject *kobj = container_of(kref, struct kobject, kref);
+#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
+	pr_debug("kobject: '%s' (%p): %s, parent %p (delayed)\n",
+		 kobject_name(kobj), kobj, __func__, kobj->parent);
+	INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
+	schedule_delayed_work(&kobj->release, HZ);
+#else
+	kobject_cleanup(kobj);
+#endif
 }
 
 /**
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index e04454c..37d9edc 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -180,7 +180,8 @@
 	struct backing_dev_info *bdi = dev_get_drvdata(dev);		\
 									\
 	return snprintf(page, PAGE_SIZE-1, "%lld\n", (long long)expr);	\
-}
+}									\
+static DEVICE_ATTR_RW(name);
 
 BDI_SHOW(read_ahead_kb, K(bdi->ra_pages))
 
@@ -231,14 +232,16 @@
 	return snprintf(page, PAGE_SIZE-1, "%d\n",
 			bdi_cap_stable_pages_required(bdi) ? 1 : 0);
 }
+static DEVICE_ATTR_RO(stable_pages_required);
 
-static struct device_attribute bdi_dev_attrs[] = {
-	__ATTR_RW(read_ahead_kb),
-	__ATTR_RW(min_ratio),
-	__ATTR_RW(max_ratio),
-	__ATTR_RO(stable_pages_required),
-	__ATTR_NULL,
+static struct attribute *bdi_dev_attrs[] = {
+	&dev_attr_read_ahead_kb.attr,
+	&dev_attr_min_ratio.attr,
+	&dev_attr_max_ratio.attr,
+	&dev_attr_stable_pages_required.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(bdi_dev);
 
 static __init int bdi_class_init(void)
 {
@@ -246,7 +249,7 @@
 	if (IS_ERR(bdi_class))
 		return PTR_ERR(bdi_class);
 
-	bdi_class->dev_attrs = bdi_dev_attrs;
+	bdi_class->dev_groups = bdi_dev_groups;
 	bdi_debug_init();
 	return 0;
 }
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 981fed3..707c313 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -60,12 +60,19 @@
 {									\
 	return sprintf(buf, format_string, net->field);			\
 }									\
-static ssize_t show_##field(struct device *dev,				\
+static ssize_t field##_show(struct device *dev,				\
 			    struct device_attribute *attr, char *buf)	\
 {									\
 	return netdev_show(dev, attr, buf, format_##field);		\
-}
+}									\
 
+#define NETDEVICE_SHOW_RO(field, format_string)				\
+NETDEVICE_SHOW(field, format_string);					\
+static DEVICE_ATTR_RO(field)
+
+#define NETDEVICE_SHOW_RW(field, format_string)				\
+NETDEVICE_SHOW(field, format_string);					\
+static DEVICE_ATTR_RW(field)
 
 /* use same locking and permission rules as SIF* ioctl's */
 static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
@@ -96,16 +103,16 @@
 	return ret;
 }
 
-NETDEVICE_SHOW(dev_id, fmt_hex);
-NETDEVICE_SHOW(addr_assign_type, fmt_dec);
-NETDEVICE_SHOW(addr_len, fmt_dec);
-NETDEVICE_SHOW(iflink, fmt_dec);
-NETDEVICE_SHOW(ifindex, fmt_dec);
-NETDEVICE_SHOW(type, fmt_dec);
-NETDEVICE_SHOW(link_mode, fmt_dec);
+NETDEVICE_SHOW_RO(dev_id, fmt_hex);
+NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec);
+NETDEVICE_SHOW_RO(addr_len, fmt_dec);
+NETDEVICE_SHOW_RO(iflink, fmt_dec);
+NETDEVICE_SHOW_RO(ifindex, fmt_dec);
+NETDEVICE_SHOW_RO(type, fmt_dec);
+NETDEVICE_SHOW_RO(link_mode, fmt_dec);
 
 /* use same locking rules as GIFHWADDR ioctl's */
-static ssize_t show_address(struct device *dev, struct device_attribute *attr,
+static ssize_t address_show(struct device *dev, struct device_attribute *attr,
 			    char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
@@ -117,15 +124,17 @@
 	read_unlock(&dev_base_lock);
 	return ret;
 }
+static DEVICE_ATTR_RO(address);
 
-static ssize_t show_broadcast(struct device *dev,
-			    struct device_attribute *attr, char *buf)
+static ssize_t broadcast_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct net_device *net = to_net_dev(dev);
 	if (dev_isalive(net))
 		return sysfs_format_mac(buf, net->broadcast, net->addr_len);
 	return -EINVAL;
 }
+static DEVICE_ATTR_RO(broadcast);
 
 static int change_carrier(struct net_device *net, unsigned long new_carrier)
 {
@@ -134,13 +143,13 @@
 	return dev_change_carrier(net, (bool) new_carrier);
 }
 
-static ssize_t store_carrier(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t len)
+static ssize_t carrier_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_carrier);
 }
 
-static ssize_t show_carrier(struct device *dev,
+static ssize_t carrier_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -149,8 +158,9 @@
 	}
 	return -EINVAL;
 }
+static DEVICE_ATTR_RW(carrier);
 
-static ssize_t show_speed(struct device *dev,
+static ssize_t speed_show(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -167,8 +177,9 @@
 	rtnl_unlock();
 	return ret;
 }
+static DEVICE_ATTR_RO(speed);
 
-static ssize_t show_duplex(struct device *dev,
+static ssize_t duplex_show(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -198,8 +209,9 @@
 	rtnl_unlock();
 	return ret;
 }
+static DEVICE_ATTR_RO(duplex);
 
-static ssize_t show_dormant(struct device *dev,
+static ssize_t dormant_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -209,6 +221,7 @@
 
 	return -EINVAL;
 }
+static DEVICE_ATTR_RO(dormant);
 
 static const char *const operstates[] = {
 	"unknown",
@@ -220,7 +233,7 @@
 	"up"
 };
 
-static ssize_t show_operstate(struct device *dev,
+static ssize_t operstate_show(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 {
 	const struct net_device *netdev = to_net_dev(dev);
@@ -237,35 +250,33 @@
 
 	return sprintf(buf, "%s\n", operstates[operstate]);
 }
+static DEVICE_ATTR_RO(operstate);
 
 /* read-write attributes */
-NETDEVICE_SHOW(mtu, fmt_dec);
 
 static int change_mtu(struct net_device *net, unsigned long new_mtu)
 {
 	return dev_set_mtu(net, (int) new_mtu);
 }
 
-static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
+static ssize_t mtu_store(struct device *dev, struct device_attribute *attr,
 			 const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_mtu);
 }
-
-NETDEVICE_SHOW(flags, fmt_hex);
+NETDEVICE_SHOW_RW(mtu, fmt_dec);
 
 static int change_flags(struct net_device *net, unsigned long new_flags)
 {
 	return dev_change_flags(net, (unsigned int) new_flags);
 }
 
-static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
+static ssize_t flags_store(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_flags);
 }
-
-NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
+NETDEVICE_SHOW_RW(flags, fmt_hex);
 
 static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
 {
@@ -273,7 +284,7 @@
 	return 0;
 }
 
-static ssize_t store_tx_queue_len(struct device *dev,
+static ssize_t tx_queue_len_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t len)
 {
@@ -282,8 +293,9 @@
 
 	return netdev_store(dev, attr, buf, len, change_tx_queue_len);
 }
+NETDEVICE_SHOW_RW(tx_queue_len, fmt_ulong);
 
-static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
+static ssize_t ifalias_store(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t len)
 {
 	struct net_device *netdev = to_net_dev(dev);
@@ -306,7 +318,7 @@
 	return ret < 0 ? ret : len;
 }
 
-static ssize_t show_ifalias(struct device *dev,
+static ssize_t ifalias_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	const struct net_device *netdev = to_net_dev(dev);
@@ -319,8 +331,7 @@
 	rtnl_unlock();
 	return ret;
 }
-
-NETDEVICE_SHOW(group, fmt_dec);
+static DEVICE_ATTR_RW(ifalias);
 
 static int change_group(struct net_device *net, unsigned long new_group)
 {
@@ -328,35 +339,37 @@
 	return 0;
 }
 
-static ssize_t store_group(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t len)
+static ssize_t group_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t len)
 {
 	return netdev_store(dev, attr, buf, len, change_group);
 }
+NETDEVICE_SHOW(group, fmt_dec);
+static DEVICE_ATTR(netdev_group, S_IRUGO | S_IWUSR, group_show, group_store);
 
-static struct device_attribute net_class_attributes[] = {
-	__ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL),
-	__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
-	__ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
-	__ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias),
-	__ATTR(iflink, S_IRUGO, show_iflink, NULL),
-	__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
-	__ATTR(type, S_IRUGO, show_type, NULL),
-	__ATTR(link_mode, S_IRUGO, show_link_mode, NULL),
-	__ATTR(address, S_IRUGO, show_address, NULL),
-	__ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
-	__ATTR(carrier, S_IRUGO | S_IWUSR, show_carrier, store_carrier),
-	__ATTR(speed, S_IRUGO, show_speed, NULL),
-	__ATTR(duplex, S_IRUGO, show_duplex, NULL),
-	__ATTR(dormant, S_IRUGO, show_dormant, NULL),
-	__ATTR(operstate, S_IRUGO, show_operstate, NULL),
-	__ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
-	__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
-	__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
-	       store_tx_queue_len),
-	__ATTR(netdev_group, S_IRUGO | S_IWUSR, show_group, store_group),
-	{}
+static struct attribute *net_class_attrs[] = {
+	&dev_attr_netdev_group.attr,
+	&dev_attr_type.attr,
+	&dev_attr_dev_id.attr,
+	&dev_attr_iflink.attr,
+	&dev_attr_ifindex.attr,
+	&dev_attr_addr_assign_type.attr,
+	&dev_attr_addr_len.attr,
+	&dev_attr_link_mode.attr,
+	&dev_attr_address.attr,
+	&dev_attr_broadcast.attr,
+	&dev_attr_speed.attr,
+	&dev_attr_duplex.attr,
+	&dev_attr_dormant.attr,
+	&dev_attr_operstate.attr,
+	&dev_attr_ifalias.attr,
+	&dev_attr_carrier.attr,
+	&dev_attr_mtu.attr,
+	&dev_attr_flags.attr,
+	&dev_attr_tx_queue_len.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(net_class);
 
 /* Show a given an attribute in the statistics group */
 static ssize_t netstat_show(const struct device *d,
@@ -382,13 +395,13 @@
 
 /* generate a read-only statistics attribute */
 #define NETSTAT_ENTRY(name)						\
-static ssize_t show_##name(struct device *d,				\
+static ssize_t name##_show(struct device *d,				\
 			   struct device_attribute *attr, char *buf) 	\
 {									\
 	return netstat_show(d, attr, buf,				\
 			    offsetof(struct rtnl_link_stats64, name));	\
 }									\
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR_RO(name)
 
 NETSTAT_ENTRY(rx_packets);
 NETSTAT_ENTRY(tx_packets);
@@ -457,6 +470,9 @@
 	.attrs = wireless_attrs,
 };
 #endif
+
+#else /* CONFIG_SYSFS */
+#define net_class_groups	NULL
 #endif /* CONFIG_SYSFS */
 
 #ifdef CONFIG_RPS
@@ -1229,9 +1245,7 @@
 static struct class net_class = {
 	.name = "net",
 	.dev_release = netdev_release,
-#ifdef CONFIG_SYSFS
-	.dev_attrs = net_class_attributes,
-#endif /* CONFIG_SYSFS */
+	.dev_groups = net_class_groups,
 	.dev_uevent = netdev_uevent,
 	.ns_type = &net_ns_type_operations,
 	.namespace = net_namespace,
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
index 13571ea..ef56ab5 100644
--- a/net/ieee802154/wpan-class.c
+++ b/net/ieee802154/wpan-class.c
@@ -36,7 +36,8 @@
 	ret = snprintf(buf, PAGE_SIZE, format_string "\n", args);	\
 	mutex_unlock(&phy->pib_lock);					\
 	return ret;							\
-}
+}									\
+static DEVICE_ATTR_RO(name);
 
 #define MASTER_SHOW(field, format_string)				\
 	MASTER_SHOW_COMPLEX(field, format_string, phy->field)
@@ -66,15 +67,17 @@
 	mutex_unlock(&phy->pib_lock);
 	return len;
 }
+static DEVICE_ATTR_RO(channels_supported);
 
-static struct device_attribute pmib_attrs[] = {
-	__ATTR_RO(current_channel),
-	__ATTR_RO(current_page),
-	__ATTR_RO(channels_supported),
-	__ATTR_RO(transmit_power),
-	__ATTR_RO(cca_mode),
-	{},
+static struct attribute *pmib_attrs[] = {
+	&dev_attr_current_channel.attr,
+	&dev_attr_current_page.attr,
+	&dev_attr_channels_supported.attr,
+	&dev_attr_transmit_power.attr,
+	&dev_attr_cca_mode.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(pmib);
 
 static void wpan_phy_release(struct device *d)
 {
@@ -85,7 +88,7 @@
 static struct class wpan_phy_class = {
 	.name = "ieee802154",
 	.dev_release = wpan_phy_release,
-	.dev_attrs = pmib_attrs,
+	.dev_groups = pmib_groups,
 };
 
 static DEFINE_MUTEX(wpan_phy_mutex);
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 1cec5e4..1bacc10 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -576,14 +576,14 @@
 }
 EXPORT_SYMBOL(rfkill_set_states);
 
-static ssize_t rfkill_name_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%s\n", rfkill->name);
 }
+static DEVICE_ATTR_RO(name);
 
 static const char *rfkill_get_type_str(enum rfkill_type type)
 {
@@ -611,54 +611,52 @@
 	}
 }
 
-static ssize_t rfkill_type_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type));
 }
+static DEVICE_ATTR_RO(type);
 
-static ssize_t rfkill_idx_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
+static ssize_t index_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", rfkill->idx);
 }
+static DEVICE_ATTR_RO(index);
 
-static ssize_t rfkill_persistent_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
+static ssize_t persistent_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", rfkill->persistent);
 }
+static DEVICE_ATTR_RO(persistent);
 
-static ssize_t rfkill_hard_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t hard_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 );
 }
+static DEVICE_ATTR_RO(hard);
 
-static ssize_t rfkill_soft_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 );
 }
 
-static ssize_t rfkill_soft_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
+static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 	unsigned long state;
@@ -680,6 +678,7 @@
 
 	return count;
 }
+static DEVICE_ATTR_RW(soft);
 
 static u8 user_state_from_blocked(unsigned long state)
 {
@@ -691,18 +690,16 @@
 	return RFKILL_USER_STATE_UNBLOCKED;
 }
 
-static ssize_t rfkill_state_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 
 	return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state));
 }
 
-static ssize_t rfkill_state_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
+static ssize_t state_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
 	struct rfkill *rfkill = to_rfkill(dev);
 	unsigned long state;
@@ -725,32 +722,27 @@
 
 	return count;
 }
+static DEVICE_ATTR_RW(state);
 
-static ssize_t rfkill_claim_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
+static ssize_t claim_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
+static DEVICE_ATTR_RO(claim);
 
-static ssize_t rfkill_claim_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
-{
-	return -EOPNOTSUPP;
-}
-
-static struct device_attribute rfkill_dev_attrs[] = {
-	__ATTR(name, S_IRUGO, rfkill_name_show, NULL),
-	__ATTR(type, S_IRUGO, rfkill_type_show, NULL),
-	__ATTR(index, S_IRUGO, rfkill_idx_show, NULL),
-	__ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL),
-	__ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store),
-	__ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store),
-	__ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store),
-	__ATTR(hard, S_IRUGO, rfkill_hard_show, NULL),
-	__ATTR_NULL
+static struct attribute *rfkill_dev_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_type.attr,
+	&dev_attr_index.attr,
+	&dev_attr_persistent.attr,
+	&dev_attr_state.attr,
+	&dev_attr_claim.attr,
+	&dev_attr_soft.attr,
+	&dev_attr_hard.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(rfkill_dev);
 
 static void rfkill_release(struct device *dev)
 {
@@ -830,7 +822,7 @@
 static struct class rfkill_class = {
 	.name		= "rfkill",
 	.dev_release	= rfkill_release,
-	.dev_attrs	= rfkill_dev_attrs,
+	.dev_groups	= rfkill_dev_groups,
 	.dev_uevent	= rfkill_dev_uevent,
 	.suspend	= rfkill_suspend,
 	.resume		= rfkill_resume,
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index a23253e..9ee6bc1 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -30,7 +30,8 @@
 			      char *buf)				\
 {									\
 	return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member);	\
-}
+}									\
+static DEVICE_ATTR_RO(name)
 
 SHOW_FMT(index, "%d", wiphy_idx);
 SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
@@ -42,7 +43,7 @@
 	struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
 	return sprintf(buf, "%s\n", dev_name(&wiphy->dev));
 }
-
+static DEVICE_ATTR_RO(name);
 
 static ssize_t addresses_show(struct device *dev,
 			      struct device_attribute *attr,
@@ -60,15 +61,17 @@
 
 	return buf - start;
 }
+static DEVICE_ATTR_RO(addresses);
 
-static struct device_attribute ieee80211_dev_attrs[] = {
-	__ATTR_RO(index),
-	__ATTR_RO(macaddress),
-	__ATTR_RO(address_mask),
-	__ATTR_RO(addresses),
-	__ATTR_RO(name),
-	{}
+static struct attribute *ieee80211_attrs[] = {
+	&dev_attr_index.attr,
+	&dev_attr_macaddress.attr,
+	&dev_attr_address_mask.attr,
+	&dev_attr_addresses.attr,
+	&dev_attr_name.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(ieee80211);
 
 static void wiphy_dev_release(struct device *dev)
 {
@@ -146,7 +149,7 @@
 	.name = "ieee80211",
 	.owner = THIS_MODULE,
 	.dev_release = wiphy_dev_release,
-	.dev_attrs = ieee80211_dev_attrs,
+	.dev_groups = ieee80211_groups,
 	.dev_uevent = wiphy_uevent,
 #ifdef CONFIG_PM
 	.suspend = wiphy_suspend,