qla2x00t-32gbit: Add load flash firmware mailbox support for 28xxx

For 28xxx adaptor Load flash firmware mailbox load the operational
firmware from flash, and also validate the checksum. Driver does not
need to load the operational firmware anymore, but it still need to read
fwdt from flash to build and allocate firmware dump template.  Remove
request_firmware() support for 28xxx adapter.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202512031128.XsuvzBv1-lkp@intel.com/
Signed-off-by: Manish Rangankar <mrangankar@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reviewed-by: Himanshu Madhani <hmadhani2024@gmail.com>
Link: https://patch.msgid.link/20251210101604.431868-4-njavali@marvell.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
[ commit b99b04b12214 upstream ]
This commit is contained in:
Gleb Chesnokov
2026-04-09 19:34:19 +03:00
parent e1a2b866d3
commit 6ac5456d9d
4 changed files with 236 additions and 4 deletions

View File

@@ -1330,6 +1330,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
*/
#define MBC_LOAD_RAM 1 /* Load RAM. */
#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware. */
#define MBC_LOAD_FLASH_FIRMWARE 3 /* Load flash firmware. */
#define MBC_READ_RAM_WORD 5 /* Read RAM word. */
#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */
#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum. */

View File

@@ -350,6 +350,9 @@ qla2x00_dump_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
extern int
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
extern int
qla28xx_load_flash_firmware(scsi_qla_host_t *vha);
extern int
qla2x00_get_fw_version(scsi_qla_host_t *);

View File

