qla2x00t-32gbit: Add LS4 pass-through IOCB handling for 29xx series

Extend the LS4 pass-through IOCB handling to support the 128-byte
pt_ls4_request_ext layout used by 29xx series adapters.  The extension
grows inline DSD capacity from 2 to 5 entries.  Function signatures are
widened to void * so both layouts can be passed without casts.

pt_ls4_request_ext overlays pt_ls4_request through exchange_address
(offsets 0-27 are byte-identical), so common-header writes go through a
single struct pt_ls4_request * view; only the divergent fields (vp_index
width, tx_/rx_byte_count offset, dsd[] base) are branched.

Signed-off-by: Manish Rangankar <mrangankar@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Link: https://patch.msgid.link/20260723050413.3897522-39-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>

[ commit 33c37242b8128fe6de92af26f9f9b48a9de1d568 upstream ]
This commit is contained in:
Manish Rangankar
2026-10-19 18:07:58 +03:00
committed by Gleb Chesnokov
parent 48d4c315db
commit 90be72c38f
6 changed files with 134 additions and 49 deletions
+37
View File
@@ -295,6 +295,43 @@ struct ct_entry_24xx_ext {
struct dsd64 dsd[NUM_CT_DSDS]; /* Data Segment Descriptors */
};
/*
* 29xx extended Link Service pass-through request IOCB (128 bytes).
*
* Same wire purpose as the 64-byte struct pt_ls4_request used on 24xx-class
* adapters, but laid out for the 128-byte 29xx request ring:
* - vp_index widened to __le16 (bits [8:0] meaningful, see
* CMD_EXT_VP_INDEX_MASK).
* - reserved area expanded to 32 bytes between exchange_address and
* rx_byte_count.
* - inline DSD capacity grown from 2 to 5.
* Header through 'tx_dseg_count' (offset 14) and the control_flags /
* exchange_address fields keep the same offsets as struct pt_ls4_request,
* so common code can populate them via either type once IS_QLA29XX(ha) is
* branched for the layout-divergent fields.
*/
#define NUM_PT_LS4_EXT_DSDS 5
struct pt_ls4_request_ext {
uint8_t entry_type;
uint8_t entry_count;
uint8_t sys_define;
uint8_t entry_status;
uint32_t handle;
__le16 status;
__le16 nport_handle;
__le16 tx_dseg_count;
__le16 vp_index; /* VP Index 9 bits; see CMD_EXT_VP_INDEX_MASK */
__le16 timeout;
__le16 control_flags; /* CF_LS4_* (see struct pt_ls4_request) */
__le16 rx_dseg_count;
__le16 rsvd2;
__le32 exchange_address;
uint8_t rsvd3[32];
__le32 rx_byte_count;
__le32 tx_byte_count;
struct dsd64 dsd[NUM_PT_LS4_EXT_DSDS];
};
/*
* ISP queue - PUREX IOCB entry structure definition
*/
+50 -24
View File
@@ -4055,39 +4055,65 @@ static void qla2x00_send_notify_ack_iocb(srb_t *sp,
}
/*
* Build NVME LS request
* Build NVME LS request.
*
* pt_ls4_request_ext overlays pt_ls4_request through exchange_address
* (offsets 0-27 are byte-identical), so the common-header writes go
* through one struct pt_ls4_request * view. The ext layout has a wider
* __le16 vp_index and places rx_/tx_byte_count and dsd[] at different
* offsets, so those assignments diverge per stride.
*/
static void
qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt)
qla_nvme_ls(srb_t *sp, void *cmd_pkt)
{
struct srb_iocb *nvme;
struct srb_iocb *nvme = &sp->u.iocb_cmd;
struct qla_hw_data *ha = sp->vha->hw;
struct pt_ls4_request *pkt = cmd_pkt;
nvme = &sp->u.iocb_cmd;
cmd_pkt->entry_type = PT_LS4_REQUEST;
cmd_pkt->entry_count = 1;
cmd_pkt->timeout = cpu_to_le16(nvme->u.nvme.timeout_sec);
cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
pkt->entry_type = PT_LS4_REQUEST;
pkt->entry_count = 1;
pkt->timeout = cpu_to_le16(nvme->u.nvme.timeout_sec);
pkt->tx_dseg_count = cpu_to_le16(1);
if (sp->unsol_rsp) {
cmd_pkt->control_flags =
cpu_to_le16(CF_LS4_RESPONDER << CF_LS4_SHIFT);
cmd_pkt->nport_handle = nvme->u.nvme.nport_handle;
cmd_pkt->exchange_address = nvme->u.nvme.exchange_address;
pkt->control_flags =
cpu_to_le16(CF_LS4_RESPONDER << CF_LS4_SHIFT);
pkt->nport_handle = nvme->u.nvme.nport_handle;
pkt->exchange_address = nvme->u.nvme.exchange_address;
} else {
cmd_pkt->control_flags =
cpu_to_le16(CF_LS4_ORIGINATOR << CF_LS4_SHIFT);
cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
cmd_pkt->rx_dseg_count = cpu_to_le16(1);
cmd_pkt->rx_byte_count = nvme->u.nvme.rsp_len;
cmd_pkt->dsd[1].length = nvme->u.nvme.rsp_len;
put_unaligned_le64(nvme->u.nvme.rsp_dma, &cmd_pkt->dsd[1].address);
pkt->control_flags =
cpu_to_le16(CF_LS4_ORIGINATOR << CF_LS4_SHIFT);
pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
pkt->rx_dseg_count = cpu_to_le16(1);
}
cmd_pkt->tx_dseg_count = cpu_to_le16(1);
cmd_pkt->tx_byte_count = nvme->u.nvme.cmd_len;
cmd_pkt->dsd[0].length = nvme->u.nvme.cmd_len;
put_unaligned_le64(nvme->u.nvme.cmd_dma, &cmd_pkt->dsd[0].address);
if (IS_QLA29XX(ha)) {
struct pt_ls4_request_ext *ext = cmd_pkt;
ext->vp_index = cpu_to_le16(sp->fcport->vha->vp_idx);
ext->tx_byte_count = nvme->u.nvme.cmd_len;
ext->dsd[0].length = nvme->u.nvme.cmd_len;
put_unaligned_le64(nvme->u.nvme.cmd_dma,
&ext->dsd[0].address);
if (!sp->unsol_rsp) {
ext->rx_byte_count = nvme->u.nvme.rsp_len;
ext->dsd[1].length = nvme->u.nvme.rsp_len;
put_unaligned_le64(nvme->u.nvme.rsp_dma,
&ext->dsd[1].address);
}
} else {
pkt->vp_index = sp->fcport->vha->vp_idx;
pkt->tx_byte_count = nvme->u.nvme.cmd_len;
pkt->dsd[0].length = nvme->u.nvme.cmd_len;
put_unaligned_le64(nvme->u.nvme.cmd_dma,
&pkt->dsd[0].address);
if (!sp->unsol_rsp) {
pkt->rx_byte_count = nvme->u.nvme.rsp_len;
pkt->dsd[1].length = nvme->u.nvme.rsp_len;
put_unaligned_le64(nvme->u.nvme.rsp_dma,
&pkt->dsd[1].address);
}
}
}
static void
+5 -4
View File
@@ -4058,7 +4058,7 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
}
void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
struct pt_ls4_request *pkt, struct req_que *req)
void *pkt, struct req_que *req)
{
srb_t *sp;
const char func[] = "LS4_IOCB";
@@ -4068,7 +4068,9 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
if (!sp)
return;
comp_status = le16_to_cpu(pkt->status);
/* status lives at the same offset (8) in both IOCB strides */
comp_status = le16_to_cpu(((struct pt_ls4_request *)pkt)->status);
sp->done(sp, comp_status);
}
@@ -4236,8 +4238,7 @@ process_err:
qlt_response_pkt_all_vps(vha, rsp, (response_t *)pkt);
break;
case PT_LS4_REQUEST:
qla24xx_nvme_ls4_iocb(vha, (struct pt_ls4_request *)pkt,
rsp->req);
qla24xx_nvme_ls4_iocb(vha, pkt, rsp->req);
break;
case NOTIFY_ACK_TYPE:
if (((response_t *)pkt)->handle == QLA_TGT_SKIP_HANDLE)
+39 -19
View File
@@ -1132,37 +1132,57 @@ static void qla_nvme_fc_format_rjt(void *buf, u8 ls_cmd, u8 reason,
rjt->rjt.vendor = vendor;
}
/*
* pt_ls4_request_ext overlays pt_ls4_request through exchange_address
* (offsets 0-27 are byte-identical), so the common-header writes go
* through one struct pt_ls4_request * view. The ext layout has a wider
* __le16 vp_index and places tx_/rx_byte_count and dsd[] at different
* offsets, so those assignments diverge per stride.
*/
static void qla_nvme_lsrjt_pt_iocb(struct scsi_qla_host *vha,
struct pt_ls4_request *lsrjt_iocb,
void *lsrjt_iocb,
struct qla_nvme_lsrjt_pt_arg *a)
{
lsrjt_iocb->entry_type = PT_LS4_REQUEST;
lsrjt_iocb->entry_count = 1;
lsrjt_iocb->sys_define = 0;
lsrjt_iocb->entry_status = 0;
lsrjt_iocb->handle = QLA_SKIP_HANDLE;
lsrjt_iocb->nport_handle = a->nport_handle;
lsrjt_iocb->exchange_address = a->xchg_address;
lsrjt_iocb->vp_index = a->vp_idx;
struct qla_hw_data *ha = vha->hw;
struct pt_ls4_request *pkt = lsrjt_iocb;
lsrjt_iocb->control_flags = cpu_to_le16(a->control_flags);
pkt->entry_type = PT_LS4_REQUEST;
pkt->entry_count = 1;
pkt->sys_define = 0;
pkt->entry_status = 0;
pkt->handle = QLA_SKIP_HANDLE;
pkt->nport_handle = a->nport_handle;
pkt->exchange_address = a->xchg_address;
pkt->control_flags = cpu_to_le16(a->control_flags);
pkt->tx_dseg_count = cpu_to_le16(1);
pkt->rx_dseg_count = 0;
put_unaligned_le64(a->tx_addr, &lsrjt_iocb->dsd[0].address);
lsrjt_iocb->dsd[0].length = cpu_to_le32(a->tx_byte_count);
lsrjt_iocb->tx_dseg_count = cpu_to_le16(1);
lsrjt_iocb->tx_byte_count = cpu_to_le32(a->tx_byte_count);
if (IS_QLA29XX(ha)) {
struct pt_ls4_request_ext *ext = lsrjt_iocb;
put_unaligned_le64(a->rx_addr, &lsrjt_iocb->dsd[1].address);
lsrjt_iocb->dsd[1].length = 0;
lsrjt_iocb->rx_dseg_count = 0;
lsrjt_iocb->rx_byte_count = 0;
ext->vp_index = cpu_to_le16(a->vp_idx);
ext->tx_byte_count = cpu_to_le32(a->tx_byte_count);
ext->rx_byte_count = 0;
put_unaligned_le64(a->tx_addr, &ext->dsd[0].address);
ext->dsd[0].length = cpu_to_le32(a->tx_byte_count);
put_unaligned_le64(a->rx_addr, &ext->dsd[1].address);
ext->dsd[1].length = 0;
} else {
pkt->vp_index = a->vp_idx;
pkt->tx_byte_count = cpu_to_le32(a->tx_byte_count);
pkt->rx_byte_count = 0;
put_unaligned_le64(a->tx_addr, &pkt->dsd[0].address);
pkt->dsd[0].length = cpu_to_le32(a->tx_byte_count);
put_unaligned_le64(a->rx_addr, &pkt->dsd[1].address);
pkt->dsd[1].length = 0;
}
}
static int
qla_nvme_ls_reject_iocb(struct scsi_qla_host *vha, struct qla_qpair *qp,
struct qla_nvme_lsrjt_pt_arg *a, bool is_xchg_terminate)
{
struct pt_ls4_request *lsrjt_iocb;
void *lsrjt_iocb;
lsrjt_iocb = __qla2x00_alloc_iocbs(qp, NULL);
if (!lsrjt_iocb) {
+2 -2
View File
@@ -169,7 +169,7 @@ static inline void qla_nvme_delete(struct scsi_qla_host *vha)
}
#endif
void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *, struct pt_ls4_request *,
struct req_que *);
void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha, void *pkt,
struct req_que *req);
void qla24xx_async_gffid_sp_done(struct srb *sp, int);
#endif
+1
View File
@@ -8655,6 +8655,7 @@ qla2x00_module_init(void)
BUILD_BUG_ON(sizeof(struct nvram_24xx) != 512);
BUILD_BUG_ON(sizeof(struct nvram_81xx) != 512);
BUILD_BUG_ON(sizeof(struct pt_ls4_request) != 64);
BUILD_BUG_ON(sizeof(struct pt_ls4_request_ext) != 128);
BUILD_BUG_ON(sizeof(struct pt_ls4_rx_unsol) != 64);
BUILD_BUG_ON(sizeof(struct purex_entry_24xx) != 64);
BUILD_BUG_ON(sizeof(struct purex_entry_24xx_ext) != 128);