static int qla2x00_restart_isp(scsi_qla_host_t *);
-static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);
-
/****************************************************************************/
/* QLogic ISP2x00 Hardware Support Functions. */
/****************************************************************************/
ha->isp_ops.nvram_config(ha);
- if (ha->flags.disable_serdes) {
- /* Mask HBA via NVRAM settings? */
- qla_printk(KERN_INFO, ha, "Masking HBA WWPN "
- "%02x%02x%02x%02x%02x%02x%02x%02x (via NVRAM).\n",
- ha->port_name[0], ha->port_name[1],
- ha->port_name[2], ha->port_name[3],
- ha->port_name[4], ha->port_name[5],
- ha->port_name[6], ha->port_name[7]);
- return QLA_FUNCTION_FAILED;
- }
-
qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
retry = 10;
mwi = 0;
if (pci_set_mwi(ha->pdev))
mwi = PCI_COMMAND_INVALIDATE;
+ pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision);
pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
mwi = 0;
if (pci_set_mwi(ha->pdev))
mwi = PCI_COMMAND_INVALIDATE;
+ pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision);
pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
mwi = 0;
if (pci_set_mwi(ha->pdev))
mwi = PCI_COMMAND_INVALIDATE;
+ pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision);
pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n");
/* Verify checksum of loaded RISC code. */
- rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address);
+ rval = qla2x00_verify_checksum(ha,
+ IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS :
+ *ha->brd_info->fw_info[0].fwstart);
}
if (rval) {
unsigned long flags = 0;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t cnt;
+ unsigned long mbx_flags = 0;
uint16_t cmd;
ha->isp_ops.disable_intrs(ha);
if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
for (cnt = 0; cnt < 30000; cnt++) {
- if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY)
+ if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)))
+ spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
+
+ if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) {
+ if (!(test_bit(ABORT_ISP_ACTIVE,
+ &ha->dpc_flags)))
+ spin_unlock_irqrestore(
+ &ha->mbx_reg_lock, mbx_flags);
break;
+ }
+
+ if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)))
+ spin_unlock_irqrestore(&ha->mbx_reg_lock,
+ mbx_flags);
udelay(100);
}
DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n",
ha->host_no));
- ha->device_type |= DT_ISP2200A;
ha->fw_transfer_size = 128;
}
return rval;
}
-void
+static void
qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
{
- int rval;
- uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
- eft_size;
- dma_addr_t eft_dma;
- void *eft;
-
- if (ha->fw_dump) {
- qla_printk(KERN_WARNING, ha,
- "Firmware dump previously allocated.\n");
- return;
- }
-
ha->fw_dumped = 0;
- fixed_size = mem_size = eft_size = 0;
- if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
- fixed_size = sizeof(struct qla2100_fw_dump);
- } else if (IS_QLA23XX(ha)) {
- fixed_size = offsetof(struct qla2300_fw_dump, data_ram);
- mem_size = (ha->fw_memory_size - 0x11000 + 1) *
- sizeof(uint16_t);
- } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
- fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
- mem_size = (ha->fw_memory_size - 0x100000 + 1) *
- sizeof(uint32_t);
-
- /* Allocate memory for Extended Trace Buffer. */
- eft = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &eft_dma,
- GFP_KERNEL);
- if (!eft) {
- qla_printk(KERN_WARNING, ha, "Unable to allocate "
- "(%d KB) for EFT.\n", EFT_SIZE / 1024);
- goto cont_alloc;
- }
-
- rval = qla2x00_trace_control(ha, TC_ENABLE, eft_dma,
- EFT_NUM_BUFFERS);
- if (rval) {
- qla_printk(KERN_WARNING, ha, "Unable to initialize "
- "EFT (%d).\n", rval);
- dma_free_coherent(&ha->pdev->dev, EFT_SIZE, eft,
- eft_dma);
- goto cont_alloc;
- }
-
- qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
- EFT_SIZE / 1024);
-
- eft_size = EFT_SIZE;
- memset(eft, 0, eft_size);
- ha->eft_dma = eft_dma;
- ha->eft = eft;
- }
-cont_alloc:
- req_q_size = ha->request_q_length * sizeof(request_t);
- rsp_q_size = ha->response_q_length * sizeof(response_t);
-
- dump_size = offsetof(struct qla2xxx_fw_dump, isp);
- dump_size += fixed_size + mem_size + req_q_size + rsp_q_size +
- eft_size;
-
- ha->fw_dump = vmalloc(dump_size);
- if (!ha->fw_dump) {
+ ha->fw_dump24_len = sizeof(struct qla24xx_fw_dump);
+ ha->fw_dump24_len += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t);
+ ha->fw_dump24 = vmalloc(ha->fw_dump24_len);
+ if (ha->fw_dump24)
+ qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware "
+ "dump...\n", ha->fw_dump24_len / 1024);
+ else
qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
- "firmware dump!!!\n", dump_size / 1024);
-
- if (ha->eft) {
- dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft,
- ha->eft_dma);
- ha->eft = NULL;
- ha->eft_dma = 0;
- }
- return;
- }
-
- qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n",
- dump_size / 1024);
-
- ha->fw_dump_len = dump_size;
- ha->fw_dump->signature[0] = 'Q';
- ha->fw_dump->signature[1] = 'L';
- ha->fw_dump->signature[2] = 'G';
- ha->fw_dump->signature[3] = 'C';
- ha->fw_dump->version = __constant_htonl(1);
-
- ha->fw_dump->fixed_size = htonl(fixed_size);
- ha->fw_dump->mem_size = htonl(mem_size);
- ha->fw_dump->req_q_size = htonl(req_q_size);
- ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
-
- ha->fw_dump->eft_size = htonl(eft_size);
- ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
- ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
-
- ha->fw_dump->header_size =
- htonl(offsetof(struct qla2xxx_fw_dump, isp));
+ "firmware dump!!!\n", ha->fw_dump24_len / 1024);
}
/**
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return;
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
+ qla2x00_alloc_fw_dump(ha);
+
/* Retrieve IOCB counts available to the firmware. */
rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt);
if (rval)
&ha->fw_subminor_version,
&ha->fw_attributes, &ha->fw_memory_size);
qla2x00_resize_request_q(ha);
-
- if (ql2xallocfwdump)
- qla2x00_alloc_fw_dump(ha);
}
} else {
DEBUG2(printk(KERN_INFO
if (ha->flags.enable_led_scheme)
ha->fw_options[2] |= BIT_12;
- /* Detect ISP6312. */
- if (IS_QLA6312(ha))
- ha->fw_options[2] |= BIT_13;
-
/* Update firmware options. */
qla2x00_set_fw_options(ha, ha->fw_options);
}
rval = QLA_FUNCTION_FAILED;
if (atomic_read(&ha->loop_down_timer) &&
- fw_state != FSTATE_READY) {
+ (fw_state >= FSTATE_LOSS_OF_SYNC ||
+ fw_state == FSTATE_WAIT_AL_PA)) {
/* Loop down. Timeout on min_wait for states
* other than Wait for Login.
*/
index = (ha->pdev->subsystem_device & 0xff);
if (index < QLA_MODEL_NAMES) {
strcpy(ha->model_number,
- qla2x00_model_name[index * 2]);
+ qla2x00_model_name[index]);
ha->model_desc =
- qla2x00_model_name[index * 2 + 1];
+ qla2x00_model_desc[index];
} else {
strcpy(ha->model_number, "QLA23xx");
}
while (cnt--)
*dptr1++ = *dptr2++;
- /* Use alternate WWN? */
- if (nv->host_p[1] & BIT_7) {
- memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
- memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
- }
-
/* Prepare nodename */
if ((icb->firmware_options[1] & BIT_6) == 0) {
/*
/*
* Set host adapter parameters.
*/
- if (nv->host_p[0] & BIT_7)
- extended_error_logging = 1;
ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0);
/* Always load RISC code on non ISP2[12]00 chips. */
if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0);
ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0);
ha->flags.enable_led_scheme = (nv->special_options[1] & BIT_4) ? 1 : 0;
- ha->flags.disable_serdes = 0;
ha->operating_mode =
(icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4;
~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) {
- ha->zio_mode = QLA_ZIO_MODE_6;
-
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
"delay (%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100));
return (rval);
}
+static void
+qla2x00_rport_add(void *data)
+{
+ fc_port_t *fcport = data;
+
+ qla2x00_reg_remote_port(fcport->ha, fcport);
+}
+
static void
qla2x00_rport_del(void *data)
{
*
* Returns a pointer to the allocated fcport, or NULL, if none available.
*/
-static fc_port_t *
+fc_port_t *
qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
{
fc_port_t *fcport;
fcport->ha = ha;
fcport->port_type = FCT_UNKNOWN;
fcport->loop_id = FC_NO_LOOP_ID;
+ fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
fcport->supported_classes = FC_COS_UNSPECIFIED;
spin_lock_init(&fcport->rport_lock);
+ INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
+ INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
return (fcport);
}
set_bit(RSCN_UPDATE, &flags);
clear_bit(LOCAL_LOOP_UPDATE, &flags);
- } else if (ha->current_topology == ISP_CFG_N) {
- clear_bit(RSCN_UPDATE, &flags);
-
} else if (!ha->flags.online ||
(test_bit(ABORT_ISP_ACTIVE, &flags))) {
PORT_RETRY_TIME);
fcport->flags &= ~FCF_LOGIN_NEEDED;
+ if (fcport->port_type == FCT_INITIATOR ||
+ fcport->port_type == FCT_BROADCAST)
+ fcport->device_type = TYPE_PROCESSOR;
+
atomic_set(&fcport->state, FCS_ONLINE);
if (ha->flags.init_done)
LIST_HEAD(new_fcports);
/* If FL port exists, then SNS is present */
- if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
loop_id = NPH_F_PORT;
else
loop_id = SNS_FL_PORT;
qla2x00_fdmi_register(ha);
/* Ensure we are logged into the SNS. */
- if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+ if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
loop_id = NPH_SNS;
else
loop_id = SIMPLE_NAME_SERVER;
}
/* Remove device from the new list and add it to DB */
- list_move_tail(&fcport->list, &ha->fcports);
+ list_del(&fcport->list);
+ list_add_tail(&fcport->list, &ha->fcports);
/* Login and update database */
qla2x00_fabric_dev_login(ha, fcport, &next_loopid);
* Context:
* Kernel context.
*/
-static int
+int
qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev)
{
int rval;
qla2x00_device_resync(scsi_qla_host_t *ha)
{
int rval;
+ int rval2;
uint32_t mask;
fc_port_t *fcport;
uint32_t rscn_entry;
switch (format) {
case 0:
+ if (ql2xprocessrscn &&
+ !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
+ !IS_QLA6312(ha) && !IS_QLA6322(ha) &&
+ !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
+ ha->flags.init_done) {
+ /* Handle port RSCN via asyncronous IOCBs */
+ rval2 = qla2x00_handle_port_rscn(ha, rscn_entry,
+ NULL, 0);
+ if (rval2 == QLA_SUCCESS)
+ continue;
+ }
mask = 0xffffff;
break;
case 1:
rval = QLA_SUCCESS;
+ /* Abort any outstanding IO descriptors. */
+ if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
+ qla2x00_cancel_io_descriptors(ha);
+
list_for_each_entry(fcport, &ha->fcports, list) {
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
(fcport->d_id.b24 & mask) != d_id.b24 ||
* 3 - Fatal error
*/
int
-qla2x00_local_device_login(scsi_qla_host_t *ha, fc_port_t *fcport)
+qla2x00_local_device_login(scsi_qla_host_t *ha, uint16_t loop_id)
{
int rval;
uint16_t mb[MAILBOX_REGISTER_COUNT];
memset(mb, 0, sizeof(mb));
- rval = qla2x00_login_local_device(ha, fcport, mb, BIT_0);
+ rval = qla2x00_login_local_device(ha, loop_id, mb, BIT_0);
if (rval == QLA_SUCCESS) {
/* Interrogate mailbox registers for any errors */
if (mb[0] == MBS_COMMAND_ERROR)
int
qla2x00_abort_isp(scsi_qla_host_t *ha)
{
- int rval;
unsigned long flags = 0;
uint16_t cnt;
srb_t *sp;
ha->isp_abort_cnt = 0;
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
-
- if (ha->eft) {
- rval = qla2x00_trace_control(ha, TC_ENABLE,
- ha->eft_dma, EFT_NUM_BUFFERS);
- if (rval) {
- qla_printk(KERN_WARNING, ha,
- "Unable to reinitialize EFT "
- "(%d).\n", rval);
- }
- }
} else { /* failed the ISP abort */
ha->flags.online = 1;
if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
ha->isp_abort_cnt--;
DEBUG(printk("qla%ld: ISP abort - "
"retry remaining %d\n",
- ha->host_no, ha->isp_abort_cnt));
+ ha->host_no, ha->isp_abort_cnt);)
status = 1;
}
} else {
ha->isp_abort_cnt = MAX_RETRIES_OF_ISP_ABORT;
DEBUG(printk("qla2x00(%ld): ISP error recovery "
"- retrying (%d) more times\n",
- ha->host_no, ha->isp_abort_cnt));
+ ha->host_no, ha->isp_abort_cnt);)
set_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
status = 1;
}
} else {
DEBUG(printk(KERN_INFO
"qla2x00_abort_isp(%ld): exiting.\n",
- ha->host_no));
+ ha->host_no);)
}
return(status);
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
+ if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) {
/*
* Disable SRAM, Instruction RAM and GP RAM
* parity.
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) {
+ if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) {
/* Enable proper parity */
if (IS_QLA2300(ha))
/* SRAM parity */
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
if (!(status = qla2x00_fw_ready(ha))) {
DEBUG(printk("%s(): Start configure loop, "
- "status = %d\n", __func__, status));
+ "status = %d\n", __func__, status);)
/* Issue a marker after FW becomes ready. */
qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
DEBUG(printk("%s(): Configure loop done, status = 0x%x\n",
__func__,
- status));
+ status);)
}
return (status);
}
/* Determine NVRAM starting address. */
ha->nvram_size = sizeof(struct nvram_24xx);
ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
- ha->vpd_size = FA_NVRAM_VPD_SIZE;
- ha->vpd_base = FA_NVRAM_VPD0_ADDR;
- if (PCI_FUNC(ha->pdev->devfn)) {
+ if (PCI_FUNC(ha->pdev->devfn))
ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
- ha->vpd_base = FA_NVRAM_VPD1_ADDR;
- }
/* Get NVRAM data and calculate checksum. */
dptr = (uint32_t *)nv;
nv->node_name[6] = 0x55;
nv->node_name[7] = 0x86;
nv->login_retry_count = __constant_cpu_to_le16(8);
+ nv->link_down_timeout = __constant_cpu_to_le16(200);
nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
nv->login_timeout = __constant_cpu_to_le16(0);
nv->firmware_options_1 =
*dptr1++ = *dptr2++;
icb->login_retry_count = nv->login_retry_count;
- icb->link_down_on_nos = nv->link_down_on_nos;
+ icb->link_down_timeout = nv->link_down_timeout;
/* Copy 2nd segment. */
dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
index = (ha->pdev->subsystem_device & 0xff);
if (index < QLA_MODEL_NAMES)
- ha->model_desc = qla2x00_model_name[index * 2 + 1];
+ ha->model_desc = qla2x00_model_desc[index];
} else
strcpy(ha->model_number, "QLA2462");
- /* Use alternate WWN? */
- if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
- memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
- memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
- }
-
/* Prepare nodename */
- if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) {
+ if ((icb->firmware_options_1 & BIT_14) == 0) {
/*
* Firmware will apply the following mask if the nodename was
* not provided.
ha->flags.enable_lip_full_login = 1;
ha->flags.enable_target_reset = 1;
ha->flags.enable_led_scheme = 0;
- ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
- ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
- (BIT_6 | BIT_5 | BIT_4)) >> 4;
+ ha->operating_mode =
+ (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4;
memcpy(ha->fw_seriallink_options24, nv->seriallink_options,
sizeof(ha->fw_seriallink_options24));
~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
ha->flags.process_response_queue = 0;
if (ha->zio_mode != QLA_ZIO_DISABLED) {
- ha->zio_mode = QLA_ZIO_MODE_6;
-
DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
"(%d us).\n", ha->host_no, ha->zio_mode,
ha->zio_timer * 100));
return (rval);
}
-static int
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+
+int
+qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+ int rval, num, i;
+ uint32_t cnt;
+ uint16_t *risc_code;
+ uint32_t risc_addr, risc_size;
+ uint16_t *req_ring;
+ struct qla_fw_info *fw_iter;
+
+ rval = QLA_SUCCESS;
+
+ /* Load firmware sequences */
+ fw_iter = ha->brd_info->fw_info;
+ *srisc_addr = *ha->brd_info->fw_info->fwstart;
+ while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
+ risc_code = fw_iter->fwcode;
+ risc_size = *fw_iter->fwlen;
+ if (fw_iter->addressing == FW_INFO_ADDR_NORMAL)
+ risc_addr = *fw_iter->fwstart;
+ else
+ risc_addr = *fw_iter->lfwstart;
+
+ num = 0;
+ rval = 0;
+ while (risc_size > 0 && !rval) {
+ cnt = (uint16_t)(ha->fw_transfer_size >> 1);
+ if (cnt > risc_size)
+ cnt = risc_size;
+
+ DEBUG7(printk("scsi(%ld): Loading risc segment@ "
+ "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
+ ha->host_no, risc_code, cnt, risc_addr));
+
+ req_ring = (uint16_t *)ha->request_ring;
+ for (i = 0; i < cnt; i++)
+ req_ring[i] = cpu_to_le16(risc_code[i]);
+
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ cnt);
+ if (rval) {
+ DEBUG(printk("scsi(%ld): [ERROR] Failed to "
+ "load segment %d of firmware\n",
+ ha->host_no, num));
+ qla_printk(KERN_WARNING, ha,
+ "[ERROR] Failed to load segment %d of "
+ "firmware\n", num);
+
+ qla2x00_dump_regs(ha);
+ break;
+ }
+
+ risc_code += cnt;
+ risc_addr += cnt;
+ risc_size -= cnt;
+ num++;
+ }
+
+ /* Next firmware sequence */
+ fw_iter++;
+ }
+ return rval;
+}
+
+int
+qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+ int rval, num, i;
+ uint32_t cnt;
+ uint32_t *risc_code;
+ uint32_t risc_addr, risc_size;
+ uint32_t *req_ring;
+ struct qla_fw_info *fw_iter;
+
+ rval = QLA_SUCCESS;
+
+ /* Load firmware sequences */
+ fw_iter = ha->brd_info->fw_info;
+ *srisc_addr = *((uint32_t *)fw_iter->lfwstart);
+ while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
+ risc_code = (uint32_t *)fw_iter->fwcode;
+ risc_size = *((uint32_t *)fw_iter->fwlen);
+ risc_addr = *((uint32_t *)fw_iter->lfwstart);
+
+ num = 0;
+ rval = 0;
+ while (risc_size > 0 && !rval) {
+ cnt = (uint32_t)(ha->fw_transfer_size >> 2);
+ if (cnt > risc_size)
+ cnt = risc_size;
+
+ DEBUG7(printk("scsi(%ld): Loading risc segment@ "
+ "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
+ ha->host_no, risc_code, cnt, risc_addr));
+
+ req_ring = (uint32_t *)ha->request_ring;
+ for (i = 0; i < cnt; i++)
+ req_ring[i] = cpu_to_le32(risc_code[i]);
+
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ cnt);
+ if (rval) {
+ DEBUG(printk("scsi(%ld): [ERROR] Failed to "
+ "load segment %d of firmware\n",
+ ha->host_no, num));
+ qla_printk(KERN_WARNING, ha,
+ "[ERROR] Failed to load segment %d of "
+ "firmware\n", num);
+
+ qla2x00_dump_regs(ha);
+ break;
+ }
+
+ risc_code += cnt;
+ risc_addr += cnt;
+ risc_size -= cnt;
+ num++;
+ }
+
+ /* Next firmware sequence */
+ fw_iter++;
+ }
+ return rval;
+}
+
+int
qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
int rval;
return rval;
}
-#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"
+#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
int
qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
blob = qla2x00_request_firmware(ha);
if (!blob) {
qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
- qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
- "from: " QLA_FW_URL ".\n");
return QLA_FUNCTION_FAILED;
}
blob = qla2x00_request_firmware(ha);
if (!blob) {
qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
- qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
- "from: " QLA_FW_URL ".\n");
-
- /* Try to load RISC code from flash. */
- qla_printk(KERN_ERR, ha, "Attempting to load (potentially "
- "outdated) firmware from flash.\n");
- return qla24xx_load_risc_flash(ha, srisc_addr);
+ return QLA_FUNCTION_FAILED;
}
rval = QLA_SUCCESS;
fail_fw_integrity:
return QLA_FUNCTION_FAILED;
}
+#endif