A successful TMF means that the URBs for a command must be killed. Also fixes sleeping with a spinlock. Signed-off-by: Oliver Neukum <oneukum@xxxxxxxx> --- drivers/usb/storage/uas.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index d789227..5eaa270 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -57,7 +57,7 @@ struct uas_dev_info { spinlock_t lock; struct work_struct work; struct completion deathknell; - bool tmf_perfomed; /* an ack to a TMF was seen */ + bool tmf_performed; /* an ack to a TMF was seen */ bool tmf_catastrophic; /* TMF failed, retry useless */ bool tmf_error; /* tmf may be retried after error handling */ }; @@ -271,9 +271,9 @@ static void finish_tmf(struct uas_dev_info *devinfo, struct response_iu *riu, st uas_log_cmd_state(cmnd, "expected response iu", response_code); if (response_code == RC_TMF_SUCCEEDED) - devinfo->tmf_perfomed = true; + devinfo->tmf_performed = true; else - devinfo->tmf_perfomed = false; + devinfo->tmf_performed = false; } static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd *cmnd) @@ -837,12 +837,9 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) struct task_mgmt_iu *tmf = devinfo->tmf_iu; struct urb *data_in_urb = NULL; struct urb *data_out_urb = NULL; - unsigned long flags; - int err, time; + int err, time = 0; int success = FAILED; - spin_lock_irqsave(&devinfo->lock, flags); - uas_log_cmd_state(cmnd, __func__, 0); /* Ensure that try_complete does not call scsi_done */ @@ -852,6 +849,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) devinfo->deathrow = cmnd; devinfo->tmf_catastrophic = false; devinfo->tmf_error = false; + devinfo->tmf_performed = false; prepare_tmf_urb(devinfo, cmnd); prepare_ABORT_TASK_tmf(tmf, cmdinfo); @@ -869,14 +867,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) time = wait_for_completion_timeout(&devinfo->deathknell, USB_CTRL_GET_TIMEOUT); /* in case of timeout */ usb_kill_urb(devinfo->management_urb); - if (time && devinfo->tmf_perfomed) { - cmdinfo->state &= ~COMMAND_ABORTING; - /* - * manually finish as resources must be freed only once - */ - cmnd->result = DID_ABORT << 16; - cmnd->scsi_done(cmnd); - } + if (devinfo->tmf_catastrophic) success = FAST_IO_FAIL; else if (devinfo->tmf_error) @@ -893,8 +884,6 @@ give_up: uas_free_unsubmitted_urbs(cmnd); - spin_unlock_irqrestore(&devinfo->lock, flags); - if (data_in_urb) { usb_kill_urb(data_in_urb); usb_put_urb(data_in_urb); @@ -903,7 +892,15 @@ give_up: usb_kill_urb(data_out_urb); usb_put_urb(data_out_urb); } - + /* must be done after the URBs are sure to be dead */ + if (time && devinfo->tmf_performed) { + cmdinfo->state &= ~COMMAND_ABORTING; + /* + * manually finish as resources must be freed only once + */ + cmnd->result = DID_ABORT << 16; + cmnd->scsi_done(cmnd); + } return success; } @@ -927,7 +924,7 @@ static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd) goto failure; time = wait_for_completion_timeout(&devinfo->deathknell, USB_CTRL_GET_TIMEOUT); - if (time && devinfo->tmf_perfomed) + if (time && devinfo->tmf_performed) success = SUCCESS; usb_kill_urb(devinfo->management_urb); -- 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