summary refs log tree commit diff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-16 12:40:26 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-16 12:40:26 -0700
commitc813b4e16ead3c3df98ac84419d4df2adf33fe01 (patch)
tree2ca4a5b6966d833b6149e3dda7a4e85d1255779c
parentc8d8a2321f9c4ee18fbcc399fdc2a77e580a03b9 (diff)
parent02683ffdf655b4ae15245376ba6fea6d9e5829a6 (diff)
downloadlinux-c813b4e16ead3c3df98ac84419d4df2adf33fe01.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (46 commits)
  UIO: Fix mapping of logical and virtual memory
  UIO: add automata sercos3 pci card support
  UIO: Change driver name of uio_pdrv
  UIO: Add alignment warnings for uio-mem
  Driver core: add bus_sort_breadthfirst() function
  NET: convert the phy_device file to use bus_find_device_by_name
  kobject: Cleanup kobject_rename and !CONFIG_SYSFS
  kobject: Fix kobject_rename and !CONFIG_SYSFS
  sysfs: Make dir and name args to sysfs_notify() const
  platform: add new device registration helper
  sysfs: use ilookup5() instead of ilookup5_nowait()
  PNP: create device attributes via default device attributes
  Driver core: make bus_find_device_by_name() more robust
  usb: turn dev_warn+WARN_ON combos into dev_WARN
  debug: use dev_WARN() rather than WARN_ON() in device_pm_add()
  debug: Introduce a dev_WARN() function
  sysfs: fix deadlock
  device model: Do a quickcheck for driver binding before doing an expensive check
  Driver core: Fix cleanup in device_create_vargs().
  Driver core: Clarify device cleanup.
  ...
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--Documentation/kobject.txt4
-rw-r--r--arch/mips/kernel/rtlx.c4
-rw-r--r--arch/mips/sibyte/common/sb_tbprof.c3
-rw-r--r--arch/x86/kernel/cpuid.c4
-rw-r--r--arch/x86/kernel/dumpstack_32.c2
-rw-r--r--arch/x86/kernel/dumpstack_64.c2
-rw-r--r--arch/x86/kernel/msr.c4
-rw-r--r--block/bsg.c3
-rw-r--r--drivers/base/bus.c54
-rw-r--r--drivers/base/core.c30
-rw-r--r--drivers/base/dd.c3
-rw-r--r--drivers/base/platform.c49
-rw-r--r--drivers/base/power/main.c2
-rw-r--r--drivers/block/aoe/aoechr.c6
-rw-r--r--drivers/block/paride/pg.c5
-rw-r--r--drivers/block/paride/pt.c10
-rw-r--r--drivers/block/pktcdvd.c5
-rw-r--r--drivers/char/bsr.c5
-rw-r--r--drivers/char/dsp56k.c4
-rw-r--r--drivers/char/ip2/ip2main.c12
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c2
-rw-r--r--drivers/char/istallion.c5
-rw-r--r--drivers/char/lp.c4
-rw-r--r--drivers/char/mem.c6
-rw-r--r--drivers/char/misc.c4
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c2
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c3
-rw-r--r--drivers/char/ppdev.c5
-rw-r--r--drivers/char/raw.c7
-rw-r--r--drivers/char/snsc.c4
-rw-r--r--drivers/char/stallion.c4
-rw-r--r--drivers/char/tty_io.c2
-rw-r--r--drivers/char/vc_screen.c12
-rw-r--r--drivers/char/viotape.c8
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c3
-rw-r--r--drivers/dca/dca-sysfs.c8
-rw-r--r--drivers/firmware/iscsi_ibft.c18
-rw-r--r--drivers/hid/hidraw.c5
-rw-r--r--drivers/hwmon/hwmon.c4
-rw-r--r--drivers/i2c/i2c-dev.c6
-rw-r--r--drivers/ide/ide-probe.c4
-rw-r--r--drivers/ide/ide-tape.c11
-rw-r--r--drivers/ieee1394/dv1394.c8
-rw-r--r--drivers/ieee1394/raw1394.c8
-rw-r--r--drivers/ieee1394/video1394.c5
-rw-r--r--drivers/infiniband/core/cm.c6
-rw-r--r--drivers/infiniband/core/user_mad.c12
-rw-r--r--drivers/infiniband/core/uverbs_main.c9
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c2
-rw-r--r--drivers/isdn/capi/capi.c3
-rw-r--r--drivers/leds/led-class.c4
-rw-r--r--drivers/macintosh/adb.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c2
-rw-r--r--drivers/misc/phantom.c6
-rw-r--r--drivers/mtd/mtdchar.c10
-rw-r--r--drivers/net/phy/phy_device.c8
-rw-r--r--drivers/net/ppp_generic.c4
-rw-r--r--drivers/net/wan/cosa.c4
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c6
-rw-r--r--drivers/pci/probe.c50
-rw-r--r--drivers/pnp/base.h2
-rw-r--r--drivers/pnp/core.c10
-rw-r--r--drivers/pnp/driver.c1
-rw-r--r--drivers/pnp/interface.c37
-rw-r--r--drivers/power/power_supply_core.c4
-rw-r--r--drivers/s390/char/raw3270.c14
-rw-r--r--drivers/s390/char/tape_class.c6
-rw-r--r--drivers/s390/char/vmlogrdr.c8
-rw-r--r--drivers/s390/char/vmur.c5
-rw-r--r--drivers/scsi/ch.c6
-rw-r--r--drivers/scsi/dpt_i2o.c2
-rw-r--r--drivers/scsi/osst.c3
-rw-r--r--drivers/scsi/sg.c10
-rw-r--r--drivers/scsi/st.c11
-rw-r--r--drivers/spi/spidev.c7
-rw-r--r--drivers/uio/Kconfig13
-rw-r--r--drivers/uio/Makefile1
-rw-r--r--drivers/uio/uio.c26
-rw-r--r--drivers/uio/uio_pdrv.c2
-rw-r--r--drivers/uio/uio_sercos3.c243
-rw-r--r--drivers/usb/core/devio.c6
-rw-r--r--drivers/usb/core/file.c6
-rw-r--r--drivers/usb/core/hcd.c5
-rw-r--r--drivers/usb/gadget/Makefile23
-rw-r--r--drivers/usb/gadget/cdc2.c25
-rw-r--r--drivers/usb/gadget/ether.c28
-rw-r--r--drivers/usb/gadget/f_ecm.c108
-rw-r--r--drivers/usb/gadget/f_loopback.c34
-rw-r--r--drivers/usb/gadget/f_subset.c44
-rw-r--r--drivers/usb/gadget/file_storage.c12
-rw-r--r--drivers/usb/gadget/gmidi.c15
-rw-r--r--drivers/usb/gadget/printer.c18
-rw-r--r--drivers/usb/gadget/rndis.c115
-rw-r--r--drivers/usb/gadget/serial.c18
-rw-r--r--drivers/usb/gadget/u_ether.c4
-rw-r--r--drivers/usb/gadget/zero.c17
-rw-r--r--drivers/usb/host/uhci-q.c24
-rw-r--r--drivers/usb/misc/phidgetkit.c5
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c5
-rw-r--r--drivers/usb/misc/phidgetservo.c5
-rw-r--r--drivers/usb/mon/mon_bin.c6
-rw-r--r--drivers/video/console/fbcon.c4
-rw-r--r--drivers/video/display/display-sysfs.c9
-rw-r--r--drivers/video/fbmem.c5
-rw-r--r--fs/coda/psdev.c5
-rw-r--r--fs/sysfs/bin.c42
-rw-r--r--fs/sysfs/dir.c24
-rw-r--r--fs/sysfs/file.c46
-rw-r--r--fs/sysfs/mount.c15
-rw-r--r--fs/sysfs/sysfs.h6
-rw-r--r--include/asm-generic/vmlinux.lds.h10
-rw-r--r--include/linux/device.h18
-rw-r--r--include/linux/dynamic_printk.h93
-rw-r--r--include/linux/kernel.h7
-rw-r--r--include/linux/module.h1
-rw-r--r--include/linux/platform_device.h2
-rw-r--r--include/linux/sysfs.h36
-rw-r--r--kernel/module.c33
-rw-r--r--lib/Kconfig.debug55
-rw-r--r--lib/Makefile2
-rw-r--r--lib/dynamic_printk.c418
-rw-r--r--lib/kobject.c35
-rw-r--r--net/netfilter/nf_conntrack_pptp.c2
-rw-r--r--scripts/Makefile.lib11
-rw-r--r--scripts/basic/Makefile2
-rw-r--r--scripts/basic/hash.c64
-rw-r--r--sound/core/init.c6
-rw-r--r--sound/core/sound.c5
-rw-r--r--sound/oss/soundcard.c15
-rw-r--r--sound/sound_core.c5
131 files changed, 1786 insertions, 617 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 82c561f3abbd..dd28a0d56981 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1714,6 +1714,11 @@ and is between 256 and 4096 characters. It is defined in the file
 			autoconfiguration.
 			Ranges are in pairs (memory base and size).
 
+	dynamic_printk
+			Enables pr_debug()/dev_dbg() calls if
+			CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. These can also
+			be switched on/off via <debugfs>/dynamic_printk/modules
+
 	print-fatal-signals=
 			[KNL] debug: print fatal signals
 			print-fatal-signals=1: print segfault info to
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index 51a8021ee532..f5d2aad65a67 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -118,6 +118,10 @@ the name of the kobject, call kobject_rename():
 
     int kobject_rename(struct kobject *kobj, const char *new_name);
 
+Note kobject_rename does perform any locking or have a solid notion of
+what names are valid so the provide must provide their own sanity checking
+and serialization.
+
 There is a function called kobject_set_name() but that is legacy cruft and
 is being removed.  If your code needs to call this function, it is
 incorrect and needs to be fixed.
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index dfd868b68364..4ce93aa7b372 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -522,8 +522,8 @@ static int __init rtlx_module_init(void)
 		atomic_set(&channel_wqs[i].in_open, 0);
 		mutex_init(&channel_wqs[i].mutex);
 
-		dev = device_create_drvdata(mt_class, NULL, MKDEV(major, i),
-					    NULL, "%s%d", module_name, i);
+		dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
+				    "%s%d", module_name, i);
 		if (IS_ERR(dev)) {
 			err = PTR_ERR(dev);
 			goto out_chrdev;
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index 66e3e3fb311f..637a194e5cd5 100644
--- a/arch/mips/sibyte/common/sb_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -576,8 +576,7 @@ static int __init sbprof_tb_init(void)
 
 	tb_class = tbc;
 
-	dev = device_create_drvdata(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0),
-				    NULL, "tb");
+	dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), NULL, "tb");
 	if (IS_ERR(dev)) {
 		err = PTR_ERR(dev);
 		goto out_class;
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index 6a44d6465991..72cefd1e649b 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -147,8 +147,8 @@ static __cpuinit int cpuid_device_create(int cpu)
 {
 	struct device *dev;
 
-	dev = device_create_drvdata(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu),
-				    NULL, "cpu%d", cpu);
+	dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL,
+			    "cpu%d", cpu);
 	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index 201ee359a1a9..1a78180f08d3 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -13,6 +13,7 @@
 #include <linux/kexec.h>
 #include <linux/bug.h>
 #include <linux/nmi.h>
+#include <linux/sysfs.h>
 
 #include <asm/stacktrace.h>
 
@@ -343,6 +344,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
 	printk("DEBUG_PAGEALLOC");
 #endif
 	printk("\n");
