diff --git a/qla2x00t-32gbit/qla_edif.c b/qla2x00t-32gbit/qla_edif.c index 98ed33d4f..61f5d726d 100644 --- a/qla2x00t-32gbit/qla_edif.c +++ b/qla2x00t-32gbit/qla_edif.c @@ -3501,12 +3501,15 @@ static void __chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, } void qla_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, - srb_t *sp, struct sts_entry_24xx *sts24) + srb_t *sp, void *pkt) { + struct sts_entry_24xx *sts24 = pkt; + struct sts_entry_24xx_ext *stsext = pkt; + struct qla_hw_data *ha = vha->hw; fc_port_t *fcport = sp->fcport; - /* sa_index used by this iocb */ struct scsi_cmnd *cmd = GET_CMD_SP(sp); uint32_t handle; + uint16_t sa_index; handle = (uint32_t)LSW(sts24->handle); @@ -3514,8 +3517,12 @@ void qla_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, if (cmd->sc_data_direction != DMA_FROM_DEVICE) return; - return __chk_edif_rx_sa_delete_pending(vha, fcport, handle, - le16_to_cpu(sts24->edif_sa_index)); + if (IS_QLA29XX(ha)) + sa_index = le16_to_cpu(stsext->read_sa_index); + else + sa_index = le16_to_cpu(sts24->edif_sa_index); + + return __chk_edif_rx_sa_delete_pending(vha, fcport, handle, sa_index); } void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport, diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index f6cb61357..dca046f54 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -136,7 +136,7 @@ void qla_edif_sadb_release(struct qla_hw_data *ha); int qla_edif_sadb_build_free_pool(struct qla_hw_data *ha); void qla_edif_sadb_release_free_pool(struct qla_hw_data *ha); void qla_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, - srb_t *sp, struct sts_entry_24xx *sts24); + srb_t *sp, void *pkt); void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport, struct ctio7_from_24xx *ctio); void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport); diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index 27b859fe9..b67d38d41 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -830,3 +830,48 @@ static inline bool val_is_in_range(u32 val, u32 start, u32 end) else return false; } + +/* + * Common fields extracted from FWI2 status IOCBs. Populated once so + * callers avoid duplicated IS_QLA29XX() branches for every field access. + */ +struct qla_sts_fwi2 { + u8 *data; + u32 data_sz; + u16 scsi_status; + u16 sts_qual; + u32 sense_len; + u32 rsp_data_len; + u32 rsp_residual_count; +}; + +static inline void +qla_sts_fwi2_extract(struct qla_hw_data *ha, void *pkt, + struct qla_sts_fwi2 *sf) +{ + if (IS_QLA29XX(ha)) { + struct sts_entry_24xx_ext *s = pkt; + + sf->scsi_status = le16_to_cpu(s->u2.scsi_status); + sf->sts_qual = le16_to_cpu(s->u2.retry_delay_timer); + sf->sense_len = le32_to_cpu(s->u2.sense_len); + sf->rsp_data_len = le32_to_cpu(s->u2.rsp_data_len_ndma); + sf->rsp_residual_count = le32_to_cpu(s->u2.rsp_residual_count); + sf->data = s->u2.data; + sf->data_sz = sizeof(s->u2.data); + host_to_fcp_swap(s->u2.data, sizeof(s->u2.data)); + host_to_fcp_swap(s->act_dif, sizeof(s->act_dif)); + host_to_fcp_swap(s->exp_dif, sizeof(s->exp_dif)); + } else { + struct sts_entry_24xx *s = pkt; + + sf->scsi_status = le16_to_cpu(s->scsi_status); + sf->sts_qual = le16_to_cpu(s->status_qualifier); + sf->sense_len = le32_to_cpu(s->sense_len); + sf->rsp_data_len = le32_to_cpu(s->rsp_data_len); + sf->rsp_residual_count = le32_to_cpu(s->rsp_residual_count); + sf->data = s->data; + sf->data_sz = sizeof(s->data); + host_to_fcp_swap(s->data, sizeof(s->data)); + } +} diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 272464b12..2e73f67a3 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -2319,8 +2319,9 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, static void qla24xx_els_ct_entry(scsi_qla_host_t *v, struct req_que *req, - struct sts_entry_24xx *pkt, int iocb_type) + void *pkt, int iocb_type) { + struct sts_entry_24xx *sts24 = pkt; struct els_sts_entry_24xx *ese = (struct els_sts_entry_24xx *)pkt; const char func[] = "ELS_CT_IOCB"; const char *type; @@ -2343,9 +2344,9 @@ qla24xx_els_ct_entry(scsi_qla_host_t *v, struct req_que *req, type = NULL; - comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status); - fw_status[1] = le32_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_1); - fw_status[2] = le32_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_2); + comp_status = fw_status[0] = le16_to_cpu(sts24->comp_status); + fw_status[1] = le32_to_cpu(ese->error_subcode_1); + fw_status[2] = le32_to_cpu(ese->error_subcode_2); switch (sp->type) { case SRB_ELS_CMD_RPT: @@ -2681,7 +2682,9 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) srb_t *sp; struct srb_iocb *iocb; struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; + struct qla_hw_data *ha = vha->hw; u16 comp_status; + struct qla_sts_fwi2 sf; sp = qla2x00_get_sp_from_handle(vha, func, req, tsk); if (!sp) @@ -2703,18 +2706,19 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) "Async-%s error - hdl=%x completion status(%x).\n", type, sp->handle, comp_status); iocb->u.tmf.data = QLA_FUNCTION_FAILED; - } else if ((le16_to_cpu(sts->scsi_status) & - SS_RESPONSE_INFO_LEN_VALID)) { - host_to_fcp_swap(sts->data, sizeof(sts->data)); - if (le32_to_cpu(sts->rsp_data_len) < 4) { - ql_log(ql_log_warn, fcport->vha, 0x503b, - "Async-%s error - hdl=%x not enough response(%d).\n", - type, sp->handle, sts->rsp_data_len); - } else if (sts->data[3]) { - ql_log(ql_log_warn, fcport->vha, 0x503c, - "Async-%s error - hdl=%x response(%x).\n", - type, sp->handle, sts->data[3]); - iocb->u.tmf.data = QLA_FUNCTION_FAILED; + } else { + qla_sts_fwi2_extract(ha, tsk, &sf); + if (sf.scsi_status & SS_RESPONSE_INFO_LEN_VALID) { + if (sf.rsp_data_len < 4) { + ql_log(ql_log_warn, fcport->vha, 0x503b, + "Async-%s error - hdl=%x not enough response(%d).\n", + type, sp->handle, sf.rsp_data_len); + } else if (sf.data[3]) { + ql_log(ql_log_warn, fcport->vha, 0x503c, + "Async-%s error - hdl=%x response(%x).\n", + type, sp->handle, sf.data[3]); + iocb->u.tmf.data = QLA_FUNCTION_FAILED; + } } } @@ -2743,7 +2747,8 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) if (iocb->u.tmf.data != QLA_SUCCESS) ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, sp->vha, 0x5055, - sts, sizeof(*sts)); + tsk, IS_QLA29XX(ha) ? + sizeof(struct sts_entry_24xx_ext) : sizeof(*sts)); sp->done(sp, 0); } @@ -2754,6 +2759,8 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, fc_port_t *fcport; struct srb_iocb *iocb; struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; + struct sts_entry_24xx_ext *stsext = (struct sts_entry_24xx_ext *)tsk; + struct qla_hw_data *ha = vha->hw; uint16_t state_flags; struct nvmefc_fcp_req *fd; uint16_t ret = QLA_SUCCESS; @@ -2805,7 +2812,10 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, uint32_t *inbuf, *outbuf; uint16_t iter; - inbuf = (uint32_t *)&sts->nvme_ersp_data; + if (IS_QLA29XX(ha)) + inbuf = (uint32_t *)stsext->u2.nvme_ersp_data; + else + inbuf = (uint32_t *)&sts->nvme_ersp_data; outbuf = (uint32_t *)fd->rspaddr; iocb->u.nvme.rsp_pyld_len = sts->nvme_rsp_pyld_len; if (unlikely(le16_to_cpu(iocb->u.nvme.rsp_pyld_len) > @@ -3061,16 +3071,26 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, * to indicate to the kernel that the HBA detected error. */ static inline int -qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) +qla2x00_handle_dif_error(srb_t *sp, void *pkt) { struct scsi_qla_host *vha = sp->vha; + struct qla_hw_data *ha = vha->hw; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - uint8_t *ap = &sts24->data[12]; - uint8_t *ep = &sts24->data[20]; + struct sts_entry_24xx *sts24 = pkt; + struct sts_entry_24xx_ext *stsext = pkt; + uint8_t *ap, *ep; uint32_t e_ref_tag, a_ref_tag; uint16_t e_app_tag, a_app_tag; uint16_t e_guard, a_guard; + if (IS_QLA29XX(ha)) { + ap = stsext->act_dif; + ep = stsext->exp_dif; + } else { + ap = &sts24->data[12]; + ep = &sts24->data[20]; + } + /* * swab32 of the "data" field in the beginning of qla2x00_status_entry() * would make guard field appear at offset 2 @@ -3083,7 +3103,7 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) e_ref_tag = get_unaligned_le32(ep + 4); ql_dbg(ql_dbg_io, vha, 0x3023, - "iocb(s) %p Returned STATUS.\n", sts24); + "iocb(s) %px Returned STATUS.\n", pkt); ql_dbg(ql_dbg_io, vha, 0x3024, "DIF ERROR in cmd 0x%x lba 0x%llx act ref" @@ -3215,7 +3235,9 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, if (IS_FWI2_CAPABLE(ha)) { comp_status = le16_to_cpu(sts24->comp_status); - scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; + scsi_status = IS_QLA29XX(ha) ? + le16_to_cpu(((struct sts_entry_24xx_ext *)pkt)->u2.scsi_status) & SS_MASK : + le16_to_cpu(sts24->scsi_status) & SS_MASK; } else { comp_status = le16_to_cpu(sts->comp_status); scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; @@ -3351,10 +3373,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) int res = 0; uint16_t state_flags = 0; uint16_t sts_qual = 0; + struct qla_sts_fwi2 sf; if (IS_FWI2_CAPABLE(ha)) { comp_status = le16_to_cpu(sts24->comp_status); - scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; + scsi_status = IS_QLA29XX(ha) ? + le16_to_cpu(((struct sts_entry_24xx_ext *)pkt)->u2.scsi_status) & SS_MASK : + le16_to_cpu(sts24->scsi_status) & SS_MASK; state_flags = le16_to_cpu(sts24->state_flags); } else { comp_status = le16_to_cpu(sts->comp_status); @@ -3425,7 +3450,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) } /* Fast path completion. */ - qla_chk_edif_rx_sa_delete_pending(vha, sp, sts24); + qla_chk_edif_rx_sa_delete_pending(vha, sp, pkt); sp->qpair->cmd_completion_cnt++; if (comp_status == CS_COMPLETE && scsi_status == 0) { @@ -3452,20 +3477,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) sense_len = par_sense_len = rsp_info_len = resid_len = fw_resid_len = 0; if (IS_FWI2_CAPABLE(ha)) { + qla_sts_fwi2_extract(ha, pkt, &sf); if (scsi_status & SS_SENSE_LEN_VALID) - sense_len = le32_to_cpu(sts24->sense_len); + sense_len = sf.sense_len; if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) - rsp_info_len = le32_to_cpu(sts24->rsp_data_len); + rsp_info_len = sf.rsp_data_len; if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) - resid_len = le32_to_cpu(sts24->rsp_residual_count); + resid_len = sf.rsp_residual_count; if (comp_status == CS_DATA_UNDERRUN) fw_resid_len = le32_to_cpu(sts24->residual_len); - rsp_info = sts24->data; - sense_data = sts24->data; - host_to_fcp_swap(sts24->data, sizeof(sts24->data)); + rsp_info = sf.data; + sense_data = sf.data; + par_sense_len = sf.data_sz; + sts_qual = sf.sts_qual; ox_id = le16_to_cpu(sts24->ox_id); - par_sense_len = sizeof(sts24->data); - sts_qual = le16_to_cpu(sts24->status_qualifier); } else { if (scsi_status & SS_SENSE_LEN_VALID) sense_len = le16_to_cpu(sts->req_sense_length); @@ -3665,7 +3690,7 @@ check_scsi_status: break; case CS_DIF_ERROR: - logit = qla2x00_handle_dif_error(sp, sts24); + logit = qla2x00_handle_dif_error(sp, pkt); res = cp->result; break; @@ -3690,7 +3715,8 @@ check_scsi_status: ox_id, cp->cmnd, scsi_bufflen(cp), rsp_info_len, resid_len, fw_resid_len, sp, cp); ql_dump_buffer(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe0ee, - pkt, sizeof(*sts24)); + pkt, IS_QLA29XX(ha) ? + sizeof(struct sts_entry_24xx_ext) : sizeof(*sts24)); res = DID_ERROR << 16; vha->hw_err_cnt++; break; @@ -3991,7 +4017,7 @@ static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void qla24xx_process_response_queue(struct scsi_qla_host *vha, struct rsp_que *rsp) { - struct sts_entry_24xx *pkt; + void *pkt; struct qla_hw_data *ha = vha->hw; struct purex_entry_24xx *purex_entry; struct purex_item *pure_item; @@ -4023,13 +4049,13 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, while (rsp->ring_index != rsp_in && rsp->ring_ptr->signature != RESPONSE_PROCESSED) { - pkt = (struct sts_entry_24xx *)rsp->ring_ptr; + pkt = (void *)rsp->ring_ptr; cur_ring_index = rsp->ring_index; qla_rsp_ring_advance(rsp); - if (pkt->entry_status != 0) { - if (qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt)) + if (((response_t *)pkt)->entry_status != 0) { + if (qla2x00_error_entry(vha, rsp, (sts_entry_t *)pkt)) goto process_err; ((response_t *)pkt)->signature = RESPONSE_PROCESSED; @@ -4038,7 +4064,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, } process_err: - switch (pkt->entry_type) { + switch (((response_t *)pkt)->entry_type) { case STATUS_TYPE: qla2x00_status_entry(vha, rsp, pkt); break; @@ -4089,7 +4115,7 @@ process_err: rsp->req); break; case NOTIFY_ACK_TYPE: - if (pkt->handle == QLA_TGT_SKIP_HANDLE) + if (((response_t *)pkt)->handle == QLA_TGT_SKIP_HANDLE) qlt_response_pkt_all_vps(vha, rsp, (response_t *)pkt); else @@ -4184,7 +4210,8 @@ process_err: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, "Received unknown response pkt type 0x%x entry status=%x.\n", - pkt->entry_type, pkt->entry_status); + ((response_t *)pkt)->entry_type, + ((response_t *)pkt)->entry_status); break; } ((response_t *)pkt)->signature = RESPONSE_PROCESSED; diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index c073dc35e..f9b326c02 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -3407,6 +3407,7 @@ struct tsk_mgmt_cmd { union { struct tsk_mgmt_entry tsk; struct sts_entry_24xx sts; + struct sts_entry_24xx_ext sts_ext; } p; }; @@ -3417,6 +3418,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, int rval, rval2; struct tsk_mgmt_cmd *tsk; struct sts_entry_24xx *sts; + struct qla_sts_fwi2 sf; dma_addr_t tsk_dma; scsi_qla_host_t *vha; struct qla_hw_data *ha; @@ -3474,18 +3476,20 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, "Failed to complete IOCB -- completion status (%x).\n", le16_to_cpu(sts->comp_status)); rval = QLA_FUNCTION_FAILED; - } else if (le16_to_cpu(sts->scsi_status) & - SS_RESPONSE_INFO_LEN_VALID) { - if (le32_to_cpu(sts->rsp_data_len) < 4) { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1097, - "Ignoring inconsistent data length -- not enough " - "response info (%d).\n", - le32_to_cpu(sts->rsp_data_len)); - } else if (sts->data[3]) { - ql_dbg(ql_dbg_mbx, vha, 0x1098, - "Failed to complete IOCB -- response (%x).\n", - sts->data[3]); - rval = QLA_FUNCTION_FAILED; + } else { + qla_sts_fwi2_extract(ha, sts, &sf); + if (sf.scsi_status & SS_RESPONSE_INFO_LEN_VALID) { + if (sf.rsp_data_len < 4) { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, + 0x1097, + "Ignoring inconsistent data length -- not enough response info (%d).\n", + sf.rsp_data_len); + } else if (sf.data[3]) { + ql_dbg(ql_dbg_mbx, vha, 0x1098, + "Failed to complete IOCB -- response (%x).\n", + sf.data[3]); + rval = QLA_FUNCTION_FAILED; + } } } diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 52241ad09..83640ea9e 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -8653,6 +8653,7 @@ qla2x00_module_init(void) BUILD_BUG_ON(sizeof(struct rdp_rsp_payload) != 336); BUILD_BUG_ON(sizeof(struct sns_cmd_pkt) != 2064); BUILD_BUG_ON(sizeof(struct sts_entry_24xx) != 64); + BUILD_BUG_ON(sizeof(struct sts_entry_24xx_ext) != 128); BUILD_BUG_ON(sizeof(struct tsk_mgmt_entry) != 64); BUILD_BUG_ON(sizeof(struct tsk_mgmt_entry_fx00) != 64); BUILD_BUG_ON(sizeof(struct verify_chip_entry_84xx) != 64);