Commit e7f40349 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: Fix lpfc overwrite of sg_cnt field in nvmefc_tgt_fcp_req

In lpfc_nvmet_prep_fcp_wqe() the line "rsp->sg_cnt = 0" is modifying the
transport's data structure. This may result in the transport believing the
s/g list was already freed, thus may not unmap/free it properly.  Lpfc
driver should not modify the transport data structure.

The zeroing of the sg_cnt is to avoid use of the transport's sgl in a
subsequent loop where the driver builds the necessary requests for the
adapter firmware to complete the IO.

Change LLDD to use a local copy of the transport sg_cnt when building
requests to be passed to the adapter fw.

Link: https://lore.kernel.org/r/20200322181304.37655-4-jsmart2021@gmail.comSigned-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f861f596
...@@ -2598,7 +2598,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, ...@@ -2598,7 +2598,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
union lpfc_wqe128 *wqe; union lpfc_wqe128 *wqe;
struct ulp_bde64 *bde; struct ulp_bde64 *bde;
dma_addr_t physaddr; dma_addr_t physaddr;
int i, cnt; int i, cnt, nsegs;
int do_pbde; int do_pbde;
int xc = 1; int xc = 1;
...@@ -2629,6 +2629,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, ...@@ -2629,6 +2629,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
phba->cfg_nvme_seg_cnt); phba->cfg_nvme_seg_cnt);
return NULL; return NULL;
} }
nsegs = rsp->sg_cnt;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
nvmewqe = ctxp->wqeq; nvmewqe = ctxp->wqeq;
...@@ -2868,7 +2869,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, ...@@ -2868,7 +2869,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
wqe->fcp_trsp.rsvd_12_15[0] = 0; wqe->fcp_trsp.rsvd_12_15[0] = 0;
/* Use rspbuf, NOT sg list */ /* Use rspbuf, NOT sg list */
rsp->sg_cnt = 0; nsegs = 0;
sgl->word2 = 0; sgl->word2 = 0;
atomic_inc(&tgtp->xmt_fcp_rsp); atomic_inc(&tgtp->xmt_fcp_rsp);
break; break;
...@@ -2885,7 +2886,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, ...@@ -2885,7 +2886,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT; nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT;
nvmewqe->context1 = ndlp; nvmewqe->context1 = ndlp;
for_each_sg(rsp->sg, sgel, rsp->sg_cnt, i) { for_each_sg(rsp->sg, sgel, nsegs, i) {
physaddr = sg_dma_address(sgel); physaddr = sg_dma_address(sgel);
cnt = sg_dma_len(sgel); cnt = sg_dma_len(sgel);
sgl->addr_hi = putPaddrHigh(physaddr); sgl->addr_hi = putPaddrHigh(physaddr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment