On Tue, Feb 25, 2003 at 05:51:42PM +0100, Henning Meier-Geinitz wrote:
> Hi,
> 
> Avoid crashing when read/write/ioctl is called after disconnecting the
> device. Keep scn until the device is closed and check scn->present in
> read/write/ioctl. 

Ick, no, I don't like this.  I think the scanner driver can actually get
rid of all of these horrible locks to handle the disconnect/close mess
by just using a reference count.  To back this up, here's a patch that I
just wrote for the scanner driver (it's on top of the two other patches
you sent me) that adds a kobject and should handle the destruction of
the device just fine when the last reference goes away.  

I can't test the patch, as I don't have a scanner, and if this works, I
think the "global" lock can go away, and much of the use of the
per-device lock can disappear too.  Especially as you are only allowing
one user access to the device at a time.

Let me know if this patch works or not.

thanks,

greg k-h


===== scanner.c 1.70 vs edited =====
--- 1.70/drivers/usb/image/scanner.c    Tue Feb 25 06:32:02 2003
+++ edited/scanner.c    Tue Feb 25 13:22:05 2003
@@ -461,6 +461,7 @@
                return -ENODEV;
        }
        scn = usb_get_intfdata(intf);
+       kobject_get(&scn->kobj);
 
        dev = scn->scn_dev;
 
@@ -521,6 +522,8 @@
        up(&scn_mutex);
        up(&(scn->sem));
 
+       kobject_put(&scn->kobj);
+
        return 0;
 }
 
@@ -813,6 +816,41 @@
        return retval;
 }
 
+static void destroy_scanner (struct kobject *kobj)
+{
+       struct scn_usb_data *scn;
+
+       dbg ("%s", __FUNCTION__);
+
+       scn = to_scanner(kobj);
+
+       down (&scn_mutex);
+       down (&(scn->sem));
+
+       if(scn->intr_ep) {
+               dbg("%s(%d): Unlinking IRQ URB", __FUNCTION__, scn->scn_minor);
+               usb_unlink_urb(scn->scn_irq);
+       }
+       usb_driver_release_interface(&scanner_driver,
+               &scn->scn_dev->actconfig->interface[scn->ifnum]);
+
+       kfree(scn->ibuf);
+       kfree(scn->obuf);
+
+       dbg("%s: De-allocating minor:%d", __FUNCTION__, scn->scn_minor);
+       devfs_unregister(scn->devfs);
+       usb_deregister_dev(1, scn->scn_minor);
+       usb_free_urb(scn->scn_irq);
+       usb_put_dev(scn->scn_dev);
+       up (&(scn->sem));
+       kfree (scn);
+       up (&scn_mutex);
+}
+
+static struct kobj_type scanner_kobj_type = {
+       .release = destroy_scanner,
+};
+
 static struct
 file_operations usb_scanner_fops = {
        .owner =        THIS_MODULE,
@@ -982,6 +1020,8 @@
                return -ENOMEM;
        }
        memset (scn, 0, sizeof(struct scn_usb_data));
+       kobject_init(&scn->kobj);
+       scn->kobj.ktype = &scanner_kobj_type;
 
        scn->scn_irq = usb_alloc_urb(0, GFP_KERNEL);
        if (!scn->scn_irq) {
@@ -1049,6 +1089,7 @@
        }
 
 
+       usb_get_dev(dev);
        scn->bulk_in_ep = have_bulk_in;
        scn->bulk_out_ep = have_bulk_out;
        scn->intr_ep = have_intr;
@@ -1089,28 +1131,8 @@
        intf->kdev = NODEV;
 
        usb_set_intfdata(intf, NULL);
-       if (scn) {
-               down (&scn_mutex);
-               down (&(scn->sem));
-
-               if(scn->intr_ep) {
-                       dbg("disconnect_scanner(%d): Unlinking IRQ URB", 
scn->scn_minor);
-                       usb_unlink_urb(scn->scn_irq);
-               }
-               usb_driver_release_interface(&scanner_driver,
-                       &scn->scn_dev->actconfig->interface[scn->ifnum]);
-
-               kfree(scn->ibuf);
-               kfree(scn->obuf);
-
-               dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
-               devfs_unregister(scn->devfs);
-               usb_deregister_dev(1, scn->scn_minor);
-               usb_free_urb(scn->scn_irq);
-               up (&(scn->sem));
-               kfree (scn);
-               up (&scn_mutex);
-       }
+       if (scn)
+               kobject_put(&scn->kobj);
 }
 
 /* we want to look at all devices, as the vendor/product id can change
===== scanner.h 1.39 vs edited =====
--- 1.39/drivers/usb/image/scanner.h    Tue Feb 25 06:24:53 2003
+++ edited/scanner.h    Tue Feb 25 13:21:41 2003
@@ -335,7 +335,9 @@
        wait_queue_head_t rd_wait_q; /* read timeouts */
        struct semaphore sem; /* lock to prevent concurrent reads or writes */
        unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
+       struct kobject kobj;    /* Handles our reference counting */
 };
+#define to_scanner(d) container_of(d, struct scn_usb_data, kobj)
 
 extern devfs_handle_t usb_devfs_handle;
 


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to