]> err.no Git - linux-2.6/blobdiff - drivers/usb/storage/transport.c
Merge commit 'origin/master'
[linux-2.6] / drivers / usb / storage / transport.c
index 670e4cbd1f06b8e09be29d1ae5d63fb3a2f6593b..3523a0bfa0ffd429caf8414ff4adae858a4c2ef6 100644 (file)
@@ -1032,8 +1032,21 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
 
        /* try to compute the actual residue, based on how much data
         * was really transferred and what the device tells us */
-       if (residue) {
-               if (!(us->fflags & US_FL_IGNORE_RESIDUE)) {
+       if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
+
+               /* Heuristically detect devices that generate bogus residues
+                * by seeing what happens with INQUIRY and READ CAPACITY
+                * commands.
+                */
+               if (bcs->Status == US_BULK_STAT_OK &&
+                               scsi_get_resid(srb) == 0 &&
+                                       ((srb->cmnd[0] == INQUIRY &&
+                                               transfer_length == 36) ||
+                                       (srb->cmnd[0] == READ_CAPACITY &&
+                                               transfer_length == 8))) {
+                       us->fflags |= US_FL_IGNORE_RESIDUE;
+
+               } else {
                        residue = min(residue, transfer_length);
                        scsi_set_resid(srb, max(scsi_get_resid(srb),
                                                               (int) residue));
@@ -1172,8 +1185,8 @@ int usb_stor_port_reset(struct us_data *us)
                        result = -EIO;
                        US_DEBUGP("No reset during disconnect\n");
                } else {
-                       result = usb_reset_composite_device(us->pusb_dev);
-                       US_DEBUGP("usb_reset_composite_device returns %d\n",
+                       result = usb_reset_device(us->pusb_dev);
+                       US_DEBUGP("usb_reset_device returns %d\n",
                                        result);
                }
                if (rc_lock)