From 1ddebc42e7a394dfbee8197d20072136ac9b729b Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Thu, 23 Jul 2026 10:33:43 +0530 Subject: [PATCH] qla2x00t-32gbit: Update handling of status entries for 29xx series Modify the handling of status entries in the qla2xxx driver to accommodate the extended structure for the 29xx series. Changes include updating function signatures to accept a generic pointer for status packets, and adjusting the logic to differentiate between the standard and extended status entries. This ensures proper processing of completion statuses and error handling for the new hardware capabilities. Signed-off-by: Nilesh Javali Reviewed-by: Hannes Reinecke Link: https://patch.msgid.link/20260723050413.3897522-27-njavali@marvell.com Signed-off-by: Martin K. Petersen (Oracle) [ commit 4cff96e29e3f911cf40e6e31970694bc2d248aac upstream ] --- qla2x00t-32gbit/qla_edif.c | 15 +++-- qla2x00t-32gbit/qla_gbl.h | 2 +- qla2x00t-32gbit/qla_inline.h | 45 ++++++++++++++ qla2x00t-32gbit/qla_isr.c | 111 ++++++++++++++++++++++------------- qla2x00t-32gbit/qla_mbx.c | 28 +++++---- qla2x00t-32gbit/qla_os.c | 1 + 6 files changed, 143 insertions(+), 59 deletions(-) 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);