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: Enhance purex_entry handling for 29xx series
Update function signatures and internal logic across qla_edif.c, qla_isr.c, and qla_os.c to accept a generic pointer for packet data and differentiate between standard purex_entry_24xx and the extended purex_entry_24xx_ext structures based on IS_QLA29XX(). This ensures proper initialization and processing of command and response data for both 64-byte and 128-byte PUREX IOCBs across all ELS paths including auth_els, RDP, copy_std_pkt, copy_multiple_pkt, consume_iocb, and copy_purex_to_buffer. Where the two layouts overlap at byte-identical offsets (entry_count, frame_size, nport_handle, rx_xchg_addr, ox_id, status_flags, trunc_frame_size, s_id, d_id, els_frame_payload base, and response_t::signature), use a single struct purex_entry_24xx * view to avoid duplicating read paths. Branch only where field encoding differs: vp_idx (u8 at offset 6 in 24xx vs __le16 at offsets 6-7 in 29xx) and els_frame_payload[] array length (20 vs 84 bytes, handled via a sizeof_field()-based payload_size local). Signed-off-by: Nilesh Javali <njavali@marvell.com> Reviewed-by: Hannes Reinecke <hare@kernel.org> Link: https://patch.msgid.link/20260723050413.3897522-29-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
c454800348
commit
7db93e3c58
@@ -5001,6 +5001,7 @@ struct active_regions {
|
||||
#define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */
|
||||
|
||||
#define QLA_DEFAULT_PAYLOAD_SIZE 64
|
||||
#define QLA_MAX_IOCB_SIZE 128
|
||||
/*
|
||||
* This item might be allocated with a size > sizeof(struct purex_item).
|
||||
* The "size" variable gives the size of the payload (which
|
||||
@@ -5015,7 +5016,7 @@ struct purex_item {
|
||||
atomic_t in_use;
|
||||
uint16_t size;
|
||||
struct {
|
||||
uint8_t iocb[64];
|
||||
u8 iocb[QLA_MAX_IOCB_SIZE];
|
||||
} iocb;
|
||||
};
|
||||
|
||||
|
||||
@@ -2534,7 +2534,7 @@ qla24xx_sa_replace_iocb(srb_t *sp, struct sa_update_28xx *sa_update_iocb)
|
||||
|
||||
void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
|
||||
{
|
||||
struct purex_entry_24xx *p = *pkt;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct enode *ptr;
|
||||
int sid;
|
||||
u16 totlen;
|
||||
@@ -2544,26 +2544,55 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
|
||||
struct fc_port *fcport;
|
||||
struct qla_els_pt_arg a;
|
||||
be_id_t beid;
|
||||
__le16 nport_handle;
|
||||
__le32 rx_xchg_addr;
|
||||
__le16 ox_id;
|
||||
__le16 frame_size, status_flags, trunc_frame_size;
|
||||
uint8_t s_id[3], d_id[3];
|
||||
uint8_t vp_idx;
|
||||
struct purex_entry_24xx *p = *pkt;
|
||||
|
||||
memset(&a, 0, sizeof(a));
|
||||
|
||||
/*
|
||||
* purex_entry_24xx_ext (29xx) overlays purex_entry_24xx for every
|
||||
* field touched here -- nport_handle, rx_xchg_addr, ox_id, frame_size,
|
||||
* status_flags, trunc_frame_size, s_id[3], d_id[3] -- with only
|
||||
* vp_idx differing in width (u8 at offset 6 vs __le16 at offsets 6-7,
|
||||
* with reserved2 at offset 7 in the 24xx layout). So all reads but
|
||||
* vp_idx go through a single struct purex_entry_24xx * view.
|
||||
*/
|
||||
nport_handle = p->nport_handle;
|
||||
rx_xchg_addr = p->rx_xchg_addr;
|
||||
ox_id = p->ox_id;
|
||||
frame_size = p->frame_size;
|
||||
status_flags = p->status_flags;
|
||||
trunc_frame_size = p->trunc_frame_size;
|
||||
memcpy(s_id, p->s_id, sizeof(s_id));
|
||||
memcpy(d_id, p->d_id, sizeof(d_id));
|
||||
if (IS_QLA29XX(ha))
|
||||
vp_idx = le16_to_cpu(((struct purex_entry_24xx_ext *)
|
||||
*pkt)->vp_idx);
|
||||
else
|
||||
vp_idx = p->vp_idx;
|
||||
|
||||
a.els_opcode = ELS_AUTH_ELS;
|
||||
a.nport_handle = p->nport_handle;
|
||||
a.rx_xchg_address = p->rx_xchg_addr;
|
||||
a.did.b.domain = p->s_id[2];
|
||||
a.did.b.area = p->s_id[1];
|
||||
a.did.b.al_pa = p->s_id[0];
|
||||
a.nport_handle = nport_handle;
|
||||
a.rx_xchg_address = rx_xchg_addr;
|
||||
a.did.b.domain = s_id[2];
|
||||
a.did.b.area = s_id[1];
|
||||
a.did.b.al_pa = s_id[0];
|
||||
a.tx_byte_count = a.tx_len = sizeof(struct fc_els_ls_rjt);
|
||||
a.tx_addr = vha->hw->elsrej.cdma;
|
||||
a.tx_addr = ha->elsrej.cdma;
|
||||
a.vp_idx = vha->vp_idx;
|
||||
a.control_flags = EPD_ELS_RJT;
|
||||
a.ox_id = le16_to_cpu(p->ox_id);
|
||||
a.ox_id = le16_to_cpu(ox_id);
|
||||
|
||||
sid = p->s_id[0] | (p->s_id[1] << 8) | (p->s_id[2] << 16);
|
||||
sid = s_id[0] | (s_id[1] << 8) | (s_id[2] << 16);
|
||||
|
||||
totlen = (le16_to_cpu(p->frame_size) & 0x0fff) - PURX_ELS_HEADER_SIZE;
|
||||
if (le16_to_cpu(p->status_flags) & 0x8000) {
|
||||
totlen = le16_to_cpu(p->trunc_frame_size);
|
||||
totlen = (le16_to_cpu(frame_size) & 0x0fff) - PURX_ELS_HEADER_SIZE;
|
||||
if (le16_to_cpu(status_flags) & 0x8000) {
|
||||
totlen = le16_to_cpu(trunc_frame_size);
|
||||
qla_els_reject_iocb(vha, (*rsp)->qpair, &a);
|
||||
__qla_consume_iocb(vha, pkt, rsp);
|
||||
return;
|
||||
@@ -2600,12 +2629,12 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
|
||||
purex = &ptr->u.purexinfo;
|
||||
purex->pur_info.pur_sid = a.did;
|
||||
purex->pur_info.pur_bytes_rcvd = totlen;
|
||||
purex->pur_info.pur_rx_xchg_address = le32_to_cpu(p->rx_xchg_addr);
|
||||
purex->pur_info.pur_nphdl = le16_to_cpu(p->nport_handle);
|
||||
purex->pur_info.pur_did.b.domain = p->d_id[2];
|
||||
purex->pur_info.pur_did.b.area = p->d_id[1];
|
||||
purex->pur_info.pur_did.b.al_pa = p->d_id[0];
|
||||
purex->pur_info.vp_idx = p->vp_idx;
|
||||
purex->pur_info.pur_rx_xchg_address = le32_to_cpu(rx_xchg_addr);
|
||||
purex->pur_info.pur_nphdl = le16_to_cpu(nport_handle);
|
||||
purex->pur_info.pur_did.b.domain = d_id[2];
|
||||
purex->pur_info.pur_did.b.area = d_id[1];
|
||||
purex->pur_info.pur_did.b.al_pa = d_id[0];
|
||||
purex->pur_info.vp_idx = vp_idx;
|
||||
|
||||
a.sid = purex->pur_info.pur_did;
|
||||
|
||||
|
||||
@@ -202,6 +202,11 @@ void __qla_consume_iocb(struct scsi_qla_host *vha,
|
||||
struct rsp_que *rsp_q = *rsp;
|
||||
response_t *new_pkt;
|
||||
uint16_t entry_count_remaining;
|
||||
/*
|
||||
* entry_count is u8 at offset 1 in both purex_entry_24xx and
|
||||
* purex_entry_24xx_ext, so the 24xx view is layout-compatible with
|
||||
* either stride.
|
||||
*/
|
||||
struct purex_entry_24xx *purex = *pkt;
|
||||
|
||||
entry_count_remaining = purex->entry_count;
|
||||
@@ -230,6 +235,14 @@ void __qla_consume_iocb(struct scsi_qla_host *vha,
|
||||
int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
|
||||
void **pkt, struct rsp_que **rsp, u8 *buf, u32 buf_len)
|
||||
{
|
||||
/*
|
||||
* purex_entry_24xx_ext overlays purex_entry_24xx for entry_count
|
||||
* (offset 1), frame_size (offset 12) and els_frame_payload (offset
|
||||
* 44, base address only -- the array size grows from 20 to 84
|
||||
* bytes). Header fields are read through the 24xx view; the
|
||||
* initial payload memcpy uses a purex_entry_24xx_ext pointer on
|
||||
* 29xx so that FORTIFY_SOURCE sees the correct 84-byte source.
|
||||
*/
|
||||
struct purex_entry_24xx *purex = *pkt;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct rsp_que *rsp_q = *rsp;
|
||||
@@ -244,8 +257,8 @@ int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
|
||||
u16 tpad;
|
||||
|
||||
entry_count_remaining = purex->entry_count;
|
||||
total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
|
||||
- PURX_ELS_HEADER_SIZE;
|
||||
total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF) -
|
||||
PURX_ELS_HEADER_SIZE;
|
||||
|
||||
/*
|
||||
* end of payload may not end in 4bytes boundary. Need to
|
||||
@@ -262,14 +275,24 @@ int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha,
|
||||
}
|
||||
|
||||
pending_bytes = total_bytes = tpad;
|
||||
no_bytes = (pending_bytes > sizeof(purex->els_frame_payload)) ?
|
||||
sizeof(purex->els_frame_payload) : pending_bytes;
|
||||
no_bytes = (pending_bytes > payload_size) ?
|
||||
payload_size : pending_bytes;
|
||||
if (IS_QLA29XX(ha)) {
|
||||
struct purex_entry_24xx_ext *purex_ext = *pkt;
|
||||
|
||||
memcpy(buf, &purex->els_frame_payload[0], no_bytes);
|
||||
memcpy(buf, &purex_ext->els_frame_payload[0], no_bytes);
|
||||
} else {
|
||||
memcpy(buf, &purex->els_frame_payload[0], no_bytes);
|
||||
}
|
||||
buffer_copy_offset += no_bytes;
|
||||
pending_bytes -= no_bytes;
|
||||
--entry_count_remaining;
|
||||
|
||||
/*
|
||||
* response_t::signature and struct response_ext::signature are both u32
|
||||
* at offset 60 (handle:4 + data[52]:60), so the 24xx view writes
|
||||
* the right slot regardless of stride.
|
||||
*/
|
||||
((response_t *)purex)->signature = RESPONSE_PROCESSED;
|
||||
/* flush signature */
|
||||
wmb();
|
||||
@@ -849,6 +872,7 @@ qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt,
|
||||
struct rsp_que **rsp, bool is_purls,
|
||||
bool byte_order)
|
||||
{
|
||||
struct purex_entry_24xx_ext *purex_ext = NULL;
|
||||
struct purex_entry_24xx *purex = NULL;
|
||||
struct pt_ls4_rx_unsol *purls = NULL;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
@@ -867,6 +891,13 @@ qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt,
|
||||
PURX_ELS_HEADER_SIZE;
|
||||
entry_count = entry_count_remaining = purls->entry_count;
|
||||
payload_size = sizeof(purls->payload);
|
||||
} else if (IS_QLA29XX(ha)) {
|
||||
purex_ext = *pkt;
|
||||
total_bytes = (le16_to_cpu(purex_ext->frame_size) & 0x0FFF) -
|
||||
PURX_ELS_HEADER_SIZE;
|
||||
entry_count = entry_count_remaining =
|
||||
purex_ext->entry_count;
|
||||
payload_size = sizeof(purex_ext->els_frame_payload);
|
||||
} else {
|
||||
purex = *pkt;
|
||||
total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF) -
|
||||
@@ -875,8 +906,8 @@ qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt,
|
||||
payload_size = sizeof(purex->els_frame_payload);
|
||||
}
|
||||
|
||||
if (total_bytes > sizeof(item->iocb.iocb))
|
||||
total_bytes = sizeof(item->iocb.iocb);
|
||||
if (total_bytes > QLA_MAX_IOCB_SIZE)
|
||||
total_bytes = QLA_MAX_IOCB_SIZE;
|
||||
|
||||
pending_bytes = total_bytes;
|
||||
no_bytes = (pending_bytes > payload_size) ? payload_size :
|
||||
@@ -893,6 +924,8 @@ qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt,
|
||||
|
||||
if (is_purls)
|
||||
memcpy(iocb_pkt, &purls->payload[0], no_bytes);
|
||||
else if (IS_QLA29XX(ha))
|
||||
memcpy(iocb_pkt, &purex_ext->els_frame_payload[0], no_bytes);
|
||||
else
|
||||
memcpy(iocb_pkt, &purex->els_frame_payload[0], no_bytes);
|
||||
buffer_copy_offset += no_bytes;
|
||||
@@ -901,6 +934,8 @@ qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt,
|
||||
|
||||
if (is_purls)
|
||||
((response_t *)purls)->signature = RESPONSE_PROCESSED;
|
||||
else if (IS_QLA29XX(ha))
|
||||
((struct response_ext *)purex_ext)->signature = RESPONSE_PROCESSED;
|
||||
else
|
||||
((response_t *)purex)->signature = RESPONSE_PROCESSED;
|
||||
wmb();
|
||||
@@ -1075,9 +1110,9 @@ qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size)
|
||||
struct purex_item *item = NULL;
|
||||
uint8_t item_hdr_size = sizeof(*item);
|
||||
|
||||
if (size > QLA_DEFAULT_PAYLOAD_SIZE) {
|
||||
if (size > QLA_MAX_IOCB_SIZE) {
|
||||
item = kzalloc(item_hdr_size +
|
||||
(size - QLA_DEFAULT_PAYLOAD_SIZE), GFP_ATOMIC);
|
||||
(size - QLA_MAX_IOCB_SIZE), GFP_ATOMIC);
|
||||
} else {
|
||||
if (atomic_inc_return(&vha->default_item.in_use) == 1) {
|
||||
item = &vha->default_item;
|
||||
@@ -1126,14 +1161,20 @@ qla24xx_queue_purex_item(scsi_qla_host_t *vha, struct purex_item *pkt,
|
||||
static struct purex_item
|
||||
*qla24xx_copy_std_pkt(struct scsi_qla_host *vha, void *pkt)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct purex_item *item;
|
||||
u16 copy_sz;
|
||||
|
||||
item = qla24xx_alloc_purex_item(vha,
|
||||
QLA_DEFAULT_PAYLOAD_SIZE);
|
||||
if (IS_QLA29XX(ha))
|
||||
copy_sz = sizeof(struct purex_entry_24xx_ext);
|
||||
else
|
||||
copy_sz = QLA_DEFAULT_PAYLOAD_SIZE;
|
||||
|
||||
item = qla24xx_alloc_purex_item(vha, copy_sz);
|
||||
if (!item)
|
||||
return item;
|
||||
|
||||
memcpy(&item->iocb, pkt, sizeof(item->iocb));
|
||||
memcpy(&item->iocb, pkt, copy_sz);
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -1165,8 +1206,8 @@ qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, void **pkt,
|
||||
total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
|
||||
- PURX_ELS_HEADER_SIZE;
|
||||
|
||||
if (total_bytes > sizeof(item->iocb.iocb))
|
||||
total_bytes = sizeof(item->iocb.iocb);
|
||||
if (total_bytes > QLA_MAX_IOCB_SIZE)
|
||||
total_bytes = QLA_MAX_IOCB_SIZE;
|
||||
|
||||
pending_bytes = total_bytes;
|
||||
entry_count = entry_count_remaining = purex->entry_count;
|
||||
@@ -3996,6 +4037,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
{
|
||||
void *pkt;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct purex_entry_24xx_ext *purex_entry_ext;
|
||||
struct purex_entry_24xx *purex_entry;
|
||||
struct purex_item *pure_item;
|
||||
struct pt_ls4_rx_unsol *p;
|
||||
@@ -4113,8 +4155,16 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
(struct vp_ctrl_entry_24xx *)pkt);
|
||||
break;
|
||||
case PUREX_IOCB_TYPE:
|
||||
purex_entry = (void *)pkt;
|
||||
switch (purex_entry->els_frame_payload[3]) {
|
||||
if (IS_QLA29XX(ha)) {
|
||||
purex_entry_ext = (void *)pkt;
|
||||
purex_entry = NULL;
|
||||
} else {
|
||||
purex_entry = (void *)pkt;
|
||||
purex_entry_ext = NULL;
|
||||
}
|
||||
switch (IS_QLA29XX(ha) ?
|
||||
purex_entry_ext->els_frame_payload[3] :
|
||||
purex_entry->els_frame_payload[3]) {
|
||||
case ELS_RDP:
|
||||
pure_item = qla24xx_copy_std_pkt(vha, pkt);
|
||||
if (!pure_item)
|
||||
@@ -4151,6 +4201,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
|
||||
ql_dbg(ql_dbg_init, vha, 0x5091,
|
||||
"Defer processing ELS opcode %#x...\n",
|
||||
IS_QLA29XX(ha) ?
|
||||
purex_entry_ext->els_frame_payload[3] :
|
||||
purex_entry->els_frame_payload[3]);
|
||||
return;
|
||||
}
|
||||
@@ -4158,7 +4210,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||
break;
|
||||
default:
|
||||
ql_log(ql_log_warn, vha, 0x509c,
|
||||
"Discarding ELS Request opcode 0x%x\n",
|
||||
"Discarding ELS Request opcode 0x%x...\n",
|
||||
IS_QLA29XX(ha) ?
|
||||
purex_entry_ext->els_frame_payload[3] :
|
||||
purex_entry->els_frame_payload[3]);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -6138,13 +6138,15 @@ qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id)
|
||||
}
|
||||
|
||||
static bool
|
||||
qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha,
|
||||
struct purex_entry_24xx *purex)
|
||||
qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, void *pkt)
|
||||
{
|
||||
struct purex_entry_24xx *purex = pkt;
|
||||
char fwstr[16];
|
||||
u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0];
|
||||
u32 sid;
|
||||
struct port_database_24xx *pdb;
|
||||
|
||||
sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0];
|
||||
|
||||
/* Domain Controller is always logged-out. */
|
||||
/* if RDP request is not from Domain Controller: */
|
||||
if (sid != 0xfffc01)
|
||||
@@ -6209,15 +6211,26 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
|
||||
uint8_t *sfp = NULL;
|
||||
uint16_t sfp_flags = 0;
|
||||
uint rsp_payload_length = sizeof(*rsp_payload);
|
||||
uint8_t vp_idx;
|
||||
size_t purex_sz;
|
||||
int rval;
|
||||
|
||||
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180,
|
||||
"%s: Enter\n", __func__);
|
||||
|
||||
if (IS_QLA29XX(ha)) {
|
||||
vp_idx = le16_to_cpu(
|
||||
((struct purex_entry_24xx_ext *)purex)->vp_idx);
|
||||
purex_sz = sizeof(struct purex_entry_24xx_ext);
|
||||
} else {
|
||||
vp_idx = purex->vp_idx;
|
||||
purex_sz = sizeof(*purex);
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0181,
|
||||
"-------- ELS REQ -------\n");
|
||||
ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182,
|
||||
purex, sizeof(*purex));
|
||||
purex, purex_sz);
|
||||
|
||||
if (qla25xx_rdp_rsp_reduce_size(vha, purex)) {
|
||||
rsp_payload_length =
|
||||
@@ -6257,7 +6270,7 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
|
||||
rsp_els->handle = 0;
|
||||
rsp_els->nport_handle = purex->nport_handle;
|
||||
rsp_els->tx_dsd_count = cpu_to_le16(1);
|
||||
rsp_els->vp_index = purex->vp_idx;
|
||||
rsp_els->vp_index = vp_idx;
|
||||
rsp_els->sof_type = EST_SOFI3;
|
||||
rsp_els->rx_xchg_address = purex->rx_xchg_addr;
|
||||
rsp_els->rx_dsd_count = 0;
|
||||
@@ -8378,6 +8391,7 @@ qla2x00_module_init(void)
|
||||
BUILD_BUG_ON(sizeof(struct pt_ls4_request) != 64);
|
||||
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);
|
||||
BUILD_BUG_ON(sizeof(struct qla2100_fw_dump) != 123634);
|
||||
BUILD_BUG_ON(sizeof(struct qla2300_fw_dump) != 136100);
|
||||
BUILD_BUG_ON(sizeof(struct qla24xx_fw_dump) != 37976);
|
||||
|
||||
Reference in New Issue
Block a user