X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fstorage%2Flibusual.c;fp=drivers%2Fusb%2Fstorage%2Flibusual.c;h=38faca734d0904f1fd139b7348c62bb570cf04eb;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=b1ec4a718547316c62cf39fa4872ffd7651424f9;hpb=4e76c8a9fa413ccc09d3f7f664183dcce3555d57;p=linux-2.6.git diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c index b1ec4a718..38faca734 100644 --- a/drivers/usb/storage/libusual.c +++ b/drivers/usb/storage/libusual.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -13,6 +14,7 @@ */ #define USU_MOD_FL_THREAD 1 /* Thread is running */ #define USU_MOD_FL_PRESENT 2 /* The module is loaded */ +#define USU_MOD_FL_FAILED 4 /* The module failed to load */ struct mod_status { unsigned long fls; @@ -33,8 +35,12 @@ static DECLARE_MUTEX_LOCKED(usu_init_notify); static DECLARE_COMPLETION(usu_end_notify); static atomic_t total_threads = ATOMIC_INIT(0); +static int usu_kick(unsigned long type); static int usu_probe_thread(void *arg); +static struct class *usu_class; +static struct class_device *usu_class_device; + /* * The table. */ @@ -111,18 +117,44 @@ int usb_usual_check_type(const struct usb_device_id *id, int caller_type) } EXPORT_SYMBOL_GPL(usb_usual_check_type); +/* + */ +static int usu_uevent(struct class_device *class_dev, + char **envp, int num_envp, char *buffer, int buffer_size) +{ + unsigned long flags; + int i; + + for (i = 1; i < 3; i++) { + spin_lock_irqsave(&usu_lock, flags); + if (stat[i].fls & USU_MOD_FL_FAILED) { + stat[i].fls &= ~USU_MOD_FL_FAILED; + spin_unlock_irqrestore(&usu_lock, flags); + usu_kick(i); + } else { + spin_unlock_irqrestore(&usu_lock, flags); + } + } + return 0; +} + /* */ static int usu_probe(struct usb_interface *intf, const struct usb_device_id *id) { unsigned long type; - int rc; - unsigned long flags; type = USB_US_TYPE(id->driver_info); if (type == 0) type = atomic_read(&usu_bias); + return usu_kick(type); +} + +static int usu_kick(unsigned long type) +{ + int rc; + unsigned long flags; spin_lock_irqsave(&usu_lock, flags); if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) { @@ -186,10 +218,14 @@ static int usu_probe_thread(void *arg) if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) { /* * This should not happen, but let us keep tabs on it. + * One common source of this a user who builds USB statically, + * then uses initrd, and has a USB device. When static devices + * are probed, request_module() calls a fake modprobe and fails. */ printk(KERN_NOTICE "libusual: " - "modprobe for %s succeeded, but module is not present\n", + "request for %s succeeded, but module is not present\n", bias_names[type]); + st->fls |= USU_MOD_FL_FAILED; } st->fls &= ~USU_MOD_FL_THREAD; spin_unlock_irqrestore(&usu_lock, flags); @@ -203,9 +239,27 @@ static int __init usb_usual_init(void) { int rc; + usu_class = class_create(THIS_MODULE, "libusual"); + if (IS_ERR(usu_class)) { + rc = PTR_ERR(usu_class_device); + goto err_class; + } + usu_class_device = class_device_create(usu_class, NULL, 0, NULL, "0"); + if (IS_ERR(usu_class_device)) { + rc = PTR_ERR(usu_class_device); + goto err_classdev; + } + usu_class_device->uevent = usu_uevent; + rc = usb_register(&usu_driver); up(&usu_init_notify); return rc; + + // class_device_destroy(usu_class, 0); +err_classdev: + class_destroy(usu_class); +err_class: + return rc; } static void __exit usb_usual_exit(void) @@ -221,6 +275,9 @@ static void __exit usb_usual_exit(void) wait_for_completion(&usu_end_notify); atomic_dec(&total_threads); } + + class_device_destroy(usu_class, 0); + class_destroy(usu_class); } /*