+	sysfs_printk_last_file();
 	if (notify_die(DIE_OOPS, str, regs, err,
 			current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
 		return 1;
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 086cc8118e39..96a5db7da8a7 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -13,6 +13,7 @@
 #include <linux/kexec.h>
 #include <linux/bug.h>
 #include <linux/nmi.h>
+#include <linux/sysfs.h>
 
 #include <asm/stacktrace.h>
 
@@ -489,6 +490,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
 	printk("DEBUG_PAGEALLOC");
 #endif
 	printk("\n");
+	sysfs_printk_last_file();
 	if (notify_die(DIE_OOPS, str, regs, err,
 			current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
 		return 1;
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 2e2af5d18191..82a7c7ed6d45 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -163,8 +163,8 @@ static int __cpuinit msr_device_create(int cpu)
 {
 	struct device *dev;
 
-	dev = device_create_drvdata(msr_class, NULL, MKDEV(MSR_MAJOR, cpu),
-				    NULL, "msr%d", cpu);
+	dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, cpu), NULL,
+			    "msr%d", cpu);
 	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 
diff --git a/block/bsg.c b/block/bsg.c
index 56cb343c76d8..034112bfe1f3 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -1024,8 +1024,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
 	bcd->release = release;
 	kref_init(&bcd->ref);
 	dev = MKDEV(bsg_major, bcd->minor);
-	class_dev = device_create_drvdata(bsg_class, parent, dev, NULL,
-					  "%s", devname);
+	class_dev = device_create(bsg_class, parent, dev, NULL, "%s", devname);
 	if (IS_ERR(class_dev)) {
 		ret = PTR_ERR(class_dev);
 		goto put_dev;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index ef522ae55480..5aee1c0169ea 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -333,9 +333,7 @@ static int match_name(struct device *dev, void *data)
 {
 	const char *name = data;
 
-	if (strcmp(name, dev->bus_id) == 0)
-		return 1;
-	return 0;
+	return sysfs_streq(name, dev->bus_id);
 }
 
 /**
@@ -982,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
 }
 EXPORT_SYMBOL_GPL(bus_get_device_klist);
 
+/*
+ * Yes, this forcably breaks the klist abstraction temporarily.  It
+ * just wants to sort the klist, not change reference counts and
+ * take/drop locks rapidly in the process.  It does all this while
+ * holding the lock for the list, so objects can't otherwise be
+ * added/removed while we're swizzling.
+ */
+static void device_insertion_sort_klist(struct device *a, struct list_head *list,
+					int (*compare)(const struct device *a,
+							const struct device *b))
+{
+	struct list_head *pos;
+	struct klist_node *n;
+	struct device *b;
+
+	list_for_each(pos, list) {
+		n = container_of(pos, struct klist_node, n_node);
+		b = container_of(n, struct device, knode_bus);
+		if (compare(a, b) <= 0) {
+			list_move_tail(&a->knode_bus.n_node,
+				       &b->knode_bus.n_node);
+			return;
+		}
+	}
+	list_move_tail(&a->knode_bus.n_node, list);
+}
+
+void bus_sort_breadthfirst(struct bus_type *bus,
+			   int (*compare)(const struct device *a,
+					  const struct device *b))
+{
+	LIST_HEAD(sorted_devices);
+	struct list_head *pos, *tmp;
+	struct klist_node *n;
+	struct device *dev;
+	struct klist *device_klist;
+
+	device_klist = bus_get_device_klist(bus);
+
+	spin_lock(&device_klist->k_lock);
+	list_for_each_safe(pos, tmp, &device_klist->k_list) {
+		n = container_of(pos, struct klist_node, n_node);
+		dev = container_of(n, struct device, knode_bus);
+		device_insertion_sort_klist(dev, &sorted_devices, compare);
+	}
+	list_splice(&sorted_devices, &device_klist->k_list);
+	spin_unlock(&device_klist->k_lock);
+}
+EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
+
 int __init buses_init(void)
 {
 	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b98cb1416a2d..8c2cc2648f5a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n)
  * device_initialize - init device structure.
  * @dev: device.
  *
- * This prepares the device for use by other layers,
- * including adding it to the device hierarchy.
+ * This prepares the device for use by other layers by initializing
+ * its fields.
  * It is the first half of device_register(), if called by
- * that, though it can also be called separately, so one
- * may use @dev's fields (e.g. the refcount).
+ * that function, though it can also be called separately, so one
+ * may use @dev's fields. In particular, get_device()/put_device()
+ * may be used for reference counting of @dev after calling this
+ * function.
+ *
+ * NOTE: Use put_device() to give up your reference instead of freeing
+ * @dev directly once you have called this function.
  */
 void device_initialize(struct device *dev)
 {
@@ -835,9 +840,13 @@ static void device_remove_sys_dev_entry(struct device *dev)
  * This is part 2 of device_register(), though may be called
  * separately _iff_ device_initialize() has been called separately.
  *
- * This adds it to the kobject hierarchy via kobject_add(), adds it
+ * This adds @dev to the kobject hierarchy via kobject_add(), adds it
  * to the global and sibling lists for the device, then
  * adds it to the other relevant subsystems of the driver model.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use put_device() to give up your
+ * reference instead.
  */
 int device_add(struct device *dev)
 {
@@ -965,6 +974,10 @@ done:
  * I.e. you should only call the two helpers separately if
  * have a clearly defined need to use and refcount the device
  * before it is added to the hierarchy.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use put_device() to give up the
+ * reference initialized in this function instead.
  */
 int device_register(struct device *dev)
 {
@@ -1243,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
 	return dev;
 
 error:
-	kfree(dev);
+	put_device(dev);
 	return ERR_PTR(retval);
 }
 EXPORT_SYMBOL_GPL(device_create_vargs);
@@ -1314,6 +1327,11 @@ EXPORT_SYMBOL_GPL(device_destroy);
  * device_rename - renames a device
  * @dev: the pointer to the struct device to be renamed
  * @new_name: the new name of the device
+ *
+ * It is the responsibility of the caller to provide mutual
+ * exclusion between two different calls of device_rename
+ * on the same device to ensure that new_name is valid and
+ * won't conflict with other devices.
  */
 int device_rename(struct device *dev, char *new_name)
 {
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 3ac443b2ac08..20febc00a525 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -257,6 +257,9 @@ static int __driver_attach(struct device *dev, void *data)
 	 * is an error.
 	 */
 
+	if (drv->bus->match && !drv->bus->match(dev, drv))
+		return 0;
+
 	if (dev->parent)	/* Needed for USB */
 		down(&dev->parent->sem);
 	down(&dev->sem);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 66b710c28812..dfcbfe504867 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -394,6 +394,53 @@ error:
 }
 EXPORT_SYMBOL_GPL(platform_device_register_simple);
 
+/**
+ * platform_device_register_data
+ * @parent: parent device for the device we're adding
+ * @name: base name of the device we're adding
+ * @id: instance id
+ * @data: platform specific data for this platform device
+ * @size: size of platform specific data
+ *
+ * This function creates a simple platform device that requires minimal
+ * resource and memory management. Canned release function freeing memory
+ * allocated for the device allows drivers using such devices to be
+ * unloaded without waiting for the last reference to the device to be
+ * dropped.
+ */
+struct platform_device *platform_device_register_data(
+		struct device *parent,
+		const char *name, int id,
+		const void *data, size_t size)
+{
+	struct platform_device *pdev;
+	int retval;
+
+	pdev = platform_device_alloc(name, id);
+	if (!pdev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	pdev->dev.parent = parent;
+
+	if (size) {
+		retval = platform_device_add_data(pdev, data, size);
+		if (retval)
+			goto error;
+	}
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto error;
+
+	return pdev;
+
+error:
+	platform_device_put(pdev);
+	return ERR_PTR(retval);
+}
+
 static int platform_drv_probe(struct device *_dev)
 {
 	struct platform_driver *drv = to_platform_driver(_dev->driver);
@@ -865,7 +912,7 @@ static int platform_pm_restore_noirq(struct device *dev)
 
 #endif /* !CONFIG_HIBERNATION */
 
-struct pm_ext_ops platform_pm_ops = {
+static struct pm_ext_ops platform_pm_ops = {
 	.base = {
 		.prepare = platform_pm_prepare,
 		.complete = platform_pm_complete,
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 03bde7524bc3..692c20ba5144 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -83,7 +83,7 @@ void device_pm_add(struct device *dev)
 		 * transition is in progress in order to avoid leaving them
 		 * unhandled down the road
 		 */
-		WARN_ON(true);
+		dev_WARN(dev, "Parentless device registered during a PM transaction\n");
 	}
 
 	list_add_tail(&dev->power.entry, &dpm_list);
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 1f56d2c5b7fc..200efc4d2c1e 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -284,9 +284,9 @@ aoechr_init(void)
 		return PTR_ERR(aoe_class);
 	}
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-		device_create_drvdata(aoe_class, NULL,
-				      MKDEV(AOE_MAJOR, chardevs[i].minor),
-				      NULL, chardevs[i].name);
+		device_create(aoe_class, NULL,
+			      MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
+			      chardevs[i].name);
 
 	return 0;
 }
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index d731ca42f802..9dfa27163001 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -686,9 +686,8 @@ static int __init pg_init(void)
 	for (unit = 0; unit < PG_UNITS; unit++) {
 		struct pg *dev = &devices[unit];
 		if (dev->present)
-			device_create_drvdata(pg_class, NULL,
-					      MKDEV(major, unit), NULL,
-					      "pg%u", unit);
+			device_create(pg_class, NULL, MKDEV(major, unit), NULL,
+				      "pg%u", unit);
 	}
 	err = 0;
 	goto out;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 673b8b2fd337..5ae229656eaa 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -979,12 +979,10 @@ static int __init pt_init(void)
 
 	for (unit = 0; unit < PT_UNITS; unit++)
 		if (pt[unit].present) {
-			device_create_drvdata(pt_class, NULL,
-					      MKDEV(major, unit), NULL,
-					      "pt%d", unit);
-			device_create_drvdata(pt_class, NULL,
-					      MKDEV(major, unit + 128), NULL,
-					      "pt%dn", unit);
+			device_create(pt_class, NULL, MKDEV(major, unit), NULL,
+				      "pt%d", unit);
+			device_create(pt_class, NULL, MKDEV(major, unit + 128),
+				      NULL, "pt%dn", unit);
 		}
 	goto out;
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 0e077150568b..195ca7c720f5 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -302,9 +302,8 @@ static struct kobj_type kobj_pkt_type_wqueue = {
 static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
 {
 	if (class_pktcdvd) {
-		pd->dev = device_create_drvdata(class_pktcdvd, NULL,
-						pd->pkt_dev, NULL,
-						"%s", pd->name);
+		pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, NULL,
+					"%s", pd->name);
 		if (IS_ERR(pd->dev))
 			pd->dev = NULL;
 	}
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index b650b4e48e50..456f54db73e2 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -229,9 +229,8 @@ static int bsr_create_devs(struct device_node *bn)
 		if (result)
 			goto out_err;
 
-		cur->bsr_device = device_create_drvdata(bsr_class, NULL,
-							cur->bsr_dev,
-							cur, cur->bsr_name);
+		cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
+						cur, cur->bsr_name);
 		if (!cur->bsr_device) {
 			printk(KERN_ERR "device_create failed for %s\n",
 			       cur->bsr_name);
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index ca7c72a486b2..85832ab924e6 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -508,8 +508,8 @@ static int __init dsp56k_init_driver(void)
 		err = PTR_ERR(dsp56k_class);
 		goto out_chrdev;
 	}
-	device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0),
-			      NULL, "dsp56k");
+	device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL,
+		      "dsp56k");
 
 	printk(banner);
 	goto out;
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 6774572d3759..70e0ebc30bd0 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -745,12 +745,12 @@ static int __init ip2_loadmain(void)
 
 		pB = i2BoardPtrTable[i];
 		if (pB != NULL) {
-			device_create_drvdata(ip2_class, NULL,
-					      MKDEV(IP2_IPL_MAJOR, 4 * i),
-					      NULL, "ipl%d", i);
-			device_create_drvdata(ip2_class, NULL,
-					      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
-					      NULL, "stat%d", i);
+			device_create(ip2_class, NULL,
+				      MKDEV(IP2_IPL_MAJOR, 4 * i),
+				      NULL, "ipl%d", i);
+			device_create(ip2_class, NULL,
+				      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+				      NULL, "stat%d", i);
 
 			for (box = 0; box < ABS_MAX_BOXES; box++)
 				for (j = 0; j < ABS_BIGGEST_BOX; j++)
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 64e1c169e826..835a33c8d5f5 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
 	entry->dev = dev;
 
 	mutex_lock(&reg_list_mutex);
-	device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
+	device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
 	list_add(&entry->link, &reg_list);
 	mutex_unlock(&reg_list_mutex);
 }
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 505d7a1f6b8c..44e5d60f517e 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -4600,9 +4600,8 @@ static int __init istallion_module_init(void)
 
 	istallion_class = class_create(THIS_MODULE, "staliomem");
 	for (i = 0; i < 4; i++)
-		device_create_drvdata(istallion_class, NULL,
-				      MKDEV(STL_SIOMEMMAJOR, i),
-				      NULL, "staliomem%d", i);
+		device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+			      NULL, "staliomem%d", i);
 
 	return 0;
 err_deinit:
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 3f2719b9f77b..e444c2dba160 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -813,8 +813,8 @@ static int lp_register(int nr, struct parport *port)
 	if (reset)
 		lp_reset(nr);
 
-	device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
-			      "lp%d", nr);
+	device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
+		      "lp%d", nr);
 
 	printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
 	       (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 672b08e694d0..6431f6921a67 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -992,9 +992,9 @@ static int __init chr_dev_init(void)
 
 	mem_class = class_create(THIS_MODULE, "mem");
 	for (i = 0; i < ARRAY_SIZE(devlist); i++)
-		device_create_drvdata(mem_class, NULL,
-				      MKDEV(MEM_MAJOR, devlist[i].minor),
-				      NULL, devlist[i].name);
+		device_create(mem_class, NULL,
+			      MKDEV(MEM_MAJOR, devlist[i].minor), NULL,
+			      devlist[i].name);
 
 	return 0;
 }
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 999aa779c08a..a5e0db9d7662 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc)
 		misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
 	dev = MKDEV(MISC_MAJOR, misc->minor);
 
-	misc->this_device = device_create_drvdata(misc_class, misc->parent,
-						  dev, NULL, "%s", misc->name);
+	misc->this_device = device_create(misc_class, misc->parent, dev, NULL,
+					  "%s", misc->name);
 	if (IS_ERR(misc->this_device)) {
 		err = PTR_ERR(misc->this_device);
 		goto out;
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 1c5bf99895ed..dbb912574569 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1871,7 +1871,7 @@ static int cm4000_probe(struct pcmcia_device *link)
 		return ret;
 	}
 
-	device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
+	device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
 
 	return 0;
 }
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 2d7c906435b7..4f0723b07974 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -637,8 +637,7 @@ static int reader_probe(struct pcmcia_device *link)
 		return ret;
 	}
 
-	device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL,
-			      "cmx%d", i);
+	device_create(cmx_class, NULL, MKDEV(major, i), NULL, "cmx%d", i);
 
 	return 0;
 }
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index bee39fdfba73..c84c34fb1231 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -760,9 +760,8 @@ static const struct file_operations pp_fops = {
 
 static void pp_attach(struct parport *port)
 {
-	device_create_drvdata(ppdev_class, port->dev,
-			      MKDEV(PP_MAJOR, port->number),
-			      NULL, "parport%d", port->number);
+	device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
+		      NULL, "parport%d", port->number);
 }
 
 static void pp_detach(struct parport *port)
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 47b8cf281d4a..e139372d0e69 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
 static void bind_device(struct raw_config_request *rq)
 {
 	device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-	device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
-			      NULL, "raw%d", rq->raw_minor);
+	device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
+		      "raw%d", rq->raw_minor);
 }
 
 /*
@@ -283,8 +283,7 @@ static int __init raw_init(void)
 		ret = PTR_ERR(raw_class);
 		goto error_region;
 	}
-	device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL,
-			      "rawctl");
+	device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
 	return 0;
 
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 3ce60df14c0a..32b74de18f5f 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -444,8 +444,8 @@ scdrv_init(void)
 				continue;
 			}
 
-			device_create_drvdata(snsc_class, NULL, dev, NULL,
-					      "%s", devname);
+			device_create(snsc_class, NULL, dev, NULL,
+				      "%s", devname);
 
 			ia64_sn_irtr_intr_enable(scd->scd_nasid,
 						 0 /*ignored */ ,
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 8b8f07a7f505..963b03fb29e5 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -4743,8 +4743,8 @@ static int __init stallion_module_init(void)
 	if (IS_ERR(stallion_class))
 		printk("STALLION: failed to create class\n");
 	for (i = 0; i < 4; i++)
-		device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-				      NULL, "staliomem%d", i);
+		device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+			      NULL, "staliomem%d", i);
 
 	return 0;
 err_unrtty:
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 3f48d88cffc0..59f472143f08 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2850,7 +2850,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
 	else
 		tty_line_name(driver, index, name);
 
-	return device_create_drvdata(tty_class, device, dev, NULL, name);
+	return device_create(tty_class, device, dev, NULL, name);
 }
 EXPORT_SYMBOL(tty_register_device);
 
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index c2ae52dd53d1..4f3b3f95fc42 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -481,10 +481,10 @@ static struct class *vc_class;
 
 void vcs_make_sysfs(struct tty_struct *tty)
 {
-	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
-			      NULL, "vcs%u", tty->index + 1);
-	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
-			      NULL, "vcsa%u", tty->index + 1);
+	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL,
+		      "vcs%u", tty->index + 1);
+	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL,
+		      "vcsa%u", tty->index + 1);
 }
 
 void vcs_remove_sysfs(struct tty_struct *tty)
@@ -499,7 +499,7 @@ int __init vcs_init(void)
 		panic("unable to get major %d for vcs device", VCS_MAJOR);
 	vc_class = class_create(THIS_MODULE, "vc");
 
-	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
-	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
 	return 0;
 }
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 7a70a40ad639..ffc9254f7e02 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 	state[i].cur_part = 0;
 	for (j = 0; j < MAX_PARTITIONS; ++j)
 		state[i].part_stat_rwi[j] = VIOT_IDLE;
-	device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
-			      NULL, "iseries!vt%d", i);
-	device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
-			      NULL, "iseries!nvt%d", i);
+	device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
+		      "iseries!vt%d", i);
+	device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), NULL,
+		      "iseries!nvt%d", i);
 	printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
 			"resource %10.10s type %4.4s, model %3.3s\n",
 			i, viotape_unitinfo[i].rsrcname,
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 278c9857bcf5..ed132fe55d3d 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -657,8 +657,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
 		goto failed3;
 	}
 
-	device_create_drvdata(icap_class, dev, devt, NULL,
-			      "%s%d", DRIVER_NAME, id);
+	device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
 	return 0;		/* success */
 
  failed3:
diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c
index 7af4b403bd2d..bb538b9690e0 100644
--- a/drivers/dca/dca-sysfs.c
+++ b/drivers/dca/dca-sysfs.c
@@ -15,9 +15,8 @@ int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
 	struct device *cd;
 	static int req_count;
 
-	cd = device_create_drvdata(dca_class, dca->cd,
-				   MKDEV(0, slot + 1), NULL,
-				   "requester%d", req_count++);
+	cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1), NULL,
+			   "requester%d", req_count++);
 	if (IS_ERR(cd))
 		return PTR_ERR(cd);
 	return 0;
@@ -48,8 +47,7 @@ idr_try_again:
 		return err;
 	}
 
-	cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL,
-				   "dca%d", dca->id);
+	cd = device_create(dca_class, dev, MKDEV(0, 0), NULL, "dca%d", dca->id);
 	if (IS_ERR(cd)) {
 		spin_lock(&dca_idr_lock);
 		idr_remove(&dca_idr, dca->id);
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index b91ef63126ed..deb154aa47c4 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -334,9 +334,9 @@ static void ibft_release(struct kobject *kobj)
 /*
  *  Routines for parsing the iBFT data to be human readable.
  */
-ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
-				  struct ibft_attribute *attr,
-				  char *buf)
+static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
+					struct ibft_attribute *attr,
+					char *buf)
 {
 	struct ibft_initiator *initiator = entry->initiator;
 	void *ibft_loc = entry->header;
@@ -376,9 +376,9 @@ ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
 	return str - buf;
 }
 
-ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
-			    struct ibft_attribute *attr,
-			    char *buf)
+static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
+				  struct ibft_attribute *attr,
+				  char *buf)
 {
 	struct ibft_nic *nic = entry->nic;
 	void *ibft_loc = entry->header;
@@ -440,9 +440,9 @@ ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
 	return str - buf;
 };
 
-ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
-			       struct ibft_attribute *attr,
-			       char *buf)
+static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
+				     struct ibft_attribute *attr,
+				     char *buf)
 {
 	struct ibft_tgt *tgt = entry->tgt;
 	void *ibft_loc = entry->header;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 497e0d1dd3c3..af3edb98df43 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -326,9 +326,8 @@ int hidraw_connect(struct hid_device *hid)
 		goto out;
 	}
 
-	dev->dev = device_create_drvdata(hidraw_class, NULL,
-					 MKDEV(hidraw_major, minor), NULL,
-					 "%s%d", "hidraw", minor);
+	dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
+				 NULL, "%s%d", "hidraw", minor);
 
 	if (IS_ERR(dev->dev)) {
 		spin_lock(&minors_lock);
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 7321a88a5112..076a59cdabe9 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -55,8 +55,8 @@ again:
 		return ERR_PTR(err);
 
 	id = id & MAX_ID_MASK;
-	hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL,
-				      HWMON_ID_FORMAT, id);
+	hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
+			      HWMON_ID_FORMAT, id);
 
 	if (IS_ERR(hwdev)) {
 		spin_lock(&idr_lock);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 307d976c9b69..c171988a9f51 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -521,9 +521,9 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
 		return PTR_ERR(i2c_dev);
 
 	/* register this i2c device with the driver core */
-	i2c_dev->dev = device_create_drvdata(i2c_dev_class, &adap->dev,
-					     MKDEV(I2C_MAJOR, adap->nr),
-					     NULL, "i2c-%d", adap->nr);
+	i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
+				     MKDEV(I2C_MAJOR, adap->nr), NULL,
+				     "i2c-%d", adap->nr);
 	if (IS_ERR(i2c_dev->dev)) {
 		res = PTR_ERR(i2c_dev->dev);
 		goto error;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index f27baa5f140e..19f8c7770a25 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -657,8 +657,8 @@ static int ide_register_port(ide_hwif_t *hwif)
 		goto out;
 	}
 
