[kernel] r19164 - in dists/sid/linux/debian: . patches patches/bugfix/all patches/features/all patches/features/all/cpu-devices

Ben Hutchings benh at alioth.debian.org
Mon Jun 18 05:14:27 UTC 2012


Author: benh
Date: Mon Jun 18 05:14:25 2012
New Revision: 19164

Log:
CPU sysdev removal from 3.3 and x86 CPU auto-loading from 3.4

* cpu: Convert 'cpu' and 'machinecheck' sysdev_class to a regular subsystem
* [x86] Add driver auto probing for x86 features
  - crypto: Add support for x86 cpuid auto loading for x86 crypto drivers
    (Closes: #568008)
  - intel-idle: convert to x86_cpu_id auto probing
  - HWMON: Convert coretemp to x86 cpuid autoprobing
  - HWMON: Convert via-cputemp to x86 cpuid autoprobing
  - cpufreq: Add support for x86 cpuinfo auto loading (Closes: #664813)
* [x86] ACPI: Load acpi-cpufreq from processor driver automatically

Added:
   dists/sid/linux/debian/patches/features/all/cpu-devices/
   dists/sid/linux/debian/patches/features/all/cpu-devices/ACPI-Load-acpi-cpufreq-from-processor-driver-automat.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/Add-driver-auto-probing-for-x86-features-v4.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/CPU-Introduce-ARCH_HAS_CPU_AUTOPROBE-and-X86-parts.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/HWMON-Convert-coretemp-to-x86-cpuid-autoprobing.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/HWMON-Convert-via-cputemp-to-x86-cpuid-autoprobing.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/Partially-revert-cpufreq-Add-support-for-x86-cpuinfo.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/X86-Introduce-HW-Pstate-scattered-cpuid-feature.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-Register-a-generic-CPU-device-on-architectures-t.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-convert-cpu-and-machinecheck-sysdev_class-to-a-r.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/cpufreq-Add-support-for-x86-cpuinfo-auto-loading-v4.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/crypto-Add-support-for-x86-cpuid-auto-loading-for-x8.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-cpu-fix-kobject-warning-when-hotplugging.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-cpu-remove-kernel-warning-when-removing-.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-implement-sysdev-functionality-for-regul.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/intel-idle-convert-to-x86_cpu_id-auto-probing.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/intel_idle-Fix-ID-for-Nehalem-EX-Xeon-in-device-ID-t.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/intel_idle-Revert-change-of-auto_demotion_disable_fl.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/powernow-k6-Really-enable-auto-loading.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/powernow-k7-Fix-CPU-family-number.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/x86-cpu-Clean-up-modalias-feature-matching.patch
   dists/sid/linux/debian/patches/features/all/cpu-devices/x86-cpu-Fix-overrun-check-in-arch_print_cpu_modalias.patch
Deleted:
   dists/sid/linux/debian/patches/bugfix/all/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch
   dists/sid/linux/debian/patches/bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch
   dists/sid/linux/debian/patches/features/all/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch
Modified:
   dists/sid/linux/debian/changelog
   dists/sid/linux/debian/patches/series

Modified: dists/sid/linux/debian/changelog
==============================================================================
--- dists/sid/linux/debian/changelog	Sun Jun 17 19:52:06 2012	(r19163)
+++ dists/sid/linux/debian/changelog	Mon Jun 18 05:14:25 2012	(r19164)
@@ -6,7 +6,16 @@
   * [arm,m68k,sh4] udeb: Build ipv6-modules
   * ethtool: allow ETHTOOL_GSSET_INFO for users
   * [rt] bump version to 3.2.20-rt32
-  
+  * cpu: Convert 'cpu' and 'machinecheck' sysdev_class to a regular subsystem
+  * [x86] Add driver auto probing for x86 features
+    - crypto: Add support for x86 cpuid auto loading for x86 crypto drivers
+      (Closes: #568008)
+    - intel-idle: convert to x86_cpu_id auto probing
+    - HWMON: Convert coretemp to x86 cpuid autoprobing
+    - HWMON: Convert via-cputemp to x86 cpuid autoprobing
+    - cpufreq: Add support for x86 cpuinfo auto loading (Closes: #664813)
+  * [x86] ACPI: Load acpi-cpufreq from processor driver automatically
+
   [ Aurelien Jarno ]
   * [mips,mipsel] udeb: Remove rivafb and nvidiafb.
   * [ppc64]: add udebs, based on powerpc/powerpc64.

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/ACPI-Load-acpi-cpufreq-from-processor-driver-automat.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/ACPI-Load-acpi-cpufreq-from-processor-driver-automat.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,81 @@
+From: Andi Kleen <ak at linux.intel.com>
+Date: Thu, 26 Jan 2012 00:09:08 +0100
+Subject: ACPI: Load acpi-cpufreq from processor driver automatically
+
+commit 9061e0e16700ef228837e96987ff51794c956197 upstream.
+
+The only left over hole in automatic cpufreq driver loading was the loading
+of ACPI cpufreq. This driver should be loaded when ACPI supports a _PDC
+method and the CPU vendor wants to use acpi cpufreq.
+
+Simply add a request module call to the acpi processor core driver
+when this is true. This seems like the simplest solution for this.
+
+Cc: Len Brown <lenb at kernel.org>
+Signed-off-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/acpi/processor_driver.c  |    1 +
+ drivers/acpi/processor_perflib.c |   22 ++++++++++++++++++++++
+ include/acpi/processor.h         |    1 +
+ 3 files changed, 24 insertions(+)
+
+diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
+index 0034ede..e6920d0 100644
+--- a/drivers/acpi/processor_driver.c
++++ b/drivers/acpi/processor_driver.c
+@@ -497,6 +497,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
+ 
+ #ifdef CONFIG_CPU_FREQ
+ 	acpi_processor_ppc_has_changed(pr, 0);
++	acpi_processor_load_module(pr);
+ #endif
+ 	acpi_processor_get_throttling_info(pr);
+ 	acpi_processor_get_limit_info(pr);
+diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
+index 85b3237..0af48a8 100644
+--- a/drivers/acpi/processor_perflib.c
++++ b/drivers/acpi/processor_perflib.c
+@@ -240,6 +240,28 @@ void acpi_processor_ppc_exit(void)
+ 	acpi_processor_ppc_status &= ~PPC_REGISTERED;
+ }
+ 
++/*
++ * Do a quick check if the systems looks like it should use ACPI
++ * cpufreq. We look at a _PCT method being available, but don't
++ * do a whole lot of sanity checks.
++ */
++void acpi_processor_load_module(struct acpi_processor *pr)
++{
++	static int requested;
++	acpi_status status = 0;
++	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
++
++	if (!arch_has_acpi_pdc() || requested)
++		return;
++	status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
++	if (!ACPI_FAILURE(status)) {
++		printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n");
++		request_module_nowait("acpi_cpufreq");
++		requested = 1;
++	}
++	kfree(buffer.pointer);
++}
++
+ static int acpi_processor_get_performance_control(struct acpi_processor *pr)
+ {
+ 	int result = 0;
+diff --git a/include/acpi/processor.h b/include/acpi/processor.h
+index 610f6fb..da57fdc 100644
+--- a/include/acpi/processor.h
++++ b/include/acpi/processor.h
+@@ -224,6 +224,7 @@ struct acpi_processor_errata {
+ 	} piix4;
+ };
+ 
++extern void acpi_processor_load_module(struct acpi_processor *pr);
+ extern int acpi_processor_preregister_performance(struct
+ 						  acpi_processor_performance
+ 						  __percpu *performance);

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/Add-driver-auto-probing-for-x86-features-v4.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/Add-driver-auto-probing-for-x86-features-v4.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,313 @@
+From: Andi Kleen <ak at linux.intel.com>
+Date: Thu, 26 Jan 2012 00:09:05 +0100
+Subject: Add driver auto probing for x86 features v4
+
+commit 644e9cbbe3fc032cc92d0936057e166a994dc246 upstream.
+
+There's a growing number of drivers that support a specific x86 feature
+or CPU.  Currently loading these drivers currently on a generic
+distribution requires various driver specific hacks and it often
+doesn't work.
+
+This patch adds auto probing for drivers based on the x86 cpuid
+information, in particular based on vendor/family/model number
+and also based on CPUID feature bits.
+
+For example a common issue is not loading the SSE 4.2 accelerated
+CRC module: this can significantly lower the performance of BTRFS
+which relies on fast CRC.
+
+Another issue is loading the right CPUFREQ driver for the current CPU.
+Currently distributions often try all all possible driver until
+one sticks, which is not really a good way to do this.
+
+It works with existing udev without any changes. The code
+exports the x86 information as a generic string in sysfs
+that can be matched by udev's pattern matching.
+
+This scheme does not support numeric ranges, so if you want to
+handle e.g. ranges of model numbers they have to be encoded
+in ASCII or simply all models or families listed. Fixing
+that would require changing udev.
+
+Another issue is that udev will happily load all drivers that match,
+there is currently no nice way to stop a specific driver from
+being loaded if it's not needed (e.g. if you don't need fast CRC)
+But there are not that many cpu specific drivers around and they're
+all not that bloated, so this isn't a particularly serious issue.
+
+Originally this patch added the modalias to the normal cpu
+sysdevs. However sysdevs don't have all the infrastructure
+needed for udev, so it couldn't really autoload drivers.
+This patch instead adds the CPU modaliases to the cpuid devices,
+which are real devices with full support for udev. This implies
+that the cpuid driver has to be loaded to use this.
+
+This patch just adds infrastructure, some driver conversions
+in followups.
+
+Thanks to Kay for helping with some sysfs magic.
+
+v2: Constifcation, some updates
+v4: (trenn at suse.de):
+    - Use kzalloc instead of kmalloc to terminate modalias buffer
+    - Use uppercase hex values to match correctly against hex values containing
+      letters
+
+Cc: Dave Jones <davej at redhat.com>
+Cc: Kay Sievers <kay.sievers at vrfy.org>
+Cc: Jen Axboe <axboe at kernel.dk>
+Cc: Herbert Xu <herbert at gondor.apana.org.au>
+Cc: Huang Ying <ying.huang at intel.com>
+Cc: Len Brown <lenb at kernel.org>
+Signed-off-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+[bwh: Backported to 3.2:
+ - adjust context
+ - make do without ADD_TO_DEVTABLE in file2alias]
+---
+--- /dev/null
++++ b/arch/x86/include/asm/cpu_device_id.h
+@@ -0,0 +1,13 @@
++#ifndef _CPU_DEVICE_ID
++#define _CPU_DEVICE_ID 1
++
++/*
++ * Declare drivers belonging to specific x86 CPUs
++ * Similar in spirit to pci_device_id and related PCI functions
++ */
++
++#include <linux/mod_devicetable.h>
++
++extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match);
++
++#endif
+--- a/arch/x86/kernel/cpu/Makefile
++++ b/arch/x86/kernel/cpu/Makefile
+@@ -16,6 +16,7 @@
+ obj-y			+= proc.o capflags.o powerflags.o common.o
+ obj-y			+= vmware.o hypervisor.o sched.o mshyperv.o
+ obj-y			+= rdrand.o
++obj-y			+= match.o
+ 
+ obj-$(CONFIG_X86_32)	+= bugs.o
+ obj-$(CONFIG_X86_64)	+= bugs_64.o
+--- /dev/null
++++ b/arch/x86/kernel/cpu/match.c
+@@ -0,0 +1,48 @@
++#include <asm/cpu_device_id.h>
++#include <asm/processor.h>
++#include <linux/cpu.h>
++#include <linux/module.h>
++
++/**
++ * x86_match_cpu - match current CPU again an array of x86_cpu_ids
++ * @match: Pointer to array of x86_cpu_ids. Last entry terminated with
++ *         {}.
++ *
++ * Return the entry if the current CPU matches the entries in the
++ * passed x86_cpu_id match table. Otherwise NULL.  The match table
++ * contains vendor (X86_VENDOR_*), family, model and feature bits or
++ * respective wildcard entries.
++ *
++ * A typical table entry would be to match a specific CPU
++ * { X86_VENDOR_INTEL, 6, 0x12 }
++ * or to match a specific CPU feature
++ * { X86_FEATURE_MATCH(X86_FEATURE_FOOBAR) }
++ *
++ * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY,
++ * %X86_MODEL_ANY, %X86_FEATURE_ANY or 0 (except for vendor)
++ *
++ * Arrays used to match for this should also be declared using
++ * MODULE_DEVICE_TABLE(x86_cpu, ...)
++ *
++ * This always matches against the boot cpu, assuming models and features are
++ * consistent over all CPUs.
++ */
++const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
++{
++	const struct x86_cpu_id *m;
++	struct cpuinfo_x86 *c = &boot_cpu_data;
++
++	for (m = match; m->vendor | m->family | m->model | m->feature; m++) {
++		if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor)
++			continue;
++		if (m->family != X86_FAMILY_ANY && c->x86 != m->family)
++			continue;
++		if (m->model != X86_MODEL_ANY && c->x86_model != m->model)
++			continue;
++		if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature))
++			continue;
++		return m;
++	}
++	return NULL;
++}
++EXPORT_SYMBOL(x86_match_cpu);
+--- a/arch/x86/kernel/cpuid.c
++++ b/arch/x86/kernel/cpuid.c
+@@ -40,6 +40,7 @@
+ #include <linux/notifier.h>
+ #include <linux/uaccess.h>
+ #include <linux/gfp.h>
++#include <linux/slab.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/msr.h>
+@@ -138,13 +139,57 @@
+ 	.open = cpuid_open,
+ };
+ 
++static ssize_t print_cpu_modalias(struct device *dev,
++				  struct device_attribute *attr,
++				  char *bufptr)
++{
++	int size = PAGE_SIZE;
++	int i, n;
++	char *buf = bufptr;
++
++	n = snprintf(buf, size, "x86cpu:vendor:%04X:family:"
++		     "%04X:model:%04X:feature:",
++		boot_cpu_data.x86_vendor,
++		boot_cpu_data.x86,
++		boot_cpu_data.x86_model);
++	size -= n;
++	buf += n;
++	size -= 2;
++	for (i = 0; i < NCAPINTS*32; i++) {
++		if (boot_cpu_has(i)) {
++			n = snprintf(buf, size, ",%04X", i);
++			if (n < 0) {
++				WARN(1, "x86 features overflow page\n");
++				break;
++			}
++			size -= n;
++			buf += n;
++		}
++	}
++	*buf++ = ',';
++	*buf++ = '\n';
++	return buf - bufptr;
++}
++
++static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
++
+ static __cpuinit int cpuid_device_create(int cpu)
+ {
+ 	struct device *dev;
++	int err;
+ 
+ 	dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL,
+ 			    "cpu%d", cpu);
+-	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
++	if (IS_ERR(dev))
++		return PTR_ERR(dev);
++
++	err = device_create_file(dev, &dev_attr_modalias);
++	if (err) {
++		/* keep device around on error. attribute is optional. */
++		err = 0;
++	}
++
++	return 0;
+ }
+ 
+ static void cpuid_device_destroy(int cpu)
+@@ -182,6 +227,17 @@
+ 	return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
+ }
+ 
++static int cpuid_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++	char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
++	if (buf) {
++		print_cpu_modalias(NULL, NULL, buf);
++		add_uevent_var(env, "MODALIAS=%s", buf);
++		kfree(buf);
++	}
++	return 0;
++}
++
+ static int __init cpuid_init(void)
+ {
+ 	int i, err = 0;
+@@ -200,6 +256,7 @@
+ 		goto out_chrdev;
+ 	}
+ 	cpuid_class->devnode = cpuid_devnode;
++	cpuid_class->dev_uevent = cpuid_dev_uevent;
+ 	for_each_online_cpu(i) {
+ 		err = cpuid_device_create(i);
+ 		if (err != 0)
+--- a/include/linux/mod_devicetable.h
++++ b/include/linux/mod_devicetable.h
+@@ -542,4 +542,25 @@
+ 	kernel_ulong_t driver_data;	/* data private to the driver */
+ };
+ 
++/*
++ * Match x86 CPUs for CPU specific drivers.
++ * See documentation of "x86_match_cpu" for details.
++ */
++
++struct x86_cpu_id {
++	__u16 vendor;
++	__u16 family;
++	__u16 model;
++	__u16 feature;	/* bit index */
++	kernel_ulong_t driver_data;
++};
++
++#define X86_FEATURE_MATCH(x) \
++	{ X86_VENDOR_ANY, X86_FAMILY_ANY, X86_MODEL_ANY, x }
++
++#define X86_VENDOR_ANY 0xffff
++#define X86_FAMILY_ANY 0
++#define X86_MODEL_ANY  0
++#define X86_FEATURE_ANY 0	/* Same as FPU, you can't test for that */
++
+ #endif /* LINUX_MOD_DEVICETABLE_H */
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -880,6 +880,29 @@
+ 	return 1;
+ }
+ 
++/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
++ * All fields are numbers. It would be nicer to use strings for vendor
++ * and feature, but getting those out of the build system here is too
++ * complicated.
++ */
++
++static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id,
++			   char *alias)
++{
++	id->feature = TO_NATIVE(id->feature);
++	id->family = TO_NATIVE(id->family);
++	id->model = TO_NATIVE(id->model);
++	id->vendor = TO_NATIVE(id->vendor);
++
++	strcpy(alias, "x86cpu:");
++	ADD(alias, "vendor:",  id->vendor != X86_VENDOR_ANY, id->vendor);
++	ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family);
++	ADD(alias, ":model:",  id->model  != X86_MODEL_ANY,  id->model);
++	ADD(alias, ":feature:*,", id->feature != X86_FEATURE_ANY, id->feature);
++	strcat(alias, ",*");
++	return 1;
++}
++
+ /* Ignore any prefix, eg. some architectures prepend _ */
+ static inline int sym_is(const char *symbol, const char *name)
+ {
+@@ -1051,6 +1074,10 @@
+ 		do_table(symval, sym->st_size,
+ 			sizeof(struct isapnp_device_id), "isa",
+ 			do_isapnp_entry, mod);
++	else if (sym_is(symname, "__mod_x86cpu_device_table"))
++		do_table(symval, sym->st_size,
++			 sizeof(struct x86_cpu_id), "x86cpu",
++			 do_x86cpu_entry, mod);
+ 	free(zeros);
+ }
+ 

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/CPU-Introduce-ARCH_HAS_CPU_AUTOPROBE-and-X86-parts.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/CPU-Introduce-ARCH_HAS_CPU_AUTOPROBE-and-X86-parts.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,266 @@
+From: Thomas Renninger <trenn at suse.de>
+Date: Thu, 26 Jan 2012 00:09:14 +0100
+Subject: CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts
+
+commit fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafa upstream.
+
+This patch is based on Andi Kleen's work:
+Implement autoprobing/loading of modules serving CPU
+specific features (x86cpu autoloading).
+
+And Kay Siever's work to get rid of sysdev cpu structures
+and making use of struct device instead.
+
+Before, the cpuid driver had to be loaded to get the x86cpu
+autoloading feature. With this patch autoloading works through
+the /sys/devices/system/cpu object
+
+Cc: Kay Sievers <kay.sievers at vrfy.org>
+Cc: Dave Jones <davej at redhat.com>
+Cc: Jens Axboe <axboe at kernel.dk>
+Cc: Herbert Xu <herbert at gondor.apana.org.au>
+Cc: Huang Ying <ying.huang at intel.com>
+Cc: Len Brown <lenb at kernel.org>
+Acked-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ arch/x86/Kconfig            |    3 +++
+ arch/x86/kernel/cpu/match.c |   44 ++++++++++++++++++++++++++++++++
+ arch/x86/kernel/cpuid.c     |   59 +------------------------------------------
+ drivers/base/cpu.c          |   11 ++++++++
+ include/linux/cpu.h         |    7 +++++
+ 5 files changed, 66 insertions(+), 58 deletions(-)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 864cc6e..6baa1e6 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -179,6 +179,9 @@ config ARCH_HAS_DEFAULT_IDLE
+ config ARCH_HAS_CACHE_LINE_SIZE
+ 	def_bool y
+ 
++config ARCH_HAS_CPU_AUTOPROBE
++	def_bool y
++
+ config HAVE_SETUP_PER_CPU_AREA
+ 	def_bool y
+ 
+diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
+index 7acc961..940e2d4 100644
+--- a/arch/x86/kernel/cpu/match.c
++++ b/arch/x86/kernel/cpu/match.c
+@@ -2,6 +2,7 @@
+ #include <asm/processor.h>
+ #include <linux/cpu.h>
+ #include <linux/module.h>
++#include <linux/slab.h>
+ 
+ /**
+  * x86_match_cpu - match current CPU again an array of x86_cpu_ids
+@@ -46,3 +47,46 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
+ 	return NULL;
+ }
+ EXPORT_SYMBOL(x86_match_cpu);
++
++ssize_t arch_print_cpu_modalias(struct device *dev,
++				struct device_attribute *attr,
++				char *bufptr)
++{
++	int size = PAGE_SIZE;
++	int i, n;
++	char *buf = bufptr;
++
++	n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:"
++		     "model:%04X:feature:",
++		boot_cpu_data.x86_vendor,
++		boot_cpu_data.x86,
++		boot_cpu_data.x86_model);
++	size -= n;
++	buf += n;
++	size -= 2;
++	for (i = 0; i < NCAPINTS*32; i++) {
++		if (boot_cpu_has(i)) {
++			n = snprintf(buf, size, ",%04X", i);
++			if (n < 0) {
++				WARN(1, "x86 features overflow page\n");
++				break;
++			}
++			size -= n;
++			buf += n;
++		}
++	}
++	*buf++ = ',';
++	*buf++ = '\n';
++	return buf - bufptr;
++}
++
++int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++	char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
++	if (buf) {
++		arch_print_cpu_modalias(NULL, NULL, buf);
++		add_uevent_var(env, "MODALIAS=%s", buf);
++		kfree(buf);
++	}
++	return 0;
++}
+diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
+index 7c89880..a524353 100644
+--- a/arch/x86/kernel/cpuid.c
++++ b/arch/x86/kernel/cpuid.c
+@@ -40,7 +40,6 @@
+ #include <linux/notifier.h>
+ #include <linux/uaccess.h>
+ #include <linux/gfp.h>
+-#include <linux/slab.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/msr.h>
+@@ -139,57 +138,13 @@ static const struct file_operations cpuid_fops = {
+ 	.open = cpuid_open,
+ };
+ 
+-static ssize_t print_cpu_modalias(struct device *dev,
+-				  struct device_attribute *attr,
+-				  char *bufptr)
+-{
+-	int size = PAGE_SIZE;
+-	int i, n;
+-	char *buf = bufptr;
+-
+-	n = snprintf(buf, size, "x86cpu:vendor:%04X:family:"
+-		     "%04X:model:%04X:feature:",
+-		boot_cpu_data.x86_vendor,
+-		boot_cpu_data.x86,
+-		boot_cpu_data.x86_model);
+-	size -= n;
+-	buf += n;
+-	size -= 2;
+-	for (i = 0; i < NCAPINTS*32; i++) {
+-		if (boot_cpu_has(i)) {
+-			n = snprintf(buf, size, ",%04X", i);
+-			if (n < 0) {
+-				WARN(1, "x86 features overflow page\n");
+-				break;
+-			}
+-			size -= n;
+-			buf += n;
+-		}
+-	}
+-	*buf++ = ',';
+-	*buf++ = '\n';
+-	return buf - bufptr;
+-}
+-
+-static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
+-
+ static __cpuinit int cpuid_device_create(int cpu)
+ {
+ 	struct device *dev;
+-	int err;
+ 
+ 	dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL,
+ 			    "cpu%d", cpu);
+-	if (IS_ERR(dev))
+-		return PTR_ERR(dev);
+-
+-	err = device_create_file(dev, &dev_attr_modalias);
+-	if (err) {
+-		/* keep device around on error. attribute is optional. */
+-		err = 0;
+-	}
+-
+-	return 0;
++	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
+ }
+ 
+ static void cpuid_device_destroy(int cpu)
+@@ -227,17 +182,6 @@ static char *cpuid_devnode(struct device *dev, umode_t *mode)
+ 	return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
+ }
+ 
+-static int cpuid_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+-{
+-	char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+-	if (buf) {
+-		print_cpu_modalias(NULL, NULL, buf);
+-		add_uevent_var(env, "MODALIAS=%s", buf);
+-		kfree(buf);
+-	}
+-	return 0;
+-}
+-
+ static int __init cpuid_init(void)
+ {
+ 	int i, err = 0;
+@@ -256,7 +200,6 @@ static int __init cpuid_init(void)
+ 		goto out_chrdev;
+ 	}
+ 	cpuid_class->devnode = cpuid_devnode;
+-	cpuid_class->dev_uevent = cpuid_dev_uevent;
+ 	for_each_online_cpu(i) {
+ 		err = cpuid_device_create(i);
+ 		if (err != 0)
+diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
+index db87e78..2a0c670 100644
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -11,6 +11,7 @@
+ #include <linux/device.h>
+ #include <linux/node.h>
+ #include <linux/gfp.h>
++#include <linux/slab.h>
+ #include <linux/percpu.h>
+ 
+ #include "base.h"
+@@ -223,6 +224,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
+ 	cpu->node_id = cpu_to_node(num);
+ 	cpu->dev.id = num;
+ 	cpu->dev.bus = &cpu_subsys;
++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
++	cpu->dev.bus->uevent = arch_cpu_uevent;
++#endif
+ 	error = device_register(&cpu->dev);
+ 	if (!error && cpu->hotpluggable)
+ 		register_cpu_control(cpu);
+@@ -247,6 +251,10 @@ struct device *get_cpu_device(unsigned cpu)
+ }
+ EXPORT_SYMBOL_GPL(get_cpu_device);
+ 
++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
++static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
++#endif
++
+ static struct attribute *cpu_root_attrs[] = {
+ #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+ 	&dev_attr_probe.attr,
+@@ -257,6 +265,9 @@ static struct attribute *cpu_root_attrs[] = {
+ 	&cpu_attrs[2].attr.attr,
+ 	&dev_attr_kernel_max.attr,
+ 	&dev_attr_offline.attr,
++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
++	&dev_attr_modalias.attr,
++#endif
+ 	NULL
+ };
+ 
+diff --git a/include/linux/cpu.h b/include/linux/cpu.h
+index 1f65875..6e53b48 100644
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -44,6 +44,13 @@ extern ssize_t arch_cpu_release(const char *, size_t);
+ #endif
+ struct notifier_block;
+ 
++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
++extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env);
++extern ssize_t arch_print_cpu_modalias(struct device *dev,
++				       struct device_attribute *attr,
++				       char *bufptr);
++#endif
++
+ /*
+  * CPU notifier priorities.
+  */

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/HWMON-Convert-coretemp-to-x86-cpuid-autoprobing.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/HWMON-Convert-coretemp-to-x86-cpuid-autoprobing.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,59 @@
+From: Andi Kleen <ak at linux.intel.com>
+Date: Thu, 26 Jan 2012 00:09:10 +0100
+Subject: HWMON: Convert coretemp to x86 cpuid autoprobing
+
+commit 9b38096fde5f9b93c3657911c3be7892cc155cbd upstream.
+
+Use the new x86 cpuid autoprobe interface for the Intel coretemp
+driver.
+
+Cc: Fenghua Yu <fenghua.yu at intel.com>
+Cc: Jean Delvare <khali at linux-fr.org>
+Cc: Guenter Roeck <guenter.roeck at ericsson.com>
+Signed-off-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/hwmon/coretemp.c |   17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index a6c6ec3..249ac46 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -39,6 +39,7 @@
+ #include <linux/moduleparam.h>
+ #include <asm/msr.h>
+ #include <asm/processor.h>
++#include <asm/cpu_device_id.h>
+ 
+ #define DRVNAME	"coretemp"
+ 
+@@ -759,13 +760,23 @@ static struct notifier_block coretemp_cpu_notifier __refdata = {
+ 	.notifier_call = coretemp_cpu_callback,
+ };
+ 
++static const struct x86_cpu_id coretemp_ids[] = {
++	{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTS },
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, coretemp_ids);
++
+ static int __init coretemp_init(void)
+ {
+ 	int i, err = -ENODEV;
+ 
+-	/* quick check if we run Intel */
+-	if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
+-		goto exit;
++	/*
++	 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
++	 * sensors. We check this bit only, all the early CPUs
++	 * without thermal sensors will be filtered out.
++	 */
++	if (!x86_match_cpu(coretemp_ids))
++		return -ENODEV;
+ 
+ 	err = platform_driver_register(&coretemp_driver);
+ 	if (err)

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/HWMON-Convert-via-cputemp-to-x86-cpuid-autoprobing.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/HWMON-Convert-via-cputemp-to-x86-cpuid-autoprobing.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,56 @@
+From: Andi Kleen <ak at linux.intel.com>
+Date: Thu, 26 Jan 2012 00:09:09 +0100
+Subject: HWMON: Convert via-cputemp to x86 cpuid autoprobing
+
+commit 267fc9788d0cdb77edafb506063f06961e1418f5 upstream.
+
+Use the new x86 cpuid autoprobe interface.
+
+Cc: Jean Delvare <khali at linux-fr.org>
+Cc: Guenter Roeck <guenter.roeck at ericsson.com>
+Signed-off-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/hwmon/via-cputemp.c |   16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
+index 8eac67d..8689664 100644
+--- a/drivers/hwmon/via-cputemp.c
++++ b/drivers/hwmon/via-cputemp.c
+@@ -37,6 +37,7 @@
+ #include <linux/cpu.h>
+ #include <asm/msr.h>
+ #include <asm/processor.h>
++#include <asm/cpu_device_id.h>
+ 
+ #define DRVNAME	"via_cputemp"
+ 
+@@ -308,15 +309,20 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = {
+ 	.notifier_call = via_cputemp_cpu_callback,
+ };
+ 
++static const struct x86_cpu_id cputemp_ids[] = {
++	{ X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */
++	{ X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */
++	{ X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, cputemp_ids);
++
+ static int __init via_cputemp_init(void)
+ {
+ 	int i, err;
+ 
+-	if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
+-		printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
+-		err = -ENODEV;
+-		goto exit;
+-	}
++	if (!x86_match_cpu(cputemp_ids))
++		return -ENODEV;
+ 
+ 	err = platform_driver_register(&via_cputemp_driver);
+ 	if (err)

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/Partially-revert-cpufreq-Add-support-for-x86-cpuinfo.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/Partially-revert-cpufreq-Add-support-for-x86-cpuinfo.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,55 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Mon, 18 Jun 2012 02:56:40 +0100
+Subject: Partially revert "cpufreq: Add support for x86 cpuinfo auto loading
+ v4"
+
+This reverts commit fa8031aefec0cf7ea6c2387c93610d99d9659aa2 in
+drivers/cpufreq/e_powersaver.c only.
+
+e_powersaver may cause the CPU to run too fast on some systems, and is
+therefore unsafe to auto-load.
+---
+ drivers/cpufreq/e_powersaver.c |   20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
+index 3fffbe6..4bd6815 100644
+--- a/drivers/cpufreq/e_powersaver.c
++++ b/drivers/cpufreq/e_powersaver.c
+@@ -16,7 +16,6 @@
+ #include <linux/io.h>
+ #include <linux/delay.h>
+ 
+-#include <asm/cpu_device_id.h>
+ #include <asm/msr.h>
+ #include <asm/tsc.h>
+ 
+@@ -438,19 +437,18 @@ static struct cpufreq_driver eps_driver = {
+ 	.attr		= eps_attr,
+ };
+ 
+-
+-/* This driver will work only on Centaur C7 processors with
+- * Enhanced SpeedStep/PowerSaver registers */
+-static const struct x86_cpu_id eps_cpu_id[] = {
+-	{ X86_VENDOR_CENTAUR, 6, X86_MODEL_ANY, X86_FEATURE_EST },
+-	{}
+-};
+-MODULE_DEVICE_TABLE(x86cpu, eps_cpu_id);
+-
+ static int __init eps_init(void)
+ {
+-	if (!x86_match_cpu(eps_cpu_id) || boot_cpu_data.x86_model < 10)
++	struct cpuinfo_x86 *c = &cpu_data(0);
++
++	/* This driver will work only on Centaur C7 processors with
++	 * Enhanced SpeedStep/PowerSaver registers */
++	if (c->x86_vendor != X86_VENDOR_CENTAUR
++	    || c->x86 != 6 || c->x86_model < 10)
++		return -ENODEV;
++	if (!cpu_has(c, X86_FEATURE_EST))
+ 		return -ENODEV;
++
+ 	if (cpufreq_register_driver(&eps_driver))
+ 		return -EINVAL;
+ 	return 0;

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/X86-Introduce-HW-Pstate-scattered-cpuid-feature.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/X86-Introduce-HW-Pstate-scattered-cpuid-feature.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,48 @@
+From: Thomas Renninger <trenn at suse.de>
+Date: Thu, 26 Jan 2012 00:09:11 +0100
+Subject: X86: Introduce HW-Pstate scattered cpuid feature
+
+commit 2f1e097e24defe64a86535b53768f5c8ab0368d1 upstream.
+
+It is rather similar to CPB (boot capability) feature
+and exists since fam10h (can be looked up in AMD's BKDG).
+
+The feature is needed for powernow-k8 to cleanup init functions and to
+provide proper autoloading matching with the new x86cpu modalias
+feature.
+
+Cc: Kay Sievers <kay.sievers at vrfy.org>
+Cc: Dave Jones <davej at redhat.com>
+Cc: Borislav Petkov <bp at amd64.org>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ arch/x86/include/asm/cpufeature.h |    1 +
+ arch/x86/kernel/cpu/scattered.c   |    1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
+index 17c5d4b..67b0910 100644
+--- a/arch/x86/include/asm/cpufeature.h
++++ b/arch/x86/include/asm/cpufeature.h
+@@ -176,6 +176,7 @@
+ #define X86_FEATURE_PLN		(7*32+ 5) /* Intel Power Limit Notification */
+ #define X86_FEATURE_PTS		(7*32+ 6) /* Intel Package Thermal Status */
+ #define X86_FEATURE_DTS		(7*32+ 7) /* Digital Thermal Sensor */
++#define X86_FEATURE_HW_PSTATE	(7*32+ 8) /* AMD HW-PState */
+ 
+ /* Virtualization flags: Linux defined, word 8 */
+ #define X86_FEATURE_TPR_SHADOW  (8*32+ 0) /* Intel TPR Shadow */
+diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
+index c7f64e6..addf9e8 100644
+--- a/arch/x86/kernel/cpu/scattered.c
++++ b/arch/x86/kernel/cpu/scattered.c
+@@ -40,6 +40,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
+ 		{ X86_FEATURE_EPB,		CR_ECX, 3, 0x00000006, 0 },
+ 		{ X86_FEATURE_XSAVEOPT,		CR_EAX,	0, 0x0000000d, 1 },
+ 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
++		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
+ 		{ X86_FEATURE_NPT,		CR_EDX, 0, 0x8000000a, 0 },
+ 		{ X86_FEATURE_LBRV,		CR_EDX, 1, 0x8000000a, 0 },
+ 		{ X86_FEATURE_SVML,		CR_EDX, 2, 0x8000000a, 0 },

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,63 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Tue, 10 Jan 2012 02:59:49 +0000
+Subject: cpu: Do not return errors from cpu_dev_init() which will be ignored
+
+commit 024f78462c3da710642a54939888a92e28704653 upstream.
+
+cpu_dev_init() is only called from driver_init(), which does not check
+its return value.  Therefore make cpu_dev_init() return void.
+
+We must register the CPU subsystem, so panic if this fails.
+
+If sched_create_sysfs_power_savings_entries() fails, the damage is
+contained, so ignore this (as before).
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+---
+ drivers/base/base.h |    2 +-
+ drivers/base/cpu.c  |   13 +++++--------
+ 2 files changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/base/base.h
++++ b/drivers/base/base.h
+@@ -94,7 +94,7 @@
+ static inline int hypervisor_init(void) { return 0; }
+ #endif
+ extern int platform_bus_init(void);
+-extern int cpu_dev_init(void);
++extern void cpu_dev_init(void);
+ 
+ extern int bus_add_device(struct device *dev);
+ extern void bus_probe_device(struct device *dev);
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -2,6 +2,7 @@
+  * CPU subsystem support
+  */
+ 
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
+@@ -267,16 +268,12 @@
+ 	NULL,
+ };
+ 
+-int __init cpu_dev_init(void)
++void __init cpu_dev_init(void)
+ {
+-	int err;
+-
+-	err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups);
+-	if (err)
+-		return err;
++	if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
++		panic("Failed to register CPU subsystem");
+ 
+ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+-	err = sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
++	sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
+ #endif
+-	return err;
+ }

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-Register-a-generic-CPU-device-on-architectures-t.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-Register-a-generic-CPU-device-on-architectures-t.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,163 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Tue, 10 Jan 2012 03:04:32 +0000
+Subject: cpu: Register a generic CPU device on architectures that currently
+ do not
+
+commit 9f13a1fd452f11c18004ba2422a6384b424ec8a9 upstream.
+
+frv, h8300, m68k, microblaze, openrisc, score, um and xtensa currently
+do not register a CPU device.  Add the config option GENERIC_CPU_DEVICES
+which causes a generic CPU device to be registered for each present CPU,
+and make all these architectures select it.
+
+Richard Weinberger <richard at nod.at> covered UML and suggested using
+per_cpu.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+---
+ arch/frv/Kconfig        |    1 +
+ arch/h8300/Kconfig      |    1 +
+ arch/m68k/Kconfig       |    1 +
+ arch/microblaze/Kconfig |    1 +
+ arch/openrisc/Kconfig   |    1 +
+ arch/score/Kconfig      |    1 +
+ arch/um/Kconfig.common  |    1 +
+ arch/xtensa/Kconfig     |    1 +
+ drivers/base/Kconfig    |    4 ++++
+ drivers/base/cpu.c      |   19 +++++++++++++++++++
+ 10 files changed, 31 insertions(+)
+
+--- a/arch/frv/Kconfig
++++ b/arch/frv/Kconfig
+@@ -8,6 +8,7 @@
+ 	select HAVE_GENERIC_HARDIRQS
+ 	select GENERIC_IRQ_SHOW
+ 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
++	select GENERIC_CPU_DEVICES
+ 
+ config ZONE_DMA
+ 	bool
+--- a/arch/h8300/Kconfig
++++ b/arch/h8300/Kconfig
+@@ -4,6 +4,7 @@
+ 	select HAVE_IDE
+ 	select HAVE_GENERIC_HARDIRQS
+ 	select GENERIC_IRQ_SHOW
++	select GENERIC_CPU_DEVICES
+ 
+ config SYMBOL_PREFIX
+ 	string
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -7,6 +7,7 @@
+ 	select HAVE_GENERIC_HARDIRQS
+ 	select GENERIC_IRQ_SHOW
+ 	select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
++	select GENERIC_CPU_DEVICES
+ 
+ config RWSEM_GENERIC_SPINLOCK
+ 	bool
+--- a/arch/microblaze/Kconfig
++++ b/arch/microblaze/Kconfig
+@@ -17,6 +17,7 @@
+ 	select HAVE_GENERIC_HARDIRQS
+ 	select GENERIC_IRQ_PROBE
+ 	select GENERIC_IRQ_SHOW
++	select GENERIC_CPU_DEVICES
+ 
+ config SWAP
+ 	def_bool n
+--- a/arch/openrisc/Kconfig
++++ b/arch/openrisc/Kconfig
+@@ -15,6 +15,7 @@
+ 	select GENERIC_IRQ_PROBE
+ 	select GENERIC_IRQ_SHOW
+ 	select GENERIC_IOMAP
++	select GENERIC_CPU_DEVICES
+ 
+ config MMU
+ 	def_bool y
+--- a/arch/score/Kconfig
++++ b/arch/score/Kconfig
+@@ -4,6 +4,7 @@
+        def_bool y
+        select HAVE_GENERIC_HARDIRQS
+        select GENERIC_IRQ_SHOW
++       select GENERIC_CPU_DEVICES
+ 
+ choice
+ 	prompt "System type"
+--- a/arch/um/Kconfig.common
++++ b/arch/um/Kconfig.common
+@@ -8,6 +8,7 @@
+ 	default y
+ 	select HAVE_GENERIC_HARDIRQS
+ 	select GENERIC_IRQ_SHOW
++	select GENERIC_CPU_DEVICES
+ 
+ config MMU
+ 	bool
+--- a/arch/xtensa/Kconfig
++++ b/arch/xtensa/Kconfig
+@@ -9,6 +9,7 @@
+ 	select HAVE_IDE
+ 	select HAVE_GENERIC_HARDIRQS
+ 	select GENERIC_IRQ_SHOW
++	select GENERIC_CPU_DEVICES
+ 	help
+ 	  Xtensa processors are 32-bit RISC machines designed by Tensilica
+ 	  primarily for embedded systems.  These processors are both
+--- a/drivers/base/Kconfig
++++ b/drivers/base/Kconfig
+@@ -172,6 +172,10 @@
+ 	bool
+ 	default n
+ 
++config GENERIC_CPU_DEVICES
++	bool
++	default n
++
+ source "drivers/base/regmap/Kconfig"
+ 
+ endmenu
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -11,6 +11,7 @@
+ #include <linux/device.h>
+ #include <linux/node.h>
+ #include <linux/gfp.h>
++#include <linux/percpu.h>
+ 
+ #include "base.h"
+ 
+@@ -268,11 +269,29 @@
+ 	NULL,
+ };
+ 
++#ifdef CONFIG_GENERIC_CPU_DEVICES
++static DEFINE_PER_CPU(struct cpu, cpu_devices);
++#endif
++
++static void __init cpu_dev_register_generic(void)
++{
++#ifdef CONFIG_GENERIC_CPU_DEVICES
++	int i;
++
++	for_each_possible_cpu(i) {
++		if (register_cpu(&per_cpu(cpu_devices, i), i))
++			panic("Failed to register CPU device");
++	}
++#endif
++}
++
+ void __init cpu_dev_init(void)
+ {
+ 	if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
+ 		panic("Failed to register CPU subsystem");
+ 
++	cpu_dev_register_generic();
++
+ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+ 	sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
+ #endif

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-convert-cpu-and-machinecheck-sysdev_class-to-a-r.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/cpu-convert-cpu-and-machinecheck-sysdev_class-to-a-r.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,4365 @@
+From: Kay Sievers <kay.sievers at vrfy.org>
+Date: Wed, 21 Dec 2011 14:29:42 -0800
+Subject: cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular
+ subsystem
+
+commit 8a25a2fd126c621f44f3aeaef80d51f00fc11639 upstream.
+
+This moves the 'cpu sysdev_class' over to a regular 'cpu' subsystem
+and converts the devices to regular devices. The sysdev drivers are
+implemented as subsystem interfaces now.
+
+After all sysdev classes are ported to regular driver core entities, the
+sysdev implementation will be entirely removed from the kernel.
+
+Userspace relies on events and generic sysfs subsystem infrastructure
+from sysdev devices, which are made available with this conversion.
+
+Cc: Haavard Skinnemoen <hskinnemoen at gmail.com>
+Cc: Hans-Christian Egtvedt <egtvedt at samfundet.no>
+Cc: Tony Luck <tony.luck at intel.com>
+Cc: Fenghua Yu <fenghua.yu at intel.com>
+Cc: Arnd Bergmann <arnd at arndb.de>
+Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org>
+Cc: Paul Mackerras <paulus at samba.org>
+Cc: Martin Schwidefsky <schwidefsky at de.ibm.com>
+Cc: Heiko Carstens <heiko.carstens at de.ibm.com>
+Cc: Paul Mundt <lethal at linux-sh.org>
+Cc: "David S. Miller" <davem at davemloft.net>
+Cc: Chris Metcalf <cmetcalf at tilera.com>
+Cc: Thomas Gleixner <tglx at linutronix.de>
+Cc: Ingo Molnar <mingo at redhat.com>
+Cc: "H. Peter Anvin" <hpa at zytor.com>
+Cc: Borislav Petkov <bp at amd64.org>
+Cc: Tigran Aivazian <tigran at aivazian.fsnet.co.uk>
+Cc: Len Brown <lenb at kernel.org>
+Cc: Zhang Rui <rui.zhang at intel.com>
+Cc: Dave Jones <davej at redhat.com>
+Cc: Peter Zijlstra <peterz at infradead.org>
+Cc: Russell King <rmk+kernel at arm.linux.org.uk>
+Cc: Andrew Morton <akpm at linux-foundation.org>
+Cc: Arjan van de Ven <arjan at linux.intel.com>
+Cc: "Rafael J. Wysocki" <rjw at sisk.pl>
+Cc: "Srivatsa S. Bhat" <srivatsa.bhat at linux.vnet.ibm.com>
+Signed-off-by: Kay Sievers <kay.sievers at vrfy.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+[bwh: Backported to 3.2:
+ - call to sysfs_remove_group() in mc_sysdev_add() was already removed
+ - microcode_init() failure path was fixed and needs to be adjusted too]
+---
+ arch/avr32/kernel/cpu.c                         |   74 +++----
+ arch/ia64/kernel/err_inject.c                   |   52 ++---
+ arch/ia64/kernel/topology.c                     |   10 +-
+ arch/powerpc/include/asm/spu.h                  |   12 +-
+ arch/powerpc/include/asm/topology.h             |   10 +-
+ arch/powerpc/kernel/cacheinfo.c                 |   10 +-
+ arch/powerpc/kernel/smp.c                       |    2 +-
+ arch/powerpc/kernel/sysfs.c                     |  257 +++++++++++------------
+ arch/powerpc/mm/numa.c                          |    8 +-
+ arch/powerpc/platforms/cell/cbe_thermal.c       |  144 ++++++-------
+ arch/powerpc/platforms/cell/spu_base.c          |   61 +++---
+ arch/powerpc/platforms/pseries/pseries_energy.c |   71 +++----
+ arch/powerpc/sysdev/ppc4xx_cpm.c                |    6 +-
+ arch/s390/kernel/smp.c                          |   76 +++----
+ arch/s390/kernel/topology.c                     |    6 +-
+ arch/sh/kernel/cpu/sh4/sq.c                     |   24 ++-
+ arch/sparc/kernel/sysfs.c                       |  122 +++++------
+ arch/tile/kernel/sysfs.c                        |   61 +++---
+ arch/x86/include/asm/mce.h                      |    2 +-
+ arch/x86/kernel/cpu/intel_cacheinfo.c           |   25 ++-
+ arch/x86/kernel/cpu/mcheck/mce-internal.h       |    4 +-
+ arch/x86/kernel/cpu/mcheck/mce.c                |  128 +++++------
+ arch/x86/kernel/cpu/mcheck/mce_amd.c            |   11 +-
+ arch/x86/kernel/cpu/mcheck/therm_throt.c        |   63 +++---
+ arch/x86/kernel/microcode_core.c                |   58 ++---
+ drivers/acpi/processor_driver.c                 |    6 +-
+ drivers/acpi/processor_thermal.c                |    1 -
+ drivers/base/cpu.c                              |  146 +++++++------
+ drivers/base/node.c                             |    8 +-
+ drivers/base/topology.c                         |   51 +++--
+ drivers/cpufreq/cpufreq.c                       |   79 ++++---
+ drivers/cpufreq/cpufreq_stats.c                 |    1 -
+ drivers/cpuidle/cpuidle.c                       |   12 +-
+ drivers/cpuidle/cpuidle.h                       |   10 +-
+ drivers/cpuidle/sysfs.c                         |   74 ++++---
+ drivers/s390/char/sclp_config.c                 |    8 +-
+ include/linux/cpu.h                             |   18 +-
+ kernel/sched.c                                  |   40 ++--
+ 38 files changed, 874 insertions(+), 877 deletions(-)
+
+--- a/arch/avr32/kernel/cpu.c
++++ b/arch/avr32/kernel/cpu.c
+@@ -6,7 +6,7 @@
+  * published by the Free Software Foundation.
+  */
+ #include <linux/init.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/seq_file.h>
+ #include <linux/cpu.h>
+ #include <linux/module.h>
+@@ -26,16 +26,16 @@
+  * XXX: If/when a SMP-capable implementation of AVR32 will ever be
+  * made, we must make sure that the code executes on the correct CPU.
+  */
+-static ssize_t show_pc0event(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t show_pc0event(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+ 	unsigned long pccr;
+ 
+ 	pccr = sysreg_read(PCCR);
+ 	return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
+ }
+-static ssize_t store_pc0event(struct sys_device *dev,
+-			struct sysdev_attribute *attr, const char *buf,
++static ssize_t store_pc0event(struct device *dev,
++			struct device_attribute *attr, const char *buf,
+ 			      size_t count)
+ {
+ 	unsigned long val;
+@@ -48,16 +48,16 @@
+ 	sysreg_write(PCCR, val);
+ 	return count;
+ }
+-static ssize_t show_pc0count(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t show_pc0count(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+ 	unsigned long pcnt0;
+ 
+ 	pcnt0 = sysreg_read(PCNT0);
+ 	return sprintf(buf, "%lu\n", pcnt0);
+ }
+-static ssize_t store_pc0count(struct sys_device *dev,
+-				struct sysdev_attribute *attr,
++static ssize_t store_pc0count(struct device *dev,
++				struct device_attribute *attr,
+ 				const char *buf, size_t count)
+ {
+ 	unsigned long val;
+@@ -71,16 +71,16 @@
+ 	return count;
+ }
+ 
+-static ssize_t show_pc1event(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_pc1event(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	unsigned long pccr;
+ 
+ 	pccr = sysreg_read(PCCR);
+ 	return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
+ }
+-static ssize_t store_pc1event(struct sys_device *dev,
+-			      struct sysdev_attribute *attr, const char *buf,
++static ssize_t store_pc1event(struct device *dev,
++			      struct device_attribute *attr, const char *buf,
+ 			      size_t count)
+ {
+ 	unsigned long val;
+@@ -93,16 +93,16 @@
+ 	sysreg_write(PCCR, val);
+ 	return count;
+ }
+-static ssize_t show_pc1count(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_pc1count(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	unsigned long pcnt1;
+ 
+ 	pcnt1 = sysreg_read(PCNT1);
+ 	return sprintf(buf, "%lu\n", pcnt1);
+ }
+-static ssize_t store_pc1count(struct sys_device *dev,
+-				struct sysdev_attribute *attr, const char *buf,
++static ssize_t store_pc1count(struct device *dev,
++				struct device_attribute *attr, const char *buf,
+ 			      size_t count)
+ {
+ 	unsigned long val;
+@@ -116,16 +116,16 @@
+ 	return count;
+ }
+ 
+-static ssize_t show_pccycles(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_pccycles(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	unsigned long pccnt;
+ 
+ 	pccnt = sysreg_read(PCCNT);
+ 	return sprintf(buf, "%lu\n", pccnt);
+ }
+-static ssize_t store_pccycles(struct sys_device *dev,
+-				struct sysdev_attribute *attr, const char *buf,
++static ssize_t store_pccycles(struct device *dev,
++				struct device_attribute *attr, const char *buf,
+ 			      size_t count)
+ {
+ 	unsigned long val;
+@@ -139,16 +139,16 @@
+ 	return count;
+ }
+ 
+-static ssize_t show_pcenable(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t show_pcenable(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+ 	unsigned long pccr;
+ 
+ 	pccr = sysreg_read(PCCR);
+ 	return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
+ }
+-static ssize_t store_pcenable(struct sys_device *dev,
+-			      struct sysdev_attribute *attr, const char *buf,
++static ssize_t store_pcenable(struct device *dev,
++			      struct device_attribute *attr, const char *buf,
+ 			      size_t count)
+ {
+ 	unsigned long pccr, val;
+@@ -167,12 +167,12 @@
+ 	return count;
+ }
+ 
+-static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event);
+-static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count);
+-static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event);
+-static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count);
+-static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles);
+-static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable);
++static DEVICE_ATTR(pc0event, 0600, show_pc0event, store_pc0event);
++static DEVICE_ATTR(pc0count, 0600, show_pc0count, store_pc0count);
++static DEVICE_ATTR(pc1event, 0600, show_pc1event, store_pc1event);
++static DEVICE_ATTR(pc1count, 0600, show_pc1count, store_pc1count);
++static DEVICE_ATTR(pccycles, 0600, show_pccycles, store_pccycles);
++static DEVICE_ATTR(pcenable, 0600, show_pcenable, store_pcenable);
+ 
+ #endif /* CONFIG_PERFORMANCE_COUNTERS */
+ 
+@@ -186,12 +186,12 @@
+ 		register_cpu(c, cpu);
+ 
+ #ifdef CONFIG_PERFORMANCE_COUNTERS
+-		sysdev_create_file(&c->sysdev, &attr_pc0event);
+-		sysdev_create_file(&c->sysdev, &attr_pc0count);
+-		sysdev_create_file(&c->sysdev, &attr_pc1event);
+-		sysdev_create_file(&c->sysdev, &attr_pc1count);
+-		sysdev_create_file(&c->sysdev, &attr_pccycles);
+-		sysdev_create_file(&c->sysdev, &attr_pcenable);
++		device_create_file(&c->dev, &dev_attr_pc0event);
++		device_create_file(&c->dev, &dev_attr_pc0count);
++		device_create_file(&c->dev, &dev_attr_pc1event);
++		device_create_file(&c->dev, &dev_attr_pc1count);
++		device_create_file(&c->dev, &dev_attr_pccycles);
++		device_create_file(&c->dev, &dev_attr_pcenable);
+ #endif
+ 	}
+ 
+--- a/arch/ia64/kernel/err_inject.c
++++ b/arch/ia64/kernel/err_inject.c
+@@ -24,7 +24,7 @@
+  * Copyright (C) 2006, Intel Corp.  All rights reserved.
+  *
+  */
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/init.h>
+ #include <linux/mm.h>
+ #include <linux/cpu.h>
+@@ -35,10 +35,10 @@
+ #define ERR_DATA_BUFFER_SIZE 3 		// Three 8-byte;
+ 
+ #define define_one_ro(name) 						\
+-static SYSDEV_ATTR(name, 0444, show_##name, NULL)
++static DEVICE_ATTR(name, 0444, show_##name, NULL)
+ 
+ #define define_one_rw(name) 						\
+-static SYSDEV_ATTR(name, 0644, show_##name, store_##name)
++static DEVICE_ATTR(name, 0644, show_##name, store_##name)
+ 
+ static u64 call_start[NR_CPUS];
+ static u64 phys_addr[NR_CPUS];
+@@ -55,7 +55,7 @@
+ 
+ #define show(name) 							\
+ static ssize_t 								\
+-show_##name(struct sys_device *dev, struct sysdev_attribute *attr,	\
++show_##name(struct device *dev, struct device_attribute *attr,	\
+ 		char *buf)						\
+ {									\
+ 	u32 cpu=dev->id;						\
+@@ -64,7 +64,7 @@
+ 
+ #define store(name)							\
+ static ssize_t 								\
+-store_##name(struct sys_device *dev, struct sysdev_attribute *attr,	\
++store_##name(struct device *dev, struct device_attribute *attr,	\
+ 					const char *buf, size_t size)	\
+ {									\
+ 	unsigned int cpu=dev->id;					\
+@@ -78,7 +78,7 @@
+  * processor. The cpu number in driver is only used for storing data.
+  */
+ static ssize_t
+-store_call_start(struct sys_device *dev, struct sysdev_attribute *attr,
++store_call_start(struct device *dev, struct device_attribute *attr,
+ 		const char *buf, size_t size)
+ {
+ 	unsigned int cpu=dev->id;
+@@ -127,7 +127,7 @@
+ store(err_type_info)
+ 
+ static ssize_t
+-show_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr,
++show_virtual_to_phys(struct device *dev, struct device_attribute *attr,
+ 			char *buf)
+ {
+ 	unsigned int cpu=dev->id;
+@@ -135,7 +135,7 @@
+ }
+ 
+ static ssize_t
+-store_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr,
++store_virtual_to_phys(struct device *dev, struct device_attribute *attr,
+ 			const char *buf, size_t size)
+ {
+ 	unsigned int cpu=dev->id;
+@@ -159,8 +159,8 @@
+ store(err_struct_info)
+ 
+ static ssize_t
+-show_err_data_buffer(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *buf)
++show_err_data_buffer(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+ 	unsigned int cpu=dev->id;
+ 
+@@ -171,8 +171,8 @@
+ }
+ 
+ static ssize_t
+-store_err_data_buffer(struct sys_device *dev,
+-			struct sysdev_attribute *attr,
++store_err_data_buffer(struct device *dev,
++			struct device_attribute *attr,
+ 			const char *buf, size_t size)
+ {
+ 	unsigned int cpu=dev->id;
+@@ -209,14 +209,14 @@
+ define_one_ro(resources);
+ 
+ static struct attribute *default_attrs[] = {
+-	&attr_call_start.attr,
+-	&attr_virtual_to_phys.attr,
+-	&attr_err_type_info.attr,
+-	&attr_err_struct_info.attr,
+-	&attr_err_data_buffer.attr,
+-	&attr_status.attr,
+-	&attr_capabilities.attr,
+-	&attr_resources.attr,
++	&dev_attr_call_start.attr,
++	&dev_attr_virtual_to_phys.attr,
++	&dev_attr_err_type_info.attr,
++	&dev_attr_err_struct_info.attr,
++	&dev_attr_err_data_buffer.attr,
++	&dev_attr_status.attr,
++	&dev_attr_capabilities.attr,
++	&dev_attr_resources.attr,
+ 	NULL
+ };
+ 
+@@ -225,12 +225,12 @@
+ 	.name = "err_inject"
+ };
+ /* Add/Remove err_inject interface for CPU device */
+-static int __cpuinit err_inject_add_dev(struct sys_device * sys_dev)
++static int __cpuinit err_inject_add_dev(struct device * sys_dev)
+ {
+ 	return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group);
+ }
+ 
+-static int __cpuinit err_inject_remove_dev(struct sys_device * sys_dev)
++static int __cpuinit err_inject_remove_dev(struct device * sys_dev)
+ {
+ 	sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
+ 	return 0;
+@@ -239,9 +239,9 @@
+ 		unsigned long action, void *hcpu)
+ {
+ 	unsigned int cpu = (unsigned long)hcpu;
+-	struct sys_device *sys_dev;
++	struct device *sys_dev;
+ 
+-	sys_dev = get_cpu_sysdev(cpu);
++	sys_dev = get_cpu_device(cpu);
+ 	switch (action) {
+ 	case CPU_ONLINE:
+ 	case CPU_ONLINE_FROZEN:
+@@ -283,13 +283,13 @@
+ err_inject_exit(void)
+ {
+ 	int i;
+-	struct sys_device *sys_dev;
++	struct device *sys_dev;
+ 
+ #ifdef ERR_INJ_DEBUG
+ 	printk(KERN_INFO "Exit error injection driver.\n");
+ #endif
+ 	for_each_online_cpu(i) {
+-		sys_dev = get_cpu_sysdev(i);
++		sys_dev = get_cpu_device(i);
+ 		sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
+ 	}
+ 	unregister_hotcpu_notifier(&err_inject_cpu_notifier);
+--- a/arch/ia64/kernel/topology.c
++++ b/arch/ia64/kernel/topology.c
+@@ -350,7 +350,7 @@
+ }
+ 
+ /* Add cache interface for CPU device */
+-static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
++static int __cpuinit cache_add_dev(struct device * sys_dev)
+ {
+ 	unsigned int cpu = sys_dev->id;
+ 	unsigned long i, j;
+@@ -400,7 +400,7 @@
+ }
+ 
+ /* Remove cache interface for CPU device */
+-static int __cpuinit cache_remove_dev(struct sys_device * sys_dev)
++static int __cpuinit cache_remove_dev(struct device * sys_dev)
+ {
+ 	unsigned int cpu = sys_dev->id;
+ 	unsigned long i;
+@@ -428,9 +428,9 @@
+ 		unsigned long action, void *hcpu)
+ {
+ 	unsigned int cpu = (unsigned long)hcpu;
+-	struct sys_device *sys_dev;
++	struct device *sys_dev;
+ 
+-	sys_dev = get_cpu_sysdev(cpu);
++	sys_dev = get_cpu_device(cpu);
+ 	switch (action) {
+ 	case CPU_ONLINE:
+ 	case CPU_ONLINE_FROZEN:
+@@ -454,7 +454,7 @@
+ 	int i;
+ 
+ 	for_each_online_cpu(i) {
+-		struct sys_device *sys_dev = get_cpu_sysdev((unsigned int)i);
++		struct device *sys_dev = get_cpu_device((unsigned int)i);
+ 		cache_add_dev(sys_dev);
+ 	}
+ 
+--- a/arch/powerpc/include/asm/spu.h
++++ b/arch/powerpc/include/asm/spu.h
+@@ -25,7 +25,7 @@
+ #ifdef __KERNEL__
+ 
+ #include <linux/workqueue.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/mutex.h>
+ 
+ #define LS_SIZE (256 * 1024)
+@@ -166,7 +166,7 @@
+ 	/* beat only */
+ 	u64 shadow_int_mask_RW[3];
+ 
+-	struct sys_device sysdev;
++	struct device dev;
+ 
+ 	int has_mem_affinity;
+ 	struct list_head aff_list;
+@@ -270,11 +270,11 @@
+ int register_spu_syscalls(struct spufs_calls *calls);
+ void unregister_spu_syscalls(struct spufs_calls *calls);
+ 
+-int spu_add_sysdev_attr(struct sysdev_attribute *attr);
+-void spu_remove_sysdev_attr(struct sysdev_attribute *attr);
++int spu_add_dev_attr(struct device_attribute *attr);
++void spu_remove_dev_attr(struct device_attribute *attr);
+ 
+-int spu_add_sysdev_attr_group(struct attribute_group *attrs);
+-void spu_remove_sysdev_attr_group(struct attribute_group *attrs);
++int spu_add_dev_attr_group(struct attribute_group *attrs);
++void spu_remove_dev_attr_group(struct attribute_group *attrs);
+ 
+ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+ 		unsigned long dsisr, unsigned *flt);
+--- a/arch/powerpc/include/asm/topology.h
++++ b/arch/powerpc/include/asm/topology.h
+@@ -3,7 +3,7 @@
+ #ifdef __KERNEL__
+ 
+ 
+-struct sys_device;
++struct device;
+ struct device_node;
+ 
+ #ifdef CONFIG_NUMA
+@@ -86,19 +86,19 @@
+ 
+ extern void __init dump_numa_cpu_topology(void);
+ 
+-extern int sysfs_add_device_to_node(struct sys_device *dev, int nid);
+-extern void sysfs_remove_device_from_node(struct sys_device *dev, int nid);
++extern int sysfs_add_device_to_node(struct device *dev, int nid);
++extern void sysfs_remove_device_from_node(struct device *dev, int nid);
+ 
+ #else
+ 
+ static inline void dump_numa_cpu_topology(void) {}
+ 
+-static inline int sysfs_add_device_to_node(struct sys_device *dev, int nid)
++static inline int sysfs_add_device_to_node(struct device *dev, int nid)
+ {
+ 	return 0;
+ }
+ 
+-static inline void sysfs_remove_device_from_node(struct sys_device *dev,
++static inline void sysfs_remove_device_from_node(struct device *dev,
+ 						int nid)
+ {
+ }
+--- a/arch/powerpc/kernel/cacheinfo.c
++++ b/arch/powerpc/kernel/cacheinfo.c
+@@ -451,15 +451,15 @@
+ static struct cache_dir *__cpuinit cacheinfo_create_cache_dir(unsigned int cpu_id)
+ {
+ 	struct cache_dir *cache_dir;
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 	struct kobject *kobj = NULL;
+ 
+-	sysdev = get_cpu_sysdev(cpu_id);
+-	WARN_ONCE(!sysdev, "no sysdev for CPU %i\n", cpu_id);
+-	if (!sysdev)
++	dev = get_cpu_device(cpu_id);
++	WARN_ONCE(!dev, "no dev for CPU %i\n", cpu_id);
++	if (!dev)
+ 		goto err;
+ 
+-	kobj = kobject_create_and_add("cache", &sysdev->kobj);
++	kobj = kobject_create_and_add("cache", &dev->kobj);
+ 	if (!kobj)
+ 		goto err;
+ 
+--- a/arch/powerpc/kernel/smp.c
++++ b/arch/powerpc/kernel/smp.c
+@@ -27,7 +27,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/cache.h>
+ #include <linux/err.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/cpu.h>
+ #include <linux/notifier.h>
+ #include <linux/topology.h>
+--- a/arch/powerpc/kernel/sysfs.c
++++ b/arch/powerpc/kernel/sysfs.c
+@@ -1,4 +1,4 @@
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/cpu.h>
+ #include <linux/smp.h>
+ #include <linux/percpu.h>
+@@ -37,12 +37,12 @@
+ /* Time in microseconds we delay before sleeping in the idle loop */
+ DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 };
+ 
+-static ssize_t store_smt_snooze_delay(struct sys_device *dev,
+-				      struct sysdev_attribute *attr,
++static ssize_t store_smt_snooze_delay(struct device *dev,
++				      struct device_attribute *attr,
+ 				      const char *buf,
+ 				      size_t count)
+ {
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
++	struct cpu *cpu = container_of(dev, struct cpu, dev);
+ 	ssize_t ret;
+ 	long snooze;
+ 
+@@ -50,21 +50,21 @@
+ 	if (ret != 1)
+ 		return -EINVAL;
+ 
+-	per_cpu(smt_snooze_delay, cpu->sysdev.id) = snooze;
++	per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
+ 
+ 	return count;
+ }
+ 
+-static ssize_t show_smt_snooze_delay(struct sys_device *dev,
+-				     struct sysdev_attribute *attr,
++static ssize_t show_smt_snooze_delay(struct device *dev,
++				     struct device_attribute *attr,
+ 				     char *buf)
+ {
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
++	struct cpu *cpu = container_of(dev, struct cpu, dev);
+ 
+-	return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->sysdev.id));
++	return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->dev.id));
+ }
+ 
+-static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
++static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
+ 		   store_smt_snooze_delay);
+ 
+ static int __init setup_smt_snooze_delay(char *str)
+@@ -117,25 +117,25 @@
+ 	ppc_enable_pmcs(); \
+ 	mtspr(ADDRESS, *(unsigned long *)val);	\
+ } \
+-static ssize_t show_##NAME(struct sys_device *dev, \
+-			struct sysdev_attribute *attr, \
++static ssize_t show_##NAME(struct device *dev, \
++			struct device_attribute *attr, \
+ 			char *buf) \
+ { \
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
++	struct cpu *cpu = container_of(dev, struct cpu, dev); \
+ 	unsigned long val; \
+-	smp_call_function_single(cpu->sysdev.id, read_##NAME, &val, 1);	\
++	smp_call_function_single(cpu->dev.id, read_##NAME, &val, 1);	\
+ 	return sprintf(buf, "%lx\n", val); \
+ } \
+ static ssize_t __used \
+-	store_##NAME(struct sys_device *dev, struct sysdev_attribute *attr, \
++	store_##NAME(struct device *dev, struct device_attribute *attr, \
+ 			const char *buf, size_t count) \
+ { \
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
++	struct cpu *cpu = container_of(dev, struct cpu, dev); \
+ 	unsigned long val; \
+ 	int ret = sscanf(buf, "%lx", &val); \
+ 	if (ret != 1) \
+ 		return -EINVAL; \
+-	smp_call_function_single(cpu->sysdev.id, write_##NAME, &val, 1); \
++	smp_call_function_single(cpu->dev.id, write_##NAME, &val, 1); \
+ 	return count; \
+ }
+ 
+@@ -178,22 +178,22 @@
+ SYSFS_PMCSETUP(spurr, SPRN_SPURR);
+ SYSFS_PMCSETUP(dscr, SPRN_DSCR);
+ 
+-static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
+-static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
+-static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
+-static SYSDEV_ATTR(purr, 0600, show_purr, store_purr);
++static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
++static DEVICE_ATTR(spurr, 0600, show_spurr, NULL);
++static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
++static DEVICE_ATTR(purr, 0600, show_purr, store_purr);
+ 
+ unsigned long dscr_default = 0;
+ EXPORT_SYMBOL(dscr_default);
+ 
+-static ssize_t show_dscr_default(struct sysdev_class *class,
+-		struct sysdev_class_attribute *attr, char *buf)
++static ssize_t show_dscr_default(struct device *dev,
++		struct device_attribute *attr, char *buf)
+ {
+ 	return sprintf(buf, "%lx\n", dscr_default);
+ }
+ 
+-static ssize_t __used store_dscr_default(struct sysdev_class *class,
+-		struct sysdev_class_attribute *attr, const char *buf,
++static ssize_t __used store_dscr_default(struct device *dev,
++		struct device_attribute *attr, const char *buf,
+ 		size_t count)
+ {
+ 	unsigned long val;
+@@ -207,15 +207,14 @@
+ 	return count;
+ }
+ 
+-static SYSDEV_CLASS_ATTR(dscr_default, 0600,
++static DEVICE_ATTR(dscr_default, 0600,
+ 		show_dscr_default, store_dscr_default);
+ 
+ static void sysfs_create_dscr_default(void)
+ {
+ 	int err = 0;
+ 	if (cpu_has_feature(CPU_FTR_DSCR))
+-		err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+-			&attr_dscr_default.attr);
++		err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default);
+ }
+ #endif /* CONFIG_PPC64 */
+ 
+@@ -259,72 +258,72 @@
+ #endif /* HAS_PPC_PMC_PA6T */
+ 
+ #ifdef HAS_PPC_PMC_IBM
+-static struct sysdev_attribute ibm_common_attrs[] = {
+-	_SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
+-	_SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
++static struct device_attribute ibm_common_attrs[] = {
++	__ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
++	__ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
+ };
+ #endif /* HAS_PPC_PMC_G4 */
+ 
+ #ifdef HAS_PPC_PMC_G4
+-static struct sysdev_attribute g4_common_attrs[] = {
+-	_SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
+-	_SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
+-	_SYSDEV_ATTR(mmcr2, 0600, show_mmcr2, store_mmcr2),
++static struct device_attribute g4_common_attrs[] = {
++	__ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
++	__ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
++	__ATTR(mmcr2, 0600, show_mmcr2, store_mmcr2),
+ };
+ #endif /* HAS_PPC_PMC_G4 */
+ 
+-static struct sysdev_attribute classic_pmc_attrs[] = {
+-	_SYSDEV_ATTR(pmc1, 0600, show_pmc1, store_pmc1),
+-	_SYSDEV_ATTR(pmc2, 0600, show_pmc2, store_pmc2),
+-	_SYSDEV_ATTR(pmc3, 0600, show_pmc3, store_pmc3),
+-	_SYSDEV_ATTR(pmc4, 0600, show_pmc4, store_pmc4),
+-	_SYSDEV_ATTR(pmc5, 0600, show_pmc5, store_pmc5),
+-	_SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6),
++static struct device_attribute classic_pmc_attrs[] = {
++	__ATTR(pmc1, 0600, show_pmc1, store_pmc1),
++	__ATTR(pmc2, 0600, show_pmc2, store_pmc2),
++	__ATTR(pmc3, 0600, show_pmc3, store_pmc3),
++	__ATTR(pmc4, 0600, show_pmc4, store_pmc4),
++	__ATTR(pmc5, 0600, show_pmc5, store_pmc5),
++	__ATTR(pmc6, 0600, show_pmc6, store_pmc6),
+ #ifdef CONFIG_PPC64
+-	_SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7),
+-	_SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8),
++	__ATTR(pmc7, 0600, show_pmc7, store_pmc7),
++	__ATTR(pmc8, 0600, show_pmc8, store_pmc8),
+ #endif
+ };
+ 
+ #ifdef HAS_PPC_PMC_PA6T
+-static struct sysdev_attribute pa6t_attrs[] = {
+-	_SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
+-	_SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
+-	_SYSDEV_ATTR(pmc0, 0600, show_pa6t_pmc0, store_pa6t_pmc0),
+-	_SYSDEV_ATTR(pmc1, 0600, show_pa6t_pmc1, store_pa6t_pmc1),
+-	_SYSDEV_ATTR(pmc2, 0600, show_pa6t_pmc2, store_pa6t_pmc2),
+-	_SYSDEV_ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3),
+-	_SYSDEV_ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4),
+-	_SYSDEV_ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5),
++static struct device_attribute pa6t_attrs[] = {
++	__ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
++	__ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
++	__ATTR(pmc0, 0600, show_pa6t_pmc0, store_pa6t_pmc0),
++	__ATTR(pmc1, 0600, show_pa6t_pmc1, store_pa6t_pmc1),
++	__ATTR(pmc2, 0600, show_pa6t_pmc2, store_pa6t_pmc2),
++	__ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3),
++	__ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4),
++	__ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5),
+ #ifdef CONFIG_DEBUG_KERNEL
+-	_SYSDEV_ATTR(hid0, 0600, show_hid0, store_hid0),
+-	_SYSDEV_ATTR(hid1, 0600, show_hid1, store_hid1),
+-	_SYSDEV_ATTR(hid4, 0600, show_hid4, store_hid4),
+-	_SYSDEV_ATTR(hid5, 0600, show_hid5, store_hid5),
+-	_SYSDEV_ATTR(ima0, 0600, show_ima0, store_ima0),
+-	_SYSDEV_ATTR(ima1, 0600, show_ima1, store_ima1),
+-	_SYSDEV_ATTR(ima2, 0600, show_ima2, store_ima2),
+-	_SYSDEV_ATTR(ima3, 0600, show_ima3, store_ima3),
+-	_SYSDEV_ATTR(ima4, 0600, show_ima4, store_ima4),
+-	_SYSDEV_ATTR(ima5, 0600, show_ima5, store_ima5),
+-	_SYSDEV_ATTR(ima6, 0600, show_ima6, store_ima6),
+-	_SYSDEV_ATTR(ima7, 0600, show_ima7, store_ima7),
+-	_SYSDEV_ATTR(ima8, 0600, show_ima8, store_ima8),
+-	_SYSDEV_ATTR(ima9, 0600, show_ima9, store_ima9),
+-	_SYSDEV_ATTR(imaat, 0600, show_imaat, store_imaat),
+-	_SYSDEV_ATTR(btcr, 0600, show_btcr, store_btcr),
+-	_SYSDEV_ATTR(pccr, 0600, show_pccr, store_pccr),
+-	_SYSDEV_ATTR(rpccr, 0600, show_rpccr, store_rpccr),
+-	_SYSDEV_ATTR(der, 0600, show_der, store_der),
+-	_SYSDEV_ATTR(mer, 0600, show_mer, store_mer),
+-	_SYSDEV_ATTR(ber, 0600, show_ber, store_ber),
+-	_SYSDEV_ATTR(ier, 0600, show_ier, store_ier),
+-	_SYSDEV_ATTR(sier, 0600, show_sier, store_sier),
+-	_SYSDEV_ATTR(siar, 0600, show_siar, store_siar),
+-	_SYSDEV_ATTR(tsr0, 0600, show_tsr0, store_tsr0),
+-	_SYSDEV_ATTR(tsr1, 0600, show_tsr1, store_tsr1),
+-	_SYSDEV_ATTR(tsr2, 0600, show_tsr2, store_tsr2),
+-	_SYSDEV_ATTR(tsr3, 0600, show_tsr3, store_tsr3),
++	__ATTR(hid0, 0600, show_hid0, store_hid0),
++	__ATTR(hid1, 0600, show_hid1, store_hid1),
++	__ATTR(hid4, 0600, show_hid4, store_hid4),
++	__ATTR(hid5, 0600, show_hid5, store_hid5),
++	__ATTR(ima0, 0600, show_ima0, store_ima0),
++	__ATTR(ima1, 0600, show_ima1, store_ima1),
++	__ATTR(ima2, 0600, show_ima2, store_ima2),
++	__ATTR(ima3, 0600, show_ima3, store_ima3),
++	__ATTR(ima4, 0600, show_ima4, store_ima4),
++	__ATTR(ima5, 0600, show_ima5, store_ima5),
++	__ATTR(ima6, 0600, show_ima6, store_ima6),
++	__ATTR(ima7, 0600, show_ima7, store_ima7),
++	__ATTR(ima8, 0600, show_ima8, store_ima8),
++	__ATTR(ima9, 0600, show_ima9, store_ima9),
++	__ATTR(imaat, 0600, show_imaat, store_imaat),
++	__ATTR(btcr, 0600, show_btcr, store_btcr),
++	__ATTR(pccr, 0600, show_pccr, store_pccr),
++	__ATTR(rpccr, 0600, show_rpccr, store_rpccr),
++	__ATTR(der, 0600, show_der, store_der),
++	__ATTR(mer, 0600, show_mer, store_mer),
++	__ATTR(ber, 0600, show_ber, store_ber),
++	__ATTR(ier, 0600, show_ier, store_ier),
++	__ATTR(sier, 0600, show_sier, store_sier),
++	__ATTR(siar, 0600, show_siar, store_siar),
++	__ATTR(tsr0, 0600, show_tsr0, store_tsr0),
++	__ATTR(tsr1, 0600, show_tsr1, store_tsr1),
++	__ATTR(tsr2, 0600, show_tsr2, store_tsr2),
++	__ATTR(tsr3, 0600, show_tsr3, store_tsr3),
+ #endif /* CONFIG_DEBUG_KERNEL */
+ };
+ #endif /* HAS_PPC_PMC_PA6T */
+@@ -333,14 +332,14 @@
+ static void __cpuinit register_cpu_online(unsigned int cpu)
+ {
+ 	struct cpu *c = &per_cpu(cpu_devices, cpu);
+-	struct sys_device *s = &c->sysdev;
+-	struct sysdev_attribute *attrs, *pmc_attrs;
++	struct device *s = &c->dev;
++	struct device_attribute *attrs, *pmc_attrs;
+ 	int i, nattrs;
+ 
+ #ifdef CONFIG_PPC64
+ 	if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
+ 			cpu_has_feature(CPU_FTR_SMT))
+-		sysdev_create_file(s, &attr_smt_snooze_delay);
++		device_create_file(s, &dev_attr_smt_snooze_delay);
+ #endif
+ 
+ 	/* PMC stuff */
+@@ -348,14 +347,14 @@
+ #ifdef HAS_PPC_PMC_IBM
+ 	case PPC_PMC_IBM:
+ 		attrs = ibm_common_attrs;
+-		nattrs = sizeof(ibm_common_attrs) / sizeof(struct sysdev_attribute);
++		nattrs = sizeof(ibm_common_attrs) / sizeof(struct device_attribute);
+ 		pmc_attrs = classic_pmc_attrs;
+ 		break;
+ #endif /* HAS_PPC_PMC_IBM */
+ #ifdef HAS_PPC_PMC_G4
+ 	case PPC_PMC_G4:
+ 		attrs = g4_common_attrs;
+-		nattrs = sizeof(g4_common_attrs) / sizeof(struct sysdev_attribute);
++		nattrs = sizeof(g4_common_attrs) / sizeof(struct device_attribute);
+ 		pmc_attrs = classic_pmc_attrs;
+ 		break;
+ #endif /* HAS_PPC_PMC_G4 */
+@@ -363,7 +362,7 @@
+ 	case PPC_PMC_PA6T:
+ 		/* PA Semi starts counting at PMC0 */
+ 		attrs = pa6t_attrs;
+-		nattrs = sizeof(pa6t_attrs) / sizeof(struct sysdev_attribute);
++		nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute);
+ 		pmc_attrs = NULL;
+ 		break;
+ #endif /* HAS_PPC_PMC_PA6T */
+@@ -374,24 +373,24 @@
+ 	}
+ 
+ 	for (i = 0; i < nattrs; i++)
+-		sysdev_create_file(s, &attrs[i]);
++		device_create_file(s, &attrs[i]);
+ 
+ 	if (pmc_attrs)
+ 		for (i = 0; i < cur_cpu_spec->num_pmcs; i++)
+-			sysdev_create_file(s, &pmc_attrs[i]);
++			device_create_file(s, &pmc_attrs[i]);
+ 
+ #ifdef CONFIG_PPC64
+ 	if (cpu_has_feature(CPU_FTR_MMCRA))
+-		sysdev_create_file(s, &attr_mmcra);
++		device_create_file(s, &dev_attr_mmcra);
+ 
+ 	if (cpu_has_feature(CPU_FTR_PURR))
+-		sysdev_create_file(s, &attr_purr);
++		device_create_file(s, &dev_attr_purr);
+ 
+ 	if (cpu_has_feature(CPU_FTR_SPURR))
+-		sysdev_create_file(s, &attr_spurr);
++		device_create_file(s, &dev_attr_spurr);
+ 
+ 	if (cpu_has_feature(CPU_FTR_DSCR))
+-		sysdev_create_file(s, &attr_dscr);
++		device_create_file(s, &dev_attr_dscr);
+ #endif /* CONFIG_PPC64 */
+ 
+ 	cacheinfo_cpu_online(cpu);
+@@ -401,8 +400,8 @@
+ static void unregister_cpu_online(unsigned int cpu)
+ {
+ 	struct cpu *c = &per_cpu(cpu_devices, cpu);
+-	struct sys_device *s = &c->sysdev;
+-	struct sysdev_attribute *attrs, *pmc_attrs;
++	struct device *s = &c->dev;
++	struct device_attribute *attrs, *pmc_attrs;
+ 	int i, nattrs;
+ 
+ 	BUG_ON(!c->hotpluggable);
+@@ -410,7 +409,7 @@
+ #ifdef CONFIG_PPC64
+ 	if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
+ 			cpu_has_feature(CPU_FTR_SMT))
+-		sysdev_remove_file(s, &attr_smt_snooze_delay);
++		device_remove_file(s, &dev_attr_smt_snooze_delay);
+ #endif
+ 
+ 	/* PMC stuff */
+@@ -418,14 +417,14 @@
+ #ifdef HAS_PPC_PMC_IBM
+ 	case PPC_PMC_IBM:
+ 		attrs = ibm_common_attrs;
+-		nattrs = sizeof(ibm_common_attrs) / sizeof(struct sysdev_attribute);
++		nattrs = sizeof(ibm_common_attrs) / sizeof(struct device_attribute);
+ 		pmc_attrs = classic_pmc_attrs;
+ 		break;
+ #endif /* HAS_PPC_PMC_IBM */
+ #ifdef HAS_PPC_PMC_G4
+ 	case PPC_PMC_G4:
+ 		attrs = g4_common_attrs;
+-		nattrs = sizeof(g4_common_attrs) / sizeof(struct sysdev_attribute);
++		nattrs = sizeof(g4_common_attrs) / sizeof(struct device_attribute);
+ 		pmc_attrs = classic_pmc_attrs;
+ 		break;
+ #endif /* HAS_PPC_PMC_G4 */
+@@ -433,7 +432,7 @@
+ 	case PPC_PMC_PA6T:
+ 		/* PA Semi starts counting at PMC0 */
+ 		attrs = pa6t_attrs;
+-		nattrs = sizeof(pa6t_attrs) / sizeof(struct sysdev_attribute);
++		nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute);
+ 		pmc_attrs = NULL;
+ 		break;
+ #endif /* HAS_PPC_PMC_PA6T */
+@@ -444,24 +443,24 @@
+ 	}
+ 
+ 	for (i = 0; i < nattrs; i++)
+-		sysdev_remove_file(s, &attrs[i]);
++		device_remove_file(s, &attrs[i]);
+ 
+ 	if (pmc_attrs)
+ 		for (i = 0; i < cur_cpu_spec->num_pmcs; i++)
+-			sysdev_remove_file(s, &pmc_attrs[i]);
++			device_remove_file(s, &pmc_attrs[i]);
+ 
+ #ifdef CONFIG_PPC64
+ 	if (cpu_has_feature(CPU_FTR_MMCRA))
+-		sysdev_remove_file(s, &attr_mmcra);
++		device_remove_file(s, &dev_attr_mmcra);
+ 
+ 	if (cpu_has_feature(CPU_FTR_PURR))
+-		sysdev_remove_file(s, &attr_purr);
++		device_remove_file(s, &dev_attr_purr);
+ 
+ 	if (cpu_has_feature(CPU_FTR_SPURR))
+-		sysdev_remove_file(s, &attr_spurr);
++		device_remove_file(s, &dev_attr_spurr);
+ 
+ 	if (cpu_has_feature(CPU_FTR_DSCR))
+-		sysdev_remove_file(s, &attr_dscr);
++		device_remove_file(s, &dev_attr_dscr);
+ #endif /* CONFIG_PPC64 */
+ 
+ 	cacheinfo_cpu_offline(cpu);
+@@ -513,70 +512,70 @@
+ 
+ static DEFINE_MUTEX(cpu_mutex);
+ 
+-int cpu_add_sysdev_attr(struct sysdev_attribute *attr)
++int cpu_add_dev_attr(struct device_attribute *attr)
+ {
+ 	int cpu;
+ 
+ 	mutex_lock(&cpu_mutex);
+ 
+ 	for_each_possible_cpu(cpu) {
+-		sysdev_create_file(get_cpu_sysdev(cpu), attr);
++		device_create_file(get_cpu_device(cpu), attr);
+ 	}
+ 
+ 	mutex_unlock(&cpu_mutex);
+ 	return 0;
+ }
+-EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr);
++EXPORT_SYMBOL_GPL(cpu_add_dev_attr);
+ 
+-int cpu_add_sysdev_attr_group(struct attribute_group *attrs)
++int cpu_add_dev_attr_group(struct attribute_group *attrs)
+ {
+ 	int cpu;
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 	int ret;
+ 
+ 	mutex_lock(&cpu_mutex);
+ 
+ 	for_each_possible_cpu(cpu) {
+-		sysdev = get_cpu_sysdev(cpu);
+-		ret = sysfs_create_group(&sysdev->kobj, attrs);
++		dev = get_cpu_device(cpu);
++		ret = sysfs_create_group(&dev->kobj, attrs);
+ 		WARN_ON(ret != 0);
+ 	}
+ 
+ 	mutex_unlock(&cpu_mutex);
+ 	return 0;
+ }
+-EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group);
++EXPORT_SYMBOL_GPL(cpu_add_dev_attr_group);
+ 
+ 
+-void cpu_remove_sysdev_attr(struct sysdev_attribute *attr)
++void cpu_remove_dev_attr(struct device_attribute *attr)
+ {
+ 	int cpu;
+ 
+ 	mutex_lock(&cpu_mutex);
+ 
+ 	for_each_possible_cpu(cpu) {
+-		sysdev_remove_file(get_cpu_sysdev(cpu), attr);
++		device_remove_file(get_cpu_device(cpu), attr);
+ 	}
+ 
+ 	mutex_unlock(&cpu_mutex);
+ }
+-EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr);
++EXPORT_SYMBOL_GPL(cpu_remove_dev_attr);
+ 
+-void cpu_remove_sysdev_attr_group(struct attribute_group *attrs)
++void cpu_remove_dev_attr_group(struct attribute_group *attrs)
+ {
+ 	int cpu;
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 
+ 	mutex_lock(&cpu_mutex);
+ 
+ 	for_each_possible_cpu(cpu) {
+-		sysdev = get_cpu_sysdev(cpu);
+-		sysfs_remove_group(&sysdev->kobj, attrs);
++		dev = get_cpu_device(cpu);
++		sysfs_remove_group(&dev->kobj, attrs);
+ 	}
+ 
+ 	mutex_unlock(&cpu_mutex);
+ }
+-EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group);
++EXPORT_SYMBOL_GPL(cpu_remove_dev_attr_group);
+ 
+ 
+ /* NUMA stuff */
+@@ -590,7 +589,7 @@
+ 		register_one_node(i);
+ }
+ 
+-int sysfs_add_device_to_node(struct sys_device *dev, int nid)
++int sysfs_add_device_to_node(struct device *dev, int nid)
+ {
+ 	struct node *node = &node_devices[nid];
+ 	return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
+@@ -598,7 +597,7 @@
+ }
+ EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
+ 
+-void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
++void sysfs_remove_device_from_node(struct device *dev, int nid)
+ {
+ 	struct node *node = &node_devices[nid];
+ 	sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
+@@ -614,14 +613,14 @@
+ #endif
+ 
+ /* Only valid if CPU is present. */
+-static ssize_t show_physical_id(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_physical_id(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
++	struct cpu *cpu = container_of(dev, struct cpu, dev);
+ 
+-	return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->sysdev.id));
++	return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->dev.id));
+ }
+-static SYSDEV_ATTR(physical_id, 0444, show_physical_id, NULL);
++static DEVICE_ATTR(physical_id, 0444, show_physical_id, NULL);
+ 
+ static int __init topology_init(void)
+ {
+@@ -646,7 +645,7 @@
+ 		if (cpu_online(cpu) || c->hotpluggable) {
+ 			register_cpu(c, cpu);
+ 
+-			sysdev_create_file(&c->sysdev, &attr_physical_id);
++			device_create_file(&c->dev, &dev_attr_physical_id);
+ 		}
+ 
+ 		if (cpu_online(cpu))
+--- a/arch/powerpc/mm/numa.c
++++ b/arch/powerpc/mm/numa.c
+@@ -1462,7 +1462,7 @@
+ {
+ 	int cpu, nid, old_nid;
+ 	unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 
+ 	for_each_cpu(cpu,&cpu_associativity_changes_mask) {
+ 		vphn_get_associativity(cpu, associativity);
+@@ -1483,9 +1483,9 @@
+ 		register_cpu_under_node(cpu, nid);
+ 		put_online_cpus();
+ 
+-		sysdev = get_cpu_sysdev(cpu);
+-		if (sysdev)
+-			kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
++		dev = get_cpu_device(cpu);
++		if (dev)
++			kobject_uevent(&dev->kobj, KOBJ_CHANGE);
+ 	}
+ 
+ 	return 1;
+--- a/arch/powerpc/platforms/cell/cbe_thermal.c
++++ b/arch/powerpc/platforms/cell/cbe_thermal.c
+@@ -46,7 +46,7 @@
+  */
+ 
+ #include <linux/module.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/kernel.h>
+ #include <linux/cpu.h>
+ #include <asm/spu.h>
+@@ -59,8 +59,8 @@
+ #define TEMP_MIN 65
+ #define TEMP_MAX 125
+ 
+-#define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode)			\
+-struct sysdev_attribute attr_ ## _prefix ## _ ## _name = {	\
++#define DEVICE_PREFIX_ATTR(_prefix,_name,_mode)			\
++struct device_attribute attr_ ## _prefix ## _ ## _name = {	\
+ 	.attr = { .name = __stringify(_name), .mode = _mode },	\
+ 	.show	= _prefix ## _show_ ## _name,			\
+ 	.store	= _prefix ## _store_ ## _name,			\
+@@ -76,36 +76,36 @@
+ 	return ((temp - TEMP_MIN) >> 1) & 0x3f;
+ }
+ 
+-static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev)
++static struct cbe_pmd_regs __iomem *get_pmd_regs(struct device *dev)
+ {
+ 	struct spu *spu;
+ 
+-	spu = container_of(sysdev, struct spu, sysdev);
++	spu = container_of(dev, struct spu, dev);
+ 
+ 	return cbe_get_pmd_regs(spu_devnode(spu));
+ }
+ 
+ /* returns the value for a given spu in a given register */
+-static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg)
++static u8 spu_read_register_value(struct device *dev, union spe_reg __iomem *reg)
+ {
+ 	union spe_reg value;
+ 	struct spu *spu;
+ 
+-	spu = container_of(sysdev, struct spu, sysdev);
++	spu = container_of(dev, struct spu, dev);
+ 	value.val = in_be64(&reg->val);
+ 
+ 	return value.spe[spu->spe_id];
+ }
+ 
+-static ssize_t spu_show_temp(struct sys_device *sysdev, struct sysdev_attribute *attr,
++static ssize_t spu_show_temp(struct device *dev, struct device_attribute *attr,
+ 			char *buf)
+ {
+ 	u8 value;
+ 	struct cbe_pmd_regs __iomem *pmd_regs;
+ 
+-	pmd_regs = get_pmd_regs(sysdev);
++	pmd_regs = get_pmd_regs(dev);
+ 
+-	value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1);
++	value = spu_read_register_value(dev, &pmd_regs->ts_ctsr1);
+ 
+ 	return sprintf(buf, "%d\n", reg_to_temp(value));
+ }
+@@ -147,48 +147,48 @@
+ 	return size;
+ }
+ 
+-static ssize_t spu_show_throttle_end(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t spu_show_throttle_end(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return show_throttle(get_pmd_regs(sysdev), buf, 0);
++	return show_throttle(get_pmd_regs(dev), buf, 0);
+ }
+ 
+-static ssize_t spu_show_throttle_begin(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t spu_show_throttle_begin(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return show_throttle(get_pmd_regs(sysdev), buf, 8);
++	return show_throttle(get_pmd_regs(dev), buf, 8);
+ }
+ 
+-static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t spu_show_throttle_full_stop(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return show_throttle(get_pmd_regs(sysdev), buf, 16);
++	return show_throttle(get_pmd_regs(dev), buf, 16);
+ }
+ 
+-static ssize_t spu_store_throttle_end(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, const char *buf, size_t size)
++static ssize_t spu_store_throttle_end(struct device *dev,
++			struct device_attribute *attr, const char *buf, size_t size)
+ {
+-	return store_throttle(get_pmd_regs(sysdev), buf, size, 0);
++	return store_throttle(get_pmd_regs(dev), buf, size, 0);
+ }
+ 
+-static ssize_t spu_store_throttle_begin(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, const char *buf, size_t size)
++static ssize_t spu_store_throttle_begin(struct device *dev,
++			struct device_attribute *attr, const char *buf, size_t size)
+ {
+-	return store_throttle(get_pmd_regs(sysdev), buf, size, 8);
++	return store_throttle(get_pmd_regs(dev), buf, size, 8);
+ }
+ 
+-static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, const char *buf, size_t size)
++static ssize_t spu_store_throttle_full_stop(struct device *dev,
++			struct device_attribute *attr, const char *buf, size_t size)
+ {
+-	return store_throttle(get_pmd_regs(sysdev), buf, size, 16);
++	return store_throttle(get_pmd_regs(dev), buf, size, 16);
+ }
+ 
+-static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos)
++static ssize_t ppe_show_temp(struct device *dev, char *buf, int pos)
+ {
+ 	struct cbe_pmd_regs __iomem *pmd_regs;
+ 	u64 value;
+ 
+-	pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
++	pmd_regs = cbe_get_cpu_pmd_regs(dev->id);
+ 	value = in_be64(&pmd_regs->ts_ctsr2);
+ 
+ 	value = (value >> pos) & 0x3f;
+@@ -199,64 +199,64 @@
+ 
+ /* shows the temperature of the DTS on the PPE,
+  * located near the linear thermal sensor */
+-static ssize_t ppe_show_temp0(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t ppe_show_temp0(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return ppe_show_temp(sysdev, buf, 32);
++	return ppe_show_temp(dev, buf, 32);
+ }
+ 
+ /* shows the temperature of the second DTS on the PPE */
+-static ssize_t ppe_show_temp1(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t ppe_show_temp1(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return ppe_show_temp(sysdev, buf, 0);
++	return ppe_show_temp(dev, buf, 0);
+ }
+ 
+-static ssize_t ppe_show_throttle_end(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t ppe_show_throttle_end(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32);
++	return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 32);
+ }
+ 
+-static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t ppe_show_throttle_begin(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40);
++	return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 40);
+ }
+ 
+-static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t ppe_show_throttle_full_stop(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48);
++	return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 48);
+ }
+ 
+-static ssize_t ppe_store_throttle_end(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, const char *buf, size_t size)
++static ssize_t ppe_store_throttle_end(struct device *dev,
++			struct device_attribute *attr, const char *buf, size_t size)
+ {
+-	return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32);
++	return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 32);
+ }
+ 
+-static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, const char *buf, size_t size)
++static ssize_t ppe_store_throttle_begin(struct device *dev,
++			struct device_attribute *attr, const char *buf, size_t size)
+ {
+-	return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40);
++	return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 40);
+ }
+ 
+-static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev,
+-			struct sysdev_attribute *attr, const char *buf, size_t size)
++static ssize_t ppe_store_throttle_full_stop(struct device *dev,
++			struct device_attribute *attr, const char *buf, size_t size)
+ {
+-	return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48);
++	return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 48);
+ }
+ 
+ 
+-static struct sysdev_attribute attr_spu_temperature = {
++static struct device_attribute attr_spu_temperature = {
+ 	.attr = {.name = "temperature", .mode = 0400 },
+ 	.show = spu_show_temp,
+ };
+ 
+-static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600);
+-static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600);
+-static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600);
++static DEVICE_PREFIX_ATTR(spu, throttle_end, 0600);
++static DEVICE_PREFIX_ATTR(spu, throttle_begin, 0600);
++static DEVICE_PREFIX_ATTR(spu, throttle_full_stop, 0600);
+ 
+ 
+ static struct attribute *spu_attributes[] = {
+@@ -272,19 +272,19 @@
+ 	.attrs	= spu_attributes,
+ };
+ 
+-static struct sysdev_attribute attr_ppe_temperature0 = {
++static struct device_attribute attr_ppe_temperature0 = {
+ 	.attr = {.name = "temperature0", .mode = 0400 },
+ 	.show = ppe_show_temp0,
+ };
+ 
+-static struct sysdev_attribute attr_ppe_temperature1 = {
++static struct device_attribute attr_ppe_temperature1 = {
+ 	.attr = {.name = "temperature1", .mode = 0400 },
+ 	.show = ppe_show_temp1,
+ };
+ 
+-static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600);
+-static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600);
+-static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600);
++static DEVICE_PREFIX_ATTR(ppe, throttle_end, 0600);
++static DEVICE_PREFIX_ATTR(ppe, throttle_begin, 0600);
++static DEVICE_PREFIX_ATTR(ppe, throttle_full_stop, 0600);
+ 
+ static struct attribute *ppe_attributes[] = {
+ 	&attr_ppe_temperature0.attr,
+@@ -307,7 +307,7 @@
+ {
+ 	int cpu;
+ 	struct cbe_pmd_regs __iomem *pmd_regs;
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 	union ppe_spe_reg tpr;
+ 	union spe_reg str1;
+ 	u64 str2;
+@@ -349,14 +349,14 @@
+ 
+ 	for_each_possible_cpu (cpu) {
+ 		pr_debug("processing cpu %d\n", cpu);
+-		sysdev = get_cpu_sysdev(cpu);
++		dev = get_cpu_device(cpu);
+ 
+-		if (!sysdev) {
+-			pr_info("invalid sysdev pointer for cbe_thermal\n");
++		if (!dev) {
++			pr_info("invalid dev pointer for cbe_thermal\n");
+ 			return -EINVAL;
+ 		}
+ 
+-		pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id);
++		pmd_regs = cbe_get_cpu_pmd_regs(dev->id);
+ 
+ 		if (!pmd_regs) {
+ 			pr_info("invalid CBE regs pointer for cbe_thermal\n");
+@@ -379,8 +379,8 @@
+ 	int rc = init_default_values();
+ 
+ 	if (rc == 0) {
+-		spu_add_sysdev_attr_group(&spu_attribute_group);
+-		cpu_add_sysdev_attr_group(&ppe_attribute_group);
++		spu_add_dev_attr_group(&spu_attribute_group);
++		cpu_add_dev_attr_group(&ppe_attribute_group);
+ 	}
+ 
+ 	return rc;
+@@ -389,8 +389,8 @@
+ 
+ static void __exit thermal_exit(void)
+ {
+-	spu_remove_sysdev_attr_group(&spu_attribute_group);
+-	cpu_remove_sysdev_attr_group(&ppe_attribute_group);
++	spu_remove_dev_attr_group(&spu_attribute_group);
++	cpu_remove_dev_attr_group(&ppe_attribute_group);
+ }
+ module_exit(thermal_exit);
+ 
+--- a/arch/powerpc/platforms/cell/spu_base.c
++++ b/arch/powerpc/platforms/cell/spu_base.c
+@@ -519,31 +519,32 @@
+ }
+ EXPORT_SYMBOL_GPL(spu_init_channels);
+ 
+-static struct sysdev_class spu_sysdev_class = {
++static struct bus_type spu_subsys = {
+ 	.name = "spu",
++	.dev_name = "spu",
+ };
+ 
+-int spu_add_sysdev_attr(struct sysdev_attribute *attr)
++int spu_add_dev_attr(struct device_attribute *attr)
+ {
+ 	struct spu *spu;
+ 
+ 	mutex_lock(&spu_full_list_mutex);
+ 	list_for_each_entry(spu, &spu_full_list, full_list)
+-		sysdev_create_file(&spu->sysdev, attr);
++		device_create_file(&spu->dev, attr);
+ 	mutex_unlock(&spu_full_list_mutex);
+ 
+ 	return 0;
+ }
+-EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
++EXPORT_SYMBOL_GPL(spu_add_dev_attr);
+ 
+-int spu_add_sysdev_attr_group(struct attribute_group *attrs)
++int spu_add_dev_attr_group(struct attribute_group *attrs)
+ {
+ 	struct spu *spu;
+ 	int rc = 0;
+ 
+ 	mutex_lock(&spu_full_list_mutex);
+ 	list_for_each_entry(spu, &spu_full_list, full_list) {
+-		rc = sysfs_create_group(&spu->sysdev.kobj, attrs);
++		rc = sysfs_create_group(&spu->dev.kobj, attrs);
+ 
+ 		/* we're in trouble here, but try unwinding anyway */
+ 		if (rc) {
+@@ -552,7 +553,7 @@
+ 
+ 			list_for_each_entry_continue_reverse(spu,
+ 					&spu_full_list, full_list)
+-				sysfs_remove_group(&spu->sysdev.kobj, attrs);
++				sysfs_remove_group(&spu->dev.kobj, attrs);
+ 			break;
+ 		}
+ 	}
+@@ -561,45 +562,45 @@
+ 
+ 	return rc;
+ }
+-EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
++EXPORT_SYMBOL_GPL(spu_add_dev_attr_group);
+ 
+ 
+-void spu_remove_sysdev_attr(struct sysdev_attribute *attr)
++void spu_remove_dev_attr(struct device_attribute *attr)
+ {
+ 	struct spu *spu;
+ 
+ 	mutex_lock(&spu_full_list_mutex);
+ 	list_for_each_entry(spu, &spu_full_list, full_list)
+-		sysdev_remove_file(&spu->sysdev, attr);
++		device_remove_file(&spu->dev, attr);
+ 	mutex_unlock(&spu_full_list_mutex);
+ }
+-EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr);
++EXPORT_SYMBOL_GPL(spu_remove_dev_attr);
+ 
+-void spu_remove_sysdev_attr_group(struct attribute_group *attrs)
++void spu_remove_dev_attr_group(struct attribute_group *attrs)
+ {
+ 	struct spu *spu;
+ 
+ 	mutex_lock(&spu_full_list_mutex);
+ 	list_for_each_entry(spu, &spu_full_list, full_list)
+-		sysfs_remove_group(&spu->sysdev.kobj, attrs);
++		sysfs_remove_group(&spu->dev.kobj, attrs);
+ 	mutex_unlock(&spu_full_list_mutex);
+ }
+-EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group);
++EXPORT_SYMBOL_GPL(spu_remove_dev_attr_group);
+ 
+-static int spu_create_sysdev(struct spu *spu)
++static int spu_create_dev(struct spu *spu)
+ {
+ 	int ret;
+ 
+-	spu->sysdev.id = spu->number;
+-	spu->sysdev.cls = &spu_sysdev_class;
+-	ret = sysdev_register(&spu->sysdev);
++	spu->dev.id = spu->number;
++	spu->dev.bus = &spu_subsys;
++	ret = device_register(&spu->dev);
+ 	if (ret) {
+ 		printk(KERN_ERR "Can't register SPU %d with sysfs\n",
+ 				spu->number);
+ 		return ret;
+ 	}
+ 
+-	sysfs_add_device_to_node(&spu->sysdev, spu->node);
++	sysfs_add_device_to_node(&spu->dev, spu->node);
+ 
+ 	return 0;
+ }
+@@ -635,7 +636,7 @@
+ 	if (ret)
+ 		goto out_destroy;
+ 
+-	ret = spu_create_sysdev(spu);
++	ret = spu_create_dev(spu);
+ 	if (ret)
+ 		goto out_free_irqs;
+ 
+@@ -692,10 +693,10 @@
+ }
+ 
+ 
+-static ssize_t spu_stat_show(struct sys_device *sysdev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t spu_stat_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+-	struct spu *spu = container_of(sysdev, struct spu, sysdev);
++	struct spu *spu = container_of(dev, struct spu, dev);
+ 
+ 	return sprintf(buf, "%s %llu %llu %llu %llu "
+ 		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+@@ -714,7 +715,7 @@
+ 		spu->stats.libassist);
+ }
+ 
+-static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL);
++static DEVICE_ATTR(stat, 0644, spu_stat_show, NULL);
+ 
+ #ifdef CONFIG_KEXEC
+ 
+@@ -813,8 +814,8 @@
+ 	if (!spu_management_ops)
+ 		goto out;
+ 
+-	/* create sysdev class for spus */
+-	ret = sysdev_class_register(&spu_sysdev_class);
++	/* create system subsystem for spus */
++	ret = subsys_system_register(&spu_subsys, NULL);
+ 	if (ret)
+ 		goto out;
+ 
+@@ -823,7 +824,7 @@
+ 	if (ret < 0) {
+ 		printk(KERN_WARNING "%s: Error initializing spus\n",
+ 			__func__);
+-		goto out_unregister_sysdev_class;
++		goto out_unregister_subsys;
+ 	}
+ 
+ 	if (ret > 0)
+@@ -833,15 +834,15 @@
+ 	xmon_register_spus(&spu_full_list);
+ 	crash_register_spus(&spu_full_list);
+ 	mutex_unlock(&spu_full_list_mutex);
+-	spu_add_sysdev_attr(&attr_stat);
++	spu_add_dev_attr(&dev_attr_stat);
+ 	register_syscore_ops(&spu_syscore_ops);
+ 
+ 	spu_init_affinity();
+ 
+ 	return 0;
+ 
+- out_unregister_sysdev_class:
+-	sysdev_class_unregister(&spu_sysdev_class);
++ out_unregister_subsys:
++	bus_unregister(&spu_subsys);
+  out:
+ 	return ret;
+ }
+--- a/arch/powerpc/platforms/pseries/pseries_energy.c
++++ b/arch/powerpc/platforms/pseries/pseries_energy.c
+@@ -15,7 +15,7 @@
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/seq_file.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/cpu.h>
+ #include <linux/of.h>
+ #include <asm/cputhreads.h>
+@@ -184,7 +184,7 @@
+ 	return s-page;
+ }
+ 
+-static ssize_t get_best_energy_data(struct sys_device *dev,
++static ssize_t get_best_energy_data(struct device *dev,
+ 					char *page, int activate)
+ {
+ 	int rc;
+@@ -207,26 +207,26 @@
+ 
+ /* Wrapper functions */
+ 
+-static ssize_t cpu_activate_hint_list_show(struct sysdev_class *class,
+-			struct sysdev_class_attribute *attr, char *page)
++static ssize_t cpu_activate_hint_list_show(struct device *dev,
++			struct device_attribute *attr, char *page)
+ {
+ 	return get_best_energy_list(page, 1);
+ }
+ 
+-static ssize_t cpu_deactivate_hint_list_show(struct sysdev_class *class,
+-			struct sysdev_class_attribute *attr, char *page)
++static ssize_t cpu_deactivate_hint_list_show(struct device *dev,
++			struct device_attribute *attr, char *page)
+ {
+ 	return get_best_energy_list(page, 0);
+ }
+ 
+-static ssize_t percpu_activate_hint_show(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *page)
++static ssize_t percpu_activate_hint_show(struct device *dev,
++			struct device_attribute *attr, char *page)
+ {
+ 	return get_best_energy_data(dev, page, 1);
+ }
+ 
+-static ssize_t percpu_deactivate_hint_show(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *page)
++static ssize_t percpu_deactivate_hint_show(struct device *dev,
++			struct device_attribute *attr, char *page)
+ {
+ 	return get_best_energy_data(dev, page, 0);
+ }
+@@ -241,48 +241,48 @@
+  *	Per-cpu value of the hint
+  */
+ 
+-struct sysdev_class_attribute attr_cpu_activate_hint_list =
+-		_SYSDEV_CLASS_ATTR(pseries_activate_hint_list, 0444,
++struct device_attribute attr_cpu_activate_hint_list =
++		__ATTR(pseries_activate_hint_list, 0444,
+ 		cpu_activate_hint_list_show, NULL);
+ 
+-struct sysdev_class_attribute attr_cpu_deactivate_hint_list =
+-		_SYSDEV_CLASS_ATTR(pseries_deactivate_hint_list, 0444,
++struct device_attribute attr_cpu_deactivate_hint_list =
++		__ATTR(pseries_deactivate_hint_list, 0444,
+ 		cpu_deactivate_hint_list_show, NULL);
+ 
+-struct sysdev_attribute attr_percpu_activate_hint =
+-		_SYSDEV_ATTR(pseries_activate_hint, 0444,
++struct device_attribute attr_percpu_activate_hint =
++		__ATTR(pseries_activate_hint, 0444,
+ 		percpu_activate_hint_show, NULL);
+ 
+-struct sysdev_attribute attr_percpu_deactivate_hint =
+-		_SYSDEV_ATTR(pseries_deactivate_hint, 0444,
++struct device_attribute attr_percpu_deactivate_hint =
++		__ATTR(pseries_deactivate_hint, 0444,
+ 		percpu_deactivate_hint_show, NULL);
+ 
+ static int __init pseries_energy_init(void)
+ {
+ 	int cpu, err;
+-	struct sys_device *cpu_sys_dev;
++	struct device *cpu_dev;
+ 
+ 	if (!check_for_h_best_energy()) {
+ 		printk(KERN_INFO "Hypercall H_BEST_ENERGY not supported\n");
+ 		return 0;
+ 	}
+ 	/* Create the sysfs files */
+-	err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+-				&attr_cpu_activate_hint_list.attr);
++	err = device_create_file(cpu_subsys.dev_root,
++				&attr_cpu_activate_hint_list);
+ 	if (!err)
+-		err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+-				&attr_cpu_deactivate_hint_list.attr);
++		err = device_create_file(cpu_subsys.dev_root,
++				&attr_cpu_deactivate_hint_list);
+ 
+ 	if (err)
+ 		return err;
+ 	for_each_possible_cpu(cpu) {
+-		cpu_sys_dev = get_cpu_sysdev(cpu);
+-		err = sysfs_create_file(&cpu_sys_dev->kobj,
+-				&attr_percpu_activate_hint.attr);
++		cpu_dev = get_cpu_device(cpu);
++		err = device_create_file(cpu_dev,
++				&attr_percpu_activate_hint);
+ 		if (err)
+ 			break;
+-		err = sysfs_create_file(&cpu_sys_dev->kobj,
+-				&attr_percpu_deactivate_hint.attr);
++		err = device_create_file(cpu_dev,
++				&attr_percpu_deactivate_hint);
+ 		if (err)
+ 			break;
+ 	}
+@@ -298,23 +298,20 @@
+ static void __exit pseries_energy_cleanup(void)
+ {
+ 	int cpu;
+-	struct sys_device *cpu_sys_dev;
++	struct device *cpu_dev;
+ 
+ 	if (!sysfs_entries)
+ 		return;
+ 
+ 	/* Remove the sysfs files */
+-	sysfs_remove_file(&cpu_sysdev_class.kset.kobj,
+-				&attr_cpu_activate_hint_list.attr);
+-
+-	sysfs_remove_file(&cpu_sysdev_class.kset.kobj,
+-				&attr_cpu_deactivate_hint_list.attr);
++	device_remove_file(cpu_subsys.dev_root, &attr_cpu_activate_hint_list);
++	device_remove_file(cpu_subsys.dev_root, &attr_cpu_deactivate_hint_list);
+ 
+ 	for_each_possible_cpu(cpu) {
+-		cpu_sys_dev = get_cpu_sysdev(cpu);
+-		sysfs_remove_file(&cpu_sys_dev->kobj,
++		cpu_dev = get_cpu_device(cpu);
++		sysfs_remove_file(&cpu_dev->kobj,
+ 				&attr_percpu_activate_hint.attr);
+-		sysfs_remove_file(&cpu_sys_dev->kobj,
++		sysfs_remove_file(&cpu_dev->kobj,
+ 				&attr_percpu_deactivate_hint.attr);
+ 	}
+ }
+--- a/arch/powerpc/sysdev/ppc4xx_cpm.c
++++ b/arch/powerpc/sysdev/ppc4xx_cpm.c
+@@ -179,12 +179,12 @@
+ 
+ static void cpm_idle_config_sysfs(void)
+ {
+-	struct sys_device *sys_dev;
++	struct device *dev;
+ 	unsigned long ret;
+ 
+-	sys_dev = get_cpu_sysdev(0);
++	dev = get_cpu_device(0);
+ 
+-	ret = sysfs_create_file(&sys_dev->kobj,
++	ret = sysfs_create_file(&dev->kobj,
+ 				&cpm_idle_attr.attr);
+ 	if (ret)
+ 		printk(KERN_WARNING
+--- a/arch/s390/kernel/smp.c
++++ b/arch/s390/kernel/smp.c
+@@ -831,8 +831,8 @@
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-static ssize_t cpu_configure_show(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t cpu_configure_show(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	ssize_t count;
+ 
+@@ -842,8 +842,8 @@
+ 	return count;
+ }
+ 
+-static ssize_t cpu_configure_store(struct sys_device *dev,
+-				  struct sysdev_attribute *attr,
++static ssize_t cpu_configure_store(struct device *dev,
++				  struct device_attribute *attr,
+ 				  const char *buf, size_t count)
+ {
+ 	int cpu = dev->id;
+@@ -889,11 +889,11 @@
+ 	put_online_cpus();
+ 	return rc ? rc : count;
+ }
+-static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
++static DEVICE_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
+ #endif /* CONFIG_HOTPLUG_CPU */
+ 
+-static ssize_t cpu_polarization_show(struct sys_device *dev,
+-				     struct sysdev_attribute *attr, char *buf)
++static ssize_t cpu_polarization_show(struct device *dev,
++				     struct device_attribute *attr, char *buf)
+ {
+ 	int cpu = dev->id;
+ 	ssize_t count;
+@@ -919,22 +919,22 @@
+ 	mutex_unlock(&smp_cpu_state_mutex);
+ 	return count;
+ }
+-static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL);
++static DEVICE_ATTR(polarization, 0444, cpu_polarization_show, NULL);
+ 
+-static ssize_t show_cpu_address(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_cpu_address(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]);
+ }
+-static SYSDEV_ATTR(address, 0444, show_cpu_address, NULL);
++static DEVICE_ATTR(address, 0444, show_cpu_address, NULL);
+ 
+ 
+ static struct attribute *cpu_common_attrs[] = {
+ #ifdef CONFIG_HOTPLUG_CPU
+-	&attr_configure.attr,
++	&dev_attr_configure.attr,
+ #endif
+-	&attr_address.attr,
+-	&attr_polarization.attr,
++	&dev_attr_address.attr,
++	&dev_attr_polarization.attr,
+ 	NULL,
+ };
+ 
+@@ -942,8 +942,8 @@
+ 	.attrs = cpu_common_attrs,
+ };
+ 
+-static ssize_t show_capability(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_capability(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	unsigned int capability;
+ 	int rc;
+@@ -953,10 +953,10 @@
+ 		return rc;
+ 	return sprintf(buf, "%u\n", capability);
+ }
+-static SYSDEV_ATTR(capability, 0444, show_capability, NULL);
++static DEVICE_ATTR(capability, 0444, show_capability, NULL);
+ 
+-static ssize_t show_idle_count(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_idle_count(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	struct s390_idle_data *idle;
+ 	unsigned long long idle_count;
+@@ -976,10 +976,10 @@
+ 		goto repeat;
+ 	return sprintf(buf, "%llu\n", idle_count);
+ }
+-static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
++static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
+ 
+-static ssize_t show_idle_time(struct sys_device *dev,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_idle_time(struct device *dev,
++				struct device_attribute *attr, char *buf)
+ {
+ 	struct s390_idle_data *idle;
+ 	unsigned long long now, idle_time, idle_enter;
+@@ -1001,12 +1001,12 @@
+ 		goto repeat;
+ 	return sprintf(buf, "%llu\n", idle_time >> 12);
+ }
+-static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
++static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
+ 
+ static struct attribute *cpu_online_attrs[] = {
+-	&attr_capability.attr,
+-	&attr_idle_count.attr,
+-	&attr_idle_time_us.attr,
++	&dev_attr_capability.attr,
++	&dev_attr_idle_count.attr,
++	&dev_attr_idle_time_us.attr,
+ 	NULL,
+ };
+ 
+@@ -1019,7 +1019,7 @@
+ {
+ 	unsigned int cpu = (unsigned int)(long)hcpu;
+ 	struct cpu *c = &per_cpu(cpu_devices, cpu);
+-	struct sys_device *s = &c->sysdev;
++	struct device *s = &c->dev;
+ 	struct s390_idle_data *idle;
+ 	int err = 0;
+ 
+@@ -1045,7 +1045,7 @@
+ static int __devinit smp_add_present_cpu(int cpu)
+ {
+ 	struct cpu *c = &per_cpu(cpu_devices, cpu);
+-	struct sys_device *s = &c->sysdev;
++	struct device *s = &c->dev;
+ 	int rc;
+ 
+ 	c->hotpluggable = 1;
+@@ -1098,8 +1098,8 @@
+ 	return rc;
+ }
+ 
+-static ssize_t __ref rescan_store(struct sysdev_class *class,
+-				  struct sysdev_class_attribute *attr,
++static ssize_t __ref rescan_store(struct device *dev,
++				  struct device_attribute *attr,
+ 				  const char *buf,
+ 				  size_t count)
+ {
+@@ -1108,11 +1108,11 @@
+ 	rc = smp_rescan_cpus();
+ 	return rc ? rc : count;
+ }
+-static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store);
++static DEVICE_ATTR(rescan, 0200, NULL, rescan_store);
+ #endif /* CONFIG_HOTPLUG_CPU */
+ 
+-static ssize_t dispatching_show(struct sysdev_class *class,
+-				struct sysdev_class_attribute *attr,
++static ssize_t dispatching_show(struct device *dev,
++				struct device_attribute *attr,
+ 				char *buf)
+ {
+ 	ssize_t count;
+@@ -1123,8 +1123,8 @@
+ 	return count;
+ }
+ 
+-static ssize_t dispatching_store(struct sysdev_class *dev,
+-				 struct sysdev_class_attribute *attr,
++static ssize_t dispatching_store(struct device *dev,
++				 struct device_attribute *attr,
+ 				 const char *buf,
+ 				 size_t count)
+ {
+@@ -1148,7 +1148,7 @@
+ 	put_online_cpus();
+ 	return rc ? rc : count;
+ }
+-static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show,
++static DEVICE_ATTR(dispatching, 0644, dispatching_show,
+ 			 dispatching_store);
+ 
+ static int __init topology_init(void)
+@@ -1159,11 +1159,11 @@
+ 	register_cpu_notifier(&smp_cpu_nb);
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-	rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_rescan);
++	rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan);
+ 	if (rc)
+ 		return rc;
+ #endif
+-	rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_dispatching);
++	rc = device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
+ 	if (rc)
+ 		return rc;
+ 	for_each_present_cpu(cpu) {
+--- a/arch/s390/kernel/topology.c
++++ b/arch/s390/kernel/topology.c
+@@ -261,7 +261,7 @@
+ int arch_update_cpu_topology(void)
+ {
+ 	struct sysinfo_15_1_x *info = tl_info;
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 	int cpu;
+ 
+ 	if (!MACHINE_HAS_TOPOLOGY) {
+@@ -273,8 +273,8 @@
+ 	tl_to_cores(info);
+ 	update_cpu_core_map();
+ 	for_each_online_cpu(cpu) {
+-		sysdev = get_cpu_sysdev(cpu);
+-		kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
++		dev = get_cpu_device(cpu);
++		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
+ 	}
+ 	return 1;
+ }
+--- a/arch/sh/kernel/cpu/sh4/sq.c
++++ b/arch/sh/kernel/cpu/sh4/sq.c
+@@ -13,7 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/cpu.h>
+ #include <linux/bitmap.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+@@ -337,9 +337,9 @@
+ 	.default_attrs	= sq_sysfs_attrs,
+ };
+ 
+-static int __devinit sq_sysdev_add(struct sys_device *sysdev)
++static int __devinit sq_dev_add(struct device *dev)
+ {
+-	unsigned int cpu = sysdev->id;
++	unsigned int cpu = dev->id;
+ 	struct kobject *kobj;
+ 	int error;
+ 
+@@ -348,25 +348,27 @@
+ 		return -ENOMEM;
+ 
+ 	kobj = sq_kobject[cpu];
+-	error = kobject_init_and_add(kobj, &ktype_percpu_entry, &sysdev->kobj,
++	error = kobject_init_and_add(kobj, &ktype_percpu_entry, &dev->kobj,
+ 				     "%s", "sq");
+ 	if (!error)
+ 		kobject_uevent(kobj, KOBJ_ADD);
+ 	return error;
+ }
+ 
+-static int __devexit sq_sysdev_remove(struct sys_device *sysdev)
++static int __devexit sq_dev_remove(struct device *dev)
+ {
+-	unsigned int cpu = sysdev->id;
++	unsigned int cpu = dev->id;
+ 	struct kobject *kobj = sq_kobject[cpu];
+ 
+ 	kobject_put(kobj);
+ 	return 0;
+ }
+ 
+-static struct sysdev_driver sq_sysdev_driver = {
+-	.add		= sq_sysdev_add,
+-	.remove		= __devexit_p(sq_sysdev_remove),
++static struct subsys_interface sq_interface = {
++	.name		= "sq"
++	.subsys		= &cpu_subsys,
++	.add_dev	= sq_dev_add,
++	.remove_dev	= __devexit_p(sq_dev_remove),
+ };
+ 
+ static int __init sq_api_init(void)
+@@ -386,7 +388,7 @@
+ 	if (unlikely(!sq_bitmap))
+ 		goto out;
+ 
+-	ret = sysdev_driver_register(&cpu_sysdev_class, &sq_sysdev_driver);
++	ret = subsys_interface_register(&sq_interface);
+ 	if (unlikely(ret != 0))
+ 		goto out;
+ 
+@@ -401,7 +403,7 @@
+ 
+ static void __exit sq_api_exit(void)
+ {
+-	sysdev_driver_unregister(&cpu_sysdev_class, &sq_sysdev_driver);
++	subsys_interface_unregister(&sq_interface);
+ 	kfree(sq_bitmap);
+ 	kmem_cache_destroy(sq_cache);
+ }
+--- a/arch/sparc/kernel/sysfs.c
++++ b/arch/sparc/kernel/sysfs.c
+@@ -3,7 +3,7 @@
+  * Copyright (C) 2007 David S. Miller <davem at davemloft.net>
+  */
+ #include <linux/sched.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/cpu.h>
+ #include <linux/smp.h>
+ #include <linux/percpu.h>
+@@ -16,13 +16,13 @@
+ static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
+ 
+ #define SHOW_MMUSTAT_ULONG(NAME) \
+-static ssize_t show_##NAME(struct sys_device *dev, \
+-			struct sysdev_attribute *attr, char *buf) \
++static ssize_t show_##NAME(struct device *dev, \
++			struct device_attribute *attr, char *buf) \
+ { \
+ 	struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
+ 	return sprintf(buf, "%lu\n", p->NAME); \
+ } \
+-static SYSDEV_ATTR(NAME, 0444, show_##NAME, NULL)
++static DEVICE_ATTR(NAME, 0444, show_##NAME, NULL)
+ 
+ SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte);
+ SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte);
+@@ -58,38 +58,38 @@
+ SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte);
+ 
+ static struct attribute *mmu_stat_attrs[] = {
+-	&attr_immu_tsb_hits_ctx0_8k_tte.attr,
+-	&attr_immu_tsb_ticks_ctx0_8k_tte.attr,
+-	&attr_immu_tsb_hits_ctx0_64k_tte.attr,
+-	&attr_immu_tsb_ticks_ctx0_64k_tte.attr,
+-	&attr_immu_tsb_hits_ctx0_4mb_tte.attr,
+-	&attr_immu_tsb_ticks_ctx0_4mb_tte.attr,
+-	&attr_immu_tsb_hits_ctx0_256mb_tte.attr,
+-	&attr_immu_tsb_ticks_ctx0_256mb_tte.attr,
+-	&attr_immu_tsb_hits_ctxnon0_8k_tte.attr,
+-	&attr_immu_tsb_ticks_ctxnon0_8k_tte.attr,
+-	&attr_immu_tsb_hits_ctxnon0_64k_tte.attr,
+-	&attr_immu_tsb_ticks_ctxnon0_64k_tte.attr,
+-	&attr_immu_tsb_hits_ctxnon0_4mb_tte.attr,
+-	&attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr,
+-	&attr_immu_tsb_hits_ctxnon0_256mb_tte.attr,
+-	&attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr,
+-	&attr_dmmu_tsb_hits_ctx0_8k_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctx0_8k_tte.attr,
+-	&attr_dmmu_tsb_hits_ctx0_64k_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctx0_64k_tte.attr,
+-	&attr_dmmu_tsb_hits_ctx0_4mb_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr,
+-	&attr_dmmu_tsb_hits_ctx0_256mb_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr,
+-	&attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr,
+-	&attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr,
+-	&attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr,
+-	&attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr,
+-	&attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr,
++	&dev_attr_immu_tsb_hits_ctx0_8k_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctx0_8k_tte.attr,
++	&dev_attr_immu_tsb_hits_ctx0_64k_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctx0_64k_tte.attr,
++	&dev_attr_immu_tsb_hits_ctx0_4mb_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctx0_4mb_tte.attr,
++	&dev_attr_immu_tsb_hits_ctx0_256mb_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctx0_256mb_tte.attr,
++	&dev_attr_immu_tsb_hits_ctxnon0_8k_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctxnon0_8k_tte.attr,
++	&dev_attr_immu_tsb_hits_ctxnon0_64k_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctxnon0_64k_tte.attr,
++	&dev_attr_immu_tsb_hits_ctxnon0_4mb_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr,
++	&dev_attr_immu_tsb_hits_ctxnon0_256mb_tte.attr,
++	&dev_attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctx0_8k_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctx0_8k_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctx0_64k_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctx0_64k_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctx0_4mb_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctx0_256mb_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr,
++	&dev_attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr,
++	&dev_attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr,
+ 	NULL,
+ };
+ 
+@@ -139,15 +139,15 @@
+ 	return sun4v_mmustat_conf(ra, &orig_ra);
+ }
+ 
+-static ssize_t show_mmustat_enable(struct sys_device *s,
+-				struct sysdev_attribute *attr, char *buf)
++static ssize_t show_mmustat_enable(struct device *s,
++				struct device_attribute *attr, char *buf)
+ {
+ 	unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0);
+ 	return sprintf(buf, "%lx\n", val);
+ }
+ 
+-static ssize_t store_mmustat_enable(struct sys_device *s,
+-			struct sysdev_attribute *attr, const char *buf,
++static ssize_t store_mmustat_enable(struct device *s,
++			struct device_attribute *attr, const char *buf,
+ 			size_t count)
+ {
+ 	unsigned long val, err;
+@@ -163,39 +163,39 @@
+ 	return count;
+ }
+ 
+-static SYSDEV_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable);
++static DEVICE_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable);
+ 
+ static int mmu_stats_supported;
+ 
+-static int register_mmu_stats(struct sys_device *s)
++static int register_mmu_stats(struct device *s)
+ {
+ 	if (!mmu_stats_supported)
+ 		return 0;
+-	sysdev_create_file(s, &attr_mmustat_enable);
++	device_create_file(s, &dev_attr_mmustat_enable);
+ 	return sysfs_create_group(&s->kobj, &mmu_stat_group);
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-static void unregister_mmu_stats(struct sys_device *s)
++static void unregister_mmu_stats(struct device *s)
+ {
+ 	if (!mmu_stats_supported)
+ 		return;
+ 	sysfs_remove_group(&s->kobj, &mmu_stat_group);
+-	sysdev_remove_file(s, &attr_mmustat_enable);
++	device_remove_file(s, &dev_attr_mmustat_enable);
+ }
+ #endif
+ 
+ #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
+-static ssize_t show_##NAME(struct sys_device *dev, \
+-		struct sysdev_attribute *attr, char *buf) \
++static ssize_t show_##NAME(struct device *dev, \
++		struct device_attribute *attr, char *buf) \
+ { \
+ 	cpuinfo_sparc *c = &cpu_data(dev->id); \
+ 	return sprintf(buf, "%lu\n", c->MEMBER); \
+ }
+ 
+ #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
+-static ssize_t show_##NAME(struct sys_device *dev, \
+-		struct sysdev_attribute *attr, char *buf) \
++static ssize_t show_##NAME(struct device *dev, \
++		struct device_attribute *attr, char *buf) \
+ { \
+ 	cpuinfo_sparc *c = &cpu_data(dev->id); \
+ 	return sprintf(buf, "%u\n", c->MEMBER); \
+@@ -209,14 +209,14 @@
+ SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size);
+ SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size);
+ 
+-static struct sysdev_attribute cpu_core_attrs[] = {
+-	_SYSDEV_ATTR(clock_tick,          0444, show_clock_tick, NULL),
+-	_SYSDEV_ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
+-	_SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
+-	_SYSDEV_ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
+-	_SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
+-	_SYSDEV_ATTR(l2_cache_size,       0444, show_l2_cache_size, NULL),
+-	_SYSDEV_ATTR(l2_cache_line_size,  0444, show_l2_cache_line_size, NULL),
++static struct device_attribute cpu_core_attrs[] = {
++	__ATTR(clock_tick,          0444, show_clock_tick, NULL),
++	__ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
++	__ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
++	__ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
++	__ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
++	__ATTR(l2_cache_size,       0444, show_l2_cache_size, NULL),
++	__ATTR(l2_cache_line_size,  0444, show_l2_cache_line_size, NULL),
+ };
+ 
+ static DEFINE_PER_CPU(struct cpu, cpu_devices);
+@@ -224,11 +224,11 @@
+ static void register_cpu_online(unsigned int cpu)
+ {
+ 	struct cpu *c = &per_cpu(cpu_devices, cpu);
+-	struct sys_device *s = &c->sysdev;
++	struct device *s = &c->dev;
+ 	int i;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+-		sysdev_create_file(s, &cpu_core_attrs[i]);
++		device_create_file(s, &cpu_core_attrs[i]);
+ 
+ 	register_mmu_stats(s);
+ }
+@@ -237,12 +237,12 @@
+ static void unregister_cpu_online(unsigned int cpu)
+ {
+ 	struct cpu *c = &per_cpu(cpu_devices, cpu);
+-	struct sys_device *s = &c->sysdev;
++	struct device *s = &c->dev;
+ 	int i;
+ 
+ 	unregister_mmu_stats(s);
+ 	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+-		sysdev_remove_file(s, &cpu_core_attrs[i]);
++		device_remove_file(s, &cpu_core_attrs[i]);
+ }
+ #endif
+ 
+--- a/arch/tile/kernel/sysfs.c
++++ b/arch/tile/kernel/sysfs.c
+@@ -14,7 +14,7 @@
+  * /sys entry support.
+  */
+ 
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/cpu.h>
+ #include <linux/slab.h>
+ #include <linux/smp.h>
+@@ -32,55 +32,55 @@
+ 	return n;
+ }
+ 
+-static ssize_t chip_width_show(struct sysdev_class *dev,
+-			       struct sysdev_class_attribute *attr,
++static ssize_t chip_width_show(struct device *dev,
++			       struct device_attribute *attr,
+ 			       char *page)
+ {
+ 	return sprintf(page, "%u\n", smp_width);
+ }
+-static SYSDEV_CLASS_ATTR(chip_width, 0444, chip_width_show, NULL);
++static DEVICE_ATTR(chip_width, 0444, chip_width_show, NULL);
+ 
+-static ssize_t chip_height_show(struct sysdev_class *dev,
+-				struct sysdev_class_attribute *attr,
++static ssize_t chip_height_show(struct device *dev,
++				struct device_attribute *attr,
+ 				char *page)
+ {
+ 	return sprintf(page, "%u\n", smp_height);
+ }
+-static SYSDEV_CLASS_ATTR(chip_height, 0444, chip_height_show, NULL);
++static DEVICE_ATTR(chip_height, 0444, chip_height_show, NULL);
+ 
+-static ssize_t chip_serial_show(struct sysdev_class *dev,
+-				struct sysdev_class_attribute *attr,
++static ssize_t chip_serial_show(struct device *dev,
++				struct device_attribute *attr,
+ 				char *page)
+ {
+ 	return get_hv_confstr(page, HV_CONFSTR_CHIP_SERIAL_NUM);
+ }
+-static SYSDEV_CLASS_ATTR(chip_serial, 0444, chip_serial_show, NULL);
++static DEVICE_ATTR(chip_serial, 0444, chip_serial_show, NULL);
+ 
+-static ssize_t chip_revision_show(struct sysdev_class *dev,
+-				  struct sysdev_class_attribute *attr,
++static ssize_t chip_revision_show(struct device *dev,
++				  struct device_attribute *attr,
+ 				  char *page)
+ {
+ 	return get_hv_confstr(page, HV_CONFSTR_CHIP_REV);
+ }
+-static SYSDEV_CLASS_ATTR(chip_revision, 0444, chip_revision_show, NULL);
++static DEVICE_ATTR(chip_revision, 0444, chip_revision_show, NULL);
+ 
+ 
+-static ssize_t type_show(struct sysdev_class *dev,
+-			    struct sysdev_class_attribute *attr,
++static ssize_t type_show(struct device *dev,
++			    struct device_attribute *attr,
+ 			    char *page)
+ {
+ 	return sprintf(page, "tilera\n");
+ }
+-static SYSDEV_CLASS_ATTR(type, 0444, type_show, NULL);
++static DEVICE_ATTR(type, 0444, type_show, NULL);
+ 
+ #define HV_CONF_ATTR(name, conf)					\
+-	static ssize_t name ## _show(struct sysdev_class *dev,		\
+-				     struct sysdev_class_attribute *attr, \
++	static ssize_t name ## _show(struct device *dev,		\
++				     struct device_attribute *attr, \
+ 				     char *page)			\
+ 	{								\
+ 		return get_hv_confstr(page, conf);			\
+ 	}								\
+-	static SYSDEV_CLASS_ATTR(name, 0444, name ## _show, NULL);
++	static DEVICE_ATTR(name, 0444, name ## _show, NULL);
+ 
+ HV_CONF_ATTR(version,		HV_CONFSTR_HV_SW_VER)
+ HV_CONF_ATTR(config_version,	HV_CONFSTR_HV_CONFIG_VER)
+@@ -96,15 +96,15 @@
+ HV_CONF_ATTR(switch_control,	HV_CONFSTR_SWITCH_CONTROL)
+ 
+ static struct attribute *board_attrs[] = {
+-	&attr_board_part.attr,
+-	&attr_board_serial.attr,
+-	&attr_board_revision.attr,
+-	&attr_board_description.attr,
+-	&attr_mezz_part.attr,
+-	&attr_mezz_serial.attr,
+-	&attr_mezz_revision.attr,
+-	&attr_mezz_description.attr,
+-	&attr_switch_control.attr,
++	&dev_attr_board_part.attr,
++	&dev_attr_board_serial.attr,
++	&dev_attr_board_revision.attr,
++	&dev_attr_board_description.attr,
++	&dev_attr_mezz_part.attr,
++	&dev_attr_mezz_serial.attr,
++	&dev_attr_mezz_revision.attr,
++	&dev_attr_mezz_description.attr,
++	&dev_attr_switch_control.attr,
+ 	NULL
+ };
+ 
+@@ -151,12 +151,11 @@
+ 
+ static int __init create_sysfs_entries(void)
+ {
+-	struct sysdev_class *cls = &cpu_sysdev_class;
+ 	int err = 0;
+ 
+ #define create_cpu_attr(name)						\
+ 	if (!err)							\
+-		err = sysfs_create_file(&cls->kset.kobj, &attr_##name.attr);
++		err = device_create_file(cpu_subsys.dev_root, &dev_attr_##name);
+ 	create_cpu_attr(chip_width);
+ 	create_cpu_attr(chip_height);
+ 	create_cpu_attr(chip_serial);
+@@ -164,7 +163,7 @@
+ 
+ #define create_hv_attr(name)						\
+ 	if (!err)							\
+-		err = sysfs_create_file(hypervisor_kobj, &attr_##name.attr);
++		err = sysfs_create_file(hypervisor_kobj, &dev_attr_##name);
+ 	create_hv_attr(type);
+ 	create_hv_attr(version);
+ 	create_hv_attr(config_version);
+--- a/arch/x86/include/asm/mce.h
++++ b/arch/x86/include/asm/mce.h
+@@ -149,7 +149,7 @@
+ 
+ void mce_setup(struct mce *m);
+ void mce_log(struct mce *m);
+-DECLARE_PER_CPU(struct sys_device, mce_sysdev);
++DECLARE_PER_CPU(struct device, mce_device);
+ 
+ /*
+  * Maximum banks number.
+--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
++++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
+@@ -872,8 +872,7 @@
+ 
+ #include <linux/kobject.h>
+ #include <linux/sysfs.h>
+-
+-extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
++#include <linux/cpu.h>
+ 
+ /* pointer to kobject for cpuX/cache */
+ static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject);
+@@ -1101,9 +1100,9 @@
+ static DECLARE_BITMAP(cache_dev_map, NR_CPUS);
+ 
+ /* Add/Remove cache interface for CPU device */
+-static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
++static int __cpuinit cache_add_dev(struct device *dev)
+ {
+-	unsigned int cpu = sys_dev->id;
++	unsigned int cpu = dev->id;
+ 	unsigned long i, j;
+ 	struct _index_kobject *this_object;
+ 	struct _cpuid4_info   *this_leaf;
+@@ -1115,7 +1114,7 @@
+ 
+ 	retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu),
+ 				      &ktype_percpu_entry,
+-				      &sys_dev->kobj, "%s", "cache");
++				      &dev->kobj, "%s", "cache");
+ 	if (retval < 0) {
+ 		cpuid4_cache_sysfs_exit(cpu);
+ 		return retval;
+@@ -1152,9 +1151,9 @@
+ 	return 0;
+ }
+ 
+-static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
++static void __cpuinit cache_remove_dev(struct device *dev)
+ {
+-	unsigned int cpu = sys_dev->id;
++	unsigned int cpu = dev->id;
+ 	unsigned long i;
+ 
+ 	if (per_cpu(ici_cpuid4_info, cpu) == NULL)
+@@ -1173,17 +1172,17 @@
+ 					unsigned long action, void *hcpu)
+ {
+ 	unsigned int cpu = (unsigned long)hcpu;
+-	struct sys_device *sys_dev;
++	struct device *dev;
+ 
+-	sys_dev = get_cpu_sysdev(cpu);
++	dev = get_cpu_device(cpu);
+ 	switch (action) {
+ 	case CPU_ONLINE:
+ 	case CPU_ONLINE_FROZEN:
+-		cache_add_dev(sys_dev);
++		cache_add_dev(dev);
+ 		break;
+ 	case CPU_DEAD:
+ 	case CPU_DEAD_FROZEN:
+-		cache_remove_dev(sys_dev);
++		cache_remove_dev(dev);
+ 		break;
+ 	}
+ 	return NOTIFY_OK;
+@@ -1202,9 +1201,9 @@
+ 
+ 	for_each_online_cpu(i) {
+ 		int err;
+-		struct sys_device *sys_dev = get_cpu_sysdev(i);
++		struct device *dev = get_cpu_device(i);
+ 
+-		err = cache_add_dev(sys_dev);
++		err = cache_add_dev(dev);
+ 		if (err)
+ 			return err;
+ 	}
+--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
++++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
+@@ -1,4 +1,4 @@
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <asm/mce.h>
+ 
+ enum severity_level {
+@@ -17,7 +17,7 @@
+ struct mce_bank {
+ 	u64			ctl;			/* subevents to enable */
+ 	unsigned char init;				/* initialise bank? */
+-	struct sysdev_attribute attr;			/* sysdev attribute */
++	struct device_attribute attr;			/* device attribute */
+ 	char			attrname[ATTR_LEN];	/* attribute name */
+ };
+ 
+--- a/arch/x86/kernel/cpu/mcheck/mce.c
++++ b/arch/x86/kernel/cpu/mcheck/mce.c
+@@ -19,7 +19,7 @@
+ #include <linux/kernel.h>
+ #include <linux/percpu.h>
+ #include <linux/string.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/syscore_ops.h>
+ #include <linux/delay.h>
+ #include <linux/ctype.h>
+@@ -1778,7 +1778,7 @@
+ };
+ 
+ /*
+- * mce_sysdev: Sysfs support
++ * mce_device: Sysfs support
+  */
+ 
+ static void mce_cpu_restart(void *data)
+@@ -1814,27 +1814,28 @@
+ 		__mcheck_cpu_init_timer();
+ }
+ 
+-static struct sysdev_class mce_sysdev_class = {
++static struct bus_type mce_subsys = {
+ 	.name		= "machinecheck",
++	.dev_name	= "machinecheck",
+ };
+ 
+-DEFINE_PER_CPU(struct sys_device, mce_sysdev);
++DEFINE_PER_CPU(struct device, mce_device);
+ 
+ __cpuinitdata
+ void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
+ 
+-static inline struct mce_bank *attr_to_bank(struct sysdev_attribute *attr)
++static inline struct mce_bank *attr_to_bank(struct device_attribute *attr)
+ {
+ 	return container_of(attr, struct mce_bank, attr);
+ }
+ 
+-static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr,
++static ssize_t show_bank(struct device *s, struct device_attribute *attr,
+ 			 char *buf)
+ {
+ 	return sprintf(buf, "%llx\n", attr_to_bank(attr)->ctl);
+ }
+ 
+-static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
++static ssize_t set_bank(struct device *s, struct device_attribute *attr,
+ 			const char *buf, size_t size)
+ {
+ 	u64 new;
+@@ -1849,14 +1850,14 @@
+ }
+ 
+ static ssize_t
+-show_trigger(struct sys_device *s, struct sysdev_attribute *attr, char *buf)
++show_trigger(struct device *s, struct device_attribute *attr, char *buf)
+ {
+ 	strcpy(buf, mce_helper);
+ 	strcat(buf, "\n");
+ 	return strlen(mce_helper) + 1;
+ }
+ 
+-static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
++static ssize_t set_trigger(struct device *s, struct device_attribute *attr,
+ 				const char *buf, size_t siz)
+ {
+ 	char *p;
+@@ -1871,8 +1872,8 @@
+ 	return strlen(mce_helper) + !!p;
+ }
+ 
+-static ssize_t set_ignore_ce(struct sys_device *s,
+-			     struct sysdev_attribute *attr,
++static ssize_t set_ignore_ce(struct device *s,
++			     struct device_attribute *attr,
+ 			     const char *buf, size_t size)
+ {
+ 	u64 new;
+@@ -1895,8 +1896,8 @@
+ 	return size;
+ }
+ 
+-static ssize_t set_cmci_disabled(struct sys_device *s,
+-				 struct sysdev_attribute *attr,
++static ssize_t set_cmci_disabled(struct device *s,
++				 struct device_attribute *attr,
+ 				 const char *buf, size_t size)
+ {
+ 	u64 new;
+@@ -1918,108 +1919,107 @@
+ 	return size;
+ }
+ 
+-static ssize_t store_int_with_restart(struct sys_device *s,
+-				      struct sysdev_attribute *attr,
++static ssize_t store_int_with_restart(struct device *s,
++				      struct device_attribute *attr,
+ 				      const char *buf, size_t size)
+ {
+-	ssize_t ret = sysdev_store_int(s, attr, buf, size);
++	ssize_t ret = device_store_int(s, attr, buf, size);
+ 	mce_restart();
+ 	return ret;
+ }
+ 
+-static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
+-static SYSDEV_INT_ATTR(tolerant, 0644, tolerant);
+-static SYSDEV_INT_ATTR(monarch_timeout, 0644, monarch_timeout);
+-static SYSDEV_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce);
+-
+-static struct sysdev_ext_attribute attr_check_interval = {
+-	_SYSDEV_ATTR(check_interval, 0644, sysdev_show_int,
+-		     store_int_with_restart),
++static DEVICE_ATTR(trigger, 0644, show_trigger, set_trigger);
++static DEVICE_INT_ATTR(tolerant, 0644, tolerant);
++static DEVICE_INT_ATTR(monarch_timeout, 0644, monarch_timeout);
++static DEVICE_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce);
++
++static struct dev_ext_attribute dev_attr_check_interval = {
++	__ATTR(check_interval, 0644, device_show_int, store_int_with_restart),
+ 	&check_interval
+ };
+ 
+-static struct sysdev_ext_attribute attr_ignore_ce = {
+-	_SYSDEV_ATTR(ignore_ce, 0644, sysdev_show_int, set_ignore_ce),
++static struct dev_ext_attribute dev_attr_ignore_ce = {
++	__ATTR(ignore_ce, 0644, device_show_int, set_ignore_ce),
+ 	&mce_ignore_ce
+ };
+ 
+-static struct sysdev_ext_attribute attr_cmci_disabled = {
+-	_SYSDEV_ATTR(cmci_disabled, 0644, sysdev_show_int, set_cmci_disabled),
++static struct dev_ext_attribute dev_attr_cmci_disabled = {
++	__ATTR(cmci_disabled, 0644, device_show_int, set_cmci_disabled),
+ 	&mce_cmci_disabled
+ };
+ 
+-static struct sysdev_attribute *mce_sysdev_attrs[] = {
+-	&attr_tolerant.attr,
+-	&attr_check_interval.attr,
+-	&attr_trigger,
+-	&attr_monarch_timeout.attr,
+-	&attr_dont_log_ce.attr,
+-	&attr_ignore_ce.attr,
+-	&attr_cmci_disabled.attr,
++static struct device_attribute *mce_device_attrs[] = {
++	&dev_attr_tolerant.attr,
++	&dev_attr_check_interval.attr,
++	&dev_attr_trigger,
++	&dev_attr_monarch_timeout.attr,
++	&dev_attr_dont_log_ce.attr,
++	&dev_attr_ignore_ce.attr,
++	&dev_attr_cmci_disabled.attr,
+ 	NULL
+ };
+ 
+-static cpumask_var_t mce_sysdev_initialized;
++static cpumask_var_t mce_device_initialized;
+ 
+-/* Per cpu sysdev init. All of the cpus still share the same ctrl bank: */
+-static __cpuinit int mce_sysdev_create(unsigned int cpu)
++/* Per cpu device init. All of the cpus still share the same ctrl bank: */
++static __cpuinit int mce_device_create(unsigned int cpu)
+ {
+-	struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu);
++	struct device *dev = &per_cpu(mce_device, cpu);
+ 	int err;
+ 	int i, j;
+ 
+ 	if (!mce_available(&boot_cpu_data))
+ 		return -EIO;
+ 
+-	memset(&sysdev->kobj, 0, sizeof(struct kobject));
+-	sysdev->id  = cpu;
+-	sysdev->cls = &mce_sysdev_class;
++	memset(&dev->kobj, 0, sizeof(struct kobject));
++	dev->id  = cpu;
++	dev->bus = &mce_subsys;
+ 
+-	err = sysdev_register(sysdev);
++	err = device_register(dev);
+ 	if (err)
+ 		return err;
+ 
+-	for (i = 0; mce_sysdev_attrs[i]; i++) {
+-		err = sysdev_create_file(sysdev, mce_sysdev_attrs[i]);
++	for (i = 0; mce_device_attrs[i]; i++) {
++		err = device_create_file(dev, mce_device_attrs[i]);
+ 		if (err)
+ 			goto error;
+ 	}
+ 	for (j = 0; j < banks; j++) {
+-		err = sysdev_create_file(sysdev, &mce_banks[j].attr);
++		err = device_create_file(dev, &mce_banks[j].attr);
+ 		if (err)
+ 			goto error2;
+ 	}
+-	cpumask_set_cpu(cpu, mce_sysdev_initialized);
++	cpumask_set_cpu(cpu, mce_device_initialized);
+ 
+ 	return 0;
+ error2:
+ 	while (--j >= 0)
+-		sysdev_remove_file(sysdev, &mce_banks[j].attr);
++		device_remove_file(dev, &mce_banks[j].attr);
+ error:
+ 	while (--i >= 0)
+-		sysdev_remove_file(sysdev, mce_sysdev_attrs[i]);
++		device_remove_file(dev, mce_device_attrs[i]);
+ 
+-	sysdev_unregister(sysdev);
++	device_unregister(dev);
+ 
+ 	return err;
+ }
+ 
+-static __cpuinit void mce_sysdev_remove(unsigned int cpu)
++static __cpuinit void mce_device_remove(unsigned int cpu)
+ {
+-	struct sys_device *sysdev = &per_cpu(mce_sysdev, cpu);
++	struct device *dev = &per_cpu(mce_device, cpu);
+ 	int i;
+ 
+-	if (!cpumask_test_cpu(cpu, mce_sysdev_initialized))
++	if (!cpumask_test_cpu(cpu, mce_device_initialized))
+ 		return;
+ 
+-	for (i = 0; mce_sysdev_attrs[i]; i++)
+-		sysdev_remove_file(sysdev, mce_sysdev_attrs[i]);
++	for (i = 0; mce_device_attrs[i]; i++)
++		device_remove_file(dev, mce_device_attrs[i]);
+ 
+ 	for (i = 0; i < banks; i++)
+-		sysdev_remove_file(sysdev, &mce_banks[i].attr);
++		device_remove_file(dev, &mce_banks[i].attr);
+ 
+-	sysdev_unregister(sysdev);
+-	cpumask_clear_cpu(cpu, mce_sysdev_initialized);
++	device_unregister(dev);
++	cpumask_clear_cpu(cpu, mce_device_initialized);
+ }
+ 
+ /* Make sure there are no machine checks on offlined CPUs. */
+@@ -2069,7 +2069,7 @@
+ 	switch (action) {
+ 	case CPU_ONLINE:
+ 	case CPU_ONLINE_FROZEN:
+-		mce_sysdev_create(cpu);
++		mce_device_create(cpu);
+ 		if (threshold_cpu_callback)
+ 			threshold_cpu_callback(action, cpu);
+ 		break;
+@@ -2077,7 +2077,7 @@
+ 	case CPU_DEAD_FROZEN:
+ 		if (threshold_cpu_callback)
+ 			threshold_cpu_callback(action, cpu);
+-		mce_sysdev_remove(cpu);
++		mce_device_remove(cpu);
+ 		break;
+ 	case CPU_DOWN_PREPARE:
+ 	case CPU_DOWN_PREPARE_FROZEN:
+@@ -2111,7 +2111,7 @@
+ 
+ 	for (i = 0; i < banks; i++) {
+ 		struct mce_bank *b = &mce_banks[i];
+-		struct sysdev_attribute *a = &b->attr;
++		struct device_attribute *a = &b->attr;
+ 
+ 		sysfs_attr_init(&a->attr);
+ 		a->attr.name	= b->attrname;
+@@ -2131,16 +2131,16 @@
+ 	if (!mce_available(&boot_cpu_data))
+ 		return -EIO;
+ 
+-	zalloc_cpumask_var(&mce_sysdev_initialized, GFP_KERNEL);
++	zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL);
+ 
+ 	mce_init_banks();
+ 
+-	err = sysdev_class_register(&mce_sysdev_class);
++	err = subsys_system_register(&mce_subsys, NULL);
+ 	if (err)
+ 		return err;
+ 
+ 	for_each_online_cpu(i) {
+-		err = mce_sysdev_create(i);
++		err = mce_device_create(i);
+ 		if (err)
+ 			return err;
+ 	}
+--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
+@@ -17,7 +17,6 @@
+ #include <linux/notifier.h>
+ #include <linux/kobject.h>
+ #include <linux/percpu.h>
+-#include <linux/sysdev.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/sysfs.h>
+@@ -548,7 +547,7 @@
+ 		if (!b)
+ 			goto out;
+ 
+-		err = sysfs_create_link(&per_cpu(mce_sysdev, cpu).kobj,
++		err = sysfs_create_link(&per_cpu(mce_device, cpu).kobj,
+ 					b->kobj, name);
+ 		if (err)
+ 			goto out;
+@@ -571,7 +570,7 @@
+ 		goto out;
+ 	}
+ 
+-	b->kobj = kobject_create_and_add(name, &per_cpu(mce_sysdev, cpu).kobj);
++	b->kobj = kobject_create_and_add(name, &per_cpu(mce_device, cpu).kobj);
+ 	if (!b->kobj)
+ 		goto out_free;
+ 
+@@ -591,7 +590,7 @@
+ 		if (i == cpu)
+ 			continue;
+ 
+-		err = sysfs_create_link(&per_cpu(mce_sysdev, i).kobj,
++		err = sysfs_create_link(&per_cpu(mce_device, i).kobj,
+ 					b->kobj, name);
+ 		if (err)
+ 			goto out;
+@@ -669,7 +668,7 @@
+ #ifdef CONFIG_SMP
+ 	/* sibling symlink */
+ 	if (shared_bank[bank] && b->blocks->cpu != cpu) {
+-		sysfs_remove_link(&per_cpu(mce_sysdev, cpu).kobj, name);
++		sysfs_remove_link(&per_cpu(mce_device, cpu).kobj, name);
+ 		per_cpu(threshold_banks, cpu)[bank] = NULL;
+ 
+ 		return;
+@@ -681,7 +680,7 @@
+ 		if (i == cpu)
+ 			continue;
+ 
+-		sysfs_remove_link(&per_cpu(mce_sysdev, i).kobj, name);
++		sysfs_remove_link(&per_cpu(mce_device, i).kobj, name);
+ 		per_cpu(threshold_banks, i)[bank] = NULL;
+ 	}
+ 
+--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
++++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
+@@ -19,7 +19,6 @@
+ #include <linux/kernel.h>
+ #include <linux/percpu.h>
+ #include <linux/export.h>
+-#include <linux/sysdev.h>
+ #include <linux/types.h>
+ #include <linux/init.h>
+ #include <linux/smp.h>
+@@ -69,16 +68,16 @@
+ static u32 lvtthmr_init __read_mostly;
+ 
+ #ifdef CONFIG_SYSFS
+-#define define_therm_throt_sysdev_one_ro(_name)				\
+-	static SYSDEV_ATTR(_name, 0444,					\
+-			   therm_throt_sysdev_show_##_name,		\
++#define define_therm_throt_device_one_ro(_name)				\
++	static DEVICE_ATTR(_name, 0444,					\
++			   therm_throt_device_show_##_name,		\
+ 				   NULL)				\
+ 
+-#define define_therm_throt_sysdev_show_func(event, name)		\
++#define define_therm_throt_device_show_func(event, name)		\
+ 									\
+-static ssize_t therm_throt_sysdev_show_##event##_##name(		\
+-			struct sys_device *dev,				\
+-			struct sysdev_attribute *attr,			\
++static ssize_t therm_throt_device_show_##event##_##name(		\
++			struct device *dev,				\
++			struct device_attribute *attr,			\
+ 			char *buf)					\
+ {									\
+ 	unsigned int cpu = dev->id;					\
+@@ -95,20 +94,20 @@
+ 	return ret;							\
+ }
+ 
+-define_therm_throt_sysdev_show_func(core_throttle, count);
+-define_therm_throt_sysdev_one_ro(core_throttle_count);
++define_therm_throt_device_show_func(core_throttle, count);
++define_therm_throt_device_one_ro(core_throttle_count);
+ 
+-define_therm_throt_sysdev_show_func(core_power_limit, count);
+-define_therm_throt_sysdev_one_ro(core_power_limit_count);
++define_therm_throt_device_show_func(core_power_limit, count);
++define_therm_throt_device_one_ro(core_power_limit_count);
+ 
+-define_therm_throt_sysdev_show_func(package_throttle, count);
+-define_therm_throt_sysdev_one_ro(package_throttle_count);
++define_therm_throt_device_show_func(package_throttle, count);
++define_therm_throt_device_one_ro(package_throttle_count);
+ 
+-define_therm_throt_sysdev_show_func(package_power_limit, count);
+-define_therm_throt_sysdev_one_ro(package_power_limit_count);
++define_therm_throt_device_show_func(package_power_limit, count);
++define_therm_throt_device_one_ro(package_power_limit_count);
+ 
+ static struct attribute *thermal_throttle_attrs[] = {
+-	&attr_core_throttle_count.attr,
++	&dev_attr_core_throttle_count.attr,
+ 	NULL
+ };
+ 
+@@ -223,36 +222,36 @@
+ 
+ #ifdef CONFIG_SYSFS
+ /* Add/Remove thermal_throttle interface for CPU device: */
+-static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev,
++static __cpuinit int thermal_throttle_add_dev(struct device *dev,
+ 				unsigned int cpu)
+ {
+ 	int err;
+ 	struct cpuinfo_x86 *c = &cpu_data(cpu);
+ 
+-	err = sysfs_create_group(&sys_dev->kobj, &thermal_attr_group);
++	err = sysfs_create_group(&dev->kobj, &thermal_attr_group);
+ 	if (err)
+ 		return err;
+ 
+ 	if (cpu_has(c, X86_FEATURE_PLN))
+-		err = sysfs_add_file_to_group(&sys_dev->kobj,
+-					      &attr_core_power_limit_count.attr,
++		err = sysfs_add_file_to_group(&dev->kobj,
++					      &dev_attr_core_power_limit_count.attr,
+ 					      thermal_attr_group.name);
+ 	if (cpu_has(c, X86_FEATURE_PTS)) {
+-		err = sysfs_add_file_to_group(&sys_dev->kobj,
+-					      &attr_package_throttle_count.attr,
++		err = sysfs_add_file_to_group(&dev->kobj,
++					      &dev_attr_package_throttle_count.attr,
+ 					      thermal_attr_group.name);
+ 		if (cpu_has(c, X86_FEATURE_PLN))
+-			err = sysfs_add_file_to_group(&sys_dev->kobj,
+-					&attr_package_power_limit_count.attr,
++			err = sysfs_add_file_to_group(&dev->kobj,
++					&dev_attr_package_power_limit_count.attr,
+ 					thermal_attr_group.name);
+ 	}
+ 
+ 	return err;
+ }
+ 
+-static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
++static __cpuinit void thermal_throttle_remove_dev(struct device *dev)
+ {
+-	sysfs_remove_group(&sys_dev->kobj, &thermal_attr_group);
++	sysfs_remove_group(&dev->kobj, &thermal_attr_group);
+ }
+ 
+ /* Mutex protecting device creation against CPU hotplug: */
+@@ -265,16 +264,16 @@
+ 			      void *hcpu)
+ {
+ 	unsigned int cpu = (unsigned long)hcpu;
+-	struct sys_device *sys_dev;
++	struct device *dev;
+ 	int err = 0;
+ 
+-	sys_dev = get_cpu_sysdev(cpu);
++	dev = get_cpu_device(cpu);
+ 
+ 	switch (action) {
+ 	case CPU_UP_PREPARE:
+ 	case CPU_UP_PREPARE_FROZEN:
+ 		mutex_lock(&therm_cpu_lock);
+-		err = thermal_throttle_add_dev(sys_dev, cpu);
++		err = thermal_throttle_add_dev(dev, cpu);
+ 		mutex_unlock(&therm_cpu_lock);
+ 		WARN_ON(err);
+ 		break;
+@@ -283,7 +282,7 @@
+ 	case CPU_DEAD:
+ 	case CPU_DEAD_FROZEN:
+ 		mutex_lock(&therm_cpu_lock);
+-		thermal_throttle_remove_dev(sys_dev);
++		thermal_throttle_remove_dev(dev);
+ 		mutex_unlock(&therm_cpu_lock);
+ 		break;
+ 	}
+@@ -310,7 +309,7 @@
+ #endif
+ 	/* connect live CPUs to sysfs */
+ 	for_each_online_cpu(cpu) {
+-		err = thermal_throttle_add_dev(get_cpu_sysdev(cpu), cpu);
++		err = thermal_throttle_add_dev(get_cpu_device(cpu), cpu);
+ 		WARN_ON(err);
+ 	}
+ #ifdef CONFIG_HOTPLUG_CPU
+--- a/arch/x86/kernel/microcode_core.c
++++ b/arch/x86/kernel/microcode_core.c
+@@ -292,8 +292,8 @@
+ 	return err;
+ }
+ 
+-static ssize_t reload_store(struct sys_device *dev,
+-			    struct sysdev_attribute *attr,
++static ssize_t reload_store(struct device *dev,
++			    struct device_attribute *attr,
+ 			    const char *buf, size_t size)
+ {
+ 	unsigned long val;
+@@ -318,30 +318,30 @@
+ 	return ret;
+ }
+ 
+-static ssize_t version_show(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t version_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+ 	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+ 
+ 	return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
+ }
+ 
+-static ssize_t pf_show(struct sys_device *dev,
+-			struct sysdev_attribute *attr, char *buf)
++static ssize_t pf_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+ 	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+ 
+ 	return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
+ }
+ 
+-static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
+-static SYSDEV_ATTR(version, 0400, version_show, NULL);
+-static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
++static DEVICE_ATTR(reload, 0200, NULL, reload_store);
++static DEVICE_ATTR(version, 0400, version_show, NULL);
++static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL);
+ 
+ static struct attribute *mc_default_attrs[] = {
+-	&attr_reload.attr,
+-	&attr_version.attr,
+-	&attr_processor_flags.attr,
++	&dev_attr_reload.attr,
++	&dev_attr_version.attr,
++	&dev_attr_processor_flags.attr,
+ 	NULL
+ };
+ 
+@@ -405,16 +405,16 @@
+ 	return ustate;
+ }
+ 
+-static int mc_sysdev_add(struct sys_device *sys_dev)
++static int mc_device_add(struct device *dev, struct subsys_interface *sif)
+ {
+-	int err, cpu = sys_dev->id;
++	int err, cpu = dev->id;
+ 
+ 	if (!cpu_online(cpu))
+ 		return 0;
+ 
+ 	pr_debug("CPU%d added\n", cpu);
+ 
+-	err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
++	err = sysfs_create_group(&dev->kobj, &mc_attr_group);
+ 	if (err)
+ 		return err;
+ 
+@@ -424,22 +424,24 @@
+ 	return err;
+ }
+ 
+-static int mc_sysdev_remove(struct sys_device *sys_dev)
++static int mc_device_remove(struct device *dev, struct subsys_interface *sif)
+ {
+-	int cpu = sys_dev->id;
++	int cpu = dev->id;
+ 
+ 	if (!cpu_online(cpu))
+ 		return 0;
+ 
+ 	pr_debug("CPU%d removed\n", cpu);
+ 	microcode_fini_cpu(cpu);
+-	sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
++	sysfs_remove_group(&dev->kobj, &mc_attr_group);
+ 	return 0;
+ }
+ 
+-static struct sysdev_driver mc_sysdev_driver = {
+-	.add			= mc_sysdev_add,
+-	.remove			= mc_sysdev_remove,
++static struct subsys_interface mc_cpu_interface = {
++	.name			= "microcode",
++	.subsys			= &cpu_subsys,
++	.add_dev		= mc_device_add,
++	.remove_dev		= mc_device_remove,
+ };
+ 
+ /**
+@@ -462,9 +464,9 @@
+ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+ {
+ 	unsigned int cpu = (unsigned long)hcpu;
+-	struct sys_device *sys_dev;
++	struct device *dev;
+ 
+-	sys_dev = get_cpu_sysdev(cpu);
++	dev = get_cpu_device(cpu);
+ 	switch (action) {
+ 	case CPU_ONLINE:
+ 	case CPU_ONLINE_FROZEN:
+@@ -472,13 +474,13 @@
+ 	case CPU_DOWN_FAILED:
+ 	case CPU_DOWN_FAILED_FROZEN:
+ 		pr_debug("CPU%d added\n", cpu);
+-		if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
++		if (sysfs_create_group(&dev->kobj, &mc_attr_group))
+ 			pr_err("Failed to create group for CPU%d\n", cpu);
+ 		break;
+ 	case CPU_DOWN_PREPARE:
+ 	case CPU_DOWN_PREPARE_FROZEN:
+ 		/* Suspend is in progress, only remove the interface */
+-		sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
++		sysfs_remove_group(&dev->kobj, &mc_attr_group);
+ 		pr_debug("CPU%d removed\n", cpu);
+ 		break;
+ 
+@@ -523,7 +525,7 @@
+ 	get_online_cpus();
+ 	mutex_lock(&microcode_mutex);
+ 
+-	error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
++	error = subsys_interface_register(&mc_cpu_interface);
+ 
+ 	mutex_unlock(&microcode_mutex);
+ 	put_online_cpus();
+@@ -533,7 +535,7 @@
+ 
+ 	error = microcode_dev_init();
+ 	if (error)
+-		goto out_sysdev_driver;
++		goto out_driver;
+ 
+ 	register_syscore_ops(&mc_syscore_ops);
+ 	register_hotcpu_notifier(&mc_cpu_notifier);
+@@ -543,11 +545,11 @@
+ 
+ 	return 0;
+ 
+-out_sysdev_driver:
++out_driver:
+ 	get_online_cpus();
+ 	mutex_lock(&microcode_mutex);
+ 
+-	sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
++	subsys_interface_unregister(&mc_cpu_interface);
+ 
+ 	mutex_unlock(&microcode_mutex);
+ 	put_online_cpus();
+@@ -569,7 +571,7 @@
+ 	get_online_cpus();
+ 	mutex_lock(&microcode_mutex);
+ 
+-	sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
++	subsys_interface_unregister(&mc_cpu_interface);
+ 
+ 	mutex_unlock(&microcode_mutex);
+ 	put_online_cpus();
+--- a/drivers/acpi/processor_driver.c
++++ b/drivers/acpi/processor_driver.c
+@@ -446,7 +446,7 @@
+ {
+ 	struct acpi_processor *pr = NULL;
+ 	int result = 0;
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 
+ 	pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+ 	if (!pr)
+@@ -491,8 +491,8 @@
+ 
+ 	per_cpu(processors, pr->id) = pr;
+ 
+-	sysdev = get_cpu_sysdev(pr->id);
+-	if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
++	dev = get_cpu_device(pr->id);
++	if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) {
+ 		result = -EFAULT;
+ 		goto err_free_cpumask;
+ 	}
+--- a/drivers/acpi/processor_thermal.c
++++ b/drivers/acpi/processor_thermal.c
+@@ -30,7 +30,6 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/cpufreq.h>
+-#include <linux/sysdev.h>
+ 
+ #include <asm/uaccess.h>
+ 
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -1,8 +1,7 @@
+ /*
+- * drivers/base/cpu.c - basic CPU class support
++ * CPU subsystem support
+  */
+ 
+-#include <linux/sysdev.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
+@@ -14,40 +13,40 @@
+ 
+ #include "base.h"
+ 
+-static struct sysdev_class_attribute *cpu_sysdev_class_attrs[];
+-
+-struct sysdev_class cpu_sysdev_class = {
++struct bus_type cpu_subsys = {
+ 	.name = "cpu",
+-	.attrs = cpu_sysdev_class_attrs,
++	.dev_name = "cpu",
+ };
+-EXPORT_SYMBOL(cpu_sysdev_class);
++EXPORT_SYMBOL_GPL(cpu_subsys);
+ 
+-static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices);
++static DEFINE_PER_CPU(struct device *, cpu_sys_devices);
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr,
++static ssize_t show_online(struct device *dev,
++			   struct device_attribute *attr,
+ 			   char *buf)
+ {
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
++	struct cpu *cpu = container_of(dev, struct cpu, dev);
+ 
+-	return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
++	return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id));
+ }
+ 
+-static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr,
+-				 const char *buf, size_t count)
++static ssize_t __ref store_online(struct device *dev,
++				  struct device_attribute *attr,
++				  const char *buf, size_t count)
+ {
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
++	struct cpu *cpu = container_of(dev, struct cpu, dev);
+ 	ssize_t ret;
+ 
+ 	cpu_hotplug_driver_lock();
+ 	switch (buf[0]) {
+ 	case '0':
+-		ret = cpu_down(cpu->sysdev.id);
++		ret = cpu_down(cpu->dev.id);
+ 		if (!ret)
+ 			kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
+ 		break;
+ 	case '1':
+-		ret = cpu_up(cpu->sysdev.id);
++		ret = cpu_up(cpu->dev.id);
+ 		if (!ret)
+ 			kobject_uevent(&dev->kobj, KOBJ_ONLINE);
+ 		break;
+@@ -60,44 +59,44 @@
+ 		ret = count;
+ 	return ret;
+ }
+-static SYSDEV_ATTR(online, 0644, show_online, store_online);
++static DEVICE_ATTR(online, 0644, show_online, store_online);
+ 
+ static void __cpuinit register_cpu_control(struct cpu *cpu)
+ {
+-	sysdev_create_file(&cpu->sysdev, &attr_online);
++	device_create_file(&cpu->dev, &dev_attr_online);
+ }
+ void unregister_cpu(struct cpu *cpu)
+ {
+-	int logical_cpu = cpu->sysdev.id;
++	int logical_cpu = cpu->dev.id;
+ 
+ 	unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
+ 
+-	sysdev_remove_file(&cpu->sysdev, &attr_online);
++	device_remove_file(&cpu->dev, &dev_attr_online);
+ 
+-	sysdev_unregister(&cpu->sysdev);
++	device_unregister(&cpu->dev);
+ 	per_cpu(cpu_sys_devices, logical_cpu) = NULL;
+ 	return;
+ }
+ 
+ #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+-static ssize_t cpu_probe_store(struct sysdev_class *class,
+-			       struct sysdev_class_attribute *attr,
++static ssize_t cpu_probe_store(struct device *dev,
++			       struct device_attribute *attr,
+ 			       const char *buf,
+ 			       size_t count)
+ {
+ 	return arch_cpu_probe(buf, count);
+ }
+ 
+-static ssize_t cpu_release_store(struct sysdev_class *class,
+-				 struct sysdev_class_attribute *attr,
++static ssize_t cpu_release_store(struct device *dev,
++				 struct device_attribute *attr,
+ 				 const char *buf,
+ 				 size_t count)
+ {
+ 	return arch_cpu_release(buf, count);
+ }
+ 
+-static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
+-static SYSDEV_CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store);
++static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
++static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
+ #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
+ 
+ #else /* ... !CONFIG_HOTPLUG_CPU */
+@@ -109,15 +108,15 @@
+ #ifdef CONFIG_KEXEC
+ #include <linux/kexec.h>
+ 
+-static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
++static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr,
+ 				char *buf)
+ {
+-	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
++	struct cpu *cpu = container_of(dev, struct cpu, dev);
+ 	ssize_t rc;
+ 	unsigned long long addr;
+ 	int cpunum;
+ 
+-	cpunum = cpu->sysdev.id;
++	cpunum = cpu->dev.id;
+ 
+ 	/*
+ 	 * Might be reading other cpu's data based on which cpu read thread
+@@ -129,7 +128,7 @@
+ 	rc = sprintf(buf, "%Lx\n", addr);
+ 	return rc;
+ }
+-static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
++static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+ #endif
+ 
+ /*
+@@ -137,12 +136,12 @@
+  */
+ 
+ struct cpu_attr {
+-	struct sysdev_class_attribute attr;
++	struct device_attribute attr;
+ 	const struct cpumask *const * const map;
+ };
+ 
+-static ssize_t show_cpus_attr(struct sysdev_class *class,
+-			      struct sysdev_class_attribute *attr,
++static ssize_t show_cpus_attr(struct device *dev,
++			      struct device_attribute *attr,
+ 			      char *buf)
+ {
+ 	struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
+@@ -153,10 +152,10 @@
+ 	return n;
+ }
+ 
+-#define _CPU_ATTR(name, map)						\
+-	{ _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map }
++#define _CPU_ATTR(name, map) \
++	{ __ATTR(name, 0444, show_cpus_attr, NULL), map }
+ 
+-/* Keep in sync with cpu_sysdev_class_attrs */
++/* Keep in sync with cpu_subsys_attrs */
+ static struct cpu_attr cpu_attrs[] = {
+ 	_CPU_ATTR(online, &cpu_online_mask),
+ 	_CPU_ATTR(possible, &cpu_possible_mask),
+@@ -166,19 +165,19 @@
+ /*
+  * Print values for NR_CPUS and offlined cpus
+  */
+-static ssize_t print_cpus_kernel_max(struct sysdev_class *class,
+-				     struct sysdev_class_attribute *attr, char *buf)
++static ssize_t print_cpus_kernel_max(struct device *dev,
++				     struct device_attribute *attr, char *buf)
+ {
+ 	int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
+ 	return n;
+ }
+-static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
++static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
+ 
+ /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
+ unsigned int total_cpus;
+ 
+-static ssize_t print_cpus_offline(struct sysdev_class *class,
+-				  struct sysdev_class_attribute *attr, char *buf)
++static ssize_t print_cpus_offline(struct device *dev,
++				  struct device_attribute *attr, char *buf)
+ {
+ 	int n = 0, len = PAGE_SIZE-2;
+ 	cpumask_var_t offline;
+@@ -205,7 +204,7 @@
+ 	n += snprintf(&buf[n], len - n, "\n");
+ 	return n;
+ }
+-static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
++static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
+ 
+ /*
+  * register_cpu - Setup a sysfs device for a CPU.
+@@ -218,57 +217,66 @@
+ int __cpuinit register_cpu(struct cpu *cpu, int num)
+ {
+ 	int error;
+-	cpu->node_id = cpu_to_node(num);
+-	cpu->sysdev.id = num;
+-	cpu->sysdev.cls = &cpu_sysdev_class;
+-
+-	error = sysdev_register(&cpu->sysdev);
+ 
++	cpu->node_id = cpu_to_node(num);
++	cpu->dev.id = num;
++	cpu->dev.bus = &cpu_subsys;
++	error = device_register(&cpu->dev);
+ 	if (!error && cpu->hotpluggable)
+ 		register_cpu_control(cpu);
+ 	if (!error)
+-		per_cpu(cpu_sys_devices, num) = &cpu->sysdev;
++		per_cpu(cpu_sys_devices, num) = &cpu->dev;
+ 	if (!error)
+ 		register_cpu_under_node(num, cpu_to_node(num));
+ 
+ #ifdef CONFIG_KEXEC
+ 	if (!error)
+-		error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
++		error = device_create_file(&cpu->dev, &dev_attr_crash_notes);
+ #endif
+ 	return error;
+ }
+ 
+-struct sys_device *get_cpu_sysdev(unsigned cpu)
++struct device *get_cpu_device(unsigned cpu)
+ {
+ 	if (cpu < nr_cpu_ids && cpu_possible(cpu))
+ 		return per_cpu(cpu_sys_devices, cpu);
+ 	else
+ 		return NULL;
+ }
+-EXPORT_SYMBOL_GPL(get_cpu_sysdev);
++EXPORT_SYMBOL_GPL(get_cpu_device);
++
++static struct attribute *cpu_root_attrs[] = {
++#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
++	&dev_attr_probe.attr,
++	&dev_attr_release.attr,
++#endif
++	&cpu_attrs[0].attr.attr,
++	&cpu_attrs[1].attr.attr,
++	&cpu_attrs[2].attr.attr,
++	&dev_attr_kernel_max.attr,
++	&dev_attr_offline.attr,
++	NULL
++};
++
++static struct attribute_group cpu_root_attr_group = {
++	.attrs = cpu_root_attrs,
++};
++
++static const struct attribute_group *cpu_root_attr_groups[] = {
++	&cpu_root_attr_group,
++	NULL,
++};
+ 
+ int __init cpu_dev_init(void)
+ {
+ 	int err;
+ 
+-	err = sysdev_class_register(&cpu_sysdev_class);
++	err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups);
++	if (err)
++		return err;
++
+ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+-	if (!err)
+-		err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
++	err = sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
+ #endif
+-
+ 	return err;
+ }
+-
+-static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = {
+-#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+-	&attr_probe,
+-	&attr_release,
+-#endif
+-	&cpu_attrs[0].attr,
+-	&cpu_attrs[1].attr,
+-	&cpu_attrs[2].attr,
+-	&attr_kernel_max,
+-	&attr_offline,
+-	NULL
+-};
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -317,12 +317,12 @@
+ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
+ {
+ 	int ret;
+-	struct sys_device *obj;
++	struct device *obj;
+ 
+ 	if (!node_online(nid))
+ 		return 0;
+ 
+-	obj = get_cpu_sysdev(cpu);
++	obj = get_cpu_device(cpu);
+ 	if (!obj)
+ 		return 0;
+ 
+@@ -339,12 +339,12 @@
+ 
+ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
+ {
+-	struct sys_device *obj;
++	struct device *obj;
+ 
+ 	if (!node_online(nid))
+ 		return 0;
+ 
+-	obj = get_cpu_sysdev(cpu);
++	obj = get_cpu_device(cpu);
+ 	if (!obj)
+ 		return 0;
+ 
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -23,7 +23,6 @@
+  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
+  */
+-#include <linux/sysdev.h>
+ #include <linux/init.h>
+ #include <linux/mm.h>
+ #include <linux/cpu.h>
+@@ -32,14 +31,14 @@
+ #include <linux/topology.h>
+ 
+ #define define_one_ro_named(_name, _func)				\
+-static SYSDEV_ATTR(_name, 0444, _func, NULL)
++	static DEVICE_ATTR(_name, 0444, _func, NULL)
+ 
+ #define define_one_ro(_name)				\
+-static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
++	static DEVICE_ATTR(_name, 0444, show_##_name, NULL)
+ 
+ #define define_id_show_func(name)				\
+-static ssize_t show_##name(struct sys_device *dev,		\
+-		struct sysdev_attribute *attr, char *buf)	\
++static ssize_t show_##name(struct device *dev,			\
++		struct device_attribute *attr, char *buf)	\
+ {								\
+ 	unsigned int cpu = dev->id;				\
+ 	return sprintf(buf, "%d\n", topology_##name(cpu));	\
+@@ -65,16 +64,16 @@
+ 
+ #ifdef arch_provides_topology_pointers
+ #define define_siblings_show_map(name)					\
+-static ssize_t show_##name(struct sys_device *dev,			\
+-			   struct sysdev_attribute *attr, char *buf)	\
++static ssize_t show_##name(struct device *dev,				\
++			   struct device_attribute *attr, char *buf)	\
+ {									\
+ 	unsigned int cpu = dev->id;					\
+ 	return show_cpumap(0, topology_##name(cpu), buf);		\
+ }
+ 
+ #define define_siblings_show_list(name)					\
+-static ssize_t show_##name##_list(struct sys_device *dev,		\
+-				  struct sysdev_attribute *attr,	\
++static ssize_t show_##name##_list(struct device *dev,			\
++				  struct device_attribute *attr,	\
+ 				  char *buf)				\
+ {									\
+ 	unsigned int cpu = dev->id;					\
+@@ -83,15 +82,15 @@
+ 
+ #else
+ #define define_siblings_show_map(name)					\
+-static ssize_t show_##name(struct sys_device *dev,			\
+-			   struct sysdev_attribute *attr, char *buf)	\
++static ssize_t show_##name(struct device *dev,				\
++			   struct device_attribute *attr, char *buf)	\
+ {									\
+ 	return show_cpumap(0, topology_##name(dev->id), buf);		\
+ }
+ 
+ #define define_siblings_show_list(name)					\
+-static ssize_t show_##name##_list(struct sys_device *dev,		\
+-				  struct sysdev_attribute *attr,	\
++static ssize_t show_##name##_list(struct device *dev,			\
++				  struct device_attribute *attr,	\
+ 				  char *buf)				\
+ {									\
+ 	return show_cpumap(1, topology_##name(dev->id), buf);		\
+@@ -124,16 +123,16 @@
+ #endif
+ 
+ static struct attribute *default_attrs[] = {
+-	&attr_physical_package_id.attr,
+-	&attr_core_id.attr,
+-	&attr_thread_siblings.attr,
+-	&attr_thread_siblings_list.attr,
+-	&attr_core_siblings.attr,
+-	&attr_core_siblings_list.attr,
++	&dev_attr_physical_package_id.attr,
++	&dev_attr_core_id.attr,
++	&dev_attr_thread_siblings.attr,
++	&dev_attr_thread_siblings_list.attr,
++	&dev_attr_core_siblings.attr,
++	&dev_attr_core_siblings_list.attr,
+ #ifdef CONFIG_SCHED_BOOK
+-	&attr_book_id.attr,
+-	&attr_book_siblings.attr,
+-	&attr_book_siblings_list.attr,
++	&dev_attr_book_id.attr,
++	&dev_attr_book_siblings.attr,
++	&dev_attr_book_siblings_list.attr,
+ #endif
+ 	NULL
+ };
+@@ -146,16 +145,16 @@
+ /* Add/Remove cpu_topology interface for CPU device */
+ static int __cpuinit topology_add_dev(unsigned int cpu)
+ {
+-	struct sys_device *sys_dev = get_cpu_sysdev(cpu);
++	struct device *dev = get_cpu_device(cpu);
+ 
+-	return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
++	return sysfs_create_group(&dev->kobj, &topology_attr_group);
+ }
+ 
+ static void __cpuinit topology_remove_dev(unsigned int cpu)
+ {
+-	struct sys_device *sys_dev = get_cpu_sysdev(cpu);
++	struct device *dev = get_cpu_device(cpu);
+ 
+-	sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
++	sysfs_remove_group(&dev->kobj, &topology_attr_group);
+ }
+ 
+ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -679,7 +679,7 @@
+  */
+ static int cpufreq_add_dev_policy(unsigned int cpu,
+ 				  struct cpufreq_policy *policy,
+-				  struct sys_device *sys_dev)
++				  struct device *dev)
+ {
+ 	int ret = 0;
+ #ifdef CONFIG_SMP
+@@ -728,7 +728,7 @@
+ 			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ 
+ 			pr_debug("CPU already managed, adding link\n");
+-			ret = sysfs_create_link(&sys_dev->kobj,
++			ret = sysfs_create_link(&dev->kobj,
+ 						&managed_policy->kobj,
+ 						"cpufreq");
+ 			if (ret)
+@@ -761,7 +761,7 @@
+ 
+ 	for_each_cpu(j, policy->cpus) {
+ 		struct cpufreq_policy *managed_policy;
+-		struct sys_device *cpu_sys_dev;
++		struct device *cpu_dev;
+ 
+ 		if (j == cpu)
+ 			continue;
+@@ -770,8 +770,8 @@
+ 
+ 		pr_debug("CPU %u already managed, adding link\n", j);
+ 		managed_policy = cpufreq_cpu_get(cpu);
+-		cpu_sys_dev = get_cpu_sysdev(j);
+-		ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
++		cpu_dev = get_cpu_device(j);
++		ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
+ 					"cpufreq");
+ 		if (ret) {
+ 			cpufreq_cpu_put(managed_policy);
+@@ -783,7 +783,7 @@
+ 
+ static int cpufreq_add_dev_interface(unsigned int cpu,
+ 				     struct cpufreq_policy *policy,
+-				     struct sys_device *sys_dev)
++				     struct device *dev)
+ {
+ 	struct cpufreq_policy new_policy;
+ 	struct freq_attr **drv_attr;
+@@ -793,7 +793,7 @@
+ 
+ 	/* prepare interface data */
+ 	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
+-				   &sys_dev->kobj, "cpufreq");
++				   &dev->kobj, "cpufreq");
+ 	if (ret)
+ 		return ret;
+ 
+@@ -866,9 +866,9 @@
+  * with with cpu hotplugging and all hell will break loose. Tried to clean this
+  * mess up, but more thorough testing is needed. - Mathieu
+  */
+-static int cpufreq_add_dev(struct sys_device *sys_dev)
++static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
+ {
+-	unsigned int cpu = sys_dev->id;
++	unsigned int cpu = dev->id;
+ 	int ret = 0, found = 0;
+ 	struct cpufreq_policy *policy;
+ 	unsigned long flags;
+@@ -947,7 +947,7 @@
+ 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ 				     CPUFREQ_START, policy);
+ 
+-	ret = cpufreq_add_dev_policy(cpu, policy, sys_dev);
++	ret = cpufreq_add_dev_policy(cpu, policy, dev);
+ 	if (ret) {
+ 		if (ret > 0)
+ 			/* This is a managed cpu, symlink created,
+@@ -956,7 +956,7 @@
+ 		goto err_unlock_policy;
+ 	}
+ 
+-	ret = cpufreq_add_dev_interface(cpu, policy, sys_dev);
++	ret = cpufreq_add_dev_interface(cpu, policy, dev);
+ 	if (ret)
+ 		goto err_out_unregister;
+ 
+@@ -999,15 +999,15 @@
+  * Caller should already have policy_rwsem in write mode for this CPU.
+  * This routine frees the rwsem before returning.
+  */
+-static int __cpufreq_remove_dev(struct sys_device *sys_dev)
++static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
+ {
+-	unsigned int cpu = sys_dev->id;
++	unsigned int cpu = dev->id;
+ 	unsigned long flags;
+ 	struct cpufreq_policy *data;
+ 	struct kobject *kobj;
+ 	struct completion *cmp;
+ #ifdef CONFIG_SMP
+-	struct sys_device *cpu_sys_dev;
++	struct device *cpu_dev;
+ 	unsigned int j;
+ #endif
+ 
+@@ -1032,7 +1032,7 @@
+ 		pr_debug("removing link\n");
+ 		cpumask_clear_cpu(cpu, data->cpus);
+ 		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+-		kobj = &sys_dev->kobj;
++		kobj = &dev->kobj;
+ 		cpufreq_cpu_put(data);
+ 		unlock_policy_rwsem_write(cpu);
+ 		sysfs_remove_link(kobj, "cpufreq");
+@@ -1071,8 +1071,8 @@
+ 			strncpy(per_cpu(cpufreq_cpu_governor, j),
+ 				data->governor->name, CPUFREQ_NAME_LEN);
+ #endif
+-			cpu_sys_dev = get_cpu_sysdev(j);
+-			kobj = &cpu_sys_dev->kobj;
++			cpu_dev = get_cpu_device(j);
++			kobj = &cpu_dev->kobj;
+ 			unlock_policy_rwsem_write(cpu);
+ 			sysfs_remove_link(kobj, "cpufreq");
+ 			lock_policy_rwsem_write(cpu);
+@@ -1112,11 +1112,11 @@
+ 	if (unlikely(cpumask_weight(data->cpus) > 1)) {
+ 		/* first sibling now owns the new sysfs dir */
+ 		cpumask_clear_cpu(cpu, data->cpus);
+-		cpufreq_add_dev(get_cpu_sysdev(cpumask_first(data->cpus)));
++		cpufreq_add_dev(get_cpu_device(cpumask_first(data->cpus)), NULL);
+ 
+ 		/* finally remove our own symlink */
+ 		lock_policy_rwsem_write(cpu);
+-		__cpufreq_remove_dev(sys_dev);
++		__cpufreq_remove_dev(dev, sif);
+ 	}
+ #endif
+ 
+@@ -1128,9 +1128,9 @@
+ }
+ 
+ 
+-static int cpufreq_remove_dev(struct sys_device *sys_dev)
++static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
+ {
+-	unsigned int cpu = sys_dev->id;
++	unsigned int cpu = dev->id;
+ 	int retval;
+ 
+ 	if (cpu_is_offline(cpu))
+@@ -1139,7 +1139,7 @@
+ 	if (unlikely(lock_policy_rwsem_write(cpu)))
+ 		BUG();
+ 
+-	retval = __cpufreq_remove_dev(sys_dev);
++	retval = __cpufreq_remove_dev(dev, sif);
+ 	return retval;
+ }
+ 
+@@ -1271,9 +1271,11 @@
+ }
+ EXPORT_SYMBOL(cpufreq_get);
+ 
+-static struct sysdev_driver cpufreq_sysdev_driver = {
+-	.add		= cpufreq_add_dev,
+-	.remove		= cpufreq_remove_dev,
++static struct subsys_interface cpufreq_interface = {
++	.name		= "cpufreq",
++	.subsys		= &cpu_subsys,
++	.add_dev	= cpufreq_add_dev,
++	.remove_dev	= cpufreq_remove_dev,
+ };
+ 
+ 
+@@ -1765,25 +1767,25 @@
+ 					unsigned long action, void *hcpu)
+ {
+ 	unsigned int cpu = (unsigned long)hcpu;
+-	struct sys_device *sys_dev;
++	struct device *dev;
+ 
+-	sys_dev = get_cpu_sysdev(cpu);
+-	if (sys_dev) {
++	dev = get_cpu_device(cpu);
++	if (dev) {
+ 		switch (action) {
+ 		case CPU_ONLINE:
+ 		case CPU_ONLINE_FROZEN:
+-			cpufreq_add_dev(sys_dev);
++			cpufreq_add_dev(dev, NULL);
+ 			break;
+ 		case CPU_DOWN_PREPARE:
+ 		case CPU_DOWN_PREPARE_FROZEN:
+ 			if (unlikely(lock_policy_rwsem_write(cpu)))
+ 				BUG();
+ 
+-			__cpufreq_remove_dev(sys_dev);
++			__cpufreq_remove_dev(dev, NULL);
+ 			break;
+ 		case CPU_DOWN_FAILED:
+ 		case CPU_DOWN_FAILED_FROZEN:
+-			cpufreq_add_dev(sys_dev);
++			cpufreq_add_dev(dev, NULL);
+ 			break;
+ 		}
+ 	}
+@@ -1830,8 +1832,7 @@
+ 	cpufreq_driver = driver_data;
+ 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ 
+-	ret = sysdev_driver_register(&cpu_sysdev_class,
+-					&cpufreq_sysdev_driver);
++	ret = subsys_interface_register(&cpufreq_interface);
+ 	if (ret)
+ 		goto err_null_driver;
+ 
+@@ -1850,7 +1851,7 @@
+ 		if (ret) {
+ 			pr_debug("no CPU initialized for driver %s\n",
+ 							driver_data->name);
+-			goto err_sysdev_unreg;
++			goto err_if_unreg;
+ 		}
+ 	}
+ 
+@@ -1858,9 +1859,8 @@
+ 	pr_debug("driver %s up and running\n", driver_data->name);
+ 
+ 	return 0;
+-err_sysdev_unreg:
+-	sysdev_driver_unregister(&cpu_sysdev_class,
+-			&cpufreq_sysdev_driver);
++err_if_unreg:
++	subsys_interface_unregister(&cpufreq_interface);
+ err_null_driver:
+ 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+ 	cpufreq_driver = NULL;
+@@ -1887,7 +1887,7 @@
+ 
+ 	pr_debug("unregistering driver %s\n", driver->name);
+ 
+-	sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
++	subsys_interface_unregister(&cpufreq_interface);
+ 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
+ 
+ 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
+@@ -1907,8 +1907,7 @@
+ 		init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
+ 	}
+ 
+-	cpufreq_global_kobject = kobject_create_and_add("cpufreq",
+-						&cpu_sysdev_class.kset.kobj);
++	cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
+ 	BUG_ON(!cpufreq_global_kobject);
+ 	register_syscore_ops(&cpufreq_syscore_ops);
+ 
+--- a/drivers/cpufreq/cpufreq_stats.c
++++ b/drivers/cpufreq/cpufreq_stats.c
+@@ -11,7 +11,6 @@
+ 
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+-#include <linux/sysdev.h>
+ #include <linux/cpu.h>
+ #include <linux/sysfs.h>
+ #include <linux/cpufreq.h>
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -291,10 +291,10 @@
+ static int __cpuidle_register_device(struct cpuidle_device *dev)
+ {
+ 	int ret;
+-	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
++	struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
+ 	struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
+ 
+-	if (!sys_dev)
++	if (!dev)
+ 		return -EINVAL;
+ 	if (!try_module_get(cpuidle_driver->owner))
+ 		return -EINVAL;
+@@ -303,7 +303,7 @@
+ 
+ 	per_cpu(cpuidle_devices, dev->cpu) = dev;
+ 	list_add(&dev->device_list, &cpuidle_detected_devices);
+-	if ((ret = cpuidle_add_sysfs(sys_dev))) {
++	if ((ret = cpuidle_add_sysfs(cpu_dev))) {
+ 		module_put(cpuidle_driver->owner);
+ 		return ret;
+ 	}
+@@ -344,7 +344,7 @@
+  */
+ void cpuidle_unregister_device(struct cpuidle_device *dev)
+ {
+-	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
++	struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
+ 	struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
+ 
+ 	if (dev->registered == 0)
+@@ -354,7 +354,7 @@
+ 
+ 	cpuidle_disable_device(dev);
+ 
+-	cpuidle_remove_sysfs(sys_dev);
++	cpuidle_remove_sysfs(cpu_dev);
+ 	list_del(&dev->device_list);
+ 	wait_for_completion(&dev->kobj_unregister);
+ 	per_cpu(cpuidle_devices, dev->cpu) = NULL;
+@@ -411,7 +411,7 @@
+ 	if (cpuidle_disabled())
+ 		return -ENODEV;
+ 
+-	ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
++	ret = cpuidle_add_interface(cpu_subsys.dev_root);
+ 	if (ret)
+ 		return ret;
+ 
+--- a/drivers/cpuidle/cpuidle.h
++++ b/drivers/cpuidle/cpuidle.h
+@@ -5,7 +5,7 @@
+ #ifndef __DRIVER_CPUIDLE_H
+ #define __DRIVER_CPUIDLE_H
+ 
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ 
+ /* For internal use only */
+ extern struct cpuidle_governor *cpuidle_curr_governor;
+@@ -23,11 +23,11 @@
+ extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
+ 
+ /* sysfs */
+-extern int cpuidle_add_class_sysfs(struct sysdev_class *cls);
+-extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls);
++extern int cpuidle_add_interface(struct device *dev);
++extern void cpuidle_remove_interface(struct device *dev);
+ extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
+ extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device);
+-extern int cpuidle_add_sysfs(struct sys_device *sysdev);
+-extern void cpuidle_remove_sysfs(struct sys_device *sysdev);
++extern int cpuidle_add_sysfs(struct device *dev);
++extern void cpuidle_remove_sysfs(struct device *dev);
+ 
+ #endif /* __DRIVER_CPUIDLE_H */
+--- a/drivers/cpuidle/sysfs.c
++++ b/drivers/cpuidle/sysfs.c
+@@ -22,8 +22,8 @@
+ }
+ __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
+ 
+-static ssize_t show_available_governors(struct sysdev_class *class,
+-					struct sysdev_class_attribute *attr,
++static ssize_t show_available_governors(struct device *dev,
++					struct device_attribute *attr,
+ 					char *buf)
+ {
+ 	ssize_t i = 0;
+@@ -42,8 +42,8 @@
+ 	return i;
+ }
+ 
+-static ssize_t show_current_driver(struct sysdev_class *class,
+-				   struct sysdev_class_attribute *attr,
++static ssize_t show_current_driver(struct device *dev,
++				   struct device_attribute *attr,
+ 				   char *buf)
+ {
+ 	ssize_t ret;
+@@ -59,8 +59,8 @@
+ 	return ret;
+ }
+ 
+-static ssize_t show_current_governor(struct sysdev_class *class,
+-				     struct sysdev_class_attribute *attr,
++static ssize_t show_current_governor(struct device *dev,
++				     struct device_attribute *attr,
+ 				     char *buf)
+ {
+ 	ssize_t ret;
+@@ -75,8 +75,8 @@
+ 	return ret;
+ }
+ 
+-static ssize_t store_current_governor(struct sysdev_class *class,
+-				      struct sysdev_class_attribute *attr,
++static ssize_t store_current_governor(struct device *dev,
++				      struct device_attribute *attr,
+ 				      const char *buf, size_t count)
+ {
+ 	char gov_name[CPUIDLE_NAME_LEN];
+@@ -109,50 +109,48 @@
+ 		return count;
+ }
+ 
+-static SYSDEV_CLASS_ATTR(current_driver, 0444, show_current_driver, NULL);
+-static SYSDEV_CLASS_ATTR(current_governor_ro, 0444, show_current_governor,
+-			 NULL);
+-
+-static struct attribute *cpuclass_default_attrs[] = {
+-	&attr_current_driver.attr,
+-	&attr_current_governor_ro.attr,
++static DEVICE_ATTR(current_driver, 0444, show_current_driver, NULL);
++static DEVICE_ATTR(current_governor_ro, 0444, show_current_governor, NULL);
++
++static struct attribute *cpuidle_default_attrs[] = {
++	&dev_attr_current_driver.attr,
++	&dev_attr_current_governor_ro.attr,
+ 	NULL
+ };
+ 
+-static SYSDEV_CLASS_ATTR(available_governors, 0444, show_available_governors,
+-			 NULL);
+-static SYSDEV_CLASS_ATTR(current_governor, 0644, show_current_governor,
+-			 store_current_governor);
+-
+-static struct attribute *cpuclass_switch_attrs[] = {
+-	&attr_available_governors.attr,
+-	&attr_current_driver.attr,
+-	&attr_current_governor.attr,
++static DEVICE_ATTR(available_governors, 0444, show_available_governors, NULL);
++static DEVICE_ATTR(current_governor, 0644, show_current_governor,
++		   store_current_governor);
++
++static struct attribute *cpuidle_switch_attrs[] = {
++	&dev_attr_available_governors.attr,
++	&dev_attr_current_driver.attr,
++	&dev_attr_current_governor.attr,
+ 	NULL
+ };
+ 
+-static struct attribute_group cpuclass_attr_group = {
+-	.attrs = cpuclass_default_attrs,
++static struct attribute_group cpuidle_attr_group = {
++	.attrs = cpuidle_default_attrs,
+ 	.name = "cpuidle",
+ };
+ 
+ /**
+- * cpuidle_add_class_sysfs - add CPU global sysfs attributes
++ * cpuidle_add_interface - add CPU global sysfs attributes
+  */
+-int cpuidle_add_class_sysfs(struct sysdev_class *cls)
++int cpuidle_add_interface(struct device *dev)
+ {
+ 	if (sysfs_switch)
+-		cpuclass_attr_group.attrs = cpuclass_switch_attrs;
++		cpuidle_attr_group.attrs = cpuidle_switch_attrs;
+ 
+-	return sysfs_create_group(&cls->kset.kobj, &cpuclass_attr_group);
++	return sysfs_create_group(&dev->kobj, &cpuidle_attr_group);
+ }
+ 
+ /**
+- * cpuidle_remove_class_sysfs - remove CPU global sysfs attributes
++ * cpuidle_remove_interface - remove CPU global sysfs attributes
+  */
+-void cpuidle_remove_class_sysfs(struct sysdev_class *cls)
++void cpuidle_remove_interface(struct device *dev)
+ {
+-	sysfs_remove_group(&cls->kset.kobj, &cpuclass_attr_group);
++	sysfs_remove_group(&dev->kobj, &cpuidle_attr_group);
+ }
+ 
+ struct cpuidle_attr {
+@@ -365,16 +363,16 @@
+ 
+ /**
+  * cpuidle_add_sysfs - creates a sysfs instance for the target device
+- * @sysdev: the target device
++ * @dev: the target device
+  */
+-int cpuidle_add_sysfs(struct sys_device *sysdev)
++int cpuidle_add_sysfs(struct device *cpu_dev)
+ {
+-	int cpu = sysdev->id;
++	int cpu = cpu_dev->id;
+ 	struct cpuidle_device *dev;
+ 	int error;
+ 
+ 	dev = per_cpu(cpuidle_devices, cpu);
+-	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &sysdev->kobj,
++	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
+ 				     "cpuidle");
+ 	if (!error)
+ 		kobject_uevent(&dev->kobj, KOBJ_ADD);
+@@ -383,11 +381,11 @@
+ 
+ /**
+  * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
+- * @sysdev: the target device
++ * @dev: the target device
+  */
+-void cpuidle_remove_sysfs(struct sys_device *sysdev)
++void cpuidle_remove_sysfs(struct device *cpu_dev)
+ {
+-	int cpu = sysdev->id;
++	int cpu = cpu_dev->id;
+ 	struct cpuidle_device *dev;
+ 
+ 	dev = per_cpu(cpuidle_devices, cpu);
+--- a/drivers/s390/char/sclp_config.c
++++ b/drivers/s390/char/sclp_config.c
+@@ -11,7 +11,7 @@
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/cpu.h>
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/workqueue.h>
+ #include <asm/smp.h>
+ 
+@@ -31,14 +31,14 @@
+ static void sclp_cpu_capability_notify(struct work_struct *work)
+ {
+ 	int cpu;
+-	struct sys_device *sysdev;
++	struct device *dev;
+ 
+ 	s390_adjust_jiffies();
+ 	pr_warning("cpu capability changed.\n");
+ 	get_online_cpus();
+ 	for_each_online_cpu(cpu) {
+-		sysdev = get_cpu_sysdev(cpu);
+-		kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
++		dev = get_cpu_device(cpu);
++		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
+ 	}
+ 	put_online_cpus();
+ }
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -14,7 +14,7 @@
+ #ifndef _LINUX_CPU_H_
+ #define _LINUX_CPU_H_
+ 
+-#include <linux/sysdev.h>
++#include <linux/device.h>
+ #include <linux/node.h>
+ #include <linux/compiler.h>
+ #include <linux/cpumask.h>
+@@ -22,19 +22,19 @@
+ struct cpu {
+ 	int node_id;		/* The node which contains the CPU */
+ 	int hotpluggable;	/* creates sysfs control file if hotpluggable */
+-	struct sys_device sysdev;
++	struct device dev;
+ };
+ 
+ extern int register_cpu(struct cpu *cpu, int num);
+-extern struct sys_device *get_cpu_sysdev(unsigned cpu);
++extern struct device *get_cpu_device(unsigned cpu);
+ 
+-extern int cpu_add_sysdev_attr(struct sysdev_attribute *attr);
+-extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr);
++extern int cpu_add_dev_attr(struct device_attribute *attr);
++extern void cpu_remove_dev_attr(struct device_attribute *attr);
+ 
+-extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs);
+-extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs);
++extern int cpu_add_dev_attr_group(struct attribute_group *attrs);
++extern void cpu_remove_dev_attr_group(struct attribute_group *attrs);
+ 
+-extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls);
++extern int sched_create_sysfs_power_savings_entries(struct device *dev);
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+ extern void unregister_cpu(struct cpu *cpu);
+@@ -160,7 +160,7 @@
+ }
+ 
+ #endif /* CONFIG_SMP */
+-extern struct sysdev_class cpu_sysdev_class;
++extern struct bus_type cpu_subsys;
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+ /* Stop CPUs going up and down. */
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -7949,54 +7949,52 @@
+ }
+ 
+ #ifdef CONFIG_SCHED_MC
+-static ssize_t sched_mc_power_savings_show(struct sysdev_class *class,
+-					   struct sysdev_class_attribute *attr,
+-					   char *page)
++static ssize_t sched_mc_power_savings_show(struct device *dev,
++					   struct device_attribute *attr,
++					   char *buf)
+ {
+-	return sprintf(page, "%u\n", sched_mc_power_savings);
++	return sprintf(buf, "%u\n", sched_mc_power_savings);
+ }
+-static ssize_t sched_mc_power_savings_store(struct sysdev_class *class,
+-					    struct sysdev_class_attribute *attr,
++static ssize_t sched_mc_power_savings_store(struct device *dev,
++					    struct device_attribute *attr,
+ 					    const char *buf, size_t count)
+ {
+ 	return sched_power_savings_store(buf, count, 0);
+ }
+-static SYSDEV_CLASS_ATTR(sched_mc_power_savings, 0644,
+-			 sched_mc_power_savings_show,
+-			 sched_mc_power_savings_store);
++static DEVICE_ATTR(sched_mc_power_savings, 0644,
++		   sched_mc_power_savings_show,
++		   sched_mc_power_savings_store);
+ #endif
+ 
+ #ifdef CONFIG_SCHED_SMT
+-static ssize_t sched_smt_power_savings_show(struct sysdev_class *dev,
+-					    struct sysdev_class_attribute *attr,
+-					    char *page)
++static ssize_t sched_smt_power_savings_show(struct device *dev,
++					    struct device_attribute *attr,
++					    char *buf)
+ {
+-	return sprintf(page, "%u\n", sched_smt_power_savings);
++	return sprintf(buf, "%u\n", sched_smt_power_savings);
+ }
+-static ssize_t sched_smt_power_savings_store(struct sysdev_class *dev,
+-					     struct sysdev_class_attribute *attr,
++static ssize_t sched_smt_power_savings_store(struct device *dev,
++					    struct device_attribute *attr,
+ 					     const char *buf, size_t count)
+ {
+ 	return sched_power_savings_store(buf, count, 1);
+ }
+-static SYSDEV_CLASS_ATTR(sched_smt_power_savings, 0644,
++static DEVICE_ATTR(sched_smt_power_savings, 0644,
+ 		   sched_smt_power_savings_show,
+ 		   sched_smt_power_savings_store);
+ #endif
+ 
+-int __init sched_create_sysfs_power_savings_entries(struct sysdev_class *cls)
++int __init sched_create_sysfs_power_savings_entries(struct device *dev)
+ {
+ 	int err = 0;
+ 
+ #ifdef CONFIG_SCHED_SMT
+ 	if (smt_capable())
+-		err = sysfs_create_file(&cls->kset.kobj,
+-					&attr_sched_smt_power_savings.attr);
++		err = device_create_file(dev, &dev_attr_sched_smt_power_savings);
+ #endif
+ #ifdef CONFIG_SCHED_MC
+ 	if (!err && mc_capable())
+-		err = sysfs_create_file(&cls->kset.kobj,
+-					&attr_sched_mc_power_savings.attr);
++		err = device_create_file(dev, &dev_attr_sched_mc_power_savings);
+ #endif
+ 	return err;
+ }

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/cpufreq-Add-support-for-x86-cpuinfo-auto-loading-v4.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/cpufreq-Add-support-for-x86-cpuinfo-auto-loading-v4.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,596 @@
+From: Andi Kleen <ak at linux.intel.com>
+Date: Thu, 26 Jan 2012 00:09:12 +0100
+Subject: cpufreq: Add support for x86 cpuinfo auto loading v4
+
+commit fa8031aefec0cf7ea6c2387c93610d99d9659aa2 upstream.
+
+This marks all the x86 cpuinfo tables to the CPU specific device drivers,
+to allow auto loading by udev. This should simplify the distribution
+startup scripts for this greatly.
+
+I didn't add MODULE_DEVICE_IDs to the centrino and p4-clockmod drivers,
+because those probably shouldn't be auto loaded and the acpi driver
+be used instead (not fully sure on that, would appreciate feedback)
+
+The old nforce drivers autoload based on the PCI ID.
+
+ACPI cpufreq is autoloaded in another patch.
+
+v3: Autoload gx based on PCI IDs only. Remove cpu check (Dave Jones)
+v4: Use newly introduce HW_PSTATE feature for powernow-k8 loading
+
+Cc: Dave Jones <davej at redhat.com>
+Cc: Kay Sievers <kay.sievers at vrfy.org>
+Signed-off-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/cpufreq/cpufreq-nforce2.c    |    8 ++++++++
+ drivers/cpufreq/e_powersaver.c       |   20 +++++++++++---------
+ drivers/cpufreq/elanfreq.c           |   14 +++++++-------
+ drivers/cpufreq/gx-suspmod.c         |    9 ++-------
+ drivers/cpufreq/longhaul.c           |    8 +++++++-
+ drivers/cpufreq/longrun.c            |   13 ++++++++-----
+ drivers/cpufreq/p4-clockmod.c        |   17 +++++++++++------
+ drivers/cpufreq/powernow-k6.c        |   12 ++++++++----
+ drivers/cpufreq/powernow-k7.c        |   14 ++++++++------
+ drivers/cpufreq/powernow-k8.c        |   19 +++++++++++++------
+ drivers/cpufreq/sc520_freq.c         |   14 ++++++++------
+ drivers/cpufreq/speedstep-centrino.c |   24 ++++++++++++++++++++----
+ drivers/cpufreq/speedstep-ich.c      |   15 +++++++++++++++
+ drivers/cpufreq/speedstep-lib.c      |    1 +
+ drivers/cpufreq/speedstep-smi.c      |   15 +++++++++++++++
+ 15 files changed, 142 insertions(+), 61 deletions(-)
+
+diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c
+index 7bac808..13d311e 100644
+--- a/drivers/cpufreq/cpufreq-nforce2.c
++++ b/drivers/cpufreq/cpufreq-nforce2.c
+@@ -385,6 +385,14 @@ static struct cpufreq_driver nforce2_driver = {
+ 	.owner = THIS_MODULE,
+ };
+ 
++#ifdef MODULE
++static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = {
++	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2 },
++	{}
++};
++MODULE_DEVICE_TABLE(pci, nforce2_ids);
++#endif
++
+ /**
+  * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic
+  *
+diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
+index 4bd6815..3fffbe6 100644
+--- a/drivers/cpufreq/e_powersaver.c
++++ b/drivers/cpufreq/e_powersaver.c
+@@ -16,6 +16,7 @@
+ #include <linux/io.h>
+ #include <linux/delay.h>
+ 
++#include <asm/cpu_device_id.h>
+ #include <asm/msr.h>
+ #include <asm/tsc.h>
+ 
+@@ -437,18 +438,19 @@ static struct cpufreq_driver eps_driver = {
+ 	.attr		= eps_attr,
+ };
+ 
++
++/* This driver will work only on Centaur C7 processors with
++ * Enhanced SpeedStep/PowerSaver registers */
++static const struct x86_cpu_id eps_cpu_id[] = {
++	{ X86_VENDOR_CENTAUR, 6, X86_MODEL_ANY, X86_FEATURE_EST },
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, eps_cpu_id);
++
+ static int __init eps_init(void)
+ {
+-	struct cpuinfo_x86 *c = &cpu_data(0);
+-
+-	/* This driver will work only on Centaur C7 processors with
+-	 * Enhanced SpeedStep/PowerSaver registers */
+-	if (c->x86_vendor != X86_VENDOR_CENTAUR
+-	    || c->x86 != 6 || c->x86_model < 10)
+-		return -ENODEV;
+-	if (!cpu_has(c, X86_FEATURE_EST))
++	if (!x86_match_cpu(eps_cpu_id) || boot_cpu_data.x86_model < 10)
+ 		return -ENODEV;
+-
+ 	if (cpufreq_register_driver(&eps_driver))
+ 		return -EINVAL;
+ 	return 0;
+diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c
+index c587db4..960671f 100644
+--- a/drivers/cpufreq/elanfreq.c
++++ b/drivers/cpufreq/elanfreq.c
+@@ -23,6 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/cpufreq.h>
+ 
++#include <asm/cpu_device_id.h>
+ #include <asm/msr.h>
+ #include <linux/timex.h>
+ #include <linux/io.h>
+@@ -277,17 +278,16 @@ static struct cpufreq_driver elanfreq_driver = {
+ 	.attr		= elanfreq_attr,
+ };
+ 
++static const struct x86_cpu_id elan_id[] = {
++	{ X86_VENDOR_AMD, 4, 10, },
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, elan_id);
+ 
+ static int __init elanfreq_init(void)
+ {
+-	struct cpuinfo_x86 *c = &cpu_data(0);
+-
+-	/* Test if we have the right hardware */
+-	if ((c->x86_vendor != X86_VENDOR_AMD) ||
+-		(c->x86 != 4) || (c->x86_model != 10)) {
+-		printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
++	if (!x86_match_cpu(elan_id))
+ 		return -ENODEV;
+-	}
+ 	return cpufreq_register_driver(&elanfreq_driver);
+ }
+ 
+diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c
+index ffe1f2c..5a06c0b 100644
+--- a/drivers/cpufreq/gx-suspmod.c
++++ b/drivers/cpufreq/gx-suspmod.c
+@@ -82,6 +82,7 @@
+ #include <linux/errno.h>
+ #include <linux/slab.h>
+ 
++#include <asm/cpu_device_id.h>
+ #include <asm/processor-cyrix.h>
+ 
+ /* PCI config registers, all at F0 */
+@@ -171,6 +172,7 @@ static struct pci_device_id gx_chipset_tbl[] __initdata = {
+ 	{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), },
+ 	{ 0, },
+ };
++MODULE_DEVICE_TABLE(gx_chipset_tbl);
+ 
+ static void gx_write_byte(int reg, int value)
+ {
+@@ -185,13 +187,6 @@ static __init struct pci_dev *gx_detect_chipset(void)
+ {
+ 	struct pci_dev *gx_pci = NULL;
+ 
+-	/* check if CPU is a MediaGX or a Geode. */
+-	if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
+-	    (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
+-		pr_debug("error: no MediaGX/Geode processor found!\n");
+-		return NULL;
+-	}
+-
+ 	/* detect which companion chip is used */
+ 	for_each_pci_dev(gx_pci) {
+ 		if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL)
+diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
+index f47d26e..53ddbc7 100644
+--- a/drivers/cpufreq/longhaul.c
++++ b/drivers/cpufreq/longhaul.c
+@@ -35,6 +35,7 @@
+ #include <linux/acpi.h>
+ 
+ #include <asm/msr.h>
++#include <asm/cpu_device_id.h>
+ #include <acpi/processor.h>
+ 
+ #include "longhaul.h"
+@@ -951,12 +952,17 @@ static struct cpufreq_driver longhaul_driver = {
+ 	.attr	= longhaul_attr,
+ };
+ 
++static const struct x86_cpu_id longhaul_id[] = {
++	{ X86_VENDOR_CENTAUR, 6 },
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, longhaul_id);
+ 
+ static int __init longhaul_init(void)
+ {
+ 	struct cpuinfo_x86 *c = &cpu_data(0);
+ 
+-	if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
++	if (!x86_match_cpu(longhaul_id))
+ 		return -ENODEV;
+ 
+ #ifdef CONFIG_SMP
+diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c
+index 34ea359..8bc9f5f 100644
+--- a/drivers/cpufreq/longrun.c
++++ b/drivers/cpufreq/longrun.c
+@@ -14,6 +14,7 @@
+ 
+ #include <asm/msr.h>
+ #include <asm/processor.h>
++#include <asm/cpu_device_id.h>
+ 
+ static struct cpufreq_driver	longrun_driver;
+ 
+@@ -288,6 +289,12 @@ static struct cpufreq_driver longrun_driver = {
+ 	.owner		= THIS_MODULE,
+ };
+ 
++static const struct x86_cpu_id longrun_ids[] = {
++	{ X86_VENDOR_TRANSMETA, X86_FAMILY_ANY, X86_MODEL_ANY,
++	  X86_FEATURE_LONGRUN },
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, longrun_ids);
+ 
+ /**
+  * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
+@@ -296,12 +303,8 @@ static struct cpufreq_driver longrun_driver = {
+  */
+ static int __init longrun_init(void)
+ {
+-	struct cpuinfo_x86 *c = &cpu_data(0);
+-
+-	if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
+-	    !cpu_has(c, X86_FEATURE_LONGRUN))
++	if (!x86_match_cpu(longrun_ids))
+ 		return -ENODEV;
+-
+ 	return cpufreq_register_driver(&longrun_driver);
+ }
+ 
+diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
+index 6be3e07..827629c9 100644
+--- a/drivers/cpufreq/p4-clockmod.c
++++ b/drivers/cpufreq/p4-clockmod.c
+@@ -31,6 +31,7 @@
+ #include <asm/processor.h>
+ #include <asm/msr.h>
+ #include <asm/timer.h>
++#include <asm/cpu_device_id.h>
+ 
+ #include "speedstep-lib.h"
+ 
+@@ -289,21 +290,25 @@ static struct cpufreq_driver p4clockmod_driver = {
+ 	.attr		= p4clockmod_attr,
+ };
+ 
++static const struct x86_cpu_id cpufreq_p4_id[] = {
++	{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ACC },
++	{}
++};
++
++/*
++ * Intentionally no MODULE_DEVICE_TABLE here: this driver should not
++ * be auto loaded.  Please don't add one.
++ */
+ 
+ static int __init cpufreq_p4_init(void)
+ {
+-	struct cpuinfo_x86 *c = &cpu_data(0);
+ 	int ret;
+ 
+ 	/*
+ 	 * THERM_CONTROL is architectural for IA32 now, so
+ 	 * we can rely on the capability checks
+ 	 */
+-	if (c->x86_vendor != X86_VENDOR_INTEL)
+-		return -ENODEV;
+-
+-	if (!test_cpu_cap(c, X86_FEATURE_ACPI) ||
+-				!test_cpu_cap(c, X86_FEATURE_ACC))
++	if (!x86_match_cpu(cpufreq_p4_id) || !boot_cpu_has(X86_FEATURE_ACPI))
+ 		return -ENODEV;
+ 
+ 	ret = cpufreq_register_driver(&p4clockmod_driver);
+diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
+index b3379d6..54dd031 100644
+--- a/drivers/cpufreq/powernow-k6.c
++++ b/drivers/cpufreq/powernow-k6.c
+@@ -16,6 +16,7 @@
+ #include <linux/timex.h>
+ #include <linux/io.h>
+ 
++#include <asm/cpu_device_id.h>
+ #include <asm/msr.h>
+ 
+ #define POWERNOW_IOPORT 0xfff0          /* it doesn't matter where, as long
+@@ -210,6 +211,12 @@ static struct cpufreq_driver powernow_k6_driver = {
+ 	.attr		= powernow_k6_attr,
+ };
+ 
++static const struct x86_cpu_id powernow_k6_ids[] = {
++	{ X86_VENDOR_AMD, 5, 12 },
++	{ X86_VENDOR_AMD, 5, 13 },
++	{}
++};
++
+ 
+ /**
+  * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver
+@@ -220,10 +227,7 @@ static struct cpufreq_driver powernow_k6_driver = {
+  */
+ static int __init powernow_k6_init(void)
+ {
+-	struct cpuinfo_x86 *c = &cpu_data(0);
+-
+-	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
+-		((c->x86_model != 12) && (c->x86_model != 13)))
++	if (!x86_match_cpu(powernow_k6_ids))
+ 		return -ENODEV;
+ 
+ 	if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
+diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
+index d71d9f3..501d167 100644
+--- a/drivers/cpufreq/powernow-k7.c
++++ b/drivers/cpufreq/powernow-k7.c
+@@ -28,6 +28,7 @@
+ #include <asm/timer.h>		/* Needed for recalibrate_cpu_khz() */
+ #include <asm/msr.h>
+ #include <asm/system.h>
++#include <asm/cpu_device_id.h>
+ 
+ #ifdef CONFIG_X86_POWERNOW_K7_ACPI
+ #include <linux/acpi.h>
+@@ -110,18 +111,19 @@ static int check_fsb(unsigned int fsbspeed)
+ 	return delta < 5;
+ }
+ 
++static const struct x86_cpu_id powernow_k7_cpuids[] = {
++	{ X86_VENDOR_AMD, 7, },
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);
++
+ static int check_powernow(void)
+ {
+ 	struct cpuinfo_x86 *c = &cpu_data(0);
+ 	unsigned int maxei, eax, ebx, ecx, edx;
+ 
+-	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) {
+-#ifdef MODULE
+-		printk(KERN_INFO PFX "This module only works with "
+-				"AMD K7 CPUs\n");
+-#endif
++	if (!x86_match_cpu(powernow_k7_cpuids))
+ 		return 0;
+-	}
+ 
+ 	/* Get maximum capabilities */
+ 	maxei = cpuid_eax(0x80000000);
+diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
+index 8f9b2ce..c0e8164 100644
+--- a/drivers/cpufreq/powernow-k8.c
++++ b/drivers/cpufreq/powernow-k8.c
+@@ -40,6 +40,7 @@
+ #include <linux/delay.h>
+ 
+ #include <asm/msr.h>
++#include <asm/cpu_device_id.h>
+ 
+ #include <linux/acpi.h>
+ #include <linux/mutex.h>
+@@ -520,6 +521,15 @@ static int core_voltage_post_transition(struct powernow_k8_data *data,
+ 	return 0;
+ }
+ 
++static const struct x86_cpu_id powernow_k8_ids[] = {
++	/* IO based frequency switching */
++	{ X86_VENDOR_AMD, 0xf },
++	/* MSR based frequency switching supported */
++	X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE),
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids);
++
+ static void check_supported_cpu(void *_rc)
+ {
+ 	u32 eax, ebx, ecx, edx;
+@@ -527,13 +537,7 @@ static void check_supported_cpu(void *_rc)
+ 
+ 	*rc = -ENODEV;
+ 
+-	if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD)
+-		return;
+-
+ 	eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
+-	if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
+-	    ((eax & CPUID_XFAM) < CPUID_XFAM_10H))
+-		return;
+ 
+ 	if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
+ 		if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
+@@ -1553,6 +1557,9 @@ static int __cpuinit powernowk8_init(void)
+ 	unsigned int i, supported_cpus = 0, cpu;
+ 	int rv;
+ 
++	if (!x86_match_cpu(powernow_k8_ids))
++		return -ENODEV;
++
+ 	for_each_online_cpu(i) {
+ 		int rc;
+ 		smp_call_function_single(i, check_supported_cpu, &rc, 1);
+diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c
+index 1e205e6..e42e073 100644
+--- a/drivers/cpufreq/sc520_freq.c
++++ b/drivers/cpufreq/sc520_freq.c
+@@ -22,6 +22,7 @@
+ #include <linux/timex.h>
+ #include <linux/io.h>
+ 
++#include <asm/cpu_device_id.h>
+ #include <asm/msr.h>
+ 
+ #define MMCR_BASE	0xfffef000	/* The default base address */
+@@ -150,18 +151,19 @@ static struct cpufreq_driver sc520_freq_driver = {
+ 	.attr	= sc520_freq_attr,
+ };
+ 
++static const struct x86_cpu_id sc520_ids[] = {
++	{ X86_VENDOR_AMD, 4, 9 },
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, sc520_ids);
+ 
+ static int __init sc520_freq_init(void)
+ {
+-	struct cpuinfo_x86 *c = &cpu_data(0);
+ 	int err;
+ 
+-	/* Test if we have the right hardware */
+-	if (c->x86_vendor != X86_VENDOR_AMD ||
+-	    c->x86 != 4 || c->x86_model != 9) {
+-		pr_debug("no Elan SC520 processor found!\n");
++	if (!x86_match_cpu(sc520_ids))
+ 		return -ENODEV;
+-	}
++
+ 	cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
+ 	if (!cpuctl) {
+ 		printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
+diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
+index 6ea3455..3a953d5 100644
+--- a/drivers/cpufreq/speedstep-centrino.c
++++ b/drivers/cpufreq/speedstep-centrino.c
+@@ -25,6 +25,7 @@
+ #include <asm/msr.h>
+ #include <asm/processor.h>
+ #include <asm/cpufeature.h>
++#include <asm/cpu_device_id.h>
+ 
+ #define PFX		"speedstep-centrino: "
+ #define MAINTAINER	"cpufreq at vger.kernel.org"
+@@ -595,6 +596,24 @@ static struct cpufreq_driver centrino_driver = {
+ 	.owner		= THIS_MODULE,
+ };
+ 
++/*
++ * This doesn't replace the detailed checks above because
++ * the generic CPU IDs don't have a way to match for steppings
++ * or ASCII model IDs.
++ */
++static const struct x86_cpu_id centrino_ids[] = {
++	{ X86_VENDOR_INTEL, 6, 9, X86_FEATURE_EST },
++	{ X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
++	{ X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
++	{ X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
++	{ X86_VENDOR_INTEL, 15, 3, X86_FEATURE_EST },
++	{ X86_VENDOR_INTEL, 15, 4, X86_FEATURE_EST },
++	{}
++};
++#if 0
++/* Autoload or not? Do not for now. */
++MODULE_DEVICE_TABLE(x86cpu, centrino_ids);
++#endif
+ 
+ /**
+  * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver
+@@ -612,11 +631,8 @@ static struct cpufreq_driver centrino_driver = {
+  */
+ static int __init centrino_init(void)
+ {
+-	struct cpuinfo_x86 *cpu = &cpu_data(0);
+-
+-	if (!cpu_has(cpu, X86_FEATURE_EST))
++	if (!x86_match_cpu(centrino_ids))
+ 		return -ENODEV;
+-
+ 	return cpufreq_register_driver(&centrino_driver);
+ }
+ 
+diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
+index a748ce7..7432b3a 100644
+--- a/drivers/cpufreq/speedstep-ich.c
++++ b/drivers/cpufreq/speedstep-ich.c
+@@ -25,6 +25,8 @@
+ #include <linux/pci.h>
+ #include <linux/sched.h>
+ 
++#include <asm/cpu_device_id.h>
++
+ #include "speedstep-lib.h"
+ 
+ 
+@@ -388,6 +390,16 @@ static struct cpufreq_driver speedstep_driver = {
+ 	.attr	= speedstep_attr,
+ };
+ 
++static const struct x86_cpu_id ss_smi_ids[] = {
++	{ X86_VENDOR_INTEL, 6, 0xb, },
++	{ X86_VENDOR_INTEL, 6, 0x8, },
++	{ X86_VENDOR_INTEL, 15, 2 },
++	{}
++};
++#if 0
++/* Autoload or not? Do not for now. */
++MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids);
++#endif
+ 
+ /**
+  * speedstep_init - initializes the SpeedStep CPUFreq driver
+@@ -398,6 +410,9 @@ static struct cpufreq_driver speedstep_driver = {
+  */
+ static int __init speedstep_init(void)
+ {
++	if (!x86_match_cpu(ss_smi_ids))
++		return -ENODEV;
++
+ 	/* detect processor */
+ 	speedstep_processor = speedstep_detect_processor();
+ 	if (!speedstep_processor) {
+diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c
+index 8af2d2f..7047821 100644
+--- a/drivers/cpufreq/speedstep-lib.c
++++ b/drivers/cpufreq/speedstep-lib.c
+@@ -249,6 +249,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_frequency);
+  *                 DETECT SPEEDSTEP-CAPABLE PROCESSOR                *
+  *********************************************************************/
+ 
++/* Keep in sync with the x86_cpu_id tables in the different modules */
+ unsigned int speedstep_detect_processor(void)
+ {
+ 	struct cpuinfo_x86 *c = &cpu_data(0);
+diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
+index c76ead3..6a457fc 100644
+--- a/drivers/cpufreq/speedstep-smi.c
++++ b/drivers/cpufreq/speedstep-smi.c
+@@ -20,6 +20,7 @@
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <asm/ist.h>
++#include <asm/cpu_device_id.h>
+ 
+ #include "speedstep-lib.h"
+ 
+@@ -379,6 +380,17 @@ static struct cpufreq_driver speedstep_driver = {
+ 	.attr		= speedstep_attr,
+ };
+ 
++static const struct x86_cpu_id ss_smi_ids[] = {
++	{ X86_VENDOR_INTEL, 6, 0xb, },
++	{ X86_VENDOR_INTEL, 6, 0x8, },
++	{ X86_VENDOR_INTEL, 15, 2 },
++	{}
++};
++#if 0
++/* Not auto loaded currently */
++MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids);
++#endif
++
+ /**
+  * speedstep_init - initializes the SpeedStep CPUFreq driver
+  *
+@@ -388,6 +400,9 @@ static struct cpufreq_driver speedstep_driver = {
+  */
+ static int __init speedstep_init(void)
+ {
++	if (!x86_match_cpu(ss_smi_ids))
++		return -ENODEV;
++
+ 	speedstep_processor = speedstep_detect_processor();
+ 
+ 	switch (speedstep_processor) {

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/crypto-Add-support-for-x86-cpuid-auto-loading-for-x8.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/crypto-Add-support-for-x86-cpuid-auto-loading-for-x8.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,215 @@
+From: Andi Kleen <ak at linux.intel.com>
+Date: Thu, 26 Jan 2012 00:09:06 +0100
+Subject: crypto: Add support for x86 cpuid auto loading for x86 crypto
+ drivers
+
+commit 3bd391f056df61e928de1680ff4a3e7e07e5b399 upstream.
+
+Add support for auto-loading of crypto drivers based on cpuid features.
+This enables auto-loading of the VIA and Intel specific drivers
+for AES, hashing and CRCs.
+
+Requires the earlier infrastructure patch to add x86 modinfo.
+I kept it all in a single patch for now.
+
+I dropped the printks when the driver cpuid doesn't match (imho
+drivers never should print anything in such a case)
+
+One drawback is that udev doesn't know if the drivers are used or not,
+so they will be unconditionally loaded at boot up. That's better
+than not loading them at all, like it often happens.
+
+Cc: Dave Jones <davej at redhat.com>
+Cc: Kay Sievers <kay.sievers at vrfy.org>
+Cc: Jen Axboe <axboe at kernel.dk>
+Cc: Herbert Xu <herbert at gondor.apana.org.au>
+Cc: Huang Ying <ying.huang at intel.com>
+Signed-off-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ arch/x86/crypto/aesni-intel_glue.c         |   12 +++++++++---
+ arch/x86/crypto/crc32c-intel.c             |   11 ++++++++---
+ arch/x86/crypto/ghash-clmulni-intel_glue.c |   12 ++++++++----
+ drivers/crypto/padlock-aes.c               |    9 ++++++++-
+ drivers/crypto/padlock-sha.c               |   16 ++++++++--------
+ 5 files changed, 41 insertions(+), 19 deletions(-)
+
+diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
+index 545d0ce..b3350bd 100644
+--- a/arch/x86/crypto/aesni-intel_glue.c
++++ b/arch/x86/crypto/aesni-intel_glue.c
+@@ -28,6 +28,7 @@
+ #include <crypto/aes.h>
+ #include <crypto/cryptd.h>
+ #include <crypto/ctr.h>
++#include <asm/cpu_device_id.h>
+ #include <asm/i387.h>
+ #include <asm/aes.h>
+ #include <crypto/scatterwalk.h>
+@@ -1253,14 +1254,19 @@ static struct crypto_alg __rfc4106_alg = {
+ };
+ #endif
+ 
++
++static const struct x86_cpu_id aesni_cpu_id[] = {
++	X86_FEATURE_MATCH(X86_FEATURE_AES),
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, aesni_cpu_id);
++
+ static int __init aesni_init(void)
+ {
+ 	int err;
+ 
+-	if (!cpu_has_aes) {
+-		printk(KERN_INFO "Intel AES-NI instructions are not detected.\n");
++	if (!x86_match_cpu(aesni_cpu_id))
+ 		return -ENODEV;
+-	}
+ 
+ 	if ((err = crypto_fpu_init()))
+ 		goto fpu_err;
+diff --git a/arch/x86/crypto/crc32c-intel.c b/arch/x86/crypto/crc32c-intel.c
+index b9d0026..493f959 100644
+--- a/arch/x86/crypto/crc32c-intel.c
++++ b/arch/x86/crypto/crc32c-intel.c
+@@ -31,6 +31,7 @@
+ #include <crypto/internal/hash.h>
+ 
+ #include <asm/cpufeature.h>
++#include <asm/cpu_device_id.h>
+ 
+ #define CHKSUM_BLOCK_SIZE	1
+ #define CHKSUM_DIGEST_SIZE	4
+@@ -173,13 +174,17 @@ static struct shash_alg alg = {
+ 	}
+ };
+ 
++static const struct x86_cpu_id crc32c_cpu_id[] = {
++	X86_FEATURE_MATCH(X86_FEATURE_XMM4_2),
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id);
+ 
+ static int __init crc32c_intel_mod_init(void)
+ {
+-	if (cpu_has_xmm4_2)
+-		return crypto_register_shash(&alg);
+-	else
++	if (!x86_match_cpu(crc32c_cpu_id))
+ 		return -ENODEV;
++	return crypto_register_shash(&alg);
+ }
+ 
+ static void __exit crc32c_intel_mod_fini(void)
+diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c
+index 976aa64..b4bf0a6 100644
+--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c
++++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c
+@@ -20,6 +20,7 @@
+ #include <crypto/gf128mul.h>
+ #include <crypto/internal/hash.h>
+ #include <asm/i387.h>
++#include <asm/cpu_device_id.h>
+ 
+ #define GHASH_BLOCK_SIZE	16
+ #define GHASH_DIGEST_SIZE	16
+@@ -294,15 +295,18 @@ static struct ahash_alg ghash_async_alg = {
+ 	},
+ };
+ 
++static const struct x86_cpu_id pcmul_cpu_id[] = {
++	X86_FEATURE_MATCH(X86_FEATURE_PCLMULQDQ), /* Pickle-Mickle-Duck */
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, pcmul_cpu_id);
++
+ static int __init ghash_pclmulqdqni_mod_init(void)
+ {
+ 	int err;
+ 
+-	if (!cpu_has_pclmulqdq) {
+-		printk(KERN_INFO "Intel PCLMULQDQ-NI instructions are not"
+-		       " detected.\n");
++	if (!x86_match_cpu(pcmul_cpu_id))
+ 		return -ENODEV;
+-	}
+ 
+ 	err = crypto_register_shash(&ghash_alg);
+ 	if (err)
+diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
+index 29b9469..37b2e94 100644
+--- a/drivers/crypto/padlock-aes.c
++++ b/drivers/crypto/padlock-aes.c
+@@ -19,6 +19,7 @@
+ #include <linux/percpu.h>
+ #include <linux/smp.h>
+ #include <linux/slab.h>
++#include <asm/cpu_device_id.h>
+ #include <asm/byteorder.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+@@ -503,12 +504,18 @@ static struct crypto_alg cbc_aes_alg = {
+ 	}
+ };
+ 
++static struct x86_cpu_id padlock_cpu_id[] = {
++	X86_FEATURE_MATCH(X86_FEATURE_XCRYPT),
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, padlock_cpu_id);
++
+ static int __init padlock_init(void)
+ {
+ 	int ret;
+ 	struct cpuinfo_x86 *c = &cpu_data(0);
+ 
+-	if (!cpu_has_xcrypt)
++	if (!x86_match_cpu(padlock_cpu_id))
+ 		return -ENODEV;
+ 
+ 	if (!cpu_has_xcrypt_enabled) {
+diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c
+index 06bdb4b..9266c0e 100644
+--- a/drivers/crypto/padlock-sha.c
++++ b/drivers/crypto/padlock-sha.c
+@@ -22,6 +22,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/kernel.h>
+ #include <linux/scatterlist.h>
++#include <asm/cpu_device_id.h>
+ #include <asm/i387.h>
+ 
+ struct padlock_sha_desc {
+@@ -526,6 +527,12 @@ static struct shash_alg sha256_alg_nano = {
+ 	}
+ };
+ 
++static struct x86_cpu_id padlock_sha_ids[] = {
++	X86_FEATURE_MATCH(X86_FEATURE_PHE),
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, padlock_sha_ids);
++
+ static int __init padlock_init(void)
+ {
+ 	int rc = -ENODEV;
+@@ -533,15 +540,8 @@ static int __init padlock_init(void)
+ 	struct shash_alg *sha1;
+ 	struct shash_alg *sha256;
+ 
+-	if (!cpu_has_phe) {
+-		printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n");
+-		return -ENODEV;
+-	}
+-
+-	if (!cpu_has_phe_enabled) {
+-		printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
++	if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled)
+ 		return -ENODEV;
+-	}
+ 
+ 	/* Register the newly added algorithm module if on *
+ 	* VIA Nano processor, or else just do as before */

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-cpu-fix-kobject-warning-when-hotplugging.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-cpu-fix-kobject-warning-when-hotplugging.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,31 @@
+From: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+Date: Wed, 8 Feb 2012 15:11:17 -0800
+Subject: driver-core: cpu: fix kobject warning when hotplugging a cpu
+
+commit 29bb5d4fd3140a7d5d02d858118c74a45f15c296 upstream.
+
+Due to the sysdev conversion to struct device, the cpu objects get
+reused when adding a cpu after offlining it, which causes a big warning
+that the kobject portion is not properly initialized.
+
+So clear out the object before we register it again, so all is quiet.
+
+Reported-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Tested-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/base/cpu.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
+index 23f2c4c..4dabf50 100644
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -240,6 +240,7 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
+ 	int error;
+ 
+ 	cpu->node_id = cpu_to_node(num);
++	memset(&cpu->dev, 0x00, sizeof(struct device));
+ 	cpu->dev.id = num;
+ 	cpu->dev.bus = &cpu_subsys;
+ 	cpu->dev.release = cpu_device_release;

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-cpu-remove-kernel-warning-when-removing-.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-cpu-remove-kernel-warning-when-removing-.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,59 @@
+From: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+Date: Thu, 2 Feb 2012 10:36:33 -0800
+Subject: driver core: cpu: remove kernel warning when removing a cpu
+
+commit 2885e25c422fb68208f677f944a45fce8eda2a3c upstream.
+
+With the movement of the cpu sysdev code to be real stuct devices, now
+when we remove a cpu from the system, the driver core rightfully
+complains that there is not a release method for this device.
+
+For now, paper over this issue by quieting the driver core, but comment
+this in detail.  This will be resolved in future kernels to be solved
+properly.
+
+Reported-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Tested-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+[bwh: Adjust context for textual conflict with commit
+ fad12ac8c8c2591c7f4e61d19b6a9d76cd49fafa]
+---
+ drivers/base/cpu.c |   20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -209,6 +209,25 @@
+ }
+ static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
+ 
++static void cpu_device_release(struct device *dev)
++{
++	/*
++	 * This is an empty function to prevent the driver core from spitting a
++	 * warning at us.  Yes, I know this is directly opposite of what the
++	 * documentation for the driver core and kobjects say, and the author
++	 * of this code has already been publically ridiculed for doing
++	 * something as foolish as this.  However, at this point in time, it is
++	 * the only way to handle the issue of statically allocated cpu
++	 * devices.  The different architectures will have their cpu device
++	 * code reworked to properly handle this in the near future, so this
++	 * function will then be changed to correctly free up the memory held
++	 * by the cpu device.
++	 *
++	 * Never copy this way of doing things, or you too will be made fun of
++	 * on the linux-kerenl list, you have been warned.
++	 */
++}
++
+ /*
+  * register_cpu - Setup a sysfs device for a CPU.
+  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
+@@ -224,6 +243,7 @@
+ 	cpu->node_id = cpu_to_node(num);
+ 	cpu->dev.id = num;
+ 	cpu->dev.bus = &cpu_subsys;
++	cpu->dev.release = cpu_device_release;
+ #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+ 	cpu->dev.bus->uevent = arch_cpu_uevent;
+ #endif

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-implement-sysdev-functionality-for-regul.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/driver-core-implement-sysdev-functionality-for-regul.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,884 @@
+From: Kay Sievers <kay.sievers at vrfy.org>
+Date: Wed, 14 Dec 2011 14:29:38 -0800
+Subject: driver-core: implement 'sysdev' functionality for regular devices
+ and buses
+
+commit ca22e56debc57b47c422b749c93217ba62644be2 upstream.
+
+All sysdev classes and sysdev devices will converted to regular devices
+and buses to properly hook userspace into the event processing.
+
+There is no interesting difference between a 'sysdev' and 'device' which
+would justify to roll an entire own subsystem with different userspace
+export semantics. Userspace relies on events and generic sysfs subsystem
+infrastructure from sysdev devices, which are currently not properly
+available.
+
+Every converted sysdev class will create a regular device with the class
+name in /sys/devices/system and all registered devices will becom a children
+of theses devices.
+
+For compatibility reasons, the sysdev class-wide attributes are created
+at this parent device. (Do not copy that logic for anything new, subsystem-
+wide properties belong to the subsystem, not to some fake parent device
+created in /sys/devices.)
+
+Every sysdev driver is implemented as a simple subsystem interface now,
+and no longer called a driver.
+
+After all sysdev classes are ported to regular driver core entities, the
+sysdev implementation will be entirely removed from the kernel.
+
+Signed-off-by: Kay Sievers <kay.sievers at vrfy.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/base/base.h    |   12 +-
+ drivers/base/bus.c     |  293 ++++++++++++++++++++++++++++++++++++++++++++----
+ drivers/base/class.c   |   14 +--
+ drivers/base/core.c    |   85 +++++++++++---
+ drivers/base/init.c    |    1 -
+ drivers/base/sys.c     |   10 +-
+ include/linux/device.h |   78 ++++++++++++-
+ 7 files changed, 431 insertions(+), 62 deletions(-)
+
+diff --git a/drivers/base/base.h b/drivers/base/base.h
+index 21c1b96..7a6ae42 100644
+--- a/drivers/base/base.h
++++ b/drivers/base/base.h
+@@ -4,7 +4,9 @@
+  * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
+  *
+  * @subsys - the struct kset that defines this subsystem
+- * @devices_kset - the list of devices associated
++ * @devices_kset - the subsystem's 'devices' directory
++ * @interfaces - list of subsystem interfaces associated
++ * @mutex - protect the devices, and interfaces lists.
+  *
+  * @drivers_kset - the list of drivers associated
+  * @klist_devices - the klist to iterate over the @devices_kset
+@@ -14,10 +16,8 @@
+  * @bus - pointer back to the struct bus_type that this structure is associated
+  *        with.
+  *
+- * @class_interfaces - list of class_interfaces associated
+  * @glue_dirs - "glue" directory to put in-between the parent device to
+  *              avoid namespace conflicts
+- * @class_mutex - mutex to protect the children, devices, and interfaces lists.
+  * @class - pointer back to the struct class that this structure is associated
+  *          with.
+  *
+@@ -28,6 +28,8 @@
+ struct subsys_private {
+ 	struct kset subsys;
+ 	struct kset *devices_kset;
++	struct list_head interfaces;
++	struct mutex mutex;
+ 
+ 	struct kset *drivers_kset;
+ 	struct klist klist_devices;
+@@ -36,9 +38,7 @@ struct subsys_private {
+ 	unsigned int drivers_autoprobe:1;
+ 	struct bus_type *bus;
+ 
+-	struct list_head class_interfaces;
+ 	struct kset glue_dirs;
+-	struct mutex class_mutex;
+ 	struct class *class;
+ };
+ #define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj)
+@@ -94,7 +94,6 @@ extern int hypervisor_init(void);
+ static inline int hypervisor_init(void) { return 0; }
+ #endif
+ extern int platform_bus_init(void);
+-extern int system_bus_init(void);
+ extern int cpu_dev_init(void);
+ 
+ extern int bus_add_device(struct device *dev);
+@@ -116,6 +115,7 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
+ 
+ extern int devres_release_all(struct device *dev);
+ 
++/* /sys/devices directory */
+ extern struct kset *devices_kset;
+ 
+ #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 000e7b2..99dc592 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -16,9 +16,14 @@
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
++#include <linux/mutex.h>
+ #include "base.h"
+ #include "power/power.h"
+ 
++/* /sys/devices/system */
++/* FIXME: make static after drivers/base/sys.c is deleted */
++struct kset *system_kset;
++
+ #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
+ 
+ /*
+@@ -360,6 +365,47 @@ struct device *bus_find_device_by_name(struct bus_type *bus,
+ }
+ EXPORT_SYMBOL_GPL(bus_find_device_by_name);
+ 
++/**
++ * subsys_find_device_by_id - find a device with a specific enumeration number
++ * @subsys: subsystem
++ * @id: index 'id' in struct device
++ * @hint: device to check first
++ *
++ * Check the hint's next object and if it is a match return it directly,
++ * otherwise, fall back to a full list search. Either way a reference for
++ * the returned object is taken.
++ */
++struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id,
++					struct device *hint)
++{
++	struct klist_iter i;
++	struct device *dev;
++
++	if (!subsys)
++		return NULL;
++
++	if (hint) {
++		klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus);
++		dev = next_device(&i);
++		if (dev && dev->id == id && get_device(dev)) {
++			klist_iter_exit(&i);
++			return dev;
++		}
++		klist_iter_exit(&i);
++	}
++
++	klist_iter_init_node(&subsys->p->klist_devices, &i, NULL);
++	while ((dev = next_device(&i))) {
++		if (dev->id == id && get_device(dev)) {
++			klist_iter_exit(&i);
++			return dev;
++		}
++	}
++	klist_iter_exit(&i);
++	return NULL;
++}
++EXPORT_SYMBOL_GPL(subsys_find_device_by_id);
++
+ static struct device_driver *next_driver(struct klist_iter *i)
+ {
+ 	struct klist_node *n = klist_next(i);
+@@ -487,38 +533,59 @@ out_put:
+ void bus_probe_device(struct device *dev)
+ {
+ 	struct bus_type *bus = dev->bus;
++	struct subsys_interface *sif;
+ 	int ret;
+ 
+-	if (bus && bus->p->drivers_autoprobe) {
++	if (!bus)
++		return;
++
++	if (bus->p->drivers_autoprobe) {
+ 		ret = device_attach(dev);
+ 		WARN_ON(ret < 0);
+ 	}
++
++	mutex_lock(&bus->p->mutex);
++	list_for_each_entry(sif, &bus->p->interfaces, node)
++		if (sif->add_dev)
++			sif->add_dev(dev, sif);
++	mutex_unlock(&bus->p->mutex);
+ }
+ 
+ /**
+  * bus_remove_device - remove device from bus
+  * @dev: device to be removed
+  *
+- * - Remove symlink from bus's directory.
++ * - Remove device from all interfaces.
++ * - Remove symlink from bus' directory.
+  * - Delete device from bus's list.
+  * - Detach from its driver.
+  * - Drop reference taken in bus_add_device().
+  */
+ void bus_remove_device(struct device *dev)
+ {
+-	if (dev->bus) {
+-		sysfs_remove_link(&dev->kobj, "subsystem");
+-		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
+-				  dev_name(dev));
+-		device_remove_attrs(dev->bus, dev);
+-		if (klist_node_attached(&dev->p->knode_bus))
+-			klist_del(&dev->p->knode_bus);
+-
+-		pr_debug("bus: '%s': remove device %s\n",
+-			 dev->bus->name, dev_name(dev));
+-		device_release_driver(dev);
+-		bus_put(dev->bus);
+-	}
++	struct bus_type *bus = dev->bus;
++	struct subsys_interface *sif;
++
++	if (!bus)
++		return;
++
++	mutex_lock(&bus->p->mutex);
++	list_for_each_entry(sif, &bus->p->interfaces, node)
++		if (sif->remove_dev)
++			sif->remove_dev(dev, sif);
++	mutex_unlock(&bus->p->mutex);
++
++	sysfs_remove_link(&dev->kobj, "subsystem");
++	sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
++			  dev_name(dev));
++	device_remove_attrs(dev->bus, dev);
++	if (klist_node_attached(&dev->p->knode_bus))
++		klist_del(&dev->p->knode_bus);
++
++	pr_debug("bus: '%s': remove device %s\n",
++		 dev->bus->name, dev_name(dev));
++	device_release_driver(dev);
++	bus_put(dev->bus);
+ }
+ 
+ static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
+@@ -847,14 +914,14 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
+ static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
+ 
+ /**
+- * bus_register - register a bus with the system.
++ * __bus_register - register a driver-core subsystem
+  * @bus: bus.
+  *
+  * Once we have that, we registered the bus with the kobject
+  * infrastructure, then register the children subsystems it has:
+- * the devices and drivers that belong to the bus.
++ * the devices and drivers that belong to the subsystem.
+  */
+-int bus_register(struct bus_type *bus)
++int __bus_register(struct bus_type *bus, struct lock_class_key *key)
+ {
+ 	int retval;
+ 	struct subsys_private *priv;
+@@ -898,6 +965,8 @@ int bus_register(struct bus_type *bus)
+ 		goto bus_drivers_fail;
+ 	}
+ 
++	INIT_LIST_HEAD(&priv->interfaces);
++	__mutex_init(&priv->mutex, "subsys mutex", key);
+ 	klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
+ 	klist_init(&priv->klist_drivers, NULL, NULL);
+ 
+@@ -927,7 +996,7 @@ out:
+ 	bus->p = NULL;
+ 	return retval;
+ }
+-EXPORT_SYMBOL_GPL(bus_register);
++EXPORT_SYMBOL_GPL(__bus_register);
+ 
+ /**
+  * bus_unregister - remove a bus from the system
+@@ -939,6 +1008,8 @@ EXPORT_SYMBOL_GPL(bus_register);
+ void bus_unregister(struct bus_type *bus)
+ {
+ 	pr_debug("bus: '%s': unregistering\n", bus->name);
++	if (bus->dev_root)
++		device_unregister(bus->dev_root);
+ 	bus_remove_attrs(bus);
+ 	remove_probe_files(bus);
+ 	kset_unregister(bus->p->drivers_kset);
+@@ -1028,10 +1099,194 @@ void bus_sort_breadthfirst(struct bus_type *bus,
+ }
+ EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
+ 
++/**
++ * subsys_dev_iter_init - initialize subsys device iterator
++ * @iter: subsys iterator to initialize
++ * @subsys: the subsys we wanna iterate over
++ * @start: the device to start iterating from, if any
++ * @type: device_type of the devices to iterate over, NULL for all
++ *
++ * Initialize subsys iterator @iter such that it iterates over devices
++ * of @subsys.  If @start is set, the list iteration will start there,
++ * otherwise if it is NULL, the iteration starts at the beginning of
++ * the list.
++ */
++void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys,
++			  struct device *start, const struct device_type *type)
++{
++	struct klist_node *start_knode = NULL;
++
++	if (start)
++		start_knode = &start->p->knode_bus;
++	klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode);
++	iter->type = type;
++}
++EXPORT_SYMBOL_GPL(subsys_dev_iter_init);
++
++/**
++ * subsys_dev_iter_next - iterate to the next device
++ * @iter: subsys iterator to proceed
++ *
++ * Proceed @iter to the next device and return it.  Returns NULL if
++ * iteration is complete.
++ *
++ * The returned device is referenced and won't be released till
++ * iterator is proceed to the next device or exited.  The caller is
++ * free to do whatever it wants to do with the device including
++ * calling back into subsys code.
++ */
++struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter)
++{
++	struct klist_node *knode;
++	struct device *dev;
++
++	for (;;) {
++		knode = klist_next(&iter->ki);
++		if (!knode)
++			return NULL;
++		dev = container_of(knode, struct device_private, knode_bus)->device;
++		if (!iter->type || iter->type == dev->type)
++			return dev;
++	}
++}
++EXPORT_SYMBOL_GPL(subsys_dev_iter_next);
++
++/**
++ * subsys_dev_iter_exit - finish iteration
++ * @iter: subsys iterator to finish
++ *
++ * Finish an iteration.  Always call this function after iteration is
++ * complete whether the iteration ran till the end or not.
++ */
++void subsys_dev_iter_exit(struct subsys_dev_iter *iter)
++{
++	klist_iter_exit(&iter->ki);
++}
++EXPORT_SYMBOL_GPL(subsys_dev_iter_exit);
++
++int subsys_interface_register(struct subsys_interface *sif)
++{
++	struct bus_type *subsys;
++	struct subsys_dev_iter iter;
++	struct device *dev;
++
++	if (!sif || !sif->subsys)
++		return -ENODEV;
++
++	subsys = bus_get(sif->subsys);
++	if (!subsys)
++		return -EINVAL;
++
++	mutex_lock(&subsys->p->mutex);
++	list_add_tail(&sif->node, &subsys->p->interfaces);
++	if (sif->add_dev) {
++		subsys_dev_iter_init(&iter, subsys, NULL, NULL);
++		while ((dev = subsys_dev_iter_next(&iter)))
++			sif->add_dev(dev, sif);
++		subsys_dev_iter_exit(&iter);
++	}
++	mutex_unlock(&subsys->p->mutex);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(subsys_interface_register);
++
++void subsys_interface_unregister(struct subsys_interface *sif)
++{
++	struct bus_type *subsys = sif->subsys;
++	struct subsys_dev_iter iter;
++	struct device *dev;
++
++	if (!sif)
++		return;
++
++	mutex_lock(&subsys->p->mutex);
++	list_del_init(&sif->node);
++	if (sif->remove_dev) {
++		subsys_dev_iter_init(&iter, subsys, NULL, NULL);
++		while ((dev = subsys_dev_iter_next(&iter)))
++			sif->remove_dev(dev, sif);
++		subsys_dev_iter_exit(&iter);
++	}
++	mutex_unlock(&subsys->p->mutex);
++
++	bus_put(subsys);
++}
++EXPORT_SYMBOL_GPL(subsys_interface_unregister);
++
++static void system_root_device_release(struct device *dev)
++{
++	kfree(dev);
++}
++/**
++ * subsys_system_register - register a subsystem at /sys/devices/system/
++ * @subsys - system subsystem
++ * @groups - default attributes for the root device
++ *
++ * All 'system' subsystems have a /sys/devices/system/<name> root device
++ * with the name of the subsystem. The root device can carry subsystem-
++ * wide attributes. All registered devices are below this single root
++ * device and are named after the subsystem with a simple enumeration
++ * number appended. The registered devices are not explicitely named;
++ * only 'id' in the device needs to be set.
++ *
++ * Do not use this interface for anything new, it exists for compatibility
++ * with bad ideas only. New subsystems should use plain subsystems; and
++ * add the subsystem-wide attributes should be added to the subsystem
++ * directory itself and not some create fake root-device placed in
++ * /sys/devices/system/<name>.
++ */
++int subsys_system_register(struct bus_type *subsys,
++			   const struct attribute_group **groups)
++{
++	struct device *dev;
++	int err;
++
++	err = bus_register(subsys);
++	if (err < 0)
++		return err;
++
++	dev = kzalloc(sizeof(struct device), GFP_KERNEL);
++	if (!dev) {
++		err = -ENOMEM;
++		goto err_dev;
++	}
++
++	err = dev_set_name(dev, "%s", subsys->name);
++	if (err < 0)
++		goto err_name;
++
++	dev->kobj.parent = &system_kset->kobj;
++	dev->groups = groups;
++	dev->release = system_root_device_release;
++
++	err = device_register(dev);
++	if (err < 0)
++		goto err_dev_reg;
++
++	subsys->dev_root = dev;
++	return 0;
++
++err_dev_reg:
++	put_device(dev);
++	dev = NULL;
++err_name:
++	kfree(dev);
++err_dev:
++	bus_unregister(subsys);
++	return err;
++}
++EXPORT_SYMBOL_GPL(subsys_system_register);
++
+ int __init buses_init(void)
+ {
+ 	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
+ 	if (!bus_kset)
+ 		return -ENOMEM;
++
++	system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
++	if (!system_kset)
++		return -ENOMEM;
++
+ 	return 0;
+ }
+diff --git a/drivers/base/class.c b/drivers/base/class.c
+index b80d91c..03243d4 100644
+--- a/drivers/base/class.c
++++ b/drivers/base/class.c
+@@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key)
+ 	if (!cp)
+ 		return -ENOMEM;
+ 	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
+-	INIT_LIST_HEAD(&cp->class_interfaces);
++	INIT_LIST_HEAD(&cp->interfaces);
+ 	kset_init(&cp->glue_dirs);
+-	__mutex_init(&cp->class_mutex, "struct class mutex", key);
++	__mutex_init(&cp->mutex, "subsys mutex", key);
+ 	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
+ 	if (error) {
+ 		kfree(cp);
+@@ -460,15 +460,15 @@ int class_interface_register(struct class_interface *class_intf)
+ 	if (!parent)
+ 		return -EINVAL;
+ 
+-	mutex_lock(&parent->p->class_mutex);
+-	list_add_tail(&class_intf->node, &parent->p->class_interfaces);
++	mutex_lock(&parent->p->mutex);
++	list_add_tail(&class_intf->node, &parent->p->interfaces);
+ 	if (class_intf->add_dev) {
+ 		class_dev_iter_init(&iter, parent, NULL, NULL);
+ 		while ((dev = class_dev_iter_next(&iter)))
+ 			class_intf->add_dev(dev, class_intf);
+ 		class_dev_iter_exit(&iter);
+ 	}
+-	mutex_unlock(&parent->p->class_mutex);
++	mutex_unlock(&parent->p->mutex);
+ 
+ 	return 0;
+ }
+@@ -482,7 +482,7 @@ void class_interface_unregister(struct class_interface *class_intf)
+ 	if (!parent)
+ 		return;
+ 
+-	mutex_lock(&parent->p->class_mutex);
++	mutex_lock(&parent->p->mutex);
+ 	list_del_init(&class_intf->node);
+ 	if (class_intf->remove_dev) {
+ 		class_dev_iter_init(&iter, parent, NULL, NULL);
+@@ -490,7 +490,7 @@ void class_interface_unregister(struct class_interface *class_intf)
+ 			class_intf->remove_dev(dev, class_intf);
+ 		class_dev_iter_exit(&iter);
+ 	}
+-	mutex_unlock(&parent->p->class_mutex);
++	mutex_unlock(&parent->p->mutex);
+ 
+ 	class_put(parent);
+ }
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 82c8654..a31ea19 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -117,6 +117,56 @@ static const struct sysfs_ops dev_sysfs_ops = {
+ 	.store	= dev_attr_store,
+ };
+ 
++#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr)
++
++ssize_t device_store_ulong(struct device *dev,
++			   struct device_attribute *attr,
++			   const char *buf, size_t size)
++{
++	struct dev_ext_attribute *ea = to_ext_attr(attr);
++	char *end;
++	unsigned long new = simple_strtoul(buf, &end, 0);
++	if (end == buf)
++		return -EINVAL;
++	*(unsigned long *)(ea->var) = new;
++	/* Always return full write size even if we didn't consume all */
++	return size;
++}
++EXPORT_SYMBOL_GPL(device_store_ulong);
++
++ssize_t device_show_ulong(struct device *dev,
++			  struct device_attribute *attr,
++			  char *buf)
++{
++	struct dev_ext_attribute *ea = to_ext_attr(attr);
++	return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
++}
++EXPORT_SYMBOL_GPL(device_show_ulong);
++
++ssize_t device_store_int(struct device *dev,
++			 struct device_attribute *attr,
++			 const char *buf, size_t size)
++{
++	struct dev_ext_attribute *ea = to_ext_attr(attr);
++	char *end;
++	long new = simple_strtol(buf, &end, 0);
++	if (end == buf || new > INT_MAX || new < INT_MIN)
++		return -EINVAL;
++	*(int *)(ea->var) = new;
++	/* Always return full write size even if we didn't consume all */
++	return size;
++}
++EXPORT_SYMBOL_GPL(device_store_int);
++
++ssize_t device_show_int(struct device *dev,
++			struct device_attribute *attr,
++			char *buf)
++{
++	struct dev_ext_attribute *ea = to_ext_attr(attr);
++
++	return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
++}
++EXPORT_SYMBOL_GPL(device_show_int);
+ 
+ /**
+  *	device_release - free device structure.
+@@ -463,7 +513,7 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
+ static struct device_attribute devt_attr =
+ 	__ATTR(dev, S_IRUGO, show_dev, NULL);
+ 
+-/* kset to create /sys/devices/  */
++/* /sys/devices/ */
+ struct kset *devices_kset;
+ 
+ /**
+@@ -710,6 +760,10 @@ static struct kobject *get_device_parent(struct device *dev,
+ 		return k;
+ 	}
+ 
++	/* subsystems can specify a default root directory for their devices */
++	if (!parent && dev->bus && dev->bus->dev_root)
++		return &dev->bus->dev_root->kobj;
++
+ 	if (parent)
+ 		return &parent->kobj;
+ 	return NULL;
+@@ -730,14 +784,6 @@ static void cleanup_device_parent(struct device *dev)
+ 	cleanup_glue_dir(dev, dev->kobj.parent);
+ }
+ 
+-static void setup_parent(struct device *dev, struct device *parent)
+-{
+-	struct kobject *kobj;
+-	kobj = get_device_parent(dev, parent);
+-	if (kobj)
+-		dev->kobj.parent = kobj;
+-}
+-
+ static int device_add_class_symlinks(struct device *dev)
+ {
+ 	int error;
+@@ -890,6 +936,7 @@ int device_private_init(struct device *dev)
+ int device_add(struct device *dev)
+ {
+ 	struct device *parent = NULL;
++	struct kobject *kobj;
+ 	struct class_interface *class_intf;
+ 	int error = -EINVAL;
+ 
+@@ -913,6 +960,10 @@ int device_add(struct device *dev)
+ 		dev->init_name = NULL;
+ 	}
+ 
++	/* subsystems can specify simple device enumeration */
++	if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
++		dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
++
+ 	if (!dev_name(dev)) {
+ 		error = -EINVAL;
+ 		goto name_error;
+@@ -921,7 +972,9 @@ int device_add(struct device *dev)
+ 	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
+ 
+ 	parent = get_device(dev->parent);
+-	setup_parent(dev, parent);
++	kobj = get_device_parent(dev, parent);
++	if (kobj)
++		dev->kobj.parent = kobj;
+ 
+ 	/* use parent numa_node */
+ 	if (parent)
+@@ -981,17 +1034,17 @@ int device_add(struct device *dev)
+ 			       &parent->p->klist_children);
+ 
+ 	if (dev->class) {
+-		mutex_lock(&dev->class->p->class_mutex);
++		mutex_lock(&dev->class->p->mutex);
+ 		/* tie the class to the device */
+ 		klist_add_tail(&dev->knode_class,
+ 			       &dev->class->p->klist_devices);
+ 
+ 		/* notify any interfaces that the device is here */
+ 		list_for_each_entry(class_intf,
+-				    &dev->class->p->class_interfaces, node)
++				    &dev->class->p->interfaces, node)
+ 			if (class_intf->add_dev)
+ 				class_intf->add_dev(dev, class_intf);
+-		mutex_unlock(&dev->class->p->class_mutex);
++		mutex_unlock(&dev->class->p->mutex);
+ 	}
+ done:
+ 	put_device(dev);
+@@ -1106,15 +1159,15 @@ void device_del(struct device *dev)
+ 	if (dev->class) {
+ 		device_remove_class_symlinks(dev);
+ 
+-		mutex_lock(&dev->class->p->class_mutex);
++		mutex_lock(&dev->class->p->mutex);
+ 		/* notify any interfaces that the device is now gone */
+ 		list_for_each_entry(class_intf,
+-				    &dev->class->p->class_interfaces, node)
++				    &dev->class->p->interfaces, node)
+ 			if (class_intf->remove_dev)
+ 				class_intf->remove_dev(dev, class_intf);
+ 		/* remove the device from the class list */
+ 		klist_del(&dev->knode_class);
+-		mutex_unlock(&dev->class->p->class_mutex);
++		mutex_unlock(&dev->class->p->mutex);
+ 	}
+ 	device_remove_file(dev, &uevent_attr);
+ 	device_remove_attrs(dev);
+diff --git a/drivers/base/init.c b/drivers/base/init.c
+index c8a934e..c16f0b8 100644
+--- a/drivers/base/init.c
++++ b/drivers/base/init.c
+@@ -31,7 +31,6 @@ void __init driver_init(void)
+ 	 * core core pieces.
+ 	 */
+ 	platform_bus_init();
+-	system_bus_init();
+ 	cpu_dev_init();
+ 	memory_dev_init();
+ }
+diff --git a/drivers/base/sys.c b/drivers/base/sys.c
+index 9dff77b..409f5ce 100644
+--- a/drivers/base/sys.c
++++ b/drivers/base/sys.c
+@@ -126,7 +126,7 @@ void sysdev_class_remove_file(struct sysdev_class *c,
+ }
+ EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
+ 
+-static struct kset *system_kset;
++extern struct kset *system_kset;
+ 
+ int sysdev_class_register(struct sysdev_class *cls)
+ {
+@@ -331,14 +331,6 @@ void sysdev_unregister(struct sys_device *sysdev)
+ EXPORT_SYMBOL_GPL(sysdev_register);
+ EXPORT_SYMBOL_GPL(sysdev_unregister);
+ 
+-int __init system_bus_init(void)
+-{
+-	system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
+-	if (!system_kset)
+-		return -ENOMEM;
+-	return 0;
+-}
+-
+ #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
+ 
+ ssize_t sysdev_store_ulong(struct sys_device *sysdev,
+diff --git a/include/linux/device.h b/include/linux/device.h
+index 341fb74..7f9fc15 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -53,6 +53,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
+  * struct bus_type - The bus type of the device
+  *
+  * @name:	The name of the bus.
++ * @dev_name:	Used for subsystems to enumerate devices like ("foo%u", dev->id).
++ * @dev_root:	Default device to use as the parent.
+  * @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.
+@@ -86,6 +88,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
+  */
+ struct bus_type {
+ 	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;
+@@ -106,12 +110,30 @@ struct bus_type {
+ 	struct subsys_private *p;
+ };
+ 
+-extern int __must_check bus_register(struct bus_type *bus);
++/* This is a #define to keep the compiler from merging different
++ * instances of the __key variable */
++#define bus_register(subsys)			\
++({						\
++	static struct lock_class_key __key;	\
++	__bus_register(subsys, &__key);	\
++})
++extern int __must_check __bus_register(struct bus_type *bus,
++				       struct lock_class_key *key);
+ extern void bus_unregister(struct bus_type *bus);
+ 
+ extern int __must_check bus_rescan_devices(struct bus_type *bus);
+ 
+ /* iterator helpers for buses */
++struct subsys_dev_iter {
++	struct klist_iter		ki;
++	const struct device_type	*type;
++};
++void subsys_dev_iter_init(struct subsys_dev_iter *iter,
++			 struct bus_type *subsys,
++			 struct device *start,
++			 const struct device_type *type);
++struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
++void subsys_dev_iter_exit(struct subsys_dev_iter *iter);
+ 
+ int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
+ 		     int (*fn)(struct device *dev, void *data));
+@@ -121,10 +143,10 @@ struct device *bus_find_device(struct bus_type *bus, struct device *start,
+ struct device *bus_find_device_by_name(struct bus_type *bus,
+ 				       struct device *start,
+ 				       const char *name);
+-
++struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id,
++					struct device *hint);
+ int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
+ 		     void *data, int (*fn)(struct device_driver *, void *));
+-
+ void bus_sort_breadthfirst(struct bus_type *bus,
+ 			   int (*compare)(const struct device *a,
+ 					  const struct device *b));
+@@ -256,6 +278,33 @@ struct device *driver_find_device(struct device_driver *drv,
+ 				  int (*match)(struct device *dev, void *data));
+ 
+ /**
++ * struct subsys_interface - interfaces to device functions
++ * @name        name of the device function
++ * @subsystem   subsytem of the devices to attach to
++ * @node        the list of functions registered at the subsystem
++ * @add         device hookup to device function handler
++ * @remove      device hookup to device function handler
++ *
++ * Simple interfaces attached to a subsystem. Multiple interfaces can
++ * attach to a subsystem and its devices. Unlike drivers, they do not
++ * exclusively claim or control devices. Interfaces usually represent
++ * a specific functionality of a subsystem/class of devices.
++ */
++struct subsys_interface {
++	const char *name;
++	struct bus_type *subsys;
++	struct list_head node;
++	int (*add_dev)(struct device *dev, struct subsys_interface *sif);
++	int (*remove_dev)(struct device *dev, struct subsys_interface *sif);
++};
++
++int subsys_interface_register(struct subsys_interface *sif);
++void subsys_interface_unregister(struct subsys_interface *sif);
++
++int subsys_system_register(struct bus_type *subsys,
++			   const struct attribute_group **groups);
++
++/**
+  * struct class - device classes
+  * @name:	Name of the class.
+  * @owner:	The module owner.
+@@ -438,8 +487,28 @@ struct device_attribute {
+ 			 const char *buf, size_t count);
+ };
+ 
++struct dev_ext_attribute {
++	struct device_attribute attr;
++	void *var;
++};
++
++ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr,
++			  char *buf);
++ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr,
++			   const char *buf, size_t count);
++ssize_t device_show_int(struct device *dev, struct device_attribute *attr,
++			char *buf);
++ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
++			 const char *buf, size_t count);
++
+ #define DEVICE_ATTR(_name, _mode, _show, _store) \
+-struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
++	struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
++#define DEVICE_ULONG_ATTR(_name, _mode, _var) \
++	struct dev_ext_attribute dev_attr_##_name = \
++		{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
++#define DEVICE_INT_ATTR(_name, _mode, _var) \
++	struct dev_ext_attribute dev_attr_##_name = \
++		{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
+ 
+ extern int __must_check device_create_file(struct device *device,
+ 					const struct device_attribute *entry);
+@@ -603,6 +672,7 @@ struct device {
+ 	struct device_node	*of_node; /* associated device tree node */
+ 
+ 	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
++	u32			id;	/* device instance */
+ 
+ 	spinlock_t		devres_lock;
+ 	struct list_head	devres_head;

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/intel-idle-convert-to-x86_cpu_id-auto-probing.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/intel-idle-convert-to-x86_cpu_id-auto-probing.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,196 @@
+From: Andi Kleen <ak at linux.intel.com>
+Date: Thu, 26 Jan 2012 00:09:07 +0100
+Subject: intel-idle: convert to x86_cpu_id auto probing
+
+commit b66b8b9a4a79087dde1b358a016e5c8739ccf186 upstream.
+
+With this it should be automatically loaded on suitable systems by
+udev.
+
+The old switch () is replaced with a table based approach, this
+also cleans up the code.
+
+Cc: Len Brown <lenb at kernel.org>
+Signed-off-by: Andi Kleen <ak at linux.intel.com>
+Signed-off-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+[bwh: Backported to 3.2: one less instance of auto_demotion_disable_flags]
+---
+ drivers/idle/intel_idle.c |  116 ++++++++++++++++++++++++++-------------------
+ 1 file changed, 66 insertions(+), 50 deletions(-)
+
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -62,6 +62,7 @@
+ #include <linux/notifier.h>
+ #include <linux/cpu.h>
+ #include <linux/module.h>
++#include <asm/cpu_device_id.h>
+ #include <asm/mwait.h>
+ #include <asm/msr.h>
+ 
+@@ -81,6 +82,17 @@
+ /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
+ static unsigned int lapic_timer_reliable_states = (1 << 1);	 /* Default to only C1 */
+ 
++struct idle_cpu {
++	struct cpuidle_state *state_table;
++
++	/*
++	 * Hardware C-state auto-demotion may not always be optimal.
++	 * Indicate which enable bits to clear here.
++	 */
++	unsigned long auto_demotion_disable_flags;
++};
++
++static const struct idle_cpu *icpu;
+ static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
+ static int intel_idle(struct cpuidle_device *dev,
+ 			struct cpuidle_driver *drv, int index);
+@@ -88,12 +100,6 @@
+ static struct cpuidle_state *cpuidle_state_table;
+ 
+ /*
+- * Hardware C-state auto-demotion may not always be optimal.
+- * Indicate which enable bits to clear here.
+- */
+-static unsigned long long auto_demotion_disable_flags;
+-
+-/*
+  * Set this flag for states where the HW flushes the TLB for us
+  * and so we don't need cross-calls to keep it consistent.
+  * If this flag is set, SW flushes the TLB, so even if the
+@@ -320,27 +326,72 @@
+ 	unsigned long long msr_bits;
+ 
+ 	rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+-	msr_bits &= ~auto_demotion_disable_flags;
++	msr_bits &= ~(icpu->auto_demotion_disable_flags);
+ 	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+ }
+ 
++static const struct idle_cpu idle_cpu_nehalem = {
++	.state_table = nehalem_cstates,
++};
++
++static const struct idle_cpu idle_cpu_westmere = {
++	.state_table = nehalem_cstates,
++	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
++};
++
++static const struct idle_cpu idle_cpu_atom = {
++	.state_table = atom_cstates,
++};
++
++static const struct idle_cpu idle_cpu_lincroft = {
++	.state_table = atom_cstates,
++	.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
++};
++
++static const struct idle_cpu idle_cpu_snb = {
++	.state_table = snb_cstates,
++};
++
++#define ICPU(model, cpu) \
++	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
++
++static const struct x86_cpu_id intel_idle_ids[] = {
++	ICPU(0x1a, idle_cpu_nehalem),
++	ICPU(0x1e, idle_cpu_nehalem),
++	ICPU(0x1f, idle_cpu_nehalem),
++	ICPU(0x25, idle_cpu_westmere),
++	ICPU(0x2c, idle_cpu_westmere),
++	ICPU(0x2f, idle_cpu_westmere),
++	ICPU(0x1c, idle_cpu_atom),
++	ICPU(0x26, idle_cpu_lincroft),
++	ICPU(0x2f, idle_cpu_westmere),
++	ICPU(0x2a, idle_cpu_snb),
++	ICPU(0x2d, idle_cpu_snb),
++	{}
++};
++MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
++
+ /*
+  * intel_idle_probe()
+  */
+ static int intel_idle_probe(void)
+ {
+ 	unsigned int eax, ebx, ecx;
++	const struct x86_cpu_id *id;
+ 
+ 	if (max_cstate == 0) {
+ 		pr_debug(PREFIX "disabled\n");
+ 		return -EPERM;
+ 	}
+ 
+-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+-		return -ENODEV;
+-
+-	if (!boot_cpu_has(X86_FEATURE_MWAIT))
++	id = x86_match_cpu(intel_idle_ids);
++	if (!id) {
++		if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
++		    boot_cpu_data.x86 == 6)
++			pr_debug(PREFIX "does not run on family %d model %d\n",
++				boot_cpu_data.x86, boot_cpu_data.x86_model);
+ 		return -ENODEV;
++	}
+ 
+ 	if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+ 		return -ENODEV;
+@@ -354,43 +405,8 @@
+ 
+ 	pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
+ 
+-
+-	if (boot_cpu_data.x86 != 6)	/* family 6 */
+-		return -ENODEV;
+-
+-	switch (boot_cpu_data.x86_model) {
+-
+-	case 0x1A:	/* Core i7, Xeon 5500 series */
+-	case 0x1E:	/* Core i7 and i5 Processor - Lynnfield Jasper Forest */
+-	case 0x1F:	/* Core i7 and i5 Processor - Nehalem */
+-	case 0x2E:	/* Nehalem-EX Xeon */
+-	case 0x2F:	/* Westmere-EX Xeon */
+-	case 0x25:	/* Westmere */
+-	case 0x2C:	/* Westmere */
+-		cpuidle_state_table = nehalem_cstates;
+-		auto_demotion_disable_flags =
+-			(NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE);
+-		break;
+-
+-	case 0x1C:	/* 28 - Atom Processor */
+-		cpuidle_state_table = atom_cstates;
+-		break;
+-
+-	case 0x26:	/* 38 - Lincroft Atom Processor */
+-		cpuidle_state_table = atom_cstates;
+-		auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE;
+-		break;
+-
+-	case 0x2A:	/* SNB */
+-	case 0x2D:	/* SNB Xeon */
+-		cpuidle_state_table = snb_cstates;
+-		break;
+-
+-	default:
+-		pr_debug(PREFIX "does not run on family %d model %d\n",
+-			boot_cpu_data.x86, boot_cpu_data.x86_model);
+-		return -ENODEV;
+-	}
++	icpu = (const struct idle_cpu *)id->driver_data;
++	cpuidle_state_table = icpu->state_table;
+ 
+ 	if (boot_cpu_has(X86_FEATURE_ARAT))	/* Always Reliable APIC Timer */
+ 		lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
+@@ -471,7 +487,7 @@
+ 		drv->state_count += 1;
+ 	}
+ 
+-	if (auto_demotion_disable_flags)
++	if (icpu->auto_demotion_disable_flags)
+ 		on_each_cpu(auto_demotion_disable, NULL, 1);
+ 
+ 	return 0;

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/intel_idle-Fix-ID-for-Nehalem-EX-Xeon-in-device-ID-t.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/intel_idle-Fix-ID-for-Nehalem-EX-Xeon-in-device-ID-t.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,32 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 11 Feb 2012 22:57:38 +0000
+Subject: intel_idle: Fix ID for Nehalem-EX Xeon in device ID table
+
+commit e668505c9811411c6096888b43ba104f35c9e9c3 upstream.
+
+Commit b66b8b9a4a79087dde1b358a016e5c8739ccf186 ('intel-idle: convert
+to x86_cpu_id auto probing') put two entries for model 0x2f
+(Westmere-EX Xeon) in the device ID table and left out model 0x2e
+(Nehalem-EX Xeon).
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Acked-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/idle/intel_idle.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
+index 237fe57..a238649 100644
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -360,7 +360,7 @@ static const struct x86_cpu_id intel_idle_ids[] = {
+ 	ICPU(0x1f, idle_cpu_nehalem),
+ 	ICPU(0x25, idle_cpu_westmere),
+ 	ICPU(0x2c, idle_cpu_westmere),
+-	ICPU(0x2f, idle_cpu_westmere),
++	ICPU(0x2e, idle_cpu_westmere),
+ 	ICPU(0x1c, idle_cpu_atom),
+ 	ICPU(0x26, idle_cpu_lincroft),
+ 	ICPU(0x2f, idle_cpu_westmere),

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/intel_idle-Revert-change-of-auto_demotion_disable_fl.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/intel_idle-Revert-change-of-auto_demotion_disable_fl.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,52 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Thu, 16 Feb 2012 04:13:14 +0000
+Subject: intel_idle: Revert change of auto_demotion_disable_flags for Nehalem
+
+commit 8bf11938459ff8ceb8643258d0a35e0f2bc9be17 upstream.
+
+Commit b66b8b9a4a79087dde1b358a016e5c8739ccf186 ('intel-idle: convert
+to x86_cpu_id auto probing') added a distinction between Nehalem and
+Westemere processors and changed auto_demotion_disable_flags for the
+former to 0.  This was not explained in the commit message, so change
+it back.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Acked-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/idle/intel_idle.c |   12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
+index a238649..1c15e9b 100644
+--- a/drivers/idle/intel_idle.c
++++ b/drivers/idle/intel_idle.c
+@@ -331,10 +331,6 @@ static void auto_demotion_disable(void *dummy)
+ 
+ static const struct idle_cpu idle_cpu_nehalem = {
+ 	.state_table = nehalem_cstates,
+-};
+-
+-static const struct idle_cpu idle_cpu_westmere = {
+-	.state_table = nehalem_cstates,
+ 	.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
+ };
+ 
+@@ -358,12 +354,12 @@ static const struct x86_cpu_id intel_idle_ids[] = {
+ 	ICPU(0x1a, idle_cpu_nehalem),
+ 	ICPU(0x1e, idle_cpu_nehalem),
+ 	ICPU(0x1f, idle_cpu_nehalem),
+-	ICPU(0x25, idle_cpu_westmere),
+-	ICPU(0x2c, idle_cpu_westmere),
+-	ICPU(0x2e, idle_cpu_westmere),
++	ICPU(0x25, idle_cpu_nehalem),
++	ICPU(0x2c, idle_cpu_nehalem),
++	ICPU(0x2e, idle_cpu_nehalem),
+ 	ICPU(0x1c, idle_cpu_atom),
+ 	ICPU(0x26, idle_cpu_lincroft),
+-	ICPU(0x2f, idle_cpu_westmere),
++	ICPU(0x2f, idle_cpu_nehalem),
+ 	ICPU(0x2a, idle_cpu_snb),
+ 	ICPU(0x2d, idle_cpu_snb),
+ 	{}

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/powernow-k6-Really-enable-auto-loading.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/powernow-k6-Really-enable-auto-loading.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,31 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 11 Feb 2012 23:04:12 +0000
+Subject: powernow-k6: Really enable auto-loading
+
+commit b4d2d23148b446f6853e711eb31c533c7385eba5 upstream.
+
+Commit fa8031aefec0cf7ea6c2387c93610d99d9659aa2 ('cpufreq: Add support
+for x86 cpuinfo auto loading v4') added a device ID table to this
+driver, but didn't declare it as the module device ID table.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Acked-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/cpufreq/powernow-k6.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
+index 54dd031..af23e0b 100644
+--- a/drivers/cpufreq/powernow-k6.c
++++ b/drivers/cpufreq/powernow-k6.c
+@@ -216,7 +216,7 @@ static const struct x86_cpu_id powernow_k6_ids[] = {
+ 	{ X86_VENDOR_AMD, 5, 13 },
+ 	{}
+ };
+-
++MODULE_DEVICE_TABLE(x86cpu, powernow_k6_ids);
+ 
+ /**
+  * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/powernow-k7-Fix-CPU-family-number.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/powernow-k7-Fix-CPU-family-number.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,31 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 11 Feb 2012 22:58:14 +0000
+Subject: powernow-k7: Fix CPU family number
+
+commit 30bcfff9bd41db5edab6420d0ae2e435609eb083 upstream.
+
+Commit fa8031aefec0cf7ea6c2387c93610d99d9659aa2 ('cpufreq: Add support
+for x86 cpuinfo auto loading v4') seems to have inadvertently changed
+the matched CPU family number from 6 to 7.  Change it back.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Acked-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ drivers/cpufreq/powernow-k7.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
+index 501d167..cf7e1ee 100644
+--- a/drivers/cpufreq/powernow-k7.c
++++ b/drivers/cpufreq/powernow-k7.c
+@@ -112,7 +112,7 @@ static int check_fsb(unsigned int fsbspeed)
+ }
+ 
+ static const struct x86_cpu_id powernow_k7_cpuids[] = {
+-	{ X86_VENDOR_AMD, 7, },
++	{ X86_VENDOR_AMD, 6, },
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,44 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Thu, 24 Nov 2011 07:04:39 +0000
+Subject: [PATCH] topology: Provide CPU topology in sysfs in !SMP
+ configurations
+
+commit ccbc60d3e19a1b6ae66ca0d89b3da02dde62088b upstream.
+
+We should provide topology information to userland even if it's not
+very interesting.  The current code appears to work properly for !SMP
+(tested on i386).
+
+Reference: http://bugs.debian.org/649216
+Reported-by: Marcus Osdoba <marcus.osdoba at googlemail.com>
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+ drivers/base/Makefile |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/base/Makefile b/drivers/base/Makefile
+index 99a375a..1334d89 100644
+--- a/drivers/base/Makefile
++++ b/drivers/base/Makefile
+@@ -3,7 +3,8 @@
+ obj-y			:= core.o sys.o bus.o dd.o syscore.o \
+ 			   driver.o class.o platform.o \
+ 			   cpu.o firmware.o init.o map.o devres.o \
+-			   attribute_container.o transport_class.o
++			   attribute_container.o transport_class.o \
++			   topology.o
+ obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
+ obj-y			+= power/
+ obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
+@@ -12,7 +13,6 @@ obj-$(CONFIG_ISA)	+= isa.o
+ obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
+ obj-$(CONFIG_NUMA)	+= node.o
+ obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
+-obj-$(CONFIG_SMP)	+= topology.o
+ ifeq ($(CONFIG_SYSFS),y)
+ obj-$(CONFIG_MODULES)	+= module.o
+ endif
+-- 
+1.7.7.3
+

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/x86-cpu-Clean-up-modalias-feature-matching.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/x86-cpu-Clean-up-modalias-feature-matching.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,57 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 11 Feb 2012 22:57:19 +0000
+Subject: x86/cpu: Clean up modalias feature matching
+
+commit 5467bdda4a326513c2f14b712a22d59115b7ae94 upstream.
+
+We currently include commas on both sides of the feature ID in a
+modalias, but this prevents the lowest numbered feature of a CPU from
+being matched.  Since all feature IDs have the same length, we do not
+need to worry about substring matches, so omit commas from the
+modalias entirely.
+
+Avoid generating multiple adjacent wildcards when there is no
+feature ID to match.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Acked-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/match.c |    3 +--
+ scripts/mod/file2alias.c    |    5 +++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/x86/kernel/cpu/match.c
++++ b/arch/x86/kernel/cpu/match.c
+@@ -63,7 +63,7 @@
+ 		boot_cpu_data.x86_model);
+ 	size -= n;
+ 	buf += n;
+-	size -= 2;
++	size -= 1;
+ 	for (i = 0; i < NCAPINTS*32; i++) {
+ 		if (boot_cpu_has(i)) {
+ 			n = snprintf(buf, size, ",%04X", i);
+@@ -75,7 +75,6 @@
+ 			buf += n;
+ 		}
+ 	}
+-	*buf++ = ',';
+ 	*buf++ = '\n';
+ 	return buf - bufptr;
+ }
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -898,8 +898,9 @@
+ 	ADD(alias, "vendor:",  id->vendor != X86_VENDOR_ANY, id->vendor);
+ 	ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family);
+ 	ADD(alias, ":model:",  id->model  != X86_MODEL_ANY,  id->model);
+-	ADD(alias, ":feature:*,", id->feature != X86_FEATURE_ANY, id->feature);
+-	strcat(alias, ",*");
++	strcat(alias, ":feature:*");
++	if (id->feature != X86_FEATURE_ANY)
++		sprintf(alias + strlen(alias), "%04X*", id->feature);
+ 	return 1;
+ }
+ 

Added: dists/sid/linux/debian/patches/features/all/cpu-devices/x86-cpu-Fix-overrun-check-in-arch_print_cpu_modalias.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/cpu-devices/x86-cpu-Fix-overrun-check-in-arch_print_cpu_modalias.patch	Mon Jun 18 05:14:25 2012	(r19164)
@@ -0,0 +1,29 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 11 Feb 2012 22:56:59 +0000
+Subject: x86/cpu: Fix overrun check in arch_print_cpu_modalias()
+
+commit 70142a9dd154f54f7409871ead86f7d77f2c6576 upstream.
+
+snprintf() does not return a negative value when truncating.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Acked-by: Thomas Renninger <trenn at suse.de>
+Acked-by: H. Peter Anvin <hpa at zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/match.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
+index 940e2d4..2dfa52b 100644
+--- a/arch/x86/kernel/cpu/match.c
++++ b/arch/x86/kernel/cpu/match.c
+@@ -67,7 +67,7 @@ ssize_t arch_print_cpu_modalias(struct device *dev,
+ 	for (i = 0; i < NCAPINTS*32; i++) {
+ 		if (boot_cpu_has(i)) {
+ 			n = snprintf(buf, size, ",%04X", i);
+-			if (n < 0) {
++			if (n >= size) {
+ 				WARN(1, "x86 features overflow page\n");
+ 				break;
+ 			}

Modified: dists/sid/linux/debian/patches/series
==============================================================================
--- dists/sid/linux/debian/patches/series	Sun Jun 17 19:52:06 2012	(r19163)
+++ dists/sid/linux/debian/patches/series	Mon Jun 18 05:14:25 2012	(r19164)
@@ -47,9 +47,6 @@
 
 bugfix/all/0004-media-staging-lirc_serial-Fix-bogus-error-codes.patch
 
-features/all/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch
-bugfix/all/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch
-bugfix/all/cpu-Register-a-generic-CPU-device-on-architectures-t.patch
 debian/x86-memtest-WARN-if-bad-RAM-found.patch
 bugfix/all/snapshot-Implement-compat_ioctl.patch
 debian/ARM-Remove-use-of-possibly-undefined-BUILD_BUG_ON-in.patch
@@ -327,3 +324,28 @@
 
 bugfix/all/KVM-Fix-buffer-overflow-in-kvm_set_irq.patch
 bugfix/all/ethtool-allow-ETHTOOL_GSSET_INFO-for-users.patch
+
+# CPU sysdev removal from 3.3 and x86 CPU auto-loading from 3.4
+features/all/cpu-devices/driver-core-implement-sysdev-functionality-for-regul.patch
+features/all/cpu-devices/cpu-convert-cpu-and-machinecheck-sysdev_class-to-a-r.patch
+features/all/cpu-devices/topology-Provide-CPU-topology-in-sysfs-in-SMP-configura.patch
+features/all/cpu-devices/cpu-Do-not-return-errors-from-cpu_dev_init-which-wil.patch
+features/all/cpu-devices/cpu-Register-a-generic-CPU-device-on-architectures-t.patch
+features/all/cpu-devices/Add-driver-auto-probing-for-x86-features-v4.patch
+features/all/cpu-devices/CPU-Introduce-ARCH_HAS_CPU_AUTOPROBE-and-X86-parts.patch
+features/all/cpu-devices/driver-core-cpu-remove-kernel-warning-when-removing-.patch
+features/all/cpu-devices/driver-core-cpu-fix-kobject-warning-when-hotplugging.patch
+features/all/cpu-devices/crypto-Add-support-for-x86-cpuid-auto-loading-for-x8.patch
+features/all/cpu-devices/intel-idle-convert-to-x86_cpu_id-auto-probing.patch
+features/all/cpu-devices/ACPI-Load-acpi-cpufreq-from-processor-driver-automat.patch
+features/all/cpu-devices/HWMON-Convert-via-cputemp-to-x86-cpuid-autoprobing.patch
+features/all/cpu-devices/HWMON-Convert-coretemp-to-x86-cpuid-autoprobing.patch
+features/all/cpu-devices/X86-Introduce-HW-Pstate-scattered-cpuid-feature.patch
+features/all/cpu-devices/cpufreq-Add-support-for-x86-cpuinfo-auto-loading-v4.patch
+features/all/cpu-devices/x86-cpu-Fix-overrun-check-in-arch_print_cpu_modalias.patch
+features/all/cpu-devices/x86-cpu-Clean-up-modalias-feature-matching.patch
+features/all/cpu-devices/intel_idle-Fix-ID-for-Nehalem-EX-Xeon-in-device-ID-t.patch
+features/all/cpu-devices/powernow-k7-Fix-CPU-family-number.patch
+features/all/cpu-devices/powernow-k6-Really-enable-auto-loading.patch
+features/all/cpu-devices/intel_idle-Revert-change-of-auto_demotion_disable_fl.patch
+features/all/cpu-devices/Partially-revert-cpufreq-Add-support-for-x86-cpuinfo.patch



More information about the Kernel-svn-changes mailing list