ChangeSet 1.872, 2002/12/12 12:39:31-08:00, [EMAIL PROTECTED]

[PATCH] USB: start to remove static minor based arrays in drivers

Here are minimal usb_find_interface() patches for the core, usblp and
scanner.

Basic design is:
- device major (USB_MAJOR for now) and minor are stored in probe()
   function to struct usb_interface as kdev_t
- open() can use new core function usb_find_interface() to find matching
  device in drivers device list
- disconnect() will set kdev_t struct usb_interface to NODEV, so open
  wont open it anymore without new probe()

I tested these patches and they work for me. I will work on small patches
of other work in these drivers (like removal of lock_kernel/unlock_kernel
in usblp, fixing the disconnect problems in both drivers etc.). Those
patches would be very small too, but there will be quite many.


diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/class/usblp.c Fri Dec 13 17:18:56 2002
@@ -188,8 +188,6 @@
 
 extern devfs_handle_t usb_devfs_handle;                        /* /dev/usb dir. */
 
-static struct usblp *usblp_table[USBLP_MINORS];
-
 /* Quirks: various printer quirks are handled by this table & its flags. */
 
 struct quirk_printer_struct {
@@ -325,17 +323,22 @@
 
 static int usblp_open(struct inode *inode, struct file *file)
 {
-       int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
+       int minor = minor(inode->i_rdev);
        struct usblp *usblp;
+       struct usb_interface *intf;
        int retval;
 
        if (minor < 0 || minor >= USBLP_MINORS)
                return -ENODEV;
 
        lock_kernel();
-       usblp  = usblp_table[minor];
 
        retval = -ENODEV;
+       intf = usb_find_interface(&usblp_driver, mk_kdev(USB_MAJOR,minor));
+       if (!intf) {
+               goto out;
+       }
+       usblp = dev_get_drvdata (&intf->dev);
        if (!usblp || !usblp->dev)
                goto out;
 
@@ -382,7 +385,6 @@
 static void usblp_cleanup (struct usblp *usblp)
 {
        devfs_unregister (usblp->devfs);
-       usblp_table [usblp->minor] = NULL;
        usb_deregister_dev (1, usblp->minor);
        info("usblp%d: removed", usblp->minor);
 
@@ -905,14 +907,11 @@
        usblp_check_status(usblp, 0);
 #endif
 
-       /* add a table entry so the device works when advertised */
-       usblp_table[usblp->minor] = usblp;
-
        /* If we have devfs, create with perms=660. */
        sprintf(name, "lp%d", usblp->minor);
        usblp->devfs = devfs_register(usb_devfs_handle, name,
                                      DEVFS_FL_DEFAULT, USB_MAJOR,
-                                     USBLP_MINOR_BASE + usblp->minor,
+                                     usblp->minor,
                                      S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
                                      S_IWGRP, &usblp_fops, NULL);
 
@@ -925,6 +924,10 @@
                usblp->dev->descriptor.idProduct);
 
        dev_set_drvdata (&intf->dev, usblp);
+
+       /* add device id so the device works when advertised */
+       intf->kdev = mk_kdev(USB_MAJOR,usblp->minor);
+
        return 0;
 
 abort_minor:
@@ -1108,6 +1111,9 @@
 static void usblp_disconnect(struct usb_interface *intf)
 {
        struct usblp *usblp = dev_get_drvdata (&intf->dev);
+
+       /* remove device id to disable open() */
+       intf->kdev = NODEV;
 
        if (!usblp || !usblp->dev) {
                err("bogus disconnect");
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c    Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/core/usb.c    Fri Dec 13 17:18:56 2002
@@ -470,6 +470,40 @@
        return NULL;
 }
 
+/**
+ * usb_find_interface - find usb_interface pointer for driver and device
+ * @drv: the driver whose current configuration is considered
+ * @kdev: the desired device
+ *
+ * This walks the driver device list and returns a pointer to the interface 
+ * with the matching kdev_t.
+ */
+struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev)
+{
+       struct list_head *entry;
+       struct device *dev;
+       struct usb_interface *intf;
+
+       list_for_each(entry, &drv->driver.devices) {
+               dev = container_of(entry, struct device, driver_list);
+
+               /* can't look at usb devices, only interfaces */
+               if (dev->driver == &usb_generic_driver)
+                       continue;
+
+               intf = to_usb_interface(dev);
+               if (!intf)
+                       continue;
+
+               if (kdev_same(intf->kdev,kdev)) {
+                       return intf;
+               }
+       }
+
+       /* no device found that matches */
+       return NULL;    
+}
+
 static int usb_device_match (struct device *dev, struct device_driver *drv)
 {
        struct usb_interface *intf;
@@ -1445,6 +1479,7 @@
 EXPORT_SYMBOL(usb_interface_claimed);
 EXPORT_SYMBOL(usb_driver_release_interface);
 EXPORT_SYMBOL(usb_match_id);
+EXPORT_SYMBOL(usb_find_interface);
 
 EXPORT_SYMBOL(usb_new_device);
 EXPORT_SYMBOL(usb_reset_device);
diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
--- a/drivers/usb/image/scanner.c       Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/image/scanner.c       Fri Dec 13 17:18:56 2002
@@ -398,6 +398,7 @@
 {
        struct scn_usb_data *scn;
        struct usb_device *dev;
+       struct usb_interface *intf;
 
        int scn_minor;
 
@@ -409,13 +410,13 @@
 
        dbg("open_scanner: scn_minor:%d", scn_minor);
 
-       if (!p_scn_table[scn_minor]) {
+       intf = usb_find_interface(&scanner_driver, mk_kdev(USB_MAJOR,scn_minor));
+       if (!intf) {
                up(&scn_mutex);
                err("open_scanner(%d): Unable to access minor data", scn_minor);
                return -ENODEV;
        }
-
-       scn = p_scn_table[scn_minor];
+       scn = dev_get_drvdata (&intf->dev);
 
        dev = scn->scn_dev;
 
@@ -458,7 +459,7 @@
 static int
 close_scanner(struct inode * inode, struct file * file)
 {
-       struct scn_usb_data *scn;
+       struct scn_usb_data *scn = file->private_data;
 
        int scn_minor;
 
@@ -466,15 +467,9 @@
 
        dbg("close_scanner: scn_minor:%d", scn_minor);
 
-       if (!p_scn_table[scn_minor]) {
-               err("close_scanner(%d): invalid scn_minor", scn_minor);
-               return -ENODEV;
-       }
-
        down(&scn_mutex);
-
-       scn = p_scn_table[scn_minor];
        down(&(scn->sem));
+
        scn->isopen = 0;
 
        file->private_data = NULL;
@@ -695,17 +690,12 @@
              unsigned int cmd, unsigned long arg)
 {
        struct usb_device *dev;
-
+       struct scn_usb_data *scn = file->private_data;
        int scn_minor;
 
        scn_minor = USB_SCN_MINOR(inode);
 
-       if (!p_scn_table[scn_minor]) {
-               err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
-               return -ENODEV;
-       }
-
-       dev = p_scn_table[scn_minor]->scn_dev;
+       dev = scn->scn_dev;
 
        switch (cmd)
        {
@@ -987,13 +977,6 @@
                return -ENOMEM;
        }
 
-/* Check to make sure that the last slot isn't already taken */
-       if (p_scn_table[scn_minor]) {
-               err("probe_scanner: No more minor devices remaining.");
-               up(&scn_mutex);
-               return -ENOMEM;
-       }
-
        dbg("probe_scanner: Allocated minor:%d", scn_minor);
 
        if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
@@ -1082,17 +1065,19 @@
        
        scn->devfs = devfs_register(usb_devfs_handle, name,
                                    DEVFS_FL_DEFAULT, USB_MAJOR,
-                                   SCN_BASE_MNR + scn->scn_minor,
+                                   scn->scn_minor,
                                    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
                                    S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, 
NULL);
        if (scn->devfs == NULL)
                dbg("scanner%d: device node registration failed", scn_minor);
 
-       p_scn_table[scn_minor] = scn;
-
        up(&scn_mutex);
 
        dev_set_drvdata(&intf->dev, scn);
+
+       /* add device id so the device works when advertised */
+       intf->kdev = mk_kdev(USB_MAJOR,scn->scn_minor);
+
        return 0;
 }
 
@@ -1101,6 +1086,9 @@
 {
        struct scn_usb_data *scn = dev_get_drvdata(&intf->dev);
 
+       /* remove device id to disable open() */
+       intf->kdev = NODEV;
+
        dev_set_drvdata(&intf->dev, NULL);
        if (scn) {
                down (&scn_mutex);
@@ -1119,7 +1107,6 @@
                dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
                devfs_unregister(scn->devfs);
                usb_deregister_dev(1, scn->scn_minor);
-               p_scn_table[scn->scn_minor] = NULL;
                usb_free_urb(scn->scn_irq);
                up (&(scn->sem));
                kfree (scn);
diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
--- a/drivers/usb/image/scanner.h       Fri Dec 13 17:18:56 2002
+++ b/drivers/usb/image/scanner.h       Fri Dec 13 17:18:56 2002
@@ -216,7 +216,7 @@
 #define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & 
USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
 #define IS_EP_INTR(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
 
-#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
+#define USB_SCN_MINOR(X) minor((X)->i_rdev)
 
 #ifdef DEBUG
 #define SCN_DEBUG(X) X
@@ -273,7 +273,5 @@
 };
 
 extern devfs_handle_t usb_devfs_handle;
-
-static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
 
 static struct usb_driver scanner_driver;
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h       Fri Dec 13 17:18:56 2002
+++ b/include/linux/usb.h       Fri Dec 13 17:18:56 2002
@@ -117,6 +117,7 @@
        unsigned max_altsetting;        /* total memory allocated */
 
        struct usb_driver *driver;      /* driver */
+       kdev_t kdev;                    /* node this interface is bound to */
        struct device dev;              /* interface specific device info */
        void *private_data;
 };
@@ -270,6 +271,8 @@
                        struct usb_interface *iface);
 const struct usb_device_id *usb_match_id(struct usb_interface *interface,
                                         const struct usb_device_id *id);
+
+struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev);
 
 /**
  * usb_make_path - returns stable device path in the usb tree


-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to