scsi: qla2xxx: Add abort command handling for 29xx series

Extend the abort-IOCB code path to support the 29xx extended
abort_entry_24xx_ext structure alongside the existing abort_entry_24xx.

The two layouts overlay byte-for-byte through req_que_no (offsets 0-17):
entry_status (offset 3), the nport_handle/comp_status union (offset 8),
and options (offset 10) sit at identical positions in both.  After that
they diverge: the 24xx variant carries reserved_1[30], 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 drops port_id.  The drv / fw unions live at
offset 56 in the 24xx layout but offset 24 in ext.

Leverage this overlap by using a single struct abort_entry_24xx * view
for the common header writes (entry_type, count, handle, nport_handle,
handle_to_abort, req_que_no) and completion-status reads (entry_status,
comp_status), branching on IS_QLA29XX() only where the layouts genuinely
diverge:

  - port_id (24xx-only) and vp_index width on the issue path
    (qla24xx_abort_iocb in qla_iocb.c, qla24xx_abort_command in
    qla_mbx.c);

  - drv / fw union access in qla_nvme_abort_set_option /
    qla_nvme_abort_process_comp_status (qla_nvme.c);

  - completion comp_status read in qla24xx_abort_iocb_entry (qla_isr.c)
    is stride-agnostic -- no IS_QLA29XX dispatch needed.

Function signatures in qla_nvme_abort_set_option(),
qla_nvme_abort_process_comp_status(), qla24xx_abort_iocb(), and
qla24xx_abort_iocb_entry() are widened to accept void * so both struct
variants can be passed through.  memset() uses qla_req_entry_size(ha) to
match the ring-slot size.  Response status checking now reads
comp_status instead of nport_handle.  A BUILD_BUG_ON verifies
abort_entry_24xx_ext is 128 bytes.

Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Link: https://patch.msgid.link/20260723050413.3897522-34-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
This commit is contained in:
Nilesh Javali
2026-07-23 10:33:50 +05:30
committed by Martin K. Petersen (Oracle)
parent 67aff6b6fe
commit b4126180f7
6 changed files with 120 additions and 52 deletions

View File

@@ -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);

View File

@@ -3926,32 +3926,50 @@ qla82xx_start_scsi(srb_t *sp)
}
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();

View File

@@ -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 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
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,

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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);