diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 14:44:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 14:44:25 -0500 |
commit | 5f0b1437e0708772b6fecae5900c01c3b5f9b512 (patch) | |
tree | bcd923e305345178bc162ed8560d56a3af197224 /drivers/scsi/qla2xxx | |
parent | 574009c1a895aeeb85eaab29c235d75852b09eb8 (diff) | |
parent | 81b7bbd1932a04869d4c8635a75222dfc6089f96 (diff) |
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: (97 commits)
[SCSI] zfcp: removed wrong comment
[SCSI] zfcp: use of uninitialized variable
[SCSI] zfcp: Invalid locking order
[SCSI] aic79xx: use dma_get_required_mask()
[SCSI] aic79xx: fix bracket mismatch in unused macro
[SCSI] BusLogic: Replace 'boolean' by 'bool'
[SCSI] advansys: clean up warnings
[SCSI] 53c7xx: brackets fix in uncompiled code
[SCSI] nsp_cs: remove old scsi code
[SCSI] aic79xx: make ahd_match_scb() static
[SCSI] DAC960: kmalloc->kzalloc/Casting cleanups
[SCSI] scsi_kmap_atomic_sg(): check that local irqs are disabled
[SCSI] Buslogic: local_irq_disable() is redundant after local_irq_save()
[SCSI] aic94xx: update for v28 firmware
[SCSI] scsi_error: Fix lost EH commands
[SCSI] aic94xx: Add default bus reset handler
[SCSI] aic94xx: Remove TMF result code munging
[SCSI] libsas: Add an LU reset mechanism to the error handler
[SCSI] libsas: Don't BUG when connecting two expanders via wide port
[SCSI] st: fix Tape dies if wrong block size used, bug 7919
...
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 68 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 38 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 6 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 218 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 245 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 18 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 24 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 348 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 |
9 files changed, 745 insertions, 222 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 7b18a6c7b7eb..8081b637d97e 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -140,6 +140,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, | |||
140 | ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); | 140 | ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); |
141 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 141 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
142 | 142 | ||
143 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
144 | |||
143 | return (count); | 145 | return (count); |
144 | } | 146 | } |
145 | 147 | ||
@@ -653,6 +655,43 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, | |||
653 | return count; | 655 | return count; |
654 | } | 656 | } |
655 | 657 | ||
658 | static ssize_t | ||
659 | qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) | ||
660 | { | ||
661 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
662 | |||
663 | return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], | ||
664 | ha->bios_revision[0]); | ||
665 | } | ||
666 | |||
667 | static ssize_t | ||
668 | qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) | ||
669 | { | ||
670 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
671 | |||
672 | return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], | ||
673 | ha->efi_revision[0]); | ||
674 | } | ||
675 | |||
676 | static ssize_t | ||
677 | qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) | ||
678 | { | ||
679 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
680 | |||
681 | return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], | ||
682 | ha->fcode_revision[0]); | ||
683 | } | ||
684 | |||
685 | static ssize_t | ||
686 | qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf) | ||
687 | { | ||
688 | scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); | ||
689 | |||
690 | return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", | ||
691 | ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], | ||
692 | ha->fw_revision[3]); | ||
693 | } | ||
694 | |||
656 | static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, | 695 | static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, |
657 | NULL); | 696 | NULL); |
658 | static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); | 697 | static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); |
@@ -669,6 +708,14 @@ static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, | |||
669 | qla2x00_zio_timer_store); | 708 | qla2x00_zio_timer_store); |
670 | static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, | 709 | static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, |
671 | qla2x00_beacon_store); | 710 | qla2x00_beacon_store); |
711 | static CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO, | ||
712 | qla2x00_optrom_bios_version_show, NULL); | ||
713 | static CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO, | ||
714 | qla2x00_optrom_efi_version_show, NULL); | ||
715 | static CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO, | ||
716 | qla2x00_optrom_fcode_version_show, NULL); | ||
717 | static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO, | ||
718 | qla2x00_optrom_fw_version_show, NULL); | ||
672 | 719 | ||
673 | struct class_device_attribute *qla2x00_host_attrs[] = { | 720 | struct class_device_attribute *qla2x00_host_attrs[] = { |
674 | &class_device_attr_driver_version, | 721 | &class_device_attr_driver_version, |
@@ -683,6 +730,10 @@ struct class_device_attribute *qla2x00_host_attrs[] = { | |||
683 | &class_device_attr_zio, | 730 | &class_device_attr_zio, |
684 | &class_device_attr_zio_timer, | 731 | &class_device_attr_zio_timer, |
685 | &class_device_attr_beacon, | 732 | &class_device_attr_beacon, |
733 | &class_device_attr_optrom_bios_version, | ||
734 | &class_device_attr_optrom_efi_version, | ||
735 | &class_device_attr_optrom_fcode_version, | ||
736 | &class_device_attr_optrom_fw_version, | ||
686 | NULL, | 737 | NULL, |
687 | }; | 738 | }; |
688 | 739 | ||
@@ -836,21 +887,24 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
836 | link_stat_t stat_buf; | 887 | link_stat_t stat_buf; |
837 | struct fc_host_statistics *pfc_host_stat; | 888 | struct fc_host_statistics *pfc_host_stat; |
838 | 889 | ||
890 | rval = QLA_FUNCTION_FAILED; | ||
839 | pfc_host_stat = &ha->fc_host_stat; | 891 | pfc_host_stat = &ha->fc_host_stat; |
840 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); | 892 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); |
841 | 893 | ||
842 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 894 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { |
843 | rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, | 895 | rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, |
844 | sizeof(stat_buf) / 4, mb_stat); | 896 | sizeof(stat_buf) / 4, mb_stat); |
845 | } else { | 897 | } else if (atomic_read(&ha->loop_state) == LOOP_READY && |
898 | !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) && | ||
899 | !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) && | ||
900 | !ha->dpc_active) { | ||
901 | /* Must be in a 'READY' state for statistics retrieval. */ | ||
846 | rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, | 902 | rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, |
847 | mb_stat); | 903 | mb_stat); |
848 | } | 904 | } |
849 | if (rval != 0) { | 905 | |
850 | qla_printk(KERN_WARNING, ha, | 906 | if (rval != QLA_SUCCESS) |
851 | "Unable to retrieve host statistics (%d).\n", mb_stat[0]); | 907 | goto done; |
852 | return pfc_host_stat; | ||
853 | } | ||
854 | 908 | ||
855 | pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt; | 909 | pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt; |
856 | pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt; | 910 | pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt; |
@@ -858,7 +912,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
858 | pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt; | 912 | pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt; |
859 | pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt; | 913 | pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt; |
860 | pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt; | 914 | pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt; |
861 | 915 | done: | |
862 | return pfc_host_stat; | 916 | return pfc_host_stat; |
863 | } | 917 | } |
864 | 918 | ||
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 2c10130d9e03..05f4f2a378eb 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2045,6 +2045,29 @@ struct isp_operations { | |||
2045 | uint32_t, uint32_t); | 2045 | uint32_t, uint32_t); |
2046 | int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t, | 2046 | int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t, |
2047 | uint32_t); | 2047 | uint32_t); |
2048 | |||
2049 | int (*get_flash_version) (struct scsi_qla_host *, void *); | ||
2050 | }; | ||
2051 | |||
2052 | /* MSI-X Support *************************************************************/ | ||
2053 | |||
2054 | #define QLA_MSIX_CHIP_REV_24XX 3 | ||
2055 | #define QLA_MSIX_FW_MODE(m) (((m) & (BIT_7|BIT_8|BIT_9)) >> 7) | ||
2056 | #define QLA_MSIX_FW_MODE_1(m) (QLA_MSIX_FW_MODE(m) == 1) | ||
2057 | |||
2058 | #define QLA_MSIX_DEFAULT 0x00 | ||
2059 | #define QLA_MSIX_RSP_Q 0x01 | ||
2060 | |||
2061 | #define QLA_MSIX_ENTRIES 2 | ||
2062 | #define QLA_MIDX_DEFAULT 0 | ||
2063 | #define QLA_MIDX_RSP_Q 1 | ||
2064 | |||
2065 | struct scsi_qla_host; | ||
2066 | |||
2067 | struct qla_msix_entry { | ||
2068 | int have_irq; | ||
2069 | uint16_t msix_vector; | ||
2070 | uint16_t msix_entry; | ||
2048 | }; | 2071 | }; |
2049 | 2072 | ||
2050 | /* | 2073 | /* |
@@ -2077,6 +2100,7 @@ typedef struct scsi_qla_host { | |||
2077 | uint32_t enable_lip_full_login :1; | 2100 | uint32_t enable_lip_full_login :1; |
2078 | uint32_t enable_target_reset :1; | 2101 | uint32_t enable_target_reset :1; |
2079 | uint32_t enable_led_scheme :1; | 2102 | uint32_t enable_led_scheme :1; |
2103 | uint32_t inta_enabled :1; | ||
2080 | uint32_t msi_enabled :1; | 2104 | uint32_t msi_enabled :1; |
2081 | uint32_t msix_enabled :1; | 2105 | uint32_t msix_enabled :1; |
2082 | uint32_t disable_serdes :1; | 2106 | uint32_t disable_serdes :1; |
@@ -2316,8 +2340,6 @@ typedef struct scsi_qla_host { | |||
2316 | #define MBX_INTR_WAIT 2 | 2340 | #define MBX_INTR_WAIT 2 |
2317 | #define MBX_UPDATE_FLASH_ACTIVE 3 | 2341 | #define MBX_UPDATE_FLASH_ACTIVE 3 |
2318 | 2342 | ||
2319 | spinlock_t mbx_reg_lock; /* Mbx Cmd Register Lock */ | ||
2320 | |||
2321 | struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ | 2343 | struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ |
2322 | struct semaphore mbx_intr_sem; /* Used for completion notification */ | 2344 | struct semaphore mbx_intr_sem; /* Used for completion notification */ |
2323 | 2345 | ||
@@ -2358,6 +2380,7 @@ typedef struct scsi_qla_host { | |||
2358 | 2380 | ||
2359 | uint8_t host_str[16]; | 2381 | uint8_t host_str[16]; |
2360 | uint32_t pci_attr; | 2382 | uint32_t pci_attr; |
2383 | uint16_t chip_revision; | ||
2361 | 2384 | ||
2362 | uint16_t product_id[4]; | 2385 | uint16_t product_id[4]; |
2363 | 2386 | ||
@@ -2379,6 +2402,15 @@ typedef struct scsi_qla_host { | |||
2379 | #define QLA_SREADING 1 | 2402 | #define QLA_SREADING 1 |
2380 | #define QLA_SWRITING 2 | 2403 | #define QLA_SWRITING 2 |
2381 | 2404 | ||
2405 | /* PCI expansion ROM image information. */ | ||
2406 | #define ROM_CODE_TYPE_BIOS 0 | ||
2407 | #define ROM_CODE_TYPE_FCODE 1 | ||
2408 | #define ROM_CODE_TYPE_EFI 3 | ||
2409 | uint8_t bios_revision[2]; | ||
2410 | uint8_t efi_revision[2]; | ||
2411 | uint8_t fcode_revision[16]; | ||
2412 | uint32_t fw_revision[4]; | ||
2413 | |||
2382 | /* Needed for BEACON */ | 2414 | /* Needed for BEACON */ |
2383 | uint16_t beacon_blink_led; | 2415 | uint16_t beacon_blink_led; |
2384 | uint8_t beacon_color_state; | 2416 | uint8_t beacon_color_state; |
@@ -2391,6 +2423,8 @@ typedef struct scsi_qla_host { | |||
2391 | uint16_t zio_mode; | 2423 | uint16_t zio_mode; |
2392 | uint16_t zio_timer; | 2424 | uint16_t zio_timer; |
2393 | struct fc_host_statistics fc_host_stat; | 2425 | struct fc_host_statistics fc_host_stat; |
2426 | |||
2427 | struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES]; | ||
2394 | } scsi_qla_host_t; | 2428 | } scsi_qla_host_t; |
2395 | 2429 | ||
2396 | 2430 | ||
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index e4dd12f4b80e..74544ae4b0e2 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -224,6 +224,9 @@ extern irqreturn_t qla24xx_intr_handler(int, void *); | |||
224 | extern void qla2x00_process_response_queue(struct scsi_qla_host *); | 224 | extern void qla2x00_process_response_queue(struct scsi_qla_host *); |
225 | extern void qla24xx_process_response_queue(struct scsi_qla_host *); | 225 | extern void qla24xx_process_response_queue(struct scsi_qla_host *); |
226 | 226 | ||
227 | extern int qla2x00_request_irqs(scsi_qla_host_t *); | ||
228 | extern void qla2x00_free_irqs(scsi_qla_host_t *); | ||
229 | |||
227 | /* | 230 | /* |
228 | * Global Function Prototypes in qla_sup.c source file. | 231 | * Global Function Prototypes in qla_sup.c source file. |
229 | */ | 232 | */ |
@@ -259,6 +262,9 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, | |||
259 | extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, | 262 | extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, |
260 | uint32_t, uint32_t); | 263 | uint32_t, uint32_t); |
261 | 264 | ||
265 | extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); | ||
266 | extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); | ||
267 | |||
262 | /* | 268 | /* |
263 | * Global Function Prototypes in qla_dbg.c source file. | 269 | * Global Function Prototypes in qla_dbg.c source file. |
264 | */ | 270 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b3dac26ddba3..98c01cd5e1a8 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -65,7 +65,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
65 | ha->flags.reset_active = 0; | 65 | ha->flags.reset_active = 0; |
66 | atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); | 66 | atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); |
67 | atomic_set(&ha->loop_state, LOOP_DOWN); | 67 | atomic_set(&ha->loop_state, LOOP_DOWN); |
68 | ha->device_flags = 0; | 68 | ha->device_flags = DFLG_NO_CABLE; |
69 | ha->dpc_flags = 0; | 69 | ha->dpc_flags = 0; |
70 | ha->flags.management_server_logged_in = 0; | 70 | ha->flags.management_server_logged_in = 0; |
71 | ha->marker_needed = 0; | 71 | ha->marker_needed = 0; |
@@ -77,16 +77,23 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
77 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); | 77 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); |
78 | rval = ha->isp_ops.pci_config(ha); | 78 | rval = ha->isp_ops.pci_config(ha); |
79 | if (rval) { | 79 | if (rval) { |
80 | DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n", | 80 | DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", |
81 | ha->host_no)); | 81 | ha->host_no)); |
82 | return (rval); | 82 | return (rval); |
83 | } | 83 | } |
84 | 84 | ||
85 | ha->isp_ops.reset_chip(ha); | 85 | ha->isp_ops.reset_chip(ha); |
86 | 86 | ||
87 | ha->isp_ops.get_flash_version(ha, ha->request_ring); | ||
88 | |||
87 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); | 89 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); |
88 | 90 | ||
89 | ha->isp_ops.nvram_config(ha); | 91 | rval = ha->isp_ops.nvram_config(ha); |
92 | if (rval) { | ||
93 | DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n", | ||
94 | ha->host_no)); | ||
95 | return rval; | ||
96 | } | ||
90 | 97 | ||
91 | if (ha->flags.disable_serdes) { | 98 | if (ha->flags.disable_serdes) { |
92 | /* Mask HBA via NVRAM settings? */ | 99 | /* Mask HBA via NVRAM settings? */ |
@@ -293,6 +300,8 @@ qla24xx_pci_config(scsi_qla_host_t *ha) | |||
293 | d &= ~PCI_ROM_ADDRESS_ENABLE; | 300 | d &= ~PCI_ROM_ADDRESS_ENABLE; |
294 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); | 301 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); |
295 | 302 | ||
303 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision); | ||
304 | |||
296 | /* Get PCI bus information. */ | 305 | /* Get PCI bus information. */ |
297 | spin_lock_irqsave(&ha->hardware_lock, flags); | 306 | spin_lock_irqsave(&ha->hardware_lock, flags); |
298 | ha->pci_attr = RD_REG_DWORD(®->ctrl_status); | 307 | ha->pci_attr = RD_REG_DWORD(®->ctrl_status); |
@@ -1351,6 +1360,39 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1351 | return(rval); | 1360 | return(rval); |
1352 | } | 1361 | } |
1353 | 1362 | ||
1363 | static inline void | ||
1364 | qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def) | ||
1365 | { | ||
1366 | char *st, *en; | ||
1367 | uint16_t index; | ||
1368 | |||
1369 | if (memcmp(model, BINZERO, len) != 0) { | ||
1370 | strncpy(ha->model_number, model, len); | ||
1371 | st = en = ha->model_number; | ||
1372 | en += len - 1; | ||
1373 | while (en > st) { | ||
1374 | if (*en != 0x20 && *en != 0x00) | ||
1375 | break; | ||
1376 | *en-- = '\0'; | ||
1377 | } | ||
1378 | |||
1379 | index = (ha->pdev->subsystem_device & 0xff); | ||
1380 | if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && | ||
1381 | index < QLA_MODEL_NAMES) | ||
1382 | ha->model_desc = qla2x00_model_name[index * 2 + 1]; | ||
1383 | } else { | ||
1384 | index = (ha->pdev->subsystem_device & 0xff); | ||
1385 | if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && | ||
1386 | index < QLA_MODEL_NAMES) { | ||
1387 | strcpy(ha->model_number, | ||
1388 | qla2x00_model_name[index * 2]); | ||
1389 | ha->model_desc = qla2x00_model_name[index * 2 + 1]; | ||
1390 | } else { | ||
1391 | strcpy(ha->model_number, def); | ||
1392 | } | ||
1393 | } | ||
1394 | } | ||
1395 | |||
1354 | /* | 1396 | /* |
1355 | * NVRAM configuration for ISP 2xxx | 1397 | * NVRAM configuration for ISP 2xxx |
1356 | * | 1398 | * |
@@ -1367,7 +1409,6 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1367 | int | 1409 | int |
1368 | qla2x00_nvram_config(scsi_qla_host_t *ha) | 1410 | qla2x00_nvram_config(scsi_qla_host_t *ha) |
1369 | { | 1411 | { |
1370 | int rval; | ||
1371 | uint8_t chksum = 0; | 1412 | uint8_t chksum = 0; |
1372 | uint16_t cnt; | 1413 | uint16_t cnt; |
1373 | uint8_t *dptr1, *dptr2; | 1414 | uint8_t *dptr1, *dptr2; |
@@ -1376,8 +1417,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1376 | uint8_t *ptr = (uint8_t *)ha->request_ring; | 1417 | uint8_t *ptr = (uint8_t *)ha->request_ring; |
1377 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 1418 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
1378 | 1419 | ||
1379 | rval = QLA_SUCCESS; | ||
1380 | |||
1381 | /* Determine NVRAM starting address. */ | 1420 | /* Determine NVRAM starting address. */ |
1382 | ha->nvram_size = sizeof(nvram_t); | 1421 | ha->nvram_size = sizeof(nvram_t); |
1383 | ha->nvram_base = 0; | 1422 | ha->nvram_base = 0; |
@@ -1401,55 +1440,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1401 | qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " | 1440 | qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " |
1402 | "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], | 1441 | "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], |
1403 | nv->nvram_version); | 1442 | nv->nvram_version); |
1404 | qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " | 1443 | return QLA_FUNCTION_FAILED; |
1405 | "invalid -- WWPN) defaults.\n"); | ||
1406 | |||
1407 | /* | ||
1408 | * Set default initialization control block. | ||
1409 | */ | ||
1410 | memset(nv, 0, ha->nvram_size); | ||
1411 | nv->parameter_block_version = ICB_VERSION; | ||
1412 | |||
1413 | if (IS_QLA23XX(ha)) { | ||
1414 | nv->firmware_options[0] = BIT_2 | BIT_1; | ||
1415 | nv->firmware_options[1] = BIT_7 | BIT_5; | ||
1416 | nv->add_firmware_options[0] = BIT_5; | ||
1417 | nv->add_firmware_options[1] = BIT_5 | BIT_4; | ||
1418 | nv->frame_payload_size = __constant_cpu_to_le16(2048); | ||
1419 | nv->special_options[1] = BIT_7; | ||
1420 | } else if (IS_QLA2200(ha)) { | ||
1421 | nv->firmware_options[0] = BIT_2 | BIT_1; | ||
1422 | nv->firmware_options[1] = BIT_7 | BIT_5; | ||
1423 | nv->add_firmware_options[0] = BIT_5; | ||
1424 | nv->add_firmware_options[1] = BIT_5 | BIT_4; | ||
1425 | nv->frame_payload_size = __constant_cpu_to_le16(1024); | ||
1426 | } else if (IS_QLA2100(ha)) { | ||
1427 | nv->firmware_options[0] = BIT_3 | BIT_1; | ||
1428 | nv->firmware_options[1] = BIT_5; | ||
1429 | nv->frame_payload_size = __constant_cpu_to_le16(1024); | ||
1430 | } | ||
1431 | |||
1432 | nv->max_iocb_allocation = __constant_cpu_to_le16(256); | ||
1433 | nv->execution_throttle = __constant_cpu_to_le16(16); | ||
1434 | nv->retry_count = 8; | ||
1435 | nv->retry_delay = 1; | ||
1436 | |||
1437 | nv->port_name[0] = 33; | ||
1438 | nv->port_name[3] = 224; | ||
1439 | nv->port_name[4] = 139; | ||
1440 | |||
1441 | nv->login_timeout = 4; | ||
1442 | |||
1443 | /* | ||
1444 | * Set default host adapter parameters | ||
1445 | */ | ||
1446 | nv->host_p[1] = BIT_2; | ||
1447 | nv->reset_delay = 5; | ||
1448 | nv->port_down_retry_count = 8; | ||
1449 | nv->max_luns_per_target = __constant_cpu_to_le16(8); | ||
1450 | nv->link_down_timeout = 60; | ||
1451 | |||
1452 | rval = 1; | ||
1453 | } | 1444 | } |
1454 | 1445 | ||
1455 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) | 1446 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) |
@@ -1489,33 +1480,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1489 | strcpy(ha->model_number, "QLA2300"); | 1480 | strcpy(ha->model_number, "QLA2300"); |
1490 | } | 1481 | } |
1491 | } else { | 1482 | } else { |
1492 | if (rval == 0 && | 1483 | qla2x00_set_model_info(ha, nv->model_number, |
1493 | memcmp(nv->model_number, BINZERO, | 1484 | sizeof(nv->model_number), "QLA23xx"); |
1494 | sizeof(nv->model_number)) != 0) { | ||
1495 | char *st, *en; | ||
1496 | |||
1497 | strncpy(ha->model_number, nv->model_number, | ||
1498 | sizeof(nv->model_number)); | ||
1499 | st = en = ha->model_number; | ||
1500 | en += sizeof(nv->model_number) - 1; | ||
1501 | while (en > st) { | ||
1502 | if (*en != 0x20 && *en != 0x00) | ||
1503 | break; | ||
1504 | *en-- = '\0'; | ||
1505 | } | ||
1506 | } else { | ||
1507 | uint16_t index; | ||
1508 | |||
1509 | index = (ha->pdev->subsystem_device & 0xff); | ||
1510 | if (index < QLA_MODEL_NAMES) { | ||
1511 | strcpy(ha->model_number, | ||
1512 | qla2x00_model_name[index * 2]); | ||
1513 | ha->model_desc = | ||
1514 | qla2x00_model_name[index * 2 + 1]; | ||
1515 | } else { | ||
1516 | strcpy(ha->model_number, "QLA23xx"); | ||
1517 | } | ||
1518 | } | ||
1519 | } | 1485 | } |
1520 | } else if (IS_QLA2200(ha)) { | 1486 | } else if (IS_QLA2200(ha)) { |
1521 | nv->firmware_options[0] |= BIT_2; | 1487 | nv->firmware_options[0] |= BIT_2; |
@@ -1687,11 +1653,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1687 | } | 1653 | } |
1688 | } | 1654 | } |
1689 | 1655 | ||
1690 | if (rval) { | 1656 | return QLA_SUCCESS; |
1691 | DEBUG2_3(printk(KERN_WARNING | ||
1692 | "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); | ||
1693 | } | ||
1694 | return (rval); | ||
1695 | } | 1657 | } |
1696 | 1658 | ||
1697 | static void | 1659 | static void |
@@ -3107,7 +3069,11 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
3107 | } | 3069 | } |
3108 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 3070 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
3109 | 3071 | ||
3110 | ha->isp_ops.nvram_config(ha); | 3072 | ha->isp_ops.get_flash_version(ha, ha->request_ring); |
3073 | |||
3074 | rval = ha->isp_ops.nvram_config(ha); | ||
3075 | if (rval) | ||
3076 | goto isp_abort_retry; | ||
3111 | 3077 | ||
3112 | if (!qla2x00_restart_isp(ha)) { | 3078 | if (!qla2x00_restart_isp(ha)) { |
3113 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 3079 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
@@ -3137,6 +3103,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
3137 | } | 3103 | } |
3138 | } | 3104 | } |
3139 | } else { /* failed the ISP abort */ | 3105 | } else { /* failed the ISP abort */ |
3106 | isp_abort_retry: | ||
3140 | ha->flags.online = 1; | 3107 | ha->flags.online = 1; |
3141 | if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { | 3108 | if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { |
3142 | if (ha->isp_abort_cnt == 0) { | 3109 | if (ha->isp_abort_cnt == 0) { |
@@ -3326,7 +3293,6 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) | |||
3326 | int | 3293 | int |
3327 | qla24xx_nvram_config(scsi_qla_host_t *ha) | 3294 | qla24xx_nvram_config(scsi_qla_host_t *ha) |
3328 | { | 3295 | { |
3329 | int rval; | ||
3330 | struct init_cb_24xx *icb; | 3296 | struct init_cb_24xx *icb; |
3331 | struct nvram_24xx *nv; | 3297 | struct nvram_24xx *nv; |
3332 | uint32_t *dptr; | 3298 | uint32_t *dptr; |
@@ -3334,7 +3300,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3334 | uint32_t chksum; | 3300 | uint32_t chksum; |
3335 | uint16_t cnt; | 3301 | uint16_t cnt; |
3336 | 3302 | ||
3337 | rval = QLA_SUCCESS; | ||
3338 | icb = (struct init_cb_24xx *)ha->init_cb; | 3303 | icb = (struct init_cb_24xx *)ha->init_cb; |
3339 | nv = (struct nvram_24xx *)ha->request_ring; | 3304 | nv = (struct nvram_24xx *)ha->request_ring; |
3340 | 3305 | ||
@@ -3367,51 +3332,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3367 | qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " | 3332 | qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " |
3368 | "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], | 3333 | "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], |
3369 | le16_to_cpu(nv->nvram_version)); | 3334 | le16_to_cpu(nv->nvram_version)); |
3370 | qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " | 3335 | return QLA_FUNCTION_FAILED; |
3371 | "invalid -- WWPN) defaults.\n"); | ||
3372 | |||
3373 | /* | ||
3374 | * Set default initialization control block. | ||
3375 | */ | ||
3376 | memset(nv, 0, ha->nvram_size); | ||
3377 | nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); | ||
3378 | nv->version = __constant_cpu_to_le16(ICB_VERSION); | ||
3379 | nv->frame_payload_size = __constant_cpu_to_le16(2048); | ||
3380 | nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); | ||
3381 | nv->exchange_count = __constant_cpu_to_le16(0); | ||
3382 | nv->hard_address = __constant_cpu_to_le16(124); | ||
3383 | nv->port_name[0] = 0x21; | ||
3384 | nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); | ||
3385 | nv->port_name[2] = 0x00; | ||
3386 | nv->port_name[3] = 0xe0; | ||
3387 | nv->port_name[4] = 0x8b; | ||
3388 | nv->port_name[5] = 0x1c; | ||
3389 | nv->port_name[6] = 0x55; | ||
3390 | nv->port_name[7] = 0x86; | ||
3391 | nv->node_name[0] = 0x20; | ||
3392 | nv->node_name[1] = 0x00; | ||
3393 | nv->node_name[2] = 0x00; | ||
3394 | nv->node_name[3] = 0xe0; | ||
3395 | nv->node_name[4] = 0x8b; | ||
3396 | nv->node_name[5] = 0x1c; | ||
3397 | nv->node_name[6] = 0x55; | ||
3398 | nv->node_name[7] = 0x86; | ||
3399 | nv->login_retry_count = __constant_cpu_to_le16(8); | ||
3400 | nv->interrupt_delay_timer = __constant_cpu_to_le16(0); | ||
3401 | nv->login_timeout = __constant_cpu_to_le16(0); | ||
3402 | nv->firmware_options_1 = | ||
3403 | __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); | ||
3404 | nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); | ||
3405 | nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); | ||
3406 | nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); | ||
3407 | nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); | ||
3408 | nv->efi_parameters = __constant_cpu_to_le32(0); | ||
3409 | nv->reset_delay = 5; | ||
3410 | nv->max_luns_per_target = __constant_cpu_to_le16(128); | ||
3411 | nv->port_down_retry_count = __constant_cpu_to_le16(30); | ||
3412 | nv->link_down_timeout = __constant_cpu_to_le16(30); | ||
3413 | |||
3414 | rval = 1; | ||
3415 | } | 3336 | } |
3416 | 3337 | ||
3417 | /* Reset Initialization control block */ | 3338 | /* Reset Initialization control block */ |
@@ -3438,25 +3359,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3438 | /* | 3359 | /* |
3439 | * Setup driver NVRAM options. | 3360 | * Setup driver NVRAM options. |
3440 | */ | 3361 | */ |
3441 | if (memcmp(nv->model_name, BINZERO, sizeof(nv->model_name)) != 0) { | 3362 | qla2x00_set_model_info(ha, nv->model_name, sizeof(nv->model_name), |
3442 | char *st, *en; | 3363 | "QLA2462"); |
3443 | uint16_t index; | ||
3444 | |||
3445 | strncpy(ha->model_number, nv->model_name, | ||
3446 | sizeof(nv->model_name)); | ||
3447 | st = en = ha->model_number; | ||
3448 | en += sizeof(nv->model_name) - 1; | ||
3449 | while (en > st) { | ||
3450 | if (*en != 0x20 && *en != 0x00) | ||
3451 | break; | ||
3452 | *en-- = '\0'; | ||
3453 | } | ||
3454 | |||
3455 | index = (ha->pdev->subsystem_device & 0xff); | ||
3456 | if (index < QLA_MODEL_NAMES) | ||
3457 | ha->model_desc = qla2x00_model_name[index * 2 + 1]; | ||
3458 | } else | ||
3459 | strcpy(ha->model_number, "QLA2462"); | ||
3460 | 3364 | ||
3461 | /* Use alternate WWN? */ | 3365 | /* Use alternate WWN? */ |
3462 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { | 3366 | if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { |
@@ -3575,11 +3479,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3575 | ha->flags.process_response_queue = 1; | 3479 | ha->flags.process_response_queue = 1; |
3576 | } | 3480 | } |
3577 | 3481 | ||
3578 | if (rval) { | 3482 | return QLA_SUCCESS; |
3579 | DEBUG2_3(printk(KERN_WARNING | ||
3580 | "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); | ||
3581 | } | ||
3582 | return (rval); | ||
3583 | } | 3483 | } |
3584 | 3484 | ||
3585 | static int | 3485 | static int |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 39fd17b05be5..d4885616cd39 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -86,12 +86,8 @@ qla2100_intr_handler(int irq, void *dev_id) | |||
86 | 86 | ||
87 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | 87 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && |
88 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | 88 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { |
89 | spin_lock_irqsave(&ha->mbx_reg_lock, flags); | ||
90 | |||
91 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 89 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
92 | up(&ha->mbx_intr_sem); | 90 | up(&ha->mbx_intr_sem); |
93 | |||
94 | spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); | ||
95 | } | 91 | } |
96 | 92 | ||
97 | return (IRQ_HANDLED); | 93 | return (IRQ_HANDLED); |
@@ -199,12 +195,8 @@ qla2300_intr_handler(int irq, void *dev_id) | |||
199 | 195 | ||
200 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | 196 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && |
201 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | 197 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { |
202 | spin_lock_irqsave(&ha->mbx_reg_lock, flags); | ||
203 | |||
204 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 198 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
205 | up(&ha->mbx_intr_sem); | 199 | up(&ha->mbx_intr_sem); |
206 | |||
207 | spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); | ||
208 | } | 200 | } |
209 | 201 | ||
210 | return (IRQ_HANDLED); | 202 | return (IRQ_HANDLED); |
@@ -654,10 +646,8 @@ qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp) | |||
654 | fcport->last_queue_full + ql2xqfullrampup * HZ)) | 646 | fcport->last_queue_full + ql2xqfullrampup * HZ)) |
655 | return; | 647 | return; |
656 | 648 | ||
657 | spin_unlock_irq(&ha->hardware_lock); | ||
658 | starget_for_each_device(sdev->sdev_target, fcport, | 649 | starget_for_each_device(sdev->sdev_target, fcport, |
659 | qla2x00_adjust_sdev_qdepth_up); | 650 | qla2x00_adjust_sdev_qdepth_up); |
660 | spin_lock_irq(&ha->hardware_lock); | ||
661 | } | 651 | } |
662 | 652 | ||
663 | /** | 653 | /** |
@@ -927,10 +917,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
927 | 917 | ||
928 | /* Adjust queue depth for all luns on the port. */ | 918 | /* Adjust queue depth for all luns on the port. */ |
929 | fcport->last_queue_full = jiffies; | 919 | fcport->last_queue_full = jiffies; |
930 | spin_unlock_irq(&ha->hardware_lock); | ||
931 | starget_for_each_device(cp->device->sdev_target, | 920 | starget_for_each_device(cp->device->sdev_target, |
932 | fcport, qla2x00_adjust_sdev_qdepth_down); | 921 | fcport, qla2x00_adjust_sdev_qdepth_down); |
933 | spin_lock_irq(&ha->hardware_lock); | ||
934 | break; | 922 | break; |
935 | } | 923 | } |
936 | if (lscsi_status != SS_CHECK_CONDITION) | 924 | if (lscsi_status != SS_CHECK_CONDITION) |
@@ -995,6 +983,22 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
995 | if (lscsi_status != 0) { | 983 | if (lscsi_status != 0) { |
996 | cp->result = DID_OK << 16 | lscsi_status; | 984 | cp->result = DID_OK << 16 | lscsi_status; |
997 | 985 | ||
986 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { | ||
987 | DEBUG2(printk(KERN_INFO | ||
988 | "scsi(%ld): QUEUE FULL status detected " | ||
989 | "0x%x-0x%x.\n", ha->host_no, comp_status, | ||
990 | scsi_status)); | ||
991 | |||
992 | /* | ||
993 | * Adjust queue depth for all luns on the | ||
994 | * port. | ||
995 | */ | ||
996 | fcport->last_queue_full = jiffies; | ||
997 | starget_for_each_device( | ||
998 | cp->device->sdev_target, fcport, | ||
999 | qla2x00_adjust_sdev_qdepth_down); | ||
1000 | break; | ||
1001 | } | ||
998 | if (lscsi_status != SS_CHECK_CONDITION) | 1002 | if (lscsi_status != SS_CHECK_CONDITION) |
999 | break; | 1003 | break; |
1000 | 1004 | ||
@@ -1482,12 +1486,8 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
1482 | 1486 | ||
1483 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | 1487 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && |
1484 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | 1488 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { |
1485 | spin_lock_irqsave(&ha->mbx_reg_lock, flags); | ||
1486 | |||
1487 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 1489 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
1488 | up(&ha->mbx_intr_sem); | 1490 | up(&ha->mbx_intr_sem); |
1489 | |||
1490 | spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); | ||
1491 | } | 1491 | } |
1492 | 1492 | ||
1493 | return IRQ_HANDLED; | 1493 | return IRQ_HANDLED; |
@@ -1536,3 +1536,216 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt) | |||
1536 | qla2x00_sp_compl(ha, sp); | 1536 | qla2x00_sp_compl(ha, sp); |
1537 | } | 1537 | } |
1538 | 1538 | ||
1539 | static irqreturn_t | ||
1540 | qla24xx_msix_rsp_q(int irq, void *dev_id) | ||
1541 | { | ||
1542 | scsi_qla_host_t *ha; | ||
1543 | struct device_reg_24xx __iomem *reg; | ||
1544 | unsigned long flags; | ||
1545 | |||
1546 | ha = dev_id; | ||
1547 | reg = &ha->iobase->isp24; | ||
1548 | |||
1549 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1550 | |||
1551 | qla24xx_process_response_queue(ha); | ||
1552 | |||
1553 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | ||
1554 | RD_REG_DWORD_RELAXED(®->hccr); | ||
1555 | |||
1556 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1557 | |||
1558 | return IRQ_HANDLED; | ||
1559 | } | ||
1560 | |||
1561 | static irqreturn_t | ||
1562 | qla24xx_msix_default(int irq, void *dev_id) | ||
1563 | { | ||
1564 | scsi_qla_host_t *ha; | ||
1565 | struct device_reg_24xx __iomem *reg; | ||
1566 | int status; | ||
1567 | unsigned long flags; | ||
1568 | unsigned long iter; | ||
1569 | uint32_t stat; | ||
1570 | uint32_t hccr; | ||
1571 | uint16_t mb[4]; | ||
1572 | |||
1573 | ha = dev_id; | ||
1574 | reg = &ha->iobase->isp24; | ||
1575 | status = 0; | ||
1576 | |||
1577 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1578 | for (iter = 50; iter--; ) { | ||
1579 | stat = RD_REG_DWORD(®->host_status); | ||
1580 | if (stat & HSRX_RISC_PAUSED) { | ||
1581 | hccr = RD_REG_DWORD(®->hccr); | ||
1582 | |||
1583 | qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " | ||
1584 | "Dumping firmware!\n", hccr); | ||
1585 | ha->isp_ops.fw_dump(ha, 1); | ||
1586 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
1587 | break; | ||
1588 | } else if ((stat & HSRX_RISC_INT) == 0) | ||
1589 | break; | ||
1590 | |||
1591 | switch (stat & 0xff) { | ||
1592 | case 0x1: | ||
1593 | case 0x2: | ||
1594 | case 0x10: | ||
1595 | case 0x11: | ||
1596 | qla24xx_mbx_completion(ha, MSW(stat)); | ||
1597 | status |= MBX_INTERRUPT; | ||
1598 | |||
1599 | break; | ||
1600 | case 0x12: | ||
1601 | mb[0] = MSW(stat); | ||
1602 | mb[1] = RD_REG_WORD(®->mailbox1); | ||
1603 | mb[2] = RD_REG_WORD(®->mailbox2); | ||
1604 | mb[3] = RD_REG_WORD(®->mailbox3); | ||
1605 | qla2x00_async_event(ha, mb); | ||
1606 | break; | ||
1607 | case 0x13: | ||
1608 | qla24xx_process_response_queue(ha); | ||
1609 | break; | ||
1610 | default: | ||
1611 | DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " | ||
1612 | "(%d).\n", | ||
1613 | ha->host_no, stat & 0xff)); | ||
1614 | break; | ||
1615 | } | ||
1616 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | ||
1617 | RD_REG_DWORD_RELAXED(®->hccr); | ||
1618 | } | ||
1619 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1620 | |||
1621 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | ||
1622 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | ||
1623 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | ||
1624 | up(&ha->mbx_intr_sem); | ||
1625 | } | ||
1626 | |||
1627 | return IRQ_HANDLED; | ||
1628 | } | ||
1629 | |||
1630 | /* Interrupt handling helpers. */ | ||
1631 | |||
1632 | struct qla_init_msix_entry { | ||
1633 | uint16_t entry; | ||
1634 | uint16_t index; | ||
1635 | const char *name; | ||
1636 | irqreturn_t (*handler)(int, void *); | ||
1637 | }; | ||
1638 | |||
1639 | static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = { | ||
1640 | { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT, | ||
1641 | "qla2xxx (default)", qla24xx_msix_default }, | ||
1642 | |||
1643 | { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q, | ||
1644 | "qla2xxx (rsp_q)", qla24xx_msix_rsp_q }, | ||
1645 | }; | ||
1646 | |||
1647 | static void | ||
1648 | qla24xx_disable_msix(scsi_qla_host_t *ha) | ||
1649 | { | ||
1650 | int i; | ||
1651 | struct qla_msix_entry *qentry; | ||
1652 | |||
1653 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) { | ||
1654 | qentry = &ha->msix_entries[imsix_entries[i].index]; | ||
1655 | if (qentry->have_irq) | ||
1656 | free_irq(qentry->msix_vector, ha); | ||
1657 | } | ||
1658 | pci_disable_msix(ha->pdev); | ||
1659 | } | ||
1660 | |||
1661 | static int | ||
1662 | qla24xx_enable_msix(scsi_qla_host_t *ha) | ||
1663 | { | ||
1664 | int i, ret; | ||
1665 | struct msix_entry entries[QLA_MSIX_ENTRIES]; | ||
1666 | struct qla_msix_entry *qentry; | ||
1667 | |||
1668 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) | ||
1669 | entries[i].entry = imsix_entries[i].entry; | ||
1670 | |||
1671 | ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); | ||
1672 | if (ret) { | ||
1673 | qla_printk(KERN_WARNING, ha, | ||
1674 | "MSI-X: Failed to enable support -- %d/%d\n", | ||
1675 | QLA_MSIX_ENTRIES, ret); | ||
1676 | goto msix_out; | ||
1677 | } | ||
1678 | ha->flags.msix_enabled = 1; | ||
1679 | |||
1680 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) { | ||
1681 | qentry = &ha->msix_entries[imsix_entries[i].index]; | ||
1682 | qentry->msix_vector = entries[i].vector; | ||
1683 | qentry->msix_entry = entries[i].entry; | ||
1684 | qentry->have_irq = 0; | ||
1685 | ret = request_irq(qentry->msix_vector, | ||
1686 | imsix_entries[i].handler, 0, imsix_entries[i].name, ha); | ||
1687 | if (ret) { | ||
1688 | qla_printk(KERN_WARNING, ha, | ||
1689 | "MSI-X: Unable to register handler -- %x/%d.\n", | ||
1690 | imsix_entries[i].index, ret); | ||
1691 | qla24xx_disable_msix(ha); | ||
1692 | goto msix_out; | ||
1693 | } | ||
1694 | qentry->have_irq = 1; | ||
1695 | } | ||
1696 | |||
1697 | msix_out: | ||
1698 | return ret; | ||
1699 | } | ||
1700 | |||
1701 | int | ||
1702 | qla2x00_request_irqs(scsi_qla_host_t *ha) | ||
1703 | { | ||
1704 | int ret; | ||
1705 | |||
1706 | /* If possible, enable MSI-X. */ | ||
1707 | if (!IS_QLA2432(ha)) | ||
1708 | goto skip_msix; | ||
1709 | |||
1710 | if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || | ||
1711 | !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) { | ||
1712 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1713 | "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", | ||
1714 | ha->chip_revision, ha->fw_attributes)); | ||
1715 | |||
1716 | goto skip_msix; | ||
1717 | } | ||
1718 | |||
1719 | ret = qla24xx_enable_msix(ha); | ||
1720 | if (!ret) { | ||
1721 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1722 | "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision, | ||
1723 | ha->fw_attributes)); | ||
1724 | return ret; | ||
1725 | } | ||
1726 | qla_printk(KERN_WARNING, ha, | ||
1727 | "MSI-X: Falling back-to INTa mode -- %d.\n", ret); | ||
1728 | skip_msix: | ||
1729 | ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, | ||
1730 | IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); | ||
1731 | if (!ret) { | ||
1732 | ha->flags.inta_enabled = 1; | ||
1733 | ha->host->irq = ha->pdev->irq; | ||
1734 | } else { | ||
1735 | qla_printk(KERN_WARNING, ha, | ||
1736 | "Failed to reserve interrupt %d already in use.\n", | ||
1737 | ha->pdev->irq); | ||
1738 | } | ||
1739 | |||
1740 | return ret; | ||
1741 | } | ||
1742 | |||
1743 | void | ||
1744 | qla2x00_free_irqs(scsi_qla_host_t *ha) | ||
1745 | { | ||
1746 | |||
1747 | if (ha->flags.msix_enabled) | ||
1748 | qla24xx_disable_msix(ha); | ||
1749 | else if (ha->flags.inta_enabled) | ||
1750 | free_irq(ha->host->irq, ha); | ||
1751 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 077e5789beeb..83376f6ac3db 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -55,7 +55,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
55 | uint16_t __iomem *optr; | 55 | uint16_t __iomem *optr; |
56 | uint32_t cnt; | 56 | uint32_t cnt; |
57 | uint32_t mboxes; | 57 | uint32_t mboxes; |
58 | unsigned long mbx_flags = 0; | ||
59 | unsigned long wait_time; | 58 | unsigned long wait_time; |
60 | 59 | ||
61 | rval = QLA_SUCCESS; | 60 | rval = QLA_SUCCESS; |
@@ -81,10 +80,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
81 | /* Save mailbox command for debug */ | 80 | /* Save mailbox command for debug */ |
82 | ha->mcp = mcp; | 81 | ha->mcp = mcp; |
83 | 82 | ||
84 | /* Try to get mailbox register access */ | ||
85 | if (!abort_active) | ||
86 | spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); | ||
87 | |||
88 | DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n", | 83 | DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n", |
89 | ha->host_no, mcp->mb[0])); | 84 | ha->host_no, mcp->mb[0])); |
90 | 85 | ||
@@ -161,9 +156,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
161 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); | 156 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); |
162 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 157 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
163 | 158 | ||
164 | if (!abort_active) | ||
165 | spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); | ||
166 | |||
167 | /* Wait for either the timer to expire | 159 | /* Wait for either the timer to expire |
168 | * or the mbox completion interrupt | 160 | * or the mbox completion interrupt |
169 | */ | 161 | */ |
@@ -184,8 +176,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
184 | else | 176 | else |
185 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); | 177 | WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); |
186 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 178 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
187 | if (!abort_active) | ||
188 | spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); | ||
189 | 179 | ||
190 | wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */ | 180 | wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */ |
191 | while (!ha->flags.mbox_int) { | 181 | while (!ha->flags.mbox_int) { |
@@ -201,9 +191,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
201 | } /* while */ | 191 | } /* while */ |
202 | } | 192 | } |
203 | 193 | ||
204 | if (!abort_active) | ||
205 | spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); | ||
206 | |||
207 | /* Check whether we timed out */ | 194 | /* Check whether we timed out */ |
208 | if (ha->flags.mbox_int) { | 195 | if (ha->flags.mbox_int) { |
209 | uint16_t *iptr2; | 196 | uint16_t *iptr2; |
@@ -256,9 +243,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | |||
256 | rval = QLA_FUNCTION_TIMEOUT; | 243 | rval = QLA_FUNCTION_TIMEOUT; |
257 | } | 244 | } |
258 | 245 | ||
259 | if (!abort_active) | ||
260 | spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); | ||
261 | |||
262 | ha->flags.mbox_busy = 0; | 246 | ha->flags.mbox_busy = 0; |
263 | 247 | ||
264 | /* Clean up */ | 248 | /* Clean up */ |
@@ -1713,7 +1697,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1713 | lg->entry_count = 1; | 1697 | lg->entry_count = 1; |
1714 | lg->nport_handle = cpu_to_le16(loop_id); | 1698 | lg->nport_handle = cpu_to_le16(loop_id); |
1715 | lg->control_flags = | 1699 | lg->control_flags = |
1716 | __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_EXPL_LOGO); | 1700 | __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); |
1717 | lg->port_id[0] = al_pa; | 1701 | lg->port_id[0] = al_pa; |
1718 | lg->port_id[1] = area; | 1702 | lg->port_id[1] = area; |
1719 | lg->port_id[2] = domain; | 1703 | lg->port_id[2] = domain; |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d6445ae841ba..68f5d24b938b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1485,6 +1485,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1485 | ha->isp_ops.fw_dump = qla2100_fw_dump; | 1485 | ha->isp_ops.fw_dump = qla2100_fw_dump; |
1486 | ha->isp_ops.read_optrom = qla2x00_read_optrom_data; | 1486 | ha->isp_ops.read_optrom = qla2x00_read_optrom_data; |
1487 | ha->isp_ops.write_optrom = qla2x00_write_optrom_data; | 1487 | ha->isp_ops.write_optrom = qla2x00_write_optrom_data; |
1488 | ha->isp_ops.get_flash_version = qla2x00_get_flash_version; | ||
1488 | if (IS_QLA2100(ha)) { | 1489 | if (IS_QLA2100(ha)) { |
1489 | host->max_id = MAX_TARGETS_2100; | 1490 | host->max_id = MAX_TARGETS_2100; |
1490 | ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; | 1491 | ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; |
@@ -1550,6 +1551,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1550 | ha->isp_ops.beacon_on = qla24xx_beacon_on; | 1551 | ha->isp_ops.beacon_on = qla24xx_beacon_on; |
1551 | ha->isp_ops.beacon_off = qla24xx_beacon_off; | 1552 | ha->isp_ops.beacon_off = qla24xx_beacon_off; |
1552 | ha->isp_ops.beacon_blink = qla24xx_beacon_blink; | 1553 | ha->isp_ops.beacon_blink = qla24xx_beacon_blink; |
1554 | ha->isp_ops.get_flash_version = qla24xx_get_flash_version; | ||
1553 | ha->gid_list_info_size = 8; | 1555 | ha->gid_list_info_size = 8; |
1554 | ha->optrom_size = OPTROM_SIZE_24XX; | 1556 | ha->optrom_size = OPTROM_SIZE_24XX; |
1555 | } | 1557 | } |
@@ -1564,14 +1566,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1564 | INIT_LIST_HEAD(&ha->list); | 1566 | INIT_LIST_HEAD(&ha->list); |
1565 | INIT_LIST_HEAD(&ha->fcports); | 1567 | INIT_LIST_HEAD(&ha->fcports); |
1566 | 1568 | ||
1567 | /* | ||
1568 | * These locks are used to prevent more than one CPU | ||
1569 | * from modifying the queue at the same time. The | ||
1570 | * higher level "host_lock" will reduce most | ||
1571 | * contention for these locks. | ||
1572 | */ | ||
1573 | spin_lock_init(&ha->mbx_reg_lock); | ||
1574 | |||
1575 | qla2x00_config_dma_addressing(ha); | 1569 | qla2x00_config_dma_addressing(ha); |
1576 | if (qla2x00_mem_alloc(ha)) { | 1570 | if (qla2x00_mem_alloc(ha)) { |
1577 | qla_printk(KERN_WARNING, ha, | 1571 | qla_printk(KERN_WARNING, ha, |
@@ -1615,15 +1609,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1615 | host->max_lun = MAX_LUNS; | 1609 | host->max_lun = MAX_LUNS; |
1616 | host->transportt = qla2xxx_transport_template; | 1610 | host->transportt = qla2xxx_transport_template; |
1617 | 1611 | ||
1618 | ret = request_irq(pdev->irq, ha->isp_ops.intr_handler, | 1612 | ret = qla2x00_request_irqs(ha); |
1619 | IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); | 1613 | if (ret) |
1620 | if (ret) { | ||
1621 | qla_printk(KERN_WARNING, ha, | ||
1622 | "Failed to reserve interrupt %d already in use.\n", | ||
1623 | pdev->irq); | ||
1624 | goto probe_failed; | 1614 | goto probe_failed; |
1625 | } | ||
1626 | host->irq = pdev->irq; | ||
1627 | 1615 | ||
1628 | /* Initialized the timer */ | 1616 | /* Initialized the timer */ |
1629 | qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL); | 1617 | qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL); |
@@ -1753,9 +1741,7 @@ qla2x00_free_device(scsi_qla_host_t *ha) | |||
1753 | 1741 | ||
1754 | qla2x00_mem_free(ha); | 1742 | qla2x00_mem_free(ha); |
1755 | 1743 | ||
1756 | /* Detach interrupts */ | 1744 | qla2x00_free_irqs(ha); |
1757 | if (ha->host->irq) | ||
1758 | free_irq(ha->host->irq, ha); | ||
1759 | 1745 | ||
1760 | /* release io space registers */ | 1746 | /* release io space registers */ |
1761 | if (ha->iobase) | 1747 | if (ha->iobase) |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 15390ad87456..ff1dd4175a7f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -611,7 +611,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
611 | flash_conf_to_access_addr(0x0339), | 611 | flash_conf_to_access_addr(0x0339), |
612 | (fdata & 0xff00) | ((fdata << 16) & | 612 | (fdata & 0xff00) | ((fdata << 16) & |
613 | 0xff0000) | ((fdata >> 16) & 0xff)); | 613 | 0xff0000) | ((fdata >> 16) & 0xff)); |
614 | fdata = (faddr & sec_mask) << 2; | ||
615 | ret = qla24xx_write_flash_dword(ha, conf_addr, | 614 | ret = qla24xx_write_flash_dword(ha, conf_addr, |
616 | (fdata & 0xff00) |((fdata << 16) & | 615 | (fdata & 0xff00) |((fdata << 16) & |
617 | 0xff0000) | ((fdata >> 16) & 0xff)); | 616 | 0xff0000) | ((fdata >> 16) & 0xff)); |
@@ -1383,6 +1382,29 @@ qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, | |||
1383 | qla2x00_write_flash_byte(ha, 0x5555, 0xf0); | 1382 | qla2x00_write_flash_byte(ha, 0x5555, 0xf0); |
1384 | } | 1383 | } |
1385 | 1384 | ||
1385 | static void | ||
1386 | qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr, | ||
1387 | uint32_t length) | ||
1388 | { | ||
1389 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
1390 | uint32_t midpoint, ilength; | ||
1391 | uint8_t data; | ||
1392 | |||
1393 | midpoint = length / 2; | ||
1394 | |||
1395 | WRT_REG_WORD(®->nvram, 0); | ||
1396 | RD_REG_WORD(®->nvram); | ||
1397 | for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) { | ||
1398 | if (ilength == midpoint) { | ||
1399 | WRT_REG_WORD(®->nvram, NVR_SELECT); | ||
1400 | RD_REG_WORD(®->nvram); | ||
1401 | } | ||
1402 | data = qla2x00_read_flash_byte(ha, saddr); | ||
1403 | if (saddr % 100) | ||
1404 | udelay(10); | ||
1405 | *tmp_buf = data; | ||
1406 | } | ||
1407 | } | ||
1386 | 1408 | ||
1387 | static inline void | 1409 | static inline void |
1388 | qla2x00_suspend_hba(struct scsi_qla_host *ha) | 1410 | qla2x00_suspend_hba(struct scsi_qla_host *ha) |
@@ -1722,3 +1744,327 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, | |||
1722 | 1744 | ||
1723 | return rval; | 1745 | return rval; |
1724 | } | 1746 | } |
1747 | |||
1748 | /** | ||
1749 | * qla2x00_get_fcode_version() - Determine an FCODE image's version. | ||
1750 | * @ha: HA context | ||
1751 | * @pcids: Pointer to the FCODE PCI data structure | ||
1752 | * | ||
1753 | * The process of retrieving the FCODE version information is at best | ||
1754 | * described as interesting. | ||
1755 | * | ||
1756 | * Within the first 100h bytes of the image an ASCII string is present | ||
1757 | * which contains several pieces of information including the FCODE | ||
1758 | * version. Unfortunately it seems the only reliable way to retrieve | ||
1759 | * the version is by scanning for another sentinel within the string, | ||
1760 | * the FCODE build date: | ||
1761 | * | ||
1762 | * ... 2.00.02 10/17/02 ... | ||
1763 | * | ||
1764 | * Returns QLA_SUCCESS on successful retrieval of version. | ||
1765 | */ | ||
1766 | static void | ||
1767 | qla2x00_get_fcode_version(scsi_qla_host_t *ha, uint32_t pcids) | ||
1768 | { | ||
1769 | int ret = QLA_FUNCTION_FAILED; | ||
1770 | uint32_t istart, iend, iter, vend; | ||
1771 | uint8_t do_next, rbyte, *vbyte; | ||
1772 | |||
1773 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1774 | |||
1775 | /* Skip the PCI data structure. */ | ||
1776 | istart = pcids + | ||
1777 | ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) | | ||
1778 | qla2x00_read_flash_byte(ha, pcids + 0x0A)); | ||
1779 | iend = istart + 0x100; | ||
1780 | do { | ||
1781 | /* Scan for the sentinel date string...eeewww. */ | ||
1782 | do_next = 0; | ||
1783 | iter = istart; | ||
1784 | while ((iter < iend) && !do_next) { | ||
1785 | iter++; | ||
1786 | if (qla2x00_read_flash_byte(ha, iter) == '/') { | ||
1787 | if (qla2x00_read_flash_byte(ha, iter + 2) == | ||
1788 | '/') | ||
1789 | do_next++; | ||
1790 | else if (qla2x00_read_flash_byte(ha, | ||
1791 | iter + 3) == '/') | ||
1792 | do_next++; | ||
1793 | } | ||
1794 | } | ||
1795 | if (!do_next) | ||
1796 | break; | ||
1797 | |||
1798 | /* Backtrack to previous ' ' (space). */ | ||
1799 | do_next = 0; | ||
1800 | while ((iter > istart) && !do_next) { | ||
1801 | iter--; | ||
1802 | if (qla2x00_read_flash_byte(ha, iter) == ' ') | ||
1803 | do_next++; | ||
1804 | } | ||
1805 | if (!do_next) | ||
1806 | break; | ||
1807 | |||
1808 | /* | ||
1809 | * Mark end of version tag, and find previous ' ' (space) or | ||
1810 | * string length (recent FCODE images -- major hack ahead!!!). | ||
1811 | */ | ||
1812 | vend = iter - 1; | ||
1813 | do_next = 0; | ||
1814 | while ((iter > istart) && !do_next) { | ||
1815 | iter--; | ||
1816 | rbyte = qla2x00_read_flash_byte(ha, iter); | ||
1817 | if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10) | ||
1818 | do_next++; | ||
1819 | } | ||
1820 | if (!do_next) | ||
1821 | break; | ||
1822 | |||
1823 | /* Mark beginning of version tag, and copy data. */ | ||
1824 | iter++; | ||
1825 | if ((vend - iter) && | ||
1826 | ((vend - iter) < sizeof(ha->fcode_revision))) { | ||
1827 | vbyte = ha->fcode_revision; | ||
1828 | while (iter <= vend) { | ||
1829 | *vbyte++ = qla2x00_read_flash_byte(ha, iter); | ||
1830 | iter++; | ||
1831 | } | ||
1832 | ret = QLA_SUCCESS; | ||
1833 | } | ||
1834 | } while (0); | ||
1835 | |||
1836 | if (ret != QLA_SUCCESS) | ||
1837 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1838 | } | ||
1839 | |||
1840 | int | ||
1841 | qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | ||
1842 | { | ||
1843 | int ret = QLA_SUCCESS; | ||
1844 | uint8_t code_type, last_image; | ||
1845 | uint32_t pcihdr, pcids; | ||
1846 | uint8_t *dbyte; | ||
1847 | uint16_t *dcode; | ||
1848 | |||
1849 | if (!ha->pio_address || !mbuf) | ||
1850 | return QLA_FUNCTION_FAILED; | ||
1851 | |||
1852 | memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); | ||
1853 | memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); | ||
1854 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1855 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
1856 | |||
1857 | qla2x00_flash_enable(ha); | ||
1858 | |||
1859 | /* Begin with first PCI expansion ROM header. */ | ||
1860 | pcihdr = 0; | ||
1861 | last_image = 1; | ||
1862 | do { | ||
1863 | /* Verify PCI expansion ROM header. */ | ||
1864 | if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 || | ||
1865 | qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) { | ||
1866 | /* No signature */ | ||
1867 | DEBUG2(printk("scsi(%ld): No matching ROM " | ||
1868 | "signature.\n", ha->host_no)); | ||
1869 | ret = QLA_FUNCTION_FAILED; | ||
1870 | break; | ||
1871 | } | ||
1872 | |||
1873 | /* Locate PCI data structure. */ | ||
1874 | pcids = pcihdr + | ||
1875 | ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) | | ||
1876 | qla2x00_read_flash_byte(ha, pcihdr + 0x18)); | ||
1877 | |||
1878 | /* Validate signature of PCI data structure. */ | ||
1879 | if (qla2x00_read_flash_byte(ha, pcids) != 'P' || | ||
1880 | qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' || | ||
1881 | qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' || | ||
1882 | qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') { | ||
1883 | /* Incorrect header. */ | ||
1884 | DEBUG2(printk("%s(): PCI data struct not found " | ||
1885 | "pcir_adr=%x.\n", __func__, pcids)); | ||
1886 | ret = QLA_FUNCTION_FAILED; | ||
1887 | break; | ||
1888 | } | ||
1889 | |||
1890 | /* Read version */ | ||
1891 | code_type = qla2x00_read_flash_byte(ha, pcids + 0x14); | ||
1892 | switch (code_type) { | ||
1893 | case ROM_CODE_TYPE_BIOS: | ||
1894 | /* Intel x86, PC-AT compatible. */ | ||
1895 | ha->bios_revision[0] = | ||
1896 | qla2x00_read_flash_byte(ha, pcids + 0x12); | ||
1897 | ha->bios_revision[1] = | ||
1898 | qla2x00_read_flash_byte(ha, pcids + 0x13); | ||
1899 | DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, | ||
1900 | ha->bios_revision[1], ha->bios_revision[0])); | ||
1901 | break; | ||
1902 | case ROM_CODE_TYPE_FCODE: | ||
1903 | /* Open Firmware standard for PCI (FCode). */ | ||
1904 | /* Eeeewww... */ | ||
1905 | qla2x00_get_fcode_version(ha, pcids); | ||
1906 | break; | ||
1907 | case ROM_CODE_TYPE_EFI: | ||
1908 | /* Extensible Firmware Interface (EFI). */ | ||
1909 | ha->efi_revision[0] = | ||
1910 | qla2x00_read_flash_byte(ha, pcids + 0x12); | ||
1911 | ha->efi_revision[1] = | ||
1912 | qla2x00_read_flash_byte(ha, pcids + 0x13); | ||
1913 | DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, | ||
1914 | ha->efi_revision[1], ha->efi_revision[0])); | ||
1915 | break; | ||
1916 | default: | ||
1917 | DEBUG2(printk("%s(): Unrecognized code type %x at " | ||
1918 | "pcids %x.\n", __func__, code_type, pcids)); | ||
1919 | break; | ||
1920 | } | ||
1921 | |||
1922 | last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7; | ||
1923 | |||
1924 | /* Locate next PCI expansion ROM. */ | ||
1925 | pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) | | ||
1926 | qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512; | ||
1927 | } while (!last_image); | ||
1928 | |||
1929 | if (IS_QLA2322(ha)) { | ||
1930 | /* Read firmware image information. */ | ||
1931 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
1932 | dbyte = mbuf; | ||
1933 | memset(dbyte, 0, 8); | ||
1934 | dcode = (uint16_t *)dbyte; | ||
1935 | |||
1936 | qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, | ||
1937 | 8); | ||
1938 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", | ||
1939 | __func__, ha->host_no)); | ||
1940 | DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8)); | ||
1941 | |||
1942 | if ((dcode[0] == 0xffff && dcode[1] == 0xffff && | ||
1943 | dcode[2] == 0xffff && dcode[3] == 0xffff) || | ||
1944 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | ||
1945 | dcode[3] == 0)) { | ||
1946 | DEBUG2(printk("%s(): Unrecognized fw revision at " | ||
1947 | "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); | ||
1948 | } else { | ||
1949 | /* values are in big endian */ | ||
1950 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; | ||
1951 | ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3]; | ||
1952 | ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5]; | ||
1953 | } | ||
1954 | } | ||
1955 | |||
1956 | qla2x00_flash_disable(ha); | ||
1957 | |||
1958 | return ret; | ||
1959 | } | ||
1960 | |||
1961 | int | ||
1962 | qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | ||
1963 | { | ||
1964 | int ret = QLA_SUCCESS; | ||
1965 | uint32_t pcihdr, pcids; | ||
1966 | uint32_t *dcode; | ||
1967 | uint8_t *bcode; | ||
1968 | uint8_t code_type, last_image; | ||
1969 | int i; | ||
1970 | |||
1971 | if (!mbuf) | ||
1972 | return QLA_FUNCTION_FAILED; | ||
1973 | |||
1974 | memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); | ||
1975 | memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); | ||
1976 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1977 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
1978 | |||
1979 | dcode = mbuf; | ||
1980 | |||
1981 | /* Begin with first PCI expansion ROM header. */ | ||
1982 | pcihdr = 0; | ||
1983 | last_image = 1; | ||
1984 | do { | ||
1985 | /* Verify PCI expansion ROM header. */ | ||
1986 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); | ||
1987 | bcode = mbuf + (pcihdr % 4); | ||
1988 | if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { | ||
1989 | /* No signature */ | ||
1990 | DEBUG2(printk("scsi(%ld): No matching ROM " | ||
1991 | "signature.\n", ha->host_no)); | ||
1992 | ret = QLA_FUNCTION_FAILED; | ||
1993 | break; | ||
1994 | } | ||
1995 | |||
1996 | /* Locate PCI data structure. */ | ||
1997 | pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); | ||
1998 | |||
1999 | qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); | ||
2000 | bcode = mbuf + (pcihdr % 4); | ||
2001 | |||
2002 | /* Validate signature of PCI data structure. */ | ||
2003 | if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || | ||
2004 | bcode[0x2] != 'I' || bcode[0x3] != 'R') { | ||
2005 | /* Incorrect header. */ | ||
2006 | DEBUG2(printk("%s(): PCI data struct not found " | ||
2007 | "pcir_adr=%x.\n", __func__, pcids)); | ||
2008 | ret = QLA_FUNCTION_FAILED; | ||
2009 | break; | ||
2010 | } | ||
2011 | |||
2012 | /* Read version */ | ||
2013 | code_type = bcode[0x14]; | ||
2014 | switch (code_type) { | ||
2015 | case ROM_CODE_TYPE_BIOS: | ||
2016 | /* Intel x86, PC-AT compatible. */ | ||
2017 | ha->bios_revision[0] = bcode[0x12]; | ||
2018 | ha->bios_revision[1] = bcode[0x13]; | ||
2019 | DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, | ||
2020 | ha->bios_revision[1], ha->bios_revision[0])); | ||
2021 | break; | ||
2022 | case ROM_CODE_TYPE_FCODE: | ||
2023 | /* Open Firmware standard for PCI (FCode). */ | ||
2024 | ha->fcode_revision[0] = bcode[0x12]; | ||
2025 | ha->fcode_revision[1] = bcode[0x13]; | ||
2026 | DEBUG3(printk("%s(): read FCODE %d.%d.\n", __func__, | ||
2027 | ha->fcode_revision[1], ha->fcode_revision[0])); | ||
2028 | break; | ||
2029 | case ROM_CODE_TYPE_EFI: | ||
2030 | /* Extensible Firmware Interface (EFI). */ | ||
2031 | ha->efi_revision[0] = bcode[0x12]; | ||
2032 | ha->efi_revision[1] = bcode[0x13]; | ||
2033 | DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, | ||
2034 | ha->efi_revision[1], ha->efi_revision[0])); | ||
2035 | break; | ||
2036 | default: | ||
2037 | DEBUG2(printk("%s(): Unrecognized code type %x at " | ||
2038 | "pcids %x.\n", __func__, code_type, pcids)); | ||
2039 | break; | ||
2040 | } | ||
2041 | |||
2042 | last_image = bcode[0x15] & BIT_7; | ||
2043 | |||
2044 | /* Locate next PCI expansion ROM. */ | ||
2045 | pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; | ||
2046 | } while (!last_image); | ||
2047 | |||
2048 | /* Read firmware image information. */ | ||
2049 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
2050 | dcode = mbuf; | ||
2051 | |||
2052 | qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); | ||
2053 | for (i = 0; i < 4; i++) | ||
2054 | dcode[i] = be32_to_cpu(dcode[i]); | ||
2055 | |||
2056 | if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && | ||
2057 | dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || | ||
2058 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | ||
2059 | dcode[3] == 0)) { | ||
2060 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", | ||
2061 | __func__, FA_RISC_CODE_ADDR)); | ||
2062 | } else { | ||
2063 | ha->fw_revision[0] = dcode[0]; | ||
2064 | ha->fw_revision[1] = dcode[1]; | ||
2065 | ha->fw_revision[2] = dcode[2]; | ||
2066 | ha->fw_revision[3] = dcode[3]; | ||
2067 | } | ||
2068 | |||
2069 | return ret; | ||
2070 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 459e0d6bd2b4..61347aee55ce 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,7 +7,7 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.01.07-k4" | 10 | #define QLA2XXX_VERSION "8.01.07-k5" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 1 | 13 | #define QLA_DRIVER_MINOR_VER 1 |