A reset based on usb_reset_device() will reset the whole host, not just a bus. We should use the correct entry. Signed-off-by: Oliver Neukum <oneukum@xxxxxxxx> --- drivers/usb/storage/uas.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 31ff1a0..f1eaa93 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -57,7 +57,9 @@ struct uas_dev_info { spinlock_t lock; struct work_struct work; struct completion deathknell; - bool aborted; + bool aborted; /* a reply to a TASK ABORT was seen */ + bool tmf_catastrophic; /* TMF failed, retry useless */ + bool tmf_error; /* tmf may be retried after error handling */ }; enum { @@ -492,6 +494,20 @@ static void uas_tmf_cmplt(struct urb *urb) if (status < 0) { devinfo->deathrow = NULL; complete(&devinfo->deathknell); + switch (status) { + case -ESHUTDOWN: + case -ENODEV: + devinfo->tmf_catastrophic = true; + break; + case -EPIPE: + /* small packages, hence no partial transmission */ + case -EILSEQ: + case -EPROTO: + devinfo->tmf_error = true; + break; + default: + break; + } } /* @@ -794,6 +810,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) struct urb *data_out_urb = NULL; unsigned long flags; int err, time; + int success = FAILED; spin_lock_irqsave(&devinfo->lock, flags); @@ -804,6 +821,8 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) init_completion(&devinfo->deathknell); devinfo->deathrow = cmnd; + devinfo->tmf_catastrophic = false; + devinfo->tmf_error = false; usb_fill_bulk_urb(devinfo->management_urb, devinfo->udev, devinfo->cmd_pipe, /* shared */ @@ -819,6 +838,12 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) err = usb_submit_urb(devinfo->management_urb, GFP_NOIO); if (err < 0) /* unkillable */ goto give_up; + else + /* + * SCSI has the convention that a potential + * ABORT is to be reported as SUCCESS + */ + success = SUCCESS; time = wait_for_completion_timeout(&devinfo->deathknell, USB_CTRL_GET_TIMEOUT); /* in case of timeout */ @@ -831,6 +856,10 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) cmnd->result = DID_ABORT << 16; cmnd->scsi_done(cmnd); } + if (devinfo->tmf_catastrophic) + success = FAST_IO_FAIL; + else if (devinfo->tmf_error) + success = FAILED; give_up: @@ -854,7 +883,7 @@ give_up: usb_put_urb(data_out_urb); } - return FAILED; + return success; } static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html