diff options
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.h | 19 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 42 |
3 files changed, 58 insertions, 4 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 22a3ff02e48a..ec48dc30b9a2 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -671,6 +671,7 @@ struct scsi_qla_host { | |||
671 | uint16_t pri_ddb_idx; | 671 | uint16_t pri_ddb_idx; |
672 | uint16_t sec_ddb_idx; | 672 | uint16_t sec_ddb_idx; |
673 | int is_reset; | 673 | int is_reset; |
674 | uint16_t temperature; | ||
674 | }; | 675 | }; |
675 | 676 | ||
676 | struct ql4_task_data { | 677 | struct ql4_task_data { |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index 35376a1c3f1b..cfb2f2edac3a 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h | |||
@@ -19,12 +19,25 @@ | |||
19 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 | 19 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 |
20 | 20 | ||
21 | /*CRB_RELATED*/ | 21 | /*CRB_RELATED*/ |
22 | #define QLA82XX_CRB_BASE QLA82XX_CAM_RAM(0x200) | 22 | #define QLA82XX_CRB_BASE (QLA82XX_CAM_RAM(0x200)) |
23 | #define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X)) | 23 | #define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X)) |
24 | |||
25 | #define CRB_CMDPEG_STATE QLA82XX_REG(0x50) | 24 | #define CRB_CMDPEG_STATE QLA82XX_REG(0x50) |
26 | #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) | 25 | #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) |
27 | #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) | 26 | #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) |
27 | #define CRB_TEMP_STATE QLA82XX_REG(0x1b4) | ||
28 | |||
29 | #define qla82xx_get_temp_val(x) ((x) >> 16) | ||
30 | #define qla82xx_get_temp_state(x) ((x) & 0xffff) | ||
31 | #define qla82xx_encode_temp(val, state) (((val) << 16) | (state)) | ||
32 | |||
33 | /* | ||
34 | * Temperature control. | ||
35 | */ | ||
36 | enum { | ||
37 | QLA82XX_TEMP_NORMAL = 0x1, /* Normal operating range */ | ||
38 | QLA82XX_TEMP_WARN, /* Sound alert, temperature getting high */ | ||
39 | QLA82XX_TEMP_PANIC /* Fatal error, hardware has shut down. */ | ||
40 | }; | ||
28 | 41 | ||
29 | #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 | 42 | #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 |
30 | #define QLA82XX_HW_H1_CH_HUB_ADR 0x0E | 43 | #define QLA82XX_HW_H1_CH_HUB_ADR 0x0E |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 0048a3facd7a..9d3eab513935 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -1972,6 +1972,42 @@ mem_alloc_error_exit: | |||
1972 | } | 1972 | } |
1973 | 1973 | ||
1974 | /** | 1974 | /** |
1975 | * qla4_8xxx_check_temp - Check the ISP82XX temperature. | ||
1976 | * @ha: adapter block pointer. | ||
1977 | * | ||
1978 | * Note: The caller should not hold the idc lock. | ||
1979 | **/ | ||
1980 | static int qla4_8xxx_check_temp(struct scsi_qla_host *ha) | ||
1981 | { | ||
1982 | uint32_t temp, temp_state, temp_val; | ||
1983 | int status = QLA_SUCCESS; | ||
1984 | |||
1985 | temp = qla4_8xxx_rd_32(ha, CRB_TEMP_STATE); | ||
1986 | |||
1987 | temp_state = qla82xx_get_temp_state(temp); | ||
1988 | temp_val = qla82xx_get_temp_val(temp); | ||
1989 | |||
1990 | if (temp_state == QLA82XX_TEMP_PANIC) { | ||
1991 | ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C" | ||
1992 | " exceeds maximum allowed. Hardware has been shut" | ||
1993 | " down.\n", temp_val); | ||
1994 | status = QLA_ERROR; | ||
1995 | } else if (temp_state == QLA82XX_TEMP_WARN) { | ||
1996 | if (ha->temperature == QLA82XX_TEMP_NORMAL) | ||
1997 | ql4_printk(KERN_WARNING, ha, "Device temperature %d" | ||
1998 | " degrees C exceeds operating range." | ||
1999 | " Immediate action needed.\n", temp_val); | ||
2000 | } else { | ||
2001 | if (ha->temperature == QLA82XX_TEMP_WARN) | ||
2002 | ql4_printk(KERN_INFO, ha, "Device temperature is" | ||
2003 | " now %d degrees C in normal range.\n", | ||
2004 | temp_val); | ||
2005 | } | ||
2006 | ha->temperature = temp_state; | ||
2007 | return status; | ||
2008 | } | ||
2009 | |||
2010 | /** | ||
1975 | * qla4_8xxx_check_fw_alive - Check firmware health | 2011 | * qla4_8xxx_check_fw_alive - Check firmware health |
1976 | * @ha: Pointer to host adapter structure. | 2012 | * @ha: Pointer to host adapter structure. |
1977 | * | 2013 | * |
@@ -2042,7 +2078,11 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
2042 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 2078 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
2043 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { | 2079 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { |
2044 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 2080 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
2045 | if (dev_state == QLA82XX_DEV_NEED_RESET && | 2081 | |
2082 | if (qla4_8xxx_check_temp(ha)) { | ||
2083 | set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); | ||
2084 | qla4xxx_wake_dpc(ha); | ||
2085 | } else if (dev_state == QLA82XX_DEV_NEED_RESET && | ||
2046 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | 2086 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
2047 | if (!ql4xdontresethba) { | 2087 | if (!ql4xdontresethba) { |
2048 | ql4_printk(KERN_INFO, ha, "%s: HW State: " | 2088 | ql4_printk(KERN_INFO, ha, "%s: HW State: " |