-	hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev,
-					      MKDEV(0, 0), hwif, hwif->name);
+	hwif->portdev = device_create(ide_port_class, &hwif->gendev,
+				      MKDEV(0, 0), hwif, hwif->name);
 	if (IS_ERR(hwif->portdev)) {
 		ret = PTR_ERR(hwif->portdev);
 		device_unregister(&hwif->gendev);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 25ac60f53273..d879c7797cde 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2420,12 +2420,11 @@ static int ide_tape_probe(ide_drive_t *drive)
 
 	idetape_setup(drive, tape, minor);
 
-	device_create_drvdata(idetape_sysfs_class, &drive->gendev,
-			      MKDEV(IDETAPE_MAJOR, minor), NULL,
-			      "%s", tape->name);
-	device_create_drvdata(idetape_sysfs_class, &drive->gendev,
-			      MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
-			      "n%s", tape->name);
+	device_create(idetape_sysfs_class, &drive->gendev,
+		      MKDEV(IDETAPE_MAJOR, minor), NULL, "%s", tape->name);
+	device_create(idetape_sysfs_class, &drive->gendev,
+		      MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+		      "n%s", tape->name);
 
 	g->fops = &idetape_block_ops;
 	ide_register_region(g);
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index b6eb2cf25914..9236c0d5a122 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2296,10 +2296,10 @@ static void dv1394_add_host(struct hpsb_host *host)
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	device_create_drvdata(hpsb_protocol_class, NULL,
-			      MKDEV(IEEE1394_MAJOR,
-				    IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL,
-			      "dv1394-%d", id);
+	device_create(hpsb_protocol_class, NULL,
+		      MKDEV(IEEE1394_MAJOR,
+			    IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+		      NULL, "dv1394-%d", id);
 
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
 	dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 6fa9e4a21840..c7833bb37ae1 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -3010,10 +3010,10 @@ static int __init init_raw1394(void)
 	hpsb_register_highlevel(&raw1394_highlevel);
 
 	if (IS_ERR
-	    (device_create_drvdata(
-	      hpsb_protocol_class, NULL,
-	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
-	      NULL, RAW1394_DEVICE_NAME))) {
+	    (device_create(hpsb_protocol_class, NULL,
+			   MKDEV(IEEE1394_MAJOR,
+				 IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+			   NULL, RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
 		goto out_unreg;
 	}
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 25db6e67fa4e..6e73b06eed4f 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1341,9 +1341,8 @@ static void video1394_add_host (struct hpsb_host *host)
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	device_create_drvdata(hpsb_protocol_class, NULL,
-			      MKDEV(IEEE1394_MAJOR, minor), NULL,
-			      "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+	device_create(hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, minor),
+		      NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 }
 
 
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 3cab0cedfca2..a78d35aecee3 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3691,9 +3691,9 @@ static void cm_add_one(struct ib_device *ib_device)
 	cm_dev->ib_device = ib_device;
 	cm_get_ack_delay(cm_dev);
 
-	cm_dev->device = device_create_drvdata(&cm_class, &ib_device->dev,
-					       MKDEV(0, 0), NULL,
-					       "%s", ib_device->name);
+	cm_dev->device = device_create(&cm_class, &ib_device->dev,
+				       MKDEV(0, 0), NULL,
+				       "%s", ib_device->name);
 	if (!cm_dev->device) {
 		kfree(cm_dev);
 		return;
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 268a2d23b7c9..8c46f2257098 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1016,9 +1016,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
 	if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
 		goto err_cdev;
 
-	port->dev = device_create_drvdata(umad_class, device->dma_device,
-					  port->cdev->dev, port,
-					  "umad%d", port->dev_num);
+	port->dev = device_create(umad_class, device->dma_device,
+				  port->cdev->dev, port,
+				  "umad%d", port->dev_num);
 	if (IS_ERR(port->dev))
 		goto err_cdev;
 
@@ -1036,9 +1036,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
 	if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
 		goto err_sm_cdev;
 
-	port->sm_dev = device_create_drvdata(umad_class, device->dma_device,
-					     port->sm_cdev->dev, port,
-					     "issm%d", port->dev_num);
+	port->sm_dev = device_create(umad_class, device->dma_device,
+				     port->sm_cdev->dev, port,
+				     "issm%d", port->dev_num);
 	if (IS_ERR(port->sm_dev))
 		goto err_sm_cdev;
 
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index aeee856c4060..d85af1b67027 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -764,12 +764,9 @@ static void ib_uverbs_add_one(struct ib_device *device)
 	if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
 		goto err_cdev;
 
-	uverbs_dev->dev = device_create_drvdata(uverbs_class,
-						device->dma_device,
-						uverbs_dev->cdev->dev,
-						uverbs_dev,
-						"uverbs%d",
-						uverbs_dev->devnum);
+	uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
+					uverbs_dev->cdev->dev, uverbs_dev,
+					"uverbs%d", uverbs_dev->devnum);
 	if (IS_ERR(uverbs_dev->dev))
 		goto err_cdev;
 
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 56c0eda3c077..1af1f3a907c6 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -2455,7 +2455,7 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
 		goto err_cdev;
 	}
 
-	device = device_create_drvdata(ipath_class, NULL, dev, NULL, name);
+	device = device_create(ipath_class, NULL, dev, NULL, name);
 
 	if (IS_ERR(device)) {
 		ret = PTR_ERR(device);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 798d7f3e42ef..1b5bf87c4cf4 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1553,8 +1553,7 @@ static int __init capi_init(void)
 		return PTR_ERR(capi_class);
 	}
 
-	device_create_drvdata(capi_class, NULL, MKDEV(capi_major, 0), NULL,
-			      "capi");
+	device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	if (capinc_tty_init() < 0) {
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 559a40861c39..ee74ee7b2acc 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -103,8 +103,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 {
 	int rc;
 
-	led_cdev->dev = device_create_drvdata(leds_class, parent, 0, led_cdev,
-					      "%s", led_cdev->name);
+	led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
+				      "%s", led_cdev->name);
 	if (IS_ERR(led_cdev->dev))
 		return PTR_ERR(led_cdev->dev);
 
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index cae52485208a..23741cec45e3 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -862,8 +862,7 @@ adbdev_init(void)
 	adb_dev_class = class_create(THIS_MODULE, "adb");
 	if (IS_ERR(adb_dev_class))
 		return;
-	device_create_drvdata(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL,
-			      "adb");
+	device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
 
 	platform_device_register(&adb_pfdev);
 	platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index e7132770a3bf..665776d72a48 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -233,7 +233,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 
 	mutex_unlock(&dvbdev_register_lock);
 
-	clsdev = device_create_drvdata(dvb_class, adap->device,
+	clsdev = device_create(dvb_class, adap->device,
 			       MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
 			       NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
 	if (IS_ERR(clsdev)) {
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index daf585689ce3..abdebe347383 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -399,9 +399,9 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
 		goto err_irq;
 	}
 
-	if (IS_ERR(device_create_drvdata(phantom_class, &pdev->dev,
-					 MKDEV(phantom_major, minor),
-					 NULL, "phantom%u", minor)))
+	if (IS_ERR(device_create(phantom_class, &pdev->dev,
+				 MKDEV(phantom_major, minor), NULL,
+				 "phantom%u", minor)))
 		dev_err(&pdev->dev, "can't create device\n");
 
 	pci_set_drvdata(pdev, pht);
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index e00d424e6575..1c74762dec89 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -26,13 +26,11 @@ static void mtd_notify_add(struct mtd_info* mtd)
 	if (!mtd)
 		return;
 
-	device_create_drvdata(mtd_class, NULL,
-			      MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
-			      NULL, "mtd%d", mtd->index);
+	device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+		      NULL, "mtd%d", mtd->index);
 
-	device_create_drvdata(mtd_class, NULL,
-			      MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
-			      NULL, "mtd%dro", mtd->index);
+	device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+		      NULL, "mtd%dro", mtd->index);
 }
 
 static void mtd_notify_remove(struct mtd_info* mtd)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index f11e900b437b..e11b03b2b25a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -309,11 +309,6 @@ void phy_disconnect(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_disconnect);
 
-static int phy_compare_id(struct device *dev, void *data)
-{
-	return strcmp((char *)data, dev->bus_id) ? 0 : 1;
-}
-
 /**
  * phy_attach - attach a network device to a particular PHY device
  * @dev: network device to attach
@@ -337,8 +332,7 @@ struct phy_device *phy_attach(struct net_device *dev,
 
 	/* Search the list of PHY devices on the mdio bus for the
 	 * PHY with the requested name */
-	d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
-
+	d = bus_find_device_by_name(bus, NULL, bus_id);
 	if (d) {
 		phydev = to_phy_device(d);
 	} else {
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 94818ee3cef5..7e857e938adb 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -866,8 +866,8 @@ static int __init ppp_init(void)
 			err = PTR_ERR(ppp_class);
 			goto out_chrdev;
 		}
-		device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0),
-				      NULL, "ppp");
+		device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL,
+			      "ppp");
 	}
 
 out:
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index f14051556c87..7f97f8d08c39 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -388,8 +388,8 @@ static int __init cosa_init(void)
 		goto out_chrdev;
 	}
 	for (i = 0; i < nr_cards; i++)
-		device_create_drvdata(cosa_class, NULL, MKDEV(cosa_major, i),
-				      NULL, "cosa%d", i);
+		device_create(cosa_class, NULL, MKDEV(cosa_major, i), NULL,
+			      "cosa%d", i);
 	err = 0;
 	goto out;
 
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c9e4a435b2fc..1a019e98dac3 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -533,11 +533,11 @@ static int __init init_mac80211_hwsim(void)
 		data = hw->priv;
 		data->hw = hw;
 
-		data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw,
-						"hwsim%d", i);
+		data->dev = device_create(hwsim_class, NULL, 0, hw,
+					  "hwsim%d", i);
 		if (IS_ERR(data->dev)) {
 			printk(KERN_DEBUG
-			       "mac80211_hwsim: device_create_drvdata "
+			       "mac80211_hwsim: device_create "
 			       "failed (%ld)\n", PTR_ERR(data->dev));
 			err = -ENOMEM;
 			goto failed_drvdata;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 36698e57b97f..dd9161a054e1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1237,8 +1237,11 @@ EXPORT_SYMBOL(pci_scan_bridge);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 #endif
 
-static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b)
+static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
 {
+	const struct pci_dev *a = to_pci_dev(d_a);
+	const struct pci_dev *b = to_pci_dev(d_b);
+
 	if      (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
 	else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return  1;
 
@@ -1251,50 +1254,7 @@ static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev
 	return 0;
 }
 
-/*
- * Yes, this forcably breaks the klist abstraction temporarily.  It
- * just wants to sort the klist, not change reference counts and
- * take/drop locks rapidly in the process.  It does all this while
- * holding the lock for the list, so objects can't otherwise be
- * added/removed while we're swizzling.
- */
-static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
-{
-	struct list_head *pos;
-	struct klist_node *n;
-	struct device *dev;
-	struct pci_dev *b;
-
-	list_for_each(pos, list) {
-		n = container_of(pos, struct klist_node, n_node);
-		dev = container_of(n, struct device, knode_bus);
-		b = to_pci_dev(dev);
-		if (pci_sort_bf_cmp(a, b) <= 0) {
-			list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
-			return;
-		}
-	}
-	list_move_tail(&a->dev.knode_bus.n_node, list);
-}
-
 void __init pci_sort_breadthfirst(void)
 {
-	LIST_HEAD(sorted_devices);
-	struct list_head *pos, *tmp;
-	struct klist_node *n;
-	struct device *dev;
-	struct pci_dev *pdev;
-	struct klist *device_klist;
-
-	device_klist = bus_get_device_klist(&pci_bus_type);
-
-	spin_lock(&device_klist->k_lock);
-	list_for_each_safe(pos, tmp, &device_klist->k_list) {
-		n = container_of(pos, struct klist_node, n_node);
-		dev = container_of(n, struct device, knode_bus);
-		pdev = to_pci_dev(dev);
-		pci_insertion_sort_klist(pdev, &sorted_devices);
-	}
-	list_splice(&sorted_devices, &device_klist->k_list);
-	spin_unlock(&device_klist->k_lock);
+	bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp);
 }
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 7cc7bf5304aa..3b8b9d3cb03d 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -4,6 +4,7 @@
  */
 
 extern spinlock_t pnp_lock;
+extern struct device_attribute pnp_interface_attrs[];
 void *pnp_alloc(long size);
 
 int pnp_register_protocol(struct pnp_protocol *protocol);
@@ -16,7 +17,6 @@ struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
 
 int pnp_add_device(struct pnp_dev *dev);
 struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
-int pnp_interface_attach_device(struct pnp_dev *dev);
 
 int pnp_add_card(struct pnp_card *card);
 void pnp_remove_card(struct pnp_card *card);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index cc0aeaed6179..817fe626e15b 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -159,21 +159,13 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
 
 int __pnp_add_device(struct pnp_dev *dev)
 {
-	int ret;
-
 	pnp_fixup_device(dev);
 	dev->status = PNP_READY;
 	spin_lock(&pnp_lock);
 	list_add_tail(&dev->global_list, &pnp_global);
 	list_add_tail(&dev->protocol_list, &dev->protocol->devices);
 	spin_unlock(&pnp_lock);
-
-	ret = device_register(&dev->dev);
-	if (ret)
-		return ret;
-
-	pnp_interface_attach_device(dev);
-	return 0;
+	return device_register(&dev->dev);
 }
 
 /*
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index d3f869ee1d92..e3f7e89c4dfb 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -206,6 +206,7 @@ struct bus_type pnp_bus_type = {
 	.remove  = pnp_device_remove,
 	.suspend = pnp_bus_suspend,
 	.resume  = pnp_bus_resume,
+	.dev_attrs = pnp_interface_attrs,
 };
 
 int pnp_register_driver(struct pnp_driver *drv)
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index a876ecf7028c..478a4a739c00 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -243,8 +243,6 @@ static ssize_t pnp_show_options(struct device *dmdev,
 	return ret;
 }
 
-static DEVICE_ATTR(options, S_IRUGO, pnp_show_options, NULL);
-
 static ssize_t pnp_show_current_resources(struct device *dmdev,
 					  struct device_attribute *attr,
 					  char *buf)
@@ -420,9 +418,6 @@ done:
 	return count;
 }
 
-static DEVICE_ATTR(resources, S_IRUGO | S_IWUSR,
-		   pnp_show_current_resources, pnp_set_current_resources);
-
 static ssize_t pnp_show_current_ids(struct device *dmdev,
 				    struct device_attribute *attr, char *buf)
 {
@@ -437,27 +432,11 @@ static ssize_t pnp_show_current_ids(struct device *dmdev,
 	return (str - buf);
 }
 
-static DEVICE_ATTR(id, S_IRUGO, pnp_show_current_ids, NULL);
-
-int pnp_interface_attach_device(struct pnp_dev *dev)
-{
-	int rc = device_create_file(&dev->dev, &dev_attr_options);
-
-	if (rc)
-		goto err;
-	rc = device_create_file(&dev->dev, &dev_attr_resources);
-	if (rc)
-		goto err_opt;
-	rc = device_create_file(&dev->dev, &dev_attr_id);
-	if (rc)
-		goto err_res;
-
-	return 0;
-
-err_res:
-	device_remove_file(&dev->dev, &dev_attr_resources);
-err_opt:
-	device_remove_file(&dev->dev, &dev_attr_options);
-err:
-	return rc;
-}
+struct device_attribute pnp_interface_attrs[] = {
+	__ATTR(resources, S_IRUGO | S_IWUSR,
+		   pnp_show_current_resources,
+		   pnp_set_current_resources),
+	__ATTR(options, S_IRUGO, pnp_show_options, NULL),
+	__ATTR(id, S_IRUGO, pnp_show_current_ids, NULL),
+	__ATTR_NULL,
+};
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index cb1ccb472921..3007695f90c8 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -91,8 +91,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
 {
 	int rc = 0;
 
-	psy->dev = device_create_drvdata(power_supply_class, parent, 0,
-					 psy, "%s", psy->name);
+	psy->dev = device_create(power_supply_class, parent, 0, psy,
+				 "%s", psy->name);
 	if (IS_ERR(psy->dev)) {
 		rc = PTR_ERR(psy->dev);
 		goto dev_create_failed;
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 1792b2c0130e..0b15cf107ec9 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1168,19 +1168,17 @@ static int raw3270_create_attributes(struct raw3270 *rp)
 	if (rc)
 		goto out;
 
-	rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev,
-					     MKDEV(IBM_TTY3270_MAJOR, rp->minor),
-					     NULL,
-					     "tty%s", dev_name(&rp->cdev->dev));
+	rp->clttydev = device_create(class3270, &rp->cdev->dev,
+				     MKDEV(IBM_TTY3270_MAJOR, rp->minor), NULL,
+				     "tty%s", dev_name(&rp->cdev->dev));
 	if (IS_ERR(rp->clttydev)) {
 		rc = PTR_ERR(rp->clttydev);
 		goto out_ttydev;
 	}
 
-	rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev,
-					     MKDEV(IBM_FS3270_MAJOR, rp->minor),
-					     NULL,
-					     "tub%s", dev_name(&rp->cdev->dev));
+	rp->cltubdev = device_create(class3270, &rp->cdev->dev,
+				     MKDEV(IBM_FS3270_MAJOR, rp->minor), NULL,
+				     "tub%s", dev_name(&rp->cdev->dev));
 	if (!IS_ERR(rp->cltubdev))
 		goto out;
 
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 12c2a5aaf31b..ddc914ccea8f 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -69,9 +69,9 @@ struct tape_class_device *register_tape_dev(
 	if (rc)
 		goto fail_with_cdev;
 
-	tcd->class_device = device_create_drvdata(tape_class, device,
-						  tcd->char_device->dev,
-						  NULL, "%s", tcd->device_name);
+	tcd->class_device = device_create(tape_class, device,
+					  tcd->char_device->dev, NULL,
+					  "%s", tcd->device_name);
 	rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
 	if (rc)
 		goto fail_with_cdev;
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 42173cc34610..24762727bc27 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -747,10 +747,10 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
 		device_unregister(dev);
 		return ret;
 	}
-	priv->class_device = device_create_drvdata(vmlogrdr_class, dev,
-						   MKDEV(vmlogrdr_major,
-							 priv->minor_num),
-						   priv, "%s", dev_name(dev));
+	priv->class_device = device_create(vmlogrdr_class, dev,
+					   MKDEV(vmlogrdr_major,
+						 priv->minor_num),
+					   priv, "%s", dev_name(dev));
 	if (IS_ERR(priv->class_device)) {
 		ret = PTR_ERR(priv->class_device);
 		priv->class_device=NULL;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 6fdfa5ddeca8..9020eba620ee 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -896,9 +896,8 @@ static int ur_set_online(struct ccw_device *cdev)
 		goto fail_free_cdev;
 	}
 
-	urd->device = device_create_drvdata(vmur_class, NULL,
-					    urd->char_device->dev, NULL,
-					    "%s", node_id);
+	urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
+				    NULL, "%s", node_id);
 	if (IS_ERR(urd->device)) {
 		rc = PTR_ERR(urd->device);
 		TRACE("ur_set_online: device_create rc=%d\n", rc);
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 3c257fe0893e..88ecf94ad979 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -914,9 +914,9 @@ static int ch_probe(struct device *dev)
 	ch->minor = minor;
 	sprintf(ch->name,"ch%d",ch->minor);
 
-	class_dev = device_create_drvdata(ch_sysfs_class, dev,
-					  MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
-					  ch, "s%s", ch->name);
+	class_dev = device_create(ch_sysfs_class, dev,
+				  MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
+				  "s%s", ch->name);
 	if (IS_ERR(class_dev)) {
 		printk(KERN_WARNING "ch%d: device_create failed\n",
 		       ch->minor);
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 1fe0901e8119..8aba4fdfb522 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -271,7 +271,7 @@ rebuild_sys_tab:
 		pHba->initialized = TRUE;
 		pHba->state &= ~DPTI_STATE_RESET;
 		if (adpt_sysfs_class) {
-			struct device *dev = device_create_drvdata(adpt_sysfs_class,
+			struct device *dev = device_create(adpt_sysfs_class,
 				NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
 				"dpti%d", pHba->unit);
 			if (IS_ERR(dev)) {
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 1c79f9794f4e..0ea78d9a37db 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5708,7 +5708,8 @@ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * S
 	struct device *osst_member;
 	int err;
 
-	osst_member = device_create_drvdata(osst_sysfs_class, device, dev, STp, "%s", name);
+	osst_member = device_create(osst_sysfs_class, device, dev, STp,
+				    "%s", name);
 	if (IS_ERR(osst_member)) {
 		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
 		return PTR_ERR(osst_member);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ba9b9bbd4e73..93bd59a1ed79 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1450,12 +1450,10 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
 	if (sg_sysfs_valid) {
 		struct device *sg_class_member;
 
-		sg_class_member = device_create_drvdata(sg_sysfs_class,
-							cl_dev->parent,
-							MKDEV(SCSI_GENERIC_MAJOR,
-							      sdp->index),
-							sdp,
-							"%s", disk->disk_name);
+		sg_class_member = device_create(sg_sysfs_class, cl_dev->parent,
+						MKDEV(SCSI_GENERIC_MAJOR,
+						      sdp->index),
+						sdp, "%s", disk->disk_name);
 		if (IS_ERR(sg_class_member)) {
 			printk(KERN_ERR "sg_add: "
 			       "device_create failed\n");
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c2bb53e3d941..5c28d08f18f4 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4428,13 +4428,10 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
 		snprintf(name, 10, "%s%s%s", rew ? "n" : "",
 			 STp->disk->disk_name, st_formats[i]);
 		st_class_member =
-			device_create_drvdata(st_sysfs_class,
-					      &STp->device->sdev_gendev,
-					      MKDEV(SCSI_TAPE_MAJOR,
-						    TAPE_MINOR(dev_num,
-							      mode, rew)),
-					      &STp->modes[mode],
-					      "%s", name);
+			device_create(st_sysfs_class, &STp->device->sdev_gendev,
+				      MKDEV(SCSI_TAPE_MAJOR,
+					    TAPE_MINOR(dev_num, mode, rew)),
+				      &STp->modes[mode], "%s", name);
 		if (IS_ERR(st_class_member)) {
 			printk(KERN_WARNING "st%d: device_create failed\n",
 			       dev_num);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index e5e0cfed5e3b..89a43755a453 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -583,10 +583,9 @@ static int spidev_probe(struct spi_device *spi)
 		struct device *dev;
 
 		spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
-		dev = device_create_drvdata(spidev_class, &spi->dev,
-				spidev->devt, spidev,
-				"spidev%d.%d",
-				spi->master->bus_num, spi->chip_select);
+		dev = device_create(spidev_class, &spi->dev, spidev->devt,
+				    spidev, "spidev%d.%d",
+				    spi->master->bus_num, spi->chip_select);
 		status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
 	} else {
 		dev_dbg(&spi->dev, "no minor number available!\n");
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 4190be64917f..04b954cfce76 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -58,4 +58,17 @@ config UIO_SMX
 
 	  If you compile this as a module, it will be called uio_smx.
 
+config UIO_SERCOS3
+	tristate "Automata Sercos III PCI card driver"
+	default n
+	help
+	  Userspace I/O interface for the Sercos III PCI card from
+	  Automata GmbH. The userspace part of this driver will be
+	  available for download from the Automata GmbH web site.
+
+	  Automata GmbH:        http://www.automataweb.com
+	  Sercos III interface: http://www.sercos.com
+
+	  If you compile this as a module, it will be called uio_sercos3.
+
 endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 8667bbdef904..e69558149859 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_UIO_CIF)	+= uio_cif.o
 obj-$(CONFIG_UIO_PDRV)	+= uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)	+= uio_pdrv_genirq.o
 obj-$(CONFIG_UIO_SMX)	+= uio_smx.o
+obj-$(CONFIG_UIO_SERCOS3)	+= uio_sercos3.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 3a6934bf7131..5dccf057a7dd 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -67,6 +67,11 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf)
 	return sprintf(buf, "0x%lx\n", mem->size);
 }
 
+static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
+{
+	return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
+}
+
 struct uio_sysfs_entry {
 	struct attribute attr;
 	ssize_t (*show)(struct uio_mem *, char *);
@@ -77,10 +82,13 @@ static struct uio_sysfs_entry addr_attribute =
 	__ATTR(addr, S_IRUGO, map_addr_show, NULL);
 static struct uio_sysfs_entry size_attribute =
 	__ATTR(size, S_IRUGO, map_size_show, NULL);
+static struct uio_sysfs_entry offset_attribute =
+	__ATTR(offset, S_IRUGO, map_offset_show, NULL);
 
 static struct attribute *attrs[] = {
 	&addr_attribute.attr,
 	&size_attribute.attr,
+	&offset_attribute.attr,
 	NULL,	/* need to NULL terminate the list of attributes */
 };
 
