On Mon, 05 Apr 2004 15:53:48 -0400
Peter Santoro <[EMAIL PROTECTED]> wrote:

>  >>EIP; c021cc1b <usb_destroy_configuration+db/210>   <=====

> Trace; c021bfb7 <usb_free_dev+37/60>
> Trace; c0108a74 <do_IRQ+64/a0>
> Trace; c010b118 <call_do_IRQ+5/d>
> Trace; c0146ed1 <open_namei+1/5c0>
> Trace; c013a7d3 <filp_open+43/70>
> Trace; c013ab93 <sys_open+53/a0>
> Trace; c010734f <system_call+33/38>


>  >>EIP; c0241cdb <usb_destroy_configuration+db/210>   <=====
> 
> Trace; c0241077 <usb_free_dev+37/60>
> Trace; c010b118 <call_do_IRQ+5/d>
> Trace; c0129c26 <__constant_memcpy+d6/110>
> Trace; c01290ad <do_wp_page+ed/270>
> Trace; c0129969 <handle_mm_fault+f9/110>
> Trace; c0115d98 <do_page_fault+168/524>
> Trace; c0118f88 <__mmdrop+38/50>
> Trace; c011cf32 <do_exit+212/240>
> Trace; c0115c30 <do_page_fault+0/524>
> Trace; c0107440 <error_code+34/3c>

This looks like what I fixed for Red Hat some time ago for our partner
Dell who shipped some pretty silly Lexar OEM USB keys. Please try the
attached patch, it migth fix the oops. It is important for me to know
the result, because I plan to push this into Marcelo's 2.4.27.

However, Stern is right, the root cause is that the device
microcode goes belly up and disconnects. My fix only prevents
oopsing but is not going to make the device work (probably).
Once you got rid of oopses, you will need to work with Mrs
Stern and Dharm to find what operating the device didn't like,
then fix that.

-- Pete

diff -ur -X dontdiff linux-2.4.26-rc1/drivers/usb/storage/scsiglue.c 
linux-2.4.26-rc1-nip/drivers/usb/storage/scsiglue.c
--- linux-2.4.26-rc1/drivers/usb/storage/scsiglue.c     2004-03-31 12:37:58.000000000 
-0800
+++ linux-2.4.26-rc1-nip/drivers/usb/storage/scsiglue.c 2004-03-31 12:59:18.000000000 
-0800
@@ -218,7 +218,14 @@
        US_DEBUGP("device_reset() called\n" );
 
        spin_unlock_irq(&io_request_lock);
+       down(&(us->dev_semaphore));
+       if (!us->pusb_dev) {
+               up(&(us->dev_semaphore));
+               spin_lock_irq(&io_request_lock);
+               return SUCCESS;
+       }
        rc = us->transport_reset(us);
+       up(&(us->dev_semaphore));
        spin_lock_irq(&io_request_lock);
        return rc;
 }
@@ -235,27 +242,32 @@
        /* we use the usb_reset_device() function to handle this for us */
        US_DEBUGP("bus_reset() called\n");
 
+       spin_unlock_irq(&io_request_lock);
+
+       down(&(us->dev_semaphore));
+
        /* if the device has been removed, this worked */
        if (!us->pusb_dev) {
                US_DEBUGP("-- device removed already\n");
+               up(&(us->dev_semaphore));
+               spin_lock_irq(&io_request_lock);
                return SUCCESS;
        }
 
-       spin_unlock_irq(&io_request_lock);
-
        /* release the IRQ, if we have one */
-       down(&(us->irq_urb_sem));
        if (us->irq_urb) {
                US_DEBUGP("-- releasing irq URB\n");
                result = usb_unlink_urb(us->irq_urb);
                US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
        }
-       up(&(us->irq_urb_sem));
 
        /* attempt to reset the port */
        if (usb_reset_device(us->pusb_dev) < 0) {
-               spin_lock_irq(&io_request_lock);
-               return FAILED;
+               /*
+                * Do not return errors, or else the error handler might
+                * invoke host_reset, which is not implemented.
+                */
+               goto bail_out;
        }
 
        /* FIXME: This needs to lock out driver probing while it's working
@@ -286,28 +298,36 @@
                up(&intf->driver->serialize);
        }
 
+bail_out:
        /* re-allocate the IRQ URB and submit it to restore connectivity
         * for CBI devices
         */
        if (us->protocol == US_PR_CBI) {
-               down(&(us->irq_urb_sem));
                us->irq_urb->dev = us->pusb_dev;
                result = usb_submit_urb(us->irq_urb);
                US_DEBUGP("usb_submit_urb() returns %d\n", result);
-               up(&(us->irq_urb_sem));
        }
-       
+
+       up(&(us->dev_semaphore));
+
        spin_lock_irq(&io_request_lock);
 
        US_DEBUGP("bus_reset() complete\n");
        return SUCCESS;
 }
 
