Skip to contentSkip to conversation

Nesting class_device patches that actually work

PATCH In review Greg KH 10 participants 44 messages Oct 13, 2005 – Dec 1, 2005

Subsystems (21)
lore
Share & tools
lore

Greg KH

author
#0 lore raw

cover Nesting class_device patches that actually work

Ok, finally. Here's a set of _working_ patches that properly implement nesting class_device structures, and the follow-on patches to move the input subsystem to use them. Hotplug and release functions work properly now, and this will let us move /sys/block/ to use class and class_device structures soon.

The input patches are on top of almost all of Dmitry's input patches. All of them are together in one series in my public patches at:
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
and should show up in the next -mm release.

The sysfs tree looks the same as it did last time, but now hotplug works properly for addition and removal, and we actually free the memory used :)

For those that don't remember, here's the sysfs tree on my desktop:

$ tree /sys/class/input/ -d
/sys/class/input/
|-- input0
|   |-- capabilities
|   |-- event0
|   `-- id
|-- input1
|   |-- capabilities
|   |-- device -> ../../../devices/platform/i8042/serio1
|   |-- event1
|   |   `-- device -> ../../../../devices/platform/i8042/serio1
|   `-- id
|-- input3
|   |-- capabilities
|   |-- device -> ../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   |-- event2
|   |   `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   |-- id
|   |-- mouse0
|   |   `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   `-- ts0
|       `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
`-- mice

To answer the remaining questions from the last thread:

Q: how are you going to determine what is really a class_dev and what
isn't, as there's no way to tell.
A: Who cares? Seriously, tools like udev will watch for the "dev" file
to be able create the required device node, and it will be the one getting the hotplug event. attribute groups do not generate hotplug events, and you should not be having a file called "dev" in your attribute group anyway.

Q: why does event2, mouse0, and input3 in the above tree all have the
same "device" symlink?
A: userspace tools expect that symlink there. They do not know that if
you traverse up a directory, and look at the symlink there, that's what the subdirectory points to too. That would be a mess. And, as those different class_device structures really are all bound to that same struct device, that is the proper representation of this.

Q: How can you determine between input interfaces and input devices?
A: input devices have a "dev" file. And what really does userspace need
to know here?

Q: Wait, what about nesting struct class instead? That would work,
right?
A: No, nesting classes is not going to happen. Classes are "major"
things, and aren't related to each other (well, some are by their name only, like the different "scsi*" classes, but to the user, they are separate.)
Also, we can't emulate /sys/block with nested classes. And no, we can't change this to be /sys/class/block/partitions and /sys/class/block/devices without almost every sysfs user complaining loudly. That's not the real representation of the devices, and we need to really try to keep backward compatibility where we possibly can.

Ok, I think that covers everything.

Oh, one final thing. I really don't think that input should be a class. It looks like a "bus" and acts like a "bus" (you have different devices that have different drivers bind to them, and you want to load those drivers with the hotplug mechanism.) The only thing keeping this from being a bus is the fact that we can't bind multiple drivers to a single device these days, and I can't see a way to move this code to that model, so oh well...

thanks,

greg k-h

author
#1 lore raw

PATCH 1/8 Driver Core: add the ability for class_device structures to be nested

From: Greg Kroah-Hartman <[email protected]>

This patch allows struct class_device to be nested, so that another struct class_device can be the parent of a new one, instead of only having the struct class be the parent. This will allow us to (hopefully) fix up the input and video class subsystem mess.

But please people, don't go crazy and start making huge trees of class devices, you should only need 2 levels deep to get everything to work (remember to use a class_interface to get notification of a new class device being added to the system.)

Oh, this also allows us to have the possibility of potentially, someday, moving /sys/block into /sys/class. The main hindrance is that pesky /dev numberspace issue...

---
 drivers/base/class.c   |  125 +++++++++++++++++++++++++++++++------------------
 include/linux/device.h |   13 +++--
 2 files changed, 91 insertions(+), 47 deletions(-)