@@ -482,15 +490,23 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct uio_device *idev = vma->vm_private_data;
 	struct page *page;
+	unsigned long offset;
 
 	int mi = uio_find_mem_index(vma);
 	if (mi < 0)
 		return VM_FAULT_SIGBUS;
 
+	/*
+	 * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
+	 * to use mem[N].
+	 */
+	offset = (vmf->pgoff - mi) << PAGE_SHIFT;
+
 	if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
-		page = virt_to_page(idev->info->mem[mi].addr);
+		page = virt_to_page(idev->info->mem[mi].addr + offset);
 	else
-		page = vmalloc_to_page((void*)idev->info->mem[mi].addr);
+		page = vmalloc_to_page((void *)idev->info->mem[mi].addr
+							+ offset);
 	get_page(page);
 	vmf->page = page;
 	return 0;
@@ -682,9 +698,9 @@ int __uio_register_device(struct module *owner,
 	if (ret)
 		goto err_get_minor;
 
-	idev->dev = device_create_drvdata(uio_class->class, parent,
-					  MKDEV(uio_major, idev->minor), idev,
-					  "uio%d", idev->minor);
+	idev->dev = device_create(uio_class->class, parent,
+				  MKDEV(uio_major, idev->minor), idev,
+				  "uio%d", idev->minor);
 	if (IS_ERR(idev->dev)) {
 		printk(KERN_ERR "UIO: device register failed\n");
 		ret = PTR_ERR(idev->dev);
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
index 0b4ef39cd85d..d494ce9288c3 100644
--- a/drivers/uio/uio_pdrv.c
+++ b/drivers/uio/uio_pdrv.c
@@ -12,7 +12,7 @@
 #include <linux/uio_driver.h>
 #include <linux/stringify.h>
 
-#define DRIVER_NAME "uio"
+#define DRIVER_NAME "uio_pdrv"
 
 struct uio_platdata {
 	struct uio_info *uioinfo;
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
new file mode 100644
index 000000000000..a6d1b2bc47f3
--- /dev/null
+++ b/drivers/uio/uio_sercos3.c
@@ -0,0 +1,243 @@
+/* sercos3: UIO driver for the Automata Sercos III PCI card
+
+   Copyright (C) 2008 Linutronix GmbH
+     Author: John Ogness <john.ogness@linutronix.de>
+
+   This is a straight-forward UIO driver, where interrupts are disabled
+   by the interrupt handler and re-enabled via a write to the UIO device
+   by the userspace-part.
+
+   The only part that may seem odd is the use of a logical OR when
+   storing and restoring enabled interrupts. This is done because the
+   userspace-part could directly modify the Interrupt Enable Register
+   at any time. To reduce possible conflicts, the kernel driver uses
+   a logical OR to make more controlled changes (rather than blindly
+   overwriting previous values).
+
+   Race conditions exist if the userspace-part directly modifies the
+   Interrupt Enable Register while in operation. The consequences are
+   that certain interrupts would fail to be enabled or disabled. For
+   this reason, the userspace-part should only directly modify the
+   Interrupt Enable Register at the beginning (to get things going).
+   The userspace-part can safely disable interrupts at any time using
+   a write to the UIO device.
+*/
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+#include <linux/io.h>
+
+/* ID's for SERCOS III PCI card (PLX 9030) */
+#define SERCOS_SUB_VENDOR_ID  0x1971
+#define SERCOS_SUB_SYSID_3530 0x3530
+#define SERCOS_SUB_SYSID_3535 0x3535
+#define SERCOS_SUB_SYSID_3780 0x3780
+
+/* Interrupt Enable Register */
+#define IER0_OFFSET 0x08
+
+/* Interrupt Status Register */
+#define ISR0_OFFSET 0x18
+
+struct sercos3_priv {
+	u32 ier0_cache;
+	spinlock_t ier0_cache_lock;
+};
+
+/* this function assumes ier0_cache_lock is locked! */
+static void sercos3_disable_interrupts(struct uio_info *info,
+				       struct sercos3_priv *priv)
+{
+	void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+	/* add enabled interrupts to cache */
+	priv->ier0_cache |= ioread32(ier0);
+
+	/* disable interrupts */
+	iowrite32(0, ier0);
+}
+
+/* this function assumes ier0_cache_lock is locked! */
+static void sercos3_enable_interrupts(struct uio_info *info,
+				      struct sercos3_priv *priv)
+{
+	void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+	/* restore previously enabled interrupts */
+	iowrite32(ioread32(ier0) | priv->ier0_cache, ier0);
+	priv->ier0_cache = 0;
+}
+
+static irqreturn_t sercos3_handler(int irq, struct uio_info *info)
+{
+	struct sercos3_priv *priv = info->priv;
+	void __iomem *isr0 = info->mem[3].internal_addr + ISR0_OFFSET;
+	void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+	if (!(ioread32(isr0) & ioread32(ier0)))
+		return IRQ_NONE;
+
+	spin_lock(&priv->ier0_cache_lock);
+	sercos3_disable_interrupts(info, priv);
+	spin_unlock(&priv->ier0_cache_lock);
+
+	return IRQ_HANDLED;
+}
+
+static int sercos3_irqcontrol(struct uio_info *info, s32 irq_on)
+{
+	struct sercos3_priv *priv = info->priv;
+
+	spin_lock_irq(&priv->ier0_cache_lock);
+	if (irq_on)
+		sercos3_enable_interrupts(info, priv);
+	else
+		sercos3_disable_interrupts(info, priv);
+	spin_unlock_irq(&priv->ier0_cache_lock);
+
+	return 0;
+}
+
+static int sercos3_setup_iomem(struct pci_dev *dev, struct uio_info *info,
+			       int n, int pci_bar)
+{
+	info->mem[n].addr = pci_resource_start(dev, pci_bar);
+	if (!info->mem[n].addr)
+		return -1;
+	info->mem[n].internal_addr = ioremap(pci_resource_start(dev, pci_bar),
+					     pci_resource_len(dev, pci_bar));
+	if (!info->mem[n].internal_addr)
+		return -1;
+	info->mem[n].size = pci_resource_len(dev, pci_bar);
+	info->mem[n].memtype = UIO_MEM_PHYS;
+	return 0;
+}
+
+static int __devinit sercos3_pci_probe(struct pci_dev *dev,
+				       const struct pci_device_id *id)
+{
+	struct uio_info *info;
+	struct sercos3_priv *priv;
+	int i;
+
+	info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	priv = kzalloc(sizeof(struct sercos3_priv), GFP_KERNEL);
+	if (!priv)
+		goto out_free;
+
+	if (pci_enable_device(dev))
+		goto out_free_priv;
+
+	if (pci_request_regions(dev, "sercos3"))
+		goto out_disable;
+
+	/* we only need PCI BAR's 0, 2, 3, 4, 5 */
+	if (sercos3_setup_iomem(dev, info, 0, 0))
+		goto out_unmap;
+	if (sercos3_setup_iomem(dev, info, 1, 2))
+		goto out_unmap;
+	if (sercos3_setup_iomem(dev, info, 2, 3))
+		goto out_unmap;
+	if (sercos3_setup_iomem(dev, info, 3, 4))
+		goto out_unmap;
+	if (sercos3_setup_iomem(dev, info, 4, 5))
+		goto out_unmap;
+
+	spin_lock_init(&priv->ier0_cache_lock);
+	info->priv = priv;
+	info->name = "Sercos_III_PCI";
+	info->version = "0.0.1";
+	info->irq = dev->irq;
+	info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
+	info->handler = sercos3_handler;
+	info->irqcontrol = sercos3_irqcontrol;
+
+	pci_set_drvdata(dev, info);
+
+	if (uio_register_device(&dev->dev, info))
+		goto out_unmap;
+
+	return 0;
+
+out_unmap:
+	for (i = 0; i < 5; i++) {
+		if (info->mem[i].internal_addr)
+			iounmap(info->mem[i].internal_addr);
+	}
+	pci_release_regions(dev);
+out_disable:
+	pci_disable_device(dev);
+out_free_priv:
+	kfree(priv);
+out_free:
+	kfree(info);
+	return -ENODEV;
+}
+
+static void sercos3_pci_remove(struct pci_dev *dev)
+{
+	struct uio_info *info = pci_get_drvdata(dev);
+	int i;
+
+	uio_unregister_device(info);
+	pci_release_regions(dev);
+	pci_disable_device(dev);
+	pci_set_drvdata(dev, NULL);
+	for (i = 0; i < 5; i++) {
+		if (info->mem[i].internal_addr)
+			iounmap(info->mem[i].internal_addr);
+	}
+	kfree(info->priv);
+	kfree(info);
+}
+
+static struct pci_device_id sercos3_pci_ids[] __devinitdata = {
+	{
+		.vendor =       PCI_VENDOR_ID_PLX,
+		.device =       PCI_DEVICE_ID_PLX_9030,
+		.subvendor =    SERCOS_SUB_VENDOR_ID,
+		.subdevice =    SERCOS_SUB_SYSID_3530,
+	},
+	{
+		.vendor =       PCI_VENDOR_ID_PLX,
+		.device =       PCI_DEVICE_ID_PLX_9030,
+		.subvendor =    SERCOS_SUB_VENDOR_ID,
+		.subdevice =    SERCOS_SUB_SYSID_3535,
+	},
+	{
+		.vendor =       PCI_VENDOR_ID_PLX,
+		.device =       PCI_DEVICE_ID_PLX_9030,
+		.subvendor =    SERCOS_SUB_VENDOR_ID,
+		.subdevice =    SERCOS_SUB_SYSID_3780,
+	},
+	{ 0, }
+};
+
+static struct pci_driver sercos3_pci_driver = {
+	.name = "sercos3",
+	.id_table = sercos3_pci_ids,
+	.probe = sercos3_pci_probe,
+	.remove = sercos3_pci_remove,
+};
+
+static int __init sercos3_init_module(void)
+{
+	return pci_register_driver(&sercos3_pci_driver);
+}
+
+static void __exit sercos3_exit_module(void)
+{
+	pci_unregister_driver(&sercos3_pci_driver);
+}
+
+module_init(sercos3_init_module);
+module_exit(sercos3_exit_module);
+
+MODULE_DESCRIPTION("UIO driver for the Automata Sercos III PCI card");
+MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 20290c5b1562..7a4fa791dc19 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1729,9 +1729,9 @@ static int usb_classdev_add(struct usb_device *dev)
 {
 	struct device *cldev;
 
-	cldev = device_create_drvdata(usb_classdev_class, &dev->dev,
-				      dev->dev.devt, NULL, "usbdev%d.%d",
-				      dev->bus->busnum, dev->devnum);
+	cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt,
+			      NULL, "usbdev%d.%d", dev->bus->busnum,
+			      dev->devnum);
 	if (IS_ERR(cldev))
 		return PTR_ERR(cldev);
 	dev->usb_classdev = cldev;
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 6b1b229e38cd..55f7f310924b 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -196,9 +196,9 @@ int usb_register_dev(struct usb_interface *intf,
 		++temp;
 	else
 		temp = name;
-	intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev,
-					      MKDEV(USB_MAJOR, minor), NULL,
-					      "%s", temp);
+	intf->usb_dev = device_create(usb_class->class, &intf->dev,
+				      MKDEV(USB_MAJOR, minor), NULL,
+				      "%s", temp);
 	if (IS_ERR(intf->usb_dev)) {
 		down_write(&minor_rwsem);
 		usb_minors[intf->minor] = NULL;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 8ab389dca2b9..c8035a8216bd 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -818,9 +818,8 @@ static int usb_register_bus(struct usb_bus *bus)
 	set_bit (busnum, busmap.busmap);
 	bus->busnum = busnum;
 
-	bus->dev = device_create_drvdata(usb_host_class, bus->controller,
-					 MKDEV(0, 0), bus,
-					 "usb_host%d", busnum);
+	bus->dev = device_create(usb_host_class, bus->controller, MKDEV(0, 0),
+				 bus, "usb_host%d", busnum);
 	result = PTR_ERR(bus->dev);
 	if (IS_ERR(bus->dev))
 		goto error_create_class_dev;
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index fcb5cb9094d9..2267fa0b51b2 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -22,24 +22,15 @@ obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
 #
 # USB gadget drivers
 #
-C_UTILS =	composite.o usbstring.o config.o epautoconf.o
-
-g_zero-objs			:= zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
-g_ether-objs			:= ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
-g_serial-objs			:= serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS)
-g_midi-objs			:= gmidi.o usbstring.o config.o epautoconf.o
+g_zero-objs			:= zero.o
+g_ether-objs			:= ether.o
+g_serial-objs			:= serial.o
+g_midi-objs			:= gmidi.o
 gadgetfs-objs			:= inode.o
-g_file_storage-objs		:= file_storage.o usbstring.o config.o \
-					epautoconf.o
-g_printer-objs			:= printer.o usbstring.o config.o \
-					epautoconf.o
-g_cdc-objs			:= cdc2.o u_ether.o f_ecm.o \
-					u_serial.o f_acm.o $(C_UTILS)
+g_file_storage-objs		:= file_storage.o
+g_printer-objs			:= printer.o
+g_cdc-objs			:= cdc2.o
 
-ifeq ($(CONFIG_USB_ETH_RNDIS),y)
-	g_ether-objs		+= f_rndis.o rndis.o
-endif
- 
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
 obj-$(CONFIG_USB_ETH)		+= g_ether.o
 obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index a39a4b940c33..a724fc149850 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -43,6 +43,25 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+#include "u_serial.c"
+#include "f_acm.c"
+#include "f_ecm.c"
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
 static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
@@ -148,7 +167,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	int			status;
 
 	if (!can_support_ecm(cdev->gadget)) {
-		ERROR(cdev, "controller '%s' not usable\n", gadget->name);
+		dev_err(&gadget->dev, "controller '%s' not usable\n",
+				gadget->name);
 		return -EINVAL;
 	}
 
@@ -203,7 +223,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	if (status < 0)
 		goto fail1;
 
-	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+	dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
+			DRIVER_DESC);
 
 	return 0;
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index bcac2e68660d..944c8e889ab4 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -96,6 +96,28 @@ static inline bool has_rndis(void)
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_ecm.c"
+#include "f_subset.c"
+#ifdef	CONFIG_USB_ETH_RNDIS
+#include "f_rndis.c"
+#include "rndis.c"
+#endif
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
 /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
@@ -293,7 +315,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 		 * but if the controller isn't recognized at all then
 		 * that assumption is a bit more likely to be wrong.
 		 */
-		WARNING(cdev, "controller '%s' not recognized; trying %s\n",
+		dev_warn(&gadget->dev,
+				"controller '%s' not recognized; trying %s\n",
 				gadget->name,
 				eth_config_driver.label);
 		device_desc.bcdDevice =
@@ -332,7 +355,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 	if (status < 0)
 		goto fail;
 
-	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+	dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
+			DRIVER_DESC);
 
 	return 0;
 
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index a2b5c092bda0..4ae579948e54 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -83,7 +83,7 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
 }
 
 /* peak (theoretical) bulk transfer rate in bits-per-second */
-static inline unsigned bitrate(struct usb_gadget *g)
+static inline unsigned ecm_bitrate(struct usb_gadget *g)
 {
 	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
 		return 13 * 512 * 8 * 1000 * 8;
@@ -107,7 +107,7 @@ static inline unsigned bitrate(struct usb_gadget *g)
  */
 
 #define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
+#define ECM_STATUS_BYTECOUNT		16	/* 8 byte header + data */
 
 
 /* interface descriptor: */
@@ -125,8 +125,8 @@ static struct usb_interface_descriptor ecm_control_intf __initdata = {
 	/* .iInterface = DYNAMIC */
 };
 
-static struct usb_cdc_header_desc header_desc __initdata = {
-	.bLength =		sizeof header_desc,
+static struct usb_cdc_header_desc ecm_header_desc __initdata = {
+	.bLength =		sizeof ecm_header_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
 
@@ -141,8 +141,8 @@ static struct usb_cdc_union_desc ecm_union_desc __initdata = {
 	/* .bSlaveInterface0 =	DYNAMIC */
 };
 
-static struct usb_cdc_ether_desc ether_desc __initdata = {
-	.bLength =		sizeof ether_desc,
+static struct usb_cdc_ether_desc ecm_desc __initdata = {
+	.bLength =		sizeof ecm_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
 
@@ -186,17 +186,17 @@ static struct usb_interface_descriptor ecm_data_intf __initdata = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxPacketSize =	__constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
 	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
 };
 
-static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -204,7 +204,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -212,34 +212,34 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
 	/* CDC ECM control descriptors */
 	(struct usb_descriptor_header *) &ecm_control_intf,
-	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
-	(struct usb_descriptor_header *) &ether_desc,
+	(struct usb_descriptor_header *) &ecm_desc,
 	/* NOTE: status endpoint might need to be removed */
-	(struct usb_descriptor_header *) &fs_notify_desc,
+	(struct usb_descriptor_header *) &fs_ecm_notify_desc,
 	/* data interface, altsettings 0 and 1 */
 	(struct usb_descriptor_header *) &ecm_data_nop_intf,
 	(struct usb_descriptor_header *) &ecm_data_intf,
-	(struct usb_descriptor_header *) &fs_in_desc,
-	(struct usb_descriptor_header *) &fs_out_desc,
+	(struct usb_descriptor_header *) &fs_ecm_in_desc,
+	(struct usb_descriptor_header *) &fs_ecm_out_desc,
 	NULL,
 };
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxPacketSize =	__constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
 	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
 };
-static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -257,19 +257,19 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
 	/* CDC ECM control descriptors */
 	(struct usb_descriptor_header *) &ecm_control_intf,
-	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &ecm_header_desc,
 	(struct usb_descriptor_header *) &ecm_union_desc,
-	(struct usb_descriptor_header *) &ether_desc,
+	(struct usb_descriptor_header *) &ecm_desc,
 	/* NOTE: status endpoint might need to be removed */
-	(struct usb_descriptor_header *) &hs_notify_desc,
+	(struct usb_descriptor_header *) &hs_ecm_notify_desc,
 	/* data interface, altsettings 0 and 1 */
 	(struct usb_descriptor_header *) &ecm_data_nop_intf,
 	(struct usb_descriptor_header *) &ecm_data_intf,
-	(struct usb_descriptor_header *) &hs_in_desc,
-	(struct usb_descriptor_header *) &hs_out_desc,
+	(struct usb_descriptor_header *) &hs_ecm_in_desc,
+	(struct usb_descriptor_header *) &hs_ecm_out_desc,
 	NULL,
 };
 
@@ -329,14 +329,14 @@ static void ecm_do_notify(struct f_ecm *ecm)
 		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
 		event->wValue = cpu_to_le16(0);
 		event->wLength = cpu_to_le16(8);
-		req->length = STATUS_BYTECOUNT;
+		req->length = ECM_STATUS_BYTECOUNT;
 
 		/* SPEED_CHANGE data is up/down speeds in bits/sec */
 		data = req->buf + sizeof *event;
-		data[0] = cpu_to_le32(bitrate(cdev->gadget));
+		data[0] = cpu_to_le32(ecm_bitrate(cdev->gadget));
 		data[1] = data[0];
 
-		DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget));
+		DBG(cdev, "notify speed %d\n", ecm_bitrate(cdev->gadget));
 		ecm->notify_state = ECM_NOTIFY_NONE;
 		break;
 	}
