ChangeSet 1.1123.18.11, 2003/08/13 13:36:06-07:00, greg@kroah.com [PATCH] USB: fix usb class device sysfs representation. Again, I messed up the usage, now we are safe from devices being removed. This fixes a number of error reports from users. drivers/usb/core/file.c | 49 +++++++++++++++++++++++++++++++----------------- include/linux/usb.h | 3 -- 2 files changed, 33 insertions(+), 19 deletions(-) diff -Nru a/drivers/usb/core/file.c b/drivers/usb/core/file.c --- a/drivers/usb/core/file.c Fri Aug 15 10:46:31 2003 +++ b/drivers/usb/core/file.c Fri Aug 15 10:46:31 2003 @@ -66,8 +66,15 @@ .open = usb_open, }; +static void release_usb_class_dev(struct class_device *class_dev) +{ + dbg("%s - %s", __FUNCTION__, class_dev->class_id); + kfree(class_dev); +} + static struct class usb_class = { - .name = "usb", + .name = "usb", + .release = &release_usb_class_dev, }; int usb_major_init(void) @@ -91,9 +98,8 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf) { - struct usb_interface *intf = class_dev_to_usb_interface(class_dev); - dev_t dev = MKDEV(USB_MAJOR, intf->minor); - return print_dev_t(buf, dev); + int minor = (int)class_get_devdata(class_dev); + return print_dev_t(buf, MKDEV(USB_MAJOR, minor)); } static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); @@ -124,6 +130,7 @@ int minor_base = class_driver->minor_base; int minor = 0; char name[DEVICE_ID_SIZE]; + struct class_device *class_dev; char *temp; #ifdef CONFIG_USB_DYNAMIC_MINORS @@ -163,18 +170,23 @@ devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name); /* create a usb class device for this usb interface */ - memset(&intf->class_dev, 0x00, sizeof(struct class_device)); - intf->class_dev.class = &usb_class; - intf->class_dev.dev = &intf->dev; - - temp = strrchr(name, '/'); - if (temp && (temp[1] != 0x00)) - ++temp; - else - temp = name; - snprintf(intf->class_dev.class_id, BUS_ID_SIZE, "%s", temp); - class_device_register(&intf->class_dev); - class_device_create_file (&intf->class_dev, &class_device_attr_dev); + class_dev = kmalloc(sizeof(*class_dev), GFP_KERNEL); + if (class_dev) { + memset(class_dev, 0x00, sizeof(struct class_device)); + class_dev->class = &usb_class; + class_dev->dev = &intf->dev; + + temp = strrchr(name, '/'); + if (temp && (temp[1] != 0x00)) + ++temp; + else + temp = name; + snprintf(class_dev->class_id, BUS_ID_SIZE, "%s", temp); + class_set_devdata(class_dev, (void *)intf->minor); + class_device_register(class_dev); + class_device_create_file(class_dev, &class_device_attr_dev); + intf->class_dev = class_dev; + } exit: return retval; } @@ -217,7 +229,10 @@ snprintf(name, DEVICE_ID_SIZE, class_driver->name, intf->minor - minor_base); devfs_remove (name); - class_device_unregister(&intf->class_dev); + if (intf->class_dev) { + class_device_unregister(intf->class_dev); + intf->class_dev = NULL; + } intf->minor = -1; } EXPORT_SYMBOL(usb_deregister_dev); diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Fri Aug 15 10:46:31 2003 +++ b/include/linux/usb.h Fri Aug 15 10:46:31 2003 @@ -123,10 +123,9 @@ struct usb_driver *driver; /* driver */ int minor; /* minor number this interface is bound to */ struct device dev; /* interface specific device info */ - struct class_device class_dev; + struct class_device *class_dev; }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) -#define class_dev_to_usb_interface(d) container_of(d, struct usb_interface, class_dev) #define interface_to_usbdev(intf) \ container_of(intf->dev.parent, struct usb_device, dev)