summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index c7588c451e30..496bdfc19c95 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -122,11 +122,9 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd, unsigned long msecs)
WARN_ON_ONCE(true);
}
- if (msecs) {
- blk_mq_requeue_request(rq, false);
+ blk_mq_requeue_request(rq, false);
+ if (!scsi_host_in_recovery(cmd->device->host))
blk_mq_delay_kick_requeue_list(rq->q, msecs);
- } else
- blk_mq_requeue_request(rq, true);
}
/**
@@ -165,7 +163,8 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
*/
cmd->result = 0;
- blk_mq_requeue_request(scsi_cmd_to_rq(cmd), true);
+ blk_mq_requeue_request(scsi_cmd_to_rq(cmd),
+ !scsi_host_in_recovery(cmd->device->host));
}
/**
@@ -453,6 +452,7 @@ static void scsi_run_queue(struct request_queue *q)
if (!list_empty(&sdev->host->starved_list))
scsi_starved_list_run(sdev->host);
+ blk_mq_kick_requeue_list(q);
blk_mq_run_hw_queues(q, false);
}
@@ -503,6 +503,9 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)
static void scsi_run_queue_async(struct scsi_device *sdev)
{
+ if (scsi_host_in_recovery(sdev->host))
+ return;
+
if (scsi_target(sdev)->single_lun ||
!list_empty(&sdev->host->starved_list)) {
kblockd_schedule_work(&sdev->requeue_work);
@@ -578,11 +581,6 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
return false;
}
-static inline u8 get_scsi_ml_byte(int result)
-{
- return (result >> 8) & 0xff;
-}
-
/**
* scsi_result_to_blk_status - translate a SCSI result code into blk_status_t
* @result: scsi error code
@@ -595,17 +593,19 @@ static blk_status_t scsi_result_to_blk_status(int result)
* Check the scsi-ml byte first in case we converted a host or status
* byte.
*/
- switch (get_scsi_ml_byte(result)) {
+ switch (scsi_ml_byte(result)) {
case SCSIML_STAT_OK:
break;
case SCSIML_STAT_RESV_CONFLICT:
- return BLK_STS_NEXUS;
+ return BLK_STS_RESV_CONFLICT;
case SCSIML_STAT_NOSPC:
return BLK_STS_NOSPC;
case SCSIML_STAT_MED_ERROR:
return BLK_STS_MEDIUM;
case SCSIML_STAT_TGT_FAILURE:
return BLK_STS_TARGET;
+ case SCSIML_STAT_DL_TIMEOUT:
+ return BLK_STS_DURATION_LIMIT;
}
switch (host_byte(result)) {
@@ -803,6 +803,8 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
blk_stat = BLK_STS_ZONE_OPEN_RESOURCE;
}
break;
+ case COMPLETED:
+ fallthrough;
default:
action = ACTION_FAIL;
break;
@@ -2151,6 +2153,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
* @sdev: SCSI device to be queried
* @dbd: set to prevent mode sense from returning block descriptors
* @modepage: mode page being requested
+ * @subpage: sub-page of the mode page being requested
* @buffer: request buffer (may not be smaller than eight bytes)
* @len: length of request buffer.
* @timeout: command timeout
@@ -2162,7 +2165,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
* Returns zero if successful, or a negative error number on failure
*/
int
-scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
+scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, int subpage,
unsigned char *buffer, int len, int timeout, int retries,
struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr)
{
@@ -2182,6 +2185,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
dbd = sdev->set_dbd_for_ms ? 8 : dbd;
cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */
cmd[2] = modepage;
+ cmd[3] = subpage;
sshdr = exec_args.sshdr;