@@ -628,13 +628,13 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	status = -ENODEV;
 
 	/* allocate instance-specific endpoints */
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc);
 	if (!ep)
 		goto fail;
 	ecm->port.in_ep = ep;
 	ep->driver_data = cdev;	/* claim */
 
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
 	if (!ep)
 		goto fail;
 	ecm->port.out_ep = ep;
@@ -644,7 +644,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	 * don't treat it that way.  It's simpler, and some newer CDC
 	 * profiles (wireless handsets) no longer treat it as optional.
 	 */
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc);
 	if (!ep)
 		goto fail;
 	ecm->notify = ep;
@@ -656,47 +656,47 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
 	ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
 	if (!ecm->notify_req)
 		goto fail;
-	ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+	ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
 	if (!ecm->notify_req->buf)
 		goto fail;
 	ecm->notify_req->context = ecm;
 	ecm->notify_req->complete = ecm_notify_complete;
 
 	/* copy descriptors, and track endpoint copies */
-	f->descriptors = usb_copy_descriptors(eth_fs_function);
+	f->descriptors = usb_copy_descriptors(ecm_fs_function);
 	if (!f->descriptors)
 		goto fail;
 
-	ecm->fs.in = usb_find_endpoint(eth_fs_function,
-			f->descriptors, &fs_in_desc);
-	ecm->fs.out = usb_find_endpoint(eth_fs_function,
-			f->descriptors, &fs_out_desc);
-	ecm->fs.notify = usb_find_endpoint(eth_fs_function,
-			f->descriptors, &fs_notify_desc);
+	ecm->fs.in = usb_find_endpoint(ecm_fs_function,
+			f->descriptors, &fs_ecm_in_desc);
+	ecm->fs.out = usb_find_endpoint(ecm_fs_function,
+			f->descriptors, &fs_ecm_out_desc);
+	ecm->fs.notify = usb_find_endpoint(ecm_fs_function,
+			f->descriptors, &fs_ecm_notify_desc);
 
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
 	 */
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_in_desc.bEndpointAddress =
-				fs_in_desc.bEndpointAddress;
-		hs_out_desc.bEndpointAddress =
-				fs_out_desc.bEndpointAddress;
-		hs_notify_desc.bEndpointAddress =
-				fs_notify_desc.bEndpointAddress;
+		hs_ecm_in_desc.bEndpointAddress =
+				fs_ecm_in_desc.bEndpointAddress;
+		hs_ecm_out_desc.bEndpointAddress =
+				fs_ecm_out_desc.bEndpointAddress;
+		hs_ecm_notify_desc.bEndpointAddress =
+				fs_ecm_notify_desc.bEndpointAddress;
 
 		/* copy descriptors, and track endpoint copies */
-		f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+		f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
 		if (!f->hs_descriptors)
 			goto fail;
 
-		ecm->hs.in = usb_find_endpoint(eth_hs_function,
-				f->hs_descriptors, &hs_in_desc);
-		ecm->hs.out = usb_find_endpoint(eth_hs_function,
-				f->hs_descriptors, &hs_out_desc);
-		ecm->hs.notify = usb_find_endpoint(eth_hs_function,
-				f->hs_descriptors, &hs_notify_desc);
+		ecm->hs.in = usb_find_endpoint(ecm_hs_function,
+				f->hs_descriptors, &hs_ecm_in_desc);
+		ecm->hs.out = usb_find_endpoint(ecm_hs_function,
+				f->hs_descriptors, &hs_ecm_out_desc);
+		ecm->hs.notify = usb_find_endpoint(ecm_hs_function,
+				f->hs_descriptors, &hs_ecm_notify_desc);
 	}
 
 	/* NOTE:  all that is done without knowing or caring about
@@ -795,7 +795,7 @@ int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 		if (status < 0)
 			return status;
 		ecm_string_defs[1].id = status;
-		ether_desc.iMACAddress = status;
+		ecm_desc.iMACAddress = status;
 	}
 
 	/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index eda4cde72c82..87dde012dacc 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -70,7 +70,7 @@ static struct usb_interface_descriptor loopback_intf = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_source_desc = {
+static struct usb_endpoint_descriptor fs_loop_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -78,7 +78,7 @@ static struct usb_endpoint_descriptor fs_source_desc = {
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_sink_desc = {
+static struct usb_endpoint_descriptor fs_loop_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -88,14 +88,14 @@ static struct usb_endpoint_descriptor fs_sink_desc = {
 
 static struct usb_descriptor_header *fs_loopback_descs[] = {
 	(struct usb_descriptor_header *) &loopback_intf,
-	(struct usb_descriptor_header *) &fs_sink_desc,
-	(struct usb_descriptor_header *) &fs_source_desc,
+	(struct usb_descriptor_header *) &fs_loop_sink_desc,
+	(struct usb_descriptor_header *) &fs_loop_source_desc,
 	NULL,
 };
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_source_desc = {
+static struct usb_endpoint_descriptor hs_loop_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -103,7 +103,7 @@ static struct usb_endpoint_descriptor hs_source_desc = {
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_sink_desc = {
+static struct usb_endpoint_descriptor hs_loop_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -113,8 +113,8 @@ static struct usb_endpoint_descriptor hs_sink_desc = {
 
 static struct usb_descriptor_header *hs_loopback_descs[] = {
 	(struct usb_descriptor_header *) &loopback_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
+	(struct usb_descriptor_header *) &hs_loop_source_desc,
+	(struct usb_descriptor_header *) &hs_loop_sink_desc,
 	NULL,
 };
 
@@ -152,7 +152,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
 
 	/* allocate endpoints */
 
-	loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+	loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
 	if (!loop->in_ep) {
 autoconf_fail:
 		ERROR(cdev, "%s: can't autoconfigure on %s\n",
@@ -161,17 +161,17 @@ autoconf_fail:
 	}
 	loop->in_ep->driver_data = cdev;	/* claim */
 
-	loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+	loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
 	if (!loop->out_ep)
 		goto autoconf_fail;
 	loop->out_ep->driver_data = cdev;	/* claim */
 
 	/* support high speed hardware */
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
+		hs_loop_source_desc.bEndpointAddress =
+				fs_loop_source_desc.bEndpointAddress;
+		hs_loop_sink_desc.bEndpointAddress =
+				fs_loop_sink_desc.bEndpointAddress;
 		f->hs_descriptors = hs_loopback_descs;
 	}
 
@@ -255,8 +255,10 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
 	struct usb_request			*req;
 	unsigned				i;
 
-	src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
-	sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+	src = ep_choose(cdev->gadget,
+			&hs_loop_source_desc, &fs_loop_source_desc);
+	sink = ep_choose(cdev->gadget,
+			&hs_loop_sink_desc, &fs_loop_sink_desc);
 
 	/* one endpoint writes data back IN to the host */
 	ep = loop->in_ep;
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index acb8d233aa1d..fe1832875771 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -103,8 +103,8 @@ static struct usb_interface_descriptor subset_data_intf __initdata = {
 	/* .iInterface = DYNAMIC */
 };
 
-static struct usb_cdc_header_desc header_desc __initdata = {
-	.bLength =		sizeof header_desc,
+static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
+	.bLength =		sizeof mdlm_header_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
 
@@ -152,7 +152,7 @@ static struct usb_cdc_ether_desc ether_desc __initdata = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -160,7 +160,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -170,18 +170,18 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
 
 static struct usb_descriptor_header *fs_eth_function[] __initdata = {
 	(struct usb_descriptor_header *) &subset_data_intf,
-	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
 	(struct usb_descriptor_header *) &mdlm_detail_desc,
 	(struct usb_descriptor_header *) &ether_desc,
-	(struct usb_descriptor_header *) &fs_in_desc,
-	(struct usb_descriptor_header *) &fs_out_desc,
+	(struct usb_descriptor_header *) &fs_subset_in_desc,
+	(struct usb_descriptor_header *) &fs_subset_out_desc,
 	NULL,
 };
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -189,7 +189,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -199,12 +199,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
 
 static struct usb_descriptor_header *hs_eth_function[] __initdata = {
 	(struct usb_descriptor_header *) &subset_data_intf,
-	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
 	(struct usb_descriptor_header *) &mdlm_detail_desc,
 	(struct usb_descriptor_header *) &ether_desc,
-	(struct usb_descriptor_header *) &hs_in_desc,
-	(struct usb_descriptor_header *) &hs_out_desc,
+	(struct usb_descriptor_header *) &hs_subset_in_desc,
+	(struct usb_descriptor_header *) &hs_subset_out_desc,
 	NULL,
 };
 
@@ -281,13 +281,13 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 	status = -ENODEV;
 
 	/* allocate instance-specific endpoints */
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_in_desc);
 	if (!ep)
 		goto fail;
 	geth->port.in_ep = ep;
 	ep->driver_data = cdev;	/* claim */
 
-	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc);
 	if (!ep)
 		goto fail;
 	geth->port.out_ep = ep;
@@ -297,9 +297,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 	f->descriptors = usb_copy_descriptors(fs_eth_function);
 
 	geth->fs.in = usb_find_endpoint(fs_eth_function,
-			f->descriptors, &fs_in_desc);
+			f->descriptors, &fs_subset_in_desc);
 	geth->fs.out = usb_find_endpoint(fs_eth_function,
-			f->descriptors, &fs_out_desc);
+			f->descriptors, &fs_subset_out_desc);
 
 
 	/* support all relevant hardware speeds... we expect that when
@@ -307,18 +307,18 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
 	 * both speeds
 	 */
 	if (gadget_is_dualspeed(c->cdev->gadget)) {
-		hs_in_desc.bEndpointAddress =
-				fs_in_desc.bEndpointAddress;
-		hs_out_desc.bEndpointAddress =
-				fs_out_desc.bEndpointAddress;
+		hs_subset_in_desc.bEndpointAddress =
+				fs_subset_in_desc.bEndpointAddress;
+		hs_subset_out_desc.bEndpointAddress =
+				fs_subset_out_desc.bEndpointAddress;
 
 		/* copy descriptors, and track endpoint copies */
 		f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
 
 		geth->hs.in = usb_find_endpoint(hs_eth_function,
-				f->hs_descriptors, &hs_in_desc);
+				f->hs_descriptors, &hs_subset_in_desc);
 		geth->hs.out = usb_find_endpoint(hs_eth_function,
-				f->hs_descriptors, &hs_out_desc);
+				f->hs_descriptors, &hs_subset_out_desc);
 	}
 
 	/* NOTE:  all that is done without knowing or caring about
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ea2c31d18080..0c632d22a631 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -245,6 +245,18 @@
 #include "gadget_chips.h"
 
 
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
 /*-------------------------------------------------------------------------*/
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index ea8651e3da1a..6eee760410d6 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -35,6 +35,21 @@
 
 #include "gadget_chips.h"
 
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+/*-------------------------------------------------------------------------*/
+
+
 MODULE_AUTHOR("Ben Williamson");
 MODULE_LICENSE("GPL v2");
 
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index e0090085b78e..2b3b9e1dd2ee 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -53,6 +53,20 @@
 
 #include "gadget_chips.h"
 
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+/*-------------------------------------------------------------------------*/
+
 #define DRIVER_DESC		"Printer Gadget"
 #define DRIVER_VERSION		"2007 OCT 06"
 
@@ -1360,8 +1374,8 @@ printer_bind(struct usb_gadget *gadget)
 
 
 	/* Setup the sysfs files for the printer gadget. */
