Parent repository is bk://kernel.bkbits.net/gregkh/linux/driver-2.6
James.Bottomley@SteelEye.com|ChangeSet|20040314215032|19484 James.Bottomley

diff -Nru a/drivers/base/Makefile b/drivers/base/Makefile
--- a/drivers/base/Makefile	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/Makefile	Sun Mar 14 14:06:40 2004
@@ -6,3 +6,8 @@
 obj-y			+= power/
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
+
+ifeq ($(CONFIG_DEBUG_DRIVER),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/bus.c	Sun Mar 14 14:06:40 2004
@@ -9,10 +9,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/errno.h>
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/class.c	Sun Mar 14 14:06:40 2004
@@ -11,10 +11,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -106,13 +102,21 @@
 
 int class_register(struct class * cls)
 {
+	int error;
+
 	pr_debug("device class '%s': registering\n",cls->name);
 
 	INIT_LIST_HEAD(&cls->children);
 	INIT_LIST_HEAD(&cls->interfaces);
-	kobject_set_name(&cls->subsys.kset.kobj,cls->name);
+	error = kobject_set_name(&cls->subsys.kset.kobj,cls->name);
+	if (error)
+		return error;
+
 	subsys_set_kset(cls,class_subsys);
-	subsystem_register(&cls->subsys);
+
+	error = subsystem_register(&cls->subsys);
+	if (error)
+		return error;
 
 	return 0;
 }
diff -Nru a/drivers/base/class_simple.c b/drivers/base/class_simple.c
--- a/drivers/base/class_simple.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/class_simple.c	Sun Mar 14 14:06:40 2004
@@ -9,10 +9,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/device.h>
 #include <linux/kdev_t.h>
 #include <linux/err.h>
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/core.c	Sun Mar 14 14:06:40 2004
@@ -9,10 +9,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/init.h>
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/driver.c	Sun Mar 14 14:06:40 2004
@@ -9,10 +9,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/errno.h>
diff -Nru a/drivers/base/power/Makefile b/drivers/base/power/Makefile
--- a/drivers/base/power/Makefile	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/power/Makefile	Sun Mar 14 14:06:40 2004
@@ -1,2 +1,6 @@
 obj-y			:= shutdown.o
 obj-$(CONFIG_PM)	+= main.o suspend.o resume.o runtime.o sysfs.o
+
+ifeq ($(CONFIG_DEBUG_DRIVER),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff -Nru a/drivers/base/power/main.c b/drivers/base/power/main.c
--- a/drivers/base/power/main.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/power/main.c	Sun Mar 14 14:06:40 2004
@@ -20,10 +20,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/device.h>
 #include "power.h"
 
diff -Nru a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
--- a/drivers/base/power/shutdown.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/power/shutdown.c	Sun Mar 14 14:06:40 2004
@@ -9,10 +9,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/device.h>
 #include <asm/semaphore.h>
 
diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c
--- a/drivers/base/sys.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/base/sys.c	Sun Mar 14 14:06:40 2004
@@ -13,10 +13,6 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_DEBUG_DRIVER
-#define DEBUG	1
-#endif
-
 #include <linux/sysdev.h>
 #include <linux/err.h>
 #include <linux/module.h>
diff -Nru a/drivers/char/drm/drm_stub.h b/drivers/char/drm/drm_stub.h
--- a/drivers/char/drm/drm_stub.h	Sun Mar 14 14:06:40 2004
+++ b/drivers/char/drm/drm_stub.h	Sun Mar 14 14:06:40 2004
@@ -35,6 +35,8 @@
 
 #define DRM_STUB_MAXCARDS 16	/* Enough for one machine */
 
+static struct class_simple *drm_class;
+
 /** Stub list. One for each minor. */
 static struct drm_stub_list {
 	const char             *name;
@@ -117,6 +119,7 @@
 			DRM(stub_root) = DRM(proc_init)(dev, i, DRM(stub_root),
 							&DRM(stub_list)[i]
 							.dev_root);
+			class_simple_device_add(drm_class, MKDEV(DRM_MAJOR, i), NULL, name);
 			return i;
 		}
 	}
@@ -141,6 +144,7 @@
 	DRM(proc_cleanup)(minor, DRM(stub_root),
 			  DRM(stub_list)[minor].dev_root);
 	if (minor) {
+		class_simple_device_remove(MKDEV(DRM_MAJOR, minor));
 		inter_module_put("drm");
 	} else {
 		inter_module_unregister("drm");
@@ -148,6 +152,8 @@
 			  sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
 			  DRM_MEM_STUB);
 		unregister_chrdev(DRM_MAJOR, "drm");
+		class_simple_device_remove(MKDEV(DRM_MAJOR, minor));
+		class_simple_destroy(drm_class);
 	}
 	return 0;
 }
