|
@@ -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));
|