mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 16:53:20 -04:00
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:
committed by
Martin K. Petersen (Oracle)
parent
67aff6b6fe
commit
b4126180f7
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user