diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 38 |
2 files changed, 40 insertions, 4 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 205b4e38030e..5464b116d328 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -3439,7 +3439,8 @@ struct els_request64_wqe { | |||
3439 | #define els_req64_hopcnt_SHIFT 24 | 3439 | #define els_req64_hopcnt_SHIFT 24 |
3440 | #define els_req64_hopcnt_MASK 0x000000ff | 3440 | #define els_req64_hopcnt_MASK 0x000000ff |
3441 | #define els_req64_hopcnt_WORD word13 | 3441 | #define els_req64_hopcnt_WORD word13 |
3442 | uint32_t reserved[2]; | 3442 | uint32_t word14; |
3443 | uint32_t max_response_payload_len; | ||
3443 | }; | 3444 | }; |
3444 | 3445 | ||
3445 | struct xmit_els_rsp64_wqe { | 3446 | struct xmit_els_rsp64_wqe { |
@@ -3554,7 +3555,8 @@ struct gen_req64_wqe { | |||
3554 | uint32_t relative_offset; | 3555 | uint32_t relative_offset; |
3555 | struct wqe_rctl_dfctl wge_ctl; /* word 5 */ | 3556 | struct wqe_rctl_dfctl wge_ctl; /* word 5 */ |
3556 | struct wqe_common wqe_com; /* words 6-11 */ | 3557 | struct wqe_common wqe_com; /* words 6-11 */ |
3557 | uint32_t rsvd_12_15[4]; | 3558 | uint32_t rsvd_12_14[3]; |
3559 | uint32_t max_response_payload_len; | ||
3558 | }; | 3560 | }; |
3559 | 3561 | ||
3560 | struct create_xri_wqe { | 3562 | struct create_xri_wqe { |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 3850949c8a79..a262d22bca44 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -8188,6 +8188,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8188 | bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); | 8188 | bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); |
8189 | bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); | 8189 | bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); |
8190 | bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); | 8190 | bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); |
8191 | wqe->els_req.max_response_payload_len = total_len - xmit_len; | ||
8191 | break; | 8192 | break; |
8192 | case CMD_XMIT_SEQUENCE64_CX: | 8193 | case CMD_XMIT_SEQUENCE64_CX: |
8193 | bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, | 8194 | bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, |
@@ -8324,6 +8325,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, | |||
8324 | bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); | 8325 | bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); |
8325 | bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); | 8326 | bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); |
8326 | bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); | 8327 | bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); |
8328 | wqe->gen_req.max_response_payload_len = total_len - xmit_len; | ||
8327 | command_type = OTHER_COMMAND; | 8329 | command_type = OTHER_COMMAND; |
8328 | break; | 8330 | break; |
8329 | case CMD_XMIT_ELS_RSP64_CX: | 8331 | case CMD_XMIT_ELS_RSP64_CX: |
@@ -11195,8 +11197,11 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, | |||
11195 | struct lpfc_iocbq *pIocbOut, | 11197 | struct lpfc_iocbq *pIocbOut, |
11196 | struct lpfc_wcqe_complete *wcqe) | 11198 | struct lpfc_wcqe_complete *wcqe) |
11197 | { | 11199 | { |
11200 | int numBdes, i; | ||
11198 | unsigned long iflags; | 11201 | unsigned long iflags; |
11199 | uint32_t status; | 11202 | uint32_t status, max_response; |
11203 | struct lpfc_dmabuf *dmabuf; | ||
11204 | struct ulp_bde64 *bpl, bde; | ||
11200 | size_t offset = offsetof(struct lpfc_iocbq, iocb); | 11205 | size_t offset = offsetof(struct lpfc_iocbq, iocb); |
11201 | 11206 | ||
11202 | memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, | 11207 | memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset, |
@@ -11213,7 +11218,36 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, | |||
11213 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 11218 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
11214 | else { | 11219 | else { |
11215 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 11220 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
11216 | pIocbIn->iocb.un.genreq64.bdl.bdeSize = wcqe->total_data_placed; | 11221 | switch (pIocbOut->iocb.ulpCommand) { |
11222 | case CMD_ELS_REQUEST64_CR: | ||
11223 | dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; | ||
11224 | bpl = (struct ulp_bde64 *)dmabuf->virt; | ||
11225 | bde.tus.w = le32_to_cpu(bpl[1].tus.w); | ||
11226 | max_response = bde.tus.f.bdeSize; | ||
11227 | break; | ||
11228 | case CMD_GEN_REQUEST64_CR: | ||
11229 | max_response = 0; | ||
11230 | if (!pIocbOut->context3) | ||
11231 | break; | ||
11232 | numBdes = pIocbOut->iocb.un.genreq64.bdl.bdeSize/ | ||
11233 | sizeof(struct ulp_bde64); | ||
11234 | dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3; | ||
11235 | bpl = (struct ulp_bde64 *)dmabuf->virt; | ||
11236 | for (i = 0; i < numBdes; i++) { | ||
11237 | bde.tus.w = le32_to_cpu(bpl[i].tus.w); | ||
11238 | if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64) | ||
11239 | max_response += bde.tus.f.bdeSize; | ||
11240 | } | ||
11241 | break; | ||
11242 | default: | ||
11243 | max_response = wcqe->total_data_placed; | ||
11244 | break; | ||
11245 | } | ||
11246 | if (max_response < wcqe->total_data_placed) | ||
11247 | pIocbIn->iocb.un.genreq64.bdl.bdeSize = max_response; | ||
11248 | else | ||
11249 | pIocbIn->iocb.un.genreq64.bdl.bdeSize = | ||
11250 | wcqe->total_data_placed; | ||
11217 | } | 11251 | } |
11218 | 11252 | ||
11219 | /* Convert BG errors for completion status */ | 11253 | /* Convert BG errors for completion status */ |