On Sun, 9 Oct 2005 12:47:33 -0400 (EDT), Alan Stern <[EMAIL PROTECTED]> wrote:
> When assigning the flags value in usb-storage, the extra > usb_usual module-type information should be masked out. OK > Apparently ub's probe routine won't accept any devices unless > libusual is configured. That's what you intended, right? > So there's no need for it to have an entry in its usb_ids table. It was a mistake. Fortunately, users of usb-storage were not affected. So, I put the entry back and changed the check. > It doesn't matter where usb_usual_set_present is called in a > modules's init routine. (This is another one of those races > involving request_module.) So I moved the calls to the end, to > avoid calling usb_usual_clear_present when registration fails. > > I converted libusual to use the kthread API. Hmm. The new API looks promising with the explicit starting and stopping. This is a good idea, but I have to revisit it separately. > There's not much extra overhead if you check the bias string > every time a new device is probed. By doing so, libusual can > react to changes made through sysfs. A new routine was added > to handle this: usb_usual_check_type. I think that open-coding the comparison was wrong and usb_usual_check_type is a better way to do it, but it is a wrong time to parse strings and print diagnostics. So I kept the parsing where it was, but also adopted usb_usual_check_type(). The libusual does not change usb_device_id array on the fly anymore. > The call to up(&usu_init_notify) can be moved to the end of the > probe_thread routine. We may as well extend the region of mutual > exclusion over the whole routine, since most of the time a > spinlock is held anyway. No, I do not like that, because I do not want request_module to be covered with any extra locks. That thing does too much, and there may be deadlocks if I do that. Not currently, but I do not like leaving things like this sitting in ambush. It's not a lock really, just a notification done through a semaphore because the stock completion primitive required a precise balance between calls to notify and to test. I think that we should get rid of it by using kthread_start. Please see the attached patch. It goes on top of what I sent yesterday. This way Greg may take it as an update. Otherwise, he may reject both. Then I'll resend a unified libusual for -rc4. -- Pete diff -urp -X dontdiff linux-2.6.14-rc3-wip6/drivers/block/ub.c linux-2.6.14-rc3-lem/drivers/block/ub.c --- linux-2.6.14-rc3-wip6/drivers/block/ub.c 2005-10-09 12:25:18.000000000 -0700 +++ linux-2.6.14-rc3-lem/drivers/block/ub.c 2005-10-09 12:24:34.000000000 -0700 @@ -2168,7 +2168,7 @@ static int ub_probe(struct usb_interface int rc; int i; - if (USB_US_TYPE(dev_id->driver_info) != USB_US_TYPE_UB) + if (usb_usual_check_type(dev_id, USB_US_TYPE_UB)) return -ENXIO; rc = -ENOMEM; @@ -2471,8 +2471,6 @@ static int __init ub_init(void) { int rc; - usb_usual_set_present(USB_US_TYPE_UB); - if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0) goto err_regblkdev; devfs_mk_dir(DEVFS_NAME); @@ -2480,13 +2478,13 @@ static int __init ub_init(void) if ((rc = usb_register(&ub_driver)) != 0) goto err_register; + usb_usual_set_present(USB_US_TYPE_UB); return 0; err_register: devfs_remove(DEVFS_NAME); unregister_blkdev(UB_MAJOR, DRV_NAME); err_regblkdev: - usb_usual_clear_present(USB_US_TYPE_UB); return rc; } diff -urp -X dontdiff linux-2.6.14-rc3-wip6/drivers/usb/storage/libusual.c linux-2.6.14-rc3-lem/drivers/usb/storage/libusual.c --- linux-2.6.14-rc3-wip6/drivers/usb/storage/libusual.c 2005-10-09 12:25:18.000000000 -0700 +++ linux-2.6.14-rc3-lem/drivers/usb/storage/libusual.c 2005-10-09 13:09:40.000000000 -0700 @@ -27,6 +27,7 @@ static DEFINE_SPINLOCK(usu_lock); #define BIAS_NAME_SIZE (sizeof("usb-storage")) static char bias[BIAS_NAME_SIZE]; +static int usb_usual_bias; static const char *bias_names[3] = { "none", "usb-storage", "ub" }; static DECLARE_MUTEX_LOCKED(usu_init_notify); @@ -34,16 +35,11 @@ static DECLARE_COMPLETION(usu_end_notify static atomic_t total_threads = ATOMIC_INIT(0); static int usu_probe_thread(void *arg); -static void bias_storage_ids(int to_bias); static int parse_bias(const char *bias_s); /* - * The UNUSUAL_DEV_FL is a version of UNUSUAL_DEV for "flags-only" - * devices which only need an entry in usb_device_id array. - * It keeps arguments for vendor and product names because - * they are valuable comments, even though they are not used by the code. + * The table. */ - #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ vendorName, productName,useProtocol, useTransport, \ initFunction, flags) \ @@ -97,16 +93,38 @@ void usb_usual_clear_present(int type) EXPORT_SYMBOL(usb_usual_clear_present); /* + * Match the calling driver type against the table. + * Returns: 0 if the device matches. + */ +int usb_usual_check_type(const struct usb_device_id *id, int caller_type) +{ + int id_type = USB_US_TYPE(id->driver_info); + + if (caller_type <= 0 || caller_type >= 3) + return -EINVAL; + + /* Drivers grab fixed assignment devices */ + if (id_type == caller_type) + return 0; + /* Drivers grab devices biased to them */ + if (id_type == USB_US_TYPE_NONE && caller_type == usb_usual_bias) + return 0; + return -ENODEV; +} +EXPORT_SYMBOL(usb_usual_check_type); + +/* */ static int usu_probe(struct usb_interface *intf, const struct usb_device_id *id) { - int type = USB_US_TYPE(id->driver_info); + int type; int rc; unsigned long flags; + type = USB_US_TYPE(id->driver_info); if (type == 0) - return -ENXIO; + type = usb_usual_bias; spin_lock_irqsave(&usu_lock, flags); if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) { @@ -178,42 +196,22 @@ static int usu_probe_thread(void *arg) } st->fls &= ~USU_MOD_FL_THREAD; spin_unlock_irqrestore(&usu_lock, flags); - complete_and_exit(&usu_end_notify, 0); -} - -/* - */ -static void bias_storage_ids(int to_bias) -{ - struct usb_device_id *id; - for (id = storage_usb_ids; - id->idVendor || id->bDeviceClass || id->bInterfaceClass || - id->driver_info; - id++) { - if (USB_US_TYPE(id->driver_info) == 0) { - id->driver_info |= to_bias << 24; - } - } + complete_and_exit(&usu_end_notify, 0); } /* */ static int __init usb_usual_init(void) { - int usb_usual_bias; int rc; bias[BIAS_NAME_SIZE-1] = 0; usb_usual_bias = parse_bias(bias); - bias_storage_ids(usb_usual_bias); - if ((rc = usb_register(&usu_driver)) != 0) { - up(&usu_init_notify); - return rc; - } + rc = usb_register(&usu_driver); up(&usu_init_notify); - return 0; + return rc; } static void __exit usb_usual_exit(void) diff -urp -X dontdiff linux-2.6.14-rc3-wip6/drivers/usb/storage/usb.c linux-2.6.14-rc3-lem/drivers/usb/storage/usb.c --- linux-2.6.14-rc3-wip6/drivers/usb/storage/usb.c 2005-10-09 12:25:18.000000000 -0700 +++ linux-2.6.14-rc3-lem/drivers/usb/storage/usb.c 2005-10-09 12:31:17.000000000 -0700 @@ -419,7 +419,7 @@ static int associate_dev(struct us_data } /* Find an unusual_dev descriptor (always succeeds in the current code) */ -static struct us_unusual_dev *find_unusual_entry(const struct usb_device_id *id) +static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) { const int id_index = id - storage_usb_ids; return &us_unusual_dev_list[id_index]; @@ -431,7 +431,7 @@ static void get_device_info(struct us_da struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = &us->pusb_intf->cur_altsetting->desc; - struct us_unusual_dev *unusual_dev = find_unusual_entry(id); + struct us_unusual_dev *unusual_dev = find_unusual(id); /* Store the entries */ us->unusual_dev = unusual_dev; @@ -441,7 +441,7 @@ static void get_device_info(struct us_da us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? idesc->bInterfaceProtocol : unusual_dev->useTransport; - us->flags = id->driver_info; + us->flags = USB_US_ORIG_FLAGS(id->driver_info); /* * This flag is only needed when we're in high-speed, so let's @@ -877,7 +899,7 @@ static int storage_probe(struct usb_inte struct us_data *us; int result; - if (USB_US_TYPE(id->driver_info) != USB_US_TYPE_STOR) + if (usb_usual_check_type(id, USB_US_TYPE_STOR)) return -ENXIO; US_DEBUGP("USB Mass Storage device detected\n"); @@ -999,15 +1021,12 @@ static int __init usb_stor_init(void) int retval; printk(KERN_INFO "Initializing USB Mass Storage driver...\n"); - usb_usual_set_present(USB_US_TYPE_STOR); - /* register the driver, return usb_register return code if error */ retval = usb_register(&usb_storage_driver); - if (retval == 0) + if (retval == 0) { printk(KERN_INFO "USB Mass Storage support registered.\n"); - else - usb_usual_clear_present(USB_US_TYPE_STOR); - + usb_usual_set_present(USB_US_TYPE_STOR); + } return retval; } diff -urp -X dontdiff linux-2.6.14-rc3-wip6/include/linux/usb_usual.h linux-2.6.14-rc3-lem/include/linux/usb_usual.h --- linux-2.6.14-rc3-wip6/include/linux/usb_usual.h 2005-10-09 12:25:18.000000000 -0700 +++ linux-2.6.14-rc3-lem/include/linux/usb_usual.h 2005-10-09 12:31:53.000000000 -0700 @@ -56,7 +56,8 @@ enum { US_DO_ALL_FLAGS }; #define USB_US_TYPE_STOR 1 /* usb-storage */ #define USB_US_TYPE_UB 2 /* ub */ -#define USB_US_TYPE(flags) (((flags) >> 24) & 0xFF) +#define USB_US_TYPE(flags) (((flags) >> 24) & 0xFF) +#define USB_US_ORIG_FLAGS(flags) ((flags) & 0x00FFFFFF) /* * This is probably not the best place to keep these constants, conceptually. @@ -111,10 +112,12 @@ enum { US_DO_ALL_FLAGS }; extern struct usb_device_id storage_usb_ids[]; extern void usb_usual_set_present(int type); extern void usb_usual_clear_present(int type); +extern int usb_usual_check_type(const struct usb_device_id *, int type); #else #define usb_usual_set_present(t) do { } while(0) #define usb_usual_clear_present(t) do { } while(0) +#define usb_usual_check_type(id, t) (0) #endif /* CONFIG_USB_LIBUSUAL */ #endif /* __LINUX_USB_USUAL_H */ ------------------------------------------------------- This SF.Net email is sponsored by: Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel