VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / usb / storage / transport.c
index e42c59a..2321558 100644 (file)
@@ -708,6 +708,12 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
                        srb->sense_buffer[0] = 0x0;
                }
        }
+
+       /* Did we transfer less than the minimum amount required? */
+       if (srb->result == SAM_STAT_GOOD &&
+                       srb->request_bufflen - srb->resid < srb->underflow)
+               srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);
+
        return;
 
        /* abort processing: the bulk-only transport requires a reset
@@ -908,26 +914,29 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
                                 USB_RECIP_INTERFACE,
                                 0, us->ifnum, us->iobuf, 1, HZ);
 
+       US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
+                 result, us->iobuf[0]);
+
+       /* if we have a successful request, return the result */
+       if (result == 1)
+               return us->iobuf[0];
+
        /* 
         * Some devices (i.e. Iomega Zip100) need this -- apparently
         * the bulk pipes get STALLed when the GetMaxLUN request is
         * processed.   This is, in theory, harmless to all other devices
         * (regardless of if they stall or not).
         */
-       if (result < 0) {
+       if (result == -EPIPE) {
                usb_stor_clear_halt(us, us->recv_bulk_pipe);
                usb_stor_clear_halt(us, us->send_bulk_pipe);
+               /* return the default -- no LUNs */
+               return 0;
        }
 
-       US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
-                 result, us->iobuf[0]);
-
-       /* if we have a successful request, return the result */
-       if (result == 1)
-               return us->iobuf[0];
-
-       /* return the default -- no LUNs */
-       return 0;
+       /* An answer or a STALL are the only valid responses.  If we get
+        * something else, return an indication of error */
+       return -1;
 }
 
 int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
@@ -1110,10 +1119,11 @@ static int usb_stor_reset_common(struct us_data *us,
                goto Done;
        }
 
-       /* long wait for reset, so unlock to allow disconnects */
-       up(&us->dev_semaphore);
-       msleep(6000);
-       down(&us->dev_semaphore);
+       /* Give the device some time to recover from the reset,
+        * but don't delay disconnect processing. */
+       wait_event_interruptible_timeout(us->dev_reset_wait,
+                       test_bit(US_FLIDX_DISCONNECTING, &us->flags),
+                       HZ*6);
        if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
                US_DEBUGP("Reset interrupted by disconnect\n");
                goto Done;