diff options
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_dbg.c | 6 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 30 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 23 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 127 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_version.h | 2 |
6 files changed, 141 insertions, 48 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index af62c3cf8752..8d58ae274829 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c | |||
@@ -20,12 +20,12 @@ void qla4xxx_dump_buffer(void *b, uint32_t size) | |||
20 | printk("------------------------------------------------------------" | 20 | printk("------------------------------------------------------------" |
21 | "--\n"); | 21 | "--\n"); |
22 | for (cnt = 0; cnt < size; c++) { | 22 | for (cnt = 0; cnt < size; c++) { |
23 | printk(KERN_INFO "%02x", *c); | 23 | printk("%02x", *c); |
24 | if (!(++cnt % 16)) | 24 | if (!(++cnt % 16)) |
25 | printk(KERN_INFO "\n"); | 25 | printk("\n"); |
26 | 26 | ||
27 | else | 27 | else |
28 | printk(KERN_INFO " "); | 28 | printk(" "); |
29 | } | 29 | } |
30 | printk(KERN_INFO "\n"); | 30 | printk(KERN_INFO "\n"); |
31 | } | 31 | } |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index fd5edc6e166d..22a3ff02e48a 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -177,6 +177,7 @@ | |||
177 | #define LOGIN_TOV 12 | 177 | #define LOGIN_TOV 12 |
178 | 178 | ||
179 | #define MAX_RESET_HA_RETRIES 2 | 179 | #define MAX_RESET_HA_RETRIES 2 |
180 | #define FW_ALIVE_WAIT_TOV 3 | ||
180 | 181 | ||
181 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) | 182 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) |
182 | 183 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 827e93078b94..95828862eea0 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -123,13 +123,13 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
123 | 123 | ||
124 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); | 124 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); |
125 | if (!srb) { | 125 | if (!srb) { |
126 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid " | 126 | ql4_printk(KERN_WARNING, ha, "%s invalid status entry: " |
127 | "handle 0x%x, sp=%p. This cmd may have already " | 127 | "handle=0x%0x, srb=%p\n", __func__, |
128 | "been completed.\n", ha->host_no, __func__, | 128 | sts_entry->handle, srb); |
129 | le32_to_cpu(sts_entry->handle), srb)); | 129 | if (is_qla8022(ha)) |
130 | ql4_printk(KERN_WARNING, ha, "%s invalid status entry:" | 130 | set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); |
131 | " handle=0x%0x\n", __func__, sts_entry->handle); | 131 | else |
132 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 132 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
133 | return; | 133 | return; |
134 | } | 134 | } |
135 | 135 | ||
@@ -563,7 +563,11 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
563 | case MBOX_ASTS_DHCP_LEASE_EXPIRED: | 563 | case MBOX_ASTS_DHCP_LEASE_EXPIRED: |
564 | DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, " | 564 | DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, " |
565 | "Reset HA\n", ha->host_no, mbox_status)); | 565 | "Reset HA\n", ha->host_no, mbox_status)); |
566 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 566 | if (is_qla8022(ha)) |
567 | set_bit(DPC_RESET_HA_FW_CONTEXT, | ||
568 | &ha->dpc_flags); | ||
569 | else | ||
570 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
567 | break; | 571 | break; |
568 | 572 | ||
569 | case MBOX_ASTS_LINK_UP: | 573 | case MBOX_ASTS_LINK_UP: |
@@ -617,9 +621,13 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
617 | (mbox_sts[2] == ACB_STATE_ACQUIRING))) | 621 | (mbox_sts[2] == ACB_STATE_ACQUIRING))) |
618 | set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); | 622 | set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); |
619 | else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) && | 623 | else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) && |
620 | (mbox_sts[2] == ACB_STATE_VALID)) | 624 | (mbox_sts[2] == ACB_STATE_VALID)) { |
621 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 625 | if (is_qla8022(ha)) |
622 | else if ((mbox_sts[3] == ACB_STATE_UNCONFIGURED)) | 626 | set_bit(DPC_RESET_HA_FW_CONTEXT, |
627 | &ha->dpc_flags); | ||
628 | else | ||
629 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
630 | } else if ((mbox_sts[3] == ACB_STATE_UNCONFIGURED)) | ||
623 | complete(&ha->disable_acb_comp); | 631 | complete(&ha->disable_acb_comp); |
624 | break; | 632 | break; |
625 | 633 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index f484ff438199..8d6bc1b2ff17 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -1792,8 +1792,11 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1792 | int rval = QLA_SUCCESS; | 1792 | int rval = QLA_SUCCESS; |
1793 | unsigned long dev_init_timeout; | 1793 | unsigned long dev_init_timeout; |
1794 | 1794 | ||
1795 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1795 | if (!test_bit(AF_INIT_DONE, &ha->flags)) { |
1796 | qla4_8xxx_idc_lock(ha); | ||
1796 | qla4_8xxx_set_drv_active(ha); | 1797 | qla4_8xxx_set_drv_active(ha); |
1798 | qla4_8xxx_idc_unlock(ha); | ||
1799 | } | ||
1797 | 1800 | ||
1798 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 1801 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
1799 | ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, | 1802 | ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, |
@@ -1802,8 +1805,8 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1802 | /* wait for 30 seconds for device to go ready */ | 1805 | /* wait for 30 seconds for device to go ready */ |
1803 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); | 1806 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); |
1804 | 1807 | ||
1808 | qla4_8xxx_idc_lock(ha); | ||
1805 | while (1) { | 1809 | while (1) { |
1806 | qla4_8xxx_idc_lock(ha); | ||
1807 | 1810 | ||
1808 | if (time_after_eq(jiffies, dev_init_timeout)) { | 1811 | if (time_after_eq(jiffies, dev_init_timeout)) { |
1809 | ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); | 1812 | ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); |
@@ -1819,15 +1822,14 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1819 | /* NOTE: Make sure idc unlocked upon exit of switch statement */ | 1822 | /* NOTE: Make sure idc unlocked upon exit of switch statement */ |
1820 | switch (dev_state) { | 1823 | switch (dev_state) { |
1821 | case QLA82XX_DEV_READY: | 1824 | case QLA82XX_DEV_READY: |
1822 | qla4_8xxx_idc_unlock(ha); | ||
1823 | goto exit; | 1825 | goto exit; |
1824 | case QLA82XX_DEV_COLD: | 1826 | case QLA82XX_DEV_COLD: |
1825 | rval = qla4_8xxx_device_bootstrap(ha); | 1827 | rval = qla4_8xxx_device_bootstrap(ha); |
1826 | qla4_8xxx_idc_unlock(ha); | ||
1827 | goto exit; | 1828 | goto exit; |
1828 | case QLA82XX_DEV_INITIALIZING: | 1829 | case QLA82XX_DEV_INITIALIZING: |
1829 | qla4_8xxx_idc_unlock(ha); | 1830 | qla4_8xxx_idc_unlock(ha); |
1830 | msleep(1000); | 1831 | msleep(1000); |
1832 | qla4_8xxx_idc_lock(ha); | ||
1831 | break; | 1833 | break; |
1832 | case QLA82XX_DEV_NEED_RESET: | 1834 | case QLA82XX_DEV_NEED_RESET: |
1833 | if (!ql4xdontresethba) { | 1835 | if (!ql4xdontresethba) { |
@@ -1836,32 +1838,37 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1836 | * reset handler */ | 1838 | * reset handler */ |
1837 | dev_init_timeout = jiffies + | 1839 | dev_init_timeout = jiffies + |
1838 | (ha->nx_dev_init_timeout * HZ); | 1840 | (ha->nx_dev_init_timeout * HZ); |
1841 | } else { | ||
1842 | qla4_8xxx_idc_unlock(ha); | ||
1843 | msleep(1000); | ||
1844 | qla4_8xxx_idc_lock(ha); | ||
1839 | } | 1845 | } |
1840 | qla4_8xxx_idc_unlock(ha); | ||
1841 | break; | 1846 | break; |
1842 | case QLA82XX_DEV_NEED_QUIESCENT: | 1847 | case QLA82XX_DEV_NEED_QUIESCENT: |
1843 | qla4_8xxx_idc_unlock(ha); | ||
1844 | /* idc locked/unlocked in handler */ | 1848 | /* idc locked/unlocked in handler */ |
1845 | qla4_8xxx_need_qsnt_handler(ha); | 1849 | qla4_8xxx_need_qsnt_handler(ha); |
1846 | qla4_8xxx_idc_lock(ha); | 1850 | break; |
1847 | /* fall thru needs idc_locked */ | ||
1848 | case QLA82XX_DEV_QUIESCENT: | 1851 | case QLA82XX_DEV_QUIESCENT: |
1849 | qla4_8xxx_idc_unlock(ha); | 1852 | qla4_8xxx_idc_unlock(ha); |
1850 | msleep(1000); | 1853 | msleep(1000); |
1854 | qla4_8xxx_idc_lock(ha); | ||
1851 | break; | 1855 | break; |
1852 | case QLA82XX_DEV_FAILED: | 1856 | case QLA82XX_DEV_FAILED: |
1853 | qla4_8xxx_idc_unlock(ha); | 1857 | qla4_8xxx_idc_unlock(ha); |
1854 | qla4xxx_dead_adapter_cleanup(ha); | 1858 | qla4xxx_dead_adapter_cleanup(ha); |
1855 | rval = QLA_ERROR; | 1859 | rval = QLA_ERROR; |
1860 | qla4_8xxx_idc_lock(ha); | ||
1856 | goto exit; | 1861 | goto exit; |
1857 | default: | 1862 | default: |
1858 | qla4_8xxx_idc_unlock(ha); | 1863 | qla4_8xxx_idc_unlock(ha); |
1859 | qla4xxx_dead_adapter_cleanup(ha); | 1864 | qla4xxx_dead_adapter_cleanup(ha); |
1860 | rval = QLA_ERROR; | 1865 | rval = QLA_ERROR; |
1866 | qla4_8xxx_idc_lock(ha); | ||
1861 | goto exit; | 1867 | goto exit; |
1862 | } | 1868 | } |
1863 | } | 1869 | } |
1864 | exit: | 1870 | exit: |
1871 | qla4_8xxx_idc_unlock(ha); | ||
1865 | return rval; | 1872 | return rval; |
1866 | } | 1873 | } |
1867 | 1874 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 78bf700b365f..ec393a00c038 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -935,7 +935,16 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len) | |||
935 | goto exit_init_fw_cb; | 935 | goto exit_init_fw_cb; |
936 | } | 936 | } |
937 | 937 | ||
938 | qla4xxx_disable_acb(ha); | 938 | rval = qla4xxx_disable_acb(ha); |
939 | if (rval != QLA_SUCCESS) { | ||
940 | ql4_printk(KERN_ERR, ha, "%s: disable acb mbx failed\n", | ||
941 | __func__); | ||
942 | rval = -EIO; | ||
943 | goto exit_init_fw_cb; | ||
944 | } | ||
945 | |||
946 | wait_for_completion_timeout(&ha->disable_acb_comp, | ||
947 | DISABLE_ACB_TOV * HZ); | ||
939 | 948 | ||
940 | qla4xxx_initcb_to_acb(init_fw_cb); | 949 | qla4xxx_initcb_to_acb(init_fw_cb); |
941 | 950 | ||
@@ -1966,9 +1975,10 @@ mem_alloc_error_exit: | |||
1966 | * | 1975 | * |
1967 | * Context: Interrupt | 1976 | * Context: Interrupt |
1968 | **/ | 1977 | **/ |
1969 | static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | 1978 | static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) |
1970 | { | 1979 | { |
1971 | uint32_t fw_heartbeat_counter, halt_status; | 1980 | uint32_t fw_heartbeat_counter; |
1981 | int status = QLA_SUCCESS; | ||
1972 | 1982 | ||
1973 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 1983 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
1974 | /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ | 1984 | /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ |
@@ -1976,7 +1986,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
1976 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " | 1986 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " |
1977 | "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", | 1987 | "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", |
1978 | ha->host_no, __func__)); | 1988 | ha->host_no, __func__)); |
1979 | return; | 1989 | return status; |
1980 | } | 1990 | } |
1981 | 1991 | ||
1982 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { | 1992 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { |
@@ -1984,8 +1994,6 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
1984 | /* FW not alive after 2 seconds */ | 1994 | /* FW not alive after 2 seconds */ |
1985 | if (ha->seconds_since_last_heartbeat == 2) { | 1995 | if (ha->seconds_since_last_heartbeat == 2) { |
1986 | ha->seconds_since_last_heartbeat = 0; | 1996 | ha->seconds_since_last_heartbeat = 0; |
1987 | halt_status = qla4_8xxx_rd_32(ha, | ||
1988 | QLA82XX_PEG_HALT_STATUS1); | ||
1989 | 1997 | ||
1990 | ql4_printk(KERN_INFO, ha, | 1998 | ql4_printk(KERN_INFO, ha, |
1991 | "scsi(%ld): %s, Dumping hw/fw registers:\n " | 1999 | "scsi(%ld): %s, Dumping hw/fw registers:\n " |
@@ -1993,7 +2001,9 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
1993 | " 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:" | 2001 | " 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:" |
1994 | " 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:" | 2002 | " 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:" |
1995 | " 0x%x,\n PEG_NET_4_PC: 0x%x\n", | 2003 | " 0x%x,\n PEG_NET_4_PC: 0x%x\n", |
1996 | ha->host_no, __func__, halt_status, | 2004 | ha->host_no, __func__, |
2005 | qla4_8xxx_rd_32(ha, | ||
2006 | QLA82XX_PEG_HALT_STATUS1), | ||
1997 | qla4_8xxx_rd_32(ha, | 2007 | qla4_8xxx_rd_32(ha, |
1998 | QLA82XX_PEG_HALT_STATUS2), | 2008 | QLA82XX_PEG_HALT_STATUS2), |
1999 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 + | 2009 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 + |
@@ -2006,24 +2016,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
2006 | 0x3c), | 2016 | 0x3c), |
2007 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 + | 2017 | qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 + |
2008 | 0x3c)); | 2018 | 0x3c)); |
2009 | 2019 | status = QLA_ERROR; | |
2010 | /* Since we cannot change dev_state in interrupt | ||
2011 | * context, set appropriate DPC flag then wakeup | ||
2012 | * DPC */ | ||
2013 | if (halt_status & HALT_STATUS_UNRECOVERABLE) | ||
2014 | set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); | ||
2015 | else { | ||
2016 | printk("scsi%ld: %s: detect abort needed!\n", | ||
2017 | ha->host_no, __func__); | ||
2018 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
2019 | } | ||
2020 | qla4xxx_wake_dpc(ha); | ||
2021 | qla4xxx_mailbox_premature_completion(ha); | ||
2022 | } | 2020 | } |
2023 | } else | 2021 | } else |
2024 | ha->seconds_since_last_heartbeat = 0; | 2022 | ha->seconds_since_last_heartbeat = 0; |
2025 | 2023 | ||
2026 | ha->fw_heartbeat_counter = fw_heartbeat_counter; | 2024 | ha->fw_heartbeat_counter = fw_heartbeat_counter; |
2025 | return status; | ||
2027 | } | 2026 | } |
2028 | 2027 | ||
2029 | /** | 2028 | /** |
@@ -2034,14 +2033,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | |||
2034 | **/ | 2033 | **/ |
2035 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | 2034 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha) |
2036 | { | 2035 | { |
2037 | uint32_t dev_state; | 2036 | uint32_t dev_state, halt_status; |
2038 | |||
2039 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
2040 | 2037 | ||
2041 | /* don't poll if reset is going on */ | 2038 | /* don't poll if reset is going on */ |
2042 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || | 2039 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || |
2043 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 2040 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
2044 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { | 2041 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { |
2042 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
2045 | if (dev_state == QLA82XX_DEV_NEED_RESET && | 2043 | if (dev_state == QLA82XX_DEV_NEED_RESET && |
2046 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | 2044 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
2047 | if (!ql4xdontresethba) { | 2045 | if (!ql4xdontresethba) { |
@@ -2049,7 +2047,6 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
2049 | "NEED RESET!\n", __func__); | 2047 | "NEED RESET!\n", __func__); |
2050 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 2048 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
2051 | qla4xxx_wake_dpc(ha); | 2049 | qla4xxx_wake_dpc(ha); |
2052 | qla4xxx_mailbox_premature_completion(ha); | ||
2053 | } | 2050 | } |
2054 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | 2051 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && |
2055 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | 2052 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { |
@@ -2059,7 +2056,24 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
2059 | qla4xxx_wake_dpc(ha); | 2056 | qla4xxx_wake_dpc(ha); |
2060 | } else { | 2057 | } else { |
2061 | /* Check firmware health */ | 2058 | /* Check firmware health */ |
2062 | qla4_8xxx_check_fw_alive(ha); | 2059 | if (qla4_8xxx_check_fw_alive(ha)) { |
2060 | halt_status = qla4_8xxx_rd_32(ha, | ||
2061 | QLA82XX_PEG_HALT_STATUS1); | ||
2062 | |||
2063 | /* Since we cannot change dev_state in interrupt | ||
2064 | * context, set appropriate DPC flag then wakeup | ||
2065 | * DPC */ | ||
2066 | if (halt_status & HALT_STATUS_UNRECOVERABLE) | ||
2067 | set_bit(DPC_HA_UNRECOVERABLE, | ||
2068 | &ha->dpc_flags); | ||
2069 | else { | ||
2070 | ql4_printk(KERN_INFO, ha, "%s: detect " | ||
2071 | "abort needed!\n", __func__); | ||
2072 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
2073 | } | ||
2074 | qla4xxx_mailbox_premature_completion(ha); | ||
2075 | qla4xxx_wake_dpc(ha); | ||
2076 | } | ||
2063 | } | 2077 | } |
2064 | } | 2078 | } |
2065 | } | 2079 | } |
@@ -2414,6 +2428,8 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) | |||
2414 | { | 2428 | { |
2415 | int status = QLA_ERROR; | 2429 | int status = QLA_ERROR; |
2416 | uint8_t reset_chip = 0; | 2430 | uint8_t reset_chip = 0; |
2431 | uint32_t dev_state; | ||
2432 | unsigned long wait; | ||
2417 | 2433 | ||
2418 | /* Stall incoming I/O until we are done */ | 2434 | /* Stall incoming I/O until we are done */ |
2419 | scsi_block_requests(ha->host); | 2435 | scsi_block_requests(ha->host); |
@@ -2464,8 +2480,29 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) | |||
2464 | * or if stop_firmware fails for ISP-82xx. | 2480 | * or if stop_firmware fails for ISP-82xx. |
2465 | * This is the default case for ISP-4xxx */ | 2481 | * This is the default case for ISP-4xxx */ |
2466 | if (!is_qla8022(ha) || reset_chip) { | 2482 | if (!is_qla8022(ha) || reset_chip) { |
2483 | if (!is_qla8022(ha)) | ||
2484 | goto chip_reset; | ||
2485 | |||
2486 | /* Check if 82XX firmware is alive or not | ||
2487 | * We may have arrived here from NEED_RESET | ||
2488 | * detection only */ | ||
2489 | if (test_bit(AF_FW_RECOVERY, &ha->flags)) | ||
2490 | goto chip_reset; | ||
2491 | |||
2492 | wait = jiffies + (FW_ALIVE_WAIT_TOV * HZ); | ||
2493 | while (time_before(jiffies, wait)) { | ||
2494 | if (qla4_8xxx_check_fw_alive(ha)) { | ||
2495 | qla4xxx_mailbox_premature_completion(ha); | ||
2496 | break; | ||
2497 | } | ||
2498 | |||
2499 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2500 | schedule_timeout(HZ); | ||
2501 | } | ||
2502 | |||
2467 | if (!test_bit(AF_FW_RECOVERY, &ha->flags)) | 2503 | if (!test_bit(AF_FW_RECOVERY, &ha->flags)) |
2468 | qla4xxx_cmd_wait(ha); | 2504 | qla4xxx_cmd_wait(ha); |
2505 | chip_reset: | ||
2469 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 2506 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
2470 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); | 2507 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); |
2471 | DEBUG2(ql4_printk(KERN_INFO, ha, | 2508 | DEBUG2(ql4_printk(KERN_INFO, ha, |
@@ -2501,6 +2538,25 @@ recover_ha_init_adapter: | |||
2501 | * Since we don't want to block the DPC for too long | 2538 | * Since we don't want to block the DPC for too long |
2502 | * with multiple resets in the same thread, | 2539 | * with multiple resets in the same thread, |
2503 | * utilize DPC to retry */ | 2540 | * utilize DPC to retry */ |
2541 | if (is_qla8022(ha)) { | ||
2542 | qla4_8xxx_idc_lock(ha); | ||
2543 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
2544 | qla4_8xxx_idc_unlock(ha); | ||
2545 | if (dev_state == QLA82XX_DEV_FAILED) { | ||
2546 | ql4_printk(KERN_INFO, ha, "%s: don't retry " | ||
2547 | "recover adapter. H/W is in Failed " | ||
2548 | "state\n", __func__); | ||
2549 | qla4xxx_dead_adapter_cleanup(ha); | ||
2550 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | ||
2551 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
2552 | clear_bit(DPC_RESET_HA_FW_CONTEXT, | ||
2553 | &ha->dpc_flags); | ||
2554 | status = QLA_ERROR; | ||
2555 | |||
2556 | goto exit_recover; | ||
2557 | } | ||
2558 | } | ||
2559 | |||
2504 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { | 2560 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { |
2505 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; | 2561 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; |
2506 | DEBUG2(printk("scsi%ld: recover adapter - retrying " | 2562 | DEBUG2(printk("scsi%ld: recover adapter - retrying " |
@@ -2539,6 +2595,7 @@ recover_ha_init_adapter: | |||
2539 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | 2595 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); |
2540 | } | 2596 | } |
2541 | 2597 | ||
2598 | exit_recover: | ||
2542 | ha->adapter_error_count++; | 2599 | ha->adapter_error_count++; |
2543 | 2600 | ||
2544 | if (test_bit(AF_ONLINE, &ha->flags)) | 2601 | if (test_bit(AF_ONLINE, &ha->flags)) |
@@ -2806,6 +2863,7 @@ dpc_post_reset_ha: | |||
2806 | **/ | 2863 | **/ |
2807 | static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | 2864 | static void qla4xxx_free_adapter(struct scsi_qla_host *ha) |
2808 | { | 2865 | { |
2866 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); | ||
2809 | 2867 | ||
2810 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { | 2868 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { |
2811 | /* Turn-off interrupts on the card. */ | 2869 | /* Turn-off interrupts on the card. */ |
@@ -4816,6 +4874,20 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) | |||
4816 | } | 4874 | } |
4817 | 4875 | ||
4818 | /** | 4876 | /** |
4877 | * qla4xxx_is_eh_active - check if error handler is running | ||
4878 | * @shost: Pointer to SCSI Host struct | ||
4879 | * | ||
4880 | * This routine finds that if reset host is called in EH | ||
4881 | * scenario or from some application like sg_reset | ||
4882 | **/ | ||
4883 | static int qla4xxx_is_eh_active(struct Scsi_Host *shost) | ||
4884 | { | ||
4885 | if (shost->shost_state == SHOST_RECOVERY) | ||
4886 | return 1; | ||
4887 | return 0; | ||
4888 | } | ||
4889 | |||
4890 | /** | ||
4819 | * qla4xxx_eh_host_reset - kernel callback | 4891 | * qla4xxx_eh_host_reset - kernel callback |
4820 | * @cmd: Pointer to Linux's SCSI command structure | 4892 | * @cmd: Pointer to Linux's SCSI command structure |
4821 | * | 4893 | * |
@@ -4832,6 +4904,11 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
4832 | if (ql4xdontresethba) { | 4904 | if (ql4xdontresethba) { |
4833 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", | 4905 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", |
4834 | ha->host_no, __func__)); | 4906 | ha->host_no, __func__)); |
4907 | |||
4908 | /* Clear outstanding srb in queues */ | ||
4909 | if (qla4xxx_is_eh_active(cmd->device->host)) | ||
4910 | qla4xxx_abort_active_cmds(ha, DID_ABORT << 16); | ||
4911 | |||
4835 | return FAILED; | 4912 | return FAILED; |
4836 | } | 4913 | } |
4837 | 4914 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 5254e57968f5..26a3fa34a33c 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,4 +5,4 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k9" | 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k10" |