drivers/base/class.c +81 -44
@@ -99,7 +99,8 @@ struct class * class_get(struct class * 
 
 void class_put(struct class * cls)
 {
-	subsys_put(&cls->subsys);
+	if (cls)
+		subsys_put(&cls->subsys);
 }
 
 
@@ -165,14 +166,25 @@ void class_unregister(struct class * cls
 
 static void class_create_release(struct class *cls)
 {
+	pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
 	kfree(cls);
 }
 
 static void class_device_create_release(struct class_device *class_dev)
 {
+	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
 	kfree(class_dev);
 }
 
+/* needed to allow these devices to have parent class devices */
+static int class_device_create_hotplug(struct class_device *class_dev,
+				       char **envp, int num_envp,
+				       char *buffer, int buffer_size)
+{
+	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
+	return 0;
+}
+
 /**
  * class_create - create a struct class structure
  * @owner: pointer to the module that is to "own" this struct class
@@ -301,10 +313,12 @@ static void class_dev_release(struct kob
 	kfree(cd->devt_attr);
 	cd->devt_attr = NULL;
 
-	if (cls->release)
+	if (cd->release)
+		cd->release(cd);
+	else if (cls->release)
 		cls->release(cd);
 	else {
-		printk(KERN_ERR "Device class '%s' does not have a release() function, "
+		printk(KERN_ERR "Class Device '%s' does not have a release() function, "
 			"it is broken and must be fixed.\n",
 			cd->class_id);
 		WARN_ON(1);
@@ -382,14 +396,18 @@ static int class_hotplug(struct kset *ks
 	buffer = &buffer[length];
 	buffer_size -= length;
 
-	if (class_dev->class->hotplug) {
-		/* have the bus specific function add its stuff */
-		retval = class_dev->class->hotplug (class_dev, envp, num_envp,
-						    buffer, buffer_size);
-			if (retval) {
-			pr_debug ("%s - hotplug() returned %d\n",
-				  __FUNCTION__, retval);
-		}
+	if (class_dev->hotplug) {
+		/* have the class device specific function add its stuff */
+		retval = class_dev->hotplug(class_dev, envp, num_envp,
+					    buffer, buffer_size);
+		if (retval)
+			pr_debug("class_dev->hotplug() returned %d\n", retval);
+	} else if (class_dev->class->hotplug) {
+		/* have the class specific function add its stuff */
+		retval = class_dev->class->hotplug(class_dev, envp, num_envp,
+						   buffer, buffer_size);
+		if (retval)
+			pr_debug("class->hotplug() returned %d\n", retval);
 	}
 
 	return retval;
@@ -476,37 +494,42 @@ static char *make_class_name(struct clas
 
 int class_device_add(struct class_device *class_dev)
 {
-	struct class * parent = NULL;
-	struct class_interface * class_intf;
+	struct class *parent_class = NULL;
+	struct class_device *parent_class_dev = NULL;
+	struct class_interface *class_intf;
 	char *class_name = NULL;
-	int error;
+	int error = -EINVAL;
 
 	class_dev = class_device_get(class_dev);
 	if (!class_dev)
 		return -EINVAL;
 
-	if (!strlen(class_dev->class_id)) {
-		error = -EINVAL;
+	if (!strlen(class_dev->class_id))
 		goto register_done;
-	}
 
-	parent = class_get(class_dev->class);
+	parent_class = class_get(class_dev->class);
+	if (!parent_class)
+		goto register_done;
+	parent_class_dev = class_device_get(class_dev->parent);
 
 	pr_debug("CLASS: registering class device: ID = '%s'\n",
 		 class_dev->class_id);
 
 	/* first, register with generic layer. */
 	kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
-	if (parent)
-		class_dev->kobj.parent = &parent->subsys.kset.kobj;
+	if (parent_class_dev)
+		class_dev->kobj.parent = &parent_class_dev->kobj;
+	else
+		class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
 
-	if ((error = kobject_add(&class_dev->kobj)))
+	error = kobject_add(&class_dev->kobj);
+	if (error)
 		goto register_done;
 
 	/* add the needed attributes to this device */
 	class_dev->uevent_attr.attr.name = "uevent";
 	class_dev->uevent_attr.attr.mode = S_IWUSR;
-	class_dev->uevent_attr.attr.owner = parent->owner;
+	class_dev->uevent_attr.attr.owner = parent_class->owner;
 	class_dev->uevent_attr.store = store_uevent;
 	class_device_create_file(class_dev, &class_dev->uevent_attr);
 
@@ -520,7 +543,7 @@ int class_device_add(struct class_device
 		}
 		attr->attr.name = "dev";
 		attr->attr.mode = S_IRUGO;
-		attr->attr.owner = parent->owner;
+		attr->attr.owner = parent_class->owner;
 		attr->show = show_dev;
 		class_device_create_file(class_dev, attr);
 		class_dev->devt_attr = attr;
@@ -538,18 +561,20 @@ int class_device_add(struct class_device
 	kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
 
 	/* notify any interfaces this device is now here */
-	if (parent) {
-		down(&parent->sem);
-		list_add_tail(&class_dev->node, &parent->children);
-		list_for_each_entry(class_intf, &parent->interfaces, node)
+	if (parent_class) {
+		down(&parent_class->sem);
+		list_add_tail(&class_dev->node, &parent_class->children);
+		list_for_each_entry(class_intf, &parent_class->interfaces, node)
 			if (class_intf->add)
 				class_intf->add(class_dev, class_intf);
-		up(&parent->sem);
+		up(&parent_class->sem);
 	}
 
  register_done:
-	if (error && parent)
-		class_put(parent);
+	if (error) {
+		class_put(parent_class);
+		class_device_put(parent_class_dev);
+	}
 	class_device_put(class_dev);
 	kfree(class_name);
 	return error;
@@ -564,21 +589,28 @@ int class_device_register(struct class_d
 /**
  * class_device_create - creates a class device and registers it with sysfs
  * @cs: pointer to the struct class that this device should be registered to.
+ * @parent: pointer to the parent struct class_device of this new device, if any.
  * @dev: the dev_t for the char device to be added.
  * @device: a pointer to a struct device that is assiociated with this class device.
  * @fmt: string for the class device's name
  *
  * This function can be used by char device classes.  A struct
  * class_device will be created in sysfs, registered to the specified
- * class.  A "dev" file will be created, showing the dev_t for the
- * device.  The pointer to the struct class_device will be returned from
- * the call.  Any further sysfs files that might be required can be
- * created using this pointer.
+ * class.
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct class_device is passed in, the newly
+ * created struct class_device will be a child of that device in sysfs.
+ * The pointer to the struct class_device will be returned from the
+ * call.  Any further sysfs files that might be required can be created
+ * using this pointer.
  *
  * Note: the struct class passed to this function must have previously
  * been created with a call to class_create().
  */
-struct class_device *class_device_create(struct class *cls, dev_t devt,
+struct class_device *class_device_create(struct class *cls,
+					 struct class_device *parent,
+					 dev_t devt,
 					 struct device *device, char *fmt, ...)
 {
 	va_list args;
@@ -597,6 +629,9 @@ struct class_device *class_device_create
 	class_dev->devt = devt;
 	class_dev->dev = device;
 	class_dev->class = cls;
+	class_dev->parent = parent;
+	class_dev->release = class_device_create_release;
+	class_dev->hotplug = class_device_create_hotplug;
 
 	va_start(args, fmt);
 	vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -614,17 +649,18 @@ error:
 
 void class_device_del(struct class_device *class_dev)
 {
-	struct class * parent = class_dev->class;
-	struct class_interface * class_intf;
+	struct class *parent_class = class_dev->class;
+	struct class_device *parent_device = class_dev->parent;
+	struct class_interface *class_intf;
 	char *class_name = NULL;
 
-	if (parent) {
-		down(&parent->sem);
+	if (parent_class) {
+		down(&parent_class->sem);
 		list_del_init(&class_dev->node);
-		list_for_each_entry(class_intf, &parent->interfaces, node)
+		list_for_each_entry(class_intf, &parent_class->interfaces, node)
 			if (class_intf->remove)
 				class_intf->remove(class_dev, class_intf);
-		up(&parent->sem);
+		up(&parent_class->sem);
 	}
 
 	if (class_dev->dev) {
@@ -640,8 +676,8 @@ void class_device_del(struct class_devic
 	kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
 	kobject_del(&class_dev->kobj);
 
-	if (parent)
-		class_put(parent);
+	class_device_put(parent_device);
+	class_put(parent_class);
 	kfree(class_name);
 }
 
@@ -721,7 +757,8 @@ struct class_device * class_device_get(s
 
 void class_device_put(struct class_device *class_dev)
 {
-	kobject_put(&class_dev->kobj);
+	if (class_dev)
+		kobject_put(&class_dev->kobj);
 }
 
 
include/linux/device.h +10 -3
@@ -213,7 +213,11 @@ struct class_device {
 	struct class_device_attribute uevent_attr;
 	struct device		* dev;		/* not necessary, but nice to have */
 	void			* class_data;	/* class-specific data */
+	struct class_device	*parent;	/* parent of this child device, if there is one */
 
+	void	(*release)(struct class_device *dev);
+	int	(*hotplug)(struct class_device *dev, char **envp,
+			   int num_envp, char *buffer, int buffer_size);
 	char	class_id[BUS_ID_SIZE];	/* unique to this class */
 };
 
@@ -261,9 +265,12 @@ extern void class_interface_unregister(s
 
 extern struct class *class_create(struct module *owner, char *name);
 extern void class_destroy(struct class *cls);
-extern struct class_device *class_device_create(struct class *cls, dev_t devt,
-						struct device *device, char *fmt, ...)
-					__attribute__((format(printf,4,5)));
+extern struct class_device *class_device_create(struct class *cls,
+						struct class_device *parent,
+						dev_t devt,
+						struct device *device,
+						char *fmt, ...)
+					__attribute__((format(printf,5,6)));
 extern void class_device_destroy(struct class *cls, dev_t devt);
 
 

--

author
#2 lore raw

PATCH 2/8 Driver Core: fix up all callers of class_device_create()

In reply to Greg KH

From: Greg Kroah-Hartman <[email protected]>

The previous patch adding the ability to nest struct class_device changed the paramaters to the call class_device_create(). This patch fixes up all in-kernel users of the function.

---
 arch/i386/kernel/cpuid.c                |    2 +-
 arch/i386/kernel/msr.c                  |    2 +-
 drivers/block/aoe/aoechr.c              |    2 +-
 drivers/block/paride/pg.c               |    2 +-
 drivers/block/paride/pt.c               |    4 ++--
 drivers/char/dsp56k.c                   |    2 +-
 drivers/char/ftape/zftape/zftape-init.c |   12 ++++++------
 drivers/char/ip2main.c                  |   10 ++++++----
 drivers/char/ipmi/ipmi_devintf.c        |    2 +-
 drivers/char/istallion.c                |    3 ++-
 drivers/char/lp.c                       |    2 +-
 drivers/char/mem.c                      |    3 ++-
 drivers/char/misc.c                     |    2 +-
 drivers/char/ppdev.c                    |    2 +-
 drivers/char/raw.c                      |    4 ++--
 drivers/char/snsc.c                     |    2 +-
 drivers/char/stallion.c                 |    4 +++-
 drivers/char/tipar.c                    |    2 +-
 drivers/char/tty_io.c                   |   10 +++++-----
 drivers/char/vc_screen.c                |   10 ++++++----
 drivers/char/viotape.c                  |    4 ++--
 drivers/hwmon/hwmon.c                   |    2 +-
 drivers/ide/ide-tape.c                  |    4 ++--
 drivers/ieee1394/dv1394.c               |    2 +-
 drivers/ieee1394/raw1394.c              |    2 +-
 drivers/ieee1394/video1394.c            |    2 +-
 drivers/infiniband/core/ucm.c           |    2 +-
 drivers/input/evdev.c                   |    2 +-
 drivers/input/joydev.c                  |    2 +-
 drivers/input/mousedev.c                |    4 ++--
 drivers/input/tsdev.c                   |    2 +-
 drivers/isdn/capi/capi.c                |    2 +-
 drivers/macintosh/adb.c                 |    2 +-
 drivers/media/dvb/dvb-core/dvbdev.c     |    2 +-
 drivers/message/i2o/iop.c               |    2 +-
 drivers/mtd/mtdchar.c                   |    4 ++--
 drivers/net/ppp_generic.c               |    2 +-
 drivers/net/wan/cosa.c                  |    2 +-
 drivers/s390/char/tape_class.c          |    1 +
 drivers/s390/char/vmlogrdr.c            |    1 +
 drivers/scsi/ch.c                       |    2 +-
 drivers/scsi/osst.c                     |    2 +-
 drivers/scsi/sg.c                       |    2 +-
 drivers/scsi/st.c                       |    2 +-
 drivers/usb/core/devio.c                |    2 +-
 drivers/usb/core/file.c                 |    4 +++-
 drivers/usb/core/hcd.c                  |    3 ++-
 drivers/video/fbmem.c                   |    2 +-
 fs/coda/psdev.c                         |    4 ++--
 sound/core/sound.c                      |    2 +-
 sound/oss/soundcard.c                   |    4 ++--
 sound/sound_core.c                      |    2 +-
 52 files changed, 86 insertions(+), 73 deletions(-)
drivers/usb/core/devio.c +1 -1
@@ -1509,7 +1509,7 @@ void usbdev_add(struct usb_device *dev)
 {
 	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
 
-	dev->class_dev = class_device_create(usb_device_class,
+	dev->class_dev = class_device_create(usb_device_class, NULL,
 				MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
 				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
 
drivers/usb/core/file.c +3 -1
@@ -172,7 +172,9 @@ int usb_register_dev(struct usb_interfac
 		++temp;
 	else
 		temp = name;
-	intf->class_dev = class_device_create(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+	intf->class_dev = class_device_create(usb_class, NULL,
+					      MKDEV(USB_MAJOR, minor),
+					      &intf->dev, "%s", temp);
 	if (IS_ERR(intf->class_dev)) {
 		spin_lock (&minor_lock);
 		usb_minors[intf->minor] = NULL;
drivers/usb/core/hcd.c +2 -1
@@ -782,7 +782,8 @@ static int usb_register_bus(struct usb_b
 		return -E2BIG;
 	}
 
-	bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb_host%d", busnum);
+	bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
+					     bus->controller, "usb_host%d", busnum);
 	if (IS_ERR(bus->class_dev)) {
 		clear_bit(busnum, busmap.busmap);
 		up(&usb_bus_list_lock);
drivers/video/fbmem.c +1 -1
@@ -1031,7 +1031,7 @@ register_framebuffer(struct fb_info *fb_
 			break;
 	fb_info->node = i;
 
-	fb_info->class_device = class_device_create(fb_class, MKDEV(FB_MAJOR, i),
+	fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i),
 				    fb_info->device, "fb%d", i);
 	if (IS_ERR(fb_info->class_device)) {
 		/* Not fatal */
drivers/block/aoe/aoechr.c +1 -1
@@ -224,7 +224,7 @@ aoechr_init(void)
 		return PTR_ERR(aoe_class);
 	}
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-		class_device_create(aoe_class,
+		class_device_create(aoe_class, NULL,
 					MKDEV(AOE_MAJOR, chardevs[i].minor),
 					NULL, chardevs[i].name);
 
drivers/block/paride/pg.c +1 -1
@@ -674,7 +674,7 @@ static int __init pg_init(void)
 	for (unit = 0; unit < PG_UNITS; unit++) {
 		struct pg *dev = &devices[unit];
 		if (dev->present) {
-			class_device_create(pg_class, MKDEV(major, unit),
+			class_device_create(pg_class, NULL, MKDEV(major, unit),
 					NULL, "pg%u", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit),
 				      S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
drivers/block/paride/pt.c +2 -2
@@ -971,7 +971,7 @@ static int __init pt_init(void)
 	devfs_mk_dir("pt");
 	for (unit = 0; unit < PT_UNITS; unit++)
 		if (pt[unit].present) {
-			class_device_create(pt_class, MKDEV(major, unit),
+			class_device_create(pt_class, NULL, MKDEV(major, unit),
 					NULL, "pt%d", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit),
 				      S_IFCHR | S_IRUSR | S_IWUSR,
@@ -980,7 +980,7 @@ static int __init pt_init(void)
 				class_device_destroy(pt_class, MKDEV(major, unit));
 				goto out_class;
 			}
-			class_device_create(pt_class, MKDEV(major, unit + 128),
+			class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
 					NULL, "pt%dn", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit + 128),
 				      S_IFCHR | S_IRUSR | S_IWUSR,
drivers/char/dsp56k.c +1 -1
@@ -515,7 +515,7 @@ static int __init dsp56k_init_driver(voi
 		err = PTR_ERR(dsp56k_class);
 		goto out_chrdev;
 	}
-	class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
+	class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
 
 	err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
 		      S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
drivers/char/ip2main.c +6 -4
@@ -721,8 +721,9 @@ ip2_loadmain(int *iop, int *irqp, unsign
 			}
 
 			if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
-				class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
-						4 * i), NULL, "ipl%d", i);
+				class_device_create(ip2_class, NULL,
+						MKDEV(IP2_IPL_MAJOR, 4 * i),
+						NULL, "ipl%d", i);
 				err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
 						"ip2/ipl%d", i);
@@ -732,8 +733,9 @@ ip2_loadmain(int *iop, int *irqp, unsign
 					goto out_class;
 				}
 
-				class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
-						4 * i + 1), NULL, "stat%d", i);
+				class_device_create(ip2_class, NULL,
+						MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+						NULL, "stat%d", i);
 				err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
 						"ip2/stat%d", i);
drivers/char/istallion.c +2 -1
@@ -5246,7 +5246,8 @@ int __init stli_init(void)
 		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
 			       S_IFCHR | S_IRUSR | S_IWUSR,
 			       "staliomem/%d", i);
-		class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
+		class_device_create(istallion_class, NULL,
+				MKDEV(STL_SIOMEMMAJOR, i),
 				NULL, "staliomem%d", i);
 	}
 
drivers/char/lp.c +1 -1
@@ -805,7 +805,7 @@ static int lp_register(int nr, struct pa
 	if (reset)
 		lp_reset(nr);
 
-	class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+	class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
 				"lp%d", nr);
 	devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
 			"printers/%d", nr);
drivers/char/mem.c +2 -1
@@ -920,7 +920,8 @@ static int __init chr_dev_init(void)
 
 	mem_class = class_create(THIS_MODULE, "mem");
 	for (i = 0; i < ARRAY_SIZE(devlist); i++) {
-		class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
+		class_device_create(mem_class, NULL,
+					MKDEV(MEM_MAJOR, devlist[i].minor),
 					NULL, devlist[i].name);
 		devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
 				S_IFCHR | devlist[i].mode, devlist[i].name);
drivers/char/misc.c +1 -1
@@ -234,7 +234,7 @@ int misc_register(struct miscdevice * mi
 	}
 	dev = MKDEV(MISC_MAJOR, misc->minor);
 
-	misc->class = class_device_create(misc_class, dev, misc->dev,
+	misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
 					  "%s", misc->name);
 	if (IS_ERR(misc->class)) {
 		err = PTR_ERR(misc->class);
drivers/char/ppdev.c +1 -1
@@ -752,7 +752,7 @@ static struct file_operations pp_fops = 
 
 static void pp_attach(struct parport *port)
 {
-	class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
+	class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
 			NULL, "parport%d", port->number);
 }
 
drivers/char/raw.c +2 -2
@@ -128,7 +128,7 @@ raw_ioctl(struct inode *inode, struct fi
 static void bind_device(struct raw_config_request *rq)
 {
 	class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-	class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+	class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
 				      NULL, "raw%d", rq->raw_minor);
 }
 
@@ -307,7 +307,7 @@ static int __init raw_init(void)
 		unregister_chrdev_region(dev, MAX_RAW_MINORS);
 		goto error;
 	}
-	class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+	class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
 	devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
 		      S_IFCHR | S_IRUGO | S_IWUGO,
drivers/char/snsc.c +1 -1
@@ -437,7 +437,7 @@ scdrv_init(void)
 				continue;
 			}
 
-			class_device_create(snsc_class, dev, NULL,
+			class_device_create(snsc_class, NULL, dev, NULL,
 						"%s", devname);
 
 			ia64_sn_irtr_intr_enable(scd->scd_nasid,
drivers/char/stallion.c +3 -1
@@ -3095,7 +3095,9 @@ static int __init stl_init(void)
 		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
 				S_IFCHR|S_IRUSR|S_IWUSR,
 				"staliomem/%d", i);
-		class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
+		class_device_create(stallion_class, NULL,
+				    MKDEV(STL_SIOMEMMAJOR, i), NULL,
+				    "staliomem%d", i);
 	}
 
 	stl_serial->owner = THIS_MODULE;
drivers/char/tipar.c +1 -1
@@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *p
 		goto out;
 	}
 
-	class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
+	class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
 			TIPAR_MINOR + nr), NULL, "par%d", nr);
 	/* Use devfs, tree: /dev/ticables/par/[0..2] */
 	err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
drivers/char/tty_io.c +5 -5
@@ -2728,7 +2728,7 @@ void tty_register_device(struct tty_driv
 		pty_line_name(driver, index, name);
 	else
 		tty_line_name(driver, index, name);
-	class_device_create(tty_class, dev, device, name);
+	class_device_create(tty_class, NULL, dev, device, "%s", name);
 }
 
 /**
@@ -2983,14 +2983,14 @@ static int __init tty_init(void)
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
 		panic("Couldn't register /dev/tty driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
-	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
 
 	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)
 		panic("Couldn't register /dev/console driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
-	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
 
 #ifdef CONFIG_UNIX98_PTYS
 	cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2998,7 +2998,7 @@ static int __init tty_init(void)
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
-	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+	class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 #endif
 
 #ifdef CONFIG_VT
@@ -3007,7 +3007,7 @@ static int __init tty_init(void)
 	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
 		panic("Couldn't register /dev/tty0 driver\n");
 	devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
-	class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+	class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
 
 	vty_init();
 #endif
drivers/char/ftape/zftape/zftape-init.c +6 -6
@@ -331,27 +331,27 @@ KERN_INFO
 
 	zft_class = class_create(THIS_MODULE, "zft");
 	for (i = 0; i < 4; i++) {
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"qft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"zqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nzqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"rawqft%i", i);
-		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
+		class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nrawqft%i", i);
drivers/char/ipmi/ipmi_devintf.c +1 -1
@@ -798,7 +798,7 @@ static void ipmi_new_smi(int if_num)
 	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
 		      "ipmidev/%d", if_num);
 
-	class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
+	class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num);
 }
 
 static void ipmi_smi_gone(int if_num)
drivers/char/vc_screen.c +6 -4
@@ -484,8 +484,10 @@ void vcs_make_devfs(struct tty_struct *t
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
 			S_IFCHR|S_IRUSR|S_IWUSR,
 			"vcc/a%u", tty->index + 1);
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+			NULL, "vcs%u", tty->index + 1);
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+			NULL, "vcsa%u", tty->index + 1);
 }
 void vcs_remove_devfs(struct tty_struct *tty)
 {
@@ -503,7 +505,7 @@ int __init vcs_init(void)
 
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
-	class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+	class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
 	return 0;
 }
drivers/char/viotape.c +2 -2
@@ -956,9 +956,9 @@ static int viotape_probe(struct vio_dev 
 	state[i].cur_part = 0;
 	for (j = 0; j < MAX_PARTITIONS; ++j)
 		state[i].part_stat_rwi[j] = VIOT_IDLE;
-	class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+	class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
 			"iseries!vt%d", i);
-	class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+	class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
 			NULL, "iseries!nvt%d", i);
 	devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
 			"iseries/vt%d", i);
drivers/hwmon/hwmon.c +1 -1
@@ -45,7 +45,7 @@ struct class_device *hwmon_device_regist
 		return ERR_PTR(-ENOMEM);
 
 	id = id & MAX_ID_MASK;
-	cdev = class_device_create(hwmon_class, MKDEV(0,0), dev,
+	cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev,
 					HWMON_ID_FORMAT, id);
 
 	if (IS_ERR(cdev))
drivers/ide/ide-tape.c +2 -2
@@ -4884,9 +4884,9 @@ static int ide_tape_probe(struct device 
 
 	idetape_setup(drive, tape, minor);
 
-	class_device_create(idetape_sysfs_class,
+	class_device_create(idetape_sysfs_class, NULL,
 			MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name);
-	class_device_create(idetape_sysfs_class,
+	class_device_create(idetape_sysfs_class, NULL,
 			MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name);
 
 	devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
drivers/ieee1394/dv1394.c +1 -1
@@ -2361,7 +2361,7 @@ static void dv1394_add_host (struct hpsb
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	class_device_create(hpsb_protocol_class, MKDEV(
+	class_device_create(hpsb_protocol_class, NULL, MKDEV(
 		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
 		NULL, "dv1394-%d", id);
 	devfs_mk_dir("ieee1394/dv/host%d", id);
drivers/ieee1394/raw1394.c +1 -1
@@ -2904,7 +2904,7 @@ static int __init init_raw1394(void)
 
 	hpsb_register_highlevel(&raw1394_highlevel);
 
-	if (IS_ERR(class_device_create(hpsb_protocol_class, MKDEV(
+	if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
 		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_RAW1394 * 16), 
 		NULL, RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
drivers/ieee1394/video1394.c +1 -1
@@ -1370,7 +1370,7 @@ static void video1394_add_host (struct h
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	class_device_create(hpsb_protocol_class, MKDEV(
+	class_device_create(hpsb_protocol_class, NULL, MKDEV(
 		IEEE1394_MAJOR,	minor), 
 		NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 	devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
drivers/infiniband/core/ucm.c +1 -1
@@ -1300,7 +1300,7 @@ static int __init ib_ucm_init(void)
 		goto err_class;
 	}
 
-	class_device_create(ib_ucm_class, IB_UCM_DEV, NULL, "ucm");
+	class_device_create(ib_ucm_class, NULL, IB_UCM_DEV, NULL, "ucm");
 
 	idr_init(&ctx_id_table);
 	init_MUTEX(&ctx_id_mutex);
drivers/isdn/capi/capi.c +1 -1
@@ -1505,7 +1505,7 @@ static int __init capi_init(void)
 		return PTR_ERR(capi_class);
 	}
 
-	class_device_create(capi_class, MKDEV(capi_major, 0), NULL, "capi");
+	class_device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
 	devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
 			"isdn/capi20");
 
drivers/macintosh/adb.c +1 -1
@@ -905,5 +905,5 @@ adbdev_init(void)
 	adb_dev_class = class_create(THIS_MODULE, "adb");
 	if (IS_ERR(adb_dev_class))
 		return;
-	class_device_create(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+	class_device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
 }
drivers/media/dvb/dvb-core/dvbdev.c +1 -1
@@ -235,7 +235,7 @@ int dvb_register_device(struct dvb_adapt
 			S_IFCHR | S_IRUSR | S_IWUSR,
 			"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 
-	class_device_create(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+	class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
 			    NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
 
 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
drivers/message/i2o/iop.c +1 -1
@@ -1141,7 +1141,7 @@ int i2o_iop_add(struct i2o_controller *c
 		goto iop_reset;
 	}
 
-	c->classdev = class_device_create(i2o_controller_class, 0,
+	c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0),
 			&c->device, "iop%d", c->unit);
 	if (IS_ERR(c->classdev)) {
 		osm_err("%s: could not add controller class\n", c->name);
drivers/mtd/mtdchar.c +2 -2
@@ -24,10 +24,10 @@ static void mtd_notify_add(struct mtd_in
 	if (!mtd)
 		return;
 
-	class_device_create(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+	class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
 			    NULL, "mtd%d", mtd->index);
 	
-	class_device_create(mtd_class, 
+	class_device_create(mtd_class, NULL,
 			    MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
 			    NULL, "mtd%dro", mtd->index);
 }
drivers/net/ppp_generic.c +1 -1
@@ -863,7 +863,7 @@ static int __init ppp_init(void)
 			err = PTR_ERR(ppp_class);
 			goto out_chrdev;
 		}
-		class_device_create(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+		class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
 		err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
 				S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
 		if (err)
drivers/net/wan/cosa.c +1 -1
@@ -400,7 +400,7 @@ static int __init cosa_init(void)
 		goto out_chrdev;
 	}
 	for (i=0; i<nr_cards; i++) {
-		class_device_create(cosa_class, MKDEV(cosa_major, i),
+		class_device_create(cosa_class, NULL, MKDEV(cosa_major, i),
 				NULL, "cosa%d", i);
 		err = devfs_mk_cdev(MKDEV(cosa_major, i),
 				S_IFCHR|S_IRUSR|S_IWUSR,
drivers/s390/char/tape_class.c +1 -0
@@ -72,6 +72,7 @@ struct tape_class_device *register_tape_
 
 	tcd->class_device = class_device_create(
 				tape_class,
+				NULL,
 				tcd->char_device->dev,
 				device,
 				"%s", tcd->device_name
drivers/s390/char/vmlogrdr.c +1 -0
@@ -787,6 +787,7 @@ vmlogrdr_register_device(struct vmlogrdr
 		return ret;
 	}
 	priv->class_device = class_device_create(
+				NULL,
 				vmlogrdr_class,
 				MKDEV(vmlogrdr_major, priv->minor_num),
 				dev,
drivers/scsi/ch.c +1 -1
@@ -936,7 +936,7 @@ static int ch_probe(struct device *dev)
 	if (init)
 		ch_init_elem(ch);
 
-	class_device_create(ch_sysfs_class,
+	class_device_create(ch_sysfs_class, NULL,
 			    MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
 			    dev, "s%s", ch->name);
 
drivers/scsi/osst.c +1 -1
@@ -5627,7 +5627,7 @@ static void osst_sysfs_add(dev_t dev, st
 
 	if (!osst_sysfs_valid) return;
 
-	osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name);
+	osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name);
 	if (IS_ERR(osst_class_member)) {
 		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
 		return;
drivers/scsi/sg.c +1 -1
@@ -1550,7 +1550,7 @@ sg_add(struct class_device *cl_dev, stru
 	if (sg_sysfs_valid) {
 		struct class_device * sg_class_member;
 
-		sg_class_member = class_device_create(sg_sysfs_class,
+		sg_class_member = class_device_create(sg_sysfs_class, NULL,
 				MKDEV(SCSI_GENERIC_MAJOR, k), 
 				cl_dev->dev, "%s", 
 				disk->disk_name);
drivers/scsi/st.c +1 -1
@@ -4375,7 +4375,7 @@ static void do_create_class_files(struct
 		snprintf(name, 10, "%s%s%s", rew ? "n" : "",
 			 STp->disk->disk_name, st_formats[i]);
 		st_class_member =
-			class_device_create(st_sysfs_class,
+			class_device_create(st_sysfs_class, NULL,
 					    MKDEV(SCSI_TAPE_MAJOR,
 						  TAPE_MINOR(dev_num, mode, rew)),
 					    &STp->device->sdev_gendev, "%s", name);
drivers/input/evdev.c +1 -1
@@ -689,7 +689,7 @@ static struct input_handle *evdev_connec
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
-	class_device_create(input_class,
+	class_device_create(input_class, NULL,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
 			dev->dev, "event%d", minor);
 
drivers/input/joydev.c +1 -1
@@ -516,7 +516,7 @@ static struct input_handle *joydev_conne
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
-	class_device_create(input_class,
+	class_device_create(input_class, NULL,
 			MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
 			dev->dev, "js%d", minor);
 
drivers/input/mousedev.c +2 -2
@@ -651,7 +651,7 @@ static struct input_handle *mousedev_con
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
-	class_device_create(input_class,
+	class_device_create(input_class, NULL,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
 			dev->dev, "mouse%d", minor);
 
@@ -740,7 +740,7 @@ static int __init mousedev_init(void)
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
-	class_device_create(input_class,
+	class_device_create(input_class, NULL,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
drivers/input/tsdev.c +1 -1
@@ -414,7 +414,7 @@ static struct input_handle *tsdev_connec
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
-	class_device_create(input_class,
+	class_device_create(input_class, NULL,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
 			dev->dev, "ts%d", minor);
 
arch/i386/kernel/cpuid.c +1 -1
@@ -163,7 +163,7 @@ static int cpuid_class_device_create(int
 	int err = 0;
 	struct class_device *class_err;
 
-	class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
+	class_err = class_device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
 	if (IS_ERR(class_err))
 		err = PTR_ERR(class_err);
 	return err;
arch/i386/kernel/msr.c +1 -1
@@ -246,7 +246,7 @@ static int msr_class_device_create(int i
 	int err = 0;
 	struct class_device *class_err;
 
-	class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
+	class_err = class_device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
 	if (IS_ERR(class_err)) 
 		err = PTR_ERR(class_err);
 	return err;
sound/core/sound.c +1 -1
@@ -231,7 +231,7 @@ int snd_register_device(int type, snd_ca
 		devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
 	if (card)
 		device = card->dev;
-	class_device_create(sound_class, MKDEV(major, minor), device, "%s", name);
+	class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name);
 
 	up(&sound_mutex);
 	return 0;
sound/oss/soundcard.c +2 -2
@@ -567,7 +567,7 @@ static int __init oss_init(void)
 		devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor),
 				S_IFCHR | dev_list[i].mode,
 				"sound/%s", dev_list[i].name);
-		class_device_create(sound_class,
+		class_device_create(sound_class, NULL,
 				    MKDEV(SOUND_MAJOR, dev_list[i].minor),
 				    NULL, "%s", dev_list[i].name);
 
@@ -579,7 +579,7 @@ static int __init oss_init(void)
 						dev_list[i].minor + (j*0x10)),
 					S_IFCHR | dev_list[i].mode,
 					"sound/%s%d", dev_list[i].name, j);
-			class_device_create(sound_class,
+			class_device_create(sound_class, NULL,
 					    MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
 					    NULL, "%s%d", dev_list[i].name, j);
 		}
sound/sound_core.c +1 -1
@@ -174,7 +174,7 @@ static int sound_insert_unit(struct soun
 
 	devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
 			S_IFCHR | mode, s->name);
-	class_device_create(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
+	class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor),
 			    dev, s->name+6);
 	return r;
 
fs/coda/psdev.c +2 -2
@@ -370,8 +370,8 @@ static int init_coda_psdev(void)
 	}		
 	devfs_mk_dir ("coda");
 	for (i = 0; i < MAX_CODADEVS; i++) {
-		class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
-				NULL, "cfs%d", i);
+		class_device_create(coda_psdev_class, NULL,
+				MKDEV(CODA_PSDEV_MAJOR,i), NULL, "cfs%d", i);
 		err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
 				S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
 		if (err)

--

author
#3 lore raw

PATCH 3/8 Driver Core: document struct class_device properly

In reply to Greg KH

From: Greg Kroah-Hartman <[email protected]>

---
 include/linux/device.h |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
include/linux/device.h +24 -0
@@ -203,6 +203,30 @@ struct class_device_attribute class_devi
 extern int class_device_create_file(struct class_device *,
 				    const struct class_device_attribute *);
 
+/**
+ * struct class_device - class devices
+ * @class: pointer to the parent class for this class device.  This is required.
+ * @devt: for internal use by the driver core only.
+ * @node: for internal use by the driver core only.
+ * @kobj: for internal use by the driver core only.
+ * @devt_attr: for internal use by the driver core only.
+ * @dev: if set, a symlink to the struct device is created in the sysfs
+ * directory for this struct class device.
+ * @class_data: pointer to whatever you want to store here for this struct
+ * class_device.  Use class_get_devdata() and class_set_devdata() to get and
+ * set this pointer.
+ * @parent: pointer to a struct class_device that is the parent of this struct
+ * class_device.  If NULL, this class_device will show up at the root of the
+ * struct class in sysfs (which is probably what you want to have happen.)
+ * @release: pointer to a release function for this struct class_device.  If
+ * set, this will be called instead of the class specific release function.
+ * Only use this if you want to override the default release function, like
+ * when you are nesting class_device structures.
+ * @hotplug: pointer to a hotplug function for this struct class_device.  If
+ * set, this will be called instead of the class specific hotplug function.
+ * Only use this if you want to override the default hotplug function, like
+ * when you are nesting class_device structures.
+ */
 struct class_device {
 	struct list_head	node;
 

--

author
#4 lore raw

PATCH 4/8 input: register the input class device sooner

In reply to Greg KH

From: Greg Kroah-Hartman <[email protected]>

This is needed so we can actually use the class device within the input handlers.

---
 drivers/input/input.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/input/input.c +3 -3
@@ -795,6 +795,9 @@ void input_register_device(struct input_
 	INIT_LIST_HEAD(&dev->h_list);
 	list_add_tail(&dev->node, &input_dev_list);
 
+	if (dev->dynalloc)
+		input_register_classdevice(dev);
+
 	list_for_each_entry(handler, &input_handler_list, node)
 		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
 			if ((id = input_match_device(handler->id_table, dev)))
@@ -802,9 +805,6 @@ void input_register_device(struct input_
 					input_link_handle(handle);
 
 
-	if (dev->dynalloc)
-		input_register_classdevice(dev);
-
 #ifdef CONFIG_HOTPLUG
 	input_call_hotplug("add", dev);
 #endif

--

author
#5 lore raw
In reply to Greg KH
Quoted 5 lines · Greg KH

Ok, finally. Here's a set of _working_ patches that properly implement nesting class_device structures, and the follow-on patches to move the input subsystem to use them. Hotplug and release functions work properly now, and this will let us move /sys/block/ to use class and class_device structures soon.

Oh, Kay, do you have a public patch to udevstart/udev that can handle this nested structure? It might be good to have that so people can test these in the next -mm.

thanks,

greg k-h

#6 lore raw
Quoted 10 lines · Greg KH
Quoted 5 lines · Greg KH

Ok, finally. Here's a set of _working_ patches that properly implement nesting class_device structures, and the follow-on patches to move the input subsystem to use them. Hotplug and release functions work properly now, and this will let us move /sys/block/ to use class and class_device structures soon.

Oh, Kay, do you have a public patch to udevstart/udev that can handle this nested structure? It might be good to have that so people can test these in the next -mm.

Sure, here is an still untested hack. Sorry, I'm "busy" at a conference this week. Anyhow, I still think that we really don't want to nest classes this way. :)

Thanks,
Kay

---

libsysfs/sysfs_class.c +39 -9
index edf751b..e95c919 100644
@@ -227,16 +227,46 @@ struct sysfs_class_device *sysfs_get_cla
 	if (clsdev->parent)
 		return (clsdev->parent);
 
-	/*
-	 * As of now, only block devices have a parent child heirarchy in sysfs
-	 * We do not know, if, in the future, more classes will have a similar
-	 * structure. Hence, we now call a specialized function for block and
-	 * later we can add support functions for other subsystems as required.
-	 */
-	if (!(strncmp(clsdev->classname, SYSFS_BLOCK_NAME, 
-					sizeof(SYSFS_BLOCK_NAME)))) {
-		if ((get_blockdev_parent(clsdev)) == 0) 
+	if (!strncmp(clsdev->classname, SYSFS_BLOCK_NAME, sizeof(SYSFS_BLOCK_NAME))) {
+		if ((get_blockdev_parent(clsdev)) == 0)
 			return (clsdev->parent);
+	} else if (!strncmp(clsdev->classname, SYSFS_CLASS_NAME, sizeof(SYSFS_CLASS_NAME))) {
+		char ppath[SYSFS_PATH_MAX];
+		char dpath[SYSFS_PATH_MAX];
+		char *tmp;
+
+		memset(ppath, 0, SYSFS_PATH_MAX);
+		memset(dpath, 0, SYSFS_PATH_MAX);
+		safestrcpy(ppath, clsdev->path);
+		tmp = strrchr(ppath, '/');
+		if (!tmp) {
+			dprintf("Invalid path to device %s\n", ppath);
+			return NULL;
+		}
+		if (*(tmp + 1) == '\0') {
+			*tmp = '\0';
+			tmp = strrchr(tmp, '/');
+			if (tmp == NULL) {
+				dprintf("Invalid path to device %s\n", ppath);
+				return NULL;
+			}
+		}
+		*tmp = '\0';
+
+		/* Make sure we're not at the top of the device tree */
+		sysfs_get_mnt_path(dpath, SYSFS_PATH_MAX);
+		safestrcat(dpath, "/" SYSFS_CLASS_NAME);
+		if (strcmp(dpath, ppath) == 0) {
+			dprintf("Device at %s does not have a parent\n", clsdev->path);
+			return NULL;
+		}
+
+		clsdev->parent = sysfs_open_class_device_path(ppath);
+		if (!clsdev->parent) {
+			dprintf("Error opening device %s's parent at %s\n", clsdev->name, ppath);
+			return NULL;
+		}
+		return (clsdev->parent);
 	}
 	return NULL;
 }
udevstart.c +23 -2
index ce96f38..09f0e5d 100644
@@ -79,7 +79,7 @@ static int device_list_insert(const char
 	struct device *new_device;
 	const char *devpath = &path[strlen(sysfs_path)];
 
-	dbg("insert: '%s'\n", devpath);
+	dbg("insert: '%s'", devpath);
 
 	list_for_each_entry(loop_device, device_list, node) {
 		if (strcmp(loop_device->path, devpath) > 0) {
@@ -296,7 +296,6 @@ static void udev_scan_class(struct list_
 		for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
 			char dirname[PATH_SIZE];
 			DIR *dir2;
-			struct dirent *dent2;
 
 			if (dent->d_name[0] == '.')
 				continue;
@@ -306,6 +305,9 @@ static void udev_scan_class(struct list_
 
 			dir2 = opendir(dirname);
 			if (dir2 != NULL) {
+				DIR *dir3;
+				struct dirent *dent2;
+
 				for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
 					char dirname2[PATH_SIZE];
 
@@ -317,6 +319,25 @@ static void udev_scan_class(struct list_
 
 					if (has_devt(dirname2) || strcmp(dent->d_name, "net") == 0)
 						device_list_insert(dirname2, dent->d_name, device_list);
+
+					dir3 = opendir(dirname2);
+					if (dir3 != NULL) {
+						struct dirent *dent3;
+
+						for (dent3 = readdir(dir3); dent3 != NULL; dent3 = readdir(dir3)) {
+							char dirname3[PATH_SIZE];
+
+							if (dent3->d_name[0] == '.')
+								continue;
+
+							snprintf(dirname3, sizeof(dirname3), "%s/%s", dirname2, dent3->d_name);
+							dirname3[sizeof(dirname3)-1] = '\0';
+
+							if (has_devt(dirname3))
+								device_list_insert(dirname3, dent->d_name, device_list);
+						}
+						closedir(dir3);
+					}
 				}
 				closedir(dir2);
 			}
author
#7 lore raw

PATCH 5/8 input: export input_dev_class so that input drivers can use it.

In reply to Greg KH

From: Greg Kroah-Hartman <[email protected]>

---
 drivers/input/input.c |    3 ++-
 include/linux/input.h |    1 +
 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/input/input.c +2 -1
@@ -40,6 +40,7 @@ EXPORT_SYMBOL(input_accept_process);
 EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
 EXPORT_SYMBOL(input_class);
+EXPORT_SYMBOL_GPL(input_dev_class);
 
 #define INPUT_DEVICES	256
 
@@ -724,7 +725,7 @@ static void input_dev_release(struct cla
 	module_put(THIS_MODULE);
 }
 
-static struct class input_dev_class = {
+struct class input_dev_class = {
 	.name			= "input_dev",
 	.release		= input_dev_release,
 	.class_dev_attrs	= input_dev_attrs,
include/linux/input.h +1 -0
@@ -1075,6 +1075,7 @@ static inline void input_set_abs_params(
 }
 
 extern struct class *input_class;
+extern struct class input_dev_class;
 
 #endif
 #endif

--

author
#8 lore raw

PATCH 6/8 input: move the input class devices under their new input_dev devices

In reply to Greg KH

From: Greg Kroah-Hartman <[email protected]>

---
 drivers/input/evdev.c    |    6 +++---
 drivers/input/joydev.c   |    6 +++---
 drivers/input/mousedev.c |   10 +++++-----
 drivers/input/tsdev.c    |    6 +++---
 4 files changed, 14 insertions(+), 14 deletions(-)
drivers/input/mousedev.c +5 -5
@@ -648,9 +648,9 @@ static struct input_handle *mousedev_con
 
 	mousedev_table[minor] = mousedev;
 
-	class_device_create(input_class, NULL,
+	class_device_create(&input_dev_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-			dev->dev, "mouse%d", minor);
+			dev->cdev.dev, "mouse%d", minor);
 
 	return &mousedev->handle;
 }
@@ -660,7 +660,7 @@ static void mousedev_disconnect(struct i
 	struct mousedev *mousedev = handle->private;
 	struct mousedev_list *list;
 
-	class_device_destroy(input_class,
+	class_device_destroy(&input_dev_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 	mousedev->exist = 0;
 
@@ -734,7 +734,7 @@ static int __init mousedev_init(void)
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
 
-	class_device_create(input_class, NULL,
+	class_device_create(&input_dev_class, NULL,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -753,7 +753,7 @@ static void __exit mousedev_exit(void)
 	if (psaux_registered)
 		misc_deregister(&psaux_mouse);
 #endif
-	class_device_destroy(input_class,
+	class_device_destroy(&input_dev_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 	input_unregister_handler(&mousedev_handler);
 }
drivers/input/evdev.c +3 -3
@@ -686,9 +686,9 @@ static struct input_handle *evdev_connec
 
 	evdev_table[minor] = evdev;
 
-	class_device_create(input_class, NULL,
+	class_device_create(&input_dev_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-			dev->dev, "event%d", minor);
+			dev->cdev.dev, "event%d", minor);
 
 	return &evdev->handle;
 }
@@ -698,7 +698,7 @@ static void evdev_disconnect(struct inpu
 	struct evdev *evdev = handle->private;
 	struct evdev_list *list;
 
-	class_device_destroy(input_class,
+	class_device_destroy(&input_dev_class,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	evdev->exist = 0;
 
drivers/input/joydev.c +3 -3
@@ -513,9 +513,9 @@ static struct input_handle *joydev_conne
 
 	joydev_table[minor] = joydev;
 
-	class_device_create(input_class, NULL,
+	class_device_create(&input_dev_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-			dev->dev, "js%d", minor);
+			dev->cdev.dev, "js%d", minor);
 
 	return &joydev->handle;
 }
@@ -525,7 +525,7 @@ static void joydev_disconnect(struct inp
 	struct joydev *joydev = handle->private;
 	struct joydev_list *list;
 
-	class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
+	class_device_destroy(&input_dev_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	joydev->exist = 0;
 
 	if (joydev->open) {
drivers/input/tsdev.c +3 -3
@@ -409,9 +409,9 @@ static struct input_handle *tsdev_connec
 
 	tsdev_table[minor] = tsdev;
 
-	class_device_create(input_class, NULL,
+	class_device_create(&input_dev_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-			dev->dev, "ts%d", minor);
+			dev->cdev.dev, "ts%d", minor);
 
 	return &tsdev->handle;
 }
@@ -421,7 +421,7 @@ static void tsdev_disconnect(struct inpu
 	struct tsdev *tsdev = handle->private;
 	struct tsdev_list *list;
 
-	class_device_destroy(input_class,
+	class_device_destroy(&input_dev_class,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	tsdev->exist = 0;
 

--

author
#9 lore raw

PATCH 7/8 input: remove the input_class structure, as it is unused.

In reply to Greg KH

From: Greg Kroah-Hartman <[email protected]>

---
 drivers/input/input.c |   18 +++---------------
 include/linux/input.h |    1 -
 2 files changed, 3 insertions(+), 16 deletions(-)
drivers/input/input.c +3 -15
@@ -39,7 +39,6 @@ EXPORT_SYMBOL(input_close_device);
 EXPORT_SYMBOL(input_accept_process);
 EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
-EXPORT_SYMBOL(input_class);
 EXPORT_SYMBOL_GPL(input_dev_class);
 
 #define INPUT_DEVICES	256
@@ -922,8 +921,6 @@ static struct file_operations input_fops
 	.open = input_open_file,
 };
 
-struct class *input_class;
-
 static int __init input_init(void)
 {
 	int err;
@@ -934,27 +931,19 @@ static int __init input_init(void)
 		return err;
 	}
 
-	input_class = class_create(THIS_MODULE, "input");
-	if (IS_ERR(input_class)) {
-		printk(KERN_ERR "input: unable to register input class\n");
-		err = PTR_ERR(input_class);
-		goto fail1;
-	}
-
 	err = input_proc_init();
 	if (err)
-		goto fail2;
+		goto fail1;
 
 	err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
 	if (err) {
 		printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
-		goto fail3;
+		goto fail2;
 	}
 
 	return 0;
 
- fail3:	input_proc_exit();
- fail2:	class_destroy(input_class);
+ fail2:	input_proc_exit();
  fail1:	class_unregister(&input_dev_class);
 	return err;
 }
@@ -963,7 +952,6 @@ static void __exit input_exit(void)
 {
 	input_proc_exit();
 	unregister_chrdev(INPUT_MAJOR, "input");
-	class_destroy(input_class);
 	class_unregister(&input_dev_class);
 }
 
include/linux/input.h +0 -1
@@ -1074,7 +1074,6 @@ static inline void input_set_abs_params(
 	dev->absbit[LONG(axis)] |= BIT(axis);
 }
 
-extern struct class *input_class;
 extern struct class input_dev_class;
 
 #endif

--

author
#10 lore raw

PATCH 8/8 input: rename input_dev_class to input_class to be correct.

In reply to Greg KH

From: Greg Kroah-Hartman <[email protected]>

---
 drivers/input/evdev.c    |    4 ++--
 drivers/input/input.c    |   14 +++++++-------
 drivers/input/joydev.c   |    4 ++--
 drivers/input/mousedev.c |    8 ++++----
 drivers/input/tsdev.c    |    4 ++--
 include/linux/input.h    |    2 +-
 6 files changed, 18 insertions(+), 18 deletions(-)
drivers/input/evdev.c +2 -2
@@ -686,7 +686,7 @@ static struct input_handle *evdev_connec
 
 	evdev_table[minor] = evdev;
 
-	class_device_create(&input_dev_class, &dev->cdev,
+	class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
 			dev->cdev.dev, "event%d", minor);
 
@@ -698,7 +698,7 @@ static void evdev_disconnect(struct inpu
 	struct evdev *evdev = handle->private;
 	struct evdev_list *list;
 
-	class_device_destroy(&input_dev_class,
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	evdev->exist = 0;
 
drivers/input/input.c +7 -7
@@ -39,7 +39,7 @@ EXPORT_SYMBOL(input_close_device);
 EXPORT_SYMBOL(input_accept_process);
 EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
-EXPORT_SYMBOL_GPL(input_dev_class);
+EXPORT_SYMBOL_GPL(input_class);
 
 #define INPUT_DEVICES	256
 
@@ -724,8 +724,8 @@ static void input_dev_release(struct cla
 	module_put(THIS_MODULE);
 }
 
-struct class input_dev_class = {
-	.name			= "input_dev",
+struct class input_class = {
+	.name			= "input",
 	.release		= input_dev_release,
 	.class_dev_attrs	= input_dev_attrs,
 };
@@ -737,7 +737,7 @@ struct input_dev *input_allocate_device(
 	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
 	if (dev) {
 		dev->dynalloc = 1;
-		dev->cdev.class = &input_dev_class;
+		dev->cdev.class = &input_class;
 		class_device_initialize(&dev->cdev);
 		INIT_LIST_HEAD(&dev->h_list);
 		INIT_LIST_HEAD(&dev->node);
@@ -925,7 +925,7 @@ static int __init input_init(void)
 {
 	int err;
 
-	err = class_register(&input_dev_class);
+	err = class_register(&input_class);
 	if (err) {
 		printk(KERN_ERR "input: unable to register input_dev class\n");
 		return err;
@@ -944,7 +944,7 @@ static int __init input_init(void)
 	return 0;
 
  fail2:	input_proc_exit();
- fail1:	class_unregister(&input_dev_class);
+ fail1:	class_unregister(&input_class);
 	return err;
 }
 
@@ -952,7 +952,7 @@ static void __exit input_exit(void)
 {
 	input_proc_exit();
 	unregister_chrdev(INPUT_MAJOR, "input");
-	class_unregister(&input_dev_class);
+	class_unregister(&input_class);
 }
 
 subsys_initcall(input_init);
drivers/input/joydev.c +2 -2
@@ -513,7 +513,7 @@ static struct input_handle *joydev_conne
 
 	joydev_table[minor] = joydev;
 
-	class_device_create(&input_dev_class, &dev->cdev,
+	class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
 			dev->cdev.dev, "js%d", minor);
 
@@ -525,7 +525,7 @@ static void joydev_disconnect(struct inp
 	struct joydev *joydev = handle->private;
 	struct joydev_list *list;
 
-	class_device_destroy(&input_dev_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
+	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	joydev->exist = 0;
 
 	if (joydev->open) {
drivers/input/mousedev.c +4 -4
@@ -648,7 +648,7 @@ static struct input_handle *mousedev_con
 
 	mousedev_table[minor] = mousedev;
 
-	class_device_create(&input_dev_class, &dev->cdev,
+	class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
 			dev->cdev.dev, "mouse%d", minor);
 
@@ -660,7 +660,7 @@ static void mousedev_disconnect(struct i
 	struct mousedev *mousedev = handle->private;
 	struct mousedev_list *list;
 
-	class_device_destroy(&input_dev_class,
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 	mousedev->exist = 0;
 
@@ -734,7 +734,7 @@ static int __init mousedev_init(void)
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
 
-	class_device_create(&input_dev_class, NULL,
+	class_device_create(&input_class, NULL,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -753,7 +753,7 @@ static void __exit mousedev_exit(void)
 	if (psaux_registered)
 		misc_deregister(&psaux_mouse);
 #endif
-	class_device_destroy(&input_dev_class,
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 	input_unregister_handler(&mousedev_handler);
 }
drivers/input/tsdev.c +2 -2
@@ -409,7 +409,7 @@ static struct input_handle *tsdev_connec
 
 	tsdev_table[minor] = tsdev;
 
-	class_device_create(&input_dev_class, &dev->cdev,
+	class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
 			dev->cdev.dev, "ts%d", minor);
 
@@ -421,7 +421,7 @@ static void tsdev_disconnect(struct inpu
 	struct tsdev *tsdev = handle->private;
 	struct tsdev_list *list;
 
-	class_device_destroy(&input_dev_class,
+	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	tsdev->exist = 0;
 
include/linux/input.h +1 -1
@@ -1074,7 +1074,7 @@ static inline void input_set_abs_params(
 	dev->absbit[LONG(axis)] |= BIT(axis);
 }
 
-extern struct class input_dev_class;
+extern struct class input_class;
 
 #endif
 #endif

--

#11 lore raw
In reply to Greg KH
Quoted 40 lines · Greg KH

Ok, finally. Here's a set of _working_ patches that properly implement nesting class_device structures, and the follow-on patches to move the input subsystem to use them. Hotplug and release functions work properly now, and this will let us move /sys/block/ to use class and class_device structures soon.

The input patches are on top of almost all of Dmitry's input patches. All of them are together in one series in my public patches at:
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
and should show up in the next -mm release.

The sysfs tree looks the same as it did last time, but now hotplug works properly for addition and removal, and we actually free the memory used :)

For those that don't remember, here's the sysfs tree on my desktop:

$ tree /sys/class/input/ -d
/sys/class/input/
|-- input0
|   |-- capabilities
|   |-- event0
|   `-- id
|-- input1
|   |-- capabilities
|   |-- device -> ../../../devices/platform/i8042/serio1
|   |-- event1
|   |   `-- device -> ../../../../devices/platform/i8042/serio1
|   `-- id
|-- input3
|   |-- capabilities
|   |-- device -> ../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   |-- event2
|   |   `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   |-- id
|   |-- mouse0
|   |   `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   `-- ts0
|       `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
`-- mice
Quoted 6 lines

Ok, I think that covers everything.

Oh, one final thing. I really don't think that input should be a class. It looks like a "bus" and acts like a "bus" (you have different devices that have different drivers bind to them, and you want to load those drivers with the hotplug mechanism.)

[ Vojtech mumbles something about saying that from the beginning. ]

Quoted 4 lines

The only thing keeping this from
being a bus is the fact that we can't bind multiple drivers to a single device these days, and I can't see a way to move this code to that model, so oh well...

Oh, well.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
maintainer
#12 lore raw
Quoted 9 lines · Vojtech Pavlik
Quoted 5 lines · Greg KH

Oh, one final thing. I really don't think that input should be a class. It looks like a "bus" and acts like a "bus" (you have different devices that have different drivers bind to them, and you want to load those drivers with the hotplug mechanism.)

[ Vojtech mumbles something about saying that from the beginning. ]

I think Greg spoke a bit hastily here. Input_devs do not directly talk to the hardware and do not control power management and do not define access methods for the hardware therefore using bus abstraction would be wrong.

Quoted 5 lines
Quoted 4 lines

The only thing keeping this from
being a bus is the fact that we can't bind multiple drivers to a single device these days, and I can't see a way to move this code to that model, so oh well...

We should never let multiple drivers control the same piece of hardware (in all cases where you would you can always split that piece into smaller pieces, each controlled by its own driver). Input intrefaces, on the other hand, are not drivers in regular sense, they do not alter behavior of the underlying hardware. They just provide different "views"/interfaces for the same device and because they don't touch the hardware there can be many of them attached to the same device. This is the crucial difference between them and normal drivers.

--
Dmitry

#13 lore raw
In reply to Greg KH
Quoted 5 lines · Greg KH

Ok, finally. Here's a set of _working_ patches that properly implement nesting class_device structures, and the follow-on patches to move the input subsystem to use them. Hotplug and release functions work properly now, and this will let us move /sys/block/ to use class and class_device structures soon.

Sorry, I completely changed my head about the "class nesting". I don't like it anymore and think it's a wrong design to spread fractions of the device relation tree over /sys/class. That breaks the whole idea of "class" to provide easy access to devices of the same kind.

Quoted 34 lines

The input patches are on top of almost all of Dmitry's input patches. All of them are together in one series in my public patches at:
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
and should show up in the next -mm release.

The sysfs tree looks the same as it did last time, but now hotplug works properly for addition and removal, and we actually free the memory used :)

For those that don't remember, here's the sysfs tree on my desktop:

$ tree /sys/class/input/ -d
/sys/class/input/
|-- input0
|   |-- capabilities
|   |-- event0
|   `-- id
|-- input1
|   |-- capabilities
|   |-- device -> ../../../devices/platform/i8042/serio1
|   |-- event1
|   |   `-- device -> ../../../../devices/platform/i8042/serio1
|   `-- id
|-- input3
|   |-- capabilities
|   |-- device -> ../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   |-- event2
|   |   `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   |-- id
|   |-- mouse0
|   |   `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
|   `-- ts0
|       `-- device -> ../../../../devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0
`-- mice
Quoted 5 lines

To answer the remaining questions from the last thread:

Q: how are you going to determine what is really a class_dev and what
isn't, as there's no way to tell.
A: Who cares?

Me at least! :) As we can't distinguish between the type of class device which is nested. And that information is lost.

Quoted 5 lines

Seriously, tools like udev will watch for the "dev" file to be able create the required device node, and it will be the one getting the hotplug event. attribute groups do not generate hotplug events, and you should not be having a file called "dev" in your attribute group anyway.

Sure, that works for the "device node" case but stuff like HAL wants to build a meaningful tree from sysfs which does not only care about a "dev" file.
I looked at supporting stacked classes in HAL and that model doesn't fit.

Quoted 11 lines

Q: why does event2, mouse0, and input3 in the above tree all have the
same "device" symlink?
A: userspace tools expect that symlink there. They do not know that if
you traverse up a directory, and look at the symlink there, that's what the subdirectory points to too. That would be a mess. And, as those different class_device structures really are all bound to that same struct device, that is the proper representation of this.

Q: How can you determine between input interfaces and input devices?
A: input devices have a "dev" file. And what really does userspace need
to know here?

Sure, we really need to know this! We could only hardcode names and match against this to get meaningful information out of that.

Quoted 4 lines

Q: Wait, what about nesting struct class instead? That would work,
right?
A: No, nesting classes is not going to happen. Classes are "major"
things, and aren't related to each other (well, some are by their

Quoted 8 lines

name only, like the different "scsi*" classes, but to the user, they are separate.)
Also, we can't emulate /sys/block with nested classes. And no, we can't change this to be /sys/class/block/partitions and /sys/class/block/devices without almost every sysfs user complaining loudly. That's not the real representation of the devices, and we need to really try to keep backward compatibility where we possibly can.

Well, actually this proposal creates two complete different class devices below one class. That may not be *implemented* as "class nesting", but it is *represented* as that to userspace.
I really think it is wrong to have the input hardware abstraction "input0" at the same level as "mice", which is a _completely_ different animal.

Quoted 1 line

Ok, I think that covers everything.

No, I really don't like that random mix of devices. A class is a simple collection of devices with the same interface and should never nest or combine different things.

Quoted 7 lines

Oh, one final thing. I really don't think that input should be a class. It looks like a "bus" and acts like a "bus" (you have different devices that have different drivers bind to them, and you want to load those drivers with the hotplug mechanism.) The only thing keeping this from being a bus is the fact that we can't bind multiple drivers to a single device these days, and I can't see a way to move this code to that model, so oh well...

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

/sys

|-- class
|   |-- block
|   |   `-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda
|   |-- block_partition
|   |   |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda1
|   |   `-- sda2 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda2
|   |-- pci
|   |   `-- 0000:00:1f.2 -> ../../devices/pci0000:00/0000:00:1f.2
|   |-- input
|   |   |-- mice -> ../../devices/mice
|   |   |-- mouse0 -> ../../devices/platform/i8042/serio0/mouse0
|   |   `-- event0 -> ../../devices/platform/i8042/serio0/event0
|   |-- input_device
|   |   `-- inputdev0 -> ../../devices/platform/i8042/serio0
|   `-- tty
|       `-- console -> ../../devices/console
|
|
|-- devices
|   |-- pci0000:00
|   |   `-- 0000:00:1f.2
|   |       |-- class -> ../../../class/pci
|   |       |-- config
|   |       |-- device
|   |       |-- host0
|   |       |   `-- target0:0:0
|   |       |       |-- 0:0:0:0
|   |       |       |   |-- sda
|   |       |       |   |   |-- dev
|   |       |       |   |   |-- range
|   |       |       |   |   |-- removable
|   |       |       |   |   |-- sda1
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- sda2
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- size
|   |       |       |   |    `-- stat
|   |       |       |   |-- delete
|   |       |       |   |-- device_blocked
|   |       |       |   |-- model
|   |       |       |   |-- type
|   |       |       |   `-- vendor
|   |       |       `-- power
|   |       |           `-- state
|   |       |-- modalias
|   |       |-- resource
|   |       |-- subsystem_device
|   |       |-- subsystem_vendor
|   |       `-- vendor
|   |-- platform
|   |   `-- i8042
|   |       |-- class -> ../../../class/platform
|   |       `-- serio0
|   |           |-- event0
|   |           |   `-- dev
|   |           |-- mouse0
|   |           |   `-- dev
|   |           |-- bind_mode
|   |           |-- class-> ../../../../class/serio
|   |           |-- description
|   |           |-- id
|   |           |   |-- extra
|   |           |   |-- id
|   |           |   |-- proto
|   |           |   `-- type
|   |           |-- modalias
|   |           |-- protocol
|   |           |-- rate
|   |           |-- resetafter
|   |           `-- resolution
|   |-- mice
|   |   `-- dev

...

Thanks,
Kay

maintainer
#14 lore raw
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Hi,

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes. I recenty got an e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

--
Dmitry

#15 lore raw

Am Do 13.10.2005 23:35 schrieb Dmitry Torokhov
<[email protected]>:

Quoted 2 lines · Kay Sievers
Quoted 1 line

[ ... ]

Quoted 6 lines
Quoted 6 lines

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

[ ... ]

Quoted 9 lines
Quoted 1 line

Hi,

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

Do not forget another side effect: we only have 'devices' within a tree under /sys/devices.
/sys/class is just a mapping with no real devices in them, only
symlinks.
So _everything_ can be found under /sys/devices, and you don't have to figure out whether this device your looking for is a class device or a proper device or whatever.

So we really have unified view for all devices, may they be physical or logical devices.

Quoted 10 lines

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes. I recenty got an e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

But you can! That was the whole idea behind it.
Every device ends up in /sys/devices, and the class is just a 'view' on those devices.
(You might even call it API if you feel so inclined). /sys/class/net/interfaces would be implemented just as a collection of symlinks onto the proper devices in /sys/devices.

Overall this approach would make so many tasks so much simpler. We could figure out the dependencies on a given device by just following up the path; no need for the 'PHYSDEVPATH' stuff we have now for the events. Plus we could model weird things like the SCSI subsystem onto sysfs without having to resort to dirty tricks like we do now. Hell, we maybe can even map the OpenPROM device tree onto sysfs for all I know.

So it definitely looks far superior to what we have now.

Cheers,

Hannes

#16 lore raw
In reply to Dmitry Torokhov
Quoted 32 lines · Dmitry Torokhov
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Quoted 8 lines

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes.

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

Quoted 7 lines

I recenty got an
e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

It invents artificial subclass names below a "master" class, which is absolutely not needed.

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs!
We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree!
That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

Thanks,
Kay

#17 lore raw
Quoted 81 lines · Kay Sievers
Quoted 32 lines · Dmitry Torokhov
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Quoted 8 lines

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes.

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

Quoted 7 lines

I recenty got an
e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

It invents artificial subclass names below a "master" class, which is absolutely not needed.

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs!
We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

Quoted 6 lines

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree!
That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

Sorry, my previous drawing wasn't correct for the input devices.

Here is a new picture of the:
- all classes are unique and flat and will stay the same, even when the hierarchy of the devices changes
- all hierarchy is _only_ in /sys/devices
- virtual and physical devices are both in /sys/devices
proposal.

/sys

|-- class
|   |-- block
|   |   `-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda
|   |-- block_partition
|   |   |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda1
|   |   `-- sda2 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda2
|   |-- pci
|   |   `-- 0000:00:1f.2 -> ../../devices/pci0000:00/0000:00:1f.2
|   |-- input
|   |   |-- mice -> ../../devices/mice
|   |   |-- mouse0 -> ../../devices/platform/i8042/serio0/input0/mouse0
|   |   `-- event0 -> ../../devices/platform/i8042/serio0/input0/event0
|   |-- input_device
|   |   `-- input0 -> ../../devices/platform/i8042/serio0/input0
|   `-- tty
|       `-- console -> ../../devices/console
|
|
|-- devices
|   |-- pci0000:00
|   |   `-- 0000:00:1f.2
|   |       |-- class -> ../../../class/pci
|   |       |-- config
|   |       |-- device
|   |       |-- host0
|   |       |   `-- target0:0:0
|   |       |       |-- 0:0:0:0
|   |       |       |   |-- sda
|   |       |       |   |   |-- dev
|   |       |       |   |   |-- range
|   |       |       |   |   |-- removable
|   |       |       |   |   |-- sda1
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- sda2
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- size
|   |       |       |   |    `-- stat
|   |       |       |   |-- model
|   |       |       |   |-- type
|   |       |       |   `-- vendor
|   |       |       `-- power
|   |       |           `-- state
|   |       |-- modalias
|   |       |-- resource
|   |       |-- subsystem_device
|   |       |-- subsystem_vendor
|   |       `-- vendor
|   |-- platform
|   |   `-- i8042
|   |       `-- serio0
|   |            `-- input0
|   |                 |-- event0
|   |                 |   `-- dev
|   |                 |-- mouse0
|   |                 |   `-- dev
|   |                 |-- bind_mode
|   |                 |-- description
|   |                 |-- id
|   |                 |   |-- extra
|   |                 |   |-- id
|   |                 |   |-- proto
|   |                 |   `-- type
|   |                 |-- modalias
|   |                 |-- protocol
|   |                 |-- rate
|   |                 |-- resetafter
|   |                 `-- resolution
|   |-- mice
|   |   `-- dev

...

Thanks,
Kay

#18 lore raw
Quoted 174 lines · Kay Sievers
Quoted 81 lines · Kay Sievers
Quoted 32 lines · Dmitry Torokhov
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Quoted 8 lines

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes.

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

Quoted 7 lines

I recenty got an
e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

It invents artificial subclass names below a "master" class, which is absolutely not needed.

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs!
We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

Quoted 6 lines

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree!
That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

Sorry, my previous drawing wasn't correct for the input devices.

Here is a new picture of the:
- all classes are unique and flat and will stay the same, even when the hierarchy of the devices changes
- all hierarchy is _only_ in /sys/devices
- virtual and physical devices are both in /sys/devices
proposal.

/sys

|-- class
|   |-- block
|   |   `-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda
|   |-- block_partition
|   |   |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda1
|   |   `-- sda2 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda2
|   |-- pci
|   |   `-- 0000:00:1f.2 -> ../../devices/pci0000:00/0000:00:1f.2
|   |-- input
|   |   |-- mice -> ../../devices/mice
|   |   |-- mouse0 -> ../../devices/platform/i8042/serio0/input0/mouse0
|   |   `-- event0 -> ../../devices/platform/i8042/serio0/input0/event0
|   |-- input_device
|   |   `-- input0 -> ../../devices/platform/i8042/serio0/input0
|   `-- tty
|       `-- console -> ../../devices/console
|
|
|-- devices
|   |-- pci0000:00
|   |   `-- 0000:00:1f.2
|   |       |-- class -> ../../../class/pci
|   |       |-- config
|   |       |-- device
|   |       |-- host0
|   |       |   `-- target0:0:0
|   |       |       |-- 0:0:0:0
|   |       |       |   |-- sda
|   |       |       |   |   |-- dev
|   |       |       |   |   |-- range
|   |       |       |   |   |-- removable
|   |       |       |   |   |-- sda1
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- sda2
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- size
|   |       |       |   |    `-- stat
|   |       |       |   |-- model
|   |       |       |   |-- type
|   |       |       |   `-- vendor
|   |       |       `-- power
|   |       |           `-- state
|   |       |-- modalias
|   |       |-- resource
|   |       |-- subsystem_device
|   |       |-- subsystem_vendor
|   |       `-- vendor
|   |-- platform
|   |   `-- i8042
|   |       `-- serio0
|   |            `-- input0
|   |                 |-- event0
|   |                 |   `-- dev
|   |                 |-- mouse0
|   |                 |   `-- dev
|   |                 |-- bind_mode
|   |                 |-- description
|   |                 |-- id
|   |                 |   |-- extra
|   |                 |   |-- id
|   |                 |   |-- proto
|   |                 |   `-- type
|   |                 |-- modalias
|   |                 |-- protocol
|   |                 |-- rate
|   |                 |-- resetafter
|   |                 `-- resolution
|   |-- mice
|   |   `-- dev
Quoted 4 lines

...

Thanks,
Kay

I have a great deal of bad experience attempting to perform emergency mounts on Sun Workstations that have this same general scheme of un-typable:

../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda1

People need to enter this stuff without the help of cut-and-pase or even a back-space that works. Are you trying to replace "/dev/sda1" with the monster above? If so, you have way too much time on your hands.

Of course if this is just some more stuff to be bloated into the kernel and you don't even intend to use it, I shouldn't be concerned, should I? Just keep that stuff away from "/dev". We need to retain a sane interface.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.13.4 on an i686 machine (5589.56 BogoMips). Warning : 98.36% of all statistics are fiction.
.

****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

#19 lore raw
Quoted 186 lines · linux-os (Dick Johnson)
Quoted 174 lines · Kay Sievers
Quoted 81 lines · Kay Sievers
Quoted 32 lines · Dmitry Torokhov
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Quoted 8 lines

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes.

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

Quoted 7 lines

I recenty got an
e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

It invents artificial subclass names below a "master" class, which is absolutely not needed.

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs!
We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

Quoted 6 lines

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree!
That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

Sorry, my previous drawing wasn't correct for the input devices.

Here is a new picture of the:
- all classes are unique and flat and will stay the same, even when the hierarchy of the devices changes
- all hierarchy is _only_ in /sys/devices
- virtual and physical devices are both in /sys/devices
proposal.

/sys

|-- class
|   |-- block
|   |   `-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda
|   |-- block_partition
|   |   |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda1
|   |   `-- sda2 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda2
|   |-- pci
|   |   `-- 0000:00:1f.2 -> ../../devices/pci0000:00/0000:00:1f.2
|   |-- input
|   |   |-- mice -> ../../devices/mice
|   |   |-- mouse0 -> ../../devices/platform/i8042/serio0/input0/mouse0
|   |   `-- event0 -> ../../devices/platform/i8042/serio0/input0/event0
|   |-- input_device
|   |   `-- input0 -> ../../devices/platform/i8042/serio0/input0
|   `-- tty
|       `-- console -> ../../devices/console
|
|
|-- devices
|   |-- pci0000:00
|   |   `-- 0000:00:1f.2
|   |       |-- class -> ../../../class/pci
|   |       |-- config
|   |       |-- device
|   |       |-- host0
|   |       |   `-- target0:0:0
|   |       |       |-- 0:0:0:0
|   |       |       |   |-- sda
|   |       |       |   |   |-- dev
|   |       |       |   |   |-- range
|   |       |       |   |   |-- removable
|   |       |       |   |   |-- sda1
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- sda2
|   |       |       |   |   |   |-- dev
|   |       |       |   |   |   |-- size
|   |       |       |   |   |   |-- start
|   |       |       |   |   |   `-- stat
|   |       |       |   |   |-- size
|   |       |       |   |    `-- stat
|   |       |       |   |-- model
|   |       |       |   |-- type
|   |       |       |   `-- vendor
|   |       |       `-- power
|   |       |           `-- state
|   |       |-- modalias
|   |       |-- resource
|   |       |-- subsystem_device
|   |       |-- subsystem_vendor
|   |       `-- vendor
|   |-- platform
|   |   `-- i8042
|   |       `-- serio0
|   |            `-- input0
|   |                 |-- event0
|   |                 |   `-- dev
|   |                 |-- mouse0
|   |                 |   `-- dev
|   |                 |-- bind_mode
|   |                 |-- description
|   |                 |-- id
|   |                 |   |-- extra
|   |                 |   |-- id
|   |                 |   |-- proto
|   |                 |   `-- type
|   |                 |-- modalias
|   |                 |-- protocol
|   |                 |-- rate
|   |                 |-- resetafter
|   |                 `-- resolution
|   |-- mice
|   |   `-- dev
Quoted 4 lines

...

Thanks,
Kay

I have a great deal of bad experience attempting to perform emergency mounts on Sun Workstations that have this same general scheme of un-typable:

Quoted 6 lines

../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda1

People need to enter this stuff without the help of cut-and-pase or even a back-space that works. Are you trying to replace "/dev/sda1" with the monster above? If so, you have way too much time on your hands.

Welcome to Linux!
Sysfs was never and will not be involved with mounting or device nodes!

Kay

#20 lore raw
In reply to Kay Sievers
Quoted 8 lines · Kay Sievers

Sorry, my previous drawing wasn't correct for the input devices.

Here is a new picture of the:
- all classes are unique and flat and will stay the same, even when the hierarchy of the devices changes
- all hierarchy is _only_ in /sys/devices
- virtual and physical devices are both in /sys/devices
proposal.

I like the layout.

I'm not completely sure whether mouse0 and event0 are the same class, because they have different APIs and protocols. And I believe that class is exactly that - a collection of devices where you can use the same API to access them. A possibility would be to do it like this:

Quoted 11 lines

/sys

|-- class
|   |-- mouse
|   |   |-- mice -> ../../devices/mice
|   |   |-- mouse0 -> ../../devices/platform/i8042/serio0/input0/mouse0
|   |---event
|   |   `-- event0 -> ../../devices/platform/i8042/serio0/input0/event0
|   |-- input
|   |   `-- input0 -> ../../devices/platform/i8042/serio0/input0
|   `-- tty
|       `-- console -> ../../devices/console

It might be too much work to create a new class in each of the handlers, it'd be similar to harddrives and partititions having different classes.

Quoted 24 lines

/sys

|-- class
|   |-- input
|   |   |-- mice -> ../../devices/mice
|   |   |-- mouse0 -> ../../devices/platform/i8042/serio0/input0/mouse0
|   |   `-- event0 -> ../../devices/platform/i8042/serio0/input0/event0
|   |-- input_device
|   |   `-- input0 -> ../../devices/platform/i8042/serio0/input0
|
|-- devices
|   |-- platform
|   |   `-- i8042
|   |       `-- serio0
|   |            `-- input0
|   |                 |-- event0
|   |                 |   `-- dev
|   |                 |-- mouse0
|   |                 |   `-- dev
|   |                 |-- bind_mode
|   |                 |-- description
|   |                 |-- id
|   |                 |   |-- extra
|   |                 |   |-- id
|   |                 |   |-- proto
Quoted 8 lines
|   |                 |   `-- type
|   |                 |-- modalias
|   |                 |-- protocol
|   |                 |-- rate
|   |                 |-- resetafter
|   |                 `-- resolution
|   |-- mice
|   |   `-- dev

Having 'mice' at top level is not very nice. It's a logical consequence of the system, and as such probably correct, though.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#21 lore raw
Quoted 30 lines · Vojtech Pavlik
Quoted 8 lines · Kay Sievers

Sorry, my previous drawing wasn't correct for the input devices.

Here is a new picture of the:
- all classes are unique and flat and will stay the same, even when the hierarchy of the devices changes
- all hierarchy is _only_ in /sys/devices
- virtual and physical devices are both in /sys/devices
proposal.

I like the layout.

I'm not completely sure whether mouse0 and event0 are the same class, because they have different APIs and protocols. And I believe that class is exactly that - a collection of devices where you can use the same API to access them. A possibility would be to do it like this:

Quoted 11 lines

/sys

|-- class
|   |-- mouse
|   |   |-- mice -> ../../devices/mice
|   |   |-- mouse0 -> ../../devices/platform/i8042/serio0/input0/mouse0
|   |---event
|   |   `-- event0 -> ../../devices/platform/i8042/serio0/input0/event0
|   |-- input
|   |   `-- input0 -> ../../devices/platform/i8042/serio0/input0
|   `-- tty
|       `-- console -> ../../devices/console
Quoted 4 lines

It might be too much work to create a new class in each of the handlers, it'd be similar to harddrives and partititions having different classes.

This illustrates the problem I have with flat classification: "event" is way too generic name and "input_event", "input_mouse", etc. is way too ugly. "input/event", "input/mouse" is much better IMO.

Signature · 1 line
Dmitry
maintainer
#22 lore raw
In reply to Kay Sievers
Quoted 54 lines · Kay Sievers
Quoted 32 lines · Dmitry Torokhov
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Quoted 8 lines

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes.

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

Quoted 7 lines

I recenty got an
e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

Quoted 4 lines

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

Does anyone know how many of these we have? We are moving /sys/block to /sys/class so many of these will require upgrades anyway. Could libsysfs hide some of the changes? I have not looked at libsysfs at all though...

Btw, is your proposal with moving it all into /sys/device less drastic?

Quoted 3 lines

It invents artificial subclass names below a "master" class, which is absolutely not needed.

I really do not see why you think that "ieee1394_node" and "ieee1394_transport" are natural names while "ieee1394/node" and "ieee1394/transport" are "artificial".

Quoted 3 lines

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

Why is "interfaces" is more magic than "wireless"? Is it just the name that is confusing? We could call it "netifs", "netdevs", "devices" - just pick a name you like better.

Quoted 9 lines

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

Well, it is rather simple I think - if it works with hardware and needs power management then it's a physical device. If it just a kernel abstraction/API for group of similar objects then it is a class device. Physical device can only have one driver, class device can have several interfaces/views. So far we have input interfaces and SCSI generic interface.

Quoted 3 lines

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs!

Could you tell me which ones you consider virtual buses?

Quoted 5 lines

We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

Quoted 7 lines

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree!
That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

Having hierarchy in the /sys/devices is nice and I think I agree with it. I don't think it will reslve any confusion for the coder WRT physical/virtual devices - after all I think you just need to change class_device kset from class's to devices and that will "move" the object into the new spot in /sys tree.

However having class hierarchy spelled out is also nice because it _does exist_. Right now we just encode it with common prefixes in the class names.

--
Dmitry

#23 lore raw
Quoted 55 lines · Dmitry Torokhov
Quoted 54 lines · Kay Sievers
Quoted 32 lines · Dmitry Torokhov
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Quoted 8 lines

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes.

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

Quoted 7 lines

I recenty got an
e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

Quoted 6 lines
Quoted 4 lines

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

Does anyone know how many of these we have?

A lot! From general distro specific system-management to subsystem specific setup tools and tons of udev rules... There is definitely no chance to break /sys/class in _all_ subsystems by introducing subdirectories.

Quoted 2 lines

We are moving /sys/block
to /sys/class so many of these will require upgrades anyway.

If needed, there can be a link from /sys/block to /sys/class/block and it will look exactly like is is today.

Quoted 1 line

Could libsysfs hide some of the changes?

Not without hardcoding susbsystem-specific knowledge/translation into it, which will not happen and will be definitely the wrong way to solve such a thing. Only the block-move case could be easily covered by libsysfs as it is already prepared to do this and "block" is a "class" from the first version of libsysfs on.

Quoted 1 line

Btw, is your proposal with moving it all into /sys/device less drastic?

Definitely, cause it keeps all the curent api! The only difference is that class-devices are reached by symlinks instead of real directories. The pathes to the devices are the same!

Quoted 7 lines
Quoted 3 lines

It invents artificial subclass names below a "master" class, which is absolutely not needed.

I really do not see why you think that "ieee1394_node" and "ieee1394_transport" are natural names while "ieee1394/node" and "ieee1394/transport" are "artificial".

Well, all three classes are different kind of devices. All devices are at the same level, which I absolutely like. You propose an artificial "hierarchy of classes" or a "superclass", which will break everything and give us no advantage, I think.

Quoted 7 lines
Quoted 3 lines

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

Why is "interfaces" is more magic than "wireless"? Is it just the name that is confusing? We could call it "netifs", "netdevs", "devices" - just pick a name you like better.

Cause "interfaces" is a classification by itself and this is wrong! If you give one of your "subclass devices" an interface, let's say "input0" will get a device node to talk to the low-level device, where do you want to stick it then? You will move the device around to the "interface" directory? That breaks the api!

Take a step back and look what a kernel interface is about. It is to give userland a unified view to devices. The internal kernel structure like "bus", "class", "bus_device", "class_device" are in no way interesting for userspace. It's a kernel implementation detail.

All we want are DEVICES! And from devices we want:
- a classification: /sys/class/<name>
- the properties: attribute files to read values or to invoke actions
- the dependency tree: /sys/devices/<device1>/<device2>
Any mix between any of the three things is completely wrong, makes it hard to read and can never provide a stable device interface.

In HAL, which is the heaviest user of sysfs today, we need to reconstruct the device tree by following the "device" symlink from sysfs to get a unified tree and use the class name to classify the device properly.
In udevd I need to read PHYSDEVPATH to ensure the right event order. All that is needed cause the _internal_ kernel structure is exported, which is "broken" in the sense of a unified device interface.
Both proposals, the subclasses and also the stacked class-devices will render it even more "broken" by mixing classification and device pathes.

Quoted 5 lines
Quoted 5 lines

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

Quoted 7 lines
Quoted 4 lines

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

Well, it is rather simple I think - if it works with hardware and needs power management then it's a physical device.

Forget power management and /sys/devices. The PM guys say, that they will need their own tree for this. Anyway, sticking virtual devices in the tree, but keep the hierarchy is not a reason not to be able to walk up the chain and change device state (We already have a lot non-hardware devices in /sys/devices). You will get the type of device by looking which class it belongs to.

The distinction between "virtual" and "physical" does not make any sense for userspace! And it will get more complicated every year with every new virtualization or abstract subsystem.

Quoted 5 lines

If it just a
kernel abstraction/API for group of similar objects then it is a class device. Physical device can only have one driver, class device can have several interfaces/views. So far we have input interfaces and SCSI generic interface.

That is a kernel implementation detail, we really don't care from userspace. Rememer, sysfs is a _userspace_ interface!

Quoted 5 lines
Quoted 3 lines

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs!

Could you tell me which ones you consider virtual buses?

acpi-bus, serial-bus, scsi-target-bus, platform-bus, ... SUSE had an input-bus, ... These all exist cause of the stupid "virtual" - "physical" distinction. XEN has it's own xen-bus, and absolutely _no_ physical hardware is involved...

Quoted 13 lines
Quoted 5 lines

We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

Quoted 7 lines

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree!
That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

Quoted 5 lines

Having hierarchy in the /sys/devices is nice and I think I agree with it. I don't think it will reslve any confusion for the coder WRT physical/virtual devices - after all I think you just need to change class_device kset from class's to devices and that will "move" the object into the new spot in /sys tree.

What we really need is to keep "hierarchy" and "classification" separated. /sys/class is our usual interface to the kernel devices and we don't want to stick hierarchy here. All hierarchy belongs into a single place with all parent-less devices in the root. That way we can move devices around in the hierarchy if we need to change kernel device handling. But the most important reason: it will always keep the class interface to the devices stable!

Think of sticking an "abstraction device" into a subsystem, like "input0" is, only with a flat class interface you can do this without breaking the users interface. (It already happened several times with scsi.)

Quoted 3 lines

However having class hierarchy spelled out is also nice because it _does exist_. Right now we just encode it with common prefixes in the class names.

That is "grouping", it does not expose any hierarchy. And again, creating tons of sysmlinks between class-devices like in your input proposal, is wrong I think.

Thanks,
Kay

#24 lore raw
Quoted 8 lines · Kay Sievers
Quoted 2 lines · Dmitry Torokhov

Does anyone know how many of these we have?

A lot! From general distro specific system-management to subsystem specific setup tools and tons of udev rules... There is definitely no chance to break /sys/class in _all_ subsystems by introducing subdirectories.

Quoted 6 lines
Quoted 2 lines

We are moving /sys/block
to /sys/class so many of these will require upgrades anyway.

If needed, there can be a link from /sys/block to /sys/class/block and it will look exactly like is is today.

We could also add links in the form of:

	/sys/class/<subsystem>/<nested_class> ->
			/sys/class/<subsystem>_<nested_class>

to keep compatibility with nested classes too to give userspace a chance to catch up...

Quoted 8 lines
Quoted 1 line

Could libsysfs hide some of the changes?

Not without hardcoding susbsystem-specific knowledge/translation into it, which will not happen and will be definitely the wrong way to solve such a thing. Only the block-move case could be easily covered by libsysfs as it is already prepared to do this and "block" is a "class" from the first version of libsysfs on.

OK..

Quoted 6 lines
Quoted 1 line

Btw, is your proposal with moving it all into /sys/device less drastic?

Definitely, cause it keeps all the curent api! The only difference is that class-devices are reached by symlinks instead of real directories. The pathes to the devices are the same!

OK..

Quoted 4 lines
Quoted 4 lines
Quoted 3 lines

It invents artificial subclass names below a "master" class, which is absolutely not needed.

Quoted 9 lines
Quoted 3 lines

I really do not see why you think that "ieee1394_node" and "ieee1394_transport" are natural names while "ieee1394/node" and "ieee1394/transport" are "artificial".

Well, all three classes are different kind of devices. All devices are at the same level, which I absolutely like. You propose an artificial "hierarchy of classes" or a "superclass", which will break everything and give us no advantage, I think.

Call it "subsystem" actually.

Quoted 8 lines
Quoted 7 lines
Quoted 3 lines

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

Why is "interfaces" is more magic than "wireless"? Is it just the name that is confusing? We could call it "netifs", "netdevs", "devices" - just pick a name you like better.

Quoted 6 lines

Cause "interfaces" is a classification by itself and this is wrong! If you give one of your "subclass devices" an interface, let's say "input0" will get a device node to talk to the low-level device, where do you want to stick it then? You will move the device around to the "interface" directory? That breaks the api!

No, not at all. The input0 will get a new interface, blahdevX, exactly like eventX, mouseX, jsX, tsX, etc. and it will go into "interfaces". input0 itself will stay in /sys/class/input/devices.

Quoted 5 lines

Take a step back and look what a kernel interface is about. It is to give userland a unified view to devices. The internal kernel structure like "bus", "class", "bus_device", "class_device" are in no way interesting for userspace. It's a kernel implementation detail.

Quoted 7 lines

All we want are DEVICES! And from devices we want:
- a classification: /sys/class/<name>
- the properties: attribute files to read values or to invoke actions
- the dependency tree: /sys/devices/<device1>/<device2>
Any mix between any of the three things is completely wrong, makes it hard to read and can never provide a stable device interface.

Yes, I agree that we should have device tree in /sys/devices. But I do not think that flat classification is sufficient. Right now it is not enough and we compensate for it with names.

Signature · 1 line
Dmitry
author
#25 lore raw
In reply to Kay Sievers
Quoted 3 lines · Kay Sievers

A lot! From general distro specific system-management to subsystem specific setup tools and tons of udev rules... There is definitely no chance to break /sys/class in _all_ subsystems by introducing subdirectories.

I agree.

Quoted 5 lines
Quoted 1 line

Btw, is your proposal with moving it all into /sys/device less drastic?

Definitely, cause it keeps all the curent api! The only difference is that class-devices are reached by symlinks instead of real directories. The pathes to the devices are the same!

Ok, I've spent a while thinking about this proposal and originally I thought it was the same thing we had heard years ago. But I was wrong, moving the class stuff into the device tree is the right thing to do, as long as we keep them as new "things" in the tree (previous proposals just had the /sys/class stuff as symlinks pointing to the devices themselves, which would not work for a range of reasons.)

So, what to do now? Here's my proposal for the future.

We figure out some way to agree on the input stuff, using class_device and get that into 2.6.15. Personally, I like the stuff I just did and is in the -mm tree :)

But, if you think we can't break userspace by adding nested class devices just yet, I agree, and can probably just put a symlink in /sys/class/input to the nested devices, which will make everything "just work". I'll try that out later tonight and let you all know how it goes.

Then, we move the class stuff into real devices. There was always a lot of duplication with the class and device code, and this shows that there is a commonality there. At the same time, I'll work on making the attribute stuff easier and possibly merge the kobject and device structures together a bit (possibly I said, I don't know quite how much yet...)

But this second step is going to take a while, have to not break everything along the way, and should hopefully clean up a lot of mess tht the current driver core has. I'd be glad to do it :)

Acceptable to everyone?

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

thanks,

greg k-h

p.s. Kay, that's the last time I mention to you that I didn't know what I would be working on for the next few months...

maintainer
#26 lore raw
Quoted 6 lines · Greg KH

So, what to do now? Here's my proposal for the future.

We figure out some way to agree on the input stuff, using class_device and get that into 2.6.15. Personally, I like the stuff I just did and is in the -mm tree :)

If we are shooting at 2.6.15 I would just go with original 2-class solution (input and input_dev) with doing symlinks in form of /sys/class/input/mouseX/device -> /sys/class/input_dev/inputX

Correct me if I am wrong but this is least invasive and (at least for older hotplug installations) all that is needed to make it work is a symlink from input.agent to input_dev.agent.

--
Dmitry

#27 lore raw
Quoted 12 lines · Dmitry Torokhov
Quoted 6 lines · Greg KH

So, what to do now? Here's my proposal for the future.

We figure out some way to agree on the input stuff, using class_device and get that into 2.6.15. Personally, I like the stuff I just did and is in the -mm tree :)

If we are shooting at 2.6.15 I would just go with original 2-class solution (input and input_dev) with doing symlinks in form of /sys/class/input/mouseX/device -> /sys/class/input_dev/inputX

Quoted 6 lines

Correct me if I am wrong but this is least invasive and (at least for older hotplug installations) all that is needed to make it work is a symlink from input.agent to input_dev.agent.

--
Dmitry

I'm not sure if we want to introduce an incorrect change to the sysfs topology only to remove it in the next release. Currently, class devices are not expected to link between one another.

Thanks,
Adam

#28 lore raw
Quoted 9 lines · Adam Belay
Quoted 8 lines · Dmitry Torokhov
Quoted 6 lines · Greg KH

So, what to do now? Here's my proposal for the future.

We figure out some way to agree on the input stuff, using class_device and get that into 2.6.15. Personally, I like the stuff I just did and is in the -mm tree :)

Quoted 7 lines
Quoted 7 lines

If we are shooting at 2.6.15 I would just go with original 2-class solution (input and input_dev) with doing symlinks in form of /sys/class/input/mouseX/device -> /sys/class/input_dev/inputX

Correct me if I am wrong but this is least invasive and (at least for older hotplug installations) all that is needed to make it work is a symlink from input.agent to input_dev.agent.

Yes, it is almost compatible with the "old" hotplug. On modern setups it is just one udev rule to catch the right event. On older setups a simple symlink should work, yes.

Quoted 3 lines

I'm not sure if we want to introduce an incorrect change to the sysfs topology only to remove it in the next release. Currently, class devices are not expected to link between one another.

The easiest would be to leave the "device"-link in its current state:
mouse0 -> ../../../devices/...
and correct that later by getting completely rid of _all_ "device" links with the move of the device object to /sys/devices/ (the DEVPATH for "mouse0" will then contain the _complete_ hierarchy including "input0").

Current userspace is not aware to follow two "device" links. Should not be hard to implement, but seems not really worth the effort, if we plan to rearrange it to a global device tree anyway.

Thanks,
Kay

#29 lore raw
In reply to Greg KH
Quoted 39 lines · Greg KH
Quoted 3 lines · Kay Sievers

A lot! From general distro specific system-management to subsystem specific setup tools and tons of udev rules... There is definitely no chance to break /sys/class in _all_ subsystems by introducing subdirectories.

I agree.

Quoted 5 lines
Quoted 1 line

Btw, is your proposal with moving it all into /sys/device less drastic?

Definitely, cause it keeps all the curent api! The only difference is that class-devices are reached by symlinks instead of real directories. The pathes to the devices are the same!

Ok, I've spent a while thinking about this proposal and originally I thought it was the same thing we had heard years ago. But I was wrong, moving the class stuff into the device tree is the right thing to do, as long as we keep them as new "things" in the tree (previous proposals just had the /sys/class stuff as symlinks pointing to the devices themselves, which would not work for a range of reasons.)

So, what to do now? Here's my proposal for the future.

We figure out some way to agree on the input stuff, using class_device and get that into 2.6.15. Personally, I like the stuff I just did and is in the -mm tree :)

But, if you think we can't break userspace by adding nested class devices just yet, I agree, and can probably just put a symlink in /sys/class/input to the nested devices, which will make everything "just work". I'll try that out later tonight and let you all know how it goes.

Then, we move the class stuff into real devices. There was always a lot of duplication with the class and device code, and this shows that there is a commonality there. At the same time, I'll work on making the attribute stuff easier and possibly merge the kobject and device structures together a bit (possibly I said, I don't know quite how much yet...)

Quoted 5 lines

But this second step is going to take a while, have to not break everything along the way, and should hopefully clean up a lot of mess tht the current driver core has. I'd be glad to do it :)

Acceptable to everyone?

Sounds good to me. The changes to driver model internals may be substantial. For example, because buses and classes will share more code, it's reasonable to allow drivers to bind to any "device" object, even class devices. Of course this would be limited to classes that choose to implement driver matching etc. We are doing this now with the pci express port driver.

It also may make sense to move bus_types to the "class" interface. The layered classes suggestion is especially useful here because we can have a "hardware" or "bus" class that acts as a parent for "pci", "usb", etc.

Also, we could make driver objects a "class" and represent them in the global device tree, giving each driver instance its own unique namespace.

Quoted 5 lines

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

I think we should be trying to kill off the platform bus (it's artifical and doesn't show the real relationships between these devices). Instead, just hang them off the root of the tree. If the device doesn't have any parents or dependencies, then that's logically where it belongs.

Thanks,
Adam

#30 lore raw
Quoted 33 lines · Adam Belay
Quoted 32 lines · Greg KH
Quoted 3 lines · Kay Sievers

A lot! From general distro specific system-management to subsystem specific setup tools and tons of udev rules... There is definitely no chance to break /sys/class in _all_ subsystems by introducing subdirectories.

I agree.

Quoted 5 lines
Quoted 1 line

Btw, is your proposal with moving it all into /sys/device less drastic?

Definitely, cause it keeps all the curent api! The only difference is that class-devices are reached by symlinks instead of real directories. The pathes to the devices are the same!

Ok, I've spent a while thinking about this proposal and originally I thought it was the same thing we had heard years ago. But I was wrong, moving the class stuff into the device tree is the right thing to do, as long as we keep them as new "things" in the tree (previous proposals just had the /sys/class stuff as symlinks pointing to the devices themselves, which would not work for a range of reasons.)

So, what to do now? Here's my proposal for the future.

We figure out some way to agree on the input stuff, using class_device and get that into 2.6.15. Personally, I like the stuff I just did and is in the -mm tree :)

But, if you think we can't break userspace by adding nested class devices just yet, I agree, and can probably just put a symlink in /sys/class/input to the nested devices, which will make everything "just work". I'll try that out later tonight and let you all know how it goes.

Quoted 6 lines
Quoted 6 lines

Then, we move the class stuff into real devices. There was always a lot of duplication with the class and device code, and this shows that there is a commonality there. At the same time, I'll work on making the attribute stuff easier and possibly merge the kobject and device structures together a bit (possibly I said, I don't know quite how much yet...)

Yeah, would be nice if we can share the attribute define/create/grouping stuff over all devices. Currently we have device/class/block attribute management which are all do almost the same.

Quoted 7 lines
Quoted 5 lines

But this second step is going to take a while, have to not break everything along the way, and should hopefully clean up a lot of mess tht the current driver core has. I'd be glad to do it :)

Acceptable to everyone?

Sounds good to me. The changes to driver model internals may be substantial.

Sounds very good to me too. :)
I like to see the "dynamic input" as soon as possible in the tree, as I'm waiting for more than a year now to get rid of the old stuff in udev only kept there for "input". :)

/sys/class/input/ and /sys/class/input_device/ and a matching SUBSYSTEM value would be the easiest for userspace without much breakage involved. That would give us a /sbin/hotplug-fork free driver core and we can start rearranging stuff.

Quoted 5 lines

For example, because buses and classes will share more code, it's reasonable to allow drivers to bind to any "device" object, even class devices. Of course this would be limited to classes that choose to implement driver matching etc. We are doing this now with the pci express port driver.

We should try this, it feels like "buses" can easily become "classes", like the SUBSYSTEM value already looks these days. We'll see...

Quoted 13 lines

It also may make sense to move bus_types to the "class" interface. The layered classes suggestion is especially useful here because we can have a "hardware" or "bus" class that acts as a parent for "pci", "usb", etc.

Also, we could make driver objects a "class" and represent them in the global device tree, giving each driver instance its own unique namespace.

Quoted 5 lines

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

Quoted 4 lines

I think we should be trying to kill off the platform bus (it's artifical and doesn't show the real relationships between these devices). Instead, just hang them off the root of the tree. If the device doesn't have any parents or dependencies, then that's logically where it belongs.

We do the same in HAL every unconnected object just lives in the root of the device tree.

Thanks,
Kay

author
#31 lore raw
In reply to Adam Belay
Quoted 7 lines · Adam Belay

Sounds good to me. The changes to driver model internals may be substantial. For example, because buses and classes will share more code, it's reasonable to allow drivers to bind to any "device" object, even class devices. Of course this would be limited to classes that choose to implement driver matching etc. We are doing this now with the pci express port driver.

That's a bus, not a class device. Drivers bind to devices through a bus. That's why we have busses.

Quoted 3 lines

It also may make sense to move bus_types to the "class" interface. The layered classes suggestion is especially useful here because we can have a "hardware" or "bus" class that acts as a parent for "pci", "usb", etc.

Hm, I don't really know...

Quoted 2 lines

Also, we could make driver objects a "class" and represent them in the global device tree, giving each driver instance its own unique namespace.

Huh? How would you do that? Also, we really don't have different driver "instances", so trying to represent something like that in sysfs would probably be more work than it's worth.

Quoted 8 lines
Quoted 4 lines

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

I think we should be trying to kill off the platform bus (it's artifical and doesn't show the real relationships between these devices). Instead, just hang them off the root of the tree.

Everything that's currently a platform device go to the root? No, that's not going to happen, sorry.

Quoted 2 lines

If the device doesn't have any parents or dependencies, then that's logically where it belongs.

We do have a real platform "bus" that devices hang off of. Where else is that keyboard controller at :)

thanks,

greg k-h

#32 lore raw
Quoted 11 lines · Greg KH
Quoted 7 lines · Adam Belay

Sounds good to me. The changes to driver model internals may be substantial. For example, because buses and classes will share more code, it's reasonable to allow drivers to bind to any "device" object, even class devices. Of course this would be limited to classes that choose to implement driver matching etc. We are doing this now with the pci express port driver.

That's a bus, not a class device. Drivers bind to devices through a bus. That's why we have busses.

If class devices and devices belong in the same tree, then clearly the original distinction is artificial. "struct bus_type" is a class of "struct device". "struct class" is a class of "struct class_dev". We now know of devices in between these two extremes (e.g. pci express port driver). It's also possible that drivers will want to bind to class devices (e.g. a partition driver binding to a block device). Isn't it fair to say that the "bus_type" vs. "class" distinction is also artificial? At the very least they are duplicating some code.

Quoted 7 lines
Quoted 3 lines

Also, we could make driver objects a "class" and represent them in the global device tree, giving each driver instance its own unique namespace.

Huh? How would you do that? Also, we really don't have different driver "instances", so trying to represent something like that in sysfs would probably be more work than it's worth.

(all in same tree)
pci0000:00.00 <- physical device
|
\- e1000:0 <- driver
|
\- eth0 <- class device

We already informally have driver instances. They're pointed to in "driver_data".

Quoted 6 lines
Quoted 6 lines
Quoted 5 lines

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

Quoted 6 lines
Quoted 3 lines

I think we should be trying to kill off the platform bus (it's artifical and doesn't show the real relationships between these devices). Instead, just hang them off the root of the tree.

Everything that's currently a platform device go to the root? No, that's not going to happen, sorry.

Not at all. Rather, everything that's currently a platform device goes to where it actually belongs in the device tree. ACPI (and other firmware) enumerates all of these devices. They're generally children of LPCs and ISA bridges. Making a special exception for these devices is ugly when we can easily represent them like every other device. This will even be possible without ACPI for many of these devices if we create an "ISA" bus driver abstraction.

The main point here is that "platform" is really a hack to represent primitive physical devices that don't fit well into the driver model. There may be better ways of approaching this problem.

Quoted 6 lines
Quoted 3 lines

If the device doesn't have any parents or dependencies, then that's logically where it belongs.

We do have a real platform "bus" that devices hang off of. Where else is that keyboard controller at :)

As stated above, the keyboard actually does have a real location to hang off of. Nonetheless, a keyboard controller is a physical device. It's very different from a "virtual device" like a tty. Therefore, it seems unreasonable to make virtual devices belong to the "platform" bus.

If a device doesn't have a parent device, it belongs at the root of the tree. That's the only obvious way to represent such a lack of dependency. This applies to both class and physical devices.

Thanks,
Adam

#33 lore raw
Quoted 8 lines · Adam Belay

As stated above, the keyboard actually does have a real location to hang off of. Nonetheless, a keyboard controller is a physical device. It's very different from a "virtual device" like a tty. Therefore, it seems unreasonable to make virtual devices belong to the "platform" bus.

If a device doesn't have a parent device, it belongs at the root of the tree. That's the only obvious way to represent such a lack of dependency. This applies to both class and physical devices.

Well, a VT is obviously a child of the graphics card and of the keyboard. Similarly for the 'mice' device, which is a child of all input devices that offer mouseying capabilities.

It's just impossible to express in a tree.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#34 lore raw
In reply to Adam Belay
Quoted 13 lines · Adam Belay
Quoted 11 lines · Greg KH
Quoted 7 lines · Adam Belay

Sounds good to me. The changes to driver model internals may be substantial. For example, because buses and classes will share more code, it's reasonable to allow drivers to bind to any "device" object, even class devices. Of course this would be limited to classes that choose to implement driver matching etc. We are doing this now with the pci express port driver.

That's a bus, not a class device. Drivers bind to devices through a bus. That's why we have busses.

Quoted 8 lines

If class devices and devices belong in the same tree, then clearly the original distinction is artificial. "struct bus_type" is a class of "struct device". "struct class" is a class of "struct class_dev". We now know of devices in between these two extremes (e.g. pci express port driver). It's also possible that drivers will want to bind to class devices (e.g. a partition driver binding to a block device). Isn't it fair to say that the "bus_type" vs. "class" distinction is also artificial? At the very least they are duplicating some code.

I agree and would like to see the "bus" functionality just as set of special methods of a unified device struture also used for class devices.

Quoted 11 lines
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

I think we should be trying to kill off the platform bus (it's artifical and doesn't show the real relationships between these devices). Instead, just hang them off the root of the tree.

Everything that's currently a platform device go to the root? No, that's not going to happen, sorry.

But will sticking stuff like "mice" or "tty" into "platform" will really work? These devices belong to their own primary class like "input" or "tty" and they can not be part of a "bus" at the same time, right?

I'm dreaming of:
- merging "struct device" and "struct class_device"

- provide current "bus" and "class" methodes for _all_ devices

- every current "bus", just becomes a "class" to indicate a group of devices, where "input" has the same "group interface" in /sys/class/ as "pci" - buses go away completely

- every device is a member of one single class, be it a pci-bus-device or a virtual class

- separate strictly between hierarchy and classification, which is a bit ugly sometimes cause of the flat class layout, but it provides a very nice way to keep the class interface simple and therefore stable, while still be able to change the device hierarchy

- /sys/devices becomes a buch of trees and some parent-less devices in the root, its whole reason is just to export the device dependency structure, nothing else

That way the "platform bus" would be a "platform class", which will only contain devices which are not part of any other class. All these parent-less devices would live in the root of /sys/devices to reflect their lack of dependency.
Things like "tty" and "mice", would be members of their natural class, but also live in the root of /sys/devices. That way we have the technically correct classifcation and hierarchy.

Does that make sense?

Thanks,
Kay

maintainer
#35 lore raw
Quoted 38 lines · Kay Sievers
Quoted 13 lines · Adam Belay
Quoted 11 lines · Greg KH
Quoted 7 lines · Adam Belay

Sounds good to me. The changes to driver model internals may be substantial. For example, because buses and classes will share more code, it's reasonable to allow drivers to bind to any "device" object, even class devices. Of course this would be limited to classes that choose to implement driver matching etc. We are doing this now with the pci express port driver.

That's a bus, not a class device. Drivers bind to devices through a bus. That's why we have busses.

Quoted 8 lines

If class devices and devices belong in the same tree, then clearly the original distinction is artificial. "struct bus_type" is a class of "struct device". "struct class" is a class of "struct class_dev". We now know of devices in between these two extremes (e.g. pci express port driver). It's also possible that drivers will want to bind to class devices (e.g. a partition driver binding to a block device). Isn't it fair to say that the "bus_type" vs. "class" distinction is also artificial? At the very least they are duplicating some code.

I agree and would like to see the "bus" functionality just as set of special methods of a unified device struture also used for class devices.

Quoted 11 lines
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

I think we should be trying to kill off the platform bus (it's artifical and doesn't show the real relationships between these devices). Instead, just hang them off the root of the tree.

Everything that's currently a platform device go to the root? No, that's not going to happen, sorry.

Quoted 9 lines

But will sticking stuff like "mice" or "tty" into "platform" will really work? These devices belong to their own primary class like "input" or "tty" and they can not be part of a "bus" at the same time, right?

I'm dreaming of:
- merging "struct device" and "struct class_device"

- provide current "bus" and "class" methodes for _all_ devices

This way you are fattening object interface and I don't think it is a good thing. While we may want to have sysfs representation of all devices be in /sys/devices internally we should keep the interfaces and implementation clean and do not turn it into a kitchen sink.

--
Dmitry

author
#36 lore raw
In reply to Adam Belay
Quoted 10 lines · Adam Belay
Quoted 9 lines · Greg KH
Quoted 7 lines · Adam Belay

Sounds good to me. The changes to driver model internals may be substantial. For example, because buses and classes will share more code, it's reasonable to allow drivers to bind to any "device" object, even class devices. Of course this would be limited to classes that choose to implement driver matching etc. We are doing this now with the pci express port driver.

Quoted 5 lines
Quoted 2 lines

That's a bus, not a class device. Drivers bind to devices through a bus. That's why we have busses.

If class devices and devices belong in the same tree, then clearly the original distinction is artificial. "struct bus_type" is a class of "struct device".

Huh? "struct bus_type" has a list of "struct device" and "struct drivers" that it knows about. I don't understand your use of the word "class" in this sentance. (yeah, it's a horribly overloaded term, sorry...)

Quoted 2 lines

"struct class" is a class of "struct class_dev". We now know of devices in between these two extremes (e.g. pci express port driver).

pci express is just fine, I don't know why you don't like it :)

It's a bus, with different types of devices on it, and different types of drivers that bind to those devices. That's it.

Quoted 2 lines

It's also possible that drivers will want to bind to class devices (e.g. a partition driver binding to a block device).

Almost. Classes like input and video might want to do something like that. But that's something for the future.

Quoted 2 lines

Isn't it fair to say that the "bus_type" vs. "class" distinction is also artificial? At the very least they are duplicating some code.

No, they are very different. busses do some work (matches drivers to devices and other bus specific glue). Classes are just a grouping of a function of a device (input, tty, misc, etc.)

Quoted 14 lines
Quoted 6 lines
Quoted 2 lines

Also, we could make driver objects a "class" and represent them in the global device tree, giving each driver instance its own unique namespace.

Huh? How would you do that? Also, we really don't have different driver "instances", so trying to represent something like that in sysfs would probably be more work than it's worth.

(all in same tree)
pci0000:00.00 <- physical device
|
\- e1000:0 <- driver
|
\- eth0 <- class device

Quoted 2 lines

We already informally have driver instances. They're pointed to in "driver_data".

That's merely a blob of data the driver needs to use. To call that a full blown "instance" is pretty gracious. I think that trying to turn that blob into a sysfs representation would require modifying every driver in the kernel tree in a non-simple manner. That's something that I don't want to undertake at all. But if you can show me otherwise... :)

You are treating the driver in your above tree as a "bridge" between the physical device and the class device. I don't think we really need to show that in our tree, as it's an artificial thing.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 4 lines

Oh, one tiny problem. "virtual devices" are not currently represented in our device tree, but are in the class tree. Things like the different vc and ttys and misc devices are examples of this. I'll just put them on the "platform" bus if no one minds.

I think we should be trying to kill off the platform bus (it's artifical and doesn't show the real relationships between these devices). Instead, just hang them off the root of the tree.

Quoted 7 lines
Quoted 2 lines

Everything that's currently a platform device go to the root? No, that's not going to happen, sorry.

Not at all. Rather, everything that's currently a platform device goes to where it actually belongs in the device tree. ACPI (and other firmware) enumerates all of these devices. They're generally children of LPCs and ISA bridges.

Not on embedded devices. Systems-on-a-chip have no "busses" generally.

Quoted 4 lines

Making a special exception for these devices is ugly when we can easily represent them like every other device. This will even be possible without ACPI for many of these devices if we create an "ISA" bus driver abstraction.

Yes, if you have a ISA and a "system" bus. But then the "platform" bus just goes back to being the system one. And you are where you started...

Quoted 3 lines

The main point here is that "platform" is really a hack to represent primitive physical devices that don't fit well into the driver model. There may be better ways of approaching this problem.

If you have a better approach, I would be glad to see it. And I don't think it's a "hack" as lots of systems only use that bus.

Quoted 10 lines
Quoted 5 lines
Quoted 2 lines

If the device doesn't have any parents or dependencies, then that's logically where it belongs.

We do have a real platform "bus" that devices hang off of. Where else is that keyboard controller at :)

As stated above, the keyboard actually does have a real location to hang off of. Nonetheless, a keyboard controller is a physical device. It's very different from a "virtual device" like a tty. Therefore, it seems unreasonable to make virtual devices belong to the "platform" bus.

Then where should virtual devices belong?

Quoted 3 lines

If a device doesn't have a parent device, it belongs at the root of the tree. That's the only obvious way to represent such a lack of dependency. This applies to both class and physical devices.

You want to put 512 tty class devices in /sys/devices/ ? I don't want to see that.

thanks,

greg k-h

author
#37 lore raw
In reply to Greg KH
Quoted 5 lines · Greg KH

But, if you think we can't break userspace by adding nested class devices just yet, I agree, and can probably just put a symlink in /sys/class/input to the nested devices, which will make everything "just work". I'll try that out later tonight and let you all know how it goes.

Below is a patch that does this for the event portion of input. Good news is that the symlink shows up just fine in sysfs. Bad news is that even with your previously posted patch, udev dies a horrible death.

And udev dies today with the nested stuff too, so that's not good either.

So I could just move the class devices back to the main /sys/input/ directory (instead of the nesting) which will make userspace happy, and then start working on the class -> device stuff.

Or I'll look at udev in the morning to see if it's just an easy fix...

thanks,

greg k-h

drivers/input/evdev.c +6 -1
@@ -661,6 +661,7 @@ static struct file_operations evdev_fops
 static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
 {
 	struct evdev *evdev;
+	struct class_device *cdev;
 	int minor;
 
 	for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
@@ -686,10 +687,13 @@ static struct input_handle *evdev_connec
 
 	evdev_table[minor] = evdev;
 
-	class_device_create(&input_class, &dev->cdev,
+	cdev = class_device_create(&input_class, &dev->cdev,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
 			dev->cdev.dev, "event%d", minor);
 
+	/* temporary symlink to keep userspace happy */
+	sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, evdev->name);
+
 	return &evdev->handle;
 }
 
@@ -698,6 +702,7 @@ static void evdev_disconnect(struct inpu
 	struct evdev *evdev = handle->private;
 	struct evdev_list *list;
 
+	sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
 	class_device_destroy(&input_class,
 			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	evdev->exist = 0;
author
#38 lore raw
Quoted 7 lines · Greg KH
Quoted 5 lines · Greg KH

But, if you think we can't break userspace by adding nested class devices just yet, I agree, and can probably just put a symlink in /sys/class/input to the nested devices, which will make everything "just work". I'll try that out later tonight and let you all know how it goes.

Quoted 6 lines

Below is a patch that does this for the event portion of input. Good news is that the symlink shows up just fine in sysfs. Bad news is that even with your previously posted patch, udev dies a horrible death.

And udev dies today with the nested stuff too, so that's not good either.

Nevermind, that was due to the kernel oops, not udev.

Kay, your original udev patch works just fine. What I don't see is why the existing udev release doesn't also work, now that I have the symlinks set up. I'll try to figure that one out too...

thanks,

greg k-h

author
#39 lore raw
Quoted 12 lines · Greg KH
Quoted 11 lines · Greg KH
Quoted 5 lines · Greg KH

But, if you think we can't break userspace by adding nested class devices just yet, I agree, and can probably just put a symlink in /sys/class/input to the nested devices, which will make everything "just work". I'll try that out later tonight and let you all know how it goes.

Below is a patch that does this for the event portion of input. Good news is that the symlink shows up just fine in sysfs. Bad news is that even with your previously posted patch, udev dies a horrible death.

Quoted 8 lines
Quoted 2 lines

And udev dies today with the nested stuff too, so that's not good either.

Nevermind, that was due to the kernel oops, not udev.

Kay, your original udev patch works just fine. What I don't see is why the existing udev release doesn't also work, now that I have the symlinks set up. I'll try to figure that one out too...

Bleah, here's a one character patch to the current udev that makes udevstart work properly with my symlink patch.

udevstart.c +1 -1
index ce96f38..ce72b82 100644
@@ -131,7 +131,7 @@ static int add_device(const char *devpat
 		setenv("UDEV_RUN", udev_run_str, 1);
 	dbg("add '%s'", devpath);
 
-	snprintf(path, sizeof(path), "%s%s", sysfs_path, devpath);
+	snprintf(path, sizeof(path), "%s%s/", sysfs_path, devpath);
 	path[sizeof(path)-1] = '\0';
 	class_dev = sysfs_open_class_device_path(path);
 	if (class_dev == NULL) {

So, any way we do it, users are going to have to upgrade udev to get things to work properly.

But I guess we should use the symlink patch in the kernel too, just to keep any other tools that don't have this kind of bug in them working properly...

Opinions?

thanks,

greg k-h

#40 lore raw
In reply to Kay Sievers
Quoted 32 lines · Kay Sievers

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

It invents artificial subclass names below a "master" class, which is absolutely not needed.

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs! We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

Quoted 6 lines

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree! That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

Let me just say: I completely agree here. The hard distinction between 'real' and 'virtual' devices causes more problems than it solves.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#41 lore raw
In reply to Kay Sievers

[ Uhh, sorry about the very long delay in responding to this. I was off the continent and unemployed at the time. Both of those problems are solved now. :) ]

Quoted 64 lines · Kay Sievers
Quoted 32 lines · Dmitry Torokhov
Quoted 23 lines · Kay Sievers

The nesting classes implement a fraction of a device hierarchy in /sys/class. It moves arbitrary relation information into the class directory, where nothing else than device classification belongs. What is the rationale behind sticking device trees into class?

Instead of that, I propose a unification of "/sys/devices-devices" and "class-devices". The differentiation of both does not make sense in a wold where we can't really tell if a device is hardware or virtual.

We should model _all_ devices with its actual realationship in /sys/devices and /sys/class should only be a pinter to the actual devices in that place. Device like "mice", which have no parent, would sit at the top level of /sys/devices. All devices in /sys/class are only symlinks and never devices by itself.
That way userspace can read all device relation at _one_ place in a sane way, and we keep the clean class interface to have easy access to all devices of a specific group.
It gives us the right abstraction and is future proof, cause the class interface will not change when the relation between devices changes. The destinction between classes and buses would no longer be needed, and as we see in the "input" case never made sense anyway.

Quoted 7 lines

/sys/class/block would look exactly like /sys/block today. The only difference is that there are symlinks to follow instead of class devices on its own. With every device creation we will get the whole dependency path of the device in the DEVPATH and a "classsification symlink" in /sys/class. The input devices are all clearly modeled in its hierarchy, in /sys/devices but we also get clean class interfaces:

Quoted 8 lines

Kay eased my task by enumerating all issues I have with Greg's approach. Not all the world is udev and not all class devices have "/dev" represetation so haveing one program being able to understand new sysfs hierarchy is not enough IHMO.

However I do not think that "moving" class devices into /sys/devices hierarchy is the right solution either because one physical device could easily end up belonging to several classes.

Sure, than that physical (while that distinction is silly by itself) will just have several child devices. Look at the mouse0 and event0 in the ascii drawing.

Quoted 7 lines

I recenty got an
e-mail from Adam Belay (whom I am pulling into the discussion) regarding his desire to rearrange net/wireless representation. I think it would be quite natural to have /sys/class/net/interfaces and /sys/class/net/wireless /sys/class/net/irda, and /sys/class/net/wired subclasses where "interfaces" would enumerate _all_ network interfaces in the system, and the rest would show only devices of their class.

That solution would keep a better device separation, sure. But it is completely incompatible with everything we ever had in sysfs and nobody wants to rewrite _all_ userspace programs.

It invents artificial subclass names below a "master" class, which is absolutely not needed.

It creates the magic "interfaces" directory, which is confusing, cause it classifies devices by itself.

Quoted 8 lines

It doesn't represent any relationship and hierarchy of devices and adding a forest of magic symlinks and "device" pointers is a very bad design. The proposed "inter-class" symlinks make it even harder to understand sysfs as it already is.

The biggest problem with current sysfs is that the driver hacker has to decide if the device is "hardware" or "virtual" which in a lot of cases just can't tell and this distiction doesn't make any sense today.

Could you provide an example of this? The driver model is currently designed to handle two basic types of objects:

- Physical objects (mapping to struct device) that are discovered by a bus driver's probing/scanning routines.

- Logical objects (mapping to struct class_device) that are created when a driver binds to a device and registers with the device class that the driver belongs to.

Most of that should happen behind the scenes in the bus and class code respectively.

Quoted 3 lines

All the more complex subsystems use "virtual buses" and an unconnected bunch of class-devices to model its sysfs represention, which is just to work around a major design flaw in sysfs!

I wouldn't call this a design flaw. This was just willingness in the implementors of those subsystems to overload the current design features, and unwillingness to add new infrastructure that better represented what they wanted to do. Don't blame the driver model for this; it was more a lack of time and/or understanding of what needed to be done.

Note this is exactly why /sys/block exists, and even why kobjects were created - someone wanted to export things that weren't currently represented, so they overloaded the existing structures, and did so in a fairly nasty way.

Quoted 11 lines

We really should get _one_ device tree with its natural hierarchy, get rid of the stupid "device"-link, the PHYSDEVPATH and the unconnected class devices. Every device should just carry its dependency tree in it _own_ devpath!

I'm very sure, we want a unified tree in /sys/devices, regardless of the type of device, to represent the global hierarchy wich is exactly what you want to know from a device tree!
That way we stack "virtual" _and_ "physical" in a sane manner and at the same time get very clean class interfaces. We would stop to mix up "hierarchy" and "classes" all over the tree.

For what purpose? To make udev easier to program? Or, to make it easier to determine what attributes are located where? Or, to determine what devices map to what class devices? (Really, I'm curious).

Recall tht sysfs is designed to export kernel objects in a natural manner. What we have now is mostly natural. There are some artificial bits to it (the most agregious are things like usb-serial), but the distinction between physical devices and class devices and their relationships with drivers and the buses that they're on is clearly spelled out.

So what if there is a forest of symlinks?

If you want a unified representation of every thing (objects and attrributes) that represent a single piece of hardware (i.e. in a compact, single screen full of text), then that should be done in userspace, IMHO. :)

Thanks,

Pat

#42 lore raw
In reply to Greg KH

NACK. The whole point of classes is to have common attributes and behaviours over a set of devices. There's much more than the dev attribute to them. Please just fix the input code to get their semantics right instead.

maintainer
#43 lore raw
Quoted 5 lines · Christoph Hellwig

NACK. The whole point of classes is to have common attributes and behaviours over a set of devices. There's much more than the dev attribute to them. Please just fix the input code to get their semantics right instead.

What kind of changes would you like to see in the input system? Currently it maps perfectly well on to what we have in sysfs (using pair of input and input_dev classes), it is just that we do not really like the general sysfs structure and would like to improve it.

--
Dmitry