diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 4ac3cb08fcc9..bba324febf09 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -989,10 +989,8 @@ extern void qla24xx_process_purex_list(struct purex_list *); extern void qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp); extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp); extern void qla_wait_nvme_release_cmd_kref(srb_t *sp); -extern void qla_nvme_abort_set_option - (struct abort_entry_24xx *abt, srb_t *sp); -extern void qla_nvme_abort_process_comp_status - (struct abort_entry_24xx *abt, srb_t *sp); +extern void qla_nvme_abort_set_option(void *pkt, srb_t *sp); +extern void qla_nvme_abort_process_comp_status(void *pkt, srb_t *sp); struct scsi_qla_host *qla_find_host_by_vp_idx(struct scsi_qla_host *vha, uint16_t vp_idx); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c21d7f418f47..b631fee8c430 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -3926,32 +3926,50 @@ queuing_error: } static void -qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) +qla24xx_abort_iocb(srb_t *sp, void *pkt) { struct srb_iocb *aio = &sp->u.iocb_cmd; scsi_qla_host_t *vha = sp->vha; + struct qla_hw_data *ha = vha->hw; struct req_que *req = sp->qpair->req; srb_t *orig_sp = sp->cmd_sp; + struct abort_entry_24xx *abt = pkt; - memset(abt_iocb, 0, sizeof(struct abort_entry_24xx)); - abt_iocb->entry_type = ABORT_IOCB_TYPE; - abt_iocb->entry_count = 1; - abt_iocb->handle = make_handle(req->id, sp->handle); - if (sp->fcport) { - abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); - abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - abt_iocb->port_id[1] = sp->fcport->d_id.b.area; - abt_iocb->port_id[2] = sp->fcport->d_id.b.domain; + /* + * abort_entry_24xx_ext overlays abort_entry_24xx through + * req_que_no (offsets 0-17). After that the layouts diverge: + * the 24xx variant has 30 bytes of reserved_1 followed by + * port_id[3] and a u8 vp_index at offsets 48-51, while the + * ext variant places a __le16 vp_index at offset 18 and has + * no port_id field. Common-header writes go through one + * struct abort_entry_24xx * view; only port_id / vp_index + * branch on stride. + */ + memset(pkt, 0, qla_req_entry_size(ha)); + abt->entry_type = ABORT_IOCB_TYPE; + abt->entry_count = 1; + abt->handle = make_handle(req->id, sp->handle); + if (sp->fcport) + abt->nport_handle = cpu_to_le16(sp->fcport->loop_id); + abt->handle_to_abort = + make_handle(le16_to_cpu(aio->u.abt.req_que_no), + aio->u.abt.cmd_hndl); + abt->req_que_no = aio->u.abt.req_que_no; + if (IS_QLA29XX(ha)) { + ((struct abort_entry_24xx_ext *)pkt)->vp_index = + cpu_to_le16(vha->vp_idx); + } else { + if (sp->fcport) { + abt->port_id[0] = sp->fcport->d_id.b.al_pa; + abt->port_id[1] = sp->fcport->d_id.b.area; + abt->port_id[2] = sp->fcport->d_id.b.domain; + } + abt->vp_index = vha->vp_idx; } - abt_iocb->handle_to_abort = - make_handle(le16_to_cpu(aio->u.abt.req_que_no), - aio->u.abt.cmd_hndl); - abt_iocb->vp_index = vha->vp_idx; - abt_iocb->req_que_no = aio->u.abt.req_que_no; /* need to pass original sp */ if (orig_sp) - qla_nvme_abort_set_option(abt_iocb, orig_sp); + qla_nvme_abort_set_option(pkt, orig_sp); /* Send the command to the firmware */ wmb(); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 855d6dbeedec..6fbcbdd208c3 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3961,7 +3961,7 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) static void qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, - struct abort_entry_24xx *pkt) + void *pkt) { const char func[] = "ABT_IOCB"; srb_t *sp; @@ -3973,7 +3973,14 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, return; abt = &sp->u.iocb_cmd; - abt->u.abt.comp_status = pkt->comp_status; + /* + * abort_entry_24xx_ext overlays abort_entry_24xx through the + * nport_handle/comp_status union at offset 8, so reading + * comp_status is stride-agnostic and goes through the 24xx view. + */ + abt->u.abt.comp_status = + ((struct abort_entry_24xx *)pkt)->comp_status; + orig_sp = sp->cmd_sp; /* Need to pass original sp */ if (orig_sp) @@ -4175,8 +4182,7 @@ process_err: qla_marker_iocb_entry(vha, rsp->req, pkt); break; case ABORT_IOCB_TYPE: - qla24xx_abort_iocb_entry(vha, rsp->req, - (struct abort_entry_24xx *)pkt); + qla24xx_abort_iocb_entry(vha, rsp->req, pkt); break; case MBX_IOCB_TYPE: qla24xx_mbx_iocb_entry(vha, rsp->req, diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 9bef87862077..0d7aa6fce007 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3324,7 +3324,7 @@ qla24xx_abort_command(srb_t *sp) { int rval; unsigned long flags = 0; - + void *abt_buf; struct abort_entry_24xx *abt; dma_addr_t abt_dma; uint32_t handle; @@ -3356,28 +3356,42 @@ qla24xx_abort_command(srb_t *sp) return QLA_ERR_NOT_FOUND; } - abt = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma); - if (abt == NULL) { + abt_buf = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &abt_dma); + if (abt_buf == NULL) { ql_log(ql_log_warn, vha, 0x108d, "Failed to allocate abort IOCB.\n"); return QLA_MEMORY_ALLOC_FAILED; } + abt = abt_buf; + /* + * abort_entry_24xx_ext overlays abort_entry_24xx through + * req_que_no (offsets 0-17), and entry_status (offset 3) and + * comp_status (offset 8) sit at identical offsets in both, so + * the common header writes and the completion-status reads are + * stride-agnostic and go through the 24xx view. Only port_id + * (24xx-only) and vp_index width / offset diverge per stride. + */ abt->entry_type = ABORT_IOCB_TYPE; abt->entry_count = 1; abt->handle = make_handle(req->id, abt->handle); abt->nport_handle = cpu_to_le16(fcport->loop_id); abt->handle_to_abort = make_handle(req->id, handle); - abt->port_id[0] = fcport->d_id.b.al_pa; - abt->port_id[1] = fcport->d_id.b.area; - abt->port_id[2] = fcport->d_id.b.domain; - abt->vp_index = fcport->vha->vp_idx; - abt->req_que_no = cpu_to_le16(req->id); - /* Need to pass original sp */ - qla_nvme_abort_set_option(abt, sp); + if (IS_QLA29XX(ha)) { + ((struct abort_entry_24xx_ext *)abt)->vp_index = + cpu_to_le16(fcport->vha->vp_idx); + } else { + abt->port_id[0] = fcport->d_id.b.al_pa; + abt->port_id[1] = fcport->d_id.b.area; + abt->port_id[2] = fcport->d_id.b.domain; + abt->vp_index = fcport->vha->vp_idx; + } - rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0); + /* Need to pass original sp */ + qla_nvme_abort_set_option(abt_buf, sp); + + rval = qla2x00_issue_iocb(vha, abt_buf, abt_dma, 0); if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x108e, "Failed to issue IOCB (%x).\n", rval); @@ -3386,11 +3400,11 @@ qla24xx_abort_command(srb_t *sp) "Failed to complete IOCB -- error status (%x).\n", abt->entry_status); rval = QLA_FUNCTION_FAILED; - } else if (abt->nport_handle != cpu_to_le16(0)) { + } else if (abt->comp_status != cpu_to_le16(0)) { ql_dbg(ql_dbg_mbx, vha, 0x1090, "Failed to complete IOCB -- completion status (%x).\n", - le16_to_cpu(abt->nport_handle)); - if (abt->nport_handle == cpu_to_le16(CS_IOCB_ERROR)) + le16_to_cpu(abt->comp_status)); + if (abt->comp_status == cpu_to_le16(CS_IOCB_ERROR)) rval = QLA_FUNCTION_PARAMETER_ERROR; else rval = QLA_FUNCTION_FAILED; @@ -3398,12 +3412,13 @@ qla24xx_abort_command(srb_t *sp) ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091, "Done %s.\n", __func__); } + if (rval == QLA_SUCCESS) - qla_nvme_abort_process_comp_status(abt, sp); + qla_nvme_abort_process_comp_status(abt_buf, sp); qla_wait_nvme_release_cmd_kref(sp); - dma_pool_free(ha->s_dma_pool, abt, abt_dma); + dma_pool_free(ha->s_dma_pool, abt_buf, abt_dma); return rval; } diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index b2eacf0277f4..8fa980db6ce4 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -1067,36 +1067,69 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) return ret; } -void qla_nvme_abort_set_option(struct abort_entry_24xx *abt, srb_t *orig_sp) +void qla_nvme_abort_set_option(void *pkt, srb_t *orig_sp) { struct qla_hw_data *ha; + struct abort_entry_24xx *abt = pkt; if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp))) return; ha = orig_sp->fcport->vha->hw; + /* + * abort_entry_24xx_ext overlays abort_entry_24xx through 'options' + * (offset 10), so options writes are stride-agnostic. The drv + * union sits at offset 56 in the 24xx layout but offset 24 in the + * ext layout, so the drv writes need a typed pointer. + */ WARN_ON_ONCE(abt->options & cpu_to_le16(BIT_0)); - /* Use Driver Specified Retry Count */ abt->options |= cpu_to_le16(AOF_ABTS_RTY_CNT); - abt->drv.abts_rty_cnt = cpu_to_le16(2); - /* Use specified response timeout */ abt->options |= cpu_to_le16(AOF_RSP_TIMEOUT); - /* set it to 2 * r_a_tov in secs */ - abt->drv.rsp_timeout = cpu_to_le16(2 * (ha->r_a_tov / 10)); + if (IS_QLA29XX(ha)) { + struct abort_entry_24xx_ext *abt_ext = pkt; + + abt_ext->drv.abts_rty_cnt = cpu_to_le16(2); + abt_ext->drv.rsp_timeout = + cpu_to_le16(2 * (ha->r_a_tov / 10)); + } else { + abt->drv.abts_rty_cnt = cpu_to_le16(2); + abt->drv.rsp_timeout = cpu_to_le16(2 * (ha->r_a_tov / 10)); + } } -void qla_nvme_abort_process_comp_status(struct abort_entry_24xx *abt, srb_t *orig_sp) +void qla_nvme_abort_process_comp_status(void *pkt, srb_t *orig_sp) { u16 comp_status; struct scsi_qla_host *vha; + u8 rjt_vendor_unique, rjt_reason_expl, rjt_reason_code; + struct abort_entry_24xx *abt = pkt; if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp))) return; vha = orig_sp->fcport->vha; + /* + * comp_status sits at offset 8 in both layouts (the + * nport_handle/comp_status union), so the read is + * stride-agnostic. The fw union, like drv, lives at offset + * 56 in the 24xx layout and offset 24 in the ext layout, so + * those byte reads still need a typed pointer. + */ comp_status = le16_to_cpu(abt->comp_status); + if (IS_QLA29XX(vha->hw)) { + struct abort_entry_24xx_ext *abt_ext = pkt; + + rjt_vendor_unique = abt_ext->fw.ba_rjt_vendorUnique; + rjt_reason_expl = abt_ext->fw.ba_rjt_reasonCodeExpl; + rjt_reason_code = abt_ext->fw.ba_rjt_reasonCode; + } else { + rjt_vendor_unique = abt->fw.ba_rjt_vendorUnique; + rjt_reason_expl = abt->fw.ba_rjt_reasonCodeExpl; + rjt_reason_code = abt->fw.ba_rjt_reasonCode; + } + switch (comp_status) { case CS_RESET: /* reset event aborted */ case CS_ABORTED: /* IOCB was cleaned */ @@ -1116,11 +1149,8 @@ void qla_nvme_abort_process_comp_status(struct abort_entry_24xx *abt, srb_t *ori /* BA_RJT was received for the ABTS */ case CS_REJECT_RECEIVED: ql_dbg(ql_dbg_async, vha, 0xf09e, - "BA_RJT was received for the ABTS rjt_vendorUnique = %u", - abt->fw.ba_rjt_vendorUnique); - ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09e, - "ba_rjt_reasonCodeExpl = %u, ba_rjt_reasonCode = %u\n", - abt->fw.ba_rjt_reasonCodeExpl, abt->fw.ba_rjt_reasonCode); + "BA_RJT was received for the ABTS rjt_vendorUnique=%u, ba_rjt_reasonCodeExpl=%u, ba_rjt_reasonCode=%u\n", + rjt_vendor_unique, rjt_reason_expl, rjt_reason_code); break; case CS_COMPLETE: diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6c951839507b..d9141d62bbb5 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -8358,6 +8358,7 @@ qla2x00_module_init(void) BUILD_BUG_ON(sizeof(ms_iocb_entry_t) != 64); BUILD_BUG_ON(sizeof(request_t) != 64); BUILD_BUG_ON(sizeof(struct abort_entry_24xx) != 64); + BUILD_BUG_ON(sizeof(struct abort_entry_24xx_ext) != 128); BUILD_BUG_ON(sizeof(struct abort_iocb_entry_fx00) != 64); BUILD_BUG_ON(sizeof(struct abts_entry_24xx) != 64); BUILD_BUG_ON(sizeof(struct access_chip_84xx) != 64);