@@ -8461,6 +8461,148 @@ bool qla24xx_risc_firmware_invalid(uint32_t *dword)
!(~dword[4] | ~dword[5] | ~dword[6] | ~dword[7]);
}
static int
qla28xx_get_srisc_addr(scsi_qla_host_t *vha, uint32_t *srisc_addr,
uint32_t faddr)
{
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
uint32_t *dcode;
int rval;
*srisc_addr = 0;
dcode = (uint32_t *)req->ring;
rval = qla24xx_read_flash_data(vha, dcode, faddr, 10);
if (rval) {
ql_log(ql_log_fatal, vha, 0x01aa,
"-> Failed to read flash addr + size .\n");
return QLA_FUNCTION_FAILED;
}
*srisc_addr = be32_to_cpu((__force __be32)dcode[2]);
return QLA_SUCCESS;
}
static int
qla28xx_load_fw_template(scsi_qla_host_t *vha, uint32_t faddr)
{
struct qla_hw_data *ha = vha->hw;
struct fwdt *fwdt = ha->fwdt;
struct req_que *req = ha->req_q_map[0];
uint32_t risc_size, risc_attr = 0;
uint templates, segments, fragment;
uint32_t *dcode;
ulong dlen;
int rval;
uint j;
dcode = (uint32_t *)req->ring;
segments = FA_RISC_CODE_SEGMENTS;
for (j = 0; j < segments; j++) {
rval = qla24xx_read_flash_data(vha, dcode, faddr, 10);
if (rval) {
ql_log(ql_log_fatal, vha, 0x01a1,
"-> Failed to read flash addr + size .\n");
return QLA_FUNCTION_FAILED;
}
risc_size = be32_to_cpu((__force __be32)dcode[3]);
if (risc_attr == 0)
risc_attr = be32_to_cpu((__force __be32)dcode[9]);
dlen = ha->fw_transfer_size >> 2;
for (fragment = 0; fragment < risc_size; fragment++) {
if (dlen > risc_size)
dlen = risc_size;
faddr += dlen;
risc_size -= dlen;
}
}
templates = (risc_attr & BIT_9) ? 2 : 1;
ql_dbg(ql_dbg_init, vha, 0x01a1, "-> templates = %u\n", templates);
for (j = 0; j < templates; j++, fwdt++) {
vfree(fwdt->template);
fwdt->template = NULL;
fwdt->length = 0;
dcode = (uint32_t *)req->ring;
rval = qla24xx_read_flash_data(vha, dcode, faddr, 7);
if (rval) {
ql_log(ql_log_fatal, vha, 0x01a2,
"-> Unable to read template size.\n");
goto failed;
}
risc_size = be32_to_cpu((__force __be32)dcode[2]);
ql_dbg(ql_dbg_init, vha, 0x01a3,
"-> fwdt%u template array at %#x (%#x dwords)\n",
j, faddr, risc_size);
if (!risc_size || !~risc_size) {
ql_dbg(ql_dbg_init, vha, 0x01a4,
"-> fwdt%u failed to read array\n", j);
goto failed;
}
/* skip header and ignore checksum */
faddr += 7;
risc_size -= 8;
ql_dbg(ql_dbg_init, vha, 0x01a5,
"-> fwdt%u template allocate template %#x words...\n",
j, risc_size);
fwdt->template = vmalloc(risc_size * sizeof(*dcode));
if (!fwdt->template) {
ql_log(ql_log_warn, vha, 0x01a6,
"-> fwdt%u failed allocate template.\n", j);
goto failed;
}
dcode = fwdt->template;
rval = qla24xx_read_flash_data(vha, dcode, faddr, risc_size);
if (rval || !qla27xx_fwdt_template_valid(dcode)) {
ql_log(ql_log_warn, vha, 0x01a7,
"-> fwdt%u failed template validate (rval %x)\n",
j, rval);
goto failed;
}
dlen = qla27xx_fwdt_template_size(dcode);
ql_dbg(ql_dbg_init, vha, 0x01a7,
"-> fwdt%u template size %#lx bytes (%#lx words)\n",
j, dlen, dlen / sizeof(*dcode));
if (dlen > risc_size * sizeof(*dcode)) {
ql_log(ql_log_warn, vha, 0x01a8,
"-> fwdt%u template exceeds array (%-lu bytes)\n",
j, dlen - risc_size * sizeof(*dcode));
goto failed;
}
fwdt->length = dlen;
ql_dbg(ql_dbg_init, vha, 0x01a9,
"-> fwdt%u loaded template ok\n", j);
faddr += risc_size + 1;
}
return QLA_SUCCESS;
failed:
vfree(fwdt->template);
fwdt->template = NULL;
fwdt->length = 0;
return QLA_SUCCESS;
}
static int
qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
uint32_t faddr)
@@ -8900,16 +9042,18 @@ int
qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
uint32_t f_region = 0;
struct qla_hw_data *ha = vha->hw;
struct active_regions active_regions = { };
if (ql2xfwloadbin == 2)
if (ql2xfwloadbin == 2 && !IS_QLA28XX(ha))
goto try_blob_fw;
/* FW Load priority:
* 1) Firmware residing in flash.
* 2) Firmware via request-firmware interface (.bin file).
* 3) Golden-Firmware residing in flash -- (limited operation).
* 1) If 28xxx, ROM cmd to load flash firmware.
* 2) Firmware residing in flash.
* 3) Firmware via request-firmware interface (.bin file).
* 4) Golden-Firmware residing in flash -- (limited operation).
*/
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
@@ -8917,6 +9061,40 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
qla27xx_get_active_image(vha, &active_regions);
/* For 28XXX, always load the flash firmware using rom mbx */
if (IS_QLA28XX(ha)) {
rval = qla28xx_load_flash_firmware(vha);
if (rval != QLA_SUCCESS) {
ql_log(ql_log_fatal, vha, 0x019e,
"Failed to load flash firmware.\n");
goto exit_load_risc;
}
f_region =
(active_regions.global != QLA27XX_SECONDARY_IMAGE) ?
ha->flt_region_fw : ha->flt_region_fw_sec;
ql_log(ql_log_info, vha, 0x019f,
"Load flash firmware successful (%s).\n",
((active_regions.global != QLA27XX_SECONDARY_IMAGE) ?
"Primary" : "Secondary"));
rval = qla28xx_get_srisc_addr(vha, srisc_addr, f_region);
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x019f,
"failed to read srisc address\n");
goto exit_load_risc;
}
rval = qla28xx_load_fw_template(vha, f_region);
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x01a0,
"failed to read firmware template\n");
}
goto exit_load_risc;
}
if (active_regions.global != QLA27XX_SECONDARY_IMAGE)
goto try_primary_fw;
@@ -8946,6 +9124,8 @@ try_blob_fw:
ql_log(ql_log_info, vha, 0x009a, "Need firmware flash update.\n");
ha->flags.running_gold_fw = 1;
exit_load_risc:
return rval;
}

View File

@@ -43,6 +43,7 @@ static struct rom_cmd {
} rom_cmds[] = {
{ MBC_LOAD_RAM },
{ MBC_EXECUTE_FIRMWARE },
{ MBC_LOAD_FLASH_FIRMWARE },
{ MBC_READ_RAM_WORD },
{ MBC_MAILBOX_REGISTER_TEST },
{ MBC_VERIFY_CHECKSUM },
@@ -824,6 +825,53 @@ done:
return rval;
}
/*
* qla2x00_load_flash_firmware
* Load firmware from flash.
*
* Input:
* vha = adapter block pointer.
*
* Returns:
* qla28xx local function return status code.
*
* Context:
* Kernel context.
*/
int
qla28xx_load_flash_firmware(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
int rval = QLA_COMMAND_ERROR;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
if (!IS_QLA28XX(ha))
return rval;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x11a6,
"Entered %s.\n", __func__);
mcp->mb[0] = MBC_LOAD_FLASH_FIRMWARE;
mcp->out_mb = MBX_2 | MBX_1 | MBX_0;
mcp->in_mb = MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_log_info, vha, 0x11a7,
"Failed=%x cmd error=%x img error=%x.\n",
rval, mcp->mb[1], mcp->mb[2]);
} else {
ql_dbg(ql_log_info, vha, 0x11a8,
"Done %s.\n", __func__);
}
return rval;
}
/*
* qla_get_exlogin_status
* Get extended login status