@@ -170,10 +176,23 @@
 		       drm_device_t *dev)
 {
 	struct drm_stub_info *i = NULL;
+	int ret1;
+	int ret2;
 
 	DRM_DEBUG("\n");
-	if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
+	ret1 = register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops));
+	if (!ret1) {
+		drm_class = class_simple_create(THIS_MODULE, "drm");
+		if (IS_ERR(drm_class)) {
+			printk (KERN_ERR "Error creating drm class.\n");
+			unregister_chrdev(DRM_MAJOR, "drm");
+			return PTR_ERR(drm_class);
+		}
+	}
+	else if (ret1 == -EBUSY)
 		i = (struct drm_stub_info *)inter_module_get("drm");
+	else
+		return -1;
 
 	if (i) {
 				/* Already registered */
@@ -186,8 +205,18 @@
 		DRM_DEBUG("calling inter_module_register\n");
 		inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
 	}
-	if (DRM(stub_info).info_register)
-		return DRM(stub_info).info_register(name, fops, dev);
+	if (DRM(stub_info).info_register) {
+		ret2 = DRM(stub_info).info_register(name, fops, dev);
+		if (ret2) {
+			if (!ret1) {
+			unregister_chrdev(DRM_MAJOR, "drm");
+			class_simple_destroy(drm_class);
+			}
+			if (!i)
+				inter_module_unregister("drm");
+		}
+		return ret2;
+	}
 	return -1;
 }
 
diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c
--- a/drivers/char/lp.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/char/lp.c	Sun Mar 14 14:06:40 2004
@@ -869,7 +869,7 @@
 
 int __init lp_init (void)
 {
-	int i;
+	int i, err = 0;
 
 	if (parport_nr[0] == LP_PARPORT_OFF)
 		return 0;
@@ -900,10 +900,15 @@
 
 	devfs_mk_dir("printers");
 	lp_class = class_simple_create(THIS_MODULE, "printer");
+	if (IS_ERR(lp_class)) {
+		err = PTR_ERR(lp_class);
+		goto out_devfs;
+	}
 
 	if (parport_register_driver (&lp_driver)) {
 		printk (KERN_ERR "lp: unable to register with parport\n");
-		return -EIO;
+		err = -EIO;
+		goto out_class;
 	}
 
 	if (!lp_count) {
@@ -915,6 +920,13 @@
 	}
 
 	return 0;
+
+out_class:
+	class_simple_destroy(lp_class);
+out_devfs:
+	devfs_remove("printers");
+	unregister_chrdev(LP_MAJOR, "lp");
+	return err;
 }
 
 static int __init lp_init_module (void)
diff -Nru a/drivers/char/misc.c b/drivers/char/misc.c
--- a/drivers/char/misc.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/char/misc.c	Sun Mar 14 14:06:40 2004
@@ -342,6 +342,7 @@
 	if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
 		printk("unable to get major %d for misc devices\n",
 		       MISC_MAJOR);
+		class_simple_destroy(misc_class);
 		return -EIO;
 	}
 	return 0;
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/char/tty_io.c	Sun Mar 14 14:06:40 2004
@@ -2195,8 +2195,6 @@
 EXPORT_SYMBOL(tty_register_device);
 EXPORT_SYMBOL(tty_unregister_device);
 
-static struct kobject tty_kobj = {.name = "tty"};
-
 struct tty_driver *alloc_tty_driver(int lines)
 {
 	struct tty_driver *driver;
@@ -2296,15 +2294,11 @@
 		driver->termios_locked = NULL;
 	}
 
