From b84b6ec0f9767c82d0cfe5b2ac2c41de6b3d37e8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 3 Feb 2022 21:29:25 +0100 Subject: scsi: core: Add scsi_done_direct() for immediate completion Add scsi_done_direct() which behaves like scsi_done() except that it invokes blk_mq_complete_request_direct() in order to complete the request. Callers from process context can complete the request directly instead waking ksoftirqd. Link: https://lore.kernel.org/r/Yfw7JaszshmfYa1d@flow Reviewed-by: Bart Van Assche Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- include/scsi/scsi_cmnd.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/scsi') diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 6794d7322cbd..ff1c4b51f7ae 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -168,6 +168,7 @@ static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) } void scsi_done(struct scsi_cmnd *cmd); +void scsi_done_direct(struct scsi_cmnd *cmd); extern void scsi_finish_command(struct scsi_cmnd *cmd); -- cgit v1.2.3 From 03e4383c7ce36ac400489c8fe84724470a8251e9 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 7 Feb 2022 22:12:31 -0800 Subject: scsi: ibmvscsis: Silence -Warray-bounds warning Instead of doing a cast to storage that is too small, add a union for the high 64 bits. Silences the warnings under -Warray-bounds: drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c: In function 'ibmvscsis_send_messages': drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:1934:44: error: array subscript 'struct viosrp_crq[0]' is partly outside array bounds of 'u64[1]' {aka 'long long unsigned int[1]'} [-Werror=array-bounds] 1934 | crq->valid = VALID_CMD_RESP_EL; | ^~ drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c:1875:13: note: while referencing 'msg_hi' 1875 | u64 msg_hi = 0; | ^~~~~~ There is no change to the resulting binary instructions. Link: https://lore.kernel.org/lkml/20220125142430.75c3160e@canb.auug.org.au Link: https://lore.kernel.org/r/20220208061231.3429486-1-keescook@chromium.org Cc: Michael Cyr Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: Tyrel Datwyler Cc: linux-scsi@vger.kernel.org Cc: target-devel@vger.kernel.org Reported-by: Stephen Rothwell Reviewed-by: Tyrel Datwyler Signed-off-by: Kees Cook Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 9 +++------ include/scsi/viosrp.h | 17 +++++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 61f06f6885a5..80238e6a3c98 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -1872,11 +1872,8 @@ static void srp_snd_msg_failed(struct scsi_info *vscsi, long rc) */ static void ibmvscsis_send_messages(struct scsi_info *vscsi) { - u64 msg_hi = 0; - /* note do not attempt to access the IU_data_ptr with this pointer - * it is not valid - */ - struct viosrp_crq *crq = (struct viosrp_crq *)&msg_hi; + struct viosrp_crq empty_crq = { }; + struct viosrp_crq *crq = &empty_crq; struct ibmvscsis_cmd *cmd, *nxt; long rc = ADAPT_SUCCESS; bool retry = false; @@ -1940,7 +1937,7 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi) crq->IU_length = cpu_to_be16(cmd->rsp.len); rc = h_send_crq(vscsi->dma_dev->unit_address, - be64_to_cpu(msg_hi), + be64_to_cpu(crq->high), be64_to_cpu(cmd->rsp.tag)); dev_dbg(&vscsi->dev, "send_messages: cmd %p, tag 0x%llx, rc %ld\n", diff --git a/include/scsi/viosrp.h b/include/scsi/viosrp.h index c978133c83e3..6c5559d2b285 100644 --- a/include/scsi/viosrp.h +++ b/include/scsi/viosrp.h @@ -70,12 +70,17 @@ enum viosrp_crq_status { }; struct viosrp_crq { - u8 valid; /* used by RPA */ - u8 format; /* SCSI vs out-of-band */ - u8 reserved; - u8 status; /* non-scsi failure? (e.g. DMA failure) */ - __be16 timeout; /* in seconds */ - __be16 IU_length; /* in bytes */ + union { + __be64 high; /* High 64 bits */ + struct { + u8 valid; /* used by RPA */ + u8 format; /* SCSI vs out-of-band */ + u8 reserved; + u8 status; /* non-scsi failure? (e.g. DMA failure) */ + __be16 timeout; /* in seconds */ + __be16 IU_length; /* in bytes */ + }; + }; __be64 IU_data_ptr; /* the TCE for transferring data */ }; -- cgit v1.2.3 From 26fc0ea74fcb9b76b41f5e9b89728cd1c01559cd Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 10 Feb 2022 18:43:24 +0800 Subject: scsi: libsas: Drop SAS_TASK_AT_INITIATOR This flag is now only ever set, so delete it. This also avoids a use-after-free in the pm8001 queue path, as reported in the following: https://lore.kernel.org/linux-scsi/c3cb7228-254e-9584-182b-007ac5e6fe0a@huawei.com/T/#m28c94c6d3ff582ec4a9fa54819180740e8bd4cfb https://lore.kernel.org/linux-scsi/0cc0c435-b4f2-9c76-258d-865ba50a29dd@huawei.com/ [mkp: checkpatch + two SAS_TASK_AT_INITIATOR references] Link: https://lore.kernel.org/r/1644489804-85730-3-git-send-email-john.garry@huawei.com Reviewed-by: Damien Le Moal Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/aic94xx/aic94xx_task.c | 9 --------- drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +-- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +-- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +-- drivers/scsi/isci/request.c | 3 +-- drivers/scsi/isci/task.c | 10 +++------- drivers/scsi/mvsas/mv_sas.c | 6 +----- drivers/scsi/pm8001/pm8001_hwi.c | 8 -------- drivers/scsi/pm8001/pm8001_sas.c | 4 ---- drivers/scsi/pm8001/pm80xx_hwi.c | 6 ------ include/scsi/libsas.h | 1 - 12 files changed, 9 insertions(+), 55 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index c6b63eae28f5..ed119a3f6f2e 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -322,7 +322,6 @@ Again: spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags &= ~SAS_TASK_STATE_PENDING; - task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; task->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { struct completion *completion = ascb->completion; @@ -532,7 +531,6 @@ int asd_execute_task(struct sas_task *task, gfp_t gfp_flags) struct sas_task *t = task; struct asd_ascb *ascb = NULL, *a; struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha; - unsigned long flags; res = asd_can_queue(asd_ha, 1); if (res) @@ -575,10 +573,6 @@ int asd_execute_task(struct sas_task *task, gfp_t gfp_flags) } if (res) goto out_err_unmap; - - spin_lock_irqsave(&t->task_state_lock, flags); - t->task_state_flags |= SAS_TASK_AT_INITIATOR; - spin_unlock_irqrestore(&t->task_state_lock, flags); } list_del_init(&alist); @@ -597,9 +591,6 @@ out_err_unmap: if (a == b) break; t = a->uldd_task; - spin_lock_irqsave(&t->task_state_lock, flags); - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; - spin_unlock_irqrestore(&t->task_state_lock, flags); switch (t->task_proto) { case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index a05ec7aece5a..5aaf7217a3a6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -406,7 +406,6 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, struct hisi_sas_cmd_hdr *cmd_hdr_base; int dlvry_queue_slot, dlvry_queue; struct sas_task *task = slot->task; - unsigned long flags; int wr_q_index; spin_lock(&dq->lock); @@ -460,10 +459,6 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, break; } - spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags |= SAS_TASK_AT_INITIATOR; - spin_unlock_irqrestore(&task->task_state_lock, flags); - WRITE_ONCE(slot->ready, 1); spin_lock(&dq->lock); @@ -1038,8 +1033,7 @@ static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, struct sas_task ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags &= - ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; if (!slot->is_internal && task->task_proto != SAS_PROTOCOL_SMP) task->task_state_flags |= SAS_TASK_STATE_DONE; spin_unlock_irqrestore(&task->task_state_lock, flags); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 3059d19e4368..6914e992a02e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1200,8 +1200,7 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba, sas_dev = device->lldd_dev; spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags &= - ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; task->task_state_flags |= SAS_TASK_STATE_DONE; spin_unlock_irqrestore(&task->task_state_lock, flags); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 64ed3e472e65..eaaf9e8b4ca4 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2344,8 +2344,7 @@ static void slot_complete_v2_hw(struct hisi_hba *hisi_hba, sas_dev = device->lldd_dev; spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags &= - ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; spin_unlock_irqrestore(&task->task_state_lock, flags); memset(ts, 0, sizeof(*ts)); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index a45ef9a5e12e..e89baf24f3d6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2217,8 +2217,7 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba, sas_dev = device->lldd_dev; spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags &= - ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; spin_unlock_irqrestore(&task->task_state_lock, flags); memset(ts, 0, sizeof(*ts)); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index ad63704b660e..92394884fbeb 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -2934,8 +2934,7 @@ static void isci_request_io_request_complete(struct isci_host *ihost, if (test_bit(IREQ_COMPLETE_IN_TARGET, &request->flags)) { /* Normal notification (task_done) */ task->task_state_flags |= SAS_TASK_STATE_DONE; - task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR | - SAS_TASK_STATE_PENDING); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; } spin_unlock_irqrestore(&task->task_state_lock, task_flags); diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 14738702d4c9..c82d07978532 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -91,8 +91,7 @@ static void isci_task_refuse(struct isci_host *ihost, struct sas_task *task, /* Normal notification (task_done) */ task->task_state_flags |= SAS_TASK_STATE_DONE; - task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR | - SAS_TASK_STATE_PENDING); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; task->lldd_task = NULL; spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -164,7 +163,6 @@ int isci_task_execute_task(struct sas_task *task, gfp_t gfp_flags) } else { struct isci_request *ireq; - task->task_state_flags |= SAS_TASK_AT_INITIATOR; /* do common allocation and init of request object. */ ireq = isci_io_request_from_tag(ihost, task, tag); spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -531,8 +529,7 @@ int isci_task_abort_task(struct sas_task *task) */ spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags |= SAS_TASK_STATE_DONE; - task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR | - SAS_TASK_STATE_PENDING); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; spin_unlock_irqrestore(&task->task_state_lock, flags); ret = TMF_RESP_FUNC_COMPLETE; @@ -580,8 +577,7 @@ int isci_task_abort_task(struct sas_task *task) test_bit(IDEV_GONE, &idev->flags)); spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR | - SAS_TASK_STATE_PENDING); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; task->task_state_flags |= SAS_TASK_STATE_DONE; spin_unlock_irqrestore(&task->task_state_lock, flags); diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 1e52bc7febfa..a8d1f3dd607a 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -815,9 +815,6 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf slot->port = tei.port; task->lldd_task = slot; list_add_tail(&slot->entry, &tei.port->list); - spin_lock(&task->task_state_lock); - task->task_state_flags |= SAS_TASK_AT_INITIATOR; - spin_unlock(&task->task_state_lock); mvi_dev->running_req++; ++(*pass); @@ -1721,8 +1718,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) mvi_dev = dev->lldd_dev; spin_lock(&task->task_state_lock); - task->task_state_flags &= - ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); + task->task_state_flags &= ~SAS_TASK_STATE_PENDING; task->task_state_flags |= SAS_TASK_STATE_DONE; /* race condition*/ aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED; diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index c814e5071712..a9decac0b5cc 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1561,7 +1561,6 @@ void pm8001_work_fn(struct work_struct *work) atomic_dec(&pm8001_dev->running_req); spin_lock_irqsave(&t->task_state_lock, flags1); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags1); @@ -2105,7 +2104,6 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) psspPayload->ssp_resp_iu.status); spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2273,7 +2271,6 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2665,7 +2662,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2855,7 +2851,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -3040,7 +3035,6 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -3714,7 +3708,6 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; spin_unlock_irqrestore(&t->task_state_lock, flags); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); @@ -4354,7 +4347,6 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_SAM_STAT_GOOD; task->task_state_flags &= ~SAS_TASK_STATE_PENDING; - task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; task->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 160ee8b228c9..b3530f53df25 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -487,9 +487,6 @@ static int pm8001_task_exec(struct sas_task *task, goto err_out_tag; } /* TODO: select normal or high priority */ - spin_lock(&t->task_state_lock); - t->task_state_flags |= SAS_TASK_AT_INITIATOR; - spin_unlock(&t->task_state_lock); } while (0); rc = 0; goto out_done; @@ -978,7 +975,6 @@ void pm8001_open_reject_retry( atomic_dec(&pm8001_dev->running_req); spin_lock_irqsave(&task->task_state_lock, flags1); task->task_state_flags &= ~SAS_TASK_STATE_PENDING; - task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; task->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index bbf538fe15b3..26b64524e327 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -2178,7 +2178,6 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) psspPayload->ssp_resp_iu.status); spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2362,7 +2361,6 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2787,7 +2785,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -3010,7 +3007,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -3225,7 +3221,6 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; - t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -4735,7 +4730,6 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_SAM_STAT_GOOD; task->task_state_flags &= ~SAS_TASK_STATE_PENDING; - task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; task->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 698f2032807b..549232d66b40 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -617,7 +617,6 @@ struct sas_task_slow { #define SAS_TASK_STATE_DONE 2 #define SAS_TASK_STATE_ABORTED 4 #define SAS_TASK_NEED_DEV_RESET 8 -#define SAS_TASK_AT_INITIATOR 16 extern struct sas_task *sas_alloc_task(gfp_t flags); extern struct sas_task *sas_alloc_slow_task(gfp_t flags); -- cgit v1.2.3 From 26d4a969dd0516da2d25e1e4dc5632853c774c17 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 11 Feb 2022 14:42:55 +0800 Subject: scsi: libsas: Use void for sas_discover_event() return code The callers of function sas_discover_event() do not check its return value. The function also only ever returns 0, so use void instead. Link: https://lore.kernel.org/r/1644561778-183074-2-git-send-email-chenxiang66@hisilicon.com Reviewed-by: John Garry Signed-off-by: Xiang Chen Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_discover.c | 6 ++---- include/scsi/libsas.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 758213694091..d5bc1314c341 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -545,19 +545,17 @@ static void sas_chain_event(int event, unsigned long *pending, } } -int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) +void sas_discover_event(struct asd_sas_port *port, enum discover_event ev) { struct sas_discovery *disc; if (!port) - return 0; + return; disc = &port->disc; BUG_ON(ev >= DISC_NUM_EVENTS); sas_chain_event(ev, &disc->pending, &disc->disc_work[ev].work, port->ha); - - return 0; } /** diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 549232d66b40..fad328d3a551 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -684,7 +684,7 @@ int sas_ex_revalidate_domain(struct domain_device *); void sas_unregister_domain_devices(struct asd_sas_port *port, int gone); void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *); -int sas_discover_event(struct asd_sas_port *, enum discover_event ev); +void sas_discover_event(struct asd_sas_port *, enum discover_event ev); int sas_discover_sata(struct domain_device *); int sas_discover_end_dev(struct domain_device *); -- cgit v1.2.3 From 3a20e64281fd481f59c5c188d60632ef1d3264ea Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 11 Feb 2022 14:42:57 +0800 Subject: scsi: libsas: Remove unused parameter for function sas_ata_eh() Input parameter work_q is not unused in function sas_ata_eh(), so remove it. Link: https://lore.kernel.org/r/1644561778-183074-4-git-send-email-chenxiang66@hisilicon.com Reviewed-by: John Garry Signed-off-by: Xiang Chen Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_ata.c | 3 +-- drivers/scsi/libsas/sas_scsi_host.c | 2 +- include/scsi/sas_ata.h | 6 ++---- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 8dbd5a771824..e0030a093994 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -782,8 +782,7 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost) sas_enable_revalidation(sas_ha); } -void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, - struct list_head *done_q) +void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q) { struct scsi_cmnd *cmd, *n; struct domain_device *eh_dev; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index fb19e739a39c..bcb391b0c7ed 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -757,7 +757,7 @@ retry: * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any * command we see here has no sas_task and is thus unknown to the HA. */ - sas_ata_eh(shost, &eh_work_q, &ha->eh_done_q); + sas_ata_eh(shost, &eh_work_q); if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q)) scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q); diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h index 416c9c47d0e7..21e7c10c6295 100644 --- a/include/scsi/sas_ata.h +++ b/include/scsi/sas_ata.h @@ -25,8 +25,7 @@ int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy); int sas_ata_init(struct domain_device *dev); void sas_ata_task_abort(struct sas_task *task); void sas_ata_strategy_handler(struct Scsi_Host *shost); -void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, - struct list_head *done_q); +void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q); void sas_ata_schedule_reset(struct domain_device *dev); void sas_ata_wait_eh(struct domain_device *dev); void sas_probe_sata(struct asd_sas_port *port); @@ -52,8 +51,7 @@ static inline void sas_ata_strategy_handler(struct Scsi_Host *shost) { } -static inline void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, - struct list_head *done_q) +static inline void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q) { } -- cgit v1.2.3 From 23406e4d1f1e4653ec16b546d9480268ef284634 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Fri, 11 Feb 2022 14:42:58 +0800 Subject: scsi: Remove unused member cmd_pool for structure scsi_host_template After commit e9c787e65c0c ("scsi: allocate scsi_cmnd structures as part of struct request"), the member cmd_pool in structure scsi_host_template is not used, so remove it. Link: https://lore.kernel.org/r/1644561778-183074-5-git-send-email-chenxiang66@hisilicon.com Reviewed-by: John Garry Signed-off-by: Xiang Chen Signed-off-by: Martin K. Petersen --- include/scsi/scsi_host.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/scsi') diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 72e1a347baa6..667d889b92b5 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -16,7 +16,6 @@ struct completion; struct module; struct scsi_cmnd; struct scsi_device; -struct scsi_host_cmd_pool; struct scsi_target; struct Scsi_Host; struct scsi_transport_template; @@ -493,8 +492,6 @@ struct scsi_host_template { */ u64 vendor_id; - struct scsi_host_cmd_pool *cmd_pool; - /* Delay for runtime autosuspend */ int rpm_autosuspend_delay; }; -- cgit v1.2.3 From 1d6049a3b14feb39c8d6c8f538a711dcc54f88e0 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:30 +0800 Subject: scsi: libsas: Use enum for response frame DATAPRES field As defined in table 126 of the SAS spec 1.1, use an enum for the DATAPRES field, which makes reading the code easier. Also change sas_ssp_task_response() to use a switch statement, which is more suitable (than if-else), as suggested by Christoph. Link: https://lore.kernel.org/r/1645112566-115804-3-git-send-email-john.garry@huawei.com Suggested-by: Xiang Chen Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Jack Wang Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/aic94xx/aic94xx_tmf.c | 2 +- drivers/scsi/isci/request.c | 7 ++++--- drivers/scsi/libsas/sas_task.c | 14 +++++++++----- drivers/scsi/mvsas/mv_sas.c | 2 +- include/scsi/sas.h | 7 +++++++ 5 files changed, 22 insertions(+), 10 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index 0eb6e206a2b4..2ba91eaaf0ee 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c @@ -287,7 +287,7 @@ static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb, fh = edb->vaddr + 16; ru = edb->vaddr + 16 + sizeof(*fh); res = ru->status; - if (ru->datapres == 1) /* Response data present */ + if (ru->datapres == SAS_DATAPRES_RESPONSE_DATA) res = ru->resp_data[3]; #if 0 ascb->tag = fh->tag; diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 92394884fbeb..ac17e3a35d2c 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1047,7 +1047,8 @@ request_started_state_tc_event(struct isci_request *ireq, resp_iu = &ireq->ssp.rsp; datapres = resp_iu->datapres; - if (datapres == 1 || datapres == 2) { + if (datapres == SAS_DATAPRES_RESPONSE_DATA || + datapres == SAS_DATAPRES_SENSE_DATA) { ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; ireq->sci_status = SCI_FAILURE_IO_RESPONSE_VALID; } else { @@ -1730,8 +1731,8 @@ sci_io_request_frame_handler(struct isci_request *ireq, resp_iu = &ireq->ssp.rsp; - if (resp_iu->datapres == 0x01 || - resp_iu->datapres == 0x02) { + if (resp_iu->datapres == SAS_DATAPRES_RESPONSE_DATA || + resp_iu->datapres == SAS_DATAPRES_SENSE_DATA) { ireq->scu_status = SCU_TASK_DONE_CHECK_RESPONSE; ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR; } else { diff --git a/drivers/scsi/libsas/sas_task.c b/drivers/scsi/libsas/sas_task.c index 2966ead1d421..e9d291007817 100644 --- a/drivers/scsi/libsas/sas_task.c +++ b/drivers/scsi/libsas/sas_task.c @@ -15,11 +15,14 @@ void sas_ssp_task_response(struct device *dev, struct sas_task *task, tstat->resp = SAS_TASK_COMPLETE; - if (iu->datapres == 0) + switch (iu->datapres) { + case SAS_DATAPRES_NO_DATA: tstat->stat = iu->status; - else if (iu->datapres == 1) + break; + case SAS_DATAPRES_RESPONSE_DATA: tstat->stat = iu->resp_data[3]; - else if (iu->datapres == 2) { + break; + case SAS_DATAPRES_SENSE_DATA: tstat->stat = SAS_SAM_STAT_CHECK_CONDITION; tstat->buf_valid_size = min_t(int, SAS_STATUS_BUF_SIZE, @@ -29,10 +32,11 @@ void sas_ssp_task_response(struct device *dev, struct sas_task *task, if (iu->status != SAM_STAT_CHECK_CONDITION) dev_warn(dev, "dev %016llx sent sense data, but stat(0x%x) is not CHECK CONDITION\n", SAS_ADDR(task->dev->sas_addr), iu->status); - } - else + break; + default: /* when datapres contains corrupt/unknown value... */ tstat->stat = SAS_SAM_STAT_CHECK_CONDITION; + } } EXPORT_SYMBOL_GPL(sas_ssp_task_response); diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index a8d1f3dd607a..b48ae26e29a9 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1638,7 +1638,7 @@ static void mvs_set_sense(u8 *buffer, int len, int d_sense, static void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu, u8 key, u8 asc, u8 asc_q) { - iu->datapres = 2; + iu->datapres = SAS_DATAPRES_SENSE_DATA; iu->response_data_len = 0; iu->sense_data_len = 17; iu->status = 02; diff --git a/include/scsi/sas.h b/include/scsi/sas.h index 64154c1fed02..332a463d08ef 100644 --- a/include/scsi/sas.h +++ b/include/scsi/sas.h @@ -191,6 +191,13 @@ enum sas_gpio_reg_type { SAS_GPIO_REG_TX_GP = 4, }; +/* Response frame DATAPRES field */ +enum { + SAS_DATAPRES_NO_DATA = 0, + SAS_DATAPRES_RESPONSE_DATA = 1, + SAS_DATAPRES_SENSE_DATA = 2, +}; + struct dev_to_host_fis { u8 fis_type; /* 0x34 */ u8 flags; -- cgit v1.2.3 From 25882c82f850e3e972a973e0af310b3e58de38fd Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:31 +0800 Subject: scsi: libsas: Delete lldd_clear_aca callback This callback is never called, so remove support. Link: https://lore.kernel.org/r/1645112566-115804-4-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Jack Wang Reviewed-by: Christoph Hellwig Reviewed-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- Documentation/scsi/libsas.rst | 2 -- drivers/scsi/aic94xx/aic94xx.h | 1 - drivers/scsi/aic94xx/aic94xx_init.c | 1 - drivers/scsi/aic94xx/aic94xx_tmf.c | 9 --------- drivers/scsi/hisi_sas/hisi_sas_main.c | 12 ------------ drivers/scsi/isci/init.c | 1 - drivers/scsi/isci/task.c | 18 ------------------ drivers/scsi/isci/task.h | 4 ---- drivers/scsi/mvsas/mv_init.c | 1 - drivers/scsi/mvsas/mv_sas.c | 11 ----------- drivers/scsi/mvsas/mv_sas.h | 1 - drivers/scsi/pm8001/pm8001_init.c | 1 - drivers/scsi/pm8001/pm8001_sas.c | 8 -------- drivers/scsi/pm8001/pm8001_sas.h | 1 - include/scsi/libsas.h | 1 - 15 files changed, 72 deletions(-) (limited to 'include/scsi') diff --git a/Documentation/scsi/libsas.rst b/Documentation/scsi/libsas.rst index 6589dfefbc02..305a253d5c3b 100644 --- a/Documentation/scsi/libsas.rst +++ b/Documentation/scsi/libsas.rst @@ -207,7 +207,6 @@ Management Functions (TMFs) described in SAM:: /* Task Management Functions. Must be called from process context. */ int (*lldd_abort_task)(struct sas_task *); int (*lldd_abort_task_set)(struct domain_device *, u8 *lun); - int (*lldd_clear_aca)(struct domain_device *, u8 *lun); int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); int (*lldd_I_T_nexus_reset)(struct domain_device *); int (*lldd_lu_reset)(struct domain_device *, u8 *lun); @@ -262,7 +261,6 @@ can look like this (called last thing from probe()) my_ha->sas_ha.lldd_abort_task = my_abort_task; my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set; - my_ha->sas_ha.lldd_clear_aca = my_clear_aca; my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set; my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2) my_ha->sas_ha.lldd_lu_reset = my_lu_reset; diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h index 8f24180646c2..f595bc2ee45e 100644 --- a/drivers/scsi/aic94xx/aic94xx.h +++ b/drivers/scsi/aic94xx/aic94xx.h @@ -60,7 +60,6 @@ void asd_set_dmamode(struct domain_device *dev); /* ---------- TMFs ---------- */ int asd_abort_task(struct sas_task *); int asd_abort_task_set(struct domain_device *, u8 *lun); -int asd_clear_aca(struct domain_device *, u8 *lun); int asd_clear_task_set(struct domain_device *, u8 *lun); int asd_lu_reset(struct domain_device *, u8 *lun); int asd_I_T_nexus_reset(struct domain_device *dev); diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 7a78606598c4..954d0c5ae2e2 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -960,7 +960,6 @@ static struct sas_domain_function_template aic94xx_transport_functions = { .lldd_abort_task = asd_abort_task, .lldd_abort_task_set = asd_abort_task_set, - .lldd_clear_aca = asd_clear_aca, .lldd_clear_task_set = asd_clear_task_set, .lldd_I_T_nexus_reset = asd_I_T_nexus_reset, .lldd_lu_reset = asd_lu_reset, diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index 2ba91eaaf0ee..27d32b8c2987 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c @@ -644,15 +644,6 @@ int asd_abort_task_set(struct domain_device *dev, u8 *lun) return res; } -int asd_clear_aca(struct domain_device *dev, u8 *lun) -{ - int res = asd_initiate_ssp_tmf(dev, lun, TMF_CLEAR_ACA, 0); - - if (res == TMF_RESP_FUNC_COMPLETE) - asd_clear_nexus_I_T_L(dev, lun); - return res; -} - int asd_clear_task_set(struct domain_device *dev, u8 *lun) { int res = asd_initiate_ssp_tmf(dev, lun, TMF_CLEAR_TASK_SET, 0); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 1873707ca599..ad630694cc4f 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1793,17 +1793,6 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) return rc; } -static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun) -{ - struct hisi_sas_tmf_task tmf_task; - int rc; - - tmf_task.tmf = TMF_CLEAR_ACA; - rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); - - return rc; -} - #define I_T_NEXUS_RESET_PHYUP_TIMEOUT (2 * HZ) static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) @@ -2333,7 +2322,6 @@ static struct sas_domain_function_template hisi_sas_transport_ops = { .lldd_control_phy = hisi_sas_control_phy, .lldd_abort_task = hisi_sas_abort_task, .lldd_abort_task_set = hisi_sas_abort_task_set, - .lldd_clear_aca = hisi_sas_clear_aca, .lldd_I_T_nexus_reset = hisi_sas_I_T_nexus_reset, .lldd_lu_reset = hisi_sas_lu_reset, .lldd_query_task = hisi_sas_query_task, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index aade707c5553..e294d5d961eb 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -193,7 +193,6 @@ static struct sas_domain_function_template isci_transport_ops = { /* Task Management Functions. Must be called from process context. */ .lldd_abort_task = isci_task_abort_task, .lldd_abort_task_set = isci_task_abort_task_set, - .lldd_clear_aca = isci_task_clear_aca, .lldd_clear_task_set = isci_task_clear_task_set, .lldd_I_T_nexus_reset = isci_task_I_T_nexus_reset, .lldd_lu_reset = isci_task_lu_reset, diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index c82d07978532..c514b20293b2 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -620,24 +620,6 @@ int isci_task_abort_task_set( } -/** - * isci_task_clear_aca() - This function is one of the SAS Domain Template - * functions. This is one of the Task Management functoins called by libsas. - * @d_device: This parameter specifies the domain device associated with this - * request. - * @lun: This parameter specifies the lun associated with this request. - * - * status, zero indicates success. - */ -int isci_task_clear_aca( - struct domain_device *d_device, - u8 *lun) -{ - return TMF_RESP_FUNC_FAILED; -} - - - /** * isci_task_clear_task_set() - This function is one of the SAS Domain Template * functions. This is one of the Task Management functoins called by libsas. diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index cae168b8916f..f96633fa6939 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -140,10 +140,6 @@ int isci_task_abort_task_set( struct domain_device *d_device, u8 *lun); -int isci_task_clear_aca( - struct domain_device *d_device, - u8 *lun); - int isci_task_clear_task_set( struct domain_device *d_device, u8 *lun); diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 44df7c03aab8..3fe0a9351cea 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -64,7 +64,6 @@ static struct sas_domain_function_template mvs_transport_ops = { .lldd_abort_task = mvs_abort_task, .lldd_abort_task_set = mvs_abort_task_set, - .lldd_clear_aca = mvs_clear_aca, .lldd_clear_task_set = mvs_clear_task_set, .lldd_I_T_nexus_reset = mvs_I_T_nexus_reset, .lldd_lu_reset = mvs_lu_reset, diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index b48ae26e29a9..e9182333e077 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1550,17 +1550,6 @@ int mvs_abort_task_set(struct domain_device *dev, u8 *lun) return rc; } -int mvs_clear_aca(struct domain_device *dev, u8 *lun) -{ - int rc = TMF_RESP_FUNC_FAILED; - struct mvs_tmf_task tmf_task; - - tmf_task.tmf = TMF_CLEAR_ACA; - rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); - - return rc; -} - int mvs_clear_task_set(struct domain_device *dev, u8 *lun) { int rc = TMF_RESP_FUNC_FAILED; diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 8ff976c9967e..fa654c73beee 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -441,7 +441,6 @@ int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time); int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags); int mvs_abort_task(struct sas_task *task); int mvs_abort_task_set(struct domain_device *dev, u8 *lun); -int mvs_clear_aca(struct domain_device *dev, u8 *lun); int mvs_clear_task_set(struct domain_device *dev, u8 * lun); void mvs_port_formed(struct asd_sas_phy *sas_phy); void mvs_port_deformed(struct asd_sas_phy *sas_phy); diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index d8a2121cb8d9..b8cf1bae4040 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -123,7 +123,6 @@ static struct sas_domain_function_template pm8001_transport_ops = { .lldd_abort_task = pm8001_abort_task, .lldd_abort_task_set = pm8001_abort_task_set, - .lldd_clear_aca = pm8001_clear_aca, .lldd_clear_task_set = pm8001_clear_task_set, .lldd_I_T_nexus_reset = pm8001_I_T_nexus_reset, .lldd_lu_reset = pm8001_lu_reset, diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 8c12fbb9c476..bd3513e1882e 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1358,14 +1358,6 @@ int pm8001_abort_task_set(struct domain_device *dev, u8 *lun) return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); } -int pm8001_clear_aca(struct domain_device *dev, u8 *lun) -{ - struct pm8001_tmf_task tmf_task; - - tmf_task.tmf = TMF_CLEAR_ACA; - return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); -} - int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) { struct pm8001_tmf_task tmf_task; diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index a17da1cebce1..3ea53a0d0cc1 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -649,7 +649,6 @@ int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time); int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags); int pm8001_abort_task(struct sas_task *task); int pm8001_abort_task_set(struct domain_device *dev, u8 *lun); -int pm8001_clear_aca(struct domain_device *dev, u8 *lun); int pm8001_clear_task_set(struct domain_device *dev, u8 *lun); int pm8001_dev_found(struct domain_device *dev); void pm8001_dev_gone(struct domain_device *dev); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index fad328d3a551..8026c1bb57ba 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -636,7 +636,6 @@ struct sas_domain_function_template { /* Task Management Functions. Must be called from process context. */ int (*lldd_abort_task)(struct sas_task *); int (*lldd_abort_task_set)(struct domain_device *, u8 *lun); - int (*lldd_clear_aca)(struct domain_device *, u8 *lun); int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); int (*lldd_I_T_nexus_reset)(struct domain_device *); int (*lldd_ata_check_ready)(struct domain_device *); -- cgit v1.2.3 From 2dd6801a671c0a82e756355d20669ad5bbe89073 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:32 +0800 Subject: scsi: libsas: Delete SAS_SG_ERR No LLDD sets exec status as SAS_SG_ERR, so remove support. Link: https://lore.kernel.org/r/1645112566-115804-5-git-send-email-john.garry@huawei.com Tested-by: Damien Le Moal Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_ata.c | 2 -- drivers/scsi/libsas/sas_scsi_host.c | 3 --- include/scsi/libsas.h | 1 - 3 files changed, 6 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index e0030a093994..71b42fe95b6f 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -52,8 +52,6 @@ static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts) case SAS_DATA_OVERRUN: case SAS_QUEUE_FULL: case SAS_DEVICE_UNKNOWN: - case SAS_SG_ERR: - return AC_ERR_INVALID; case SAS_OPEN_TO: case SAS_OPEN_REJECT: pr_warn("%s: Saw error %d. What to do?\n", diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 19cb954afd80..387083a16a79 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -67,9 +67,6 @@ static void sas_end_task(struct scsi_cmnd *sc, struct sas_task *task) case SAS_DEVICE_UNKNOWN: hs = DID_BAD_TARGET; break; - case SAS_SG_ERR: - hs = DID_PARITY; - break; case SAS_OPEN_REJECT: if (ts->open_rej_reason == SAS_OREJ_RSVD_RETRY) hs = DID_SOFT_ERROR; /* retry */ diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 8026c1bb57ba..cd2b2b67bf93 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -492,7 +492,6 @@ enum exec_status { SAS_INTERRUPTED, SAS_QUEUE_FULL, SAS_DEVICE_UNKNOWN, - SAS_SG_ERR, SAS_OPEN_REJECT, SAS_OPEN_TO, SAS_PROTO_RESPONSE, -- cgit v1.2.3 From bbfe82cdbaf84e6622ceb6f3447c8c4bb7dde7ab Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:35 +0800 Subject: scsi: libsas: Add struct sas_tmf_task Some of the LLDDs which use libsas have their own definition of a struct to hold TMF info, so add a common struct for libsas. Also add an interim force phy id field for hisi_sas driver, which will be removed once the STP "TMF" code is factored out. Even though some LLDDs (pm8001) use a u32 for the tag, u16 will be adequate, as that named driver only uses tags in range [0, 1024). Link: https://lore.kernel.org/r/1645112566-115804-8-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 9 +-------- drivers/scsi/hisi_sas/hisi_sas_main.c | 22 +++++++++++----------- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++-- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- drivers/scsi/mvsas/mv_defs.h | 5 ----- drivers/scsi/mvsas/mv_sas.c | 20 ++++++++++---------- drivers/scsi/pm8001/pm8001_hwi.c | 4 ++-- drivers/scsi/pm8001/pm8001_sas.c | 18 +++++++++--------- drivers/scsi/pm8001/pm8001_sas.h | 10 +++------- include/scsi/libsas.h | 9 +++++++++ 11 files changed, 49 insertions(+), 56 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 15a58c955516..fe0c15bbfca9 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -234,13 +234,6 @@ struct hisi_sas_device { spinlock_t lock; /* For protecting slots */ }; -struct hisi_sas_tmf_task { - int force_phy; - int phy_id; - u8 tmf; - u16 tag_of_task_to_be_managed; -}; - struct hisi_sas_slot { struct list_head entry; struct list_head delivery; @@ -259,7 +252,7 @@ struct hisi_sas_slot { dma_addr_t cmd_hdr_dma; struct timer_list internal_abort_timer; bool is_internal; - struct hisi_sas_tmf_task *tmf; + struct sas_tmf_task *tmf; /* Do not reorder/change members after here */ void *buf; dma_addr_t buf_dma; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 5bacf849c36a..88e641143b82 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -11,7 +11,7 @@ ((!dev) || (dev->dev_type == SAS_PHY_UNUSED)) static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, - u8 *lun, struct hisi_sas_tmf_task *tmf); + u8 *lun, struct sas_tmf_task *tmf); static int hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, struct domain_device *device, @@ -464,7 +464,7 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, } static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, - struct hisi_sas_tmf_task *tmf) + struct sas_tmf_task *tmf) { int n_elem = 0, n_elem_dif = 0, n_elem_req = 0; struct domain_device *device = task->dev; @@ -672,7 +672,7 @@ static int hisi_sas_init_device(struct domain_device *device) { int rc = TMF_RESP_FUNC_COMPLETE; struct scsi_lun lun; - struct hisi_sas_tmf_task tmf_task; + struct sas_tmf_task tmf_task; int retry = HISI_SAS_DISK_RECOVER_CNT; struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; @@ -1236,7 +1236,7 @@ static void hisi_sas_tmf_timedout(struct timer_list *t) #define INTERNAL_ABORT_TIMEOUT (6 * HZ) static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, void *parameter, u32 para_len, - struct hisi_sas_tmf_task *tmf) + struct sas_tmf_task *tmf) { struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_hba *hisi_hba = sas_dev->hisi_hba; @@ -1371,7 +1371,7 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; int s = sizeof(struct host_to_dev_fis); - struct hisi_sas_tmf_task tmf = {}; + struct sas_tmf_task tmf = {}; ata_for_each_link(link, ap, EDGE) { int pmp = sata_srst_pmp(link); @@ -1405,7 +1405,7 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) } static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, - u8 *lun, struct hisi_sas_tmf_task *tmf) + u8 *lun, struct sas_tmf_task *tmf) { struct sas_ssp_task ssp_task; @@ -1512,7 +1512,7 @@ static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba, struct asd_sas_port *sas_port, struct domain_device *device) { - struct hisi_sas_tmf_task tmf_task = { .force_phy = 1 }; + struct sas_tmf_task tmf_task = { .force_phy = 1 }; struct ata_port *ap = device->sata_dev.ap; struct device *dev = hisi_hba->dev; int s = sizeof(struct host_to_dev_fis); @@ -1664,7 +1664,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) static int hisi_sas_abort_task(struct sas_task *task) { struct scsi_lun lun; - struct hisi_sas_tmf_task tmf_task; + struct sas_tmf_task tmf_task; struct domain_device *device = task->dev; struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_hba *hisi_hba; @@ -1773,7 +1773,7 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) { struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; - struct hisi_sas_tmf_task tmf_task; + struct sas_tmf_task tmf_task; int rc; rc = hisi_sas_internal_task_abort(hisi_hba, device, @@ -1924,7 +1924,7 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) hisi_sas_release_task(hisi_hba, device); sas_put_local_phy(phy); } else { - struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET }; + struct sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET }; rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); if (rc == TMF_RESP_FUNC_COMPLETE) @@ -1982,7 +1982,7 @@ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha) static int hisi_sas_query_task(struct sas_task *task) { struct scsi_lun lun; - struct hisi_sas_tmf_task tmf_task; + struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED; if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 6914e992a02e..763888144aef 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -958,7 +958,7 @@ static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba, struct hisi_sas_port *port = slot->port; struct sas_ssp_task *ssp_task = &task->ssp_task; struct scsi_cmnd *scsi_cmnd = ssp_task->cmd; - struct hisi_sas_tmf_task *tmf = slot->tmf; + struct sas_tmf_task *tmf = slot->tmf; int has_data = 0, priority = !!tmf; u8 *buf_cmd, fburst = 0; u32 dw1, dw2; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index eaaf9e8b4ca4..5bab51dc21b3 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1742,7 +1742,7 @@ static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_port *port = slot->port; struct sas_ssp_task *ssp_task = &task->ssp_task; struct scsi_cmnd *scsi_cmnd = ssp_task->cmd; - struct hisi_sas_tmf_task *tmf = slot->tmf; + struct sas_tmf_task *tmf = slot->tmf; int has_data = 0, priority = !!tmf; u8 *buf_cmd; u32 dw1 = 0, dw2 = 0; @@ -2491,7 +2491,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; struct asd_sas_port *sas_port = device->port; struct hisi_sas_port *port = to_hisi_sas_port(sas_port); - struct hisi_sas_tmf_task *tmf = slot->tmf; + struct sas_tmf_task *tmf = slot->tmf; u8 *buf_cmd; int has_data = 0, hdr_tag = 0; u32 dw0, dw1 = 0, dw2 = 0; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index e472068cc256..a57f247481ed 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1219,7 +1219,7 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_port *port = slot->port; struct sas_ssp_task *ssp_task = &task->ssp_task; struct scsi_cmnd *scsi_cmnd = ssp_task->cmd; - struct hisi_sas_tmf_task *tmf = slot->tmf; + struct sas_tmf_task *tmf = slot->tmf; int has_data = 0, priority = !!tmf; unsigned char prot_op; u8 *buf_cmd; diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h index 199ab49aa047..7123a2efbf58 100644 --- a/drivers/scsi/mvsas/mv_defs.h +++ b/drivers/scsi/mvsas/mv_defs.h @@ -486,9 +486,4 @@ enum datapres_field { SENSE_DATA = 2, }; -/* define task management IU */ -struct mvs_tmf_task{ - u8 tmf; - u16 tag_of_task_to_be_managed; -}; #endif diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index e9182333e077..53509996db9f 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -556,7 +556,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi, static int mvs_task_prep_ssp(struct mvs_info *mvi, struct mvs_task_exec_info *tei, int is_tmf, - struct mvs_tmf_task *tmf) + struct sas_tmf_task *tmf) { struct sas_task *task = tei->task; struct mvs_cmd_hdr *hdr = tei->hdr; @@ -696,7 +696,7 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi, #define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == SAS_PHY_UNUSED))) static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf, - struct mvs_tmf_task *tmf, int *pass) + struct sas_tmf_task *tmf, int *pass) { struct domain_device *dev = task->dev; struct mvs_device *mvi_dev = dev->lldd_dev; @@ -839,7 +839,7 @@ prep_out: static int mvs_task_exec(struct sas_task *task, gfp_t gfp_flags, struct completion *completion, int is_tmf, - struct mvs_tmf_task *tmf) + struct sas_tmf_task *tmf) { struct mvs_info *mvi = NULL; u32 rc = 0; @@ -1277,7 +1277,7 @@ static void mvs_tmf_timedout(struct timer_list *t) #define MVS_TASK_TIMEOUT 20 static int mvs_exec_internal_tmf_task(struct domain_device *dev, - void *parameter, u32 para_len, struct mvs_tmf_task *tmf) + void *parameter, u32 para_len, struct sas_tmf_task *tmf) { int res, retry; struct sas_task *task = NULL; @@ -1352,7 +1352,7 @@ ex_err: } static int mvs_debug_issue_ssp_tmf(struct domain_device *dev, - u8 *lun, struct mvs_tmf_task *tmf) + u8 *lun, struct sas_tmf_task *tmf) { struct sas_ssp_task ssp_task; if (!(dev->tproto & SAS_PROTOCOL_SSP)) @@ -1384,7 +1384,7 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun) { unsigned long flags; int rc = TMF_RESP_FUNC_FAILED; - struct mvs_tmf_task tmf_task; + struct sas_tmf_task tmf_task; struct mvs_device * mvi_dev = dev->lldd_dev; struct mvs_info *mvi = mvi_dev->mvi_info; @@ -1428,7 +1428,7 @@ int mvs_query_task(struct sas_task *task) { u32 tag; struct scsi_lun lun; - struct mvs_tmf_task tmf_task; + struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED; if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { @@ -1465,7 +1465,7 @@ int mvs_query_task(struct sas_task *task) int mvs_abort_task(struct sas_task *task) { struct scsi_lun lun; - struct mvs_tmf_task tmf_task; + struct sas_tmf_task tmf_task; struct domain_device *dev = task->dev; struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; struct mvs_info *mvi; @@ -1542,7 +1542,7 @@ out: int mvs_abort_task_set(struct domain_device *dev, u8 *lun) { int rc; - struct mvs_tmf_task tmf_task; + struct sas_tmf_task tmf_task; tmf_task.tmf = TMF_ABORT_TASK_SET; rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); @@ -1553,7 +1553,7 @@ int mvs_abort_task_set(struct domain_device *dev, u8 *lun) int mvs_clear_task_set(struct domain_device *dev, u8 *lun) { int rc = TMF_RESP_FUNC_FAILED; - struct mvs_tmf_task tmf_task; + struct sas_tmf_task tmf_task; tmf_task.tmf = TMF_CLEAR_TASK_SET; rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 4683fee87b84..575c6ecfdce3 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -4602,7 +4602,7 @@ int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, * @tmf: task management function. */ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, - struct pm8001_ccb_info *ccb, struct pm8001_tmf_task *tmf) + struct pm8001_ccb_info *ccb, struct sas_tmf_task *tmf) { struct sas_task *task = ccb->task; struct domain_device *dev = task->dev; @@ -4614,7 +4614,7 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, memset(&sspTMCmd, 0, sizeof(sspTMCmd)); sspTMCmd.device_id = cpu_to_le32(pm8001_dev->device_id); - sspTMCmd.relate_tag = cpu_to_le32(tmf->tag_of_task_to_be_managed); + sspTMCmd.relate_tag = cpu_to_le32((u32)tmf->tag_of_task_to_be_managed); sspTMCmd.tmf = cpu_to_le32(tmf->tmf); memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8); sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index bd3513e1882e..a93b7f0bb358 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -336,7 +336,7 @@ static int pm8001_task_prep_ata(struct pm8001_hba_info *pm8001_ha, * @tmf: the task management IU */ static int pm8001_task_prep_ssp_tm(struct pm8001_hba_info *pm8001_ha, - struct pm8001_ccb_info *ccb, struct pm8001_tmf_task *tmf) + struct pm8001_ccb_info *ccb, struct sas_tmf_task *tmf) { return PM8001_CHIP_DISP->ssp_tm_req(pm8001_ha, ccb, tmf); } @@ -379,7 +379,7 @@ static int sas_find_local_port_id(struct domain_device *dev) * @tmf: the task management IU */ static int pm8001_task_exec(struct sas_task *task, - gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf) + gfp_t gfp_flags, int is_tmf, struct sas_tmf_task *tmf) { struct domain_device *dev = task->dev; struct pm8001_hba_info *pm8001_ha; @@ -728,7 +728,7 @@ static void pm8001_tmf_timedout(struct timer_list *t) * this function, note it is also with the task execute interface. */ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, - void *parameter, u32 para_len, struct pm8001_tmf_task *tmf) + void *parameter, u32 para_len, struct sas_tmf_task *tmf) { int res, retry; struct sas_task *task = NULL; @@ -919,7 +919,7 @@ void pm8001_dev_gone(struct domain_device *dev) } static int pm8001_issue_ssp_tmf(struct domain_device *dev, - u8 *lun, struct pm8001_tmf_task *tmf) + u8 *lun, struct sas_tmf_task *tmf) { struct sas_ssp_task ssp_task; if (!(dev->tproto & SAS_PROTOCOL_SSP)) @@ -1120,7 +1120,7 @@ out: int pm8001_lu_reset(struct domain_device *dev, u8 *lun) { int rc = TMF_RESP_FUNC_FAILED; - struct pm8001_tmf_task tmf_task; + struct sas_tmf_task tmf_task; struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); DECLARE_COMPLETION_ONSTACK(completion_setstate); @@ -1149,7 +1149,7 @@ int pm8001_query_task(struct sas_task *task) { u32 tag = 0xdeadbeef; struct scsi_lun lun; - struct pm8001_tmf_task tmf_task; + struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED; if (unlikely(!task || !task->lldd_task || !task->dev)) return rc; @@ -1198,7 +1198,7 @@ int pm8001_abort_task(struct sas_task *task) struct pm8001_hba_info *pm8001_ha; struct scsi_lun lun; struct pm8001_device *pm8001_dev; - struct pm8001_tmf_task tmf_task; + struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED, ret; u32 phy_id, port_id; struct sas_task_slow slow_task; @@ -1352,7 +1352,7 @@ out: int pm8001_abort_task_set(struct domain_device *dev, u8 *lun) { - struct pm8001_tmf_task tmf_task; + struct sas_tmf_task tmf_task; tmf_task.tmf = TMF_ABORT_TASK_SET; return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); @@ -1360,7 +1360,7 @@ int pm8001_abort_task_set(struct domain_device *dev, u8 *lun) int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) { - struct pm8001_tmf_task tmf_task; + struct sas_tmf_task tmf_task; struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 3ea53a0d0cc1..0b1086042ca6 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -99,11 +99,7 @@ extern const struct pm8001_dispatch pm8001_80xx_dispatch; struct pm8001_hba_info; struct pm8001_ccb_info; struct pm8001_device; -/* define task management IU */ -struct pm8001_tmf_task { - u8 tmf; - u32 tag_of_task_to_be_managed; -}; + struct pm8001_ioctl_payload { u32 signature; u16 major_function; @@ -203,7 +199,7 @@ struct pm8001_dispatch { struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag); int (*ssp_tm_req)(struct pm8001_hba_info *pm8001_ha, - struct pm8001_ccb_info *ccb, struct pm8001_tmf_task *tmf); + struct pm8001_ccb_info *ccb, struct sas_tmf_task *tmf); int (*get_nvmd_req)(struct pm8001_hba_info *pm8001_ha, void *payload); int (*set_nvmd_req)(struct pm8001_hba_info *pm8001_ha, void *payload); int (*fw_flash_update_req)(struct pm8001_hba_info *pm8001_ha, @@ -687,7 +683,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload); int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload); int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, struct pm8001_ccb_info *ccb, - struct pm8001_tmf_task *tmf); + struct sas_tmf_task *tmf); int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index cd2b2b67bf93..7a55853fad7b 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -576,6 +576,15 @@ struct sas_ssp_task { struct scsi_cmnd *cmd; }; +struct sas_tmf_task { + u8 tmf; + u16 tag_of_task_to_be_managed; + + /* Temp */ + int force_phy; + int phy_id; +}; + struct sas_task { struct domain_device *dev; -- cgit v1.2.3 From 96e54376a8b27066d32ca36800318c43e6b6d2c5 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:36 +0800 Subject: scsi: libsas: Add sas_task.tmf Add a pointer to a sas_tmf_task to the sas_task struct, as this will be used when the common LLDD TMF code is factored out. Also set it for the LLDDs to store per-sas_task TMF info. Link: https://lore.kernel.org/r/1645112566-115804-9-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 16 ++++++---------- drivers/scsi/mvsas/mv_sas.c | 15 ++++++--------- drivers/scsi/pm8001/pm8001_sas.c | 28 ++++++++++------------------ include/scsi/libsas.h | 1 + 4 files changed, 23 insertions(+), 37 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 88e641143b82..bd40323f7053 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -463,8 +463,7 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, spin_unlock(&dq->lock); } -static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, - struct sas_tmf_task *tmf) +static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) { int n_elem = 0, n_elem_dif = 0, n_elem_req = 0; struct domain_device *device = task->dev; @@ -575,8 +574,8 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, slot->task = task; slot->port = port; - slot->tmf = tmf; - slot->is_internal = tmf; + slot->tmf = task->tmf; + slot->is_internal = task->tmf; /* protect task_prep and start_delivery sequence */ hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev, NULL); @@ -1106,11 +1105,6 @@ static void hisi_sas_dev_gone(struct domain_device *device) up(&hisi_hba->sem); } -static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) -{ - return hisi_sas_task_exec(task, gfp_flags, NULL); -} - static int hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no, struct sas_phy_linkrates *r) { @@ -1264,7 +1258,9 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, task->slow_task->timer.expires = jiffies + TASK_TIMEOUT; add_timer(&task->slow_task->timer); - res = hisi_sas_task_exec(task, GFP_KERNEL, tmf); + task->tmf = tmf; + + res = hisi_sas_queue_command(task, GFP_KERNEL); if (res) { del_timer_sync(&task->slow_task->timer); dev_err(dev, "abort tmf: executing internal task failed: %d\n", diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 53509996db9f..47fcd8de9ece 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -837,14 +837,14 @@ prep_out: return rc; } -static int mvs_task_exec(struct sas_task *task, gfp_t gfp_flags, - struct completion *completion, int is_tmf, - struct sas_tmf_task *tmf) +int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags) { struct mvs_info *mvi = NULL; u32 rc = 0; u32 pass = 0; unsigned long flags = 0; + struct sas_tmf_task *tmf = task->tmf; + int is_tmf = !!task->tmf; mvi = ((struct mvs_device *)task->dev->lldd_dev)->mvi_info; @@ -861,11 +861,6 @@ static int mvs_task_exec(struct sas_task *task, gfp_t gfp_flags, return rc; } -int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags) -{ - return mvs_task_exec(task, gfp_flags, NULL, 0, NULL); -} - static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc) { u32 slot_idx = rx_desc & RXQ_SLOT_MASK; @@ -1297,7 +1292,9 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev, task->slow_task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ; add_timer(&task->slow_task->timer); - res = mvs_task_exec(task, GFP_KERNEL, NULL, 1, tmf); + task->tmf = tmf; + + res = mvs_queue_command(task, GFP_KERNEL); if (res) { del_timer(&task->slow_task->timer); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index a93b7f0bb358..a53e4b54154f 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -371,15 +371,14 @@ static int sas_find_local_port_id(struct domain_device *dev) #define DEV_IS_GONE(pm8001_dev) \ ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))) + /** - * pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware. + * pm8001_queue_command - register for upper layer used, all IO commands sent + * to HBA are from this interface. * @task: the task to be execute. - * @gfp_flags: gfp_flags. - * @is_tmf: if it is task management task. - * @tmf: the task management IU + * @gfp_flags: gfp_flags */ -static int pm8001_task_exec(struct sas_task *task, - gfp_t gfp_flags, int is_tmf, struct sas_tmf_task *tmf) +int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags) { struct domain_device *dev = task->dev; struct pm8001_hba_info *pm8001_ha; @@ -390,6 +389,8 @@ static int pm8001_task_exec(struct sas_task *task, u32 tag = 0xdeadbeef, rc = 0, n_elem = 0; unsigned long flags = 0; enum sas_protocol task_proto = t->task_proto; + struct sas_tmf_task *tmf = task->tmf; + int is_tmf = !!task->tmf; if (!dev->port) { struct task_status_struct *tsm = &t->task_status; @@ -504,17 +505,6 @@ out_done: return rc; } -/** - * pm8001_queue_command - register for upper layer used, all IO commands sent - * to HBA are from this interface. - * @task: the task to be execute. - * @gfp_flags: gfp_flags - */ -int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags) -{ - return pm8001_task_exec(task, gfp_flags, 0, NULL); -} - /** * pm8001_ccb_task_free - free the sg for ssp and smp command, free the ccb. * @pm8001_ha: our hba card information @@ -749,7 +739,9 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ; add_timer(&task->slow_task->timer); - res = pm8001_task_exec(task, GFP_KERNEL, 1, tmf); + task->tmf = tmf; + + res = pm8001_queue_command(task, GFP_KERNEL); if (res) { del_timer(&task->slow_task->timer); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 7a55853fad7b..9c181ebccfee 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -610,6 +610,7 @@ struct sas_task { void *lldd_task; /* for use by LLDDs */ void *uldd_task; struct sas_task_slow *slow_task; + struct sas_tmf_task *tmf; }; struct sas_task_slow { -- cgit v1.2.3 From 2037a340314f4be8977563006476bd15c859eda2 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:39 +0800 Subject: scsi: libsas: Add TMF handler exec complete callback The pm8001 TMF handler has some special processing when the TMF completes, so add a callback and fill it in for the pm8001 driver. Link: https://lore.kernel.org/r/1645112566-115804-12-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_scsi_host.c | 3 +++ drivers/scsi/pm8001/pm8001_init.c | 1 + drivers/scsi/pm8001/pm8001_sas.c | 14 ++++++++++++++ drivers/scsi/pm8001/pm8001_sas.h | 1 + include/scsi/libsas.h | 3 +++ 5 files changed, 22 insertions(+) (limited to 'include/scsi') diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index af2dd95a2b28..0f599744738d 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -957,6 +957,9 @@ int sas_execute_tmf(struct domain_device *device, void *parameter, wait_for_completion(&task->slow_task->completion); + if (i->dft->lldd_tmf_exec_complete) + i->dft->lldd_tmf_exec_complete(device); + res = TMF_RESP_FUNC_FAILED; if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index b8cf1bae4040..8eef8f4de42f 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -128,6 +128,7 @@ static struct sas_domain_function_template pm8001_transport_ops = { .lldd_lu_reset = pm8001_lu_reset, .lldd_query_task = pm8001_query_task, .lldd_port_formed = pm8001_port_formed, + .lldd_tmf_exec_complete = pm8001_setds_completion, }; /** diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index a53e4b54154f..69da7246ea20 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1376,3 +1376,17 @@ void pm8001_port_formed(struct asd_sas_phy *sas_phy) } sas_port->lldd_port = port; } + +void pm8001_setds_completion(struct domain_device *dev) +{ + struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); + struct pm8001_device *pm8001_dev = dev->lldd_dev; + DECLARE_COMPLETION_ONSTACK(completion_setstate); + + if (pm8001_ha->chip_id != chip_8001) { + pm8001_dev->setds_completion = &completion_setstate; + PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, + pm8001_dev, DS_OPERATIONAL); + wait_for_completion(&completion_setstate); + } +} diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 0b1086042ca6..c19c9c80206c 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -742,6 +742,7 @@ pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha, smp_mb(); /*in order to force CPU ordering*/ task->task_done(task); } +void pm8001_setds_completion(struct domain_device *dev); #endif diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9c181ebccfee..dd6551e809a0 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -652,6 +652,9 @@ struct sas_domain_function_template { int (*lldd_lu_reset)(struct domain_device *, u8 *lun); int (*lldd_query_task)(struct sas_task *); + /* Special TMF callbacks */ + void (*lldd_tmf_exec_complete)(struct domain_device *dev); + /* Port and Adapter management */ int (*lldd_clear_nexus_port)(struct asd_sas_port *); int (*lldd_clear_nexus_ha)(struct sas_ha_struct *); -- cgit v1.2.3 From 693e66a0a6ac56322687f614ba6e8bfbc43a1530 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:40 +0800 Subject: scsi: libsas: Add TMF handler aborted callback The hisi_sas and pm8001 TMF handlers have some special processing for when the TMF is aborted, so add a callback and fill it in for those drivers. Link: https://lore.kernel.org/r/1645112566-115804-13-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 20 ++++++++++++++++++++ drivers/scsi/libsas/sas_scsi_host.c | 2 ++ drivers/scsi/pm8001/pm8001_init.c | 1 + drivers/scsi/pm8001/pm8001_sas.c | 8 ++++++++ drivers/scsi/pm8001/pm8001_sas.h | 1 + include/scsi/libsas.h | 1 + 6 files changed, 33 insertions(+) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index bd40323f7053..21e929c8bdb0 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -666,6 +666,25 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) return sas_dev; } +static void hisi_sas_tmf_aborted(struct sas_task *task) +{ + struct hisi_sas_slot *slot = task->lldd_task; + struct domain_device *device = task->dev; + struct hisi_sas_device *sas_dev = device->lldd_dev; + struct hisi_hba *hisi_hba = sas_dev->hisi_hba; + + if (slot) { + struct hisi_sas_cq *cq = + &hisi_hba->cq[slot->dlvry_queue]; + /* + * sync irq to avoid free'ing task + * before using task in IO completion + */ + synchronize_irq(cq->irq_no); + slot->task = NULL; + } +} + #define HISI_SAS_DISK_RECOVER_CNT 3 static int hisi_sas_init_device(struct domain_device *device) { @@ -2322,6 +2341,7 @@ static struct sas_domain_function_template hisi_sas_transport_ops = { .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha, .lldd_port_formed = hisi_sas_port_formed, .lldd_write_gpio = hisi_sas_write_gpio, + .lldd_tmf_aborted = hisi_sas_tmf_aborted, }; void hisi_sas_init_mem(struct hisi_hba *hisi_hba) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 0f599744738d..c5d9c6a6b870 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -966,6 +966,8 @@ int sas_execute_tmf(struct domain_device *device, void *parameter, if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { pr_err("TMF task timeout for %016llx and not done\n", SAS_ADDR(device->sas_addr)); + if (i->dft->lldd_tmf_aborted) + i->dft->lldd_tmf_aborted(task); break; } pr_warn("TMF task timeout for %016llx and done\n", diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 8eef8f4de42f..6a3635c39f6a 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -129,6 +129,7 @@ static struct sas_domain_function_template pm8001_transport_ops = { .lldd_query_task = pm8001_query_task, .lldd_port_formed = pm8001_port_formed, .lldd_tmf_exec_complete = pm8001_setds_completion, + .lldd_tmf_aborted = pm8001_tmf_aborted, }; /** diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 69da7246ea20..a530fb0aaa05 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1390,3 +1390,11 @@ void pm8001_setds_completion(struct domain_device *dev) wait_for_completion(&completion_setstate); } } + +void pm8001_tmf_aborted(struct sas_task *task) +{ + struct pm8001_ccb_info *ccb = task->lldd_task; + + if (ccb) + ccb->task = NULL; +} diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index c19c9c80206c..aa018d2d19a3 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -743,6 +743,7 @@ pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha, task->task_done(task); } void pm8001_setds_completion(struct domain_device *dev); +void pm8001_tmf_aborted(struct sas_task *task); #endif diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index dd6551e809a0..c44de478e314 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -654,6 +654,7 @@ struct sas_domain_function_template { /* Special TMF callbacks */ void (*lldd_tmf_exec_complete)(struct domain_device *dev); + void (*lldd_tmf_aborted)(struct sas_task *task); /* Port and Adapter management */ int (*lldd_clear_nexus_port)(struct asd_sas_port *); -- cgit v1.2.3 From 69b80a0ed0b5d0c54ee1618eb5a015699e8c47c5 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:41 +0800 Subject: scsi: libsas: Add sas_abort_task_set() Add a generic implementation of abort task set TMF handler, and use in LLDDs. Link: https://lore.kernel.org/r/1645112566-115804-14-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 5 +---- drivers/scsi/libsas/sas_scsi_host.c | 16 ++++++++++++---- drivers/scsi/mvsas/mv_init.c | 2 +- drivers/scsi/mvsas/mv_sas.c | 11 ----------- drivers/scsi/mvsas/mv_sas.h | 1 - drivers/scsi/pm8001/pm8001_init.c | 2 +- drivers/scsi/pm8001/pm8001_sas.c | 8 -------- drivers/scsi/pm8001/pm8001_sas.h | 1 - include/scsi/libsas.h | 2 ++ 9 files changed, 17 insertions(+), 31 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 21e929c8bdb0..54fe25ddac5b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1788,7 +1788,6 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) { struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; - struct sas_tmf_task tmf_task; int rc; rc = hisi_sas_internal_task_abort(hisi_hba, device, @@ -1799,9 +1798,7 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) } hisi_sas_dereg_device(hisi_hba, device); - tmf_task.tmf = TMF_ABORT_TASK_SET; - rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); - + rc = sas_abort_task_set(device, lun); if (rc == TMF_RESP_FUNC_COMPLETE) hisi_sas_release_task(hisi_hba, device); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index c5d9c6a6b870..06bc7221ac3a 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -1030,10 +1030,8 @@ int sas_execute_tmf(struct domain_device *device, void *parameter, return res; } -int sas_execute_ssp_tmf(struct domain_device *device, u8 *lun, - struct sas_tmf_task *tmf); -int sas_execute_ssp_tmf(struct domain_device *device, u8 *lun, - struct sas_tmf_task *tmf) +static int sas_execute_ssp_tmf(struct domain_device *device, u8 *lun, + struct sas_tmf_task *tmf) { struct sas_ssp_task ssp_task; @@ -1045,6 +1043,16 @@ int sas_execute_ssp_tmf(struct domain_device *device, u8 *lun, return sas_execute_tmf(device, &ssp_task, sizeof(ssp_task), -1, tmf); } +int sas_abort_task_set(struct domain_device *dev, u8 *lun) +{ + struct sas_tmf_task tmf_task = { + .tmf = TMF_ABORT_TASK_SET, + }; + + return sas_execute_ssp_tmf(dev, lun, &tmf_task); +} +EXPORT_SYMBOL_GPL(sas_abort_task_set); + /* * Tell an upper layer that it needs to initiate an abort for a given task. * This should only ever be called by an LLDD. diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 3fe0a9351cea..13a002e08a12 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -63,7 +63,7 @@ static struct sas_domain_function_template mvs_transport_ops = { .lldd_control_phy = mvs_phy_control, .lldd_abort_task = mvs_abort_task, - .lldd_abort_task_set = mvs_abort_task_set, + .lldd_abort_task_set = sas_abort_task_set, .lldd_clear_task_set = mvs_clear_task_set, .lldd_I_T_nexus_reset = mvs_I_T_nexus_reset, .lldd_lu_reset = mvs_lu_reset, diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 47fcd8de9ece..0cdbba31f327 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1536,17 +1536,6 @@ out: return rc; } -int mvs_abort_task_set(struct domain_device *dev, u8 *lun) -{ - int rc; - struct sas_tmf_task tmf_task; - - tmf_task.tmf = TMF_ABORT_TASK_SET; - rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); - - return rc; -} - int mvs_clear_task_set(struct domain_device *dev, u8 *lun) { int rc = TMF_RESP_FUNC_FAILED; diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index fa654c73beee..0bee63596208 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -440,7 +440,6 @@ void mvs_scan_start(struct Scsi_Host *shost); int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time); int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags); int mvs_abort_task(struct sas_task *task); -int mvs_abort_task_set(struct domain_device *dev, u8 *lun); int mvs_clear_task_set(struct domain_device *dev, u8 * lun); void mvs_port_formed(struct asd_sas_phy *sas_phy); void mvs_port_deformed(struct asd_sas_phy *sas_phy); diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 6a3635c39f6a..d7b95ad4533e 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -122,7 +122,7 @@ static struct sas_domain_function_template pm8001_transport_ops = { .lldd_control_phy = pm8001_phy_control, .lldd_abort_task = pm8001_abort_task, - .lldd_abort_task_set = pm8001_abort_task_set, + .lldd_abort_task_set = sas_abort_task_set, .lldd_clear_task_set = pm8001_clear_task_set, .lldd_I_T_nexus_reset = pm8001_I_T_nexus_reset, .lldd_lu_reset = pm8001_lu_reset, diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index a530fb0aaa05..543113564a58 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1342,14 +1342,6 @@ out: return rc; } -int pm8001_abort_task_set(struct domain_device *dev, u8 *lun) -{ - struct sas_tmf_task tmf_task; - - tmf_task.tmf = TMF_ABORT_TASK_SET; - return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); -} - int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) { struct sas_tmf_task tmf_task; diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index aa018d2d19a3..d26f25186779 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -644,7 +644,6 @@ void pm8001_scan_start(struct Scsi_Host *shost); int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time); int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags); int pm8001_abort_task(struct sas_task *task); -int pm8001_abort_task_set(struct domain_device *dev, u8 *lun); int pm8001_clear_task_set(struct domain_device *dev, u8 *lun); int pm8001_dev_found(struct domain_device *dev); void pm8001_dev_gone(struct domain_device *dev); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index c44de478e314..53fdc18bdd09 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -722,6 +722,8 @@ struct sas_phy *sas_get_local_phy(struct domain_device *dev); int sas_request_addr(struct Scsi_Host *shost, u8 *addr); +int sas_abort_task_set(struct domain_device *dev, u8 *lun); + int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, gfp_t gfp_flags); int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, -- cgit v1.2.3 From e8585452953a040a6d1d901e5b2e8c327f09e219 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:42 +0800 Subject: scsi: libsas: Add sas_clear_task_set() Add a generic implementation of clear task set TMF handler, and use in LLDDs. Link: https://lore.kernel.org/r/1645112566-115804-15-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 5 +---- drivers/scsi/libsas/sas_scsi_host.c | 10 ++++++++++ drivers/scsi/mvsas/mv_init.c | 2 +- drivers/scsi/mvsas/mv_sas.c | 11 ----------- drivers/scsi/mvsas/mv_sas.h | 1 - drivers/scsi/pm8001/pm8001_sas.c | 4 +--- include/scsi/libsas.h | 1 + 7 files changed, 14 insertions(+), 20 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 54fe25ddac5b..6826ddfeaca5 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -690,7 +690,6 @@ static int hisi_sas_init_device(struct domain_device *device) { int rc = TMF_RESP_FUNC_COMPLETE; struct scsi_lun lun; - struct sas_tmf_task tmf_task; int retry = HISI_SAS_DISK_RECOVER_CNT; struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; @@ -700,10 +699,8 @@ static int hisi_sas_init_device(struct domain_device *device) case SAS_END_DEVICE: int_to_scsilun(0, &lun); - tmf_task.tmf = TMF_CLEAR_TASK_SET; while (retry-- > 0) { - rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun, - &tmf_task); + rc = sas_clear_task_set(device, lun.scsi_lun); if (rc == TMF_RESP_FUNC_COMPLETE) { hisi_sas_release_task(hisi_hba, device); break; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 06bc7221ac3a..ac669215c3bc 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -1053,6 +1053,16 @@ int sas_abort_task_set(struct domain_device *dev, u8 *lun) } EXPORT_SYMBOL_GPL(sas_abort_task_set); +int sas_clear_task_set(struct domain_device *dev, u8 *lun) +{ + struct sas_tmf_task tmf_task = { + .tmf = TMF_CLEAR_TASK_SET, + }; + + return sas_execute_ssp_tmf(dev, lun, &tmf_task); +} +EXPORT_SYMBOL_GPL(sas_clear_task_set); + /* * Tell an upper layer that it needs to initiate an abort for a given task. * This should only ever be called by an LLDD. diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 13a002e08a12..d12fb210c868 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -64,7 +64,7 @@ static struct sas_domain_function_template mvs_transport_ops = { .lldd_abort_task = mvs_abort_task, .lldd_abort_task_set = sas_abort_task_set, - .lldd_clear_task_set = mvs_clear_task_set, + .lldd_clear_task_set = sas_clear_task_set, .lldd_I_T_nexus_reset = mvs_I_T_nexus_reset, .lldd_lu_reset = mvs_lu_reset, .lldd_query_task = mvs_query_task, diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 0cdbba31f327..37604b1ebd46 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1536,17 +1536,6 @@ out: return rc; } -int mvs_clear_task_set(struct domain_device *dev, u8 *lun) -{ - int rc = TMF_RESP_FUNC_FAILED; - struct sas_tmf_task tmf_task; - - tmf_task.tmf = TMF_CLEAR_TASK_SET; - rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); - - return rc; -} - static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, u32 slot_idx, int err) { diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 0bee63596208..509d8f32a04f 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -440,7 +440,6 @@ void mvs_scan_start(struct Scsi_Host *shost); int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time); int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags); int mvs_abort_task(struct sas_task *task); -int mvs_clear_task_set(struct domain_device *dev, u8 * lun); void mvs_port_formed(struct asd_sas_phy *sas_phy); void mvs_port_deformed(struct asd_sas_phy *sas_phy); int mvs_dev_found(struct domain_device *dev); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 543113564a58..fd86490616e8 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1344,14 +1344,12 @@ out: int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) { - struct sas_tmf_task tmf_task; struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); pm8001_dbg(pm8001_ha, EH, "I_T_L_Q clear task set[%x]\n", pm8001_dev->device_id); - tmf_task.tmf = TMF_CLEAR_TASK_SET; - return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); + return sas_clear_task_set(dev, lun); } void pm8001_port_formed(struct asd_sas_phy *sas_phy) diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 53fdc18bdd09..f71a47740ff8 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -723,6 +723,7 @@ struct sas_phy *sas_get_local_phy(struct domain_device *dev); int sas_request_addr(struct Scsi_Host *shost, u8 *addr); int sas_abort_task_set(struct domain_device *dev, u8 *lun); +int sas_clear_task_set(struct domain_device *dev, u8 *lun); int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, gfp_t gfp_flags); -- cgit v1.2.3 From 29d7769055a21968c0bbfe866affe1640d90bd1d Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:43 +0800 Subject: scsi: libsas: Add sas_lu_reset() Add a generic implementation of LU reset TMF handler, and use in LLDDs. Link: https://lore.kernel.org/r/1645112566-115804-16-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 4 +--- drivers/scsi/libsas/sas_scsi_host.c | 10 ++++++++++ drivers/scsi/mvsas/mv_sas.c | 4 +--- drivers/scsi/pm8001/pm8001_sas.c | 4 +--- include/scsi/libsas.h | 1 + 5 files changed, 14 insertions(+), 9 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 6826ddfeaca5..3773874b0c2e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1933,9 +1933,7 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) hisi_sas_release_task(hisi_hba, device); sas_put_local_phy(phy); } else { - struct sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET }; - - rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); + rc = sas_lu_reset(device, lun); if (rc == TMF_RESP_FUNC_COMPLETE) hisi_sas_release_task(hisi_hba, device); } diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index ac669215c3bc..d6f29e13204e 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -1063,6 +1063,16 @@ int sas_clear_task_set(struct domain_device *dev, u8 *lun) } EXPORT_SYMBOL_GPL(sas_clear_task_set); +int sas_lu_reset(struct domain_device *dev, u8 *lun) +{ + struct sas_tmf_task tmf_task = { + .tmf = TMF_LU_RESET, + }; + + return sas_execute_ssp_tmf(dev, lun, &tmf_task); +} +EXPORT_SYMBOL_GPL(sas_lu_reset); + /* * Tell an upper layer that it needs to initiate an abort for a given task. * This should only ever be called by an LLDD. diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 37604b1ebd46..fdaaa4380e74 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1381,13 +1381,11 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun) { unsigned long flags; int rc = TMF_RESP_FUNC_FAILED; - struct sas_tmf_task tmf_task; struct mvs_device * mvi_dev = dev->lldd_dev; struct mvs_info *mvi = mvi_dev->mvi_info; - tmf_task.tmf = TMF_LU_RESET; mvi_dev->dev_status = MVS_DEV_EH; - rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); + rc = sas_lu_reset(dev, lun); if (rc == TMF_RESP_FUNC_COMPLETE) { spin_lock_irqsave(&mvi->lock, flags); mvs_release_task(mvi, dev); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index fd86490616e8..18e8420055b5 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1112,7 +1112,6 @@ out: int pm8001_lu_reset(struct domain_device *dev, u8 *lun) { int rc = TMF_RESP_FUNC_FAILED; - struct sas_tmf_task tmf_task; struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); DECLARE_COMPLETION_ONSTACK(completion_setstate); @@ -1127,8 +1126,7 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) pm8001_dev, DS_OPERATIONAL); wait_for_completion(&completion_setstate); } else { - tmf_task.tmf = TMF_LU_RESET; - rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task); + rc = sas_lu_reset(dev, lun); } /* If failed, fall-through I_T_Nexus reset */ pm8001_dbg(pm8001_ha, EH, "for device[%x]:rc=%d\n", diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index f71a47740ff8..7b1e2e7f5a6c 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -724,6 +724,7 @@ int sas_request_addr(struct Scsi_Host *shost, u8 *addr); int sas_abort_task_set(struct domain_device *dev, u8 *lun); int sas_clear_task_set(struct domain_device *dev, u8 *lun); +int sas_lu_reset(struct domain_device *dev, u8 *lun); int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, gfp_t gfp_flags); -- cgit v1.2.3 From 72f8810e1fdcd52deedfd294497fa8337703a632 Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:44 +0800 Subject: scsi: libsas: Add sas_query_task() Add a generic implementation of query task TMF handler, and use in LLDDs. Link: https://lore.kernel.org/r/1645112566-115804-17-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +----------- drivers/scsi/libsas/sas_scsi_host.c | 16 ++++++++++++++++ drivers/scsi/mvsas/mv_sas.c | 9 +-------- drivers/scsi/pm8001/pm8001_sas.c | 7 +------ include/scsi/libsas.h | 1 + 5 files changed, 20 insertions(+), 25 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 3773874b0c2e..808eefaf3359 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1988,23 +1988,13 @@ static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha) static int hisi_sas_query_task(struct sas_task *task) { - struct scsi_lun lun; - struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED; if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { - struct scsi_cmnd *cmnd = task->uldd_task; - struct domain_device *device = task->dev; struct hisi_sas_slot *slot = task->lldd_task; u32 tag = slot->idx; - int_to_scsilun(cmnd->device->lun, &lun); - tmf_task.tmf = TMF_QUERY_TASK; - tmf_task.tag_of_task_to_be_managed = tag; - - rc = hisi_sas_debug_issue_ssp_tmf(device, - lun.scsi_lun, - &tmf_task); + rc = sas_query_task(task, tag); switch (rc) { /* The task is still in Lun, release it then */ case TMF_RESP_FUNC_SUCC: diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index d6f29e13204e..1923a0627ce7 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -1073,6 +1073,22 @@ int sas_lu_reset(struct domain_device *dev, u8 *lun) } EXPORT_SYMBOL_GPL(sas_lu_reset); +int sas_query_task(struct sas_task *task, u16 tag) +{ + struct sas_tmf_task tmf_task = { + .tmf = TMF_QUERY_TASK, + .tag_of_task_to_be_managed = tag, + }; + struct scsi_cmnd *cmnd = task->uldd_task; + struct domain_device *dev = task->dev; + struct scsi_lun lun; + + int_to_scsilun(cmnd->device->lun, &lun); + + return sas_execute_ssp_tmf(dev, lun.scsi_lun, &tmf_task); +} +EXPORT_SYMBOL_GPL(sas_query_task); + /* * Tell an upper layer that it needs to initiate an abort for a given task. * This should only ever be called by an LLDD. diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index fdaaa4380e74..63a96c307e3c 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1422,27 +1422,20 @@ int mvs_I_T_nexus_reset(struct domain_device *dev) int mvs_query_task(struct sas_task *task) { u32 tag; - struct scsi_lun lun; - struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED; if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { - struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; struct domain_device *dev = task->dev; struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; struct mvs_info *mvi = mvi_dev->mvi_info; - int_to_scsilun(cmnd->device->lun, &lun); rc = mvs_find_tag(mvi, task, &tag); if (rc == 0) { rc = TMF_RESP_FUNC_FAILED; return rc; } - tmf_task.tmf = TMF_QUERY_TASK; - tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); - - rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); + rc = sas_query_task(task, tag); switch (rc) { /* The task is still in Lun, release it then */ case TMF_RESP_FUNC_SUCC: diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 18e8420055b5..e8bdc3390019 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1138,8 +1138,6 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) int pm8001_query_task(struct sas_task *task) { u32 tag = 0xdeadbeef; - struct scsi_lun lun; - struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED; if (unlikely(!task || !task->lldd_task || !task->dev)) return rc; @@ -1150,17 +1148,14 @@ int pm8001_query_task(struct sas_task *task) struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); - int_to_scsilun(cmnd->device->lun, &lun); rc = pm8001_find_tag(task, &tag); if (rc == 0) { rc = TMF_RESP_FUNC_FAILED; return rc; } pm8001_dbg(pm8001_ha, EH, "Query:[%16ph]\n", cmnd->cmnd); - tmf_task.tmf = TMF_QUERY_TASK; - tmf_task.tag_of_task_to_be_managed = tag; - rc = pm8001_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); + rc = sas_query_task(task, tag); switch (rc) { /* The task is still in Lun, release it then */ case TMF_RESP_FUNC_SUCC: diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 7b1e2e7f5a6c..bf8613fb1c4e 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -725,6 +725,7 @@ int sas_request_addr(struct Scsi_Host *shost, u8 *addr); int sas_abort_task_set(struct domain_device *dev, u8 *lun); int sas_clear_task_set(struct domain_device *dev, u8 *lun); int sas_lu_reset(struct domain_device *dev, u8 *lun); +int sas_query_task(struct sas_task *task, u16 tag); int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, gfp_t gfp_flags); -- cgit v1.2.3 From 4fea759edfa795b170a72bfd3be7b7601012ce4b Mon Sep 17 00:00:00 2001 From: John Garry Date: Thu, 17 Feb 2022 23:42:45 +0800 Subject: scsi: libsas: Add sas_abort_task() Add a generic implementation of abort task TMF handler, and use in LLDDs. With that, some LLDDs custom TMF functions can now be deleted. Link: https://lore.kernel.org/r/1645112566-115804-18-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 27 +------- drivers/scsi/libsas/sas_scsi_host.c | 16 +++++ drivers/scsi/mvsas/mv_sas.c | 118 +--------------------------------- drivers/scsi/pm8001/pm8001_sas.c | 117 +-------------------------------- include/scsi/libsas.h | 1 + 5 files changed, 20 insertions(+), 259 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 808eefaf3359..34ed4f8da7cc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -10,8 +10,6 @@ #define DEV_IS_GONE(dev) \ ((!dev) || (dev->dev_type == SAS_PHY_UNUSED)) -static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, - u8 *lun, struct sas_tmf_task *tmf); static int hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, struct domain_device *device, @@ -1416,20 +1414,6 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) return rc; } -static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, - u8 *lun, struct sas_tmf_task *tmf) -{ - struct sas_ssp_task ssp_task; - - if (!(device->tproto & SAS_PROTOCOL_SSP)) - return TMF_RESP_FUNC_ESUPP; - - memcpy(ssp_task.LUN, lun, 8); - - return hisi_sas_exec_internal_tmf_task(device, &ssp_task, - sizeof(ssp_task), tmf); -} - static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba) { u32 state = hisi_hba->hw->get_phys_state(hisi_hba); @@ -1675,8 +1659,6 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) static int hisi_sas_abort_task(struct sas_task *task) { - struct scsi_lun lun; - struct sas_tmf_task tmf_task; struct domain_device *device = task->dev; struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_hba *hisi_hba; @@ -1711,18 +1693,11 @@ static int hisi_sas_abort_task(struct sas_task *task) spin_unlock_irqrestore(&task->task_state_lock, flags); if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { - struct scsi_cmnd *cmnd = task->uldd_task; struct hisi_sas_slot *slot = task->lldd_task; u16 tag = slot->idx; int rc2; - int_to_scsilun(cmnd->device->lun, &lun); - tmf_task.tmf = TMF_ABORT_TASK; - tmf_task.tag_of_task_to_be_managed = tag; - - rc = hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, - &tmf_task); - + rc = sas_abort_task(task, tag); rc2 = hisi_sas_internal_task_abort(hisi_hba, device, HISI_SAS_INT_ABT_CMD, tag, false); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 1923a0627ce7..87dd18a85f6f 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -1089,6 +1089,22 @@ int sas_query_task(struct sas_task *task, u16 tag) } EXPORT_SYMBOL_GPL(sas_query_task); +int sas_abort_task(struct sas_task *task, u16 tag) +{ + struct sas_tmf_task tmf_task = { + .tmf = TMF_ABORT_TASK, + .tag_of_task_to_be_managed = tag, + }; + struct scsi_cmnd *cmnd = task->uldd_task; + struct domain_device *dev = task->dev; + struct scsi_lun lun; + + int_to_scsilun(cmnd->device->lun, &lun); + + return sas_execute_ssp_tmf(dev, lun.scsi_lun, &tmf_task); +} +EXPORT_SYMBOL_GPL(sas_abort_task); + /* * Tell an upper layer that it needs to initiate an abort for a given task. * This should only ever be called by an LLDD. diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 63a96c307e3c..a6867dae0e7c 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -1254,114 +1254,6 @@ void mvs_dev_gone(struct domain_device *dev) mvs_dev_gone_notify(dev); } -static void mvs_task_done(struct sas_task *task) -{ - if (!del_timer(&task->slow_task->timer)) - return; - complete(&task->slow_task->completion); -} - -static void mvs_tmf_timedout(struct timer_list *t) -{ - struct sas_task_slow *slow = from_timer(slow, t, timer); - struct sas_task *task = slow->task; - - task->task_state_flags |= SAS_TASK_STATE_ABORTED; - complete(&task->slow_task->completion); -} - -#define MVS_TASK_TIMEOUT 20 -static int mvs_exec_internal_tmf_task(struct domain_device *dev, - void *parameter, u32 para_len, struct sas_tmf_task *tmf) -{ - int res, retry; - struct sas_task *task = NULL; - - for (retry = 0; retry < 3; retry++) { - task = sas_alloc_slow_task(GFP_KERNEL); - if (!task) - return -ENOMEM; - - task->dev = dev; - task->task_proto = dev->tproto; - - memcpy(&task->ssp_task, parameter, para_len); - task->task_done = mvs_task_done; - - task->slow_task->timer.function = mvs_tmf_timedout; - task->slow_task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ; - add_timer(&task->slow_task->timer); - - task->tmf = tmf; - - res = mvs_queue_command(task, GFP_KERNEL); - - if (res) { - del_timer(&task->slow_task->timer); - mv_printk("executing internal task failed:%d\n", res); - goto ex_err; - } - - wait_for_completion(&task->slow_task->completion); - res = TMF_RESP_FUNC_FAILED; - /* Even TMF timed out, return direct. */ - if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - mv_printk("TMF task[%x] timeout.\n", tmf->tmf); - goto ex_err; - } - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_SAM_STAT_GOOD) { - res = TMF_RESP_FUNC_COMPLETE; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_DATA_UNDERRUN) { - /* no error, but return the number of bytes of - * underrun */ - res = task->task_status.residual; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_DATA_OVERRUN) { - mv_dprintk("blocked task error.\n"); - res = -EMSGSIZE; - break; - } else { - mv_dprintk(" task to dev %016llx response: 0x%x " - "status 0x%x\n", - SAS_ADDR(dev->sas_addr), - task->task_status.resp, - task->task_status.stat); - sas_free_task(task); - task = NULL; - - } - } -ex_err: - BUG_ON(retry == 3 && task != NULL); - sas_free_task(task); - return res; -} - -static int mvs_debug_issue_ssp_tmf(struct domain_device *dev, - u8 *lun, struct sas_tmf_task *tmf) -{ - struct sas_ssp_task ssp_task; - if (!(dev->tproto & SAS_PROTOCOL_SSP)) - return TMF_RESP_FUNC_ESUPP; - - memcpy(ssp_task.LUN, lun, 8); - - return mvs_exec_internal_tmf_task(dev, &ssp_task, - sizeof(ssp_task), tmf); -} - - /* Standard mandates link reset for ATA (type 0) and hard reset for SSP (type 1) , only for RECOVERY */ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev) @@ -1452,8 +1344,6 @@ int mvs_query_task(struct sas_task *task) /* mandatory SAM-3, still need free task/slot info */ int mvs_abort_task(struct sas_task *task) { - struct scsi_lun lun; - struct sas_tmf_task tmf_task; struct domain_device *dev = task->dev; struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; struct mvs_info *mvi; @@ -1477,9 +1367,6 @@ int mvs_abort_task(struct sas_task *task) spin_unlock_irqrestore(&task->task_state_lock, flags); mvi_dev->dev_status = MVS_DEV_EH; if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { - struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; - - int_to_scsilun(cmnd->device->lun, &lun); rc = mvs_find_tag(mvi, task, &tag); if (rc == 0) { mv_printk("No such tag in %s\n", __func__); @@ -1487,10 +1374,7 @@ int mvs_abort_task(struct sas_task *task) return rc; } - tmf_task.tmf = TMF_ABORT_TASK; - tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); - - rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); + rc = sas_abort_task(task, tag); /* if successful, clear the task and callback forwards.*/ if (rc == TMF_RESP_FUNC_COMPLETE) { diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index e8bdc3390019..828d719afa1b 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -706,103 +706,6 @@ static void pm8001_tmf_timedout(struct timer_list *t) } #define PM8001_TASK_TIMEOUT 20 -/** - * pm8001_exec_internal_tmf_task - execute some task management commands. - * @dev: the wanted device. - * @tmf: which task management wanted to be take. - * @para_len: para_len. - * @parameter: ssp task parameter. - * - * when errors or exception happened, we may want to do something, for example - * abort the issued task which result in this exception, it is done by calling - * this function, note it is also with the task execute interface. - */ -static int pm8001_exec_internal_tmf_task(struct domain_device *dev, - void *parameter, u32 para_len, struct sas_tmf_task *tmf) -{ - int res, retry; - struct sas_task *task = NULL; - struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); - struct pm8001_device *pm8001_dev = dev->lldd_dev; - DECLARE_COMPLETION_ONSTACK(completion_setstate); - - for (retry = 0; retry < 3; retry++) { - task = sas_alloc_slow_task(GFP_KERNEL); - if (!task) - return -ENOMEM; - - task->dev = dev; - task->task_proto = dev->tproto; - memcpy(&task->ssp_task, parameter, para_len); - task->task_done = pm8001_task_done; - task->slow_task->timer.function = pm8001_tmf_timedout; - task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ; - add_timer(&task->slow_task->timer); - - task->tmf = tmf; - - res = pm8001_queue_command(task, GFP_KERNEL); - - if (res) { - del_timer(&task->slow_task->timer); - pm8001_dbg(pm8001_ha, FAIL, "Executing internal task failed\n"); - goto ex_err; - } - wait_for_completion(&task->slow_task->completion); - if (pm8001_ha->chip_id != chip_8001) { - pm8001_dev->setds_completion = &completion_setstate; - PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, - pm8001_dev, DS_OPERATIONAL); - wait_for_completion(&completion_setstate); - } - res = -TMF_RESP_FUNC_FAILED; - /* Even TMF timed out, return direct. */ - if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { - struct pm8001_ccb_info *ccb = task->lldd_task; - - pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n", - tmf->tmf); - - if (ccb) - ccb->task = NULL; - goto ex_err; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_SAM_STAT_GOOD) { - res = TMF_RESP_FUNC_COMPLETE; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_DATA_UNDERRUN) { - /* no error, but return the number of bytes of - * underrun */ - res = task->task_status.residual; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_DATA_OVERRUN) { - pm8001_dbg(pm8001_ha, FAIL, "Blocked task error.\n"); - res = -EMSGSIZE; - break; - } else { - pm8001_dbg(pm8001_ha, EH, - " Task to dev %016llx response:0x%x status 0x%x\n", - SAS_ADDR(dev->sas_addr), - task->task_status.resp, - task->task_status.stat); - sas_free_task(task); - task = NULL; - } - } -ex_err: - BUG_ON(retry == 3 && task != NULL); - sas_free_task(task); - return res; -} - static int pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, struct pm8001_device *pm8001_dev, struct domain_device *dev, u32 flag, @@ -910,18 +813,6 @@ void pm8001_dev_gone(struct domain_device *dev) pm8001_dev_gone_notify(dev); } -static int pm8001_issue_ssp_tmf(struct domain_device *dev, - u8 *lun, struct sas_tmf_task *tmf) -{ - struct sas_ssp_task ssp_task; - if (!(dev->tproto & SAS_PROTOCOL_SSP)) - return TMF_RESP_FUNC_ESUPP; - - memcpy((u8 *)&ssp_task.LUN, lun, 8); - return pm8001_exec_internal_tmf_task(dev, &ssp_task, sizeof(ssp_task), - tmf); -} - /* retry commands by ha, by task and/or by device */ void pm8001_open_reject_retry( struct pm8001_hba_info *pm8001_ha, @@ -1181,9 +1072,7 @@ int pm8001_abort_task(struct sas_task *task) u32 tag; struct domain_device *dev ; struct pm8001_hba_info *pm8001_ha; - struct scsi_lun lun; struct pm8001_device *pm8001_dev; - struct sas_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED, ret; u32 phy_id, port_id; struct sas_task_slow slow_task; @@ -1219,11 +1108,7 @@ int pm8001_abort_task(struct sas_task *task) } spin_unlock_irqrestore(&task->task_state_lock, flags); if (task->task_proto & SAS_PROTOCOL_SSP) { - struct scsi_cmnd *cmnd = task->uldd_task; - int_to_scsilun(cmnd->device->lun, &lun); - tmf_task.tmf = TMF_ABORT_TASK; - tmf_task.tag_of_task_to_be_managed = tag; - rc = pm8001_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); + rc = sas_abort_task(task, tag); pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev, pm8001_dev->sas_device, 0, tag); } else if (task->task_proto & SAS_PROTOCOL_SATA || diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index bf8613fb1c4e..4ea964d33600 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -726,6 +726,7 @@ int sas_abort_task_set(struct domain_device *dev, u8 *lun); int sas_clear_task_set(struct domain_device *dev, u8 *lun); int sas_lu_reset(struct domain_device *dev, u8 *lun); int sas_query_task(struct sas_task *task, u16 tag); +int sas_abort_task(struct sas_task *task, u16 tag); int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, gfp_t gfp_flags); -- cgit v1.2.3 From 3f2e252ef727318f81588704461735617ad55b88 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 22 Feb 2022 20:50:59 +0800 Subject: scsi: libsas: Add sas_execute_ata_cmd() Add a function to execute an ATA command using the TMF code, and use in the hisi_sas driver. That driver needs to be able to issue the command on a specific phy, so add an interface for that. With that, hisi_sas_exec_internal_tmf_task() may be deleted. Link: https://lore.kernel.org/r/1645534259-27068-19-git-send-email-john.garry@huawei.com Tested-by: Yihang Li Tested-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 130 +-------------------------------- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 5 +- drivers/scsi/libsas/sas_ata.c | 8 ++ drivers/scsi/libsas/sas_scsi_host.c | 10 ++- include/scsi/libsas.h | 7 +- include/scsi/sas_ata.h | 8 ++ 6 files changed, 34 insertions(+), 134 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 34ed4f8da7cc..efedfb3332c3 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1239,124 +1239,7 @@ static void hisi_sas_tmf_timedout(struct timer_list *t) complete(&task->slow_task->completion); } -#define TASK_TIMEOUT (20 * HZ) -#define TASK_RETRY 3 #define INTERNAL_ABORT_TIMEOUT (6 * HZ) -static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, - void *parameter, u32 para_len, - struct sas_tmf_task *tmf) -{ - struct hisi_sas_device *sas_dev = device->lldd_dev; - struct hisi_hba *hisi_hba = sas_dev->hisi_hba; - struct device *dev = hisi_hba->dev; - struct sas_task *task; - int res, retry; - - for (retry = 0; retry < TASK_RETRY; retry++) { - task = sas_alloc_slow_task(GFP_KERNEL); - if (!task) - return -ENOMEM; - - task->dev = device; - task->task_proto = device->tproto; - - if (dev_is_sata(device)) { - task->ata_task.device_control_reg_update = 1; - memcpy(&task->ata_task.fis, parameter, para_len); - } else { - memcpy(&task->ssp_task, parameter, para_len); - } - task->task_done = hisi_sas_task_done; - - task->slow_task->timer.function = hisi_sas_tmf_timedout; - task->slow_task->timer.expires = jiffies + TASK_TIMEOUT; - add_timer(&task->slow_task->timer); - - task->tmf = tmf; - - res = hisi_sas_queue_command(task, GFP_KERNEL); - if (res) { - del_timer_sync(&task->slow_task->timer); - dev_err(dev, "abort tmf: executing internal task failed: %d\n", - res); - goto ex_err; - } - - wait_for_completion(&task->slow_task->completion); - res = TMF_RESP_FUNC_FAILED; - /* Even TMF timed out, return direct. */ - if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - struct hisi_sas_slot *slot = task->lldd_task; - - dev_err(dev, "abort tmf: TMF task timeout and not done\n"); - if (slot) { - struct hisi_sas_cq *cq = - &hisi_hba->cq[slot->dlvry_queue]; - /* - * sync irq to avoid free'ing task - * before using task in IO completion - */ - synchronize_irq(cq->irq_no); - slot->task = NULL; - } - - goto ex_err; - } else - dev_err(dev, "abort tmf: TMF task timeout\n"); - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == TMF_RESP_FUNC_COMPLETE) { - res = TMF_RESP_FUNC_COMPLETE; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == TMF_RESP_FUNC_SUCC) { - res = TMF_RESP_FUNC_SUCC; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_DATA_UNDERRUN) { - /* no error, but return the number of bytes of - * underrun - */ - dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x sts 0x%x underrun\n", - SAS_ADDR(device->sas_addr), - task->task_status.resp, - task->task_status.stat); - res = task->task_status.residual; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_DATA_OVERRUN) { - dev_warn(dev, "abort tmf: blocked task error\n"); - res = -EMSGSIZE; - break; - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAS_OPEN_REJECT) { - dev_warn(dev, "abort tmf: open reject failed\n"); - res = -EIO; - } else { - dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x status 0x%x\n", - SAS_ADDR(device->sas_addr), - task->task_status.resp, - task->task_status.stat); - } - sas_free_task(task); - task = NULL; - } -ex_err: - if (retry == TASK_RETRY) - dev_warn(dev, "abort tmf: executing internal task failed!\n"); - sas_free_task(task); - return res; -} static void hisi_sas_fill_ata_reset_cmd(struct ata_device *dev, bool reset, int pmp, u8 *fis) @@ -1380,14 +1263,12 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) int rc = TMF_RESP_FUNC_FAILED; struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; - int s = sizeof(struct host_to_dev_fis); - struct sas_tmf_task tmf = {}; ata_for_each_link(link, ap, EDGE) { int pmp = sata_srst_pmp(link); hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis); - rc = hisi_sas_exec_internal_tmf_task(device, fis, s, &tmf); + rc = sas_execute_ata_cmd(device, fis, -1); if (rc != TMF_RESP_FUNC_COMPLETE) break; } @@ -1397,8 +1278,7 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device) int pmp = sata_srst_pmp(link); hisi_sas_fill_ata_reset_cmd(link->device, 0, pmp, fis); - rc = hisi_sas_exec_internal_tmf_task(device, fis, - s, &tmf); + rc = sas_execute_ata_cmd(device, fis, -1); if (rc != TMF_RESP_FUNC_COMPLETE) dev_err(dev, "ata disk %016llx de-reset failed\n", SAS_ADDR(device->sas_addr)); @@ -1508,10 +1388,8 @@ static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba, struct asd_sas_port *sas_port, struct domain_device *device) { - struct sas_tmf_task tmf_task = { .force_phy = 1 }; struct ata_port *ap = device->sata_dev.ap; struct device *dev = hisi_hba->dev; - int s = sizeof(struct host_to_dev_fis); int rc = TMF_RESP_FUNC_FAILED; struct ata_link *link; u8 fis[20] = {0}; @@ -1524,10 +1402,8 @@ static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba, ata_for_each_link(link, ap, EDGE) { int pmp = sata_srst_pmp(link); - tmf_task.phy_id = i; hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis); - rc = hisi_sas_exec_internal_tmf_task(device, fis, s, - &tmf_task); + rc = sas_execute_ata_cmd(device, fis, i); if (rc != TMF_RESP_FUNC_COMPLETE) { dev_err(dev, "phy%d ata reset failed rc=%d\n", i, rc); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 5bab51dc21b3..441ac4b6f1f4 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2491,6 +2491,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; struct asd_sas_port *sas_port = device->port; struct hisi_sas_port *port = to_hisi_sas_port(sas_port); + struct sas_ata_task *ata_task = &task->ata_task; struct sas_tmf_task *tmf = slot->tmf; u8 *buf_cmd; int has_data = 0, hdr_tag = 0; @@ -2504,9 +2505,9 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, else dw0 |= 4 << CMD_HDR_CMD_OFF; - if (tmf && tmf->force_phy) { + if (tmf && ata_task->force_phy) { dw0 |= CMD_HDR_FORCE_PHY_MSK; - dw0 |= (1 << tmf->phy_id) << CMD_HDR_PHY_ID_OFF; + dw0 |= (1 << ata_task->force_phy_id) << CMD_HDR_PHY_ID_OFF; } hdr->dw0 = cpu_to_le32(dw0); diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 71b42fe95b6f..d89ffb357f14 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -852,3 +852,11 @@ void sas_ata_wait_eh(struct domain_device *dev) ap = dev->sata_dev.ap; ata_port_wait_eh(ap); } + +int sas_execute_ata_cmd(struct domain_device *device, u8 *fis, int force_phy_id) +{ + struct sas_tmf_task tmf_task = {}; + return sas_execute_tmf(device, fis, sizeof(struct host_to_dev_fis), + force_phy_id, &tmf_task); +} +EXPORT_SYMBOL_GPL(sas_execute_ata_cmd); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 87dd18a85f6f..5b5747e33dbd 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -937,8 +937,16 @@ int sas_execute_tmf(struct domain_device *device, void *parameter, task->dev = device; task->task_proto = device->tproto; - if (!dev_is_sata(device)) + if (dev_is_sata(device)) { + task->ata_task.device_control_reg_update = 1; + if (force_phy_id >= 0) { + task->ata_task.force_phy = true; + task->ata_task.force_phy_id = force_phy_id; + } + memcpy(&task->ata_task.fis, parameter, para_len); + } else { memcpy(&task->ssp_task, parameter, para_len); + } task->task_done = sas_task_internal_done; task->tmf = tmf; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 4ea964d33600..dc529cc92d65 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -552,6 +552,9 @@ struct sas_ata_task { u8 stp_affil_pol:1; u8 device_control_reg_update:1; + + bool force_phy; + int force_phy_id; }; struct sas_smp_task { @@ -579,10 +582,6 @@ struct sas_ssp_task { struct sas_tmf_task { u8 tmf; u16 tag_of_task_to_be_managed; - - /* Temp */ - int force_phy; - int phy_id; }; struct sas_task { diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h index 21e7c10c6295..d47dea70855d 100644 --- a/include/scsi/sas_ata.h +++ b/include/scsi/sas_ata.h @@ -32,6 +32,8 @@ void sas_probe_sata(struct asd_sas_port *port); void sas_suspend_sata(struct asd_sas_port *port); void sas_resume_sata(struct asd_sas_port *port); void sas_ata_end_eh(struct ata_port *ap); +int sas_execute_ata_cmd(struct domain_device *device, u8 *fis, + int force_phy_id); #else @@ -83,6 +85,12 @@ static inline int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy static inline void sas_ata_end_eh(struct ata_port *ap) { } + +static inline int sas_execute_ata_cmd(struct domain_device *device, u8 *fis, + int force_phy_id) +{ + return 0; +} #endif #endif /* _SAS_ATA_H_ */ -- cgit v1.2.3 From db22de3eb0352d2f8e7cda08f3fa65690e3fd64d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 18 Feb 2022 11:50:53 -0800 Subject: scsi: iscsi: Stop using the SCSI pointer Instead of storing the iSCSI task pointer and the session age in the SCSI pointer, use command-private variables. This patch prepares for removal of the SCSI pointer from struct scsi_cmnd. The list of iSCSI drivers has been obtained as follows: $ git grep -lw iscsi_host_alloc drivers/infiniband/ulp/iser/iscsi_iser.c drivers/scsi/be2iscsi/be_main.c drivers/scsi/bnx2i/bnx2i_iscsi.c drivers/scsi/cxgbi/libcxgbi.c drivers/scsi/iscsi_tcp.c drivers/scsi/libiscsi.c drivers/scsi/qedi/qedi_main.c drivers/scsi/qla4xxx/ql4_os.c include/scsi/libiscsi.h Note: it is not clear to me how the qla4xxx driver can work without this patch since it uses the scsi_cmnd::SCp.ptr member for two different purposes: - The qla4xxx driver uses this member to store a struct srb pointer. - libiscsi uses this member to store a struct iscsi_task pointer. Reviewed-by: Lee Duncan Reviewed-by: Hannes Reinecke Reviewed-by: Himanshu Madhani Cc: Chris Leech Cc: Sagi Grimberg Cc: Nilesh Javali Cc: Manish Rangankar Cc: Karen Xie Cc: Ketan Mukadam Signed-off-by: Bart Van Assche iscsi Link: https://lore.kernel.org/r/20220218195117.25689-26-bvanassche@acm.org Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/iser/iscsi_iser.c | 1 + drivers/scsi/be2iscsi/be_main.c | 3 ++- drivers/scsi/bnx2i/bnx2i_iscsi.c | 1 + drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 1 + drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 1 + drivers/scsi/iscsi_tcp.c | 1 + drivers/scsi/libiscsi.c | 20 ++++++++++---------- drivers/scsi/qedi/qedi_fw.c | 4 ++-- drivers/scsi/qedi/qedi_iscsi.c | 1 + drivers/scsi/qla4xxx/ql4_def.h | 16 +++++++++++++--- drivers/scsi/qla4xxx/ql4_os.c | 13 +++++++------ include/scsi/libiscsi.h | 12 ++++++++++++ 12 files changed, 52 insertions(+), 22 deletions(-) (limited to 'include/scsi') diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 07e47021a71f..f8d0bab4424c 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -971,6 +971,7 @@ static struct scsi_host_template iscsi_iser_sht = { .proc_name = "iscsi_iser", .this_id = -1, .track_queue_depth = 1, + .cmd_size = sizeof(struct iscsi_cmd), }; static struct iscsi_transport iscsi_iser_transport = { diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index ab55681145f8..3bb0adefbe06 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -218,7 +218,7 @@ static char const *cqe_desc[] = { static int beiscsi_eh_abort(struct scsi_cmnd *sc) { - struct iscsi_task *abrt_task = (struct iscsi_task *)sc->SCp.ptr; + struct iscsi_task *abrt_task = iscsi_cmd(sc)->task; struct iscsi_cls_session *cls_session; struct beiscsi_io_task *abrt_io_task; struct beiscsi_conn *beiscsi_conn; @@ -403,6 +403,7 @@ static struct scsi_host_template beiscsi_sht = { .cmd_per_lun = BEISCSI_CMD_PER_LUN, .vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID, .track_queue_depth = 1, + .cmd_size = sizeof(struct iscsi_cmd), }; static struct scsi_transport_template *beiscsi_scsi_transport; diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index e21b053b4f3e..fe86fd61a995 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -2268,6 +2268,7 @@ static struct scsi_host_template bnx2i_host_template = { .sg_tablesize = ISCSI_MAX_BDS_PER_CMD, .shost_groups = bnx2i_dev_groups, .track_queue_depth = 1, + .cmd_size = sizeof(struct iscsi_cmd), }; struct iscsi_transport bnx2i_iscsi_transport = { diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index f949a4e00783..ff9d4287937a 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -98,6 +98,7 @@ static struct scsi_host_template cxgb3i_host_template = { .dma_boundary = PAGE_SIZE - 1, .this_id = -1, .track_queue_depth = 1, + .cmd_size = sizeof(struct iscsi_cmd), }; static struct iscsi_transport cxgb3i_iscsi_transport = { diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index efb3e2b3398e..53d91bf9c12a 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -116,6 +116,7 @@ static struct scsi_host_template cxgb4i_host_template = { .dma_boundary = PAGE_SIZE - 1, .this_id = -1, .track_queue_depth = 1, + .cmd_size = sizeof(struct iscsi_cmd), }; static struct iscsi_transport cxgb4i_iscsi_transport = { diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 1bc37593c88f..9fee70d6434a 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1007,6 +1007,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = { .proc_name = "iscsi_tcp", .this_id = -1, .track_queue_depth = 1, + .cmd_size = sizeof(struct iscsi_cmd), }; static struct iscsi_transport iscsi_sw_tcp_transport = { diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 059dae8909ee..d69203d19f2c 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -462,7 +462,7 @@ static void iscsi_free_task(struct iscsi_task *task) if (sc) { /* SCSI eh reuses commands to verify us */ - sc->SCp.ptr = NULL; + iscsi_cmd(sc)->task = NULL; /* * queue command may call this to free the task, so * it will decide how to return sc to scsi-ml. @@ -1344,10 +1344,10 @@ struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt) if (!task || !task->sc) return NULL; - if (task->sc->SCp.phase != conn->session->age) { + if (iscsi_cmd(task->sc)->age != conn->session->age) { iscsi_session_printk(KERN_ERR, conn->session, "task's session age %d, expected %d\n", - task->sc->SCp.phase, conn->session->age); + iscsi_cmd(task->sc)->age, conn->session->age); return NULL; } @@ -1645,8 +1645,8 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, (void *) &task, sizeof(void *))) return NULL; - sc->SCp.phase = conn->session->age; - sc->SCp.ptr = (char *) task; + iscsi_cmd(sc)->age = conn->session->age; + iscsi_cmd(sc)->task = task; refcount_set(&task->refcount, 1); task->state = ISCSI_TASK_PENDING; @@ -1683,7 +1683,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) struct iscsi_task *task = NULL; sc->result = 0; - sc->SCp.ptr = NULL; + iscsi_cmd(sc)->task = NULL; ihost = shost_priv(host); @@ -1997,7 +1997,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); spin_lock(&session->back_lock); - task = (struct iscsi_task *)sc->SCp.ptr; + task = iscsi_cmd(sc)->task; if (!task) { /* * Raced with completion. Blk layer has taken ownership @@ -2260,7 +2260,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) * if session was ISCSI_STATE_IN_RECOVERY then we may not have * got the command. */ - if (!sc->SCp.ptr) { + if (!iscsi_cmd(sc)->task) { ISCSI_DBG_EH(session, "sc never reached iscsi layer or " "it completed.\n"); spin_unlock_bh(&session->frwd_lock); @@ -2273,7 +2273,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) * then let the host reset code handle this */ if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN || - sc->SCp.phase != session->age) { + iscsi_cmd(sc)->age != session->age) { spin_unlock_bh(&session->frwd_lock); mutex_unlock(&session->eh_mutex); ISCSI_DBG_EH(session, "failing abort due to dropped " @@ -2282,7 +2282,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) } spin_lock(&session->back_lock); - task = (struct iscsi_task *)sc->SCp.ptr; + task = iscsi_cmd(sc)->task; if (!task || !task->sc) { /* task completed before time out */ ISCSI_DBG_EH(session, "sc completed while abort in progress\n"); diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c index 5916ed7662d5..4e99508ff95d 100644 --- a/drivers/scsi/qedi/qedi_fw.c +++ b/drivers/scsi/qedi/qedi_fw.c @@ -603,9 +603,9 @@ static void qedi_scsi_completion(struct qedi_ctx *qedi, goto error; } - if (!sc_cmd->SCp.ptr) { + if (!iscsi_cmd(sc_cmd)->task) { QEDI_WARN(&qedi->dbg_ctx, - "SCp.ptr is NULL, returned in another context.\n"); + "NULL task pointer, returned in another context.\n"); goto error; } diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 282ecb4e39bb..8196f89f404e 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -59,6 +59,7 @@ struct scsi_host_template qedi_host_template = { .dma_boundary = QEDI_HW_DMA_BOUNDARY, .cmd_per_lun = 128, .shost_groups = qedi_shost_groups, + .cmd_size = sizeof(struct iscsi_cmd), }; static void qedi_conn_free_login_resources(struct qedi_ctx *qedi, diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 69a590546bf9..5f82c8afd5e0 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -216,11 +216,21 @@ #define IDC_COMP_TOV 5 #define LINK_UP_COMP_TOV 30 -#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) +/* + * Note: the data structure below does not have a struct iscsi_cmd member since + * the qla4xxx driver does not use libiscsi for SCSI I/O. + */ +struct qla4xxx_cmd_priv { + struct srb *srb; +}; + +static inline struct qla4xxx_cmd_priv *qla4xxx_cmd_priv(struct scsi_cmnd *cmd) +{ + return scsi_cmd_priv(cmd); +} /* - * SCSI Request Block structure (srb) that is placed - * on cmd->SCp location of every I/O [We have 22 bytes available] + * SCSI Request Block structure (srb) that is associated with each scsi_cmnd. */ struct srb { struct list_head list; /* (8) */ diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 0ae936d839f1..d64eda961412 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -226,6 +226,7 @@ static struct scsi_host_template qla4xxx_driver_template = { .name = DRIVER_NAME, .proc_name = DRIVER_NAME, .queuecommand = qla4xxx_queuecommand, + .cmd_size = sizeof(struct qla4xxx_cmd_priv), .eh_abort_handler = qla4xxx_eh_abort, .eh_device_reset_handler = qla4xxx_eh_device_reset, @@ -4054,7 +4055,7 @@ static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, srb->ddb = ddb_entry; srb->cmd = cmd; srb->flags = 0; - CMD_SP(cmd) = (void *)srb; + qla4xxx_cmd_priv(cmd)->srb = srb; return srb; } @@ -4067,7 +4068,7 @@ static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb) scsi_dma_unmap(cmd); srb->flags &= ~SRB_DMA_VALID; } - CMD_SP(cmd) = NULL; + qla4xxx_cmd_priv(cmd)->srb = NULL; } void qla4xxx_srb_compl(struct kref *ref) @@ -4640,7 +4641,7 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) * the scsi/block layer is going to prevent * the tag from being released. */ - if (cmd != NULL && CMD_SP(cmd)) + if (cmd != NULL && qla4xxx_cmd_priv(cmd)->srb) break; } spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -9079,7 +9080,7 @@ struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, if (!cmd) return srb; - srb = (struct srb *)CMD_SP(cmd); + srb = qla4xxx_cmd_priv(cmd)->srb; if (!srb) return srb; @@ -9121,7 +9122,7 @@ static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha, do { /* Checking to see if its returned to OS */ - rp = (struct srb *) CMD_SP(cmd); + rp = qla4xxx_cmd_priv(cmd)->srb; if (rp == NULL) { done++; break; @@ -9215,7 +9216,7 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) } spin_lock_irqsave(&ha->hardware_lock, flags); - srb = (struct srb *) CMD_SP(cmd); + srb = qla4xxx_cmd_priv(cmd)->srb; if (!srb) { spin_unlock_irqrestore(&ha->hardware_lock, flags); ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Specified command has already completed.\n", diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 4ee233e5a6ff..cb805ed9cbf1 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -19,6 +19,7 @@ #include #include #include +#include #include struct scsi_transport_template; @@ -152,6 +153,17 @@ static inline bool iscsi_task_is_completed(struct iscsi_task *task) task->state == ISCSI_TASK_ABRT_SESS_RECOV; } +/* Private data associated with struct scsi_cmnd. */ +struct iscsi_cmd { + struct iscsi_task *task; + int age; +}; + +static inline struct iscsi_cmd *iscsi_cmd(struct scsi_cmnd *cmd) +{ + return scsi_cmd_priv(cmd); +} + /* Connection's states */ enum { ISCSI_CONN_INITIAL_STAGE, -- cgit v1.2.3 From 5d21aa3636fa8c7d3a2a69be93287da164054a3a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 18 Feb 2022 11:50:55 -0800 Subject: scsi: libfc: Stop using the SCSI pointer Move the fc_fcp_pkt pointer, the residual length and the SCSI status into the new data structure libfc_cmd_priv. This patch prepares for removal of the SCSI pointer from struct scsi_cmnd. The user of the libfc data path functions have been identified as follows: $ git grep -lw fc_queuecommand | grep -v scsi/libfc/ drivers/scsi/fcoe/fcoe.c Link: https://lore.kernel.org/r/20220218195117.25689-28-bvanassche@acm.org Cc: Saurav Kashyap Cc: Javed Hasan Reviewed-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 1 + drivers/scsi/libfc/fc_fcp.c | 26 +++++++++++--------------- include/scsi/libfc.h | 9 +++++++++ 3 files changed, 21 insertions(+), 15 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 6415f88738ad..44ca6110213c 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -277,6 +277,7 @@ static struct scsi_host_template fcoe_shost_template = { .sg_tablesize = SG_ALL, .max_sectors = 0xffff, .track_queue_depth = 1, + .cmd_size = sizeof(struct libfc_cmd_priv), }; /** diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 871b11edb586..bce90eb56c9c 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -45,14 +45,10 @@ static struct kmem_cache *scsi_pkt_cachep; #define FC_SRB_READ (1 << 1) #define FC_SRB_WRITE (1 << 0) -/* - * The SCp.ptr should be tested and set under the scsi_pkt_queue lock - */ -#define CMD_SP(Cmnd) ((struct fc_fcp_pkt *)(Cmnd)->SCp.ptr) -#define CMD_ENTRY_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in) -#define CMD_COMPL_STATUS(Cmnd) ((Cmnd)->SCp.this_residual) -#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status) -#define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual) +static struct libfc_cmd_priv *libfc_priv(struct scsi_cmnd *cmd) +{ + return scsi_cmd_priv(cmd); +} /** * struct fc_fcp_internal - FCP layer internal data @@ -1137,7 +1133,7 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) unsigned long flags; int rc; - fsp->cmd->SCp.ptr = (char *)fsp; + libfc_priv(fsp->cmd)->fsp = fsp; fsp->cdb_cmd.fc_dl = htonl(fsp->data_len); fsp->cdb_cmd.fc_flags = fsp->req_flags & ~FCP_CFL_LEN_MASK; @@ -1150,7 +1146,7 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv); if (unlikely(rc)) { spin_lock_irqsave(&si->scsi_queue_lock, flags); - fsp->cmd->SCp.ptr = NULL; + libfc_priv(fsp->cmd)->fsp = NULL; list_del(&fsp->list); spin_unlock_irqrestore(&si->scsi_queue_lock, flags); } @@ -1983,7 +1979,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) fc_fcp_can_queue_ramp_up(lport); sc_cmd = fsp->cmd; - CMD_SCSI_STATUS(sc_cmd) = fsp->cdb_status; + libfc_priv(sc_cmd)->status = fsp->cdb_status; switch (fsp->status_code) { case FC_COMPLETE: if (fsp->cdb_status == 0) { @@ -1992,7 +1988,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) */ sc_cmd->result = DID_OK << 16; if (fsp->scsi_resid) - CMD_RESID_LEN(sc_cmd) = fsp->scsi_resid; + libfc_priv(sc_cmd)->resid_len = fsp->scsi_resid; } else { /* * transport level I/O was ok but scsi @@ -2025,7 +2021,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) */ FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " "due to FC_DATA_UNDRUN (scsi)\n"); - CMD_RESID_LEN(sc_cmd) = fsp->scsi_resid; + libfc_priv(sc_cmd)->resid_len = fsp->scsi_resid; sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status; } break; @@ -2085,7 +2081,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) spin_lock_irqsave(&si->scsi_queue_lock, flags); list_del(&fsp->list); - sc_cmd->SCp.ptr = NULL; + libfc_priv(sc_cmd)->fsp = NULL; spin_unlock_irqrestore(&si->scsi_queue_lock, flags); scsi_done(sc_cmd); @@ -2121,7 +2117,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd) si = fc_get_scsi_internal(lport); spin_lock_irqsave(&si->scsi_queue_lock, flags); - fsp = CMD_SP(sc_cmd); + fsp = libfc_priv(sc_cmd)->fsp; if (!fsp) { /* command completed while scsi eh was setting up */ spin_unlock_irqrestore(&si->scsi_queue_lock, flags); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index eeb8d689ff6b..6e29e1719db1 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -351,6 +351,15 @@ struct fc_fcp_pkt { struct completion tm_done; } ____cacheline_aligned_in_smp; +/* + * @fsp should be tested and set under the scsi_pkt_queue lock + */ +struct libfc_cmd_priv { + struct fc_fcp_pkt *fsp; + u32 resid_len; + u8 status; +}; + /* * Structure and function definitions for managing Fibre Channel Exchanges * and Sequences -- cgit v1.2.3 From 8264aee803a2168124d1eb867a893047dc2977a0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 18 Feb 2022 11:51:17 -0800 Subject: scsi: core: Remove struct scsi_pointer from struct scsi_cmnd Remove struct scsi_pointer from struct scsi_cmnd since the previous patches removed all users of that member of struct scsi_cmnd. Additionally, reorder the members of struct scsi_cmnd such that the statement that the field below can be modified by the SCSI LLD is again correct. Link: https://lore.kernel.org/r/20220218195117.25689-50-bvanassche@acm.org Cc: Ming Lei Cc: Hannes Reinecke Cc: Christoph Hellwig Reviewed-by: Johannes Thumshirn Reviewed-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- include/scsi/scsi_cmnd.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'include/scsi') diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index ff1c4b51f7ae..7a19c8bbaed9 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -123,11 +123,15 @@ struct scsi_cmnd { * command (auto-sense). Length must be * SCSI_SENSE_BUFFERSIZE bytes. */ + int flags; /* Command flags */ + unsigned long state; /* Command completion state */ + + unsigned int extra_len; /* length of alignment and padding */ + /* - * The following fields can be written to by the host specific code. - * Everything else should be left alone. + * The fields below can be modified by the LLD but the fields above + * must not be modified. */ - struct scsi_pointer SCp; /* Scratchpad used by some host adapters */ unsigned char *host_scribble; /* The host adapter is allowed to * call scsi_malloc and get some memory @@ -138,10 +142,6 @@ struct scsi_cmnd { * to be at an address < 16Mb). */ int result; /* Status code from lower level driver */ - int flags; /* Command flags */ - unsigned long state; /* Command completion state */ - - unsigned int extra_len; /* length of alignment and padding */ }; /* Variant of blk_mq_rq_from_pdu() that verifies the type of its argument. */ -- cgit v1.2.3 From c5b483d5c1a26b6006180f5dc7b2f8674f19afa3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 14 Feb 2022 16:39:03 -0600 Subject: scsi: libfc: Replace one-element arrays with flexible-array members Use flexible-array members in struct fc_fdmi_attr_entry and fs_fdmi_attrs instead of one-element arrays, and refactor the code accordingly. Also, this helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy(). https://github.com/KSPP/linux/issues/79 https://github.com/ClangBuiltLinux/linux/issues/1590 Link: https://lore.kernel.org/r/20220214223903.GA859464@embeddedor Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_encode.h | 2 +- include/scsi/fc/fc_ms.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libfc/fc_encode.h b/drivers/scsi/libfc/fc_encode.h index 74ae7fd15d8d..7dcac3b6baa7 100644 --- a/drivers/scsi/libfc/fc_encode.h +++ b/drivers/scsi/libfc/fc_encode.h @@ -246,7 +246,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, &entry->type); put_unaligned_be16(len, &entry->len); put_unaligned_be64(lport->wwnn, - (__be64 *)&entry->value[0]); + (__be64 *)&entry->value); /* Manufacturer */ entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + diff --git a/include/scsi/fc/fc_ms.h b/include/scsi/fc/fc_ms.h index 00191695233a..56a5d2b5a624 100644 --- a/include/scsi/fc/fc_ms.h +++ b/include/scsi/fc/fc_ms.h @@ -158,7 +158,7 @@ struct fc_fdmi_port_name { struct fc_fdmi_attr_entry { __be16 type; __be16 len; - __u8 value[1]; + __u8 value[]; } __attribute__((__packed__)); /* @@ -166,7 +166,7 @@ struct fc_fdmi_attr_entry { */ struct fs_fdmi_attrs { __be32 numattrs; - struct fc_fdmi_attr_entry attr[1]; + struct fc_fdmi_attr_entry attr[]; } __attribute__((__packed__)); /* -- cgit v1.2.3 From f1834fd1635be4b530a7e070c04a6158b8f78c0e Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 25 Feb 2022 18:57:35 +0800 Subject: scsi: libsas: Make sas_notify_{phy,port}_event() return void Nobody checks the return codes, so make them return void. Indeed, if the LLDD cannot send an event, nothing much can be done in the LLDD about it. Also remove prototype for sas_notify_phy_event() in sas_internal.h, which should not be there. Link: https://lore.kernel.org/r/1645786656-221630-2-git-send-email-john.garry@huawei.com Reviewed-by: Xiang Chen Reviewed-by: Damien Le Moal Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_event.c | 20 ++++++++------------ drivers/scsi/libsas/sas_internal.h | 2 -- include/scsi/libsas.h | 8 ++++---- 3 files changed, 12 insertions(+), 18 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index 3613b9b315bc..8ff58fd97837 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -165,8 +165,8 @@ static bool sas_defer_event(struct asd_sas_phy *phy, struct asd_sas_event *ev) return deferred; } -int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, - gfp_t gfp_flags) +void sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags) { struct sas_ha_struct *ha = phy->ha; struct asd_sas_event *ev; @@ -176,7 +176,7 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, ev = sas_alloc_event(phy, gfp_flags); if (!ev) - return -ENOMEM; + return; /* Call pm_runtime_put() with pairs in sas_port_event_worker() */ pm_runtime_get_noresume(ha->dev); @@ -184,20 +184,18 @@ int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event); if (sas_defer_event(phy, ev)) - return 0; + return; ret = sas_queue_event(event, &ev->work, ha); if (ret != 1) { pm_runtime_put(ha->dev); sas_free_event(ev); } - - return ret; } EXPORT_SYMBOL_GPL(sas_notify_port_event); -int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, - gfp_t gfp_flags) +void sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + gfp_t gfp_flags) { struct sas_ha_struct *ha = phy->ha; struct asd_sas_event *ev; @@ -207,7 +205,7 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, ev = sas_alloc_event(phy, gfp_flags); if (!ev) - return -ENOMEM; + return; /* Call pm_runtime_put() with pairs in sas_phy_event_worker() */ pm_runtime_get_noresume(ha->dev); @@ -215,14 +213,12 @@ int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event); if (sas_defer_event(phy, ev)) - return 0; + return; ret = sas_queue_event(event, &ev->work, ha); if (ret != 1) { pm_runtime_put(ha->dev); sas_free_event(ev); } - - return ret; } EXPORT_SYMBOL_GPL(sas_notify_phy_event); diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index b60f0bf612cf..24843db2cb65 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -78,8 +78,6 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id, enum phy_func phy_func, struct sas_phy_linkrates *); int sas_smp_get_phy_events(struct sas_phy *phy); -int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, - gfp_t flags); void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index dc529cc92d65..df2c8fc43429 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -727,9 +727,9 @@ int sas_lu_reset(struct domain_device *dev, u8 *lun); int sas_query_task(struct sas_task *task, u16 tag); int sas_abort_task(struct sas_task *task, u16 tag); -int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, - gfp_t gfp_flags); -int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, - gfp_t gfp_flags); +void sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, + gfp_t gfp_flags); +void sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, + gfp_t gfp_flags); #endif /* _SASLIB_H_ */ -- cgit v1.2.3 From ce70fd9a551af7424a7dace2a1ba05a7de8eae27 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 24 Feb 2022 18:55:47 +0100 Subject: scsi: core: Remove the cmd field from struct scsi_request Now that each scsi_request is backed by a scsi_cmnd, there is no need to indirect the CDB storage. Change all submitters of SCSI passthrough requests to store the CDB information directly in the scsi_cmnd, and while doing so allocate the full 32 bytes that cover all Linux supported SCSI hosts instead of requiring dynamic allocation for > 16 byte CDBs. On 64-bit systems this does not change the size of the scsi_cmnd at all, while on 32-bit systems it slightly increases it for now, but that increase will be made up by the removal of the remaining scsi_request fields. Link: https://lore.kernel.org/r/20220224175552.988286-4-hch@lst.de Reviewed-by: Bart Van Assche Reviewed-by: John Garry Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/ata/libata-scsi.c | 4 +++- drivers/block/pktcdvd.c | 6 ++++-- drivers/scsi/scsi_bsg.c | 23 +++++++++++------------ drivers/scsi/scsi_debugfs.c | 4 +--- drivers/scsi/scsi_error.c | 28 ++++++++++++++-------------- drivers/scsi/scsi_ioctl.c | 37 +++++++++++++++++-------------------- drivers/scsi/scsi_lib.c | 19 ++++++++----------- drivers/scsi/scsi_logging.c | 5 +---- drivers/scsi/sd.c | 28 +--------------------------- drivers/scsi/sg.c | 30 +++++++++++------------------- drivers/scsi/sr.c | 24 +++++++++++++----------- drivers/scsi/st.c | 12 +++++++----- drivers/scsi/ufs/ufshpb.c | 22 ++++++++++------------ drivers/target/target_core_pscsi.c | 12 ++++++++---- drivers/usb/storage/cypress_atacb.c | 1 - drivers/usb/storage/isd200.c | 4 ++-- include/scsi/scsi_cmnd.h | 7 +------ include/scsi/scsi_eh.h | 4 +--- include/scsi/scsi_request.h | 11 ----------- 19 files changed, 113 insertions(+), 168 deletions(-) (limited to 'include/scsi') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index ed8be585a98f..c8283bd4ffd1 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1022,7 +1022,9 @@ void ata_scsi_sdev_config(struct scsi_device *sdev) */ bool ata_scsi_dma_need_drain(struct request *rq) { - return atapi_cmd_type(scsi_req(rq)->cmd[0]) == ATAPI_MISC; + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); + + return atapi_cmd_type(scmd->cmnd[0]) == ATAPI_MISC; } EXPORT_SYMBOL_GPL(ata_scsi_dma_need_drain); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 2b6b70a39e76..42c284b2d7f9 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -693,6 +693,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc) { struct request_queue *q = bdev_get_queue(pd->bdev); + struct scsi_cmnd *scmd; struct request *rq; int ret = 0; @@ -700,6 +701,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(rq)) return PTR_ERR(rq); + scmd = blk_mq_rq_to_pdu(rq); if (cgc->buflen) { ret = blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen, @@ -708,8 +710,8 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * goto out; } - scsi_req(rq)->cmd_len = COMMAND_SIZE(cgc->cmd[0]); - memcpy(scsi_req(rq)->cmd, cgc->cmd, CDROM_PACKET_SIZE); + scmd->cmd_len = COMMAND_SIZE(cgc->cmd[0]); + memcpy(scmd->cmnd, cgc->cmd, CDROM_PACKET_SIZE); rq->timeout = 60*HZ; if (cgc->quiet) diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c index b7a464383cc0..f8b65bd75ee1 100644 --- a/drivers/scsi/scsi_bsg.c +++ b/drivers/scsi/scsi_bsg.c @@ -13,6 +13,7 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, fmode_t mode, unsigned int timeout) { struct scsi_request *sreq; + struct scsi_cmnd *scmd; struct request *rq; struct bio *bio; int ret; @@ -33,19 +34,19 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, ret = -ENOMEM; sreq = scsi_req(rq); - sreq->cmd_len = hdr->request_len; - if (sreq->cmd_len > BLK_MAX_CDB) { - sreq->cmd = kzalloc(sreq->cmd_len, GFP_KERNEL); - if (!sreq->cmd) - goto out_put_request; + scmd = blk_mq_rq_to_pdu(rq); + scmd->cmd_len = hdr->request_len; + if (scmd->cmd_len > sizeof(scmd->cmnd)) { + ret = -EINVAL; + goto out_put_request; } ret = -EFAULT; - if (copy_from_user(sreq->cmd, uptr64(hdr->request), sreq->cmd_len)) - goto out_free_cmd; + if (copy_from_user(scmd->cmnd, uptr64(hdr->request), scmd->cmd_len)) + goto out_put_request; ret = -EPERM; - if (!scsi_cmd_allowed(sreq->cmd, mode)) - goto out_free_cmd; + if (!scsi_cmd_allowed(scmd->cmnd, mode)) + goto out_put_request; ret = 0; if (hdr->dout_xfer_len) { @@ -57,7 +58,7 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, } if (ret) - goto out_free_cmd; + goto out_put_request; bio = rq->bio; blk_execute_rq(rq, !(hdr->flags & BSG_FLAG_Q_AT_TAIL)); @@ -92,8 +93,6 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, blk_rq_unmap_user(bio); -out_free_cmd: - scsi_req_free_cmd(scsi_req(rq)); out_put_request: blk_mq_free_request(rq); return ret; diff --git a/drivers/scsi/scsi_debugfs.c b/drivers/scsi/scsi_debugfs.c index db8517f1a485..17d7f73a895c 100644 --- a/drivers/scsi/scsi_debugfs.c +++ b/drivers/scsi/scsi_debugfs.c @@ -36,11 +36,9 @@ void scsi_show_rq(struct seq_file *m, struct request *rq) struct scsi_cmnd *cmd = container_of(scsi_req(rq), typeof(*cmd), req); int alloc_ms = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc); int timeout_ms = jiffies_to_msecs(rq->timeout); - const u8 *const cdb = READ_ONCE(cmd->cmnd); char buf[80] = "(?)"; - if (cdb) - __scsi_format_command(buf, sizeof(buf), cdb, cmd->cmd_len); + __scsi_format_command(buf, sizeof(buf), cmd->cmnd, cmd->cmd_len); seq_printf(m, ", .cmd=%s, .retries=%d, .result = %#x, .flags=", buf, cmd->retries, cmd->result); scsi_flags_show(m, cmd->flags, scsi_cmd_flags, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 60a6ae9d1219..5383139a3de8 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -980,7 +980,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) * @scmd: SCSI command structure to hijack * @ses: structure to save restore information * @cmnd: CDB to send. Can be NULL if no new cmnd is needed - * @cmnd_size: size in bytes of @cmnd (must be <= BLK_MAX_CDB) + * @cmnd_size: size in bytes of @cmnd (must be <= MAX_COMMAND_SIZE) * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * * This function is used to save a scsi command information before re-execution @@ -1002,7 +1002,6 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, * command. */ ses->cmd_len = scmd->cmd_len; - ses->cmnd = scmd->cmnd; ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->result = scmd->result; @@ -1013,8 +1012,8 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, scmd->prot_op = SCSI_PROT_NORMAL; scmd->eh_eflags = 0; - scmd->cmnd = ses->eh_cmnd; - memset(scmd->cmnd, 0, BLK_MAX_CDB); + memcpy(ses->cmnd, scmd->cmnd, sizeof(ses->cmnd)); + memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->result = 0; scmd->req.resid_len = 0; @@ -1033,7 +1032,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, } else { scmd->sc_data_direction = DMA_NONE; if (cmnd) { - BUG_ON(cmnd_size > BLK_MAX_CDB); + BUG_ON(cmnd_size > sizeof(scmd->cmnd)); memcpy(scmd->cmnd, cmnd, cmnd_size); scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } @@ -1066,7 +1065,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) * Restore original data */ scmd->cmd_len = ses->cmd_len; - scmd->cmnd = ses->cmnd; + memcpy(scmd->cmnd, ses->cmnd, sizeof(ses->cmnd)); scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->result = ses->result; @@ -2022,6 +2021,7 @@ static void eh_lock_door_done(struct request *req, blk_status_t status) */ static void scsi_eh_lock_door(struct scsi_device *sdev) { + struct scsi_cmnd *scmd; struct request *req; struct scsi_request *rq; @@ -2029,14 +2029,15 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) if (IS_ERR(req)) return; rq = scsi_req(req); + scmd = blk_mq_rq_to_pdu(req); - rq->cmd[0] = ALLOW_MEDIUM_REMOVAL; - rq->cmd[1] = 0; - rq->cmd[2] = 0; - rq->cmd[3] = 0; - rq->cmd[4] = SCSI_REMOVAL_PREVENT; - rq->cmd[5] = 0; - rq->cmd_len = COMMAND_SIZE(rq->cmd[0]); + scmd->cmnd[0] = ALLOW_MEDIUM_REMOVAL; + scmd->cmnd[1] = 0; + scmd->cmnd[2] = 0; + scmd->cmnd[3] = 0; + scmd->cmnd[4] = SCSI_REMOVAL_PREVENT; + scmd->cmnd[5] = 0; + scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); req->rq_flags |= RQF_QUIET; req->timeout = 10 * HZ; @@ -2399,7 +2400,6 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) scmd = (struct scsi_cmnd *)(rq + 1); scsi_init_command(dev, scmd); - scmd->cmnd = scsi_req(rq)->cmd; scmd->submitter = SUBMITTED_BY_SCSI_RESET_IOCTL; memset(&scmd->sdb, 0, sizeof(scmd->sdb)); diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index e13fd380deb6..6d9f1b44566d 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -345,19 +345,15 @@ EXPORT_SYMBOL(scsi_cmd_allowed); static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq, struct sg_io_hdr *hdr, fmode_t mode) { - struct scsi_request *req = scsi_req(rq); + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); if (hdr->cmd_len < 6) return -EMSGSIZE; - if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len)) + if (copy_from_user(scmd->cmnd, hdr->cmdp, hdr->cmd_len)) return -EFAULT; - if (!scsi_cmd_allowed(req->cmd, mode)) + if (!scsi_cmd_allowed(scmd->cmnd, mode)) return -EPERM; - - /* - * fill in request structure - */ - req->cmd_len = hdr->cmd_len; + scmd->cmd_len = hdr->cmd_len; rq->timeout = msecs_to_jiffies(hdr->timeout); if (!rq->timeout) @@ -416,6 +412,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) int at_head = 0; struct request *rq; struct scsi_request *req; + struct scsi_cmnd *scmd; struct bio *bio; if (hdr->interface_id != 'S') @@ -444,16 +441,16 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) if (IS_ERR(rq)) return PTR_ERR(rq); req = scsi_req(rq); + scmd = blk_mq_rq_to_pdu(rq); - if (hdr->cmd_len > BLK_MAX_CDB) { - req->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL); - if (!req->cmd) - goto out_put_request; + if (hdr->cmd_len > sizeof(scmd->cmnd)) { + ret = -EINVAL; + goto out_put_request; } ret = scsi_fill_sghdr_rq(sdev, rq, hdr, mode); if (ret < 0) - goto out_free_cdb; + goto out_put_request; ret = 0; if (hdr->iovec_count) { @@ -463,7 +460,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) ret = import_iovec(rq_data_dir(rq), hdr->dxferp, hdr->iovec_count, 0, &iov, &i); if (ret < 0) - goto out_free_cdb; + goto out_put_request; /* SG_IO howto says that the shorter of the two wins */ iov_iter_truncate(&i, hdr->dxfer_len); @@ -475,7 +472,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) hdr->dxfer_len, GFP_KERNEL); if (ret) - goto out_free_cdb; + goto out_put_request; bio = rq->bio; req->retries = 0; @@ -488,8 +485,6 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) ret = scsi_complete_sghdr_rq(rq, hdr, bio); -out_free_cdb: - scsi_req_free_cmd(req); out_put_request: blk_mq_free_request(rq); return ret; @@ -530,6 +525,7 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, struct scsi_request *req; int err; unsigned int in_len, out_len, bytes, opcode, cmdlen; + struct scsi_cmnd *scmd; char *buffer = NULL; if (!sic) @@ -561,6 +557,7 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, goto error_free_buffer; } req = scsi_req(rq); + scmd = blk_mq_rq_to_pdu(rq); cmdlen = COMMAND_SIZE(opcode); @@ -568,15 +565,15 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, * get command and data to send to device, if any */ err = -EFAULT; - req->cmd_len = cmdlen; - if (copy_from_user(req->cmd, sic->data, cmdlen)) + scmd->cmd_len = cmdlen; + if (copy_from_user(scmd->cmnd, sic->data, cmdlen)) goto error; if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) goto error; err = -EPERM; - if (!scsi_cmd_allowed(req->cmd, mode)) + if (!scsi_cmd_allowed(scmd->cmnd, mode)) goto error; /* default. possible overridden later */ diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 572ffc3abe44..623c8cbcaef8 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -214,6 +214,7 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, { struct request *req; struct scsi_request *rq; + struct scsi_cmnd *scmd; int ret; req = scsi_alloc_request(sdev->request_queue, @@ -231,8 +232,9 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, if (ret) goto out; } - rq->cmd_len = COMMAND_SIZE(cmd[0]); - memcpy(rq->cmd, cmd, rq->cmd_len); + scmd = blk_mq_rq_to_pdu(req); + scmd->cmd_len = COMMAND_SIZE(cmd[0]); + memcpy(scmd->cmnd, cmd, scmd->cmd_len); rq->retries = retries; req->timeout = timeout; req->cmd_flags |= flags; @@ -1126,9 +1128,9 @@ static void scsi_initialize_rq(struct request *rq) struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); struct scsi_request *req = &cmd->req; - memset(req->__cmd, 0, sizeof(req->__cmd)); - req->cmd = req->__cmd; - req->cmd_len = BLK_MAX_CDB; + memset(cmd->cmnd, 0, sizeof(cmd->cmnd)); + cmd->cmd_len = MAX_COMMAND_SIZE; + req->sense_len = 0; init_rcu_head(&cmd->rcu); @@ -1196,8 +1198,6 @@ static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev, memset(&cmd->sdb, 0, sizeof(cmd->sdb)); } - cmd->cmd_len = scsi_req(req)->cmd_len; - cmd->cmnd = scsi_req(req)->cmd; cmd->transfersize = blk_rq_bytes(req); cmd->allowed = scsi_req(req)->retries; return BLK_STS_OK; @@ -1567,8 +1567,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req) cmd->prot_type = 0; cmd->prot_flags = 0; cmd->submitter = 0; - cmd->cmd_len = 0; - cmd->cmnd = NULL; memset(&cmd->sdb, 0, sizeof(cmd->sdb)); cmd->underflow = 0; cmd->transfersize = 0; @@ -1616,8 +1614,7 @@ static blk_status_t scsi_prepare_cmd(struct request *req) return ret; } - cmd->cmnd = scsi_req(req)->cmd = scsi_req(req)->__cmd; - memset(cmd->cmnd, 0, BLK_MAX_CDB); + memset(cmd->cmnd, 0, sizeof(cmd->cmnd)); return scsi_cmd_to_driver(cmd)->init_command(cmd); } diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c index 1f8f80b2dbfc..ff89de86545d 100644 --- a/drivers/scsi/scsi_logging.c +++ b/drivers/scsi/scsi_logging.c @@ -87,7 +87,7 @@ void scmd_printk(const char *level, const struct scsi_cmnd *scmd, char *logbuf; size_t off = 0, logbuf_len; - if (!scmd || !scmd->cmnd) + if (!scmd) return; logbuf = scsi_log_reserve_buffer(&logbuf_len); @@ -183,9 +183,6 @@ void scsi_print_command(struct scsi_cmnd *cmd) char *logbuf; size_t off, logbuf_len; - if (!cmd->cmnd) - return; - logbuf = scsi_log_reserve_buffer(&logbuf_len); if (!logbuf) return; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index bf32a0541427..2f9d160bc8c2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -128,7 +128,6 @@ static DEFINE_IDA(sd_index_ida); static DEFINE_MUTEX(sd_ref_mutex); static struct kmem_cache *sd_cdb_cache; -static mempool_t *sd_cdb_pool; static mempool_t *sd_page_pool; static struct lock_class_key sd_bio_compl_lkclass; @@ -1075,13 +1074,7 @@ static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write, sector_t lba, unsigned int nr_blocks, unsigned char flags) { - cmd->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); - if (unlikely(cmd->cmnd == NULL)) - return BLK_STS_RESOURCE; - cmd->cmd_len = SD_EXT_CDB_SIZE; - memset(cmd->cmnd, 0, cmd->cmd_len); - cmd->cmnd[0] = VARIABLE_LENGTH_CMD; cmd->cmnd[7] = 0x18; /* Additional CDB len */ cmd->cmnd[9] = write ? WRITE_32 : READ_32; @@ -1313,17 +1306,9 @@ static blk_status_t sd_init_command(struct scsi_cmnd *cmd) static void sd_uninit_command(struct scsi_cmnd *SCpnt) { struct request *rq = scsi_cmd_to_rq(SCpnt); - u8 *cmnd; if (rq->rq_flags & RQF_SPECIAL_PAYLOAD) mempool_free(rq->special_vec.bv_page, sd_page_pool); - - if (SCpnt->cmnd != scsi_req(rq)->cmd) { - cmnd = SCpnt->cmnd; - SCpnt->cmnd = NULL; - SCpnt->cmd_len = 0; - mempool_free(cmnd, sd_cdb_pool); - } } static bool sd_need_revalidate(struct block_device *bdev, @@ -3819,18 +3804,11 @@ static int __init init_sd(void) goto err_out_class; } - sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache); - if (!sd_cdb_pool) { - printk(KERN_ERR "sd: can't init extended cdb pool\n"); - err = -ENOMEM; - goto err_out_cache; - } - sd_page_pool = mempool_create_page_pool(SD_MEMPOOL_SIZE, 0); if (!sd_page_pool) { printk(KERN_ERR "sd: can't init discard page pool\n"); err = -ENOMEM; - goto err_out_ppool; + goto err_out_cache; } err = scsi_register_driver(&sd_template.gendrv); @@ -3842,9 +3820,6 @@ static int __init init_sd(void) err_out_driver: mempool_destroy(sd_page_pool); -err_out_ppool: - mempool_destroy(sd_cdb_pool); - err_out_cache: kmem_cache_destroy(sd_cdb_cache); @@ -3868,7 +3843,6 @@ static void __exit exit_sd(void) SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); scsi_unregister_driver(&sd_template.gendrv); - mempool_destroy(sd_cdb_pool); mempool_destroy(sd_page_pool); kmem_cache_destroy(sd_cdb_cache); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index bbd75026ec93..cc3f11270dc2 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -818,7 +818,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, } if (atomic_read(&sdp->detaching)) { if (srp->bio) { - scsi_req_free_cmd(scsi_req(srp->rq)); blk_mq_free_request(srp->rq); srp->rq = NULL; } @@ -1393,7 +1392,6 @@ sg_rq_end_io(struct request *rq, blk_status_t status) * blk_rq_unmap_user() can be called from user context. */ srp->rq = NULL; - scsi_req_free_cmd(scsi_req(rq)); blk_mq_free_request(rq); write_lock_irqsave(&sfp->rq_list_lock, iflags); @@ -1738,18 +1736,12 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) struct request_queue *q = sfp->parentdp->device->request_queue; struct rq_map_data *md, map_data; int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; - unsigned char *long_cmdp = NULL; + struct scsi_cmnd *scmd; SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, "sg_start_req: dxfer_len=%d\n", dxfer_len)); - if (hp->cmd_len > BLK_MAX_CDB) { - long_cmdp = kzalloc(hp->cmd_len, GFP_KERNEL); - if (!long_cmdp) - return -ENOMEM; - } - /* * NOTE * @@ -1763,16 +1755,18 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) */ rq = scsi_alloc_request(q, hp->dxfer_direction == SG_DXFER_TO_DEV ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); - if (IS_ERR(rq)) { - kfree(long_cmdp); + if (IS_ERR(rq)) return PTR_ERR(rq); - } + scmd = blk_mq_rq_to_pdu(rq); req = scsi_req(rq); - if (hp->cmd_len > BLK_MAX_CDB) - req->cmd = long_cmdp; - memcpy(req->cmd, cmd, hp->cmd_len); - req->cmd_len = hp->cmd_len; + if (hp->cmd_len > sizeof(scmd->cmnd)) { + blk_mq_free_request(rq); + return -EINVAL; + } + + memcpy(scmd->cmnd, cmd, hp->cmd_len); + scmd->cmd_len = hp->cmd_len; srp->rq = rq; rq->end_io_data = srp; @@ -1865,10 +1859,8 @@ sg_finish_rem_req(Sg_request *srp) if (srp->bio) ret = blk_rq_unmap_user(srp->bio); - if (srp->rq) { - scsi_req_free_cmd(scsi_req(srp->rq)); + if (srp->rq) blk_mq_free_request(srp->rq); - } if (srp->res_used) sg_unlink_reserve(sfp, srp); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index f925b1f1f9ad..3adba389cae5 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -966,6 +966,7 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, struct gendisk *disk = cdi->disk; u32 len = nr * CD_FRAMESIZE_RAW; struct scsi_request *req; + struct scsi_cmnd *scmd; struct request *rq; struct bio *bio; int ret; @@ -974,22 +975,23 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, if (IS_ERR(rq)) return PTR_ERR(rq); req = scsi_req(rq); + scmd = blk_mq_rq_to_pdu(rq); ret = blk_rq_map_user(disk->queue, rq, NULL, ubuf, len, GFP_KERNEL); if (ret) goto out_put_request; - req->cmd[0] = GPCMD_READ_CD; - req->cmd[1] = 1 << 2; - req->cmd[2] = (lba >> 24) & 0xff; - req->cmd[3] = (lba >> 16) & 0xff; - req->cmd[4] = (lba >> 8) & 0xff; - req->cmd[5] = lba & 0xff; - req->cmd[6] = (nr >> 16) & 0xff; - req->cmd[7] = (nr >> 8) & 0xff; - req->cmd[8] = nr & 0xff; - req->cmd[9] = 0xf8; - req->cmd_len = 12; + scmd->cmnd[0] = GPCMD_READ_CD; + scmd->cmnd[1] = 1 << 2; + scmd->cmnd[2] = (lba >> 24) & 0xff; + scmd->cmnd[3] = (lba >> 16) & 0xff; + scmd->cmnd[4] = (lba >> 8) & 0xff; + scmd->cmnd[5] = lba & 0xff; + scmd->cmnd[6] = (nr >> 16) & 0xff; + scmd->cmnd[7] = (nr >> 8) & 0xff; + scmd->cmnd[8] = nr & 0xff; + scmd->cmnd[9] = 0xf8; + scmd->cmd_len = 12; rq->timeout = 60 * HZ; bio = rq->bio; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index e869e90e05af..229e819a1797 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -472,10 +472,11 @@ static void st_release_request(struct st_request *streq) static void st_do_stats(struct scsi_tape *STp, struct request *req) { + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); ktime_t now; now = ktime_get(); - if (scsi_req(req)->cmd[0] == WRITE_6) { + if (scmd->cmnd[0] == WRITE_6) { now = ktime_sub(now, STp->stats->write_time); atomic64_add(ktime_to_ns(now), &STp->stats->tot_write_time); atomic64_add(ktime_to_ns(now), &STp->stats->tot_io_time); @@ -489,7 +490,7 @@ static void st_do_stats(struct scsi_tape *STp, struct request *req) } else atomic64_add(atomic_read(&STp->stats->last_write_size), &STp->stats->write_byte_cnt); - } else if (scsi_req(req)->cmd[0] == READ_6) { + } else if (scmd->cmnd[0] == READ_6) { now = ktime_sub(now, STp->stats->read_time); atomic64_add(ktime_to_ns(now), &STp->stats->tot_read_time); atomic64_add(ktime_to_ns(now), &STp->stats->tot_io_time); @@ -542,12 +543,14 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data; int err = 0; struct scsi_tape *STp = SRpnt->stp; + struct scsi_cmnd *scmd; req = scsi_alloc_request(SRpnt->stp->device->request_queue, data_direction == DMA_TO_DEVICE ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(req)) return PTR_ERR(req); + scmd = blk_mq_rq_to_pdu(req); rq = scsi_req(req); req->rq_flags |= RQF_QUIET; @@ -574,9 +577,8 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, } SRpnt->bio = req->bio; - rq->cmd_len = COMMAND_SIZE(cmd[0]); - memset(rq->cmd, 0, BLK_MAX_CDB); - memcpy(rq->cmd, cmd, rq->cmd_len); + scmd->cmd_len = COMMAND_SIZE(cmd[0]); + memcpy(scmd->cmnd, cmd, scmd->cmd_len); req->timeout = timeout; rq->retries = retries; req->end_io_data = SRpnt; diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c index 2d36a0715fca..3ca745ad616c 100644 --- a/drivers/scsi/ufs/ufshpb.c +++ b/drivers/scsi/ufs/ufshpb.c @@ -666,15 +666,14 @@ static void ufshpb_execute_umap_req(struct ufshpb_lu *hpb, struct ufshpb_req *umap_req, struct ufshpb_region *rgn) { - struct request *req; - struct scsi_request *rq; + struct request *req = umap_req->req; + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); - req = umap_req->req; req->timeout = 0; - req->end_io_data = (void *)umap_req; - rq = scsi_req(req); - ufshpb_set_unmap_cmd(rq->cmd, rgn); - rq->cmd_len = HPB_WRITE_BUFFER_CMD_LENGTH; + req->end_io_data = umap_req; + + ufshpb_set_unmap_cmd(scmd->cmnd, rgn); + scmd->cmd_len = HPB_WRITE_BUFFER_CMD_LENGTH; blk_execute_rq_nowait(req, true, ufshpb_umap_req_compl_fn); @@ -686,7 +685,7 @@ static int ufshpb_execute_map_req(struct ufshpb_lu *hpb, { struct request_queue *q; struct request *req; - struct scsi_request *rq; + struct scsi_cmnd *scmd; int mem_size = hpb->srgn_mem_size; int ret = 0; int i; @@ -709,14 +708,13 @@ static int ufshpb_execute_map_req(struct ufshpb_lu *hpb, req->end_io_data = map_req; - rq = scsi_req(req); - if (unlikely(last)) mem_size = hpb->last_srgn_entries * HPB_ENTRY_SIZE; - ufshpb_set_read_buf_cmd(rq->cmd, map_req->rb.rgn_idx, + scmd = blk_mq_rq_to_pdu(req); + ufshpb_set_read_buf_cmd(scmd->cmnd, map_req->rb.rgn_idx, map_req->rb.srgn_idx, mem_size); - rq->cmd_len = HPB_READ_BUFFER_CMD_LENGTH; + scmd->cmd_len = HPB_READ_BUFFER_CMD_LENGTH; blk_execute_rq_nowait(req, true, ufshpb_map_req_compl_fn); diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 622158ed5d9c..0a8078db923d 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -961,6 +961,7 @@ pscsi_execute_cmd(struct se_cmd *cmd) struct scatterlist *sgl = cmd->t_data_sg; u32 sgl_nents = cmd->t_data_nents; struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); + struct scsi_cmnd *scmd; struct request *req; sense_reason_t ret; @@ -978,12 +979,15 @@ pscsi_execute_cmd(struct se_cmd *cmd) req->end_io = pscsi_req_done; req->end_io_data = cmd; - scsi_req(req)->cmd_len = scsi_command_size(cmd->t_task_cdb); - if (scsi_req(req)->cmd_len > BLK_MAX_CDB) { + + scmd = blk_mq_rq_to_pdu(req); + scmd->cmd_len = scsi_command_size(cmd->t_task_cdb); + if (scmd->cmd_len > sizeof(scmd->cmnd)) { ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto fail_put_request; } - memcpy(scsi_req(req)->cmd, cmd->t_task_cdb, scsi_req(req)->cmd_len); + memcpy(scmd->cmnd, cmd->t_task_cdb, scmd->cmd_len); + if (pdv->pdv_sd->type == TYPE_DISK || pdv->pdv_sd->type == TYPE_ZBC) req->timeout = PS_TIMEOUT_DISK; @@ -991,7 +995,7 @@ pscsi_execute_cmd(struct se_cmd *cmd) req->timeout = PS_TIMEOUT_OTHER; scsi_req(req)->retries = PS_RETRY; - cmd->priv = scsi_req(req)->cmd; + cmd->priv = scmd->cmnd; blk_execute_rq_nowait(req, cmd->sam_task_attr == TCM_HEAD_TAG, pscsi_req_done); diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 2f7093ba5a2f..98b3ec352a13 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -177,7 +177,6 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) * but reading register selected in srb->cmnd[4] */ srb->cmd_len = 16; - srb->cmnd = ses.cmnd; srb->cmnd[2] = 1; usb_stor_transparent_scsi_command(srb, us); diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 3c76336e43bb..05429f1f69f9 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -326,7 +326,7 @@ struct isd200_info { /* maximum number of LUNs supported */ unsigned char MaxLUNs; - unsigned char cmnd[BLK_MAX_CDB]; + unsigned char cmnd[MAX_COMMAND_SIZE]; struct scsi_cmnd srb; struct scatterlist sg; }; @@ -485,7 +485,7 @@ static int isd200_action( struct us_data *us, int action, int status; memset(&ata, 0, sizeof(ata)); - srb->cmnd = info->cmnd; + memcpy(srb->cmnd, info->cmnd, MAX_COMMAND_SIZE); srb->device = &srb_dev; ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 7a19c8bbaed9..3e432e25645a 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -28,9 +28,6 @@ struct scsi_driver; * supports without specifying a cmd_len by ULD's */ #define MAX_COMMAND_SIZE 16 -#if (MAX_COMMAND_SIZE > BLK_MAX_CDB) -# error MAX_COMMAND_SIZE can not be bigger than BLK_MAX_CDB -#endif struct scsi_data_buffer { struct sg_table table; @@ -100,9 +97,7 @@ struct scsi_cmnd { unsigned short cmd_len; enum dma_data_direction sc_data_direction; - /* These elements define the operation we are about to perform */ - unsigned char *cmnd; - + unsigned char cmnd[32]; /* SCSI CDB */ /* These elements define the operation we ultimately want to perform */ struct scsi_data_buffer sdb; diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 468094254b3c..1ae08e81339f 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -38,10 +38,8 @@ struct scsi_eh_save { unsigned underflow; unsigned char cmd_len; unsigned char prot_op; - unsigned char *cmnd; + unsigned char cmnd[32]; struct scsi_data_buffer sdb; - /* new command support */ - unsigned char eh_cmnd[BLK_MAX_CDB]; struct scatterlist sense_sgl; }; diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index 9129b23e12bc..aeee0611bcbe 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -4,12 +4,7 @@ #include -#define BLK_MAX_CDB 16 - struct scsi_request { - unsigned char __cmd[BLK_MAX_CDB]; - unsigned char *cmd; - unsigned short cmd_len; int result; unsigned int sense_len; unsigned int resid_len; /* residual count */ @@ -22,10 +17,4 @@ static inline struct scsi_request *scsi_req(struct request *rq) return blk_mq_rq_to_pdu(rq); } -static inline void scsi_req_free_cmd(struct scsi_request *req) -{ - if (req->cmd != req->__cmd) - kfree(req->cmd); -} - #endif /* _SCSI_SCSI_REQUEST_H */ -- cgit v1.2.3 From 5b794f98074a8b7e8eb77dd43746062940b51160 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 24 Feb 2022 18:55:48 +0100 Subject: scsi: core: Remove the sense and sense_len fields from struct scsi_request Just use the sense_buffer field in struct scsi_cmnd for the sense data and move the sense_len field over to struct scsi_cmnd. Link: https://lore.kernel.org/r/20220224175552.988286-5-hch@lst.de Reviewed-by: Bart Van Assche Reviewed-by: John Garry Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_bsg.c | 7 ++++--- drivers/scsi/scsi_ioctl.c | 16 ++++++++-------- drivers/scsi/scsi_lib.c | 18 +++++++----------- drivers/scsi/sg.c | 7 ++++--- drivers/scsi/sr.c | 2 +- drivers/scsi/st.c | 5 +++-- drivers/target/target_core_pscsi.c | 3 ++- include/scsi/scsi_cmnd.h | 1 + include/scsi/scsi_request.h | 2 -- 9 files changed, 30 insertions(+), 31 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c index f8b65bd75ee1..0a6f6140501b 100644 --- a/drivers/scsi/scsi_bsg.c +++ b/drivers/scsi/scsi_bsg.c @@ -76,11 +76,12 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, hdr->info |= SG_INFO_CHECK; hdr->response_len = 0; - if (sreq->sense_len && hdr->response) { + if (scmd->sense_len && hdr->response) { int len = min_t(unsigned int, hdr->max_response_len, - sreq->sense_len); + scmd->sense_len); - if (copy_to_user(uptr64(hdr->response), sreq->sense, len)) + if (copy_to_user(uptr64(hdr->response), scmd->sense_buffer, + len)) ret = -EFAULT; else hdr->response_len = len; diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 6d9f1b44566d..5d0ec21a7e5f 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -369,6 +369,7 @@ static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq, static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, struct bio *bio) { + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); struct scsi_request *req = scsi_req(rq); int r, ret = 0; @@ -388,10 +389,10 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, hdr->resid = req->resid_len; hdr->sb_len_wr = 0; - if (req->sense_len && hdr->sbp) { - int len = min((unsigned int) hdr->mx_sb_len, req->sense_len); + if (scmd->sense_len && hdr->sbp) { + int len = min((unsigned int) hdr->mx_sb_len, scmd->sense_len); - if (!copy_to_user(hdr->sbp, req->sense, len)) + if (!copy_to_user(hdr->sbp, scmd->sense_buffer, len)) hdr->sb_len_wr = len; else ret = -EFAULT; @@ -520,7 +521,6 @@ out_put_request: static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, struct scsi_ioctl_command __user *sic) { - enum { OMAX_SB_LEN = 16 }; /* For backward compatibility */ struct request *rq; struct scsi_request *req; int err; @@ -613,10 +613,10 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, err = req->result & 0xff; /* only 8 bit SCSI status */ if (err) { - if (req->sense_len && req->sense) { - bytes = (OMAX_SB_LEN > req->sense_len) ? - req->sense_len : OMAX_SB_LEN; - if (copy_to_user(sic->data, req->sense, bytes)) + if (scmd->sense_len && scmd->sense_buffer) { + /* limit sense len for backward compatibility */ + if (copy_to_user(sic->data, scmd->sense_buffer, + min(scmd->sense_len, 16U))) err = -EFAULT; } } else { diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 623c8cbcaef8..896b3ecdce8e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -256,10 +256,11 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, if (resid) *resid = rq->resid_len; - if (sense && rq->sense_len) - memcpy(sense, rq->sense, SCSI_SENSE_BUFFERSIZE); + if (sense && scmd->sense_len) + memcpy(sense, scmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); if (sshdr) - scsi_normalize_sense(rq->sense, rq->sense_len, sshdr); + scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len, + sshdr); ret = rq->result; out: blk_mq_free_request(req); @@ -876,9 +877,8 @@ static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, int result, /* * SG_IO wants current and deferred errors */ - scsi_req(req)->sense_len = - min(8 + cmd->sense_buffer[7], - SCSI_SENSE_BUFFERSIZE); + cmd->sense_len = min(8 + cmd->sense_buffer[7], + SCSI_SENSE_BUFFERSIZE); } if (sense_current) *blk_statp = scsi_result_to_blk_status(cmd, result); @@ -1126,13 +1126,10 @@ EXPORT_SYMBOL(scsi_alloc_sgtables); static void scsi_initialize_rq(struct request *rq) { struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); - struct scsi_request *req = &cmd->req; memset(cmd->cmnd, 0, sizeof(cmd->cmnd)); cmd->cmd_len = MAX_COMMAND_SIZE; - - req->sense_len = 0; - + cmd->sense_len = 0; init_rcu_head(&cmd->rcu); cmd->jiffies_at_alloc = jiffies; cmd->retries = 0; @@ -1824,7 +1821,6 @@ static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq, kmem_cache_alloc_node(scsi_sense_cache, GFP_KERNEL, numa_node); if (!cmd->sense_buffer) return -ENOMEM; - cmd->req.sense = cmd->sense_buffer; if (scsi_host_get_prot(shost)) { sg = (void *)cmd + sizeof(struct scsi_cmnd) + diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index cc3f11270dc2..0f96c7cde9e5 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1323,6 +1323,7 @@ sg_rq_end_io_usercontext(struct work_struct *work) static void sg_rq_end_io(struct request *rq, blk_status_t status) { + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); struct sg_request *srp = rq->end_io_data; struct scsi_request *req = scsi_req(rq); Sg_device *sdp; @@ -1343,7 +1344,7 @@ sg_rq_end_io(struct request *rq, blk_status_t status) if (unlikely(atomic_read(&sdp->detaching))) pr_info("%s: device detaching\n", __func__); - sense = req->sense; + sense = scmd->sense_buffer; result = req->result; resid = req->resid_len; @@ -1380,8 +1381,8 @@ sg_rq_end_io(struct request *rq, blk_status_t status) } } - if (req->sense_len) - memcpy(srp->sense_b, req->sense, SCSI_SENSE_BUFFERSIZE); + if (scmd->sense_len) + memcpy(srp->sense_b, scmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); /* Rely on write phase to clean out srp status values, so no "else" */ diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 3adba389cae5..1d19dd13d7f0 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -999,7 +999,7 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, if (scsi_req(rq)->result) { struct scsi_sense_hdr sshdr; - scsi_normalize_sense(req->sense, req->sense_len, + scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len, &sshdr); *last_sense = sshdr.sense_key; ret = -EIO; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 229e819a1797..9b98e848d78c 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -514,6 +514,7 @@ static void st_do_stats(struct scsi_tape *STp, struct request *req) static void st_scsi_execute_end(struct request *req, blk_status_t status) { + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); struct st_request *SRpnt = req->end_io_data; struct scsi_request *rq = scsi_req(req); struct scsi_tape *STp = SRpnt->stp; @@ -525,8 +526,8 @@ static void st_scsi_execute_end(struct request *req, blk_status_t status) st_do_stats(STp, req); tmp = SRpnt->bio; - if (rq->sense_len) - memcpy(SRpnt->sense, rq->sense, SCSI_SENSE_BUFFERSIZE); + if (scmd->sense_len) + memcpy(SRpnt->sense, scmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); if (SRpnt->waiting) complete(SRpnt->waiting); diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 0a8078db923d..9146193d0576 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1031,6 +1031,7 @@ static sector_t pscsi_get_blocks(struct se_device *dev) static void pscsi_req_done(struct request *req, blk_status_t status) { struct se_cmd *cmd = req->end_io_data; + struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); int result = scsi_req(req)->result; enum sam_status scsi_status = result & 0xff; u8 *cdb = cmd->priv; @@ -1040,7 +1041,7 @@ static void pscsi_req_done(struct request *req, blk_status_t status) " 0x%02x Result: 0x%08x\n", cmd, cdb[0], result); } - pscsi_complete_cmd(cmd, scsi_status, scsi_req(req)->sense); + pscsi_complete_cmd(cmd, scsi_status, scmd->sense_buffer); switch (host_byte(result)) { case DID_OK: diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 3e432e25645a..47add5b32f46 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -112,6 +112,7 @@ struct scsi_cmnd { reconnects. Probably == sector size */ + unsigned sense_len; unsigned char *sense_buffer; /* obtained by REQUEST SENSE when * CHECK CONDITION is received on original diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index aeee0611bcbe..bed1cc49132a 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -6,10 +6,8 @@ struct scsi_request { int result; - unsigned int sense_len; unsigned int resid_len; /* residual count */ int retries; - void *sense; }; static inline struct scsi_request *scsi_req(struct request *rq) -- cgit v1.2.3 From a9a4ea1166d640d1b397f24afc1cd7e96c46cd03 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 24 Feb 2022 18:55:49 +0100 Subject: scsi: core: Move the resid_len field from struct scsi_request to struct scsi_cmnd Prepare for removing the scsi_request structure by moving the resid_len field to struct scsi_cmnd. Link: https://lore.kernel.org/r/20220224175552.988286-6-hch@lst.de Reviewed-by: Bart Van Assche Reviewed-by: John Garry Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_bsg.c | 4 ++-- drivers/scsi/scsi_error.c | 6 +++--- drivers/scsi/scsi_ioctl.c | 2 +- drivers/scsi/scsi_lib.c | 6 +++--- drivers/scsi/sg.c | 2 +- drivers/scsi/st.c | 2 +- drivers/target/target_core_pscsi.c | 2 +- include/scsi/scsi_cmnd.h | 6 +++--- include/scsi/scsi_request.h | 1 - 9 files changed, 15 insertions(+), 16 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c index 0a6f6140501b..4c697d0ddf1d 100644 --- a/drivers/scsi/scsi_bsg.c +++ b/drivers/scsi/scsi_bsg.c @@ -88,9 +88,9 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, } if (rq_data_dir(rq) == READ) - hdr->din_resid = sreq->resid_len; + hdr->din_resid = scmd->resid_len; else - hdr->dout_resid = sreq->resid_len; + hdr->dout_resid = scmd->resid_len; blk_rq_unmap_user(bio); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5383139a3de8..cf02d1c50389 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1005,7 +1005,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->result = scmd->result; - ses->resid_len = scmd->req.resid_len; + ses->resid_len = scmd->resid_len; ses->underflow = scmd->underflow; ses->prot_op = scmd->prot_op; ses->eh_eflags = scmd->eh_eflags; @@ -1016,7 +1016,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->result = 0; - scmd->req.resid_len = 0; + scmd->resid_len = 0; if (sense_bytes) { scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE, @@ -1069,7 +1069,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->result = ses->result; - scmd->req.resid_len = ses->resid_len; + scmd->resid_len = ses->resid_len; scmd->underflow = ses->underflow; scmd->prot_op = ses->prot_op; scmd->eh_eflags = ses->eh_eflags; diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 5d0ec21a7e5f..b066fdd6305a 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -386,7 +386,7 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, hdr->info = 0; if (hdr->masked_status || hdr->host_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; - hdr->resid = req->resid_len; + hdr->resid = scmd->resid_len; hdr->sb_len_wr = 0; if (scmd->sense_len && hdr->sbp) { diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 896b3ecdce8e..a9d8e80032a3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -251,11 +251,11 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, * is invalid. Prevent the garbage from being misinterpreted * and prevent security leaks by zeroing out the excess data. */ - if (unlikely(rq->resid_len > 0 && rq->resid_len <= bufflen)) - memset(buffer + (bufflen - rq->resid_len), 0, rq->resid_len); + if (unlikely(scmd->resid_len > 0 && scmd->resid_len <= bufflen)) + memset(buffer + bufflen - scmd->resid_len, 0, scmd->resid_len); if (resid) - *resid = rq->resid_len; + *resid = scmd->resid_len; if (sense && scmd->sense_len) memcpy(sense, scmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); if (sshdr) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 0f96c7cde9e5..3eaabfb315e0 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1346,7 +1346,7 @@ sg_rq_end_io(struct request *rq, blk_status_t status) sense = scmd->sense_buffer; result = req->result; - resid = req->resid_len; + resid = scmd->resid_len; SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, "sg_cmd_done: pack_id=%d, res=0x%x\n", diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 9b98e848d78c..0546d2c84ad1 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -521,7 +521,7 @@ static void st_scsi_execute_end(struct request *req, blk_status_t status) struct bio *tmp; STp->buffer->cmdstat.midlevel_result = SRpnt->result = rq->result; - STp->buffer->cmdstat.residual = rq->resid_len; + STp->buffer->cmdstat.residual = scmd->resid_len; st_do_stats(STp, req); diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 9146193d0576..d5828da3d392 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1046,7 +1046,7 @@ static void pscsi_req_done(struct request *req, blk_status_t status) switch (host_byte(result)) { case DID_OK: target_complete_cmd_with_length(cmd, scsi_status, - cmd->data_length - scsi_req(req)->resid_len); + cmd->data_length - scmd->resid_len); break; default: pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 47add5b32f46..5ff0a6e8460c 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -111,7 +111,7 @@ struct scsi_cmnd { (ie, between disconnect / reconnects. Probably == sector size */ - + unsigned resid_len; /* residual count */ unsigned sense_len; unsigned char *sense_buffer; /* obtained by REQUEST SENSE when @@ -200,12 +200,12 @@ static inline unsigned scsi_bufflen(struct scsi_cmnd *cmd) static inline void scsi_set_resid(struct scsi_cmnd *cmd, unsigned int resid) { - cmd->req.resid_len = resid; + cmd->resid_len = resid; } static inline unsigned int scsi_get_resid(struct scsi_cmnd *cmd) { - return cmd->req.resid_len; + return cmd->resid_len; } #define scsi_for_each_sg(cmd, sg, nseg, __i) \ diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index bed1cc49132a..74be75336a54 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -6,7 +6,6 @@ struct scsi_request { int result; - unsigned int resid_len; /* residual count */ int retries; }; -- cgit v1.2.3 From dbb4c84d87af7416bb7e35f8e6dd8d87d5f221d4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 24 Feb 2022 18:55:50 +0100 Subject: scsi: core: Move the result field from struct scsi_request to struct scsi_cmnd Prepare for removing the scsi_request structure by moving the result field to struct scsi_cmnd. Link: https://lore.kernel.org/r/20220224175552.988286-7-hch@lst.de Reviewed-by: Bart Van Assche Reviewed-by: John Garry Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/block/pktcdvd.c | 2 +- drivers/scsi/scsi_bsg.c | 8 +++----- drivers/scsi/scsi_ioctl.c | 9 ++++----- drivers/scsi/scsi_lib.c | 15 ++++----------- drivers/scsi/sg.c | 3 +-- drivers/scsi/sr.c | 2 +- drivers/scsi/st.c | 7 +++---- drivers/target/target_core_pscsi.c | 9 ++++----- include/scsi/scsi_request.h | 1 - 9 files changed, 21 insertions(+), 35 deletions(-) (limited to 'include/scsi') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 42c284b2d7f9..aca94ebf4947 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -718,7 +718,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command * rq->rq_flags |= RQF_QUIET; blk_execute_rq(rq, false); - if (scsi_req(rq)->result) + if (scmd->result) ret = -EIO; out: blk_mq_free_request(rq); diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c index 4c697d0ddf1d..8039c3c11a6e 100644 --- a/drivers/scsi/scsi_bsg.c +++ b/drivers/scsi/scsi_bsg.c @@ -12,7 +12,6 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, fmode_t mode, unsigned int timeout) { - struct scsi_request *sreq; struct scsi_cmnd *scmd; struct request *rq; struct bio *bio; @@ -33,7 +32,6 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, rq->timeout = timeout; ret = -ENOMEM; - sreq = scsi_req(rq); scmd = blk_mq_rq_to_pdu(rq); scmd->cmd_len = hdr->request_len; if (scmd->cmd_len > sizeof(scmd->cmnd)) { @@ -66,10 +64,10 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr, /* * fill in all the output members */ - hdr->device_status = sreq->result & 0xff; - hdr->transport_status = host_byte(sreq->result); + hdr->device_status = scmd->result & 0xff; + hdr->transport_status = host_byte(scmd->result); hdr->driver_status = 0; - if (scsi_status_is_check_condition(sreq->result)) + if (scsi_status_is_check_condition(scmd->result)) hdr->driver_status = DRIVER_SENSE; hdr->info = 0; if (hdr->device_status || hdr->transport_status || hdr->driver_status) diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index b066fdd6305a..04b7c70d1dba 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -370,16 +370,15 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, struct bio *bio) { struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); - struct scsi_request *req = scsi_req(rq); int r, ret = 0; /* * fill in all the output members */ - hdr->status = req->result & 0xff; - hdr->masked_status = status_byte(req->result); + hdr->status = scmd->result & 0xff; + hdr->masked_status = status_byte(scmd->result); hdr->msg_status = COMMAND_COMPLETE; - hdr->host_status = host_byte(req->result); + hdr->host_status = host_byte(scmd->result); hdr->driver_status = 0; if (scsi_status_is_check_condition(hdr->status)) hdr->driver_status = DRIVER_SENSE; @@ -611,7 +610,7 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, blk_execute_rq(rq, false); - err = req->result & 0xff; /* only 8 bit SCSI status */ + err = scmd->result & 0xff; /* only 8 bit SCSI status */ if (err) { if (scmd->sense_len && scmd->sense_buffer) { /* limit sense len for backward compatibility */ diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a9d8e80032a3..0c41e023a3ce 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -261,7 +261,7 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, if (sshdr) scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len, sshdr); - ret = rq->result; + ret = scmd->result; out: blk_mq_free_request(req); @@ -959,13 +959,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) if (unlikely(result)) /* a nz result may or may not be an error */ result = scsi_io_completion_nz_result(cmd, result, &blk_stat); - if (unlikely(blk_rq_is_passthrough(req))) { - /* - * scsi_result_to_blk_status may have reset the host_byte - */ - scsi_req(req)->result = cmd->result; - } - /* * Next deal with any sectors which we were able to correctly * handle. @@ -1779,15 +1772,15 @@ out_put_budget: ret = BLK_STS_DEV_RESOURCE; break; case BLK_STS_AGAIN: - scsi_req(req)->result = DID_BUS_BUSY << 16; + cmd->result = DID_BUS_BUSY << 16; if (req->rq_flags & RQF_DONTPREP) scsi_mq_uninit_cmd(cmd); break; default: if (unlikely(!scsi_device_online(sdev))) - scsi_req(req)->result = DID_NO_CONNECT << 16; + cmd->result = DID_NO_CONNECT << 16; else - scsi_req(req)->result = DID_ERROR << 16; + cmd->result = DID_ERROR << 16; /* * Make sure to release all allocated resources when * we hit an error, as we will never see this command diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 3eaabfb315e0..26a753521cb2 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1325,7 +1325,6 @@ sg_rq_end_io(struct request *rq, blk_status_t status) { struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq); struct sg_request *srp = rq->end_io_data; - struct scsi_request *req = scsi_req(rq); Sg_device *sdp; Sg_fd *sfp; unsigned long iflags; @@ -1345,7 +1344,7 @@ sg_rq_end_io(struct request *rq, blk_status_t status) pr_info("%s: device detaching\n", __func__); sense = scmd->sense_buffer; - result = req->result; + result = scmd->result; resid = scmd->resid_len; SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 1d19dd13d7f0..494d00b05f53 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -996,7 +996,7 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, bio = rq->bio; blk_execute_rq(rq, false); - if (scsi_req(rq)->result) { + if (scmd->result) { struct scsi_sense_hdr sshdr; scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len, diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 0546d2c84ad1..c8533ca225bc 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -481,7 +481,7 @@ static void st_do_stats(struct scsi_tape *STp, struct request *req) atomic64_add(ktime_to_ns(now), &STp->stats->tot_write_time); atomic64_add(ktime_to_ns(now), &STp->stats->tot_io_time); atomic64_inc(&STp->stats->write_cnt); - if (scsi_req(req)->result) { + if (scmd->result) { atomic64_add(atomic_read(&STp->stats->last_write_size) - STp->buffer->cmdstat.residual, &STp->stats->write_byte_cnt); @@ -495,7 +495,7 @@ static void st_do_stats(struct scsi_tape *STp, struct request *req) atomic64_add(ktime_to_ns(now), &STp->stats->tot_read_time); atomic64_add(ktime_to_ns(now), &STp->stats->tot_io_time); atomic64_inc(&STp->stats->read_cnt); - if (scsi_req(req)->result) { + if (scmd->result) { atomic64_add(atomic_read(&STp->stats->last_read_size) - STp->buffer->cmdstat.residual, &STp->stats->read_byte_cnt); @@ -516,11 +516,10 @@ static void st_scsi_execute_end(struct request *req, blk_status_t status) { struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); struct st_request *SRpnt = req->end_io_data; - struct scsi_request *rq = scsi_req(req); struct scsi_tape *STp = SRpnt->stp; struct bio *tmp; - STp->buffer->cmdstat.midlevel_result = SRpnt->result = rq->result; + STp->buffer->cmdstat.midlevel_result = SRpnt->result = scmd->result; STp->buffer->cmdstat.residual = scmd->resid_len; st_do_stats(STp, req); diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index d5828da3d392..5b23a0ff905e 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1032,25 +1032,24 @@ static void pscsi_req_done(struct request *req, blk_status_t status) { struct se_cmd *cmd = req->end_io_data; struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); - int result = scsi_req(req)->result; - enum sam_status scsi_status = result & 0xff; + enum sam_status scsi_status = scmd->result & 0xff; u8 *cdb = cmd->priv; if (scsi_status != SAM_STAT_GOOD) { pr_debug("PSCSI Status Byte exception at cmd: %p CDB:" - " 0x%02x Result: 0x%08x\n", cmd, cdb[0], result); + " 0x%02x Result: 0x%08x\n", cmd, cdb[0], scmd->result); } pscsi_complete_cmd(cmd, scsi_status, scmd->sense_buffer); - switch (host_byte(result)) { + switch (host_byte(scmd->result)) { case DID_OK: target_complete_cmd_with_length(cmd, scsi_status, cmd->data_length - scmd->resid_len); break; default: pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" - " 0x%02x Result: 0x%08x\n", cmd, cdb[0], result); + " 0x%02x Result: 0x%08x\n", cmd, cdb[0], scmd->result); target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION); break; } diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index 74be75336a54..929c7bd5c72f 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -5,7 +5,6 @@ #include struct scsi_request { - int result; int retries; }; -- cgit v1.2.3 From 6aded12b10e0c9536ee2c8ee33a1f7ed52f9cb34 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 24 Feb 2022 18:55:51 +0100 Subject: scsi: core: Remove struct scsi_request Let submitters initialize the scmd->allowed field directly instead of indirecting through struct scsi_request and remove the now superfluous structure. Link: https://lore.kernel.org/r/20220224175552.988286-8-hch@lst.de Reviewed-by: Bart Van Assche Reviewed-by: John Garry Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debugfs.c | 2 +- drivers/scsi/scsi_error.c | 4 +--- drivers/scsi/scsi_ioctl.c | 12 ++++-------- drivers/scsi/scsi_lib.c | 6 +----- drivers/scsi/sg.c | 4 +--- drivers/scsi/sr.c | 2 -- drivers/scsi/st.c | 4 +--- drivers/target/target_core_pscsi.c | 2 +- include/scsi/scsi_cmnd.h | 1 - include/scsi/scsi_request.h | 9 --------- 10 files changed, 10 insertions(+), 36 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/scsi_debugfs.c b/drivers/scsi/scsi_debugfs.c index 17d7f73a895c..217b70c678c3 100644 --- a/drivers/scsi/scsi_debugfs.c +++ b/drivers/scsi/scsi_debugfs.c @@ -33,7 +33,7 @@ static int scsi_flags_show(struct seq_file *m, const unsigned long flags, void scsi_show_rq(struct seq_file *m, struct request *rq) { - struct scsi_cmnd *cmd = container_of(scsi_req(rq), typeof(*cmd), req); + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); int alloc_ms = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc); int timeout_ms = jiffies_to_msecs(rq->timeout); char buf[80] = "(?)"; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index cf02d1c50389..9c237b223e63 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2023,12 +2023,10 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) { struct scsi_cmnd *scmd; struct request *req; - struct scsi_request *rq; req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN, 0); if (IS_ERR(req)) return; - rq = scsi_req(req); scmd = blk_mq_rq_to_pdu(req); scmd->cmnd[0] = ALLOW_MEDIUM_REMOVAL; @@ -2041,7 +2039,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) req->rq_flags |= RQF_QUIET; req->timeout = 10 * HZ; - rq->retries = 5; + scmd->allowed = 5; blk_execute_rq_nowait(req, true, eh_lock_door_done); } diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 04b7c70d1dba..0613015cae39 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -411,7 +411,6 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) int writing = 0; int at_head = 0; struct request *rq; - struct scsi_request *req; struct scsi_cmnd *scmd; struct bio *bio; @@ -440,7 +439,6 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); if (IS_ERR(rq)) return PTR_ERR(rq); - req = scsi_req(rq); scmd = blk_mq_rq_to_pdu(rq); if (hdr->cmd_len > sizeof(scmd->cmnd)) { @@ -475,7 +473,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) goto out_put_request; bio = rq->bio; - req->retries = 0; + scmd->allowed = 0; start_time = jiffies; @@ -521,7 +519,6 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, struct scsi_ioctl_command __user *sic) { struct request *rq; - struct scsi_request *req; int err; unsigned int in_len, out_len, bytes, opcode, cmdlen; struct scsi_cmnd *scmd; @@ -555,7 +552,6 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, err = PTR_ERR(rq); goto error_free_buffer; } - req = scsi_req(rq); scmd = blk_mq_rq_to_pdu(rq); cmdlen = COMMAND_SIZE(opcode); @@ -576,13 +572,13 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, goto error; /* default. possible overridden later */ - req->retries = 5; + scmd->allowed = 5; switch (opcode) { case SEND_DIAGNOSTIC: case FORMAT_UNIT: rq->timeout = FORMAT_UNIT_TIMEOUT; - req->retries = 1; + scmd->allowed = 1; break; case START_STOP: rq->timeout = START_STOP_TIMEOUT; @@ -595,7 +591,7 @@ static int sg_scsi_ioctl(struct request_queue *q, fmode_t mode, break; case READ_DEFECT_DATA: rq->timeout = READ_DEFECT_DATA_TIMEOUT; - req->retries = 1; + scmd->allowed = 1; break; default: rq->timeout = BLK_DEFAULT_SG_TIMEOUT; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0c41e023a3ce..a7788184908e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -213,7 +213,6 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, int *resid) { struct request *req; - struct scsi_request *rq; struct scsi_cmnd *scmd; int ret; @@ -224,8 +223,6 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, if (IS_ERR(req)) return PTR_ERR(req); - rq = scsi_req(req); - if (bufflen) { ret = blk_rq_map_kern(sdev->request_queue, req, buffer, bufflen, GFP_NOIO); @@ -235,7 +232,7 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, scmd = blk_mq_rq_to_pdu(req); scmd->cmd_len = COMMAND_SIZE(cmd[0]); memcpy(scmd->cmnd, cmd, scmd->cmd_len); - rq->retries = retries; + scmd->allowed = retries; req->timeout = timeout; req->cmd_flags |= flags; req->rq_flags |= rq_flags | RQF_QUIET; @@ -1189,7 +1186,6 @@ static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev, } cmd->transfersize = blk_rq_bytes(req); - cmd->allowed = scsi_req(req)->retries; return BLK_STS_OK; } diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 26a753521cb2..6a1c3ffaf32a 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1725,7 +1725,6 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) { int res; struct request *rq; - struct scsi_request *req; Sg_fd *sfp = srp->parentfp; sg_io_hdr_t *hp = &srp->header; int dxfer_len = (int) hp->dxfer_len; @@ -1758,7 +1757,6 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) if (IS_ERR(rq)) return PTR_ERR(rq); scmd = blk_mq_rq_to_pdu(rq); - req = scsi_req(rq); if (hp->cmd_len > sizeof(scmd->cmnd)) { blk_mq_free_request(rq); @@ -1770,7 +1768,7 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) srp->rq = rq; rq->end_io_data = srp; - req->retries = SG_DEFAULT_RETRIES; + scmd->allowed = SG_DEFAULT_RETRIES; if ((dxfer_len <= 0) || (dxfer_dir == SG_DXFER_NONE)) return 0; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 494d00b05f53..aaa54ad5f035 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -965,7 +965,6 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, { struct gendisk *disk = cdi->disk; u32 len = nr * CD_FRAMESIZE_RAW; - struct scsi_request *req; struct scsi_cmnd *scmd; struct request *rq; struct bio *bio; @@ -974,7 +973,6 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf, rq = scsi_alloc_request(disk->queue, REQ_OP_DRV_IN, 0); if (IS_ERR(rq)) return PTR_ERR(rq); - req = scsi_req(rq); scmd = blk_mq_rq_to_pdu(rq); ret = blk_rq_map_user(disk->queue, rq, NULL, ubuf, len, GFP_KERNEL); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index c8533ca225bc..6d4213e2e49a 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -539,7 +539,6 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, int timeout, int retries) { struct request *req; - struct scsi_request *rq; struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data; int err = 0; struct scsi_tape *STp = SRpnt->stp; @@ -551,7 +550,6 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, if (IS_ERR(req)) return PTR_ERR(req); scmd = blk_mq_rq_to_pdu(req); - rq = scsi_req(req); req->rq_flags |= RQF_QUIET; mdata->null_mapped = 1; @@ -580,7 +578,7 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd, scmd->cmd_len = COMMAND_SIZE(cmd[0]); memcpy(scmd->cmnd, cmd, scmd->cmd_len); req->timeout = timeout; - rq->retries = retries; + scmd->allowed = retries; req->end_io_data = SRpnt; blk_execute_rq_nowait(req, true, st_scsi_execute_end); diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 5b23a0ff905e..d18d75d0d750 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -993,7 +993,7 @@ pscsi_execute_cmd(struct se_cmd *cmd) req->timeout = PS_TIMEOUT_DISK; else req->timeout = PS_TIMEOUT_OTHER; - scsi_req(req)->retries = PS_RETRY; + scmd->allowed = PS_RETRY; cmd->priv = scmd->cmnd; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 5ff0a6e8460c..4b33ca6a7c7d 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -68,7 +68,6 @@ enum scsi_cmnd_submitter { } __packed; struct scsi_cmnd { - struct scsi_request req; struct scsi_device *device; struct list_head eh_entry; /* entry for the host eh_abort_list/eh_cmd_q */ struct delayed_work abort_work; diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index 929c7bd5c72f..6d424d3e8d02 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -4,13 +4,4 @@ #include -struct scsi_request { - int retries; -}; - -static inline struct scsi_request *scsi_req(struct request *rq) -{ - return blk_mq_rq_to_pdu(rq); -} - #endif /* _SCSI_SCSI_REQUEST_H */ -- cgit v1.2.3 From 26440303310591e29121964ede0048583cb3126d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 24 Feb 2022 18:55:52 +0100 Subject: scsi: core: Remove This header is empty now except for an include of , so remove it. Link: https://lore.kernel.org/r/20220224175552.988286-9-hch@lst.de Reviewed-by: Bart Van Assche Reviewed-by: John Garry Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/cdrom/cdrom.c | 1 - drivers/scsi/scsi_transport_sas.c | 1 - include/linux/bsg-lib.h | 1 - include/scsi/scsi_cmnd.h | 1 - include/scsi/scsi_request.h | 7 ------- 5 files changed, 11 deletions(-) delete mode 100644 include/scsi/scsi_request.h (limited to 'include/scsi') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 1b57d4666e43..7bd10d63ddbe 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -284,7 +284,6 @@ #include #include #include -#include /* used to tell the module to turn on full debugging messages */ static bool debug; diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 4ee578b181da..12bff64dade6 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h index 6b211323a489..9e97ced2896d 100644 --- a/include/linux/bsg-lib.h +++ b/include/linux/bsg-lib.h @@ -10,7 +10,6 @@ #define _BLK_BSG_ #include -#include struct bsg_job; struct request; diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 4b33ca6a7c7d..76c5eaeeb3b5 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -10,7 +10,6 @@ #include #include #include -#include struct Scsi_Host; struct scsi_driver; diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h deleted file mode 100644 index 6d424d3e8d02..000000000000 --- a/include/scsi/scsi_request.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _SCSI_SCSI_REQUEST_H -#define _SCSI_SCSI_REQUEST_H - -#include - -#endif /* _SCSI_SCSI_REQUEST_H */ -- cgit v1.2.3 From d8ec5d67b8bb6593223f24c04e1d530d86748250 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sat, 26 Feb 2022 17:04:32 -0600 Subject: scsi: iscsi: Remove iscsi_scan_finished() qla4xxx does not use iscsi_scan_finished() anymore so remove it. Link: https://lore.kernel.org/r/20220226230435.38733-4-michael.christie@oracle.com Reviewed-by: Lee Duncan Reviewed-by: Chris Leech Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 39 ++++--------------------------------- include/scsi/scsi_transport_iscsi.h | 2 -- 2 files changed, 4 insertions(+), 37 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 732938f5436b..05cd4bca979e 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1557,7 +1557,6 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, struct iscsi_cls_host *ihost = shost->shost_data; memset(ihost, 0, sizeof(*ihost)); - atomic_set(&ihost->nr_scans, 0); mutex_init(&ihost->mutex); iscsi_bsg_host_add(shost, ihost); @@ -1744,25 +1743,6 @@ void iscsi_host_for_each_session(struct Scsi_Host *shost, } EXPORT_SYMBOL_GPL(iscsi_host_for_each_session); -/** - * iscsi_scan_finished - helper to report when running scans are done - * @shost: scsi host - * @time: scan run time - * - * This function can be used by drives like qla4xxx to report to the scsi - * layer when the scans it kicked off at module load time are done. - */ -int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time) -{ - struct iscsi_cls_host *ihost = shost->shost_data; - /* - * qla4xxx will have kicked off some session unblocks before calling - * scsi_scan_host, so just wait for them to complete. - */ - return !atomic_read(&ihost->nr_scans); -} -EXPORT_SYMBOL_GPL(iscsi_scan_finished); - struct iscsi_scan_data { unsigned int channel; unsigned int id; @@ -1831,8 +1811,6 @@ static void iscsi_scan_session(struct work_struct *work) { struct iscsi_cls_session *session = container_of(work, struct iscsi_cls_session, scan_work); - struct Scsi_Host *shost = iscsi_session_to_shost(session); - struct iscsi_cls_host *ihost = shost->shost_data; struct iscsi_scan_data scan_data; scan_data.channel = 0; @@ -1841,7 +1819,6 @@ static void iscsi_scan_session(struct work_struct *work) scan_data.rescan = SCSI_SCAN_RESCAN; iscsi_user_scan_session(&session->dev, &scan_data); - atomic_dec(&ihost->nr_scans); } /** @@ -1912,8 +1889,6 @@ static void __iscsi_unblock_session(struct work_struct *work) struct iscsi_cls_session *session = container_of(work, struct iscsi_cls_session, unblock_work); - struct Scsi_Host *shost = iscsi_session_to_shost(session); - struct iscsi_cls_host *ihost = shost->shost_data; unsigned long flags; ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n"); @@ -1924,15 +1899,6 @@ static void __iscsi_unblock_session(struct work_struct *work) spin_unlock_irqrestore(&session->lock, flags); /* start IO */ scsi_target_unblock(&session->dev, SDEV_RUNNING); - /* - * Only do kernel scanning if the driver is properly hooked into - * the async scanning code (drivers like iscsi_tcp do login and - * scanning from userspace). - */ - if (shost->hostt->scan_finished) { - if (scsi_queue_work(shost, &session->scan_work)) - atomic_inc(&ihost->nr_scans); - } ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session\n"); } @@ -2192,7 +2158,10 @@ void iscsi_remove_session(struct iscsi_cls_session *session) spin_unlock_irqrestore(&session->lock, flags); scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE); - /* flush running scans then delete devices */ + /* + * qla4xxx can perform it's own scans when it runs in kernel only + * mode. Make sure to flush those scans. + */ flush_work(&session->scan_work); /* flush running unbind operations */ flush_work(&session->unbind_work); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index c5d7810fd792..90b55db46d7c 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -278,7 +278,6 @@ struct iscsi_cls_session { iscsi_dev_to_session(_stgt->dev.parent) struct iscsi_cls_host { - atomic_t nr_scans; struct mutex mutex; struct request_queue *bsg_q; uint32_t port_speed; @@ -448,7 +447,6 @@ extern void iscsi_get_conn(struct iscsi_cls_conn *conn); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session); -extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time); extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size); extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep); extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle); -- cgit v1.2.3 From 5842ea3668310466dcf645a23b6cd5012ce2eadf Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sat, 26 Feb 2022 17:04:33 -0600 Subject: scsi: iscsi: ql4xxx: Use per-session workqueue for unbinding We currently allocate a workqueue per host and only use it for removing the target. For the session per host case we could be using this workqueue to be able to do recoveries (block, unblock, timeout handling) in parallel. To also allow offload drivers to do their session recoveries in parallel, this drops the per host workqueue and replaces it with a per session one. Link: https://lore.kernel.org/r/20220226230435.38733-5-michael.christie@oracle.com Reviewed-by: Lee Duncan Reviewed-by: Chris Leech Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_os.c | 2 +- drivers/scsi/scsi_transport_iscsi.c | 19 ++++++++++++++----- include/scsi/scsi_transport_iscsi.h | 2 ++ 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index b49c38416fb9..3f6cb2a5c2c2 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -5096,7 +5096,7 @@ int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session) ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" " start scan\n", ha->host_no, __func__, ddb_entry->fw_ddb_index); - scsi_queue_work(ha->host, &ddb_entry->sess->scan_work); + queue_work(ddb_entry->sess->workq, &ddb_entry->sess->scan_work); } return QLA_SUCCESS; } diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 05cd4bca979e..ecb592a70e03 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2032,19 +2032,27 @@ EXPORT_SYMBOL_GPL(iscsi_alloc_session); int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) { + struct Scsi_Host *shost = iscsi_session_to_shost(session); unsigned long flags; int id = 0; int err; session->sid = atomic_add_return(1, &iscsi_session_nr); + session->workq = alloc_workqueue("iscsi_ctrl_%d:%d", + WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND, 0, + shost->host_no, session->sid); + if (!session->workq) + return -ENOMEM; + if (target_id == ISCSI_MAX_TARGET) { id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL); if (id < 0) { iscsi_cls_session_printk(KERN_ERR, session, "Failure in Target ID Allocation\n"); - return id; + err = id; + goto destroy_wq; } session->target_id = (unsigned int)id; session->ida_used = true; @@ -2078,7 +2086,8 @@ release_dev: release_ida: if (session->ida_used) ida_simple_remove(&iscsi_sess_ida, session->target_id); - +destroy_wq: + destroy_workqueue(session->workq); return err; } EXPORT_SYMBOL_GPL(iscsi_add_session); @@ -2177,6 +2186,8 @@ void iscsi_remove_session(struct iscsi_cls_session *session) transport_unregister_device(&session->dev); + destroy_workqueue(session->workq); + ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n"); device_del(&session->dev); } @@ -3833,8 +3844,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) case ISCSI_UEVENT_UNBIND_SESSION: session = iscsi_session_lookup(ev->u.d_session.sid); if (session) - scsi_queue_work(iscsi_session_to_shost(session), - &session->unbind_work); + queue_work(session->workq, &session->unbind_work); else err = -EINVAL; break; @@ -4707,7 +4717,6 @@ iscsi_register_transport(struct iscsi_transport *tt) INIT_LIST_HEAD(&priv->list); priv->iscsi_transport = tt; priv->t.user_scan = iscsi_user_scan; - priv->t.create_work_queue = 1; priv->dev.class = &iscsi_transport_class; dev_set_name(&priv->dev, "%s", tt->name); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 90b55db46d7c..7a0d24d3b916 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -251,6 +251,8 @@ struct iscsi_cls_session { bool recovery_tmo_sysfs_override; struct delayed_work recovery_work; + struct workqueue_struct *workq; + unsigned int target_id; bool ida_used; -- cgit v1.2.3 From 69af1c9577aae2149f79be6f485609250fdfb0ad Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sat, 26 Feb 2022 17:04:35 -0600 Subject: scsi: iscsi: Drop temp workq_name When the workqueue code was created it didn't allow variable args so we have been using a temp buffer. Drop that. Link: https://lore.kernel.org/r/20220226230435.38733-7-michael.christie@oracle.com Reviewed-by: Chris Leech Reviewed-by: Lee Duncan Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 6 ++---- include/scsi/libiscsi.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index d69203d19f2c..c84c2a349e28 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2798,11 +2798,9 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, ihost = shost_priv(shost); if (xmit_can_sleep) { - snprintf(ihost->workq_name, sizeof(ihost->workq_name), - "iscsi_q_%d", shost->host_no); - ihost->workq = alloc_workqueue("%s", + ihost->workq = alloc_workqueue("iscsi_q_%d", WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND, - 1, ihost->workq_name); + 1, shost->host_no); if (!ihost->workq) goto free_host; } diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index cb805ed9cbf1..e76c94697c1b 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -383,7 +383,6 @@ struct iscsi_host { int state; struct workqueue_struct *workq; - char workq_name[20]; }; /* -- cgit v1.2.3 From af4edb1d50c6d1044cb34bc43621411b7ba2cffe Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 28 Feb 2022 13:36:51 +0200 Subject: scsi: core: sd: Add silence_suspend flag to suppress some PM messages Kernel messages produced during runtime PM can cause a never-ending cycle because user space utilities (e.g. journald or rsyslog) write the messages back to storage, causing runtime resume, more messages, and so on. Messages that tell of things that are expected to happen are arguably unnecessary, so add a flag to suppress them. This flag is used by the UFS driver. Link: https://lore.kernel.org/r/20220228113652.970857-2-adrian.hunter@intel.com Cc: stable@vger.kernel.org Signed-off-by: Adrian Hunter Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_error.c | 9 +++++++-- drivers/scsi/sd.c | 6 ++++-- include/scsi/scsi_device.h | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 9c237b223e63..fd0827116f53 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -484,8 +484,13 @@ static void scsi_report_sense(struct scsi_device *sdev, if (sshdr->asc == 0x29) { evt_type = SDEV_EVT_POWER_ON_RESET_OCCURRED; - sdev_printk(KERN_WARNING, sdev, - "Power-on or device reset occurred\n"); + /* + * Do not print message if it is an expected side-effect + * of runtime PM. + */ + if (!sdev->silence_suspend) + sdev_printk(KERN_WARNING, sdev, + "Power-on or device reset occurred\n"); } if (sshdr->asc == 0x2a && sshdr->ascq == 0x01) { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2f9d160bc8c2..7a5eb4ebc036 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3676,7 +3676,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) return 0; if (sdkp->WCE && sdkp->media_present) { - sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); + if (!sdkp->device->silence_suspend) + sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); ret = sd_sync_cache(sdkp, &sshdr); if (ret) { @@ -3698,7 +3699,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) } if (sdkp->device->manage_start_stop) { - sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); + if (!sdkp->device->silence_suspend) + sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); /* an error is not worth aborting a system sleep */ ret = sd_start_stop_device(sdkp, 0); if (ignore_stop_errors) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 647c53b26105..57e3e239a1fc 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -206,6 +206,7 @@ struct scsi_device { unsigned rpm_autosuspend:1; /* Enable runtime autosuspend at device * creation time */ unsigned ignore_media_change:1; /* Ignore MEDIA CHANGE on resume */ + unsigned silence_suspend:1; /* Do not print runtime PM related messages */ unsigned int queue_stopped; /* request queue is quiesced */ bool offline_already; /* Device offline message logged */ -- cgit v1.2.3 From 5c9bf3635b66add7d829b4d8d538ae0d770d9d89 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 11 Mar 2022 20:23:49 +0800 Subject: scsi: libsas: Add sas_execute_internal_abort_single() The internal abort feature is common to hisi_sas and pm8001 HBAs, and the driver support is similar also, so add a common handler. Two modes of operation will be supported: - single: Abort a single tagged command - device: Abort all commands associated with a specific domain device A new protocol is added, SAS_PROTOCOL_INTERNAL_ABORT, so the common queue command API may be re-used. Only add "single" support as a first step. Link: https://lore.kernel.org/r/1647001432-239276-2-git-send-email-john.garry@huawei.com Tested-by: Damien Le Moal Acked-by: Jack Wang Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_scsi_host.c | 74 +++++++++++++++++++++++++++++++++++++ include/scsi/libsas.h | 14 +++++++ include/scsi/sas.h | 2 + 3 files changed, 90 insertions(+) (limited to 'include/scsi') diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 5b5747e33dbd..bb6baa52264d 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -920,6 +920,80 @@ void sas_task_internal_timedout(struct timer_list *t) #define TASK_TIMEOUT (20 * HZ) #define TASK_RETRY 3 +static int sas_execute_internal_abort(struct domain_device *device, + enum sas_internal_abort type, u16 tag, + unsigned int qid, void *data) +{ + struct sas_ha_struct *ha = device->port->ha; + struct sas_internal *i = to_sas_internal(ha->core.shost->transportt); + struct sas_task *task = NULL; + int res, retry; + + for (retry = 0; retry < TASK_RETRY; retry++) { + task = sas_alloc_slow_task(GFP_KERNEL); + if (!task) + return -ENOMEM; + + task->dev = device; + task->task_proto = SAS_PROTOCOL_INTERNAL_ABORT; + task->task_done = sas_task_internal_done; + task->slow_task->timer.function = sas_task_internal_timedout; + task->slow_task->timer.expires = jiffies + TASK_TIMEOUT; + add_timer(&task->slow_task->timer); + + task->abort_task.tag = tag; + task->abort_task.type = type; + + res = i->dft->lldd_execute_task(task, GFP_KERNEL); + if (res) { + del_timer_sync(&task->slow_task->timer); + pr_err("Executing internal abort failed %016llx (%d)\n", + SAS_ADDR(device->sas_addr), res); + break; + } + + wait_for_completion(&task->slow_task->completion); + res = TMF_RESP_FUNC_FAILED; + + /* Even if the internal abort timed out, return direct. */ + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + pr_err("Internal abort: timeout %016llx\n", + SAS_ADDR(device->sas_addr)); + res = -EIO; + break; + } + + if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == SAS_SAM_STAT_GOOD) { + res = TMF_RESP_FUNC_COMPLETE; + break; + } + + if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == TMF_RESP_FUNC_SUCC) { + res = TMF_RESP_FUNC_SUCC; + break; + } + + pr_err("Internal abort: task to dev %016llx response: 0x%x status 0x%x\n", + SAS_ADDR(device->sas_addr), task->task_status.resp, + task->task_status.stat); + sas_free_task(task); + task = NULL; + } + BUG_ON(retry == TASK_RETRY && task != NULL); + sas_free_task(task); + return res; +} + +int sas_execute_internal_abort_single(struct domain_device *device, u16 tag, + unsigned int qid, void *data) +{ + return sas_execute_internal_abort(device, SAS_INTERNAL_ABORT_SINGLE, + tag, qid, data); +} +EXPORT_SYMBOL_GPL(sas_execute_internal_abort_single); + int sas_execute_tmf(struct domain_device *device, void *parameter, int para_len, int force_phy_id, struct sas_tmf_task *tmf) diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index df2c8fc43429..2d30d57916e5 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -557,6 +557,16 @@ struct sas_ata_task { int force_phy_id; }; +/* LLDDs rely on these values */ +enum sas_internal_abort { + SAS_INTERNAL_ABORT_SINGLE = 0, +}; + +struct sas_internal_abort_task { + enum sas_internal_abort type; + u16 tag; +}; + struct sas_smp_task { struct scatterlist smp_req; struct scatterlist smp_resp; @@ -596,6 +606,7 @@ struct sas_task { struct sas_ata_task ata_task; struct sas_smp_task smp_task; struct sas_ssp_task ssp_task; + struct sas_internal_abort_task abort_task; }; struct scatterlist *scatter; @@ -683,6 +694,9 @@ extern int sas_slave_configure(struct scsi_device *); extern int sas_change_queue_depth(struct scsi_device *, int new_depth); extern int sas_bios_param(struct scsi_device *, struct block_device *, sector_t capacity, int *hsc); +int sas_execute_internal_abort_single(struct domain_device *device, + u16 tag, unsigned int qid, + void *data); extern struct scsi_transport_template * sas_domain_attach_transport(struct sas_domain_function_template *); extern struct device_attribute dev_attr_phy_event_threshold; diff --git a/include/scsi/sas.h b/include/scsi/sas.h index 332a463d08ef..acfc69fd72d0 100644 --- a/include/scsi/sas.h +++ b/include/scsi/sas.h @@ -95,6 +95,8 @@ enum sas_protocol { SAS_PROTOCOL_SSP = 0x08, SAS_PROTOCOL_ALL = 0x0E, SAS_PROTOCOL_STP_ALL = SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA, + /* these are internal to libsas */ + SAS_PROTOCOL_INTERNAL_ABORT = 0x10, }; /* From the spec; local phys only */ -- cgit v1.2.3 From 6a91c3e31578979a93b500efc76af4d3499f75ad Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 11 Mar 2022 20:23:50 +0800 Subject: scsi: libsas: Add sas_execute_internal_abort_dev() Add support for a "device" variant of internal abort, which will abort all pending I/Os for a specific device. Link: https://lore.kernel.org/r/1647001432-239276-3-git-send-email-john.garry@huawei.com Tested-by: Damien Le Moal Acked-by: Jack Wang Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_scsi_host.c | 8 ++++++++ include/scsi/libsas.h | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'include/scsi') diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index bb6baa52264d..13142ec97f1d 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -994,6 +994,14 @@ int sas_execute_internal_abort_single(struct domain_device *device, u16 tag, } EXPORT_SYMBOL_GPL(sas_execute_internal_abort_single); +int sas_execute_internal_abort_dev(struct domain_device *device, + unsigned int qid, void *data) +{ + return sas_execute_internal_abort(device, SAS_INTERNAL_ABORT_DEV, + SCSI_NO_TAG, qid, data); +} +EXPORT_SYMBOL_GPL(sas_execute_internal_abort_dev); + int sas_execute_tmf(struct domain_device *device, void *parameter, int para_len, int force_phy_id, struct sas_tmf_task *tmf) diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 2d30d57916e5..71f632b2d2bd 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -560,6 +560,7 @@ struct sas_ata_task { /* LLDDs rely on these values */ enum sas_internal_abort { SAS_INTERNAL_ABORT_SINGLE = 0, + SAS_INTERNAL_ABORT_DEV = 1, }; struct sas_internal_abort_task { @@ -641,6 +642,11 @@ extern struct sas_task *sas_alloc_task(gfp_t flags); extern struct sas_task *sas_alloc_slow_task(gfp_t flags); extern void sas_free_task(struct sas_task *task); +static inline bool sas_is_internal_abort(struct sas_task *task) +{ + return task->task_proto == SAS_PROTOCOL_INTERNAL_ABORT; +} + struct sas_domain_function_template { /* The class calls these to notify the LLDD of an event. */ void (*lldd_port_formed)(struct asd_sas_phy *); @@ -697,6 +703,8 @@ extern int sas_bios_param(struct scsi_device *, struct block_device *, int sas_execute_internal_abort_single(struct domain_device *device, u16 tag, unsigned int qid, void *data); +int sas_execute_internal_abort_dev(struct domain_device *device, + unsigned int qid, void *data); extern struct scsi_transport_template * sas_domain_attach_transport(struct sas_domain_function_template *); extern struct device_attribute dev_attr_phy_event_threshold; -- cgit v1.2.3 From 095478a6e5bf590f2bbf341569eb25173c9c5f32 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 11 Mar 2022 20:23:52 +0800 Subject: scsi: hisi_sas: Use libsas internal abort support Use the common libsas internal abort functionality. In addition, this driver has special handling for internal abort timeouts - specifically whether to reset the controller in that instance, so extend the API for that. Timeout is now increased to 20 * Hz from 6 * Hz. We also retry for failure now, but this should not make a difference. Link: https://lore.kernel.org/r/1647001432-239276-5-git-send-email-john.garry@huawei.com Tested-by: Damien Le Moal Acked-by: Jack Wang Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 8 +- drivers/scsi/hisi_sas/hisi_sas_main.c | 453 +++++++++++---------------------- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 11 +- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 18 +- drivers/scsi/libsas/sas_scsi_host.c | 13 +- include/scsi/libsas.h | 2 + 6 files changed, 183 insertions(+), 322 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index 99ceffad4bd9..24c83bc4f5dc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -133,11 +133,6 @@ struct hisi_sas_rst { bool done; }; -struct hisi_sas_internal_abort { - unsigned int flag; - unsigned int tag; -}; - #define HISI_SAS_RST_WORK_INIT(r, c) \ { .hisi_hba = hisi_hba, \ .completion = &c, \ @@ -325,8 +320,7 @@ struct hisi_sas_hw { void (*prep_stp)(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot); void (*prep_abort)(struct hisi_hba *hisi_hba, - struct hisi_sas_slot *slot, - int device_id, int abort_flag, int tag_to_abort); + struct hisi_sas_slot *slot); void (*phys_init)(struct hisi_hba *hisi_hba); void (*phy_start)(struct hisi_hba *hisi_hba, int phy_no); void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no); diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index cd8ec851e760..461ef8a76c4c 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -10,10 +10,6 @@ #define DEV_IS_GONE(dev) \ ((!dev) || (dev->dev_type == SAS_PHY_UNUSED)) -static int -hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, - struct domain_device *device, - int abort_flag, int tag, bool rst_to_recover); static int hisi_sas_softreset_ata_disk(struct domain_device *device); static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, void *funcdata); @@ -21,6 +17,10 @@ static void hisi_sas_release_task(struct hisi_hba *hisi_hba, struct domain_device *device); static void hisi_sas_dev_gone(struct domain_device *device); +struct hisi_sas_internal_abort_data { + bool rst_ha_timeout; /* reset the HA for timeout */ +}; + u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) { switch (fis->command) { @@ -263,11 +263,9 @@ static void hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba, } static void hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba, - struct hisi_sas_internal_abort *abort, - struct hisi_sas_slot *slot, int device_id) + struct hisi_sas_slot *slot) { - hisi_hba->hw->prep_abort(hisi_hba, slot, - device_id, abort->flag, abort->tag); + hisi_hba->hw->prep_abort(hisi_hba, slot); } static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba, @@ -397,8 +395,7 @@ static void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, struct hisi_sas_dq *dq, - struct hisi_sas_device *sas_dev, - struct hisi_sas_internal_abort *abort) + struct hisi_sas_device *sas_dev) { struct hisi_sas_cmd_hdr *cmd_hdr_base; int dlvry_queue_slot, dlvry_queue; @@ -439,19 +436,15 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba, break; case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: - case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: + case SAS_PROTOCOL_STP_ALL: hisi_sas_task_prep_ata(hisi_hba, slot); break; - case SAS_PROTOCOL_NONE: - if (abort) { - hisi_sas_task_prep_abort(hisi_hba, abort, slot, sas_dev->device_id); - break; - } + case SAS_PROTOCOL_INTERNAL_ABORT: + hisi_sas_task_prep_abort(hisi_hba, slot); + break; fallthrough; default: - dev_err(hisi_hba->dev, "task prep: unknown/unsupported proto (0x%x)\n", - task->task_proto); - break; + return; } WRITE_ONCE(slot->ready, 1); @@ -467,6 +460,7 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) struct domain_device *device = task->dev; struct asd_sas_port *sas_port = device->port; struct hisi_sas_device *sas_dev = device->lldd_dev; + bool internal_abort = sas_is_internal_abort(task); struct scsi_cmnd *scmd = NULL; struct hisi_sas_dq *dq = NULL; struct hisi_sas_port *port; @@ -484,7 +478,7 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) * libsas will use dev->port, should * not call task_done for sata */ - if (device->dev_type != SAS_SATA_DEV) + if (device->dev_type != SAS_SATA_DEV && !internal_abort) task->task_done(task); return -ECOMM; } @@ -492,59 +486,85 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) hisi_hba = dev_to_hisi_hba(device); dev = hisi_hba->dev; - if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) { - if (!gfpflags_allow_blocking(gfp_flags)) - return -EINVAL; + switch (task->task_proto) { + case SAS_PROTOCOL_SSP: + case SAS_PROTOCOL_SMP: + case SAS_PROTOCOL_SATA: + case SAS_PROTOCOL_STP: + case SAS_PROTOCOL_STP_ALL: + if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) { + if (!gfpflags_allow_blocking(gfp_flags)) + return -EINVAL; - down(&hisi_hba->sem); - up(&hisi_hba->sem); - } + down(&hisi_hba->sem); + up(&hisi_hba->sem); + } - if (DEV_IS_GONE(sas_dev)) { - if (sas_dev) - dev_info(dev, "task prep: device %d not ready\n", - sas_dev->device_id); - else - dev_info(dev, "task prep: device %016llx not ready\n", - SAS_ADDR(device->sas_addr)); + if (DEV_IS_GONE(sas_dev)) { + if (sas_dev) + dev_info(dev, "task prep: device %d not ready\n", + sas_dev->device_id); + else + dev_info(dev, "task prep: device %016llx not ready\n", + SAS_ADDR(device->sas_addr)); - return -ECOMM; - } + return -ECOMM; + } - if (task->uldd_task) { - struct ata_queued_cmd *qc; + port = to_hisi_sas_port(sas_port); + if (!port->port_attached) { + dev_info(dev, "task prep: %s port%d not attach device\n", + dev_is_sata(device) ? "SATA/STP" : "SAS", + device->port->id); - if (dev_is_sata(device)) { - qc = task->uldd_task; - scmd = qc->scsicmd; - } else { - scmd = task->uldd_task; + return -ECOMM; } - } - if (scmd) { - unsigned int dq_index; - u32 blk_tag; + if (task->uldd_task) { + struct ata_queued_cmd *qc; - blk_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd)); - dq_index = blk_mq_unique_tag_to_hwq(blk_tag); - dq = &hisi_hba->dq[dq_index]; - } else { - struct Scsi_Host *shost = hisi_hba->shost; - struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; - int queue = qmap->mq_map[raw_smp_processor_id()]; + if (dev_is_sata(device)) { + qc = task->uldd_task; + scmd = qc->scsicmd; + } else { + scmd = task->uldd_task; + } + } - dq = &hisi_hba->dq[queue]; - } + if (scmd) { + unsigned int dq_index; + u32 blk_tag; - port = to_hisi_sas_port(sas_port); - if (port && !port->port_attached) { - dev_info(dev, "task prep: %s port%d not attach device\n", - (dev_is_sata(device)) ? - "SATA/STP" : "SAS", - device->port->id); + blk_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd)); + dq_index = blk_mq_unique_tag_to_hwq(blk_tag); + dq = &hisi_hba->dq[dq_index]; + } else { + struct Scsi_Host *shost = hisi_hba->shost; + struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; + int queue = qmap->mq_map[raw_smp_processor_id()]; - return -ECOMM; + dq = &hisi_hba->dq[queue]; + } + break; + case SAS_PROTOCOL_INTERNAL_ABORT: + if (!hisi_hba->hw->prep_abort) + return TMF_RESP_FUNC_FAILED; + + if (test_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags)) + return -EIO; + + hisi_hba = dev_to_hisi_hba(device); + + if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) + return -EINVAL; + + port = to_hisi_sas_port(sas_port); + dq = &hisi_hba->dq[task->abort_task.qid]; + break; + default: + dev_err(hisi_hba->dev, "task prep: unknown/unsupported proto (0x%x)\n", + task->task_proto); + return -EINVAL; } rc = hisi_sas_dma_map(hisi_hba, task, &n_elem, @@ -558,7 +578,7 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) goto err_out_dma_unmap; } - if (hisi_hba->hw->slot_index_alloc) + if (!internal_abort && hisi_hba->hw->slot_index_alloc) rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device); else rc = hisi_sas_slot_index_alloc(hisi_hba, scmd); @@ -573,10 +593,10 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) slot->port = port; slot->tmf = task->tmf; - slot->is_internal = task->tmf; + slot->is_internal = !!task->tmf || internal_abort; /* protect task_prep and start_delivery sequence */ - hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev, NULL); + hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev); return 0; @@ -1088,6 +1108,29 @@ static void hisi_sas_dereg_device(struct hisi_hba *hisi_hba, hisi_hba->hw->dereg_device(hisi_hba, device); } +static int +hisi_sas_internal_task_abort_dev(struct hisi_sas_device *sas_dev, + bool rst_ha_timeout) +{ + struct hisi_sas_internal_abort_data data = { rst_ha_timeout }; + struct domain_device *device = sas_dev->sas_device; + struct hisi_hba *hisi_hba = sas_dev->hisi_hba; + int i, rc; + + for (i = 0; i < hisi_hba->cq_nvecs; i++) { + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; + const struct cpumask *mask = cq->irq_mask; + + if (mask && !cpumask_intersects(cpu_online_mask, mask)) + continue; + rc = sas_execute_internal_abort_dev(device, i, &data); + if (rc) + return rc; + } + + return 0; +} + static void hisi_sas_dev_gone(struct domain_device *device) { struct hisi_sas_device *sas_dev = device->lldd_dev; @@ -1100,8 +1143,7 @@ static void hisi_sas_dev_gone(struct domain_device *device) down(&hisi_hba->sem); if (!test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags)) { - hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, 0, true); + hisi_sas_internal_task_abort_dev(sas_dev, true); hisi_sas_dereg_device(hisi_hba, device); @@ -1216,32 +1258,6 @@ out: return ret; } -static void hisi_sas_task_done(struct sas_task *task) -{ - del_timer_sync(&task->slow_task->timer); - complete(&task->slow_task->completion); -} - -static void hisi_sas_tmf_timedout(struct timer_list *t) -{ - struct sas_task_slow *slow = from_timer(slow, t, timer); - struct sas_task *task = slow->task; - unsigned long flags; - bool is_completed = true; - - spin_lock_irqsave(&task->task_state_lock, flags); - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - task->task_state_flags |= SAS_TASK_STATE_ABORTED; - is_completed = false; - } - spin_unlock_irqrestore(&task->task_state_lock, flags); - - if (!is_completed) - complete(&task->slow_task->completion); -} - -#define INTERNAL_ABORT_TIMEOUT (6 * HZ) - static void hisi_sas_fill_ata_reset_cmd(struct ata_device *dev, bool reset, int pmp, u8 *fis) { @@ -1426,9 +1442,7 @@ static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba) if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device) continue; - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, 0, - false); + rc = hisi_sas_internal_task_abort_dev(sas_dev, false); if (rc < 0) dev_err(dev, "STP reject: abort dev failed %d\n", rc); } @@ -1536,6 +1550,7 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba) static int hisi_sas_abort_task(struct sas_task *task) { + struct hisi_sas_internal_abort_data internal_abort_data = { false }; struct domain_device *device = task->dev; struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_hba *hisi_hba; @@ -1575,9 +1590,8 @@ static int hisi_sas_abort_task(struct sas_task *task) int rc2; rc = sas_abort_task(task, tag); - rc2 = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_CMD, tag, - false); + rc2 = sas_execute_internal_abort_single(device, tag, + slot->dlvry_queue, &internal_abort_data); if (rc2 < 0) { dev_err(dev, "abort task: internal abort (%d)\n", rc2); return TMF_RESP_FUNC_FAILED; @@ -1597,9 +1611,7 @@ static int hisi_sas_abort_task(struct sas_task *task) } else if (task->task_proto & SAS_PROTOCOL_SATA || task->task_proto & SAS_PROTOCOL_STP) { if (task->dev->dev_type == SAS_SATA_DEV) { - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, - 0, false); + rc = hisi_sas_internal_task_abort_dev(sas_dev, false); if (rc < 0) { dev_err(dev, "abort task: internal abort failed\n"); goto out; @@ -1613,9 +1625,9 @@ static int hisi_sas_abort_task(struct sas_task *task) u32 tag = slot->idx; struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue]; - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_CMD, tag, - false); + rc = sas_execute_internal_abort_single(device, + tag, slot->dlvry_queue, + &internal_abort_data); if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) && task->lldd_task) { /* @@ -1635,12 +1647,12 @@ out: static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun) { + struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; int rc; - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, 0, false); + rc = hisi_sas_internal_task_abort_dev(sas_dev, false); if (rc < 0) { dev_err(dev, "abort task set: internal abort rc=%d\n", rc); return TMF_RESP_FUNC_FAILED; @@ -1713,12 +1725,12 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) static int hisi_sas_I_T_nexus_reset(struct domain_device *device) { + struct hisi_sas_device *sas_dev = device->lldd_dev; struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct device *dev = hisi_hba->dev; int rc; - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, 0, false); + rc = hisi_sas_internal_task_abort_dev(sas_dev, false); if (rc < 0) { dev_err(dev, "I_T nexus reset: internal abort (%d)\n", rc); return TMF_RESP_FUNC_FAILED; @@ -1766,8 +1778,7 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun) int rc = TMF_RESP_FUNC_FAILED; /* Clear internal IO and then lu reset */ - rc = hisi_sas_internal_task_abort(hisi_hba, device, - HISI_SAS_INT_ABT_DEV, 0, false); + rc = hisi_sas_internal_task_abort_dev(sas_dev, false); if (rc < 0) { dev_err(dev, "lu_reset: internal abort failed\n"); goto out; @@ -1862,203 +1873,48 @@ static int hisi_sas_query_task(struct sas_task *task) return rc; } -static int -hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, - struct hisi_sas_internal_abort *abort, - struct sas_task *task, - struct hisi_sas_dq *dq) +static bool hisi_sas_internal_abort_timeout(struct sas_task *task, + void *data) { struct domain_device *device = task->dev; - struct hisi_sas_device *sas_dev = device->lldd_dev; - struct device *dev = hisi_hba->dev; - struct hisi_sas_port *port; - struct asd_sas_port *sas_port = device->port; - struct hisi_sas_slot *slot; - int slot_idx; - - if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) - return -EINVAL; - - if (!device->port) - return -1; - - port = to_hisi_sas_port(sas_port); - - /* simply get a slot and send abort command */ - slot_idx = hisi_sas_slot_index_alloc(hisi_hba, NULL); - if (slot_idx < 0) - goto err_out; - - slot = &hisi_hba->slot_info[slot_idx]; - slot->n_elem = 0; - slot->task = task; - slot->port = port; - slot->is_internal = true; - - hisi_sas_task_deliver(hisi_hba, slot, dq, sas_dev, abort); - - return 0; - -err_out: - dev_err(dev, "internal abort task prep: failed[%d]!\n", slot_idx); - - return slot_idx; -} - -/** - * _hisi_sas_internal_task_abort -- execute an internal - * abort command for single IO command or a device - * @hisi_hba: host controller struct - * @device: domain device - * @abort_flag: mode of operation, device or single IO - * @tag: tag of IO to be aborted (only relevant to single - * IO mode) - * @dq: delivery queue for this internal abort command - * @rst_to_recover: If rst_to_recover set, queue a controller - * reset if an internal abort times out. - */ -static int -_hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, - struct domain_device *device, int abort_flag, - int tag, struct hisi_sas_dq *dq, bool rst_to_recover) -{ - struct sas_task *task; - struct hisi_sas_device *sas_dev = device->lldd_dev; - struct hisi_sas_internal_abort abort = { - .flag = abort_flag, - .tag = tag, - }; - struct device *dev = hisi_hba->dev; - int res; - /* - * The interface is not realized means this HW don't support internal - * abort, or don't need to do internal abort. Then here, we return - * TMF_RESP_FUNC_FAILED and let other steps go on, which depends that - * the internal abort has been executed and returned CQ. - */ - if (!hisi_hba->hw->prep_abort) - return TMF_RESP_FUNC_FAILED; - - if (test_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags)) - return -EIO; - - task = sas_alloc_slow_task(GFP_KERNEL); - if (!task) - return -ENOMEM; - - task->dev = device; - task->task_proto = SAS_PROTOCOL_NONE; - task->task_done = hisi_sas_task_done; - task->slow_task->timer.function = hisi_sas_tmf_timedout; - task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT; - add_timer(&task->slow_task->timer); - - res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id, - &abort, task, dq); - if (res) { - del_timer_sync(&task->slow_task->timer); - dev_err(dev, "internal task abort: executing internal task failed: %d\n", - res); - goto exit; - } - wait_for_completion(&task->slow_task->completion); - res = TMF_RESP_FUNC_FAILED; - - /* Internal abort timed out */ - if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { - if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) - queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); - - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - struct hisi_sas_slot *slot = task->lldd_task; - - set_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags); - - if (slot) { - struct hisi_sas_cq *cq = - &hisi_hba->cq[slot->dlvry_queue]; - /* - * sync irq to avoid free'ing task - * before using task in IO completion - */ - synchronize_irq(cq->irq_no); - slot->task = NULL; - } - - if (rst_to_recover) { - dev_err(dev, "internal task abort: timeout and not done. Queuing reset.\n"); - queue_work(hisi_hba->wq, &hisi_hba->rst_work); - } else { - dev_err(dev, "internal task abort: timeout and not done.\n"); - } - - res = -EIO; - goto exit; - } else - dev_err(dev, "internal task abort: timeout.\n"); - } - - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == TMF_RESP_FUNC_COMPLETE) { - res = TMF_RESP_FUNC_COMPLETE; - goto exit; - } + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + struct hisi_sas_internal_abort_data *timeout = data; - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == TMF_RESP_FUNC_SUCC) { - res = TMF_RESP_FUNC_SUCC; - goto exit; - } + if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); -exit: - dev_dbg(dev, "internal task abort: task to dev %016llx task=%pK resp: 0x%x sts 0x%x\n", - SAS_ADDR(device->sas_addr), task, - task->task_status.resp, /* 0 is complete, -1 is undelivered */ - task->task_status.stat); - sas_free_task(task); + if (task->task_state_flags & SAS_TASK_STATE_DONE) { + pr_err("Internal abort: timeout %016llx\n", + SAS_ADDR(device->sas_addr)); + } else { + struct hisi_sas_slot *slot = task->lldd_task; - return res; -} + set_bit(HISI_SAS_HW_FAULT_BIT, &hisi_hba->flags); -static int -hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, - struct domain_device *device, - int abort_flag, int tag, bool rst_to_recover) -{ - struct hisi_sas_slot *slot; - struct device *dev = hisi_hba->dev; - struct hisi_sas_dq *dq; - int i, rc; + if (slot) { + struct hisi_sas_cq *cq = + &hisi_hba->cq[slot->dlvry_queue]; + /* + * sync irq to avoid free'ing task + * before using task in IO completion + */ + synchronize_irq(cq->irq_no); + slot->task = NULL; + } - switch (abort_flag) { - case HISI_SAS_INT_ABT_CMD: - slot = &hisi_hba->slot_info[tag]; - dq = &hisi_hba->dq[slot->dlvry_queue]; - return _hisi_sas_internal_task_abort(hisi_hba, device, - abort_flag, tag, dq, - rst_to_recover); - case HISI_SAS_INT_ABT_DEV: - for (i = 0; i < hisi_hba->cq_nvecs; i++) { - struct hisi_sas_cq *cq = &hisi_hba->cq[i]; - const struct cpumask *mask = cq->irq_mask; - - if (mask && !cpumask_intersects(cpu_online_mask, mask)) - continue; - dq = &hisi_hba->dq[i]; - rc = _hisi_sas_internal_task_abort(hisi_hba, device, - abort_flag, tag, - dq, rst_to_recover); - if (rc) - return rc; + if (timeout->rst_ha_timeout) { + pr_err("Internal abort: timeout and not done %016llx. Queuing reset.\n", + SAS_ADDR(device->sas_addr)); + queue_work(hisi_hba->wq, &hisi_hba->rst_work); + } else { + pr_err("Internal abort: timeout and not done %016llx.\n", + SAS_ADDR(device->sas_addr)); } - break; - default: - dev_err(dev, "Unrecognised internal abort flag (%d)\n", - abort_flag); - return -EINVAL; + + return true; } - return 0; + return false; } static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy) @@ -2176,6 +2032,7 @@ static struct sas_domain_function_template hisi_sas_transport_ops = { .lldd_port_formed = hisi_sas_port_formed, .lldd_write_gpio = hisi_sas_write_gpio, .lldd_tmf_aborted = hisi_sas_tmf_aborted, + .lldd_abort_timeout = hisi_sas_internal_abort_timeout, }; void hisi_sas_init_mem(struct hisi_hba *hisi_hba) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 441ac4b6f1f4..455d49299ddf 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2603,14 +2603,15 @@ static void hisi_sas_internal_abort_quirk_timeout(struct timer_list *t) } static void prep_abort_v2_hw(struct hisi_hba *hisi_hba, - struct hisi_sas_slot *slot, - int device_id, int abort_flag, int tag_to_abort) + struct hisi_sas_slot *slot) { struct sas_task *task = slot->task; + struct sas_internal_abort_task *abort = &task->abort_task; struct domain_device *dev = task->dev; struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; struct hisi_sas_port *port = slot->port; struct timer_list *timer = &slot->internal_abort_timer; + struct hisi_sas_device *sas_dev = dev->lldd_dev; /* setup the quirk timer */ timer_setup(timer, hisi_sas_internal_abort_quirk_timeout, 0); @@ -2622,13 +2623,13 @@ static void prep_abort_v2_hw(struct hisi_hba *hisi_hba, (port->id << CMD_HDR_PORT_OFF) | (dev_is_sata(dev) << CMD_HDR_ABORT_DEVICE_TYPE_OFF) | - (abort_flag << CMD_HDR_ABORT_FLAG_OFF)); + (abort->type << CMD_HDR_ABORT_FLAG_OFF)); /* dw1 */ - hdr->dw1 = cpu_to_le32(device_id << CMD_HDR_DEV_ID_OFF); + hdr->dw1 = cpu_to_le32(sas_dev->device_id << CMD_HDR_DEV_ID_OFF); /* dw7 */ - hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF); + hdr->dw7 = cpu_to_le32(abort->tag << CMD_HDR_ABORT_IPTT_OFF); hdr->transfer_tags = cpu_to_le32(slot->idx); } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 914ae4e82f5e..79f87d7c3e68 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1452,28 +1452,28 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, } static void prep_abort_v3_hw(struct hisi_hba *hisi_hba, - struct hisi_sas_slot *slot, - int device_id, int abort_flag, int tag_to_abort) + struct hisi_sas_slot *slot) { struct sas_task *task = slot->task; + struct sas_internal_abort_task *abort = &task->abort_task; struct domain_device *dev = task->dev; struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; struct hisi_sas_port *port = slot->port; + struct hisi_sas_device *sas_dev = dev->lldd_dev; + bool sata = dev_is_sata(dev); /* dw0 */ - hdr->dw0 = cpu_to_le32((5U << CMD_HDR_CMD_OFF) | /*abort*/ + hdr->dw0 = cpu_to_le32((5U << CMD_HDR_CMD_OFF) | /* abort */ (port->id << CMD_HDR_PORT_OFF) | - (dev_is_sata(dev) - << CMD_HDR_ABORT_DEVICE_TYPE_OFF) | - (abort_flag - << CMD_HDR_ABORT_FLAG_OFF)); + (sata << CMD_HDR_ABORT_DEVICE_TYPE_OFF) | + (abort->type << CMD_HDR_ABORT_FLAG_OFF)); /* dw1 */ - hdr->dw1 = cpu_to_le32(device_id + hdr->dw1 = cpu_to_le32(sas_dev->device_id << CMD_HDR_DEV_ID_OFF); /* dw7 */ - hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF); + hdr->dw7 = cpu_to_le32(abort->tag << CMD_HDR_ABORT_IPTT_OFF); hdr->transfer_tags = cpu_to_le32(slot->idx); } diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 13142ec97f1d..9c82e5dc4fcc 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -943,6 +943,7 @@ static int sas_execute_internal_abort(struct domain_device *device, task->abort_task.tag = tag; task->abort_task.type = type; + task->abort_task.qid = qid; res = i->dft->lldd_execute_task(task, GFP_KERNEL); if (res) { @@ -957,10 +958,16 @@ static int sas_execute_internal_abort(struct domain_device *device, /* Even if the internal abort timed out, return direct. */ if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { - pr_err("Internal abort: timeout %016llx\n", - SAS_ADDR(device->sas_addr)); + bool quit = true; + + if (i->dft->lldd_abort_timeout) + quit = i->dft->lldd_abort_timeout(task, data); + else + pr_err("Internal abort: timeout %016llx\n", + SAS_ADDR(device->sas_addr)); res = -EIO; - break; + if (quit) + break; } if (task->task_status.resp == SAS_TASK_COMPLETE && diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 71f632b2d2bd..ff04eb6d250b 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -565,6 +565,7 @@ enum sas_internal_abort { struct sas_internal_abort_task { enum sas_internal_abort type; + unsigned int qid; u16 tag; }; @@ -671,6 +672,7 @@ struct sas_domain_function_template { /* Special TMF callbacks */ void (*lldd_tmf_exec_complete)(struct domain_device *dev); void (*lldd_tmf_aborted)(struct sas_task *task); + bool (*lldd_abort_timeout)(struct sas_task *task, void *data); /* Port and Adapter management */ int (*lldd_clear_nexus_port)(struct asd_sas_port *); -- cgit v1.2.3 From ad515cada7dac3cdf5e1ad77a0ed696f5f34e0ab Mon Sep 17 00:00:00 2001 From: Wenchao Hao Date: Wed, 9 Mar 2022 20:57:57 -0500 Subject: scsi: iscsi: Add helper functions to manage iscsi_cls_conn - iscsi_alloc_conn(): Allocate and initialize iscsi_cls_conn - iscsi_add_conn(): Expose iscsi_cls_conn to userspace via sysfs - iscsi_remove_conn(): Remove iscsi_cls_conn from sysfs Link: https://lore.kernel.org/r/20220310015759.3296841-2-haowenchao@huawei.com Reviewed-by: Mike Christie Signed-off-by: Wenchao Hao Signed-off-by: Wu Bo Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 97 +++++++++++++++++++++++++++++++++++++ include/scsi/scsi_transport_iscsi.h | 4 ++ 2 files changed, 101 insertions(+) (limited to 'include/scsi') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 754277bec63a..fe586336591b 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2317,6 +2317,103 @@ void iscsi_free_session(struct iscsi_cls_session *session) } EXPORT_SYMBOL_GPL(iscsi_free_session); +/** + * iscsi_alloc_conn - alloc iscsi class connection + * @session: iscsi cls session + * @dd_size: private driver data size + * @cid: connection id + */ +struct iscsi_cls_conn * +iscsi_alloc_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) +{ + struct iscsi_transport *transport = session->transport; + struct iscsi_cls_conn *conn; + + conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL); + if (!conn) + return NULL; + if (dd_size) + conn->dd_data = &conn[1]; + + mutex_init(&conn->ep_mutex); + INIT_LIST_HEAD(&conn->conn_list); + INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn); + conn->transport = transport; + conn->cid = cid; + conn->state = ISCSI_CONN_DOWN; + + /* this is released in the dev's release function */ + if (!get_device(&session->dev)) + goto free_conn; + + dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid); + device_initialize(&conn->dev); + conn->dev.parent = &session->dev; + conn->dev.release = iscsi_conn_release; + + return conn; + +free_conn: + kfree(conn); + return NULL; +} +EXPORT_SYMBOL_GPL(iscsi_alloc_conn); + +/** + * iscsi_add_conn - add iscsi class connection + * @conn: iscsi cls connection + * + * This will expose iscsi_cls_conn to sysfs so make sure the related + * resources for sysfs attributes are initialized before calling this. + */ +int iscsi_add_conn(struct iscsi_cls_conn *conn) +{ + int err; + unsigned long flags; + struct iscsi_cls_session *session = iscsi_dev_to_session(conn->dev.parent); + + err = device_add(&conn->dev); + if (err) { + iscsi_cls_session_printk(KERN_ERR, session, + "could not register connection's dev\n"); + return err; + } + err = transport_register_device(&conn->dev); + if (err) { + iscsi_cls_session_printk(KERN_ERR, session, + "could not register transport's dev\n"); + device_del(&conn->dev); + return err; + } + + spin_lock_irqsave(&connlock, flags); + list_add(&conn->conn_list, &connlist); + spin_unlock_irqrestore(&connlock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_add_conn); + +/** + * iscsi_remove_conn - remove iscsi class connection from sysfs + * @conn: iscsi cls connection + * + * Remove iscsi_cls_conn from sysfs, and wait for previous + * read/write of iscsi_cls_conn's attributes in sysfs to finish. + */ +void iscsi_remove_conn(struct iscsi_cls_conn *conn) +{ + unsigned long flags; + + spin_lock_irqsave(&connlock, flags); + list_del(&conn->conn_list); + spin_unlock_irqrestore(&connlock, flags); + + transport_unregister_device(&conn->dev); + device_del(&conn->dev); +} +EXPORT_SYMBOL_GPL(iscsi_remove_conn); + /** * iscsi_create_conn - create iscsi class connection * @session: iscsi cls session diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 7a0d24d3b916..ad341835e847 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -442,6 +442,10 @@ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, unsigned int target_id); extern void iscsi_remove_session(struct iscsi_cls_session *session); extern void iscsi_free_session(struct iscsi_cls_session *session); +extern struct iscsi_cls_conn *iscsi_alloc_conn(struct iscsi_cls_session *sess, + int dd_size, uint32_t cid); +extern int iscsi_add_conn(struct iscsi_cls_conn *conn); +extern void iscsi_remove_conn(struct iscsi_cls_conn *conn); extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, int dd_size, uint32_t cid); extern void iscsi_put_conn(struct iscsi_cls_conn *conn); -- cgit v1.2.3 From 7dae459f5e56a89ab01413ae055595c982713349 Mon Sep 17 00:00:00 2001 From: Wenchao Hao Date: Wed, 9 Mar 2022 20:57:58 -0500 Subject: scsi: libiscsi: Add iscsi_cls_conn to sysfs after initialization iscsi_create_conn() exposed iscsi_cls_conn to sysfs prior to initialization of iscsi_conn's dd_data. When userspace tried to access an attribute such as the connect address, a NULL pointer dereference was observed. Do not add iscsi_cls_conn to sysfs until it has been initialized. Remove iscsi_create_conn() since it is no longer used. Link: https://lore.kernel.org/r/20220310015759.3296841-3-haowenchao@huawei.com Reviewed-by: Mike Christie Signed-off-by: Wenchao Hao Signed-off-by: Wu Bo Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 13 ++++++- drivers/scsi/scsi_transport_iscsi.c | 76 ------------------------------------- include/scsi/scsi_transport_iscsi.h | 2 - 3 files changed, 11 insertions(+), 80 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c84c2a349e28..69ddc9f585c5 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -3038,8 +3038,9 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, struct iscsi_conn *conn; struct iscsi_cls_conn *cls_conn; char *data; + int err; - cls_conn = iscsi_create_conn(cls_session, sizeof(*conn) + dd_size, + cls_conn = iscsi_alloc_conn(cls_session, sizeof(*conn) + dd_size, conn_idx); if (!cls_conn) return NULL; @@ -3076,13 +3077,21 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, goto login_task_data_alloc_fail; conn->login_task->data = conn->data = data; + err = iscsi_add_conn(cls_conn); + if (err) + goto login_task_add_dev_fail; + return cls_conn; +login_task_add_dev_fail: + free_pages((unsigned long) conn->data, + get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); + login_task_data_alloc_fail: kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); login_task_alloc_fail: - iscsi_destroy_conn(cls_conn); + iscsi_put_conn(cls_conn); return NULL; } EXPORT_SYMBOL_GPL(iscsi_conn_setup); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index fe586336591b..803b6b06d83b 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2414,82 +2414,6 @@ void iscsi_remove_conn(struct iscsi_cls_conn *conn) } EXPORT_SYMBOL_GPL(iscsi_remove_conn); -/** - * iscsi_create_conn - create iscsi class connection - * @session: iscsi cls session - * @dd_size: private driver data size - * @cid: connection id - * - * This can be called from a LLD or iscsi_transport. The connection - * is child of the session so cid must be unique for all connections - * on the session. - * - * Since we do not support MCS, cid will normally be zero. In some cases - * for software iscsi we could be trying to preallocate a connection struct - * in which case there could be two connection structs and cid would be - * non-zero. - */ -struct iscsi_cls_conn * -iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) -{ - struct iscsi_transport *transport = session->transport; - struct iscsi_cls_conn *conn; - unsigned long flags; - int err; - - conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL); - if (!conn) - return NULL; - if (dd_size) - conn->dd_data = &conn[1]; - - mutex_init(&conn->ep_mutex); - INIT_LIST_HEAD(&conn->conn_list); - INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn); - conn->transport = transport; - conn->cid = cid; - conn->state = ISCSI_CONN_DOWN; - - /* this is released in the dev's release function */ - if (!get_device(&session->dev)) - goto free_conn; - - dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid); - conn->dev.parent = &session->dev; - conn->dev.release = iscsi_conn_release; - err = device_register(&conn->dev); - if (err) { - iscsi_cls_session_printk(KERN_ERR, session, "could not " - "register connection's dev\n"); - goto release_parent_ref; - } - err = transport_register_device(&conn->dev); - if (err) { - iscsi_cls_session_printk(KERN_ERR, session, "could not " - "register transport's dev\n"); - goto release_conn_ref; - } - - spin_lock_irqsave(&connlock, flags); - list_add(&conn->conn_list, &connlist); - spin_unlock_irqrestore(&connlock, flags); - - ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n"); - return conn; - -release_conn_ref: - device_unregister(&conn->dev); - put_device(&session->dev); - return NULL; -release_parent_ref: - put_device(&session->dev); -free_conn: - kfree(conn); - return NULL; -} - -EXPORT_SYMBOL_GPL(iscsi_create_conn); - /** * iscsi_destroy_conn - destroy iscsi class connection * @conn: iscsi cls session diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index ad341835e847..97e947962b52 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -446,8 +446,6 @@ extern struct iscsi_cls_conn *iscsi_alloc_conn(struct iscsi_cls_session *sess, int dd_size, uint32_t cid); extern int iscsi_add_conn(struct iscsi_cls_conn *conn); extern void iscsi_remove_conn(struct iscsi_cls_conn *conn); -extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, - int dd_size, uint32_t cid); extern void iscsi_put_conn(struct iscsi_cls_conn *conn); extern void iscsi_get_conn(struct iscsi_cls_conn *conn); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); -- cgit v1.2.3 From 8709c323091be019f76a49cf783052a5636aca85 Mon Sep 17 00:00:00 2001 From: Wenchao Hao Date: Wed, 9 Mar 2022 20:57:59 -0500 Subject: scsi: libiscsi: Teardown iscsi_cls_conn gracefully Commit 1b8d0300a3e9 ("scsi: libiscsi: Fix UAF in iscsi_conn_get_param()/iscsi_conn_teardown()") fixed an UAF in iscsi_conn_get_param() and introduced 2 tmp_xxx varibles. We can gracefully fix this UAF with the help of device_del(). Calling iscsi_remove_conn() at the beginning of iscsi_conn_teardown would make userspace unable to see iscsi_cls_conn. This way we we can free memory safely. Remove iscsi_destroy_conn() since it is no longer used. Link: https://lore.kernel.org/r/20220310015759.3296841-4-haowenchao@huawei.com Reviewed-by: Mike Christie Signed-off-by: Wenchao Hao Signed-off-by: Wu Bo Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 10 +++++----- drivers/scsi/scsi_transport_iscsi.c | 27 +++++---------------------- include/scsi/scsi_transport_iscsi.h | 1 - 3 files changed, 10 insertions(+), 28 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 69ddc9f585c5..d09926e6c8a8 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -3107,8 +3107,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; - char *tmp_persistent_address = conn->persistent_address; - char *tmp_local_ipaddr = conn->local_ipaddr; + + iscsi_remove_conn(cls_conn); del_timer_sync(&conn->transport_timer); @@ -3130,6 +3130,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) spin_lock_bh(&session->frwd_lock); free_pages((unsigned long) conn->data, get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); + kfree(conn->persistent_address); + kfree(conn->local_ipaddr); /* regular RX path uses back_lock */ spin_lock_bh(&session->back_lock); kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, @@ -3140,9 +3142,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) spin_unlock_bh(&session->frwd_lock); mutex_unlock(&session->eh_mutex); - iscsi_destroy_conn(cls_conn); - kfree(tmp_persistent_address); - kfree(tmp_local_ipaddr); + iscsi_put_conn(cls_conn); } EXPORT_SYMBOL_GPL(iscsi_conn_teardown); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 803b6b06d83b..27951ea05dd4 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2137,7 +2137,11 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data) { if (!iscsi_is_conn_dev(dev)) return 0; - return iscsi_destroy_conn(iscsi_dev_to_conn(dev)); + + iscsi_remove_conn(iscsi_dev_to_conn(dev)); + iscsi_put_conn(iscsi_dev_to_conn(dev)); + + return 0; } void iscsi_remove_session(struct iscsi_cls_session *session) @@ -2414,27 +2418,6 @@ void iscsi_remove_conn(struct iscsi_cls_conn *conn) } EXPORT_SYMBOL_GPL(iscsi_remove_conn); -/** - * iscsi_destroy_conn - destroy iscsi class connection - * @conn: iscsi cls session - * - * This can be called from a LLD or iscsi_transport. - */ -int iscsi_destroy_conn(struct iscsi_cls_conn *conn) -{ - unsigned long flags; - - spin_lock_irqsave(&connlock, flags); - list_del(&conn->conn_list); - spin_unlock_irqrestore(&connlock, flags); - - transport_unregister_device(&conn->dev); - ISCSI_DBG_TRANS_CONN(conn, "Completing conn destruction\n"); - device_unregister(&conn->dev); - return 0; -} -EXPORT_SYMBOL_GPL(iscsi_destroy_conn); - void iscsi_put_conn(struct iscsi_cls_conn *conn) { put_device(&conn->dev); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 97e947962b52..38e4a67f5922 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -448,7 +448,6 @@ extern int iscsi_add_conn(struct iscsi_cls_conn *conn); extern void iscsi_remove_conn(struct iscsi_cls_conn *conn); extern void iscsi_put_conn(struct iscsi_cls_conn *conn); extern void iscsi_get_conn(struct iscsi_cls_conn *conn); -extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session); extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size); -- cgit v1.2.3