mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
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:
@@ -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. */
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user