diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0df15cb738d2..0dbf25512778 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1642,8 +1642,18 @@ static blk_status_t scsi_mq_prep_fn(struct request *req) | |||
1642 | 1642 | ||
1643 | static void scsi_mq_done(struct scsi_cmnd *cmd) | 1643 | static void scsi_mq_done(struct scsi_cmnd *cmd) |
1644 | { | 1644 | { |
1645 | if (unlikely(test_and_set_bit(SCMD_STATE_COMPLETE, &cmd->state))) | ||
1646 | return; | ||
1645 | trace_scsi_dispatch_cmd_done(cmd); | 1647 | trace_scsi_dispatch_cmd_done(cmd); |
1646 | blk_mq_complete_request(cmd->request); | 1648 | |
1649 | /* | ||
1650 | * If the block layer didn't complete the request due to a timeout | ||
1651 | * injection, scsi must clear its internal completed state so that the | ||
1652 | * timeout handler will see it needs to escalate its own error | ||
1653 | * recovery. | ||
1654 | */ | ||
1655 | if (unlikely(!blk_mq_complete_request(cmd->request))) | ||
1656 | clear_bit(SCMD_STATE_COMPLETE, &cmd->state); | ||
1647 | } | 1657 | } |
1648 | 1658 | ||
1649 | static void scsi_mq_put_budget(struct blk_mq_hw_ctx *hctx) | 1659 | static void scsi_mq_put_budget(struct blk_mq_hw_ctx *hctx) |
@@ -1702,6 +1712,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
1702 | if (!scsi_host_queue_ready(q, shost, sdev)) | 1712 | if (!scsi_host_queue_ready(q, shost, sdev)) |
1703 | goto out_dec_target_busy; | 1713 | goto out_dec_target_busy; |
1704 | 1714 | ||
1715 | clear_bit(SCMD_STATE_COMPLETE, &cmd->state); | ||
1705 | if (!(req->rq_flags & RQF_DONTPREP)) { | 1716 | if (!(req->rq_flags & RQF_DONTPREP)) { |
1706 | ret = scsi_mq_prep_fn(req); | 1717 | ret = scsi_mq_prep_fn(req); |
1707 | if (ret != BLK_STS_OK) | 1718 | if (ret != BLK_STS_OK) |