diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 08:19:33 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 08:19:33 -0700 |
commit | df3d80f5a5c74168be42788364d13cf6c83c7b9c (patch) | |
tree | 892a964c2fd28d028f2fb7471e8543d3f4006a58 /drivers/scsi/qla2xxx | |
parent | 3d06f7a5f74a813cee817c4b30b5e6f0398da0be (diff) | |
parent | c8e91b0a8fc8493e3bf3efcb3c8f866e9453cf1c (diff) | |
download | linux-df3d80f5a5c74168be42788364d13cf6c83c7b9c.tar.bz2 |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (207 commits)
[SCSI] gdth: fix CONFIG_ISA build failure
[SCSI] esp_scsi: remove __dev{init,exit}
[SCSI] gdth: !use_sg cleanup and use of scsi accessors
[SCSI] gdth: Move members from SCp to gdth_cmndinfo, stage 2
[SCSI] gdth: Setup proper per-command private data
[SCSI] gdth: Remove gdth_ctr_tab[]
[SCSI] gdth: switch to modern scsi host registration
[SCSI] gdth: gdth_interrupt() gdth_get_status() & gdth_wait() fixes
[SCSI] gdth: clean up host private data
[SCSI] gdth: Remove virt hosts
[SCSI] gdth: Reorder scsi_host_template intitializers
[SCSI] gdth: kill gdth_{read,write}[bwl] wrappers
[SCSI] gdth: Remove 2.4.x support, in-kernel changelog
[SCSI] gdth: split out pci probing
[SCSI] gdth: split out eisa probing
[SCSI] gdth: split out isa probing
gdth: Make one abuse of scsi_cmnd less obvious
[SCSI] NCR5380: Use scsi_eh API for REQUEST_SENSE invocation
[SCSI] usb storage: use scsi_eh API in REQUEST_SENSE execution
[SCSI] scsi_error: Refactoring scsi_error to facilitate in synchronous REQUEST_SENSE
...
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 200 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 1846 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 15 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 6 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 6 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 40 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 88 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 62 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 40 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 140 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 221 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 |
15 files changed, 1195 insertions, 1486 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 0f2a9f5d801c..05fa7796a559 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -18,7 +18,7 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); char *rbuf = (char *)ha->fw_dump; @@ -39,7 +39,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int reading; @@ -89,7 +89,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int size = ha->nvram_size; char *nvram_cache = ha->nvram; @@ -112,7 +112,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); unsigned long flags; uint16_t cnt; @@ -146,7 +146,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); - ha->isp_ops->read_nvram(ha, (uint8_t *)&ha->nvram, ha->nvram_base, + ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -170,15 +170,15 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SREADING) return 0; - if (off > ha->optrom_size) + if (off > ha->optrom_region_size) return 0; - if (off + count > ha->optrom_size) - count = ha->optrom_size - off; + if (off + count > ha->optrom_region_size) + count = ha->optrom_region_size - off; memcpy(buf, &ha->optrom_buffer[off], count); @@ -190,15 +190,15 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SWRITING) return -EINVAL; - if (off > ha->optrom_size) + if (off > ha->optrom_region_size) return -ERANGE; - if (off + count > ha->optrom_size) - count = ha->optrom_size - off; + if (off + count > ha->optrom_region_size) + count = ha->optrom_region_size - off; memcpy(&ha->optrom_buffer[off], buf, count); @@ -220,14 +220,18 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - int val; + uint32_t start = 0; + uint32_t size = ha->optrom_size; + int val, valid; if (off) return 0; - if (sscanf(buf, "%d", &val) != 1) + if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) + return -EINVAL; + if (start > ha->optrom_size) return -EINVAL; switch (val) { @@ -237,6 +241,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, break; ha->optrom_state = QLA_SWAITING; + + DEBUG2(qla_printk(KERN_INFO, ha, + "Freeing flash region allocation -- 0x%x bytes.\n", + ha->optrom_region_size)); + vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; break; @@ -244,44 +253,107 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, if (ha->optrom_state != QLA_SWAITING) break; + if (start & 0xfff) { + qla_printk(KERN_WARNING, ha, + "Invalid start region 0x%x/0x%x.\n", start, size); + return -EINVAL; + } + + ha->optrom_region_start = start; + ha->optrom_region_size = start + size > ha->optrom_size ? + ha->optrom_size - start : size; + ha->optrom_state = QLA_SREADING; - ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); + ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom retrieval " - "(%x).\n", ha->optrom_size); + "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return count; } - memset(ha->optrom_buffer, 0, ha->optrom_size); - ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0, - ha->optrom_size); + DEBUG2(qla_printk(KERN_INFO, ha, + "Reading flash region -- 0x%x/0x%x.\n", + ha->optrom_region_start, ha->optrom_region_size)); + + memset(ha->optrom_buffer, 0, ha->optrom_region_size); + ha->isp_ops->read_optrom(ha, ha->optrom_buffer, + ha->optrom_region_start, ha->optrom_region_size); break; case 2: if (ha->optrom_state != QLA_SWAITING) break; + /* + * We need to be more restrictive on which FLASH regions are + * allowed to be updated via user-space. Regions accessible + * via this method include: + * + * ISP21xx/ISP22xx/ISP23xx type boards: + * + * 0x000000 -> 0x020000 -- Boot code. + * + * ISP2322/ISP24xx type boards: + * + * 0x000000 -> 0x07ffff -- Boot code. + * 0x080000 -> 0x0fffff -- Firmware. + * + * ISP25xx type boards: + * + * 0x000000 -> 0x07ffff -- Boot code. + * 0x080000 -> 0x0fffff -- Firmware. + * 0x120000 -> 0x12ffff -- VPD and HBA parameters. + */ + valid = 0; + if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) + valid = 1; + else if (start == (FA_BOOT_CODE_ADDR*4) || + start == (FA_RISC_CODE_ADDR*4)) + valid = 1; + else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) + valid = 1; + if (!valid) { + qla_printk(KERN_WARNING, ha, + "Invalid start region 0x%x/0x%x.\n", start, size); + return -EINVAL; + } + + ha->optrom_region_start = start; + ha->optrom_region_size = start + size > ha->optrom_size ? + ha->optrom_size - start : size; + ha->optrom_state = QLA_SWRITING; - ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); + ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom update " - "(%x).\n", ha->optrom_size); + "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return count; } - memset(ha->optrom_buffer, 0, ha->optrom_size); + + DEBUG2(qla_printk(KERN_INFO, ha, + "Staging flash region write -- 0x%x/0x%x.\n", + ha->optrom_region_start, ha->optrom_region_size)); + + memset(ha->optrom_buffer, 0, ha->optrom_region_size); break; case 3: if (ha->optrom_state != QLA_SWRITING) break; - ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0, - ha->optrom_size); + DEBUG2(qla_printk(KERN_INFO, ha, + "Writing flash region -- 0x%x/0x%x.\n", + ha->optrom_region_start, ha->optrom_region_size)); + + ha->isp_ops->write_optrom(ha, ha->optrom_buffer, + ha->optrom_region_start, ha->optrom_region_size); break; + default: + count = -EINVAL; } return count; } @@ -300,7 +372,7 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int size = ha->vpd_size; char *vpd_cache = ha->vpd; @@ -323,7 +395,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); unsigned long flags; @@ -354,7 +426,7 @@ qla2x00_sysfs_read_sfp(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); uint16_t iter, addr, offset; int rval; @@ -459,7 +531,7 @@ qla2x00_drvr_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_fw_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); char fw_str[30]; return snprintf(buf, PAGE_SIZE, "%s\n", @@ -469,7 +541,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_serial_num_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); uint32_t sn; sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; @@ -480,14 +552,14 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_isp_name_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device); } static ssize_t qla2x00_isp_id_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", ha->product_id[0], ha->product_id[1], ha->product_id[2], ha->product_id[3]); @@ -496,14 +568,14 @@ qla2x00_isp_id_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_model_name_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number); } static ssize_t qla2x00_model_desc_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_desc ? ha->model_desc: ""); } @@ -511,7 +583,7 @@ qla2x00_model_desc_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_pci_info_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); char pci_info[30]; return snprintf(buf, PAGE_SIZE, "%s\n", @@ -521,7 +593,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_state_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int len = 0; if (atomic_read(&ha->loop_state) == LOOP_DOWN || @@ -559,7 +631,7 @@ qla2x00_state_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_zio_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int len = 0; switch (ha->zio_mode) { @@ -576,7 +648,7 @@ qla2x00_zio_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int val = 0; uint16_t zio_mode; @@ -602,7 +674,7 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count) static ssize_t qla2x00_zio_timer_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100); } @@ -611,7 +683,7 @@ static ssize_t qla2x00_zio_timer_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int val = 0; uint16_t zio_timer; @@ -629,7 +701,7 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf, static ssize_t qla2x00_beacon_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int len = 0; if (ha->beacon_blink_led) @@ -643,7 +715,7 @@ static ssize_t qla2x00_beacon_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int val = 0; int rval; @@ -673,7 +745,7 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, static ssize_t qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], ha->bios_revision[0]); @@ -682,7 +754,7 @@ qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], ha->efi_revision[0]); @@ -691,7 +763,7 @@ qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], ha->fcode_revision[0]); @@ -700,7 +772,7 @@ qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], @@ -757,7 +829,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = { static void qla2x00_get_host_port_id(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); fc_host_port_id(shost) = ha->d_id.b.domain << 16 | ha->d_id.b.area << 8 | ha->d_id.b.al_pa; @@ -766,7 +838,7 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost) static void qla2x00_get_host_speed(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); uint32_t speed = 0; switch (ha->link_data_rate) { @@ -786,7 +858,7 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) static void qla2x00_get_host_port_type(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); uint32_t port_type = FC_PORTTYPE_UNKNOWN; switch (ha->current_topology) { @@ -810,7 +882,7 @@ static void qla2x00_get_starget_node_name(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(starget->dev.parent); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); fc_port_t *fcport; u64 node_name = 0; @@ -828,7 +900,7 @@ static void qla2x00_get_starget_port_name(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(starget->dev.parent); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); fc_port_t *fcport; u64 port_name = 0; @@ -846,7 +918,7 @@ static void qla2x00_get_starget_port_id(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(starget->dev.parent); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); fc_port_t *fcport; uint32_t port_id = ~0U; @@ -865,7 +937,7 @@ static void qla2x00_get_rport_loss_tmo(struct fc_rport *rport) { struct Scsi_Host *host = rport_to_shost(rport); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); rport->dev_loss_tmo = ha->port_down_retry_count + 5; } @@ -874,7 +946,7 @@ static void qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { struct Scsi_Host *host = rport_to_shost(rport); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); if (timeout) ha->port_down_retry_count = timeout; @@ -887,7 +959,7 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) static int qla2x00_issue_lip(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); return 0; @@ -896,7 +968,7 @@ qla2x00_issue_lip(struct Scsi_Host *shost) static struct fc_host_statistics * qla2x00_get_fc_host_stats(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); int rval; uint16_t mb_stat[1]; link_stat_t stat_buf; @@ -934,7 +1006,7 @@ done: static void qla2x00_get_host_symbolic_name(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost)); } @@ -942,7 +1014,7 @@ qla2x00_get_host_symbolic_name(struct Scsi_Host *shost) static void qla2x00_set_host_system_hostname(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); } @@ -950,7 +1022,7 @@ qla2x00_set_host_system_hostname(struct Scsi_Host *shost) static void qla2x00_get_host_fabric_name(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); u64 node_name; if (ha->device_flags & SWITCH_FOUND) @@ -964,7 +1036,7 @@ qla2x00_get_host_fabric_name(struct Scsi_Host *shost) static void qla2x00_get_host_port_state(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); if (!ha->flags.online) fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; @@ -978,7 +1050,7 @@ static int qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) { int ret = 0; - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha; ret = qla24xx_vport_create_req_sanity_check(fc_vport); @@ -1047,7 +1119,7 @@ vport_create_failed_2: int qla24xx_vport_delete(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha = fc_vport->dd_data; qla24xx_disable_vp(vha); @@ -1178,6 +1250,6 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); fc_host_supported_classes(ha->host) = FC_COS_CLASS3; - fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC; + fc_host_max_npiv_vports(ha->host) = ha->max_npiv_vports;; fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count; } diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index c6680348b648..eaa04dabcdf6 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -38,7 +38,7 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr) } static int -qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, +qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, uint32_t cram_size, uint32_t *ext_mem, void **nxt) { int rval; @@ -152,6 +152,103 @@ qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, return rval; } +static uint32_t * +qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase, + uint32_t count, uint32_t *buf) +{ + uint32_t __iomem *dmp_reg; + + WRT_REG_DWORD(®->iobase_addr, iobase); + dmp_reg = ®->iobase_window; + while (count--) + *buf++ = htonl(RD_REG_DWORD(dmp_reg++)); + + return buf; +} + +static inline int +qla24xx_pause_risc(struct device_reg_24xx __iomem *reg) +{ + int rval = QLA_SUCCESS; + uint32_t cnt; + + if (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) + return rval; + + WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); + for (cnt = 30000; (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) + udelay(100); + else + rval = QLA_FUNCTION_TIMEOUT; + } + + return rval; +} + +static int +qla24xx_soft_reset(scsi_qla_host_t *ha) +{ + int rval = QLA_SUCCESS; + uint32_t cnt; + uint16_t mb0, wd; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + /* Reset RISC. */ + WRT_REG_DWORD(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0) + break; + + udelay(10); + } + + WRT_REG_DWORD(®->ctrl_status, + CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); + pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); + + udelay(100); + /* Wait for firmware to complete NVRAM accesses. */ + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); + for (cnt = 10000 ; cnt && mb0; cnt--) { + udelay(5); + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); + barrier(); + } + + /* Wait for soft-reset to complete. */ + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_DWORD(®->ctrl_status) & + CSRX_ISP_SOFT_RESET) == 0) + break; + + udelay(10); + } + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); + RD_REG_DWORD(®->hccr); /* PCI Posting. */ + + for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) + udelay(100); + else + rval = QLA_FUNCTION_TIMEOUT; + } + + return rval; +} + +static inline void +qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count, + uint16_t *buf) +{ + uint16_t __iomem *dmp_reg = ®->u.isp2300.fb_cmd; + + while (count--) + *buf++ = htons(RD_REG_WORD(dmp_reg++)); +} + /** * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. * @ha: HA context @@ -214,88 +311,61 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } if (rval == QLA_SUCCESS) { - dmp_reg = (uint16_t __iomem *)(reg + 0); + dmp_reg = ®->flash_address; for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); + dmp_reg = ®->u.isp2300.req_q_in; for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++) fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40); + dmp_reg = ®->u.isp2300.mailbox0; for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->ctrl_status, 0x40); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->resp_dma_reg) / 2; cnt++) - fw->resp_dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 32, fw->resp_dma_reg); WRT_REG_WORD(®->ctrl_status, 0x50); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) - fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 48, fw->dma_reg); WRT_REG_WORD(®->ctrl_status, 0x00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); + dmp_reg = ®->risc_hw; for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->pcr, 0x2000); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++) - fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); WRT_REG_WORD(®->pcr, 0x2200); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++) - fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); WRT_REG_WORD(®->pcr, 0x2400); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++) - fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); WRT_REG_WORD(®->pcr, 0x2600); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++) - fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); WRT_REG_WORD(®->pcr, 0x2800); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++) - fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); WRT_REG_WORD(®->pcr, 0x2A00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++) - fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); WRT_REG_WORD(®->pcr, 0x2C00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++) - fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); WRT_REG_WORD(®->pcr, 0x2E00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++) - fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); WRT_REG_WORD(®->ctrl_status, 0x10); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++) - fw->frame_buf_hdw_reg[cnt] = - htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg); WRT_REG_WORD(®->ctrl_status, 0x20); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++) - fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); WRT_REG_WORD(®->ctrl_status, 0x30); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++) - fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); /* Reset RISC. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); @@ -567,83 +637,59 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) rval = QLA_FUNCTION_TIMEOUT; } if (rval == QLA_SUCCESS) { - dmp_reg = (uint16_t __iomem *)(reg + 0); + dmp_reg = ®->flash_address; for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); + dmp_reg = ®->u.isp2100.mailbox0; for (cnt = 0; cnt < ha->mbx_count; cnt++) { - if (cnt == 8) { - dmp_reg = (uint16_t __iomem *) - ((uint8_t __iomem *)reg + 0xe0); - } + if (cnt == 8) + dmp_reg = ®->u_end.isp2200.mailbox8; + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); } - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x20); + dmp_reg = ®->u.isp2100.unused_2[0]; for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->ctrl_status, 0x00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); + dmp_reg = ®->risc_hw; for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->pcr, 0x2000); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++) - fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); WRT_REG_WORD(®->pcr, 0x2100); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++) - fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); WRT_REG_WORD(®->pcr, 0x2200); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++) - fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); WRT_REG_WORD(®->pcr, 0x2300); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++) - fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); WRT_REG_WORD(®->pcr, 0x2400); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++) - fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); WRT_REG_WORD(®->pcr, 0x2500); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++) - fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); WRT_REG_WORD(®->pcr, 0x2600); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++) - fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); WRT_REG_WORD(®->pcr, 0x2700); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++) - fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); WRT_REG_WORD(®->ctrl_status, 0x10); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++) - fw->frame_buf_hdw_reg[cnt] = - htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg); WRT_REG_WORD(®->ctrl_status, 0x20); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++) - fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); WRT_REG_WORD(®->ctrl_status, 0x30); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++) - fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); /* Reset the ISP. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); @@ -750,7 +796,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) int rval; uint32_t cnt; uint32_t risc_address; - uint16_t mb0, wd; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -782,547 +827,198 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) fw = &ha->fw_dump->isp.isp24; qla2xxx_prep_dump(ha, ha->fw_dump); - rval = QLA_SUCCESS; fw->host_status = htonl(RD_REG_DWORD(®->host_status)); /* Pause RISC. */ - if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | - HCCRX_CLR_HOST_INT); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); - for (cnt = 30000; - (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - } - - if (rval == QLA_SUCCESS) { - /* Host interface registers. */ - dmp_reg = (uint32_t __iomem *)(reg + 0); - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) - fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Disable interrupts. */ - WRT_REG_DWORD(®->ictrl, 0); - RD_REG_DWORD(®->ictrl); - - /* Shadow registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - RD_REG_DWORD(®->iobase_addr); - WRT_REG_DWORD(®->iobase_select, 0xB0000000); - fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0100000); - fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0200000); - fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0300000); - fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0400000); - fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0500000); - fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0600000); - fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - /* Mailbox registers. */ - mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) - fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); - - /* Transfer sequence registers. */ - iter_reg = fw->xseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xBF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++) - fw->xseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) - fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive sequence registers. */ - iter_reg = fw->rseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xFF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFD0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++) - fw->rseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) - fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) - fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Command DMA registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x7100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) - fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Queues. */ - iter_reg = fw->req0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7200); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->resp0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7300); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->req1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7400); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Transmit DMA registers. */ - iter_reg = fw->xmt0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7600); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7610); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7620); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7630); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt2_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7640); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7650); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt3_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7660); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7670); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt4_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7680); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7690); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x76A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) - fw->xmt_data_dma_reg[cnt] = - htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive DMA registers. */ - iter_reg = fw->rcvt0_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7700); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7710); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->rcvt1_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7720); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7730); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* RISC registers. */ - iter_reg = fw->risc_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0x0F00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Local memory controller registers. */ - iter_reg = fw->lmc_reg; - WRT_REG_DWORD(®->iobase_addr, 0x3000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Fibre Protocol Module registers. */ - iter_reg = fw->fpm_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x4000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4080); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4090); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Frame Buffer registers. */ - iter_reg = fw->fb_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x6000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6130); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6150); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6170); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6190); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x61B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Reset RISC. */ - WRT_REG_DWORD(®->ctrl_status, - CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_DMA_ACTIVE) == 0) - break; - - udelay(10); - } - - WRT_REG_DWORD(®->ctrl_status, - CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); - - udelay(100); - /* Wait for firmware to complete NVRAM accesses. */ - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - for (cnt = 10000 ; cnt && mb0; cnt--) { - udelay(5); - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - barrier(); - } - - /* Wait for soft-reset to complete. */ - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_ISP_SOFT_RESET) == 0) - break; - - udelay(10); - } - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - } - - for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - - if (rval == QLA_SUCCESS) - rval = qla2xxx_dump_memory(ha, fw->code_ram, - sizeof(fw->code_ram), fw->ext_mem, &nxt); - - if (rval == QLA_SUCCESS) { - nxt = qla2xxx_copy_queues(ha, nxt); - if (ha->eft) - memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); - } - + rval = qla24xx_pause_risc(reg); + if (rval != QLA_SUCCESS) + goto qla24xx_fw_dump_failed_0; + + /* Host interface registers. */ + dmp_reg = ®->flash_addr; + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Disable interrupts. */ + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); + + /* Shadow registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_select, 0xB0000000); + fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0100000); + fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0200000); + fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0300000); + fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0400000); + fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0500000); + fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0600000); + fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + /* Mailbox registers. */ + mbx_reg = ®->mailbox0; + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); + + /* Transfer sequence registers. */ + iter_reg = fw->xseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); + qla24xx_read_window(reg, 0xBF70, 16, iter_reg); + + qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg); + qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); + + /* Receive sequence registers. */ + iter_reg = fw->rseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); + qla24xx_read_window(reg, 0xFF70, 16, iter_reg); + + qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg); + qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); + qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); + + /* Command DMA registers. */ + qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); + + /* Queues. */ + iter_reg = fw->req0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->resp0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->req1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Transmit DMA registers. */ + iter_reg = fw->xmt0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); + qla24xx_read_window(reg, 0x7610, 16, iter_reg); + + iter_reg = fw->xmt1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); + qla24xx_read_window(reg, 0x7630, 16, iter_reg); + + iter_reg = fw->xmt2_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); + qla24xx_read_window(reg, 0x7650, 16, iter_reg); + + iter_reg = fw->xmt3_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); + qla24xx_read_window(reg, 0x7670, 16, iter_reg); + + iter_reg = fw->xmt4_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); + qla24xx_read_window(reg, 0x7690, 16, iter_reg); + + qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); + + /* Receive DMA registers. */ + iter_reg = fw->rcvt0_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); + qla24xx_read_window(reg, 0x7710, 16, iter_reg); + + iter_reg = fw->rcvt1_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); + qla24xx_read_window(reg, 0x7730, 16, iter_reg); + + /* RISC registers. */ + iter_reg = fw->risc_gp_reg; + iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); + qla24xx_read_window(reg, 0x0F70, 16, iter_reg); + + /* Local memory controller registers. */ + iter_reg = fw->lmc_reg; + iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); + qla24xx_read_window(reg, 0x3060, 16, iter_reg); + + /* Fibre Protocol Module registers. */ + iter_reg = fw->fpm_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); + qla24xx_read_window(reg, 0x40B0, 16, iter_reg); + + /* Frame Buffer registers. */ + iter_reg = fw->fb_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); + qla24xx_read_window(reg, 0x61B0, 16, iter_reg); + + rval = qla24xx_soft_reset(ha); + if (rval != QLA_SUCCESS) + goto qla24xx_fw_dump_failed_0; + + rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), + fw->ext_mem, &nxt); + if (rval != QLA_SUCCESS) + goto qla24xx_fw_dump_failed_0; + + nxt = qla2xxx_copy_queues(ha, nxt); + if (ha->eft) + memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); + +qla24xx_fw_dump_failed_0: if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); @@ -1346,7 +1042,6 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) int rval; uint32_t cnt; uint32_t risc_address; - uint16_t mb0, wd; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -1377,655 +1072,260 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } fw = &ha->fw_dump->isp.isp25; qla2xxx_prep_dump(ha, ha->fw_dump); + ha->fw_dump->version = __constant_htonl(2); - rval = QLA_SUCCESS; fw->host_status = htonl(RD_REG_DWORD(®->host_status)); /* Pause RISC. */ - if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | - HCCRX_CLR_HOST_INT); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); - for (cnt = 30000; - (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - } - - if (rval == QLA_SUCCESS) { - /* Host interface registers. */ - dmp_reg = (uint32_t __iomem *)(reg + 0); - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) - fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Disable interrupts. */ - WRT_REG_DWORD(®->ictrl, 0); - RD_REG_DWORD(®->ictrl); - - /* Shadow registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - RD_REG_DWORD(®->iobase_addr); - WRT_REG_DWORD(®->iobase_select, 0xB0000000); - fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0100000); - fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0200000); - fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0300000); - fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0400000); - fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0500000); - fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0600000); - fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0700000); - fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0800000); - fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0900000); - fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0A00000); - fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - /* RISC I/O register. */ - WRT_REG_DWORD(®->iobase_addr, 0x0010); - RD_REG_DWORD(®->iobase_addr); - fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); - - /* Mailbox registers. */ - mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) - fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); - - /* Transfer sequence registers. */ - iter_reg = fw->xseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xBF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xseq_0_reg; - WRT_REG_DWORD(®->iobase_addr, 0xBFC0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFD0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) - fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive sequence registers. */ - iter_reg = fw->rseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xFF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->rseq_0_reg; - WRT_REG_DWORD(®->iobase_addr, 0xFFC0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFD0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) - fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) - fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Auxiliary sequence registers. */ - iter_reg = fw->aseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xB000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->aseq_0_reg; - WRT_REG_DWORD(®->iobase_addr, 0xB0C0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB0D0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB0E0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->aseq_1_reg) / 4; cnt++) - fw->aseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB0F0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->aseq_2_reg) / 4; cnt++) - fw->aseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Command DMA registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x7100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) - fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Queues. */ - iter_reg = fw->req0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7200); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->resp0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7300); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->req1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7400); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Transmit DMA registers. */ - iter_reg = fw->xmt0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7600); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7610); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7620); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7630); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt2_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7640); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7650); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt3_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7660); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7670); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt4_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7680); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7690); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x76A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) - fw->xmt_data_dma_reg[cnt] = - htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive DMA registers. */ - iter_reg = fw->rcvt0_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7700); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7710); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->rcvt1_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7720); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7730); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* RISC registers. */ - iter_reg = fw->risc_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0x0F00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Local memory controller registers. */ - iter_reg = fw->lmc_reg; - WRT_REG_DWORD(®->iobase_addr, 0x3000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Fibre Protocol Module registers. */ - iter_reg = fw->fpm_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x4000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4080); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4090); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Frame Buffer registers. */ - iter_reg = fw->fb_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x6000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6130); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6150); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6170); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6190); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x61B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6F00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Reset RISC. */ - WRT_REG_DWORD(®->ctrl_status, - CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_DMA_ACTIVE) == 0) - break; - - udelay(10); - } - - WRT_REG_DWORD(®->ctrl_status, - CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); - - udelay(100); - /* Wait for firmware to complete NVRAM accesses. */ - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - for (cnt = 10000 ; cnt && mb0; cnt--) { - udelay(5); - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - barrier(); - } - - /* Wait for soft-reset to complete. */ - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_ISP_SOFT_RESET) == 0) - break; - - udelay(10); - } - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - } - - for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - - if (rval == QLA_SUCCESS) - rval = qla2xxx_dump_memory(ha, fw->code_ram, - sizeof(fw->code_ram), fw->ext_mem, &nxt); - - if (rval == QLA_SUCCESS) { - nxt = qla2xxx_copy_queues(ha, nxt); - if (ha->eft) - memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); - } - + rval = qla24xx_pause_risc(reg); + if (rval != QLA_SUCCESS) + goto qla25xx_fw_dump_failed_0; + + /* Host/Risc registers. */ + iter_reg = fw->host_risc_reg; + iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg); + qla24xx_read_window(reg, 0x7010, 16, iter_reg); + + /* PCIe registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x7C00); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_window, 0x01); + dmp_reg = ®->iobase_c4; + fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++)); + fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++)); + fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); + fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); + WRT_REG_DWORD(®->iobase_window, 0x00); + RD_REG_DWORD(®->iobase_window); + + /* Host interface registers. */ + dmp_reg = ®->flash_addr; + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Disable interrupts. */ + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); + + /* Shadow registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_select, 0xB0000000); + fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0100000); + fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0200000); + fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0300000); + fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0400000); + fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0500000); + fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0600000); + fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0700000); + fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0800000); + fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0900000); + fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0A00000); + fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + /* RISC I/O register. */ + WRT_REG_DWORD(®->iobase_addr, 0x0010); + fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); + + /* Mailbox registers. */ + mbx_reg = ®->mailbox0; + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); + + /* Transfer sequence registers. */ + iter_reg = fw->xseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); + qla24xx_read_window(reg, 0xBF70, 16, iter_reg); + + iter_reg = fw->xseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg); + qla24xx_read_window(reg, 0xBFE0, 16, iter_reg); + + qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); + + /* Receive sequence registers. */ + iter_reg = fw->rseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); + qla24xx_read_window(reg, 0xFF70, 16, iter_reg); + + iter_reg = fw->rseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg); + qla24xx_read_window(reg, 0xFFD0, 16, iter_reg); + + qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); + qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); + + /* Auxiliary sequence registers. */ + iter_reg = fw->aseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg); + qla24xx_read_window(reg, 0xB070, 16, iter_reg); + + iter_reg = fw->aseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg); + qla24xx_read_window(reg, 0xB0D0, 16, iter_reg); + + qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg); + qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg); + + /* Command DMA registers. */ + qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); + + /* Queues. */ + iter_reg = fw->req0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->resp0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->req1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Transmit DMA registers. */ + iter_reg = fw->xmt0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); + qla24xx_read_window(reg, 0x7610, 16, iter_reg); + + iter_reg = fw->xmt1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); + qla24xx_read_window(reg, 0x7630, 16, iter_reg); + + iter_reg = fw->xmt2_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); + qla24xx_read_window(reg, 0x7650, 16, iter_reg); + + iter_reg = fw->xmt3_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); + qla24xx_read_window(reg, 0x7670, 16, iter_reg); + + iter_reg = fw->xmt4_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); + qla24xx_read_window(reg, 0x7690, 16, iter_reg); + + qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); + + /* Receive DMA registers. */ + iter_reg = fw->rcvt0_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); + qla24xx_read_window(reg, 0x7710, 16, iter_reg); + + iter_reg = fw->rcvt1_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); + qla24xx_read_window(reg, 0x7730, 16, iter_reg); + + /* RISC registers. */ + iter_reg = fw->risc_gp_reg; + iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); + qla24xx_read_window(reg, 0x0F70, 16, iter_reg); + + /* Local memory controller registers. */ + iter_reg = fw->lmc_reg; + iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg); + qla24xx_read_window(reg, 0x3070, 16, iter_reg); + + /* Fibre Protocol Module registers. */ + iter_reg = fw->fpm_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); + qla24xx_read_window(reg, 0x40B0, 16, iter_reg); + + /* Frame Buffer registers. */ + iter_reg = fw->fb_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); + qla24xx_read_window(reg, 0x6F00, 16, iter_reg); + + rval = qla24xx_soft_reset(ha); + if (rval != QLA_SUCCESS) + goto qla25xx_fw_dump_failed_0; + + rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), + fw->ext_mem, &nxt); + if (rval != QLA_SUCCESS) + goto qla25xx_fw_dump_failed_0; + + nxt = qla2xxx_copy_queues(ha, nxt); + if (ha->eft) + memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); + +qla25xx_fw_dump_failed_0: if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); @@ -2102,7 +1402,7 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd) struct scsi_qla_host *ha; srb_t *sp; - ha = (struct scsi_qla_host *)cmd->device->host->hostdata; + ha = shost_priv(cmd->device->host); sp = (srb_t *) cmd->SCp.ptr; printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble); diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index cca4b0d8253e..a50ecf0b7c84 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -215,6 +215,8 @@ struct qla24xx_fw_dump { struct qla25xx_fw_dump { uint32_t host_status; + uint32_t host_risc_reg[32]; + uint32_t pcie_regs[4]; uint32_t host_reg[32]; uint32_t shadow_reg[11]; uint32_t risc_io_reg; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index c1964866a423..1900fbf6cd74 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/workqueue.h> #include <linux/firmware.h> +#include <linux/aer.h> #include <asm/semaphore.h> #include <scsi/scsi.h> @@ -184,8 +185,6 @@ * SCSI Request Block */ typedef struct srb { - struct list_head list; - struct scsi_qla_host *ha; /* HA the SP is queued on */ struct fc_port *fcport; @@ -316,7 +315,9 @@ struct device_reg_2xxx { } u; uint16_t fpm_diag_config; - uint16_t unused_5[0x6]; /* Gap */ + uint16_t unused_5[0x4]; /* Gap */ + uint16_t risc_hw; + uint16_t unused_5_1; /* Gap */ uint16_t pcr; /* Processor Control Register. */ uint16_t unused_6[0x5]; /* Gap */ uint16_t mctr; /* Memory Configuration and Timing. */ @@ -1702,7 +1703,7 @@ struct ct_fdmi_hba_attributes { /* * Port attribute types. */ -#define FDMI_PORT_ATTR_COUNT 5 +#define FDMI_PORT_ATTR_COUNT 6 #define FDMI_PORT_FC4_TYPES 1 #define FDMI_PORT_SUPPORT_SPEED 2 #define FDMI_PORT_CURRENT_SPEED 3 @@ -2476,6 +2477,8 @@ typedef struct scsi_qla_host { #define QLA_SWAITING 0 #define QLA_SREADING 1 #define QLA_SWRITING 2 + uint32_t optrom_region_start; + uint32_t optrom_region_size; /* PCI expansion ROM image information. */ #define ROM_CODE_TYPE_BIOS 0 @@ -2529,7 +2532,7 @@ typedef struct scsi_qla_host { #define VP_ERR_FAB_NORESOURCES 3 #define VP_ERR_FAB_LOGOUT 4 #define VP_ERR_ADAP_NORESOURCES 5 - int max_npiv_vports; /* 63 or 125 per topoloty */ + uint16_t max_npiv_vports; /* 63 or 125 per topoloty */ int cur_vport_count; } scsi_qla_host_t; @@ -2542,8 +2545,6 @@ typedef struct scsi_qla_host { test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ atomic_read(&ha->loop_state) == LOOP_DOWN) -#define to_qla_host(x) ((scsi_qla_host_t *) (x)->hostdata) - #define qla_printk(level, ha, format, arg...) \ dev_printk(level , &((ha)->pdev->dev) , format , ## arg) diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 99fe49618d61..25364b1aaf12 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -779,6 +779,8 @@ struct device_reg_24xx { #define FA_NVRAM_VPD_SIZE 0x200 #define FA_NVRAM_VPD0_ADDR 0x00 #define FA_NVRAM_VPD1_ADDR 0x100 + +#define FA_BOOT_CODE_ADDR 0x00000 /* * RISC code begins at offset 512KB * within flash. Consisting of two @@ -940,7 +942,9 @@ struct device_reg_24xx { uint16_t mailbox31; uint32_t iobase_window; - uint32_t unused_4[8]; /* Gap. */ + uint32_t iobase_c4; + uint32_t iobase_c8; + uint32_t unused_4_1[6]; /* Gap. */ uint32_t iobase_q; uint32_t unused_5[2]; /* Gap. */ uint32_t iobase_select; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index aa1e41152283..09cb2a908059 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -134,6 +134,9 @@ extern int qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); extern int +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 void @@ -212,8 +215,8 @@ extern int qla2x00_get_id_list(scsi_qla_host_t *, void *, dma_addr_t, uint16_t *); extern int -qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *, - uint16_t *); +qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, + uint16_t *, uint16_t *, uint16_t *); extern int qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); @@ -302,6 +305,8 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); +extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, + uint32_t, uint32_t); extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index a7e23583f899..eb0784c9ff83 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1517,7 +1517,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) /* Attributes */ ct_req->req.rpa.attrs.count = - __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT); + __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1); entries = ct_req->req.rpa.port_name; /* FC4 types. */ @@ -1600,7 +1600,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) /* OS device name. */ eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no); + strcpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME); alen = strlen(eiter->a.os_dev_name); alen += (alen & 3) ? (4 - (alen & 3)) : 4; eiter->len = cpu_to_be16(4 + alen); @@ -1611,6 +1611,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) /* Hostname. */ if (strlen(fc_host_system_hostname(ha->host))) { + ct_req->req.rpa.attrs.count = + __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT); eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME); snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1a058ec9bd0c..191dafd89be0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -849,7 +849,8 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) return; /* Retrieve IOCB counts available to the firmware. */ - rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); + rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt, + &ha->max_npiv_vports); if (rval) return; /* No point in continuing if current settings are sufficient. */ @@ -916,9 +917,15 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_attributes, &ha->fw_memory_size); qla2x00_resize_request_q(ha); ha->flags.npiv_supported = 0; - if (IS_QLA24XX(ha) && - (ha->fw_attributes & BIT_2)) + if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) && + (ha->fw_attributes & BIT_2)) { ha->flags.npiv_supported = 1; + if ((!ha->max_npiv_vports) || + ((ha->max_npiv_vports + 1) % + MAX_MULTI_ID_FABRIC)) + ha->max_npiv_vports = + MAX_NUM_VPORT_FABRIC; + } if (ql2xallocfwdump) qla2x00_alloc_fw_dump(ha); @@ -1155,8 +1162,7 @@ qla2x00_init_rings(scsi_qla_host_t *ha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); - mid_init_cb->count = MAX_NUM_VPORT_FABRIC; - ha->max_npiv_vports = MAX_NUM_VPORT_FABRIC; + mid_init_cb->count = ha->max_npiv_vports; rval = qla2x00_init_firmware(ha, ha->init_cb_size); if (rval) { @@ -1786,12 +1792,11 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) { fc_port_t *fcport; - fcport = kmalloc(sizeof(fc_port_t), flags); - if (fcport == NULL) - return (fcport); + fcport = kzalloc(sizeof(fc_port_t), flags); + if (!fcport) + return NULL; /* Setup fcport template structure. */ - memset(fcport, 0, sizeof (fc_port_t)); fcport->ha = ha; fcport->vp_idx = ha->vp_idx; fcport->port_type = FCT_UNKNOWN; @@ -1801,7 +1806,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) fcport->supported_classes = FC_COS_UNSPECIFIED; spin_lock_init(&fcport->rport_lock); - return (fcport); + return fcport; } /* @@ -2127,15 +2132,9 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) if (!IS_IIDMA_CAPABLE(ha)) return; - if (fcport->fp_speed == PORT_SPEED_UNKNOWN) { - DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- " - "unsupported FM port operating speed.\n", - ha->host_no, fcport->port_name[0], fcport->port_name[1], - fcport->port_name[2], fcport->port_name[3], - fcport->port_name[4], fcport->port_name[5], - fcport->port_name[6], fcport->port_name[7])); + if (fcport->fp_speed == PORT_SPEED_UNKNOWN || + fcport->fp_speed > ha->link_data_rate) return; - } rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed, mb); @@ -2473,13 +2472,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) rval = QLA_SUCCESS; /* Try GID_PT to get device list, else GAN. */ - swl = kmalloc(sizeof(sw_info_t) * MAX_FIBRE_DEVICES, GFP_ATOMIC); - if (swl == NULL) { + swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC); + if (!swl) { /*EMPTY*/ DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " "on GA_NXT\n", ha->host_no)); } else { - memset(swl, 0, sizeof(sw_info_t) * MAX_FIBRE_DEVICES); if (qla2x00_gid_pt(ha, swl) != QLA_SUCCESS) { kfree(swl); swl = NULL; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 3a5e78cb6b3f..7f6a89bd94f3 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -308,7 +308,7 @@ qla2x00_start_scsi(srb_t *sp) handle++; if (handle == MAX_OUTSTANDING_COMMANDS) handle = 1; - if (ha->outstanding_cmds[handle] == 0) + if (!ha->outstanding_cmds[handle]) break; } if (index == MAX_OUTSTANDING_COMMANDS) @@ -711,7 +711,7 @@ qla24xx_start_scsi(srb_t *sp) handle++; if (handle == MAX_OUTSTANDING_COMMANDS) handle = 1; - if (ha->outstanding_cmds[handle] == 0) + if (!ha->outstanding_cmds[handle]) break; } if (index == MAX_OUTSTANDING_COMMANDS) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index eecae9905ece..c4768c4f3990 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -6,6 +6,7 @@ */ #include "qla_def.h" +#include <linux/delay.h> #include <scsi/scsi_tcq.h> static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); @@ -34,6 +35,7 @@ qla2100_intr_handler(int irq, void *dev_id) int status; unsigned long flags; unsigned long iter; + uint16_t hccr; uint16_t mb[4]; ha = (scsi_qla_host_t *) dev_id; @@ -48,7 +50,23 @@ qla2100_intr_handler(int irq, void *dev_id) spin_lock_irqsave(&ha->hardware_lock, flags); for (iter = 50; iter--; ) { - if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) + hccr = RD_REG_WORD(®->hccr); + if (hccr & HCCR_RISC_PAUSE) { + if (pci_channel_offline(ha->pdev)) + break; + + /* + * Issue a "HARD" reset in order for the RISC interrupt + * bit to be cleared. Schedule a big hammmer to get + * out of the RISC PAUSED state. + */ + WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); + RD_REG_WORD(®->hccr); + + ha->isp_ops->fw_dump(ha, 1); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + } else if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) break; if (RD_REG_WORD(®->semaphore) & BIT_0) { @@ -127,6 +145,9 @@ qla2300_intr_handler(int irq, void *dev_id) for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->u.isp2300.host_status); if (stat & HSR_RISC_PAUSED) { + if (pci_channel_offline(ha->pdev)) + break; + hccr = RD_REG_WORD(®->hccr); if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8)) qla_printk(KERN_INFO, ha, "Parity error -- " @@ -1464,6 +1485,52 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha) WRT_REG_DWORD(®->rsp_q_out, ha->rsp_ring_index); } +static void +qla2xxx_check_risc_status(scsi_qla_host_t *ha) +{ + int rval; + uint32_t cnt; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + if (!IS_QLA25XX(ha)) + return; + + rval = QLA_SUCCESS; + WRT_REG_DWORD(®->iobase_addr, 0x7C00); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_window, 0x0001); + for (cnt = 10000; (RD_REG_DWORD(®->iobase_window) & BIT_0) == 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) { + WRT_REG_DWORD(®->iobase_window, 0x0001); + udelay(10); + } else + rval = QLA_FUNCTION_TIMEOUT; + } + if (rval == QLA_SUCCESS) + goto next_test; + + WRT_REG_DWORD(®->iobase_window, 0x0003); + for (cnt = 100; (RD_REG_DWORD(®->iobase_window) & BIT_0) == 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) { + WRT_REG_DWORD(®->iobase_window, 0x0003); + udelay(10); + } else + rval = QLA_FUNCTION_TIMEOUT; + } + if (rval != QLA_SUCCESS) + goto done; + +next_test: + if (RD_REG_DWORD(®->iobase_c8) & BIT_3) + qla_printk(KERN_INFO, ha, "Additional code -- 0x55AA.\n"); + +done: + WRT_REG_DWORD(®->iobase_window, 0x0000); + RD_REG_DWORD(®->iobase_window); +} + /** * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. * @irq: @@ -1499,10 +1566,16 @@ qla24xx_intr_handler(int irq, void *dev_id) for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { + if (pci_channel_offline(ha->pdev)) + break; + hccr = RD_REG_DWORD(®->hccr); qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); + + qla2xxx_check_risc_status(ha); + ha->isp_ops->fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; @@ -1606,7 +1679,6 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) qla24xx_process_response_queue(ha); WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - RD_REG_DWORD_RELAXED(®->hccr); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -1620,7 +1692,6 @@ qla24xx_msix_default(int irq, void *dev_id) struct device_reg_24xx __iomem *reg; int status; unsigned long flags; - unsigned long iter; uint32_t stat; uint32_t hccr; uint16_t mb[4]; @@ -1630,13 +1701,19 @@ qla24xx_msix_default(int irq, void *dev_id) status = 0; spin_lock_irqsave(&ha->hardware_lock, flags); - for (iter = 50; iter--; ) { + do { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { + if (pci_channel_offline(ha->pdev)) + break; + hccr = RD_REG_DWORD(®->hccr); qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); + + qla2xxx_check_risc_status(ha); + ha->isp_ops->fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; @@ -1669,8 +1746,7 @@ qla24xx_msix_default(int irq, void *dev_id) break; } WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - RD_REG_DWORD_RELAXED(®->hccr); - } + } while (0); spin_unlock_irqrestore(&ha->hardware_lock, flags); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index d3746ec80a85..c53ec67c47f4 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -391,7 +391,8 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; - mcp->out_mb |= MBX_3|MBX_2|MBX_1; + mcp->mb[4] = 0; + mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1; mcp->in_mb |= MBX_1; } else { mcp->mb[1] = LSW(risc_addr); @@ -1919,7 +1920,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, */ int qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, - uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, uint16_t *orig_iocb_cnt) + uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, + uint16_t *orig_iocb_cnt, uint16_t *max_npiv_vports) { int rval; mbx_cmd_t mc; @@ -1929,7 +1931,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; mcp->out_mb = MBX_0; - mcp->in_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); @@ -1940,9 +1942,9 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, ha->host_no, mcp->mb[0])); } else { DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x " - "mb7=%x mb10=%x.\n", __func__, ha->host_no, + "mb7=%x mb10=%x mb11=%x.\n", __func__, ha->host_no, mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[6], mcp->mb[7], - mcp->mb[10])); + mcp->mb[10], mcp->mb[11])); if (cur_xchg_cnt) *cur_xchg_cnt = mcp->mb[3]; @@ -1952,6 +1954,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, *cur_iocb_cnt = mcp->mb[7]; if (orig_iocb_cnt) *orig_iocb_cnt = mcp->mb[10]; + if (max_npiv_vports) + *max_npiv_vports = mcp->mb[11]; } return (rval); @@ -2980,3 +2984,51 @@ qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format, return rval; } + +int +qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr, + uint32_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); + + if (MSW(addr) || IS_FWI2_CAPABLE(ha)) { + mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; + mcp->mb[8] = MSW(addr); + mcp->out_mb = MBX_8|MBX_0; + } else { + mcp->mb[0] = MBC_DUMP_RISC_RAM; + mcp->out_mb = MBX_0; + } + mcp->mb[1] = LSW(addr); + mcp->mb[2] = MSW(req_dma); + mcp->mb[3] = LSW(req_dma); + mcp->mb[6] = MSW(MSD(req_dma)); + mcp->mb[7] = LSW(MSD(req_dma)); + mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; + if (IS_FWI2_CAPABLE(ha)) { + mcp->mb[4] = MSW(size); + mcp->mb[5] = LSW(size); + mcp->out_mb |= MBX_5|MBX_4; + } else { + mcp->mb[4] = LSW(size); + mcp->out_mb |= MBX_4; + } + + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, + ha->host_no, rval, mcp->mb[0])); + } else { + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); + } + + return rval; +} diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 54dc415d8b53..821ee74aadc6 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -104,7 +104,7 @@ qla24xx_find_vhost_by_name(scsi_qla_host_t *ha, uint8_t *port_name) * * Context: */ -void +static void qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) { fc_port_t *fcport; @@ -179,37 +179,7 @@ enable_failed: return 1; } -/** - * qla24xx_modify_vport() - Modifies the virtual fabric port's configuration - * @ha: HA context - * @vp: pointer to buffer of virtual port parameters. - * @ret_code: return error code: - * - * Returns the virtual port id, or MAX_VSAN_ID, if couldn't create. - */ -uint32_t -qla24xx_modify_vhba(scsi_qla_host_t *ha, vport_params_t *vp, uint32_t *vp_id) -{ - scsi_qla_host_t *vha; - - vha = qla24xx_find_vhost_by_name(ha, vp->port_name); - if (!vha) { - *vp_id = MAX_NUM_VPORT_LOOP; - return VP_RET_CODE_WWPN; - } - - if (qla24xx_enable_vp(vha)) { - scsi_host_put(vha->host); - qla2x00_mem_free(vha); - *vp_id = MAX_NUM_VPORT_LOOP; - return VP_RET_CODE_RESOURCES; - } - - *vp_id = vha->vp_idx; - return VP_RET_CODE_OK; -} - -void +static void qla24xx_configure_vp(scsi_qla_host_t *vha) { struct fc_vport *fc_vport; @@ -363,7 +333,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *ha) int qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha; uint8_t port_name[WWN_SIZE]; @@ -397,7 +367,7 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport) scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha; struct Scsi_Host *host; @@ -409,7 +379,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) return(NULL); } - vha = (scsi_qla_host_t *)host->hostdata; + vha = shost_priv(host); /* clone the parent hba */ memcpy(vha, ha, sizeof (scsi_qla_host_t)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index acca898ce0a2..a6bb8d0ecf13 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -379,12 +379,17 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport, static int qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); srb_t *sp; int rval; + if (unlikely(pci_channel_offline(ha->pdev))) { + cmd->result = DID_REQUEUE << 16; + goto qc_fail_command; + } + rval = fc_remote_port_chkready(rport); if (rval) { cmd->result = rval; @@ -440,13 +445,18 @@ qc_fail_command: static int qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); srb_t *sp; int rval; scsi_qla_host_t *pha = to_qla_parent(ha); + if (unlikely(pci_channel_offline(ha->pdev))) { + cmd->result = DID_REQUEUE << 16; + goto qc24_fail_command; + } + rval = fc_remote_port_chkready(rport); if (rval) { cmd->result = rval; @@ -653,7 +663,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd) static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); srb_t *sp; int ret, i; unsigned int id, lun; @@ -793,7 +803,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) static int qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; unsigned int id, lun; @@ -922,7 +932,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) static int qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); scsi_qla_host_t *pha = to_qla_parent(ha); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; @@ -982,7 +992,7 @@ eh_bus_reset_done: static int qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; unsigned int id, lun; @@ -1132,7 +1142,7 @@ qla2xxx_slave_alloc(struct scsi_device *sdev) static int qla2xxx_slave_configure(struct scsi_device *sdev) { - scsi_qla_host_t *ha = to_qla_host(sdev->host); + scsi_qla_host_t *ha = shost_priv(sdev->host); struct fc_rport *rport = starget_to_rport(sdev->sdev_target); if (sdev->tagged_supported) @@ -1384,7 +1394,7 @@ static struct isp_operations qla25xx_isp_ops = { .beacon_on = qla24xx_beacon_on, .beacon_off = qla24xx_beacon_off, .beacon_blink = qla24xx_beacon_blink, - .read_optrom = qla24xx_read_optrom_data, + .read_optrom = qla25xx_read_optrom_data, .write_optrom = qla24xx_write_optrom_data, .get_flash_version = qla24xx_get_flash_version, }; @@ -1533,7 +1543,7 @@ iospace_error_exit: static void qla2xxx_scan_start(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + scsi_qla_host_t *ha = shost_priv(shost); set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); @@ -1543,7 +1553,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost) static int qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) { - scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + scsi_qla_host_t *ha = shost_priv(shost); if (!ha->host) return 1; @@ -1571,6 +1581,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (pci_enable_device(pdev)) goto probe_out; + if (pci_find_aer_capability(pdev)) + if (pci_enable_pcie_error_reporting(pdev)) + goto probe_out; + sht = &qla2x00_driver_template; if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || @@ -1586,7 +1600,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) } /* Clear our data area */ - ha = (scsi_qla_host_t *)host->hostdata; + ha = shost_priv(host); memset(ha, 0, sizeof(scsi_qla_host_t)); ha->pdev = pdev; @@ -2423,7 +2437,6 @@ qla2x00_do_dpc(void *data) if (atomic_read(&fcport->state) != FCS_ONLINE && fcport->login_retry) { - fcport->login_retry--; if (fcport->flags & FCF_FABRIC_DEVICE) { if (fcport->flags & FCF_TAPE_PRESENT) @@ -2439,6 +2452,7 @@ qla2x00_do_dpc(void *data) qla2x00_local_device_login( ha, fcport); + fcport->login_retry--; if (status == QLA_SUCCESS) { fcport->old_loop_id = fcport->loop_id; @@ -2456,6 +2470,8 @@ qla2x00_do_dpc(void *data) } else { fcport->login_retry = 0; } + if (fcport->login_retry == 0) + fcport->loop_id = FC_NO_LOOP_ID; } if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) break; @@ -2814,6 +2830,105 @@ qla2x00_release_firmware(void) up(&qla_fw_lock); } +static pci_ers_result_t +qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ + switch (state) { + case pci_channel_io_normal: + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + pci_disable_device(pdev); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + qla2x00_remove_one(pdev); + return PCI_ERS_RESULT_DISCONNECT; + } + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t +qla2xxx_pci_mmio_enabled(struct pci_dev *pdev) +{ + int risc_paused = 0; + uint32_t stat; + unsigned long flags; + scsi_qla_host_t *ha = pci_get_drvdata(pdev); + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; + + spin_lock_irqsave(&ha->hardware_lock, flags); + if (IS_QLA2100(ha) || IS_QLA2200(ha)){ + stat = RD_REG_DWORD(®->hccr); + if (stat & HCCR_RISC_PAUSE) + risc_paused = 1; + } else if (IS_QLA23XX(ha)) { + stat = RD_REG_DWORD(®->u.isp2300.host_status); + if (stat & HSR_RISC_PAUSED) + risc_paused = 1; + } else if (IS_FWI2_CAPABLE(ha)) { + stat = RD_REG_DWORD(®24->host_status); + if (stat & HSRX_RISC_PAUSED) + risc_paused = 1; + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (risc_paused) { + qla_printk(KERN_INFO, ha, "RISC paused -- mmio_enabled, " + "Dumping firmware!\n"); + ha->isp_ops->fw_dump(ha, 0); + + return PCI_ERS_RESULT_NEED_RESET; + } else + return PCI_ERS_RESULT_RECOVERED; +} + +static pci_ers_result_t +qla2xxx_pci_slot_reset(struct pci_dev *pdev) +{ + pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; + scsi_qla_host_t *ha = pci_get_drvdata(pdev); + + if (pci_enable_device(pdev)) { + qla_printk(KERN_WARNING, ha, + "Can't re-enable PCI device after reset.\n"); + + return ret; + } + pci_set_master(pdev); + + if (ha->isp_ops->pci_config(ha)) + return ret; + + set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + if (qla2x00_abort_isp(ha)== QLA_SUCCESS) + ret = PCI_ERS_RESULT_RECOVERED; + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + + return ret; +} + +static void +qla2xxx_pci_resume(struct pci_dev *pdev) +{ + scsi_qla_host_t *ha = pci_get_drvdata(pdev); + int ret; + + ret = qla2x00_wait_for_hba_online(ha); + if (ret != QLA_SUCCESS) { + qla_printk(KERN_ERR, ha, + "the device failed to resume I/O " + "from slot/link_reset"); + } + pci_cleanup_aer_uncorrect_error_status(pdev); +} + +static struct pci_error_handlers qla2xxx_err_handler = { + .error_detected = qla2xxx_pci_error_detected, + .mmio_enabled = qla2xxx_pci_mmio_enabled, + .slot_reset = qla2xxx_pci_slot_reset, + .resume = qla2xxx_pci_resume, +}; + static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) }, @@ -2839,6 +2954,7 @@ static struct pci_driver qla2xxx_pci_driver = { .id_table = qla2xxx_pci_tbl, .probe = qla2x00_probe_one, .remove = __devexit_p(qla2x00_remove_one), + .err_handler = &qla2xxx_err_handler, }; /** diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index a925a3f179f9..40b059fc1981 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -425,6 +425,9 @@ qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat) /* Flash Manipulation Routines */ /*****************************************************************************/ +#define OPTROM_BURST_SIZE 0x1000 +#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) + static inline uint32_t flash_conf_to_access_addr(uint32_t faddr) { @@ -544,41 +547,59 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { int ret; - uint32_t liter; - uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask; + uint32_t liter, miter; + uint32_t sec_mask, rest_addr, conf_addr; uint32_t fdata, findex ; uint8_t man_id, flash_id; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + dma_addr_t optrom_dma; + void *optrom = NULL; + uint32_t *s, *d; ret = QLA_SUCCESS; + /* Prepare burst-capable write on supported ISPs. */ + if (IS_QLA25XX(ha) && !(faddr & 0xfff) && + dwords > OPTROM_BURST_DWORDS) { + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + qla_printk(KERN_DEBUG, ha, + "Unable to allocate memory for optrom burst write " + "(%x KB).\n", OPTROM_BURST_SIZE / 1024); + } + } + qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, ha->host_no, man_id, flash_id)); - sec_end_mask = 0; conf_addr = flash_conf_to_access_addr(0x03d8); switch (man_id) { case 0xbf: /* STT flash. */ - rest_addr = 0x1fff; - sec_mask = 0x3e000; + if (flash_id == 0x8e) { + rest_addr = 0x3fff; + sec_mask = 0x7c000; + } else { + rest_addr = 0x1fff; + sec_mask = 0x7e000; + } if (flash_id == 0x80) conf_addr = flash_conf_to_access_addr(0x0352); break; case 0x13: /* ST M25P80. */ rest_addr = 0x3fff; - sec_mask = 0x3c000; + sec_mask = 0x7c000; break; case 0x1f: // Atmel 26DF081A - rest_addr = 0x0fff; - sec_mask = 0xff000; - sec_end_mask = 0x003ff; + rest_addr = 0x3fff; + sec_mask = 0x7c000; conf_addr = flash_conf_to_access_addr(0x0320); break; default: /* Default to 64 kb sector size. */ rest_addr = 0x3fff; - sec_mask = 0x3c000; + sec_mask = 0x7c000; break; } @@ -592,56 +613,81 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, /* Some flash parts need an additional zero-write to clear bits.*/ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0); - do { /* Loop once to provide quick error exit. */ - for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { - if (man_id == 0x1f) { - findex = faddr << 2; - fdata = findex & sec_mask; - } else { - findex = faddr; - fdata = (findex & sec_mask) << 2; - } + for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { + if (man_id == 0x1f) { + findex = faddr << 2; + fdata = findex & sec_mask; + } else { + findex = faddr; + fdata = (findex & sec_mask) << 2; + } - /* Are we at the beginning of a sector? */ - if ((findex & rest_addr) == 0) { - /* - * Do sector unprotect at 4K boundry for Atmel - * part. - */ - if (man_id == 0x1f) - qla24xx_write_flash_dword(ha, - flash_conf_to_access_addr(0x0339), - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); - ret = qla24xx_write_flash_dword(ha, conf_addr, - (fdata & 0xff00) |((fdata << 16) & + /* Are we at the beginning of a sector? */ + if ((findex & rest_addr) == 0) { + /* Do sector unprotect at 4K boundry for Atmel part. */ + if (man_id == 0x1f) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0339), + (fdata & 0xff00) | ((fdata << 16) & 0xff0000) | ((fdata >> 16) & 0xff)); - if (ret != QLA_SUCCESS) { - DEBUG9(printk("%s(%ld) Unable to flash " - "sector: address=%x.\n", __func__, - ha->host_no, faddr)); - break; - } + ret = qla24xx_write_flash_dword(ha, conf_addr, + (fdata & 0xff00) |((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); + if (ret != QLA_SUCCESS) { + DEBUG9(printk("%s(%ld) Unable to flash " + "sector: address=%x.\n", __func__, + ha->host_no, faddr)); + break; } - ret = qla24xx_write_flash_dword(ha, + } + + /* Go with burst-write. */ + if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) { + /* Copy data to DMA'ble buffer. */ + for (miter = 0, s = optrom, d = dwptr; + miter < OPTROM_BURST_DWORDS; miter++, s++, d++) + *s = cpu_to_le32(*d); + + ret = qla2x00_load_ram(ha, optrom_dma, flash_data_to_access_addr(faddr), - cpu_to_le32(*dwptr)); + OPTROM_BURST_DWORDS); if (ret != QLA_SUCCESS) { - DEBUG9(printk("%s(%ld) Unable to program flash " - "address=%x data=%x.\n", __func__, - ha->host_no, faddr, *dwptr)); - break; + qla_printk(KERN_WARNING, ha, + "Unable to burst-write optrom segment " + "(%x/%x/%llx).\n", ret, + flash_data_to_access_addr(faddr), + optrom_dma); + qla_printk(KERN_WARNING, ha, + "Reverting to slow-write.\n"); + + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + optrom = NULL; + } else { + liter += OPTROM_BURST_DWORDS - 1; + faddr += OPTROM_BURST_DWORDS - 1; + dwptr += OPTROM_BURST_DWORDS - 1; + continue; } + } - /* Do sector protect at 4K boundry for Atmel part. */ - if (man_id == 0x1f && - ((faddr & sec_end_mask) == 0x3ff)) - qla24xx_write_flash_dword(ha, - flash_conf_to_access_addr(0x0336), - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); + ret = qla24xx_write_flash_dword(ha, + flash_data_to_access_addr(faddr), cpu_to_le32(*dwptr)); + if (ret != QLA_SUCCESS) { + DEBUG9(printk("%s(%ld) Unable to program flash " + "address=%x data=%x.\n", __func__, + ha->host_no, faddr, *dwptr)); + break; } - } while (0); + + /* Do sector protect at 4K boundry for Atmel part. */ + if (man_id == 0x1f && + ((faddr & rest_addr) == rest_addr)) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0336), + (fdata & 0xff00) | ((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); + } /* Enable flash write-protection. */ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c); @@ -651,6 +697,10 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ + if (optrom) + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + return ret; } @@ -1728,7 +1778,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, { /* Suspend HBA. */ scsi_block_requests(ha->host); - ha->isp_ops->disable_intrs(ha); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with read. */ @@ -1736,7 +1785,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); - ha->isp_ops->enable_intrs(ha); scsi_unblock_requests(ha->host); return buf; @@ -1750,7 +1798,6 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, /* Suspend HBA. */ scsi_block_requests(ha->host); - ha->isp_ops->disable_intrs(ha); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with write. */ @@ -1767,6 +1814,70 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, return rval; } +uint8_t * +qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, + uint32_t offset, uint32_t length) +{ + int rval; + dma_addr_t optrom_dma; + void *optrom; + uint8_t *pbuf; + uint32_t faddr, left, burst; + + if (offset & 0xfff) + goto slow_read; + if (length < OPTROM_BURST_SIZE) + goto slow_read; + + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + qla_printk(KERN_DEBUG, ha, + "Unable to allocate memory for optrom burst read " + "(%x KB).\n", OPTROM_BURST_SIZE / 1024); + + goto slow_read; + } + + pbuf = buf; + faddr = offset >> 2; + left = length >> 2; + burst = OPTROM_BURST_DWORDS; + while (left != 0) { + if (burst > left) + burst = left; + + rval = qla2x00_dump_ram(ha, optrom_dma, + flash_data_to_access_addr(faddr), burst); + if (rval) { + qla_printk(KERN_WARNING, ha, + "Unable to burst-read optrom segment " + "(%x/%x/%llx).\n", rval, + flash_data_to_access_addr(faddr), optrom_dma); + qla_printk(KERN_WARNING, ha, + "Reverting to slow-read.\n"); + + dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + optrom, optrom_dma); + goto slow_read; + } + + memcpy(pbuf, optrom, burst * 4); + + left -= burst; + faddr += burst; + pbuf += burst * 4; + } + + dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom, + optrom_dma); + + return buf; + +slow_read: + return qla24xx_read_optrom_data(ha, buf, offset, length); +} + /** * qla2x00_get_fcode_version() - Determine an FCODE image's version. * @ha: HA context diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 18095b9b76f4..2d551a3006f6 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.00-k3" +#define QLA2XXX_VERSION "8.02.00-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 |