-/* FIXME: This doesn't do anything right now */
 static int host_reset( Scsi_Cmnd *srb )
 {
-       printk(KERN_CRIT "usb-storage: host_reset() requested but not implemented\n" );
-       return FAILED;
+       struct us_data *us = (struct us_data *)srb->host->hostdata[0];
+
+       spin_unlock_irq(&io_request_lock);
+       down(&(us->dev_semaphore));
+        printk(KERN_CRIT "usb-storage: host_reset() requested but hardly 
implemented\n" );
+       up(&(us->dev_semaphore));
+       spin_lock_irq(&io_request_lock);
+       US_DEBUGP("host_reset() complete\n");
+
+       return SUCCESS;
 }
 
 /***********************************************************************
@@ -399,6 +419,13 @@
        can_queue:              1,
        this_id:                -1,
 
+       /*
+        * This is supposed to be an HBA limit. In our case, it is here
+        * because many _devices_ break if transfer is too long, but
+        * we know no reliable way to detect and blacklist them.
+        */
+       max_sectors:            240,
+
        sg_tablesize:           SG_ALL,
        cmd_per_lun:            1,
        present:                0,
diff -ur -X dontdiff linux-2.4.26-rc1/drivers/usb/storage/usb.c 
linux-2.4.26-rc1-nip/drivers/usb/storage/usb.c
--- linux-2.4.26-rc1/drivers/usb/storage/usb.c  2004-02-26 14:09:59.000000000 -0800
+++ linux-2.4.26-rc1-nip/drivers/usb/storage/usb.c      2004-03-31 12:55:52.000000000 
-0800
@@ -501,6 +501,9 @@
  * strucuture is current.  This includes the ep_int field, which gives us
  * the endpoint for the interrupt.
  * Returns non-zero on failure, zero on success
+ *
+ * ss->dev_semaphore is expected taken, except for a newly minted,
+ * unregistered device.
  */ 
 static int usb_stor_allocate_irq(struct us_data *ss)
 {
@@ -510,13 +513,9 @@
 
        US_DEBUGP("Allocating IRQ for CBI transport\n");
 
-       /* lock access to the data structure */
-       down(&(ss->irq_urb_sem));
-
        /* allocate the URB */
        ss->irq_urb = usb_alloc_urb(0);
        if (!ss->irq_urb) {
-               up(&(ss->irq_urb_sem));
                US_DEBUGP("couldn't allocate interrupt URB");
                return 1;
        }
@@ -537,12 +536,9 @@
        US_DEBUGP("usb_submit_urb() returns %d\n", result);
        if (result) {
                usb_free_urb(ss->irq_urb);
-               up(&(ss->irq_urb_sem));
                return 2;
        }
 
-       /* unlock the data structure and return success */
-       up(&(ss->irq_urb_sem));
        return 0;
 }
 
@@ -772,7 +768,6 @@
                init_completion(&(ss->notify));
                init_MUTEX_LOCKED(&(ss->ip_waitq));
                spin_lock_init(&(ss->queue_exclusion));
-               init_MUTEX(&(ss->irq_urb_sem));
                init_MUTEX(&(ss->current_urb_sem));
                init_MUTEX(&(ss->dev_semaphore));
 
@@ -1063,7 +1058,6 @@
        down(&(ss->dev_semaphore));
 
        /* release the IRQ, if we have one */
-       down(&(ss->irq_urb_sem));
        if (ss->irq_urb) {
                US_DEBUGP("-- releasing irq URB\n");
                result = usb_unlink_urb(ss->irq_urb);
@@ -1071,7 +1065,6 @@
                usb_free_urb(ss->irq_urb);
                ss->irq_urb = NULL;
        }
-       up(&(ss->irq_urb_sem));
 
        /* free up the main URB for this device */
        US_DEBUGP("-- releasing main URB\n");
diff -ur -X dontdiff linux-2.4.26-rc1/drivers/usb/storage/usb.h 
linux-2.4.26-rc1-nip/drivers/usb/storage/usb.h
--- linux-2.4.26-rc1/drivers/usb/storage/usb.h  2003-11-29 19:23:15.000000000 -0800
+++ linux-2.4.26-rc1-nip/drivers/usb/storage/usb.h      2004-04-04 19:19:30.000000000 
-0700
@@ -116,7 +116,7 @@
        struct us_data          *next;           /* next device */
 
        /* the device we're working with */
-       struct semaphore        dev_semaphore;   /* protect pusb_dev */
+       struct semaphore        dev_semaphore;   /* protect many things */
        struct usb_device       *pusb_dev;       /* this usb_device */
 
        unsigned int            flags;           /* from filter initially */
@@ -162,7 +162,6 @@
        atomic_t                ip_wanted[1];    /* is an IRQ expected?  */
 
        /* interrupt communications data */
-       struct semaphore        irq_urb_sem;     /* to protect irq_urb   */
        struct urb              *irq_urb;        /* for USB int requests */
        unsigned char           irqbuf[2];       /* buffer for USB IRQ   */
        unsigned char           irqdata[2];      /* data from USB IRQ    */


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to