-	driver->cdev.kobj.parent = &tty_kobj;
-	strcpy(driver->cdev.kobj.name, driver->name);
-	for (s = strchr(driver->cdev.kobj.name, '/'); s; s = strchr(s, '/'))
-		*s = '!';
 	cdev_init(&driver->cdev, &tty_fops);
 	driver->cdev.owner = driver->owner;
 	error = cdev_add(&driver->cdev, dev, driver->num);
 	if (error) {
-		kobject_del(&driver->cdev.kobj);
+		cdev_del(&driver->cdev);
 		unregister_chrdev_region(dev, driver->num);
 		driver->ttys = NULL;
 		driver->termios = driver->termios_locked = NULL;
@@ -2420,7 +2414,9 @@
 }
 
 postcore_initcall(tty_class_init);
- 
+
+/* 3/2004 jmc: why do these devices exist? */
+
 static struct cdev tty_cdev, console_cdev;
 #ifdef CONFIG_UNIX98_PTYS
 static struct cdev ptmx_cdev;
@@ -2435,7 +2431,6 @@
  */
 static int __init tty_init(void)
 {
-	strcpy(tty_cdev.kobj.name, "dev.tty");
 	cdev_init(&tty_cdev, &tty_fops);
 	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
@@ -2443,7 +2438,6 @@
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
 	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
 
-	strcpy(console_cdev.kobj.name, "dev.console");
 	cdev_init(&console_cdev, &console_fops);
 	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
@@ -2451,11 +2445,7 @@
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
 	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
 
-	tty_kobj.kset = tty_cdev.kobj.kset;
-	kobject_register(&tty_kobj);
-
 #ifdef CONFIG_UNIX98_PTYS
-	strcpy(ptmx_cdev.kobj.name, "dev.ptmx");
 	cdev_init(&ptmx_cdev, &tty_fops);
 	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
@@ -2465,7 +2455,6 @@
 #endif
 
 #ifdef CONFIG_VT
-	strcpy(vc0_cdev.kobj.name, "dev.vc0");
 	cdev_init(&vc0_cdev, &console_fops);
 	if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
 	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
--- a/drivers/ieee1394/amdtp.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/ieee1394/amdtp.c	Sun Mar 14 14:06:40 2004
@@ -1266,7 +1266,6 @@
 {
 	cdev_init(&amdtp_cdev, &amdtp_fops);
 	amdtp_cdev.owner = THIS_MODULE;
-	kobject_set_name(&amdtp_cdev.kobj, "amdtp");
 	if (cdev_add(&amdtp_cdev, IEEE1394_AMDTP_DEV, 16)) {
 		HPSB_ERR("amdtp: unable to add char device");
  		return -EIO;
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/ieee1394/dv1394.c	Sun Mar 14 14:06:40 2004
@@ -2616,7 +2616,6 @@
 
 	cdev_init(&dv1394_cdev, &dv1394_fops);
 	dv1394_cdev.owner = THIS_MODULE;
-	kobject_set_name(&dv1394_cdev.kobj, "dv1394");
 	ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
 	if (ret) {
 		printk(KERN_ERR "dv1394: unable to register character device\n");
diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
--- a/drivers/ieee1394/raw1394.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/ieee1394/raw1394.c	Sun Mar 14 14:06:40 2004
@@ -2746,9 +2746,9 @@
 
 	cdev_init(&raw1394_cdev, &raw1394_fops);
 	raw1394_cdev.owner = THIS_MODULE;
-	kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
 	ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
 	if (ret) {
+		/* jmc: leaves reference to (static) raw1394_cdev */
                 HPSB_ERR("raw1394 failed to register minor device block");
                 devfs_remove(RAW1394_DEVICE_NAME);
                 hpsb_unregister_highlevel(&raw1394_highlevel);
diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
--- a/drivers/ieee1394/video1394.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/ieee1394/video1394.c	Sun Mar 14 14:06:40 2004
@@ -1457,7 +1457,6 @@
 
 	cdev_init(&video1394_cdev, &video1394_fops);
 	video1394_cdev.owner = THIS_MODULE;
-	kobject_set_name(&video1394_cdev.kobj, VIDEO1394_DRIVER_NAME);
 	ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
 	if (ret) {
 		PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
diff -Nru a/drivers/input/input.c b/drivers/input/input.c
--- a/drivers/input/input.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/input/input.c	Sun Mar 14 14:06:40 2004
@@ -727,6 +727,8 @@
 	int retval = -ENOMEM;
 
 	input_class = class_simple_create(THIS_MODULE, "input");
+	if (IS_ERR(input_class))
+		return PTR_ERR(input_class);
 	input_proc_init();
 	retval = register_chrdev(INPUT_MAJOR, "input", &input_fops);
 	if (retval) {
@@ -734,6 +736,7 @@
 		remove_proc_entry("devices", proc_bus_input_dir);
 		remove_proc_entry("handlers", proc_bus_input_dir);
 		remove_proc_entry("input", proc_bus);
+		class_simple_destroy(input_class);
 		return retval;
 	}
 
@@ -743,6 +746,7 @@
 		remove_proc_entry("handlers", proc_bus_input_dir);
 		remove_proc_entry("input", proc_bus);
 		unregister_chrdev(INPUT_MAJOR, "input");
+		class_simple_destroy(input_class);
 	}
 	return retval;
 }
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/net/ppp_generic.c	Sun Mar 14 14:06:40 2004
@@ -45,6 +45,7 @@
 #include <linux/smp_lock.h>
 #include <linux/rwsem.h>
 #include <linux/stddef.h>
+#include <linux/device.h>
 #include <net/slhc_vj.h>
 #include <asm/atomic.h>
 
@@ -271,6 +272,8 @@
 static int ppp_disconnect_channel(struct channel *pch);
 static void ppp_destroy_channel(struct channel *pch);
 
+static struct class_simple *ppp_class;
+
 /* Translates a PPP protocol number to a NP index (NP == network protocol) */
 static inline int proto_to_npindex(int proto)
 {
@@ -804,15 +807,29 @@
 	printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
 	err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
 	if (!err) {
+		ppp_class = class_simple_create(THIS_MODULE, "ppp");
+		if (IS_ERR(ppp_class)) {
+			err = PTR_ERR(ppp_class);
+			goto out_chrdev;
+		}
+		class_simple_device_add(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
 		err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
 				S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
 		if (err)
-			unregister_chrdev(PPP_MAJOR, "ppp");
+			goto out_class;
 	}
 
+out:
 	if (err)
 		printk(KERN_ERR "failed to register PPP device (%d)\n", err);
 	return err;
+
+out_class:
+	class_simple_device_remove(MKDEV(PPP_MAJOR,0));
+	class_simple_destroy(ppp_class);
+out_chrdev:
+	unregister_chrdev(PPP_MAJOR, "ppp");
+	goto out;
 }
 
 /*
@@ -2545,6 +2562,8 @@
 	if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
 		printk(KERN_ERR "PPP: failed to unregister PPP device\n");
 	devfs_remove("ppp");
+	class_simple_device_remove(MKDEV(PPP_MAJOR, 0));
+	class_simple_destroy(ppp_class);
 }
 
 /*
diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
--- a/drivers/pci/hotplug/pci_hotplug_core.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/pci/hotplug/pci_hotplug_core.c	Sun Mar 14 14:06:40 2004
@@ -104,19 +104,7 @@
 	.release = &hotplug_slot_release,
 };
 
-/* 
- * We create a struct subsystem on our own and not use decl_subsys so
- * we can have a sane name "slots" in sysfs, yet still keep a good
- * global variable name "pci_hotplug_slots_subsys.
- * If the decl_subsys() #define ever changes, this declaration will
- * need to be update to make sure everything is initialized properly.
- */
-struct subsystem pci_hotplug_slots_subsys = {
-	.kset = {
-		.kobj = { .name = "slots" },
-		.ktype = &hotplug_slot_ktype,
-	}
-};
+decl_subsys_name(pci_hotplug_slots, slots, &hotplug_slot_ktype, NULL);
 
 /* these strings match up with the values in pci_bus_speed */
 static char *pci_bus_speed_strings[] = {
diff -Nru a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
--- a/drivers/s390/char/tape_class.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/s390/char/tape_class.c	Sun Mar 14 14:06:40 2004
@@ -46,13 +46,10 @@
 	cdev->owner = fops->owner;
 	cdev->ops   = fops;
 	cdev->dev   = dev;
-	strcpy(cdev->kobj.name, devname);
-	for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/'))
-		*s = '!';
 
 	rc = cdev_add(cdev, cdev->dev, 1);
 	if (rc) {
-		kobject_put(&cdev->kobj);
+		cdev_del(cdev);
 		return ERR_PTR(rc);
 	}
 	class_simple_device_add(tape_class, cdev->dev, device, "%s", devname);
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/scsi/sg.c	Sun Mar 14 14:06:40 2004
@@ -1409,7 +1409,6 @@
 	SCSI_LOG_TIMEOUT(3, printk("sg_add: dev=%d \n", k));
 	memset(sdp, 0, sizeof(*sdp));
 	sprintf(disk->disk_name, "sg%d", k);
-	strncpy(cdev->kobj.name, disk->disk_name, KOBJ_NAME_LEN);
 	cdev->owner = THIS_MODULE;
 	cdev->ops = &sg_fops;
 	disk->major = SCSI_GENERIC_MAJOR;
@@ -1439,7 +1438,7 @@
 				MKDEV(SCSI_GENERIC_MAJOR, k), 
 				cl_dev->dev, "%s", 
 				disk->disk_name);
-		if (NULL == sg_class_member)
+		if (IS_ERR(sg_class_member))
 			printk(KERN_WARNING "sg_add: "
 				"class_simple_device_add failed\n");
 		class_set_devdata(sg_class_member, sdp);
@@ -1462,7 +1461,7 @@
 out:
 	put_disk(disk);
 	if (cdev)
-		kobject_put(&cdev->kobj);
+		cdev_del(cdev);
 	return error;
 }
 
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Sun Mar 14 14:06:40 2004
+++ b/drivers/scsi/st.c	Sun Mar 14 14:06:40 2004
@@ -3959,7 +3959,7 @@
 		}
 	}
 	if (cdev)
-		kobject_put(&cdev->kobj);
+		cdev_del(cdev);
 	write_lock(&st_dev_arr_lock);
 	scsi_tapes[dev_num] = NULL;
 	st_nr_dev--;
diff -Nru a/fs/char_dev.c b/fs/char_dev.c
--- a/fs/char_dev.c	Sun Mar 14 14:06:40 2004
+++ b/fs/char_dev.c	Sun Mar 14 14:06:40 2004
@@ -340,15 +340,9 @@
 
 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 {
-	int err = kobject_add(&p->kobj);
-	if (err)
-		return err;
-	err = kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
-	if (err)
-		kobject_del(&p->kobj);
 	p->dev = dev;
 	p->count = count;
-	return err;
+	return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
 }
 
 static void cdev_unmap(dev_t dev, unsigned count)
@@ -359,7 +353,6 @@
 void cdev_del(struct cdev *p)
 {
 	cdev_unmap(p->dev, p->count);
-	kobject_del(&p->kobj);
 	kobject_put(&p->kobj);
 }
 
@@ -407,18 +400,12 @@
 	.release	= cdev_dynamic_release,
 };
 
-static struct kset kset_dynamic = {
-	.subsys = &cdev_subsys,
-	.kobj = {.name = "major",},
-	.ktype = &ktype_cdev_dynamic,
-};
-
 struct cdev *cdev_alloc(void)
 {
 	struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL);
 	if (p) {
 		memset(p, 0, sizeof(struct cdev));
-		p->kobj.kset = &kset_dynamic;
+		p->kobj.ktype = &ktype_cdev_dynamic;
 		INIT_LIST_HEAD(&p->list);
 		kobject_init(&p->kobj);
 	}
@@ -428,7 +415,6 @@
 void cdev_init(struct cdev *cdev, struct file_operations *fops)
 {
 	INIT_LIST_HEAD(&cdev->list);
-	kobj_set_kset_s(cdev, cdev_subsys);
 	cdev->kobj.ktype = &ktype_cdev_default;
 	kobject_init(&cdev->kobj);
 	cdev->ops = fops;
@@ -444,8 +430,12 @@
 
 void __init chrdev_init(void)
 {
-	subsystem_register(&cdev_subsys);
-	kset_register(&kset_dynamic);
+/*
+ * Keep cdev_subsys around because (and only because) the kobj_map code
+ * depends on the rwsem it contains.  We don't make it public in sysfs,
+ * however.
+ */
+	subsystem_init(&cdev_subsys);
 	cdev_map = kobj_map_init(base_probe, &cdev_subsys);
 }
 
diff -Nru a/include/linux/kobject.h b/include/linux/kobject.h
--- a/include/linux/kobject.h	Sun Mar 14 14:06:40 2004
+++ b/include/linux/kobject.h	Sun Mar 14 14:06:40 2004
@@ -151,6 +151,14 @@
 		.hotplug_ops =_hotplug_ops, \
 	} \
 }
