Hi,

[about the oops in ohci when a scanner is disconnected]

On Fri, Feb 28, 2003 at 09:07:17AM -0800, Greg KH wrote:
> On Thu, Feb 27, 2003 at 11:15:34AM +0100, Henning Meier-Geinitz wrote:
> > Hi,
> > 
> > On Wed, Feb 26, 2003 at 03:12:03PM -0800, Greg KH wrote:
> > > On Wed, Feb 26, 2003 at 10:37:30PM +0100, Henning Meier-Geinitz wrote:
> > > > Unable to handle kernel NULL pointer dereference at virtual address 00000000
> > > >  printing eip:
> > > > c01e1dd7
> > > > *pde = 00000000
> > > > Oops: 0000
> > > > CPU:    0
> > > > EIP:    0060:[<c01e1dd7>]    Not tainted
> > > > EFLAGS: 00010082
> > > > EIP is at dl_reverse_done_list+0x163/0x194
> > > > eax: 00000000   ebx: dfd72080   ecx: dfd7b0c0   edx: 00000014
> > > > esi: dfd7b0e0   edi: df73f2bc   ebp: c02b1efc   esp: c02b1eb8
> > > > ds: 007b   es: 007b   ss: 0068
> > > > Process swapper (pid: 0, threadinfo=c02b0000 task=c027bde0)
> > > > Stack: dfbbb15e df73f2bc c1524eec dfbbb004 00000003 c0262c60 00000005 ffffff92 
> > > >        e0800010 dfe0e000 00000002 00000014 00000000 00000000 00000000 00000005 
> > > >        00000246 c02b1f2c c01e2c10 dfe0e000 c02b1f90 e0800014 c026324c 0000023a 
> > > > Call Trace:
> > > >  [<c01e2c10>] ohci_irq+0x130/0x1d8
> > > 
> > > David, any clues?
> > 
> > The crash doesn't happen if I move back the irq unlink from
> > destroy_scanner to disconnect_scanner:
> 
> Which points at the ohci driver not allowing usb_unlink_urb() to be
> called after the device is disconnected.  David, is this true?

Ok, what's the result of the discussion? Should I wait for changes in
ohci/usbcore or just send the patch for the scanner driver that moves
the irq urb unlink to the disconnect function?

Anyway, I'll just append it (against 2.5.64) :-)

--------

Used kobject reference counting to free the scn struct when the device
is closed and disconnected. Avoids crashes when writing to a 
disconnected device. (Thanks to Greg KH).

I've also changed irq_scanner to avoid submitting new URBs when the
old one returned with an error. Without this change irq_scanner gets
called ever and ever again after a disconnect while open.

Bye,
  Henning

diff -u linux-2.5.64/drivers/usb/image/scanner.c 
linux-2.5.64-nohang2/drivers/usb/image/scanner.c
--- linux-2.5.64/drivers/usb/image/scanner.c    2003-03-11 11:19:47.000000000 +0100
+++ linux-2.5.64-nohang2/drivers/usb/image/scanner.c    2003-03-11 13:18:54.000000000 
+0100
@@ -1,7 +1,7 @@
 /* -*- linux-c -*- */
 
 /* 
- * Driver for USB Scanners (linux-2.5.64)
+ * Driver for USB Scanners (linux-2.5)
  *
  * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
  * Copyright (C) 2002, 2003 Henning Meier-Geinitz
@@ -350,6 +350,9 @@
  *    - Added vendor/product ids for Artec, Avision, Brother, Medion, Primax,
  *      Prolink, Fujitsu, Plustek, and SYSCAN scanners.
  *    - Fixed generation of devfs names if dynamic minors are disabled.
+ *    - Used kobject reference counting to free the scn struct when the device
+ *      is closed and disconnected. Avoids crashes when writing to a 
+ *      disconnected device. (Thanks to Greg KH).
  *
  * TODO
  *    - Performance
@@ -427,6 +430,7 @@
                return;
        default:
                dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               return; 
        }
 
        dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
@@ -461,6 +465,7 @@
                return -ENODEV;
        }
        scn = usb_get_intfdata(intf);
+       kobject_get(&scn->kobj);
 
        dev = scn->scn_dev;
 
@@ -521,6 +526,8 @@
        up(&scn_mutex);
        up(&(scn->sem));
 
+       kobject_put(&scn->kobj);
+
        return 0;
 }
 
@@ -813,6 +820,37 @@
        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));
+
+       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 +1130,13 @@
        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->intr_ep) {
+               dbg("%s(%d): Unlinking IRQ URB", __FUNCTION__, scn->scn_minor);
+               usb_unlink_urb(scn->scn_irq);
        }
+
+       if (scn)
+               kobject_put(&scn->kobj);
 }
 
 /* we want to look at all devices, as the vendor/product id can change
diff -u linux-2.5.64/drivers/usb/image/scanner.h 
linux-2.5.64-nohang2/drivers/usb/image/scanner.h
--- linux-2.5.64/drivers/usb/image/scanner.h    2003-03-11 11:19:47.000000000 +0100
+++ linux-2.5.64-nohang2/drivers/usb/image/scanner.h    2003-03-11 13:33:00.000000000 
+0100
@@ -1,5 +1,5 @@
 /*
- * Driver for USB Scanners (linux-2.5.64)
+ * Driver for USB Scanners (linux-2.5)
  *
  * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
  * Previously maintained by Brian Beattie
@@ -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