-	dev->pdev = device_create_drvdata(usb_gadget_class, NULL,
-					  g_printer_devno, NULL, "g_printer");
+	dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
+				  NULL, "g_printer");
 	if (IS_ERR(dev->pdev)) {
 		ERROR(dev, "Failed to create device: g_printer\n");
 		goto fail;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 7228e8562236..8c26f5ea2b83 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -57,11 +57,6 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
 #define rndis_debug		0
 #endif
 
-#define DBG(str,args...) do { \
-	if (rndis_debug) \
-		pr_debug(str , ## args); \
-	} while (0)
-
 #define RNDIS_MAX_CONFIGS	1
 
 
@@ -183,9 +178,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	if (!resp) return -ENOMEM;
 
 	if (buf_len && rndis_debug > 1) {
-		DBG("query OID %08x value, len %d:\n", OID, buf_len);
+		pr_debug("query OID %08x value, len %d:\n", OID, buf_len);
 		for (i = 0; i < buf_len; i += 16) {
-			DBG("%03d: %08x %08x %08x %08x\n", i,
+			pr_debug("%03d: %08x %08x %08x %08x\n", i,
 				get_unaligned_le32(&buf[i]),
 				get_unaligned_le32(&buf[i + 4]),
 				get_unaligned_le32(&buf[i + 8]),
@@ -209,7 +204,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_SUPPORTED_LIST:
-		DBG("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
+		pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
 		length = sizeof (oid_supported_list);
 		count  = length / sizeof (u32);
 		for (i = 0; i < count; i++)
@@ -219,7 +214,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_HARDWARE_STATUS:
-		DBG("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
+		pr_debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
 		/* Bogus question!
 		 * Hardware must be ready to receive high level protocols.
 		 * BTW:
@@ -232,14 +227,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_MEDIA_SUPPORTED:
-		DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
+		pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MEDIA_IN_USE:
-		DBG("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
+		pr_debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
 		/* one medium, one transport... (maybe you do it better) */
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
@@ -247,7 +242,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_FRAME_SIZE:
-		DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
+		pr_debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -258,7 +253,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_GEN_LINK_SPEED:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_LINK_SPEED\n", __func__);
+			pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__);
 		if (rndis_per_dev_params [configNr].media_state
 				== NDIS_MEDIA_STATE_DISCONNECTED)
 			*outbuf = __constant_cpu_to_le32 (0);
@@ -270,7 +265,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
-		DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
+		pr_debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -280,7 +275,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_RECEIVE_BLOCK_SIZE:
-		DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
+		pr_debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
 		if (rndis_per_dev_params [configNr].dev) {
 			*outbuf = cpu_to_le32 (
 				rndis_per_dev_params [configNr].dev->mtu);
@@ -290,7 +285,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_VENDOR_ID:
-		DBG("%s: OID_GEN_VENDOR_ID\n", __func__);
+		pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__);
 		*outbuf = cpu_to_le32 (
 			rndis_per_dev_params [configNr].vendorID);
 		retval = 0;
@@ -298,7 +293,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_VENDOR_DESCRIPTION:
-		DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
+		pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
 		length = strlen (rndis_per_dev_params [configNr].vendorDescr);
 		memcpy (outbuf,
 			rndis_per_dev_params [configNr].vendorDescr, length);
@@ -306,7 +301,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 		break;
 
 	case OID_GEN_VENDOR_DRIVER_VERSION:
-		DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
+		pr_debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
 		/* Created as LE */
 		*outbuf = rndis_driver_version;
 		retval = 0;
@@ -314,14 +309,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_CURRENT_PACKET_FILTER:
-		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
+		pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
 		*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_TOTAL_SIZE:
-		DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
+		pr_debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
 		*outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
 		retval = 0;
 		break;
@@ -329,14 +324,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_GEN_MEDIA_CONNECT_STATUS:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
+			pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
 						.media_state);
 		retval = 0;
 		break;
 
 	case OID_GEN_PHYSICAL_MEDIUM:
-		DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
+		pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
@@ -346,7 +341,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
 	 */
 	case OID_GEN_MAC_OPTIONS:		/* from WinME */
-		DBG("%s: OID_GEN_MAC_OPTIONS\n", __func__);
+		pr_debug("%s: OID_GEN_MAC_OPTIONS\n", __func__);
 		*outbuf = __constant_cpu_to_le32(
 			  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
 			| NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -358,7 +353,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_GEN_XMIT_OK:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_XMIT_OK\n", __func__);
+			pr_debug("%s: OID_GEN_XMIT_OK\n", __func__);
 		if (stats) {
 			*outbuf = cpu_to_le32(stats->tx_packets
 				- stats->tx_errors - stats->tx_dropped);
@@ -369,7 +364,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_GEN_RCV_OK:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_RCV_OK\n", __func__);
+			pr_debug("%s: OID_GEN_RCV_OK\n", __func__);
 		if (stats) {
 			*outbuf = cpu_to_le32(stats->rx_packets
 				- stats->rx_errors - stats->rx_dropped);
@@ -380,7 +375,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_GEN_XMIT_ERROR:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
+			pr_debug("%s: OID_GEN_XMIT_ERROR\n", __func__);
 		if (stats) {
 			*outbuf = cpu_to_le32(stats->tx_errors);
 			retval = 0;
@@ -390,7 +385,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 	/* mandatory */
 	case OID_GEN_RCV_ERROR:
 		if (rndis_debug > 1)
-			DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
+			pr_debug("%s: OID_GEN_RCV_ERROR\n", __func__);
 		if (stats) {
 			*outbuf = cpu_to_le32(stats->rx_errors);
 			retval = 0;
@@ -399,7 +394,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_GEN_RCV_NO_BUFFER:
-		DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
+		pr_debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
 		if (stats) {
 			*outbuf = cpu_to_le32(stats->rx_dropped);
 			retval = 0;
@@ -410,7 +405,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_802_3_PERMANENT_ADDRESS:
-		DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
+		pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = ETH_ALEN;
 			memcpy (outbuf,
@@ -422,7 +417,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_802_3_CURRENT_ADDRESS:
-		DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
+		pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
 		if (rndis_per_dev_params [configNr].dev) {
 			length = ETH_ALEN;
 			memcpy (outbuf,
@@ -434,7 +429,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_802_3_MULTICAST_LIST:
-		DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+		pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 		/* Multicast base address only */
 		*outbuf = __constant_cpu_to_le32 (0xE0000000);
 		retval = 0;
@@ -442,21 +437,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_802_3_MAXIMUM_LIST_SIZE:
-		DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
+		pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
 		/* Multicast base address only */
 		*outbuf = __constant_cpu_to_le32 (1);
 		retval = 0;
 		break;
 
 	case OID_802_3_MAC_OPTIONS:
-		DBG("%s: OID_802_3_MAC_OPTIONS\n", __func__);
+		pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
 		break;
 
 	/* ieee802.3 statistics OIDs (table 4-4) */
 
 	/* mandatory */
 	case OID_802_3_RCV_ERROR_ALIGNMENT:
-		DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
+		pr_debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
 		if (stats) {
 			*outbuf = cpu_to_le32(stats->rx_frame_errors);
 			retval = 0;
@@ -465,14 +460,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
 	/* mandatory */
 	case OID_802_3_XMIT_ONE_COLLISION:
-		DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
+		pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_802_3_XMIT_MORE_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
+		pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
@@ -504,9 +499,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
 		return -ENOMEM;
 
 	if (buf_len && rndis_debug > 1) {
-		DBG("set OID %08x value, len %d:\n", OID, buf_len);
+		pr_debug("set OID %08x value, len %d:\n", OID, buf_len);
 		for (i = 0; i < buf_len; i += 16) {
-			DBG("%03d: %08x %08x %08x %08x\n", i,
+			pr_debug("%03d: %08x %08x %08x %08x\n", i,
 				get_unaligned_le32(&buf[i]),
 				get_unaligned_le32(&buf[i + 4]),
 				get_unaligned_le32(&buf[i + 8]),
@@ -525,7 +520,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
 		 *	MULTICAST, ALL_MULTICAST, BROADCAST
 		 */
 		*params->filter = (u16)get_unaligned_le32(buf);
-		DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+		pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
 			__func__, *params->filter);
 
 		/* this call has a significant side effect:  it's
@@ -547,7 +542,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
 
 	case OID_802_3_MULTICAST_LIST:
 		/* I think we can ignore this */
-		DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+		pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 		retval = 0;
 		break;
 
@@ -606,7 +601,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
 	rndis_resp_t            *r;
 	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
-	// DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
+	/* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
 	if (!params->dev)
 		return -ENOTSUPP;
 
@@ -659,15 +654,15 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
 	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
 #ifdef	VERBOSE_DEBUG
-	DBG("%s: Length: %d\n", __func__, BufLength);
-	DBG("%s: Offset: %d\n", __func__, BufOffset);
-	DBG("%s: InfoBuffer: ", __func__);
+	pr_debug("%s: Length: %d\n", __func__, BufLength);
+	pr_debug("%s: Offset: %d\n", __func__, BufOffset);
+	pr_debug("%s: InfoBuffer: ", __func__);
 
 	for (i = 0; i < BufLength; i++) {
-		DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+		pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
 	}
 
-	DBG("\n");
+	pr_debug("\n");
 #endif
 
 	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
@@ -821,14 +816,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 	/* For USB: responses may take up to 10 seconds */
 	switch (MsgType) {
 	case REMOTE_NDIS_INITIALIZE_MSG:
-		DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+		pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
 			__func__ );
 		params->state = RNDIS_INITIALIZED;
 		return  rndis_init_response (configNr,
 					(rndis_init_msg_type *) buf);
 
 	case REMOTE_NDIS_HALT_MSG:
-		DBG("%s: REMOTE_NDIS_HALT_MSG\n",
+		pr_debug("%s: REMOTE_NDIS_HALT_MSG\n",
 			__func__ );
 		params->state = RNDIS_UNINITIALIZED;
 		if (params->dev) {
@@ -846,7 +841,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 					(rndis_set_msg_type *) buf);
 
 	case REMOTE_NDIS_RESET_MSG:
-		DBG("%s: REMOTE_NDIS_RESET_MSG\n",
+		pr_debug("%s: REMOTE_NDIS_RESET_MSG\n",
 			__func__ );
 		return rndis_reset_response (configNr,
 					(rndis_reset_msg_type *) buf);
@@ -854,7 +849,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 	case REMOTE_NDIS_KEEPALIVE_MSG:
 		/* For USB: host does this every 5 seconds */
 		if (rndis_debug > 1)
-			DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+			pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
 				__func__ );
 		return rndis_keepalive_response (configNr,
 						 (rndis_keepalive_msg_type *)
@@ -870,7 +865,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 		{
 			unsigned i;
 			for (i = 0; i < MsgLength; i += 16) {
-				DBG("%03d: "
+				pr_debug("%03d: "
 					" %02x %02x %02x %02x"
 					" %02x %02x %02x %02x"
 					" %02x %02x %02x %02x"
@@ -905,18 +900,18 @@ int rndis_register(void (*resp_avail)(void *v), void *v)
 			rndis_per_dev_params [i].used = 1;
 			rndis_per_dev_params [i].resp_avail = resp_avail;
 			rndis_per_dev_params [i].v = v;
-			DBG("%s: configNr = %d\n", __func__, i);
+			pr_debug("%s: configNr = %d\n", __func__, i);
 			return i;
 		}
 	}
-	DBG("failed\n");
+	pr_debug("failed\n");
 
 	return -ENODEV;
 }
 
 void rndis_deregister (int configNr)
 {
-	DBG("%s: \n", __func__ );
+	pr_debug("%s: \n", __func__);
 
 	if (configNr >= RNDIS_MAX_CONFIGS) return;
 	rndis_per_dev_params [configNr].used = 0;
@@ -926,7 +921,7 @@ void rndis_deregister (int configNr)
 
 int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
 {
-	DBG("%s:\n", __func__ );
+	pr_debug("%s:\n", __func__);
 	if (!dev)
 		return -EINVAL;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
@@ -939,7 +934,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
 
 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 {
-	DBG("%s:\n", __func__ );
+	pr_debug("%s:\n", __func__);
 	if (!vendorDescr) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -951,7 +946,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 
 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
 {
-	DBG("%s: %u %u\n", __func__, medium, speed);
+	pr_debug("%s: %u %u\n", __func__, medium, speed);
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
 	rndis_per_dev_params [configNr].medium = medium;
@@ -1114,7 +1109,7 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
 			break;
 		default:
 			if (fl_speed) p->speed = speed;
-			else DBG("%c is not valid\n", c);
+			else pr_debug("%c is not valid\n", c);
 			break;
 		}
 
@@ -1159,12 +1154,12 @@ int __init rndis_init (void)
 					&rndis_proc_fops,
 					(void *)(rndis_per_dev_params + i))))
 		{
-			DBG("%s :remove entries", __func__);
+			pr_debug("%s :remove entries", __func__);
 			while (i) {
 				sprintf (name, NAME_TEMPLATE, --i);
 				remove_proc_entry (name, NULL);
 			}
-			DBG("\n");
+			pr_debug("\n");
 			return -EIO;
 		}
 #endif
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b3699afff002..3faa7a7022df 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -30,6 +30,24 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_acm.c"
+#include "f_serial.c"
+#include "u_serial.c"
+
+/*-------------------------------------------------------------------------*/
+
 /* Thanks to NetChip Technologies for donating this product ID.
 *
 * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 3791e6271903..dbd575a194f3 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -52,7 +52,7 @@
  * this single "physical" link to be used by multiple virtual links.)
  */
 
-#define DRIVER_VERSION	"29-May-2008"
+#define UETH__VERSION	"29-May-2008"
 
 struct eth_dev {
 	/* lock is held while accessing port_usb
@@ -170,7 +170,7 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
 	struct eth_dev	*dev = netdev_priv(net);
 
 	strlcpy(p->driver, "g_ether", sizeof p->driver);
-	strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
+	strlcpy(p->version, UETH__VERSION, sizeof p->version);
 	strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
 	strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
 }
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index aa0bd4f126a1..361d9659ac48 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -59,6 +59,23 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_sourcesink.c"
+#include "f_loopback.c"
+
+/*-------------------------------------------------------------------------*/
+
 #define DRIVER_VERSION		"Cinco de Mayo 2008"
 
 static const char longname[] = "Gadget Zero";
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index db645936eedd..1f0c2cf26e5d 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -123,14 +123,10 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
 
 static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
 {
-	if (!list_empty(&td->list)) {
-		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
-		WARN_ON(1);
-	}
-	if (!list_empty(&td->fl_list)) {
-		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
-		WARN_ON(1);
-	}
+	if (!list_empty(&td->list))
+		dev_WARN(uhci_dev(uhci), "td %p still in list!\n", td);
+	if (!list_empty(&td->fl_list))
+		dev_WARN(uhci_dev(uhci), "td %p still in fl_list!\n", td);
 
 	dma_pool_free(uhci->td_pool, td, td->dma_handle);
 }
@@ -295,10 +291,8 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
 static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
-	if (!list_empty(&qh->queue)) {
-		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
-		WARN_ON(1);
-	}
+	if (!list_empty(&qh->queue))
+		dev_WARN(uhci_dev(uhci), "qh %p list not empty!\n", qh);
 
 	list_del(&qh->node);
 	if (qh->udev) {
@@ -746,11 +740,9 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
 {
 	struct uhci_td *td, *tmp;
 
-	if (!list_empty(&urbp->node)) {
-		dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
+	if (!list_empty(&urbp->node))
+		dev_WARN(uhci_dev(uhci), "urb %p still on QH's list!\n",
 				urbp->urb);
-		WARN_ON(1);
-	}
 
 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
 		uhci_remove_td_from_urbp(td);
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 4cfa25b0f44e..cc8e0a926f99 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -595,9 +595,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
         } while(value);
         kit->dev_no = bit;
 
-	kit->dev = device_create_drvdata(phidget_class, &kit->udev->dev,
-					MKDEV(0, 0), kit,
-					"interfacekit%d", kit->dev_no);
+	kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0),
+				 kit, "interfacekit%d", kit->dev_no);
         if (IS_ERR(kit->dev)) {
                 rc = PTR_ERR(kit->dev);
                 kit->dev = NULL;
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 9b4696f21b22..38088b44349e 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -365,9 +365,8 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
 	} while(value);
 	mc->dev_no = bit;
 
-	mc->dev = device_create_drvdata(phidget_class, &mc->udev->dev,
-					MKDEV(0, 0), mc,
-					"motorcontrol%d", mc->dev_no);
+	mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc,
+				"motorcontrol%d", mc->dev_no);
 	if (IS_ERR(mc->dev)) {
 		rc = PTR_ERR(mc->dev);
 		mc->dev = NULL;
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index 1ca7ddb41d4d..bef6fe16364b 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -275,9 +275,8 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
         } while (value);
 	dev->dev_no = bit;
 
-	dev->dev = device_create_drvdata(phidget_class, &dev->udev->dev,
-					 MKDEV(0, 0), dev,
-					 "servo%d", dev->dev_no);
+	dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0),
+				 dev, "servo%d", dev->dev_no);
 	if (IS_ERR(dev->dev)) {
 		rc = PTR_ERR(dev->dev);
 		dev->dev = NULL;
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 6566fc0a3228..c9de3f027aab 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1162,9 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
 	if (minor >= MON_BIN_MAX_MINOR)
 		return 0;
 
-	dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL,
-				    MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
-				    "usbmon%d", minor);
+	dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL,
+			    MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
+			    "usbmon%d", minor);
 	if (IS_ERR(dev))
 		return 0;
 
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 93a080e827cc..64b3d30027b8 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3573,8 +3573,8 @@ static int __init fb_console_init(void)
 
 	acquire_console_sem();
 	fb_register_client(&fbcon_event_notifier);
-	fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
-					     NULL, "fbcon");
+	fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
+				     "fbcon");
 
 	if (IS_ERR(fbcon_device)) {
 		printk(KERN_WARNING "Unable to create device "
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
index 6ef800bdf482..4830b1bf51e5 100644
--- a/drivers/video/display/display-sysfs.c
+++ b/drivers/video/display/display-sysfs.c
@@ -153,12 +153,9 @@ struct display_device *display_device_register(struct display_driver *driver,
 		mutex_unlock(&allocated_dsp_lock);
 
 		if (!ret) {
-			new_dev->dev = device_create_drvdata(display_class,
-							     parent,
-							     MKDEV(0,0),
-							     new_dev,
-							     "display%d",
-							     new_dev->idx);
+			new_dev->dev = device_create(display_class, parent,
+						     MKDEV(0, 0), new_dev,
+						     "display%d", new_dev->idx);
 			if (!IS_ERR(new_dev->dev)) {
 				new_dev->parent = parent;
 				new_dev->driver = driver;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 3f18bb9abad0..217c5118ae9e 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1430,9 +1430,8 @@ register_framebuffer(struct fb_info *fb_info)
 			break;
 	fb_info->node = i;
 
-	fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
-					     MKDEV(FB_MAJOR, i), NULL,
-					     "fb%d", i);
+	fb_info->dev = device_create(fb_class, fb_info->device,
+				     MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
 	if (IS_ERR(fb_info->dev)) {
 		/* Not fatal */
 		printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 0d9b80ec689c..cfd29da714d1 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -362,9 +362,8 @@ static int init_coda_psdev(void)
 		goto out_chrdev;
 	}		
 	for (i = 0; i < MAX_CODADEVS; i++)
-		device_create_drvdata(coda_psdev_class, NULL,
-				      MKDEV(CODA_PSDEV_MAJOR, i),
-				      NULL, "cfs%d", i);
+		device_create(coda_psdev_class, NULL,
+			      MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
 	coda_sysctl_init();
 	goto out;
 
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 006fc64227dd..66f6e58a7e4b 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -61,6 +61,7 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
 	int size = dentry->d_inode->i_size;
 	loff_t offs = *off;
 	int count = min_t(size_t, bytes, PAGE_SIZE);
+	char *temp;
 
 	if (size) {
 		if (offs > size)
@@ -69,23 +70,33 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
 			count = size - offs;
 	}
 
+	temp = kmalloc(count, GFP_KERNEL);
+	if (!temp)
+		return -ENOMEM;
+
 	mutex_lock(&bb->mutex);
 
 	count = fill_read(dentry, bb->buffer, offs, count);
-	if (count < 0)
-		goto out_unlock;
+	if (count < 0) {
+		mutex_unlock(&bb->mutex);
+		goto out_free;
+	}
 
-	if (copy_to_user(userbuf, bb->buffer, count)) {
+	memcpy(temp, bb->buffer, count);
+
+	mutex_unlock(&bb->mutex);
+
+	if (copy_to_user(userbuf, temp, count)) {
 		count = -EFAULT;
-		goto out_unlock;
+		goto out_free;
 	}
 
 	pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
 
 	*off = offs + count;
 
- out_unlock:
-	mutex_unlock(&bb->mutex);
+ out_free:
+	kfree(temp);
 	return count;
 }
 
@@ -118,6 +129,7 @@ static ssize_t write(struct file *file, const char __user *userbuf,
 	int size = dentry->d_inode->i_size;
 	loff_t offs = *off;
 	int count = min_t(size_t, bytes, PAGE_SIZE);
+	char *temp;
 
 	if (size) {
 		if (offs > size)
@@ -126,19 +138,27 @@ static ssize_t write(struct file *file, const char __user *userbuf,
 			count = size - offs;
 	}
 
-	mutex_lock(&bb->mutex);
+	temp = kmalloc(count, GFP_KERNEL);
+	if (!temp)
+		return -ENOMEM;
 
-	if (copy_from_user(bb->buffer, userbuf, count)) {
+	if (copy_from_user(temp, userbuf, count)) {
 		count = -EFAULT;
-		goto out_unlock;
+		goto out_free;
 	}
 
+	mutex_lock(&bb->mutex);
+
+	memcpy(bb->buffer, temp, count);
+
 	count = flush_write(dentry, bb->buffer, offs, count);
+	mutex_unlock(&bb->mutex);
+
 	if (count > 0)
 		*off = offs + count;
 
- out_unlock:
-	mutex_unlock(&bb->mutex);
+out_free:
+	kfree(temp);
 	return count;
 }
 
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index aedaeba82ae5..3a05a596e3b4 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -370,17 +370,17 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
 	memset(acxt, 0, sizeof(*acxt));
 	acxt->parent_sd = parent_sd;
 
-	/* Lookup parent inode.  inode initialization and I_NEW
-	 * clearing are protected by sysfs_mutex.  By grabbing it and
-	 * looking up with _nowait variant, inode state can be
-	 * determined reliably.
+	/* Lookup parent inode.  inode initialization is protected by
+	 * sysfs_mutex, so inode existence can be determined by
+	 * looking up inode while holding sysfs_mutex.
 	 */
 	mutex_lock(&sysfs_mutex);
 
-	inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
-				parent_sd);
+	inode = ilookup5(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
+			 parent_sd);
+	if (inode) {
+		WARN_ON(inode->i_state & I_NEW);
 
-	if (inode && !(inode->i_state & I_NEW)) {
 		/* parent inode available */
 		acxt->parent_inode = inode;
 
@@ -393,8 +393,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
 			mutex_lock(&inode->i_mutex);
 			mutex_lock(&sysfs_mutex);
 		}
-	} else
-		iput(inode);
+	}
 }
 
 /**
@@ -636,6 +635,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
 
 	return sd;
 }
+EXPORT_SYMBOL_GPL(sysfs_get_dirent);
 
 static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
 		      const char *name, struct sysfs_dirent **p_sd)
@@ -829,16 +829,12 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
 	if (!new_dentry)
 		goto out_unlock;
 
-	/* rename kobject and sysfs_dirent */
+	/* rename sysfs_dirent */
 	error = -ENOMEM;
 	new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
 	if (!new_name)
 		goto out_unlock;
 
-	error = kobject_set_name(kobj, "%s", new_name);
-	if (error)
-		goto out_unlock;
-
 	dup_name = sd->s_name;
 	sd->s_name = new_name;
 
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index c9e4e5091da1..1f4a3f877262 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -19,10 +19,18 @@
 #include <linux/poll.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/limits.h>
 #include <asm/uaccess.h>
 
 #include "sysfs.h"
 
+/* used in crash dumps to help with debugging */
+static char last_sysfs_file[PATH_MAX];
+void sysfs_printk_last_file(void)
+{
+	printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file);
+}
+
 /*
  * There's one sysfs_buffer for each open file and one
  * sysfs_open_dirent for each sysfs_dirent with one or more open
@@ -328,6 +336,11 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 	struct sysfs_buffer *buffer;
 	struct sysfs_ops *ops;
 	int error = -EACCES;
+	char *p;
+
+	p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
+	if (p)
+		memmove(last_sysfs_file, p, strlen(p) + 1);
 
 	/* need attr_sd for attr and ops, its parent for kobj */
 	if (!sysfs_get_active_two(attr_sd))
@@ -440,7 +453,23 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
 	return POLLERR|POLLPRI;
 }
 
-void sysfs_notify(struct kobject *k, char *dir, char *attr)
+void sysfs_notify_dirent(struct sysfs_dirent *sd)
+{
+	struct sysfs_open_dirent *od;
+
+	spin_lock(&sysfs_open_dirent_lock);
+
+	od = sd->s_attr.open;
+	if (od) {
+		atomic_inc(&od->event);
+		wake_up_interruptible(&od->poll);
+	}
+
+	spin_unlock(&sysfs_open_dirent_lock);
+}
+EXPORT_SYMBOL_GPL(sysfs_notify_dirent);
+
+void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
 {
 	struct sysfs_dirent *sd = k->sd;
 
@@ -450,19 +479,8 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr)
 		sd = sysfs_find_dirent(sd, dir);
 	if (sd && attr)
 		sd = sysfs_find_dirent(sd, attr);
-	if (sd) {
-		struct sysfs_open_dirent *od;
-
-		spin_lock(&sysfs_open_dirent_lock);
-
-		od = sd->s_attr.open;
-		if (od) {
-			atomic_inc(&od->event);
-			wake_up_interruptible(&od->poll);
-		}
-
-		spin_unlock(&sysfs_open_dirent_lock);
-	}
+	if (sd)
+		sysfs_notify_dirent(sd);
 
 	mutex_unlock(&sysfs_mutex);
 }
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 14f0023984d7..ab343e371d64 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -16,6 +16,7 @@
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include "sysfs.h"
 
@@ -115,3 +116,17 @@ out_err:
 	sysfs_dir_cachep = NULL;
 	goto out;
 }
+
+#undef sysfs_get
+struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+	return __sysfs_get(sd);
+}
+EXPORT_SYMBOL_GPL(sysfs_get);
+
+#undef sysfs_put
+void sysfs_put(struct sysfs_dirent *sd)
+{
+	__sysfs_put(sd);
+}
+EXPORT_SYMBOL_GPL(sysfs_put);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a5db496f71c7..93c6d6b27c4d 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -124,7 +124,7 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
 			struct sysfs_dirent **p_sd);
 void sysfs_remove_subdir(struct sysfs_dirent *sd);
 
-static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
 {
 	if (sd) {
 		WARN_ON(!atomic_read(&sd->s_count));
@@ -132,12 +132,14 @@ static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
 	}
 	return sd;
 }
+#define sysfs_get(sd) __sysfs_get(sd)
 
-static inline void sysfs_put(struct sysfs_dirent *sd)
+static inline void __sysfs_put(struct sysfs_dirent *sd)
 {
 	if (sd && atomic_dec_and_test(&sd->s_count))
 		release_sysfs_dirent(sd);
 }
+#define sysfs_put(sd) __sysfs_put(sd)
 
 /*
  * inode.c
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 7440a0dceddb..74c5faf26c05 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -268,7 +268,15 @@
 	CPU_DISCARD(init.data)						\
 	CPU_DISCARD(init.rodata)					\
 	MEM_DISCARD(init.data)						\
-	MEM_DISCARD(init.rodata)
+	MEM_DISCARD(init.rodata)					\
+	/* implement dynamic printk debug */				\
+	VMLINUX_SYMBOL(__start___verbose_strings) = .;                  \
+	*(__verbose_strings)                                            \
+	VMLINUX_SYMBOL(__stop___verbose_strings) = .;                   \
+	. = ALIGN(8);							\
+	VMLINUX_SYMBOL(__start___verbose) = .;                          \
+	*(__verbose)                                                    \
+	VMLINUX_SYMBOL(__stop___verbose) = .;
 
 #define INIT_TEXT							\
 	*(.init.text)							\
diff --git a/include/linux/device.h b/include/linux/device.h
index 246937c9cbc7..987f5912720a 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -90,6 +90,9 @@ int __must_check 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));
 /*
  * Bus notifiers: Get notified of addition/removal of devices
  * and binding/unbinding of drivers to devices.
@@ -502,7 +505,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
 				    dev_t devt, void *drvdata,
 				    const char *fmt, ...)
 				    __attribute__((format(printf, 5, 6)));
-#define device_create_drvdata	device_create
 extern void device_destroy(struct class *cls, dev_t devt);
 
 /*
@@ -551,7 +553,11 @@ extern const char *dev_driver_string(const struct device *dev);
 #define dev_info(dev, format, arg...)		\
 	dev_printk(KERN_INFO , dev , format , ## arg)
 
-#ifdef DEBUG
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#define dev_dbg(dev, format, ...) do { \
+	dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
+	} while (0)
+#elif defined(DEBUG)
 #define dev_dbg(dev, format, arg...)		\
 	dev_printk(KERN_DEBUG , dev , format , ## arg)
 #else
@@ -567,6 +573,14 @@ extern const char *dev_driver_string(const struct device *dev);
 	({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
 #endif
 
+/*
+ * dev_WARN() acts like dev_printk(), but with the key difference
+ * of using a WARN/WARN_ON to get the message out, including the
+ * file/line information and a backtrace.
+ */
+#define dev_WARN(dev, format, arg...) \
+	WARN(1, "Device: %s\n" format, dev_driver_string(dev), ## arg);
+
 /* Create alias, so I can be autoloaded. */
 #define MODULE_ALIAS_CHARDEV(major,minor) \
 	MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
diff --git a/include/linux/dynamic_printk.h b/include/linux/dynamic_printk.h
new file mode 100644
index 000000000000..2d528d009074
--- /dev/null
+++ b/include/linux/dynamic_printk.h
@@ -0,0 +1,93 @@
+#ifndef _DYNAMIC_PRINTK_H
+#define _DYNAMIC_PRINTK_H
+
+#define DYNAMIC_DEBUG_HASH_BITS 6
+#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS)
+
+#define TYPE_BOOLEAN 1
+
+#define DYNAMIC_ENABLED_ALL 0
+#define DYNAMIC_ENABLED_NONE 1
+#define DYNAMIC_ENABLED_SOME 2
+
+extern int dynamic_enabled;
+
+/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+extern long long dynamic_printk_enabled;
+extern long long dynamic_printk_enabled2;
+
+struct mod_debug {
+	char *modname;
+	char *logical_modname;
+	char *flag_names;
+	int type;
+	int hash;
+	int hash2;
+} __attribute__((aligned(8)));
+
+int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
+					char *flags, int hash, int hash2);
+
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+extern int unregister_dynamic_debug_module(char *mod_name);
+extern int __dynamic_dbg_enabled_helper(char *modname, int type,
+					int value, int hash);
+
+#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({	     \
+	int __ret = 0;							     \
+	if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) &&	     \
+			(dynamic_printk_enabled2 & (1LL << DEBUG_HASH2))))   \
+			__ret = __dynamic_dbg_enabled_helper(module, type,   \
+								value, hash);\
+	__ret; })
+
+#define dynamic_pr_debug(fmt, ...) do {					    \
+	static char mod_name[]						    \
+	__attribute__((section("__verbose_strings")))			    \
+	 = KBUILD_MODNAME;						    \
+	static struct mod_debug descriptor				    \
+	__used								    \
+	__attribute__((section("__verbose"), aligned(8))) =		    \
+	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
+	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \
+						0, 0, DEBUG_HASH))	    \
+		printk(KERN_DEBUG KBUILD_MODNAME ":" fmt,		    \
+				##__VA_ARGS__);				    \
+	} while (0)
+
+#define dynamic_dev_dbg(dev, format, ...) do {				    \
+	static char mod_name[]						    \
+	__attribute__((section("__verbose_strings")))			    \
+	 = KBUILD_MODNAME;						    \
+	static struct mod_debug descriptor				    \
+	__used								    \
+	__attribute__((section("__verbose"), aligned(8))) =		    \
+	{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
+	if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,		    \
+						0, 0, DEBUG_HASH))	    \
+			dev_printk(KERN_DEBUG, dev,			    \
+					KBUILD_MODNAME ": " format,	    \
+					##__VA_ARGS__);			    \
+	} while (0)
+
+#else
+
+static inline int unregister_dynamic_debug_module(const char *mod_name)
+{
+	return 0;
+}
+static inline int __dynamic_dbg_enabled_helper(char *modname, int type,
+						int value, int hash)
+{
+	return 0;
+}
+
+#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({ 0; })
+#define dynamic_pr_debug(fmt, ...)  do { } while (0)
+#define dynamic_dev_dbg(dev, format, ...)  do { } while (0)
+#endif
+
+#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e971c55f45ac..1f3cd8ad0523 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -16,6 +16,7 @@
 #include <linux/log2.h>
 #include <linux/typecheck.h>
 #include <linux/ratelimit.h>
+#include <linux/dynamic_printk.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -304,8 +305,12 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 #define pr_info(fmt, arg...) \
 	printk(KERN_INFO fmt, ##arg)
 
-#ifdef DEBUG
 /* If you are writing a driver, please use dev_dbg instead */
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#define pr_debug(fmt, ...) do { \
+	dynamic_pr_debug(fmt, ##__VA_ARGS__); \
+	} while (0)
+#elif defined(DEBUG)
 #define pr_debug(fmt, arg...) \
 	printk(KERN_DEBUG fmt, ##arg)
 #else
diff --git a/include/linux/module.h b/include/linux/module.h
index 68e09557c951..a41555cbe00a 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -345,7 +345,6 @@ struct module
 	/* Reference counts */
 	struct module_ref ref[NR_CPUS];
 #endif
-
 };
 #ifndef MODULE_ARCH_INIT
 #define MODULE_ARCH_INIT {}
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 95ac21ab3a09..4b8cc6a32479 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -37,6 +37,8 @@ extern int platform_add_devices(struct platform_device **, int);
 
 extern struct platform_device *platform_device_register_simple(const char *, int id,
 					struct resource *, unsigned int);
+extern struct platform_device *platform_device_register_data(struct device *,
+		const char *, int, const void *, size_t);
 
 extern struct platform_device *platform_device_alloc(const char *name, int id);
 extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 37fa24152bd8..b330e289d71f 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -78,6 +78,8 @@ struct sysfs_ops {
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
+struct sysfs_dirent;
+
 #ifdef CONFIG_SYSFS
 
 int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
@@ -117,9 +119,14 @@ int sysfs_add_file_to_group(struct kobject *kobj,
 void sysfs_remove_file_from_group(struct kobject *kobj,
 			const struct attribute *attr, const char *group);
 
-void sysfs_notify(struct kobject *kobj, char *dir, char *attr);
-
-extern int __must_check sysfs_init(void);
+void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
+void sysfs_notify_dirent(struct sysfs_dirent *sd);
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+				      const unsigned char *name);
+struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
+void sysfs_put(struct sysfs_dirent *sd);
+void sysfs_printk_last_file(void);
+int __must_check sysfs_init(void);
 
 #else /* CONFIG_SYSFS */
 
@@ -222,7 +229,24 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj,
 {
 }
 
-static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr)
+static inline void sysfs_notify(struct kobject *kobj, const char *dir,
+				const char *attr)
+{
+}
+static inline void sysfs_notify_dirent(struct sysfs_dirent *sd)
+{
+}
+static inline
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+				      const unsigned char *name)
+{
+	return NULL;
+}
+static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+	return NULL;
+}
+static inline void sysfs_put(struct sysfs_dirent *sd)
 {
 }
 
@@ -231,6 +255,10 @@ static inline int __must_check sysfs_init(void)
 	return 0;
 }
 
+static inline void sysfs_printk_last_file(void)
+{
+}
+
 #endif /* CONFIG_SYSFS */
 
 #endif /* _SYSFS_H_ */
diff --git a/kernel/module.c b/kernel/module.c
index dd9ac6ad5cb9..b7205f67cfaf 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -784,6 +784,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
 	mutex_lock(&module_mutex);
 	/* Store the name of the last unloaded module for diagnostic purposes */
 	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
+	unregister_dynamic_debug_module(mod->name);
 	free_module(mod);
 
  out:
@@ -1173,7 +1174,7 @@ static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
 		while (i-- > 0)
 			sysfs_remove_bin_file(notes_attrs->dir,
 					      &notes_attrs->attrs[i]);
-		kobject_del(notes_attrs->dir);
+		kobject_put(notes_attrs->dir);
 	}
 	kfree(notes_attrs);
 }