+#define decl_subsys_name(_varname,_name,_type,_hotplug_ops) \
+struct subsystem _varname##_subsys = { \
+	.kset = { \
+		.kobj = { .name = __stringify(_name) }, \
+		.ktype = _type, \
+		.hotplug_ops =_hotplug_ops, \
+	} \
+}
 
 
 /**
diff -Nru a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c
--- a/net/netlink/netlink_dev.c	Sun Mar 14 14:06:40 2004
+++ b/net/netlink/netlink_dev.c	Sun Mar 14 14:06:40 2004
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
+#include <linux/device.h>
 
 #include <asm/bitops.h>
 #include <asm/system.h>
@@ -34,6 +35,7 @@
 
 static long open_map;
 static struct socket *netlink_user[MAX_LINKS];
+static struct class_simple *netlink_class;
 
 /*
  *	Device operations
@@ -229,17 +231,26 @@
 		return -EIO;
 	}
 
+	netlink_class = class_simple_create(THIS_MODULE, "netlink");
+	if (IS_ERR(netlink_class)) {
+		printk (KERN_ERR "Error creating netlink class.\n");
+		unregister_chrdev(NETLINK_MAJOR, "netlink");
+		return PTR_ERR(netlink_class);
+	}
+
 	devfs_mk_dir("netlink");
 
 	/*  Someone tell me the official names for the uppercase ones  */
 	for (i = 0; i < ARRAY_SIZE(entries); i++) {
 		devfs_mk_cdev(MKDEV(NETLINK_MAJOR, entries[i].minor),
 			S_IFCHR|S_IRUSR|S_IWUSR, "netlink/%s", entries[i].name);
+		class_simple_device_add(netlink_class, MKDEV(NETLINK_MAJOR, entries[i].minor), NULL, "%s", entries[i].name);
 	}
 
 	for (i = 0; i < 16; i++) {
 		devfs_mk_cdev(MKDEV(NETLINK_MAJOR, i + 16),
 			S_IFCHR|S_IRUSR|S_IWUSR, "netlink/tap%d", i);
+		class_simple_device_add(netlink_class, MKDEV(NETLINK_MAJOR, i + 16), NULL, "tap%d", i);
 	}
 
 	return 0;
@@ -249,11 +260,16 @@
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(entries); i++)
+	for (i = 0; i < ARRAY_SIZE(entries); i++) {
 		devfs_remove("netlink/%s", entries[i].name);
-	for (i = 0; i < 16; i++)
+		class_simple_device_remove(MKDEV(NETLINK_MAJOR, entries[i].minor));
+	}
+	for (i = 0; i < 16; i++) {
 		devfs_remove("netlink/tap%d", i);
+		class_simple_device_remove(MKDEV(NETLINK_MAJOR, i + 16));
+	}
 	devfs_remove("netlink");
+	class_simple_destroy(netlink_class);
 	unregister_chrdev(NETLINK_MAJOR, "netlink");
 }
 
