Simple evaluation of the response uis result codes
Signed-off-by: Oliver Neukum <[email protected]>
---
drivers/usb/storage/uas.c | 80 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 65 insertions(+), 15 deletions(-)
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 843c73e..d2d9244 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 aborted; /* a reply to a TASK ABORT was seen */
+ bool tmf_perfomed; /* 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->aborted = true;
+ devinfo->tmf_perfomed = true;
else
- devinfo->aborted = false;
+ devinfo->tmf_perfomed = false;
}
static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd
*cmnd)
@@ -796,6 +796,35 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
static DEF_SCSI_QCMD(uas_queuecommand)
+static void prepare_tmf_urb(struct uas_dev_info *devinfo, struct scsi_cmnd
*cmnd)
+{
+ usb_fill_bulk_urb(devinfo->management_urb,
+ devinfo->udev,
+ devinfo->cmd_pipe, /* shared */
+ devinfo->tmf_iu,
+ sizeof(devinfo->tmf_iu),
+ uas_tmf_cmplt,
+ cmnd->device->host);
+}
+
+static void prepare_ABORT_TASK_tmf(struct task_mgmt_iu *tmf, struct
uas_cmd_info *cmdinfo)
+{
+ memset(tmf, 0, sizeof(struct task_mgmt_iu));
+ tmf->iu_id = IU_ID_TASK_MGMT;
+ tmf->tag = cpu_to_be16( TAG_FOR_TMF );
+ tmf->function = TMF_ABORT_TASK;
+ tmf->task_tag = cmdinfo->uas_tag; /* already BE */
+}
+
+static void prepare_LOGICAL_UNIT_RESET_tmf(struct task_mgmt_iu *tmf, struct
scsi_device *sdev)
+{
+ memset(tmf, 0, sizeof(struct task_mgmt_iu));
+ tmf->iu_id = IU_ID_TASK_MGMT;
+ tmf->tag = cpu_to_be16( TAG_FOR_TMF );
+ tmf->function = TMF_LOGICAL_UNIT_RESET;
+ int_to_scsilun(sdev->lun, &tmf->lun);
+}
+
/*
* For now we do not support actually sending an abort to the device, so
* this eh always fails. Still we must define it to make sure that we've
@@ -823,17 +852,9 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
devinfo->deathrow = cmnd;
devinfo->tmf_catastrophic = false;
devinfo->tmf_error = false;
- usb_fill_bulk_urb(devinfo->management_urb,
- devinfo->udev,
- devinfo->cmd_pipe, /* shared */
- devinfo->tmf_iu,
- sizeof(devinfo->tmf_iu),
- uas_tmf_cmplt,
- cmnd->device->host);
- tmf->iu_id = IU_ID_TASK_MGMT;
- tmf->tag = cpu_to_be16( TAG_FOR_TMF );
- tmf->function = TMF_ABORT_TASK;
- tmf->task_tag = cmdinfo->uas_tag; /* already BE */
+
+ prepare_tmf_urb(devinfo, cmnd);
+ prepare_ABORT_TASK_tmf(tmf, cmdinfo);
err = usb_submit_urb(devinfo->management_urb, GFP_NOIO);
if (err < 0) /* unkillable */
@@ -848,7 +869,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->aborted) {
+ if (time && devinfo->tmf_perfomed) {
cmdinfo->state &= ~COMMAND_ABORTING;
/*
* manually finish as resources must be freed only once
@@ -886,6 +907,34 @@ give_up:
return success;
}
+static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
+{
+ struct scsi_device *sdev = cmnd->device;
+ struct uas_dev_info *devinfo = sdev->hostdata;
+ struct task_mgmt_iu *tmf = devinfo->tmf_iu;
+ int success = FAILED;
+ int err;
+ int time;
+
+ devinfo->tmf_catastrophic = false;
+ devinfo->tmf_error = false;
+ init_completion(&devinfo->deathknell);
+ prepare_tmf_urb(devinfo, cmnd);
+ prepare_LOGICAL_UNIT_RESET_tmf(tmf, cmnd->device);
+
+ err = usb_submit_urb(devinfo->management_urb, GFP_NOIO);
+ if (err < 0)
+ goto failure;
+
+ time = wait_for_completion_timeout(&devinfo->deathknell,
USB_CTRL_GET_TIMEOUT);
+ if (time && devinfo->tmf_perfomed)
+ success = SUCCESS;
+ usb_kill_urb(devinfo->management_urb);
+
+failure:
+ return success;
+}
+
static int uas_eh_host_reset_handler(struct scsi_cmnd *cmnd)
{
struct scsi_device *sdev = cmnd->device;
@@ -990,6 +1039,7 @@ static struct scsi_host_template uas_host_template = {
.slave_alloc = uas_slave_alloc,
.slave_configure = uas_slave_configure,
.eh_abort_handler = uas_eh_abort_handler,
+ .eh_device_reset_handler = uas_eh_device_reset_handler,
.eh_host_reset_handler = uas_eh_host_reset_handler,
.can_queue = 65536, /* Is there a limit on the _host_ ? */
.this_id = -1,
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html