@@ -1783,6 +1784,33 @@ static inline void add_kallsyms(struct module *mod,
 }
 #endif /* CONFIG_KALLSYMS */
 
+#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
+static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex)
+{
+	struct mod_debug *debug_info;
+	unsigned long pos, end;
+	unsigned int num_verbose;
+
+	pos = sechdrs[verboseindex].sh_addr;
+	num_verbose = sechdrs[verboseindex].sh_size /
+				sizeof(struct mod_debug);
+	end = pos + (num_verbose * sizeof(struct mod_debug));
+
+	for (; pos < end; pos += sizeof(struct mod_debug)) {
+		debug_info = (struct mod_debug *)pos;
+		register_dynamic_debug_module(debug_info->modname,
+			debug_info->type, debug_info->logical_modname,
+			debug_info->flag_names, debug_info->hash,
+			debug_info->hash2);
+	}
+}
+#else
+static inline void dynamic_printk_setup(Elf_Shdr *sechdrs,
+					unsigned int verboseindex)
+{
+}
+#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
+
 static void *module_alloc_update_bounds(unsigned long size)
 {
 	void *ret = module_alloc(size);
@@ -1831,6 +1859,7 @@ static noinline struct module *load_module(void __user *umod,
 #endif
 	unsigned int markersindex;
 	unsigned int markersstringsindex;
+	unsigned int verboseindex;
 	struct module *mod;
 	long err = 0;
 	void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -2117,6 +2146,7 @@ static noinline struct module *load_module(void __user *umod,
 	markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
  	markersstringsindex = find_sec(hdr, sechdrs, secstrings,
 					"__markers_strings");
+	verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose");
 
 	/* Now do relocations. */
 	for (i = 1; i < hdr->e_shnum; i++) {
@@ -2167,6 +2197,7 @@ static noinline struct module *load_module(void __user *umod,
 		marker_update_probe_range(mod->markers,
 			mod->markers + mod->num_markers);
 #endif
+	dynamic_printk_setup(sechdrs, verboseindex);
 	err = module_finalize(hdr, sechdrs, mod);
 	if (err < 0)
 		goto cleanup;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index aa81d2848448..31d784dd80d0 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -807,6 +807,61 @@ menuconfig BUILD_DOCSRC
 
 	  Say N if you are unsure.
 
+config DYNAMIC_PRINTK_DEBUG
+	bool "Enable dynamic printk() call support"
+	default n
+	depends on PRINTK
+	select PRINTK_DEBUG
+	help
+
+	  Compiles debug level messages into the kernel, which would not
+	  otherwise be available at runtime. These messages can then be
+	  enabled/disabled on a per module basis. This mechanism implicitly
+	  enables all pr_debug() and dev_dbg() calls. The impact of this
+	  compile option is a larger kernel text size of about 2%.
+
+	  Usage:
+
+	  Dynamic debugging is controlled by the debugfs file,
+	  dynamic_printk/modules. This file contains a list of the modules that
+	  can be enabled. The format of the file is the module name, followed
+	  by a set of flags that can be enabled. The first flag is always the
+	  'enabled' flag. For example:
+
+		<module_name> <enabled=0/1>
+				.
+				.
+				.
+
+	  <module_name> : Name of the module in which the debug call resides
+	  <enabled=0/1> : whether the messages are enabled or not
+
+	  From a live system:
+
+		snd_hda_intel enabled=0
+		fixup enabled=0
+		driver enabled=0
+
+	  Enable a module:
+
+	  	$echo "set enabled=1 <module_name>" > dynamic_printk/modules
+
+	  Disable a module:
+
+	  	$echo "set enabled=0 <module_name>" > dynamic_printk/modules
+
+	  Enable all modules:
+
+		$echo "set enabled=1 all" > dynamic_printk/modules
+
+	  Disable all modules:
+
+		$echo "set enabled=0 all" > dynamic_printk/modules
+
+	  Finally, passing "dynamic_printk" at the command line enables
+	  debugging for all modules. This mode can be turned off via the above
+	  disable command.
+
 source "samples/Kconfig"
 
 source "lib/Kconfig.kgdb"
diff --git a/lib/Makefile b/lib/Makefile
index 44001af76a7d..16feaab057b2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -81,6 +81,8 @@ obj-$(CONFIG_HAVE_LMB) += lmb.o
 
 obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
 
+obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c
new file mode 100644
index 000000000000..d640f87bdc9e
--- /dev/null
+++ b/lib/dynamic_printk.c
@@ -0,0 +1,418 @@
+/*
+ * lib/dynamic_printk.c
+ *
+ * make pr_debug()/dev_dbg() calls runtime configurable based upon their
+ * their source module.
+ *
+ * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+
+extern struct mod_debug __start___verbose[];
+extern struct mod_debug __stop___verbose[];
+
+struct debug_name {
+	struct hlist_node hlist;
+	struct hlist_node hlist2;
+	int hash1;
+	int hash2;
+	char *name;
+	int enable;
+	int type;
+};
+
+static int nr_entries;
+static int num_enabled;
+int dynamic_enabled = DYNAMIC_ENABLED_NONE;
+static struct hlist_head module_table[DEBUG_HASH_TABLE_SIZE] =
+	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
+static struct hlist_head module_table2[DEBUG_HASH_TABLE_SIZE] =
+	{ [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
+static DECLARE_MUTEX(debug_list_mutex);
+
+/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+long long dynamic_printk_enabled;
+EXPORT_SYMBOL_GPL(dynamic_printk_enabled);
+long long dynamic_printk_enabled2;
+EXPORT_SYMBOL_GPL(dynamic_printk_enabled2);
+
+/* returns the debug module pointer. */
+static struct debug_name *find_debug_module(char *module_name)
+{
+	int i;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct debug_name *element;
+
+	element = NULL;
+	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
+		head = &module_table[i];
+		hlist_for_each_entry_rcu(element, node, head, hlist)
+			if (!strcmp(element->name, module_name))
+				return element;
+	}
+	return NULL;
+}
+
+/* returns the debug module pointer. */
+static struct debug_name *find_debug_module_hash(char *module_name, int hash)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct debug_name *element;
+
+	element = NULL;
+	head = &module_table[hash];
+	hlist_for_each_entry_rcu(element, node, head, hlist)
+		if (!strcmp(element->name, module_name))
+			return element;
+	return NULL;
+}
+
+/* caller must hold mutex*/
+static int __add_debug_module(char *mod_name, int hash, int hash2)
+{
+	struct debug_name *new;
+	char *module_name;
+	int ret = 0;
+
+	if (find_debug_module(mod_name)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	module_name = kmalloc(strlen(mod_name) + 1, GFP_KERNEL);
+	if (!module_name) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	module_name = strcpy(module_name, mod_name);
+	module_name[strlen(mod_name)] = '\0';
+	new = kzalloc(sizeof(struct debug_name), GFP_KERNEL);
+	if (!new) {
+		kfree(module_name);
+		ret = -ENOMEM;
+		goto out;
+	}
+	INIT_HLIST_NODE(&new->hlist);
+	INIT_HLIST_NODE(&new->hlist2);
+	new->name = module_name;
+	new->hash1 = hash;
+	new->hash2 = hash2;
+	hlist_add_head_rcu(&new->hlist, &module_table[hash]);
+	hlist_add_head_rcu(&new->hlist2, &module_table2[hash2]);
+	nr_entries++;
+out:
+	return ret;
+}
+
+int unregister_dynamic_debug_module(char *mod_name)
+{
+	struct debug_name *element;
+	int ret = 0;
+
+	down(&debug_list_mutex);
+	element = find_debug_module(mod_name);
+	if (!element) {
+		ret = -EINVAL;
+		goto out;
+	}
+	hlist_del_rcu(&element->hlist);
+	hlist_del_rcu(&element->hlist2);
+	synchronize_rcu();
+	kfree(element->name);
+	if (element->enable)
+		num_enabled--;
+	kfree(element);
+	nr_entries--;
+out:
+	up(&debug_list_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module);
+
+int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
+					char *flags, int hash, int hash2)
+{
+	struct debug_name *elem;
+	int ret = 0;
+
+	down(&debug_list_mutex);
+	elem = find_debug_module(mod_name);
+	if (!elem) {
+		if (__add_debug_module(mod_name, hash, hash2))
+			goto out;
+		elem = find_debug_module(mod_name);
+		if (dynamic_enabled == DYNAMIC_ENABLED_ALL &&
+				!strcmp(mod_name, share_name)) {
+			elem->enable = true;
+			num_enabled++;
+		}
+	}
+	elem->type |= type;
+out:
+	up(&debug_list_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(register_dynamic_debug_module);
+
+int __dynamic_dbg_enabled_helper(char *mod_name, int type, int value, int hash)
+{
+	struct debug_name *elem;
+	int ret = 0;
+
+	if (dynamic_enabled == DYNAMIC_ENABLED_ALL)
+		return 1;
+	rcu_read_lock();
+	elem = find_debug_module_hash(mod_name, hash);
+	if (elem && elem->enable)
+		ret = 1;
+	rcu_read_unlock();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__dynamic_dbg_enabled_helper);
+
+static void set_all(bool enable)
+{
+	struct debug_name *e;
+	struct hlist_node *node;
+	int i;
+	long long enable_mask;
+
+	for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
+		if (module_table[i].first != NULL) {
+			hlist_for_each_entry(e, node, &module_table[i], hlist) {
+				e->enable = enable;
+			}
+		}
+	}
+	if (enable)
+		enable_mask = ULLONG_MAX;
+	else
+		enable_mask = 0;
+	dynamic_printk_enabled = enable_mask;
+	dynamic_printk_enabled2 = enable_mask;
+}
+
+static int disabled_hash(int i, bool first_table)
+{
+	struct debug_name *e;
+	struct hlist_node *node;
+
+	if (first_table) {
+		hlist_for_each_entry(e, node, &module_table[i], hlist) {
+			if (e->enable)
+				return 0;
+		}
+	} else {
+		hlist_for_each_entry(e, node, &module_table2[i], hlist2) {
+			if (e->enable)
+				return 0;
+		}
+	}
+	return 1;
+}
+
+static ssize_t pr_debug_write(struct file *file, const char __user *buf,
+				size_t length, loff_t *ppos)
+{
+	char *buffer, *s, *value_str, *setting_str;
+	int err, value;
+	struct debug_name *elem = NULL;
+	int all = 0;
+
+	if (length > PAGE_SIZE || length < 0)
+		return -EINVAL;
+
+	buffer = (char *)__get_free_page(GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	err = -EFAULT;
+	if (copy_from_user(buffer, buf, length))
+		goto out;
+
+	err = -EINVAL;
+	if (length < PAGE_SIZE)
+		buffer[length] = '\0';
+	else if (buffer[PAGE_SIZE-1])
+		goto out;
+
+	err = -EINVAL;
+	down(&debug_list_mutex);
+
+	if (strncmp("set", buffer, 3))
+		goto out_up;
+	s = buffer + 3;
+	setting_str = strsep(&s, "=");
+	if (s == NULL)
+		goto out_up;
+	setting_str = strstrip(setting_str);
+	value_str = strsep(&s, " ");
+	if (s == NULL)
+		goto out_up;
+	s = strstrip(s);
+	if (!strncmp(s, "all", 3))
+		all = 1;
+	else
+		elem = find_debug_module(s);
+	if (!strncmp(setting_str, "enable", 6)) {
+		value = !!simple_strtol(value_str, NULL, 10);
+		if (all) {
+			if (value) {
+				set_all(true);
+				num_enabled = nr_entries;
+				dynamic_enabled = DYNAMIC_ENABLED_ALL;
+			} else {
+				set_all(false);
+				num_enabled = 0;
+				dynamic_enabled = DYNAMIC_ENABLED_NONE;
+			}
+			err = 0;
+		} else {
+			if (elem) {
+				if (value && (elem->enable == 0)) {
+					dynamic_printk_enabled |=
+							(1LL << elem->hash1);
+					dynamic_printk_enabled2 |=
+							(1LL << elem->hash2);
+					elem->enable = 1;
+					num_enabled++;
+					dynamic_enabled = DYNAMIC_ENABLED_SOME;
+					err = 0;
+					printk(KERN_DEBUG
+					       "debugging enabled for module %s",
+					       elem->name);
+				} else if (!value && (elem->enable == 1)) {
+					elem->enable = 0;
+					num_enabled--;
+					if (disabled_hash(elem->hash1, true))
+						dynamic_printk_enabled &=
+							~(1LL << elem->hash1);
+					if (disabled_hash(elem->hash2, false))
+						dynamic_printk_enabled2 &=
+							~(1LL << elem->hash2);
+					if (num_enabled)
+						dynamic_enabled =
+							DYNAMIC_ENABLED_SOME;
+					else
+						dynamic_enabled =
+							DYNAMIC_ENABLED_NONE;
+					err = 0;
+					printk(KERN_DEBUG
+					       "debugging disabled for module "
+					       "%s", elem->name);
+				}
+			}
+		}
+	}
+	if (!err)
+		err = length;
+out_up:
+	up(&debug_list_mutex);
+out:
+	free_page((unsigned long)buffer);
+	return err;
+}
+
+static void *pr_debug_seq_start(struct seq_file *f, loff_t *pos)
+{
+	return (*pos < DEBUG_HASH_TABLE_SIZE) ? pos : NULL;
+}
+
+static void *pr_debug_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	(*pos)++;
+	if (*pos >= DEBUG_HASH_TABLE_SIZE)
+		return NULL;
+	return pos;
+}
+
+static void pr_debug_seq_stop(struct seq_file *s, void *v)
+{
+	/* Nothing to do */
+}
+
+static int pr_debug_seq_show(struct seq_file *s, void *v)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct debug_name *elem;
+	unsigned int i = *(loff_t *) v;
+
+	rcu_read_lock();
+	head = &module_table[i];
+	hlist_for_each_entry_rcu(elem, node, head, hlist) {
+		seq_printf(s, "%s enabled=%d", elem->name, elem->enable);
+		seq_printf(s, "\n");
+	}
+	rcu_read_unlock();
+	return 0;
+}
+
+static struct seq_operations pr_debug_seq_ops = {
+	.start = pr_debug_seq_start,
+	.next  = pr_debug_seq_next,
+	.stop  = pr_debug_seq_stop,
+	.show  = pr_debug_seq_show
+};
+
+static int pr_debug_open(struct inode *inode, struct file *filp)
+{
+	return seq_open(filp, &pr_debug_seq_ops);
+}
+
+static const struct file_operations pr_debug_operations = {
+	.open		= pr_debug_open,
+	.read		= seq_read,
+	.write		= pr_debug_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init dynamic_printk_init(void)
+{
+	struct dentry *dir, *file;
+	struct mod_debug *iter;
+	unsigned long value;
+
+	dir = debugfs_create_dir("dynamic_printk", NULL);
+	if (!dir)
+		return -ENOMEM;
+	file = debugfs_create_file("modules", 0644, dir, NULL,
+					&pr_debug_operations);
+	if (!file) {
+		debugfs_remove(dir);
+		return -ENOMEM;
+	}
+	for (value = (unsigned long)__start___verbose;
+		value < (unsigned long)__stop___verbose;
+		value += sizeof(struct mod_debug)) {
+			iter = (struct mod_debug *)value;
+			register_dynamic_debug_module(iter->modname,
+				iter->type,
+				iter->logical_modname,
+				iter->flag_names, iter->hash, iter->hash2);
+	}
+	return 0;
+}
+module_init(dynamic_printk_init);
+/* may want to move this earlier so we can get traces as early as possible */
+
+static int __init dynamic_printk_setup(char *str)
+{
+	if (str)
+		return -ENOENT;
+	set_all(true);
+	return 0;
+}
+/* Use early_param(), so we can get debug output as early as possible */
+early_param("dynamic_printk", dynamic_printk_setup);
diff --git a/lib/kobject.c b/lib/kobject.c
index fbf0ae282376..0487d1f64806 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -387,11 +387,17 @@ EXPORT_SYMBOL_GPL(kobject_init_and_add);
  * kobject_rename - change the name of an object
  * @kobj: object in question.
  * @new_name: object's new name
+ *
+ * It is the responsibility of the caller to provide mutual
+ * exclusion between two different calls of kobject_rename
+ * on the same kobject and to ensure that new_name is valid and
+ * won't conflict with other kobjects.
  */
 int kobject_rename(struct kobject *kobj, const char *new_name)
 {
 	int error = 0;
 	const char *devpath = NULL;
+	const char *dup_name = NULL, *name;
 	char *devpath_string = NULL;
 	char *envp[2];
 
@@ -401,19 +407,6 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
 	if (!kobj->parent)
 		return -EINVAL;
 
-	/* see if this name is already in use */
-	if (kobj->kset) {
-		struct kobject *temp_kobj;
-		temp_kobj = kset_find_obj(kobj->kset, new_name);
-		if (temp_kobj) {
-			printk(KERN_WARNING "kobject '%s' cannot be renamed "
-			       "to '%s' as '%s' is already in existence.\n",
-			       kobject_name(kobj), new_name, new_name);
-			kobject_put(temp_kobj);
-			return -EINVAL;
-		}
-	}
-
 	devpath = kobject_get_path(kobj, GFP_KERNEL);
 	if (!devpath) {
 		error = -ENOMEM;
@@ -428,15 +421,27 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
 	envp[0] = devpath_string;
 	envp[1] = NULL;
 
+	name = dup_name = kstrdup(new_name, GFP_KERNEL);
+	if (!name) {
+		error = -ENOMEM;
+		goto out;
+	}
+
 	error = sysfs_rename_dir(kobj, new_name);
+	if (error)
+		goto out;
+
+	/* Install the new kobject name */
+	dup_name = kobj->name;
+	kobj->name = name;
 
 	/* This function is mostly/only used for network interface.
 	 * Some hotplug package track interfaces by their name and
 	 * therefore want to know when the name is changed by the user. */
-	if (!error)
-		kobject_uevent_env(kobj, KOBJ_MOVE, envp);
+	kobject_uevent_env(kobj, KOBJ_MOVE, envp);
 
 out:
+	kfree(dup_name);
 	kfree(devpath_string);
 	kfree(devpath);
 	kobject_put(kobj);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 373e51e91ce5..1bc3001d1827 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -65,7 +65,7 @@ void
 			     struct nf_conntrack_expect *exp) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
 
-#ifdef DEBUG
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
 /* PptpControlMessageType names */
 const char *const pptp_msg_name[] = {
 	"UNKNOWN_MESSAGE",
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index ea48b82a3707..b4ca38a21158 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -96,6 +96,14 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
 modname_flags  = $(if $(filter 1,$(words $(modname))),\
                  -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
 
+#hash values
+ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
+debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
+              -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
+else
+debug_flags =
+endif
+
 orig_c_flags   = $(KBUILD_CFLAGS) $(ccflags-y) $(CFLAGS_$(basetarget).o)
 _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
 _a_flags       = $(KBUILD_AFLAGS) $(asflags-y) $(AFLAGS_$(basetarget).o)
@@ -121,7 +129,8 @@ endif
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
 		 $(__c_flags) $(modkern_cflags) \
-		 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
+		 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
+		  $(debug_flags)
 
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
 		 $(__a_flags) $(modkern_aflags)
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 4c324a1f1e0e..09559951df12 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -9,7 +9,7 @@
 # fixdep: 	 Used to generate dependency information during build process
 # docproc:	 Used in Documentation/DocBook
 
-hostprogs-y	:= fixdep docproc
+hostprogs-y	:= fixdep docproc hash
 always		:= $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
diff --git a/scripts/basic/hash.c b/scripts/basic/hash.c
new file mode 100644
index 000000000000..3299ad7fc8c0
--- /dev/null
+++ b/scripts/basic/hash.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DYNAMIC_DEBUG_HASH_BITS 6
+
+static const char *program;
+
+static void usage(void)
+{
+	printf("Usage: %s <djb2|r5> <modname>\n", program);
+	exit(1);
+}
+
+/* djb2 hashing algorithm by Dan Bernstein. From:
+ * http://www.cse.yorku.ca/~oz/hash.html
+ */
+
+unsigned int djb2_hash(char *str)
+{
+	unsigned long hash = 5381;
+	int c;
+
+	c = *str;
+	while (c) {
+		hash = ((hash << 5) + hash) + c;
+		c = *++str;
+	}
+	return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
+}
+
+unsigned int r5_hash(char *str)
+{
+	unsigned long hash = 0;
+	int c;
+
+	c = *str;
+	while (c) {
+		hash = (hash + (c << 4) + (c >> 4)) * 11;
+		c = *++str;
+	}
+	return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
+}
+
+int main(int argc, char *argv[])
+{
+	program = argv[0];
+
+	if (argc != 3)
+		usage();
+	if (!strcmp(argv[1], "djb2"))
+		printf("%d\n", djb2_hash(argv[2]));
+	else if (!strcmp(argv[1], "r5"))
+		printf("%d\n", r5_hash(argv[2]));
+	else
+		usage();
+	exit(0);
+}
+
diff --git a/sound/core/init.c b/sound/core/init.c
index 8af467df9245..ef2352c2e451 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -549,9 +549,9 @@ int snd_card_register(struct snd_card *card)
 		return -EINVAL;
 #ifndef CONFIG_SYSFS_DEPRECATED
 	if (!card->card_dev) {
-		card->card_dev = device_create_drvdata(sound_class, card->dev,
-						       MKDEV(0, 0), NULL,
-						       "card%i", card->number);
+		card->card_dev = device_create(sound_class, card->dev,
+					       MKDEV(0, 0), NULL,
+					       "card%i", card->number);
 		if (IS_ERR(card->card_dev))
 			card->card_dev = NULL;
 	}
diff --git a/sound/core/sound.c b/sound/core/sound.c
index c0685e2f0afa..44a69bb8d4f0 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -274,9 +274,8 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
 		return minor;
 	}
 	snd_minors[minor] = preg;
-	preg->dev = device_create_drvdata(sound_class, device,
-					  MKDEV(major, minor),
-					  private_data, "%s", name);
+	preg->dev = device_create(sound_class, device, MKDEV(major, minor),
+				  private_data, "%s", name);
 	if (IS_ERR(preg->dev)) {
 		snd_minors[minor] = NULL;
 		mutex_unlock(&sound_mutex);
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 7d89c081a086..61aaedae6b7e 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -560,19 +560,18 @@ static int __init oss_init(void)
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-		device_create_drvdata(sound_class, NULL,
-				      MKDEV(SOUND_MAJOR, dev_list[i].minor),
-				      NULL, "%s", dev_list[i].name);
+		device_create(sound_class, NULL,
+			      MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL,
+			      "%s", dev_list[i].name);
 
 		if (!dev_list[i].num)
 			continue;
 
 		for (j = 1; j < *dev_list[i].num; j++)
-			device_create_drvdata(sound_class, NULL,
-					      MKDEV(SOUND_MAJOR,
-						    dev_list[i].minor + (j*0x10)),
-					      NULL,
-					      "%s%d", dev_list[i].name, j);
+			device_create(sound_class, NULL,
+				      MKDEV(SOUND_MAJOR,
+					    dev_list[i].minor + (j*0x10)),
+				      NULL, "%s%d", dev_list[i].name, j);
 	}
 
 	if (sound_nblocks >= 1024)
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 4ae07e236b36..faef87a9bc3f 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -220,9 +220,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
 	else
 		sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 
-	device_create_drvdata(sound_class, dev,
-			      MKDEV(SOUND_MAJOR, s->unit_minor),
-			      NULL, s->name+6);
+	device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
+		      NULL, s->name+6);
 	return r;
 
  fail: