summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c300
1 files changed, 230 insertions, 70 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 72d9090df3d..a91fea69ad6 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
-#include <linux/firmware.h>
#include <scsi/scsi_transport_fc.h>
#include "qla_devtbl.h"
@@ -147,8 +146,8 @@ check_fw_ready_again:
* LIP to complete
*/
- if (atomic_read(&ha->loop_state) ==
- LOOP_DOWN && retry--) {
+ if (atomic_read(&ha->loop_state) !=
+ LOOP_READY && retry--) {
goto check_fw_ready_again;
}
wait_time--;
@@ -567,6 +566,7 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
uint32_t cnt, d2;
+ uint16_t wd;
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -581,10 +581,10 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
WRT_REG_DWORD(&reg->ctrl_status,
CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
- RD_REG_DWORD(&reg->ctrl_status);
+ pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
+ udelay(100);
/* Wait for firmware to complete NVRAM accesses. */
- udelay(5);
d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
for (cnt = 10000 ; cnt && d2; cnt--) {
udelay(5);
@@ -592,7 +592,7 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
barrier();
}
- udelay(20);
+ /* Wait for soft-reset to complete. */
d2 = RD_REG_DWORD(&reg->ctrl_status);
for (cnt = 6000000 ; cnt && (d2 & CSRX_ISP_SOFT_RESET); cnt--) {
udelay(5);
@@ -1014,11 +1014,13 @@ qla24xx_update_fw_options(scsi_qla_host_t *ha)
int rval;
/* Update Serial Link options. */
- if ((ha->fw_seriallink_options24[0] & BIT_0) == 0)
+ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
return;
- rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1],
- ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]);
+ rval = qla2x00_set_serdes_params(ha,
+ le16_to_cpu(ha->fw_seriallink_options24[1]),
+ le16_to_cpu(ha->fw_seriallink_options24[2]),
+ le16_to_cpu(ha->fw_seriallink_options24[3]));
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Unable to update Serial Link options (%x).\n", rval);
@@ -1258,9 +1260,15 @@ qla2x00_configure_hba(scsi_qla_host_t *ha)
rval = qla2x00_get_adapter_id(ha,
&loop_id, &al_pa, &area, &domain, &topo);
if (rval != QLA_SUCCESS) {
- qla_printk(KERN_WARNING, ha,
- "ERROR -- Unable to get host loop ID.\n");
- set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) ||
+ (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
+ DEBUG2(printk("%s(%ld) Loop is in a transition state\n",
+ __func__, ha->host_no));
+ } else {
+ qla_printk(KERN_WARNING, ha,
+ "ERROR -- Unable to get host loop ID.\n");
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ }
return (rval);
}
@@ -1789,7 +1797,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
}
if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
- if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
+ if (LOOP_TRANSITION(ha)) {
rval = QLA_FUNCTION_FAILED;
} else {
rval = qla2x00_configure_fabric(ha);
@@ -1933,6 +1941,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
"information -- get_port_database=%x, "
"loop_id=0x%04x\n",
ha->host_no, rval2, new_fcport->loop_id));
+ DEBUG2(printk("scsi(%ld): Scheduling resync...\n",
+ ha->host_no));
+ set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
continue;
}
@@ -2362,8 +2373,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
if (qla2x00_is_reserved_id(ha, loop_id))
continue;
- if (atomic_read(&ha->loop_down_timer) ||
- test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
+ if (atomic_read(&ha->loop_down_timer) || LOOP_TRANSITION(ha))
break;
if (swl != NULL) {
@@ -2643,7 +2653,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
switch (format) {
case 0:
- if (!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
+ if (ql2xprocessrscn &&
+ !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
!IS_QLA6312(ha) && !IS_QLA6322(ha) &&
!IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
ha->flags.init_done) {
@@ -3397,6 +3408,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
ha->node_name = icb->node_name;
ha->port_name = icb->port_name;
+ icb->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+
ha->retry_count = le16_to_cpu(nv->login_retry_count);
/* Set minimum login_timeout to 4 seconds. */
@@ -3478,17 +3491,16 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
return (rval);
}
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+
int
qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
- int rval;
- uint16_t cnt;
- uint16_t *risc_code;
- unsigned long risc_address;
- unsigned long risc_code_size;
- int num;
- int i;
- uint16_t *req_ring;
+ 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;
@@ -3498,37 +3510,29 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
*srisc_addr = *ha->brd_info->fw_info->fwstart;
while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
risc_code = fw_iter->fwcode;
- risc_code_size = *fw_iter->fwlen;
-
- if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {
- risc_address = *fw_iter->fwstart;
- } else {
- /* Extended address */
- risc_address = *fw_iter->lfwstart;
- }
+ 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_code_size > 0 && !rval) {
+ while (risc_size > 0 && !rval) {
cnt = (uint16_t)(ha->fw_transfer_size >> 1);
- if (cnt > risc_code_size)
- cnt = risc_code_size;
+ 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_address));
+ 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]);
- if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {
- rval = qla2x00_load_ram(ha, ha->request_dma,
- risc_address, cnt);
- } else {
- rval = qla2x00_load_ram_ext(ha,
- ha->request_dma, risc_address, cnt);
- }
+ 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",
@@ -3542,16 +3546,76 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
}
risc_code += cnt;
- risc_address += cnt;
- risc_code_size -= cnt;
+ risc_addr += cnt;
+ risc_size -= cnt;
num++;
}
/* Next firmware sequence */
fw_iter++;
}
+ return rval;
+}
- 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
@@ -3611,8 +3675,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
for (i = 0; i < dlen; i++)
dcode[i] = swab32(dcode[i]);
- rval = qla2x00_load_ram_ext(ha, ha->request_dma,
- risc_addr, dlen);
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
@@ -3636,8 +3700,108 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
return rval;
}
+#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+
int
-qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+ int rval;
+ int i, fragment;
+ uint16_t *wcode, *fwcode;
+ uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
+ struct fw_blob *blob;
+
+ /* Load firmware blob. */
+ blob = qla2x00_request_firmware(ha);
+ if (!blob) {
+ qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ rval = QLA_SUCCESS;
+
+ wcode = (uint16_t *)ha->request_ring;
+ *srisc_addr = 0;
+ fwcode = (uint16_t *)blob->fw->data;
+ fwclen = 0;
+
+ /* Validate firmware image by checking version. */
+ if (blob->fw->size < 8 * sizeof(uint16_t)) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to verify integrity of firmware image (%Zd)!\n",
+ blob->fw->size);
+ goto fail_fw_integrity;
+ }
+ for (i = 0; i < 4; i++)
+ wcode[i] = be16_to_cpu(fwcode[i + 4]);
+ if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
+ wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
+ wcode[2] == 0 && wcode[3] == 0)) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to verify integrity of firmware image!\n");
+ qla_printk(KERN_WARNING, ha,
+ "Firmware data: %04x %04x %04x %04x!\n", wcode[0],
+ wcode[1], wcode[2], wcode[3]);
+ goto fail_fw_integrity;
+ }
+
+ seg = blob->segs;
+ while (*seg && rval == QLA_SUCCESS) {
+ risc_addr = *seg;
+ *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr;
+ risc_size = be16_to_cpu(fwcode[3]);
+
+ /* Validate firmware image size. */
+ fwclen += risc_size * sizeof(uint16_t);
+ if (blob->fw->size < fwclen) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to verify integrity of firmware image "
+ "(%Zd)!\n", blob->fw->size);
+ goto fail_fw_integrity;
+ }
+
+ fragment = 0;
+ while (risc_size > 0 && rval == QLA_SUCCESS) {
+ wlen = (uint16_t)(ha->fw_transfer_size >> 1);
+ if (wlen > risc_size)
+ wlen = risc_size;
+
+ DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
+ "addr %x, number of words 0x%x.\n", ha->host_no,
+ risc_addr, wlen));
+
+ for (i = 0; i < wlen; i++)
+ wcode[i] = swab16(fwcode[i]);
+
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ wlen);
+ if (rval) {
+ DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
+ "segment %d of firmware\n", ha->host_no,
+ fragment));
+ qla_printk(KERN_WARNING, ha,
+ "[ERROR] Failed to load segment %d of "
+ "firmware\n", fragment);
+ break;
+ }
+
+ fwcode += wlen;
+ risc_addr += wlen;
+ risc_size -= wlen;
+ fragment++;
+ }
+
+ /* Next segment. */
+ seg++;
+ }
+ return rval;
+
+fail_fw_integrity:
+ return QLA_FUNCTION_FAILED;
+}
+
+int
+qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
int rval;
int segments, fragment;
@@ -3645,14 +3809,13 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
uint32_t risc_addr;
uint32_t risc_size;
uint32_t i;
- const struct firmware *fw_entry;
+ struct fw_blob *blob;
uint32_t *fwcode, fwclen;
- if (request_firmware(&fw_entry, ha->brd_info->fw_fname,
- &ha->pdev->dev)) {
- qla_printk(KERN_ERR, ha,
- "Firmware image file not available: '%s'\n",
- ha->brd_info->fw_fname);
+ /* Load firmware blob. */
+ blob = qla2x00_request_firmware(ha);
+ if (!blob) {
+ qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
return QLA_FUNCTION_FAILED;
}
@@ -3661,14 +3824,14 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
segments = FA_RISC_CODE_SEGMENTS;
dcode = (uint32_t *)ha->request_ring;
*srisc_addr = 0;
- fwcode = (uint32_t *)fw_entry->data;
+ fwcode = (uint32_t *)blob->fw->data;
fwclen = 0;
/* Validate firmware image by checking version. */
- if (fw_entry->size < 8 * sizeof(uint32_t)) {
+ if (blob->fw->size < 8 * sizeof(uint32_t)) {
qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of flash firmware image "
- "(%Zd)!\n", fw_entry->size);
+ "Unable to verify integrity of firmware image (%Zd)!\n",
+ blob->fw->size);
goto fail_fw_integrity;
}
for (i = 0; i < 4; i++)
@@ -3678,7 +3841,7 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of flash firmware image!\n");
+ "Unable to verify integrity of firmware image!\n");
qla_printk(KERN_WARNING, ha,
"Firmware data: %08x %08x %08x %08x!\n", dcode[0],
dcode[1], dcode[2], dcode[3]);
@@ -3692,10 +3855,11 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
/* Validate firmware image size. */
fwclen += risc_size * sizeof(uint32_t);
- if (fw_entry->size < fwclen) {
+ if (blob->fw->size < fwclen) {
qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of flash firmware "
- "image (%Zd)!\n", fw_entry->size);
+ "Unable to verify integrity of firmware image "
+ "(%Zd)!\n", blob->fw->size);
+
goto fail_fw_integrity;
}
@@ -3712,8 +3876,8 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
for (i = 0; i < dlen; i++)
dcode[i] = swab32(fwcode[i]);
- rval = qla2x00_load_ram_ext(ha, ha->request_dma,
- risc_addr, dlen);
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
@@ -3733,13 +3897,9 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
/* Next segment. */
segments--;
}
-
- release_firmware(fw_entry);
return rval;
fail_fw_integrity:
-
- release_firmware(fw_entry);
return QLA_FUNCTION_FAILED;
-
}
+#endif