!(~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)
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))
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;
ql_log(ql_log_info, vha, 0x009a, "Need firmware flash update.\n");
ha->flags.running_gold_fw = 1;
+
+exit_load_risc:
return rval;
}
} rom_cmds[] = {
{ MBC_LOAD_RAM },
{ MBC_EXECUTE_FIRMWARE },
+ { MBC_LOAD_FLASH_FIRMWARE },
{ MBC_READ_RAM_WORD },
{ MBC_MAILBOX_REGISTER_TEST },
{ MBC_VERIFY_CHECKSUM },
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