diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2008-09-12 00:22:49 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-10-03 12:46:17 -0400 |
commit | c00d8994d91e51aa6b891ad0e877f66cc1011de2 (patch) | |
tree | 5c200c361fffd2d8ac48572b22db0c9cd8b55451 | |
parent | 4b89258c7320bab4155b692e76ae9ffdd85e79be (diff) |
[SCSI] qla2xxx: Add Flash Layout Table support.
The Flash Layout Table (FLT) present on many recent HBAs encodes
flash usage information, organizes data stored into separate
regions and presents the information uniformly to the driver.
Use this information rather than using specific hard-coded values
based on ISP type.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 8 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 45 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 10 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 242 |
7 files changed, 272 insertions, 44 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 866b0a8b83a1..0ddfe7106b3b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -292,10 +292,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
292 | valid = 0; | 292 | valid = 0; |
293 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) | 293 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) |
294 | valid = 1; | 294 | valid = 1; |
295 | else if (start == (FA_BOOT_CODE_ADDR*4) || | 295 | else if (start == (ha->flt_region_boot * 4) || |
296 | start == (FA_RISC_CODE_ADDR*4)) | 296 | start == (ha->flt_region_fw * 4)) |
297 | valid = 1; | 297 | valid = 1; |
298 | else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) | 298 | else if (IS_QLA25XX(ha) && |
299 | start == (ha->flt_region_vpd_nvram * 4)) | ||
299 | valid = 1; | 300 | valid = 1; |
300 | if (!valid) { | 301 | if (!valid) { |
301 | qla_printk(KERN_WARNING, ha, | 302 | qla_printk(KERN_WARNING, ha, |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index d1160d229d10..880e71127b73 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2508,7 +2508,6 @@ typedef struct scsi_qla_host { | |||
2508 | uint64_t fce_wr, fce_rd; | 2508 | uint64_t fce_wr, fce_rd; |
2509 | struct mutex fce_mutex; | 2509 | struct mutex fce_mutex; |
2510 | 2510 | ||
2511 | uint32_t hw_event_start; | ||
2512 | uint32_t hw_event_ptr; | 2511 | uint32_t hw_event_ptr; |
2513 | uint32_t hw_event_pause_errors; | 2512 | uint32_t hw_event_pause_errors; |
2514 | 2513 | ||
@@ -2554,6 +2553,13 @@ typedef struct scsi_qla_host { | |||
2554 | uint32_t fdt_unprotect_sec_cmd; | 2553 | uint32_t fdt_unprotect_sec_cmd; |
2555 | uint32_t fdt_protect_sec_cmd; | 2554 | uint32_t fdt_protect_sec_cmd; |
2556 | 2555 | ||
2556 | uint32_t flt_region_flt; | ||
2557 | uint32_t flt_region_fdt; | ||
2558 | uint32_t flt_region_boot; | ||
2559 | uint32_t flt_region_fw; | ||
2560 | uint32_t flt_region_vpd_nvram; | ||
2561 | uint32_t flt_region_hw_event; | ||
2562 | |||
2557 | /* Needed for BEACON */ | 2563 | /* Needed for BEACON */ |
2558 | uint16_t beacon_blink_led; | 2564 | uint16_t beacon_blink_led; |
2559 | uint8_t beacon_color_state; | 2565 | uint8_t beacon_color_state; |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index cf194517400d..2ec986bf8344 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -789,12 +789,16 @@ struct device_reg_24xx { | |||
789 | #define FA_RISC_CODE_ADDR 0x20000 | 789 | #define FA_RISC_CODE_ADDR 0x20000 |
790 | #define FA_RISC_CODE_SEGMENTS 2 | 790 | #define FA_RISC_CODE_SEGMENTS 2 |
791 | 791 | ||
792 | #define FA_FLASH_DESCR_ADDR_24 0x11000 | ||
793 | #define FA_FLASH_LAYOUT_ADDR_24 0x11400 | ||
794 | |||
792 | #define FA_FW_AREA_ADDR 0x40000 | 795 | #define FA_FW_AREA_ADDR 0x40000 |
793 | #define FA_VPD_NVRAM_ADDR 0x48000 | 796 | #define FA_VPD_NVRAM_ADDR 0x48000 |
794 | #define FA_FEATURE_ADDR 0x4C000 | 797 | #define FA_FEATURE_ADDR 0x4C000 |
795 | #define FA_FLASH_DESCR_ADDR 0x50000 | 798 | #define FA_FLASH_DESCR_ADDR 0x50000 |
799 | #define FA_FLASH_LAYOUT_ADDR 0x50400 | ||
796 | #define FA_HW_EVENT0_ADDR 0x54000 | 800 | #define FA_HW_EVENT0_ADDR 0x54000 |
797 | #define FA_HW_EVENT1_ADDR 0x54200 | 801 | #define FA_HW_EVENT1_ADDR 0x54400 |
798 | #define FA_HW_EVENT_SIZE 0x200 | 802 | #define FA_HW_EVENT_SIZE 0x200 |
799 | #define FA_HW_EVENT_ENTRY_SIZE 4 | 803 | #define FA_HW_EVENT_ENTRY_SIZE 4 |
800 | /* | 804 | /* |
@@ -806,10 +810,6 @@ struct device_reg_24xx { | |||
806 | #define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023 | 810 | #define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023 |
807 | #define HW_EVENT_FLASH_FW_ERR 0xF024 | 811 | #define HW_EVENT_FLASH_FW_ERR 0xF024 |
808 | 812 | ||
809 | #define FA_BOOT_LOG_ADDR 0x58000 | ||
810 | #define FA_FW_DUMP0_ADDR 0x60000 | ||
811 | #define FA_FW_DUMP1_ADDR 0x70000 | ||
812 | |||
813 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ | 813 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ |
814 | 814 | ||
815 | uint32_t ctrl_status; /* Control/Status. */ | 815 | uint32_t ctrl_status; /* Control/Status. */ |
@@ -1203,6 +1203,41 @@ struct qla_fdt_layout { | |||
1203 | uint8_t unused2[65]; | 1203 | uint8_t unused2[65]; |
1204 | }; | 1204 | }; |
1205 | 1205 | ||
1206 | /* Flash Layout Table ********************************************************/ | ||
1207 | |||
1208 | struct qla_flt_location { | ||
1209 | uint8_t sig[4]; | ||
1210 | uint32_t start_lo; | ||
1211 | uint32_t start_hi; | ||
1212 | uint16_t unused; | ||
1213 | uint16_t checksum; | ||
1214 | }; | ||
1215 | |||
1216 | struct qla_flt_header { | ||
1217 | uint16_t version; | ||
1218 | uint16_t length; | ||
1219 | uint16_t checksum; | ||
1220 | uint16_t unused; | ||
1221 | }; | ||
1222 | |||
1223 | #define FLT_REG_FW 0x01 | ||
1224 | #define FLT_REG_BOOT_CODE 0x07 | ||
1225 | #define FLT_REG_VPD_0 0x14 | ||
1226 | #define FLT_REG_NVRAM_0 0x15 | ||
1227 | #define FLT_REG_VPD_1 0x16 | ||
1228 | #define FLT_REG_NVRAM_1 0x17 | ||
1229 | #define FLT_REG_FDT 0x1a | ||
1230 | #define FLT_REG_FLT 0x1c | ||
1231 | #define FLT_REG_HW_EVENT_0 0x1d | ||
1232 | #define FLT_REG_HW_EVENT_1 0x1f | ||
1233 | |||
1234 | struct qla_flt_region { | ||
1235 | uint32_t code; | ||
1236 | uint32_t size; | ||
1237 | uint32_t start; | ||
1238 | uint32_t end; | ||
1239 | }; | ||
1240 | |||
1206 | /* 84XX Support **************************************************************/ | 1241 | /* 84XX Support **************************************************************/ |
1207 | 1242 | ||
1208 | #define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */ | 1243 | #define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0b156735e9a6..dbd9f93890e8 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -313,7 +313,7 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); | |||
313 | extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, | 313 | extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, |
314 | uint16_t, uint16_t); | 314 | uint16_t, uint16_t); |
315 | 315 | ||
316 | extern void qla2xxx_get_flash_info(scsi_qla_host_t *); | 316 | extern int qla2xxx_get_flash_info(scsi_qla_host_t *); |
317 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); | 317 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); |
318 | 318 | ||
319 | /* | 319 | /* |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 57f24df626d9..20847fb15bdb 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -83,6 +83,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
83 | 83 | ||
84 | ha->isp_ops->reset_chip(ha); | 84 | ha->isp_ops->reset_chip(ha); |
85 | 85 | ||
86 | rval = qla2xxx_get_flash_info(ha); | ||
87 | if (rval) { | ||
88 | DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n", | ||
89 | ha->host_no)); | ||
90 | return (rval); | ||
91 | } | ||
92 | |||
86 | ha->isp_ops->get_flash_version(ha, ha->request_ring); | 93 | ha->isp_ops->get_flash_version(ha, ha->request_ring); |
87 | 94 | ||
88 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); | 95 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); |
@@ -109,7 +116,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
109 | rval = qla2x00_setup_chip(ha); | 116 | rval = qla2x00_setup_chip(ha); |
110 | if (rval) | 117 | if (rval) |
111 | return (rval); | 118 | return (rval); |
112 | qla2xxx_get_flash_info(ha); | ||
113 | } | 119 | } |
114 | if (IS_QLA84XX(ha)) { | 120 | if (IS_QLA84XX(ha)) { |
115 | ha->cs84xx = qla84xx_get_chip(ha); | 121 | ha->cs84xx = qla84xx_get_chip(ha); |
@@ -3751,7 +3757,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3751 | rval = QLA_SUCCESS; | 3757 | rval = QLA_SUCCESS; |
3752 | 3758 | ||
3753 | segments = FA_RISC_CODE_SEGMENTS; | 3759 | segments = FA_RISC_CODE_SEGMENTS; |
3754 | faddr = FA_RISC_CODE_ADDR; | 3760 | faddr = ha->flt_region_fw; |
3755 | dcode = (uint32_t *)ha->request_ring; | 3761 | dcode = (uint32_t *)ha->request_ring; |
3756 | *srisc_addr = 0; | 3762 | *srisc_addr = 0; |
3757 | 3763 | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6d0f0e5f2827..c1ffc3070ebe 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1663,8 +1663,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1663 | ha->gid_list_info_size = 8; | 1663 | ha->gid_list_info_size = 8; |
1664 | ha->optrom_size = OPTROM_SIZE_25XX; | 1664 | ha->optrom_size = OPTROM_SIZE_25XX; |
1665 | ha->isp_ops = &qla25xx_isp_ops; | 1665 | ha->isp_ops = &qla25xx_isp_ops; |
1666 | ha->hw_event_start = PCI_FUNC(pdev->devfn) ? | ||
1667 | FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR; | ||
1668 | } | 1666 | } |
1669 | host->can_queue = ha->request_q_length + 128; | 1667 | host->can_queue = ha->request_q_length + 128; |
1670 | 1668 | ||
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 1bca74474935..6de1e3bc62a8 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -543,23 +543,186 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, | |||
543 | } | 543 | } |
544 | } | 544 | } |
545 | 545 | ||
546 | void | 546 | static int |
547 | qla2xxx_get_flash_info(scsi_qla_host_t *ha) | 547 | qla2xxx_find_flt_start(scsi_qla_host_t *ha, uint32_t *start) |
548 | { | ||
549 | const char *loc, *locations[] = { "DEF", "PCI" }; | ||
550 | uint32_t pcihdr, pcids; | ||
551 | uint32_t *dcode; | ||
552 | uint8_t *buf, *bcode, last_image; | ||
553 | uint16_t cnt, chksum, *wptr; | ||
554 | struct qla_flt_location *fltl; | ||
555 | |||
556 | /* | ||
557 | * FLT-location structure resides after the last PCI region. | ||
558 | */ | ||
559 | |||
560 | /* Begin with sane defaults. */ | ||
561 | loc = locations[0]; | ||
562 | *start = IS_QLA24XX_TYPE(ha) ? FA_FLASH_LAYOUT_ADDR_24: | ||
563 | FA_FLASH_LAYOUT_ADDR; | ||
564 | |||
565 | /* Begin with first PCI expansion ROM header. */ | ||
566 | buf = (uint8_t *)ha->request_ring; | ||
567 | dcode = (uint32_t *)ha->request_ring; | ||
568 | pcihdr = 0; | ||
569 | last_image = 1; | ||
570 | do { | ||
571 | /* Verify PCI expansion ROM header. */ | ||
572 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); | ||
573 | bcode = buf + (pcihdr % 4); | ||
574 | if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) | ||
575 | goto end; | ||
576 | |||
577 | /* Locate PCI data structure. */ | ||
578 | pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); | ||
579 | qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); | ||
580 | bcode = buf + (pcihdr % 4); | ||
581 | |||
582 | /* Validate signature of PCI data structure. */ | ||
583 | if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || | ||
584 | bcode[0x2] != 'I' || bcode[0x3] != 'R') | ||
585 | goto end; | ||
586 | |||
587 | last_image = bcode[0x15] & BIT_7; | ||
588 | |||
589 | /* Locate next PCI expansion ROM. */ | ||
590 | pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; | ||
591 | } while (!last_image); | ||
592 | |||
593 | /* Now verify FLT-location structure. */ | ||
594 | fltl = (struct qla_flt_location *)ha->request_ring; | ||
595 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, | ||
596 | sizeof(struct qla_flt_location) >> 2); | ||
597 | if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' || | ||
598 | fltl->sig[2] != 'L' || fltl->sig[3] != 'T') | ||
599 | goto end; | ||
600 | |||
601 | wptr = (uint16_t *)ha->request_ring; | ||
602 | cnt = sizeof(struct qla_flt_location) >> 1; | ||
603 | for (chksum = 0; cnt; cnt--) | ||
604 | chksum += le16_to_cpu(*wptr++); | ||
605 | if (chksum) { | ||
606 | qla_printk(KERN_ERR, ha, | ||
607 | "Inconsistent FLTL detected: checksum=0x%x.\n", chksum); | ||
608 | qla2x00_dump_buffer(buf, sizeof(struct qla_flt_location)); | ||
609 | return QLA_FUNCTION_FAILED; | ||
610 | } | ||
611 | |||
612 | /* Good data. Use specified location. */ | ||
613 | loc = locations[1]; | ||
614 | *start = le16_to_cpu(fltl->start_hi) << 16 | | ||
615 | le16_to_cpu(fltl->start_lo); | ||
616 | end: | ||
617 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start)); | ||
618 | return QLA_SUCCESS; | ||
619 | } | ||
620 | |||
621 | static void | ||
622 | qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr) | ||
623 | { | ||
624 | const char *loc, *locations[] = { "DEF", "FLT" }; | ||
625 | uint16_t *wptr; | ||
626 | uint16_t cnt, chksum; | ||
627 | uint32_t start; | ||
628 | struct qla_flt_header *flt; | ||
629 | struct qla_flt_region *region; | ||
630 | |||
631 | ha->flt_region_flt = flt_addr; | ||
632 | wptr = (uint16_t *)ha->request_ring; | ||
633 | flt = (struct qla_flt_header *)ha->request_ring; | ||
634 | region = (struct qla_flt_region *)&flt[1]; | ||
635 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, | ||
636 | flt_addr << 2, OPTROM_BURST_SIZE); | ||
637 | if (*wptr == __constant_cpu_to_le16(0xffff)) | ||
638 | goto no_flash_data; | ||
639 | if (flt->version != __constant_cpu_to_le16(1)) { | ||
640 | DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported FLT detected: " | ||
641 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
642 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
643 | le16_to_cpu(flt->checksum))); | ||
644 | goto no_flash_data; | ||
645 | } | ||
646 | |||
647 | cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; | ||
648 | for (chksum = 0; cnt; cnt--) | ||
649 | chksum += le16_to_cpu(*wptr++); | ||
650 | if (chksum) { | ||
651 | DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FLT detected: " | ||
652 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
653 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
654 | chksum)); | ||
655 | goto no_flash_data; | ||
656 | } | ||
657 | |||
658 | loc = locations[1]; | ||
659 | cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); | ||
660 | for ( ; cnt; cnt--, region++) { | ||
661 | /* Store addresses as DWORD offsets. */ | ||
662 | start = le32_to_cpu(region->start) >> 2; | ||
663 | |||
664 | DEBUG3(qla_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x " | ||
665 | "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start, | ||
666 | le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size))); | ||
667 | |||
668 | switch (le32_to_cpu(region->code)) { | ||
669 | case FLT_REG_FW: | ||
670 | ha->flt_region_fw = start; | ||
671 | break; | ||
672 | case FLT_REG_BOOT_CODE: | ||
673 | ha->flt_region_boot = start; | ||
674 | break; | ||
675 | case FLT_REG_VPD_0: | ||
676 | ha->flt_region_vpd_nvram = start; | ||
677 | break; | ||
678 | case FLT_REG_FDT: | ||
679 | ha->flt_region_fdt = start; | ||
680 | break; | ||
681 | case FLT_REG_HW_EVENT_0: | ||
682 | if (!PCI_FUNC(ha->pdev->devfn)) | ||
683 | ha->flt_region_hw_event = start; | ||
684 | break; | ||
685 | case FLT_REG_HW_EVENT_1: | ||
686 | if (PCI_FUNC(ha->pdev->devfn)) | ||
687 | ha->flt_region_hw_event = start; | ||
688 | break; | ||
689 | } | ||
690 | } | ||
691 | goto done; | ||
692 | |||
693 | no_flash_data: | ||
694 | /* Use hardcoded defaults. */ | ||
695 | loc = locations[0]; | ||
696 | ha->flt_region_fw = FA_RISC_CODE_ADDR; | ||
697 | ha->flt_region_boot = FA_BOOT_CODE_ADDR; | ||
698 | ha->flt_region_vpd_nvram = FA_VPD_NVRAM_ADDR; | ||
699 | ha->flt_region_fdt = IS_QLA24XX_TYPE(ha) ? FA_FLASH_DESCR_ADDR_24: | ||
700 | FA_FLASH_DESCR_ADDR; | ||
701 | ha->flt_region_hw_event = !PCI_FUNC(ha->pdev->devfn) ? | ||
702 | FA_HW_EVENT0_ADDR: FA_HW_EVENT1_ADDR; | ||
703 | done: | ||
704 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " | ||
705 | "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x.\n", loc, | ||
706 | ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram, | ||
707 | ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event)); | ||
708 | } | ||
709 | |||
710 | static void | ||
711 | qla2xxx_get_fdt_info(scsi_qla_host_t *ha) | ||
548 | { | 712 | { |
549 | #define FLASH_BLK_SIZE_32K 0x8000 | 713 | #define FLASH_BLK_SIZE_32K 0x8000 |
550 | #define FLASH_BLK_SIZE_64K 0x10000 | 714 | #define FLASH_BLK_SIZE_64K 0x10000 |
715 | const char *loc, *locations[] = { "MID", "FDT" }; | ||
551 | uint16_t cnt, chksum; | 716 | uint16_t cnt, chksum; |
552 | uint16_t *wptr; | 717 | uint16_t *wptr; |
553 | struct qla_fdt_layout *fdt; | 718 | struct qla_fdt_layout *fdt; |
554 | uint8_t man_id, flash_id; | 719 | uint8_t man_id, flash_id; |
555 | 720 | uint16_t mid, fid; | |
556 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
557 | return; | ||
558 | 721 | ||
559 | wptr = (uint16_t *)ha->request_ring; | 722 | wptr = (uint16_t *)ha->request_ring; |
560 | fdt = (struct qla_fdt_layout *)ha->request_ring; | 723 | fdt = (struct qla_fdt_layout *)ha->request_ring; |
561 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, | 724 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, |
562 | FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE); | 725 | ha->flt_region_fdt << 2, OPTROM_BURST_SIZE); |
563 | if (*wptr == __constant_cpu_to_le16(0xffff)) | 726 | if (*wptr == __constant_cpu_to_le16(0xffff)) |
564 | goto no_flash_data; | 727 | goto no_flash_data; |
565 | if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || | 728 | if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || |
@@ -577,7 +740,10 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) | |||
577 | goto no_flash_data; | 740 | goto no_flash_data; |
578 | } | 741 | } |
579 | 742 | ||
580 | ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f; | 743 | loc = locations[1]; |
744 | mid = le16_to_cpu(fdt->man_id); | ||
745 | fid = le16_to_cpu(fdt->id); | ||
746 | ha->fdt_odd_index = mid == 0x1f; | ||
581 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; | 747 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; |
582 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); | 748 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); |
583 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); | 749 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); |
@@ -588,16 +754,12 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) | |||
588 | flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd): | 754 | flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd): |
589 | flash_conf_to_access_addr(0x0336); | 755 | flash_conf_to_access_addr(0x0336); |
590 | } | 756 | } |
591 | 757 | goto done; | |
592 | DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x " | ||
593 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", | ||
594 | le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd, | ||
595 | ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd, | ||
596 | ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size)); | ||
597 | return; | ||
598 | |||
599 | no_flash_data: | 758 | no_flash_data: |
759 | loc = locations[0]; | ||
600 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); | 760 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); |
761 | mid = man_id; | ||
762 | fid = flash_id; | ||
601 | ha->fdt_wrt_disable = 0x9c; | 763 | ha->fdt_wrt_disable = 0x9c; |
602 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8); | 764 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8); |
603 | switch (man_id) { | 765 | switch (man_id) { |
@@ -625,14 +787,33 @@ no_flash_data: | |||
625 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; | 787 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; |
626 | break; | 788 | break; |
627 | } | 789 | } |
628 | 790 | done: | |
629 | DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x " | 791 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " |
630 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id, | 792 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid, |
631 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, | 793 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, |
632 | ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, | 794 | ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, |
633 | ha->fdt_block_size)); | 795 | ha->fdt_block_size)); |
634 | } | 796 | } |
635 | 797 | ||
798 | int | ||
799 | qla2xxx_get_flash_info(scsi_qla_host_t *ha) | ||
800 | { | ||
801 | int ret; | ||
802 | uint32_t flt_addr; | ||
803 | |||
804 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
805 | return QLA_SUCCESS; | ||
806 | |||
807 | ret = qla2xxx_find_flt_start(ha, &flt_addr); | ||
808 | if (ret != QLA_SUCCESS) | ||
809 | return ret; | ||
810 | |||
811 | qla2xxx_get_flt_info(ha, flt_addr); | ||
812 | qla2xxx_get_fdt_info(ha); | ||
813 | |||
814 | return QLA_SUCCESS; | ||
815 | } | ||
816 | |||
636 | static void | 817 | static void |
637 | qla24xx_unprotect_flash(scsi_qla_host_t *ha) | 818 | qla24xx_unprotect_flash(scsi_qla_host_t *ha) |
638 | { | 819 | { |
@@ -920,7 +1101,8 @@ qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
920 | dwptr = (uint32_t *)buf; | 1101 | dwptr = (uint32_t *)buf; |
921 | for (i = 0; i < bytes >> 2; i++, naddr++) | 1102 | for (i = 0; i < bytes >> 2; i++, naddr++) |
922 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | 1103 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, |
923 | flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr))); | 1104 | flash_data_to_access_addr(ha->flt_region_vpd_nvram | |
1105 | naddr))); | ||
924 | 1106 | ||
925 | return buf; | 1107 | return buf; |
926 | } | 1108 | } |
@@ -935,10 +1117,10 @@ qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
935 | dbuf = vmalloc(RMW_BUFFER_SIZE); | 1117 | dbuf = vmalloc(RMW_BUFFER_SIZE); |
936 | if (!dbuf) | 1118 | if (!dbuf) |
937 | return QLA_MEMORY_ALLOC_FAILED; | 1119 | return QLA_MEMORY_ALLOC_FAILED; |
938 | ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | 1120 | ha->isp_ops->read_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, |
939 | RMW_BUFFER_SIZE); | 1121 | RMW_BUFFER_SIZE); |
940 | memcpy(dbuf + (naddr << 2), buf, bytes); | 1122 | memcpy(dbuf + (naddr << 2), buf, bytes); |
941 | ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | 1123 | ha->isp_ops->write_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, |
942 | RMW_BUFFER_SIZE); | 1124 | RMW_BUFFER_SIZE); |
943 | vfree(dbuf); | 1125 | vfree(dbuf); |
944 | 1126 | ||
@@ -2166,7 +2348,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2166 | memset(dbyte, 0, 8); | 2348 | memset(dbyte, 0, 8); |
2167 | dcode = (uint16_t *)dbyte; | 2349 | dcode = (uint16_t *)dbyte; |
2168 | 2350 | ||
2169 | qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, | 2351 | qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10, |
2170 | 8); | 2352 | 8); |
2171 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", | 2353 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", |
2172 | __func__, ha->host_no)); | 2354 | __func__, ha->host_no)); |
@@ -2177,7 +2359,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2177 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 2359 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
2178 | dcode[3] == 0)) { | 2360 | dcode[3] == 0)) { |
2179 | DEBUG2(printk("%s(): Unrecognized fw revision at " | 2361 | DEBUG2(printk("%s(): Unrecognized fw revision at " |
2180 | "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); | 2362 | "%x.\n", __func__, ha->flt_region_fw * 4)); |
2181 | } else { | 2363 | } else { |
2182 | /* values are in big endian */ | 2364 | /* values are in big endian */ |
2183 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; | 2365 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; |
@@ -2212,7 +2394,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2212 | dcode = mbuf; | 2394 | dcode = mbuf; |
2213 | 2395 | ||
2214 | /* Begin with first PCI expansion ROM header. */ | 2396 | /* Begin with first PCI expansion ROM header. */ |
2215 | pcihdr = 0; | 2397 | pcihdr = ha->flt_region_boot; |
2216 | last_image = 1; | 2398 | last_image = 1; |
2217 | do { | 2399 | do { |
2218 | /* Verify PCI expansion ROM header. */ | 2400 | /* Verify PCI expansion ROM header. */ |
@@ -2282,7 +2464,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2282 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | 2464 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); |
2283 | dcode = mbuf; | 2465 | dcode = mbuf; |
2284 | 2466 | ||
2285 | qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); | 2467 | qla24xx_read_flash_data(ha, dcode, ha->flt_region_fw + 4, 4); |
2286 | for (i = 0; i < 4; i++) | 2468 | for (i = 0; i < 4; i++) |
2287 | dcode[i] = be32_to_cpu(dcode[i]); | 2469 | dcode[i] = be32_to_cpu(dcode[i]); |
2288 | 2470 | ||
@@ -2291,7 +2473,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2291 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 2473 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
2292 | dcode[3] == 0)) { | 2474 | dcode[3] == 0)) { |
2293 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", | 2475 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", |
2294 | __func__, FA_RISC_CODE_ADDR)); | 2476 | __func__, ha->flt_region_fw)); |
2295 | } else { | 2477 | } else { |
2296 | ha->fw_revision[0] = dcode[0]; | 2478 | ha->fw_revision[0] = dcode[0]; |
2297 | ha->fw_revision[1] = dcode[1]; | 2479 | ha->fw_revision[1] = dcode[1]; |
@@ -2355,7 +2537,7 @@ qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata) | |||
2355 | /* Locate first empty entry. */ | 2537 | /* Locate first empty entry. */ |
2356 | for (;;) { | 2538 | for (;;) { |
2357 | if (ha->hw_event_ptr >= | 2539 | if (ha->hw_event_ptr >= |
2358 | ha->hw_event_start + FA_HW_EVENT_SIZE) { | 2540 | ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { |
2359 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2541 | DEBUG2(qla_printk(KERN_WARNING, ha, |
2360 | "HW event -- Log Full!\n")); | 2542 | "HW event -- Log Full!\n")); |
2361 | return QLA_MEMORY_ALLOC_FAILED; | 2543 | return QLA_MEMORY_ALLOC_FAILED; |
@@ -2391,7 +2573,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2391 | int rval; | 2573 | int rval; |
2392 | uint32_t marker[2], fdata[4]; | 2574 | uint32_t marker[2], fdata[4]; |
2393 | 2575 | ||
2394 | if (ha->hw_event_start == 0) | 2576 | if (ha->flt_region_hw_event == 0) |
2395 | return QLA_FUNCTION_FAILED; | 2577 | return QLA_FUNCTION_FAILED; |
2396 | 2578 | ||
2397 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2579 | DEBUG2(qla_printk(KERN_WARNING, ha, |
@@ -2406,7 +2588,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2406 | QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER); | 2588 | QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER); |
2407 | 2589 | ||
2408 | /* Locate marker. */ | 2590 | /* Locate marker. */ |
2409 | ha->hw_event_ptr = ha->hw_event_start; | 2591 | ha->hw_event_ptr = ha->flt_region_hw_event; |
2410 | for (;;) { | 2592 | for (;;) { |
2411 | qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr, | 2593 | qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr, |
2412 | 4); | 2594 | 4); |
@@ -2415,7 +2597,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2415 | break; | 2597 | break; |
2416 | ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE; | 2598 | ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE; |
2417 | if (ha->hw_event_ptr >= | 2599 | if (ha->hw_event_ptr >= |
2418 | ha->hw_event_start + FA_HW_EVENT_SIZE) { | 2600 | ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { |
2419 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2601 | DEBUG2(qla_printk(KERN_WARNING, ha, |
2420 | "HW event -- Log Full!\n")); | 2602 | "HW event -- Log Full!\n")); |
2421 | return QLA_MEMORY_ALLOC_FAILED; | 2603 | return QLA_MEMORY_ALLOC_FAILED; |