aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorArmen Baloyan <armen.baloyan@qlogic.com>2013-08-27 01:37:38 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-09-03 10:28:03 -0400
commit71e56003621b2347405c65c3061e5dc0fa9cdd98 (patch)
tree80d656817b2b869062882ec58d384329731b9838 /drivers/scsi/qla2xxx
parent4247934397d7bf4105a9fd5abcf990954cf39d5f (diff)
[SCSI] qla2xxx: Add critical temperature handling for ISPFX00.
Signed-off-by: Armen Baloyan <armen.baloyan@qlogic.com> Acked-by: Srinivasa Rao <srinivasa.rao@qlogic.com> Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.c86
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.h27
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c1
5 files changed, 104 insertions, 17 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index aa31f7ab78ce..b1b6bc150c81 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -11,7 +11,7 @@
11 * ---------------------------------------------------------------------- 11 * ----------------------------------------------------------------------
12 * | Level | Last Value Used | Holes | 12 * | Level | Last Value Used | Holes |
13 * ---------------------------------------------------------------------- 13 * ----------------------------------------------------------------------
14 * | Module Init and Probe | 0x0151 | 0x4b,0xba,0xfa | 14 * | Module Init and Probe | 0x0152 | 0x4b,0xba,0xfa |
15 * | Mailbox commands | 0x1181 | 0x111a-0x111b | 15 * | Mailbox commands | 0x1181 | 0x111a-0x111b |
16 * | | | 0x1155-0x1158 | 16 * | | | 0x1155-0x1158 |
17 * | | | 0x1018-0x1019 | 17 * | | | 0x1018-0x1019 |
@@ -26,11 +26,11 @@
26 * | | | 0x3036,0x3038 | 26 * | | | 0x3036,0x3038 |
27 * | | | 0x303a | 27 * | | | 0x303a |
28 * | DPC Thread | 0x4022 | 0x4002,0x4013 | 28 * | DPC Thread | 0x4022 | 0x4002,0x4013 |
29 * | Async Events | 0x5081 | 0x502b-0x502f | 29 * | Async Events | 0x5083 | 0x502b-0x502f |
30 * | | | 0x5047,0x5052 | 30 * | | | 0x5047,0x5052 |
31 * | | | 0x5040,0x5075 | 31 * | | | 0x5040,0x5075 |
32 * | | | 0x503d,0x5044 | 32 * | | | 0x503d,0x5044 |
33 * | Timer Routines | 0x6011 | | 33 * | Timer Routines | 0x6012 | |
34 * | User Space Interactions | 0x70dd | 0x7018,0x702e, | 34 * | User Space Interactions | 0x70dd | 0x7018,0x702e, |
35 * | | | 0x7020,0x7024, | 35 * | | | 0x7020,0x7024, |
36 * | | | 0x7039,0x7045, | 36 * | | | 0x7039,0x7045, |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a494e2e74693..e5d3373e7aeb 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3369,6 +3369,7 @@ typedef struct scsi_qla_host {
3369#define PORT_UPDATE_NEEDED 24 3369#define PORT_UPDATE_NEEDED 24
3370#define FX00_RESET_RECOVERY 25 3370#define FX00_RESET_RECOVERY 25
3371#define FX00_TARGET_SCAN 26 3371#define FX00_TARGET_SCAN 26
3372#define FX00_CRITEMP_RECOVERY 27
3372 3373
3373 uint32_t device_flags; 3374 uint32_t device_flags;
3374#define SWITCH_FOUND BIT_0 3375#define SWITCH_FOUND BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index ab2ae8e26fea..27b8af8bc68e 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1372,21 +1372,22 @@ qlafx00_configure_devices(scsi_qla_host_t *vha)
1372} 1372}
1373 1373
1374static void 1374static void
1375qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha) 1375qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha, bool critemp)
1376{ 1376{
1377 struct qla_hw_data *ha = vha->hw; 1377 struct qla_hw_data *ha = vha->hw;
1378 fc_port_t *fcport; 1378 fc_port_t *fcport;
1379 1379
1380 vha->flags.online = 0; 1380 vha->flags.online = 0;
1381 ha->flags.chip_reset_done = 0;
1382 ha->mr.fw_hbt_en = 0; 1381 ha->mr.fw_hbt_en = 0;
1383 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1384 vha->qla_stats.total_isp_aborts++;
1385
1386 ql_log(ql_log_info, vha, 0x013f,
1387 "Performing ISP error recovery - ha = %p.\n", ha);
1388 1382
1389 ha->isp_ops->reset_chip(vha); 1383 if (!critemp) {
1384 ha->flags.chip_reset_done = 0;
1385 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1386 vha->qla_stats.total_isp_aborts++;
1387 ql_log(ql_log_info, vha, 0x013f,
1388 "Performing ISP error recovery - ha = %p.\n", ha);
1389 ha->isp_ops->reset_chip(vha);
1390 }
1390 1391
1391 if (atomic_read(&vha->loop_state) != LOOP_DOWN) { 1392 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
1392 atomic_set(&vha->loop_state, LOOP_DOWN); 1393 atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -1406,12 +1407,19 @@ qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha)
1406 } 1407 }
1407 1408
1408 if (!ha->flags.eeh_busy) { 1409 if (!ha->flags.eeh_busy) {
1409 /* Requeue all commands in outstanding command list. */ 1410 if (critemp) {
1410 qla2x00_abort_all_cmds(vha, DID_RESET << 16); 1411 qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
1412 } else {
1413 /* Requeue all commands in outstanding command list. */
1414 qla2x00_abort_all_cmds(vha, DID_RESET << 16);
1415 }
1411 } 1416 }
1412 1417
1413 qla2x00_free_irqs(vha); 1418 qla2x00_free_irqs(vha);
1414 set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags); 1419 if (critemp)
1420 set_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags);
1421 else
1422 set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
1415 1423
1416 /* Clear the Interrupts */ 1424 /* Clear the Interrupts */
1417 QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS); 1425 QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
@@ -1498,6 +1506,7 @@ qlafx00_timer_routine(scsi_qla_host_t *vha)
1498 uint32_t fw_heart_beat; 1506 uint32_t fw_heart_beat;
1499 uint32_t aenmbx0; 1507 uint32_t aenmbx0;
1500 struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00; 1508 struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
1509 uint32_t tempc;
1501 1510
1502 /* Check firmware health */ 1511 /* Check firmware health */
1503 if (ha->mr.fw_hbt_cnt) 1512 if (ha->mr.fw_hbt_cnt)
@@ -1569,6 +1578,29 @@ qlafx00_timer_routine(scsi_qla_host_t *vha)
1569 ha->mr.old_aenmbx0_state = aenmbx0; 1578 ha->mr.old_aenmbx0_state = aenmbx0;
1570 ha->mr.fw_reset_timer_tick--; 1579 ha->mr.fw_reset_timer_tick--;
1571 } 1580 }
1581 if (test_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags)) {
1582 /*
1583 * Critical temperature recovery to be
1584 * performed in timer routine
1585 */
1586 if (ha->mr.fw_critemp_timer_tick == 0) {
1587 tempc = QLAFX00_GET_TEMPERATURE(ha);
1588 ql_log(ql_dbg_timer, vha, 0x6012,
1589 "ISPFx00(%s): Critical temp timer, "
1590 "current SOC temperature: %d\n",
1591 __func__, tempc);
1592 if (tempc < ha->mr.critical_temperature) {
1593 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
1594 clear_bit(FX00_CRITEMP_RECOVERY,
1595 &vha->dpc_flags);
1596 qla2xxx_wake_dpc(vha);
1597 }
1598 ha->mr.fw_critemp_timer_tick =
1599 QLAFX00_CRITEMP_INTERVAL;
1600 } else {
1601 ha->mr.fw_critemp_timer_tick--;
1602 }
1603 }
1572} 1604}
1573 1605
1574/* 1606/*
@@ -1596,7 +1628,7 @@ qlafx00_reset_initialize(scsi_qla_host_t *vha)
1596 1628
1597 if (vha->flags.online) { 1629 if (vha->flags.online) {
1598 scsi_block_requests(vha->host); 1630 scsi_block_requests(vha->host);
1599 qlafx00_abort_isp_cleanup(vha); 1631 qlafx00_abort_isp_cleanup(vha, false);
1600 } 1632 }
1601 1633
1602 ql_log(ql_log_info, vha, 0x0143, 1634 ql_log(ql_log_info, vha, 0x0143,
@@ -1628,7 +1660,7 @@ qlafx00_abort_isp(scsi_qla_host_t *vha)
1628 } 1660 }
1629 1661
1630 scsi_block_requests(vha->host); 1662 scsi_block_requests(vha->host);
1631 qlafx00_abort_isp_cleanup(vha); 1663 qlafx00_abort_isp_cleanup(vha, false);
1632 } else { 1664 } else {
1633 scsi_block_requests(vha->host); 1665 scsi_block_requests(vha->host);
1634 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); 1666 clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -1722,6 +1754,16 @@ qlafx00_process_aen(struct scsi_qla_host *vha, struct qla_work_evt *evt)
1722 aen_code = FCH_EVT_LINKDOWN; 1754 aen_code = FCH_EVT_LINKDOWN;
1723 aen_data = 0; 1755 aen_data = 0;
1724 break; 1756 break;
1757 case QLAFX00_MBA_TEMP_OVER:
1758 case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */
1759 ql_log(ql_log_info, vha, 0x5082,
1760 "Process critical temperature event "
1761 "aenmb[0]: %x\n",
1762 evt->u.aenfx.evtcode);
1763 scsi_block_requests(vha->host);
1764 qlafx00_abort_isp_cleanup(vha, true);
1765 scsi_unblock_requests(vha->host);
1766 break;
1725 } 1767 }
1726 1768
1727 fc_host_post_event(vha->host, fc_get_event_number(), 1769 fc_host_post_event(vha->host, fc_get_event_number(),
@@ -1913,6 +1955,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
1913 sizeof(vha->hw->mr.uboot_version)); 1955 sizeof(vha->hw->mr.uboot_version));
1914 memcpy(&vha->hw->mr.fru_serial_num, pinfo->fru_serial_num, 1956 memcpy(&vha->hw->mr.fru_serial_num, pinfo->fru_serial_num,
1915 sizeof(vha->hw->mr.fru_serial_num)); 1957 sizeof(vha->hw->mr.fru_serial_num));
1958 vha->hw->mr.critical_temperature = pinfo->nominal_temp_value;
1916 } else if (fx_type == FXDISC_GET_PORT_INFO) { 1959 } else if (fx_type == FXDISC_GET_PORT_INFO) {
1917 struct port_info_data *pinfo = 1960 struct port_info_data *pinfo =
1918 (struct port_info_data *) fdisc->u.fxiocb.rsp_addr; 1961 (struct port_info_data *) fdisc->u.fxiocb.rsp_addr;
@@ -2055,6 +2098,7 @@ qlafx00_initialize_adapter(scsi_qla_host_t *vha)
2055{ 2098{
2056 int rval; 2099 int rval;
2057 struct qla_hw_data *ha = vha->hw; 2100 struct qla_hw_data *ha = vha->hw;
2101 uint32_t tempc;
2058 2102
2059 /* Clear adapter flags. */ 2103 /* Clear adapter flags. */
2060 vha->flags.online = 0; 2104 vha->flags.online = 0;
@@ -2105,6 +2149,11 @@ qlafx00_initialize_adapter(scsi_qla_host_t *vha)
2105 rval = qla2x00_init_rings(vha); 2149 rval = qla2x00_init_rings(vha);
2106 ha->flags.chip_reset_done = 1; 2150 ha->flags.chip_reset_done = 1;
2107 2151
2152 tempc = QLAFX00_GET_TEMPERATURE(ha);
2153 ql_dbg(ql_dbg_init, vha, 0x0152,
2154 "ISPFx00(%s): Critical temp timer, current SOC temperature: 0x%x\n",
2155 __func__, tempc);
2156
2108 return rval; 2157 return rval;
2109} 2158}
2110 2159
@@ -2854,6 +2903,17 @@ qlafx00_async_event(scsi_qla_host_t *vha)
2854 ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3]); 2903 ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3]);
2855 data_size = 4; 2904 data_size = 4;
2856 break; 2905 break;
2906
2907 case QLAFX00_MBA_TEMP_OVER: /* Over temperature event */
2908 case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */
2909 ql_log(ql_log_info, vha, 0x5083,
2910 "Asynchronous critical temperature event received "
2911 "aenmb[0]: %x\n",
2912 ha->aenmb[0]);
2913 qlafx00_post_aenfx_work(vha, ha->aenmb[0],
2914 (uint32_t *)ha->aenmb, 1);
2915 break;
2916
2857 default: 2917 default:
2858 ha->aenmb[1] = RD_REG_WORD(&reg->aenmailbox1); 2918 ha->aenmb[1] = RD_REG_WORD(&reg->aenmailbox1);
2859 ha->aenmb[2] = RD_REG_WORD(&reg->aenmailbox2); 2919 ha->aenmb[2] = RD_REG_WORD(&reg->aenmailbox2);
diff --git a/drivers/scsi/qla2xxx/qla_mr.h b/drivers/scsi/qla2xxx/qla_mr.h
index 179f8e42b1c0..982f7d3b14e7 100644
--- a/drivers/scsi/qla2xxx/qla_mr.h
+++ b/drivers/scsi/qla2xxx/qla_mr.h
@@ -329,11 +329,13 @@ struct config_info_data {
329 uint64_t adapter_id; 329 uint64_t adapter_id;
330 330
331 uint32_t cluster_key_len; 331 uint32_t cluster_key_len;
332 uint8_t cluster_key[10]; 332 uint8_t cluster_key[16];
333 333
334 uint64_t cluster_master_id; 334 uint64_t cluster_master_id;
335 uint64_t cluster_slave_id; 335 uint64_t cluster_slave_id;
336 uint8_t cluster_flags; 336 uint8_t cluster_flags;
337 uint32_t enabled_capabilities;
338 uint32_t nominal_temp_value;
337} __packed; 339} __packed;
338 340
339#define FXDISC_GET_CONFIG_INFO 0x01 341#define FXDISC_GET_CONFIG_INFO 0x01
@@ -346,6 +348,7 @@ struct config_info_data {
346#define QLAFX00_ICR_ENB_MASK 0x80000000 348#define QLAFX00_ICR_ENB_MASK 0x80000000
347#define QLAFX00_ICR_DIS_MASK 0x7fffffff 349#define QLAFX00_ICR_DIS_MASK 0x7fffffff
348#define QLAFX00_HST_RST_REG 0x18264 350#define QLAFX00_HST_RST_REG 0x18264
351#define QLAFX00_SOC_TEMP_REG 0x184C4
349#define QLAFX00_HST_TO_HBA_REG 0x20A04 352#define QLAFX00_HST_TO_HBA_REG 0x20A04
350#define QLAFX00_HBA_TO_HOST_REG 0x21B70 353#define QLAFX00_HBA_TO_HOST_REG 0x21B70
351#define QLAFX00_HST_INT_STS_BITS 0x7 354#define QLAFX00_HST_INT_STS_BITS 0x7
@@ -361,6 +364,9 @@ struct config_info_data {
361#define QLAFX00_INTR_ALL_CMPLT 0x7 364#define QLAFX00_INTR_ALL_CMPLT 0x7
362 365
363#define QLAFX00_MBA_SYSTEM_ERR 0x8002 366#define QLAFX00_MBA_SYSTEM_ERR 0x8002
367#define QLAFX00_MBA_TEMP_OVER 0x8005
368#define QLAFX00_MBA_TEMP_NORM 0x8006
369#define QLAFX00_MBA_TEMP_CRIT 0x8007
364#define QLAFX00_MBA_LINK_UP 0x8011 370#define QLAFX00_MBA_LINK_UP 0x8011
365#define QLAFX00_MBA_LINK_DOWN 0x8012 371#define QLAFX00_MBA_LINK_DOWN 0x8012
366#define QLAFX00_MBA_PORT_UPDATE 0x8014 372#define QLAFX00_MBA_PORT_UPDATE 0x8014
@@ -501,12 +507,31 @@ struct mr_data_fx00 {
501 uint32_t old_fw_hbt_cnt; 507 uint32_t old_fw_hbt_cnt;
502 uint16_t fw_reset_timer_tick; 508 uint16_t fw_reset_timer_tick;
503 uint8_t fw_reset_timer_exp; 509 uint8_t fw_reset_timer_exp;
510 uint16_t fw_critemp_timer_tick;
504 uint32_t old_aenmbx0_state; 511 uint32_t old_aenmbx0_state;
512 uint32_t critical_temperature;
505}; 513};
506 514
515/*
516 * SoC Junction Temperature is stored in
517 * bits 9:1 of SoC Junction Temperature Register
518 * in a firmware specific format format.
519 * To get the temperature in Celsius degrees
520 * the value from this bitfiled should be converted
521 * using this formula:
522 * Temperature (degrees C) = ((3,153,000 - (10,000 * X)) / 13,825)
523 * where X is the bit field value
524 * this macro reads the register, extracts the bitfield value,
525 * performs the calcualtions and returns temperature in Celsius
526 */
527#define QLAFX00_GET_TEMPERATURE(ha) ((3153000 - (10000 * \
528 ((QLAFX00_RD_REG(ha, QLAFX00_SOC_TEMP_REG) & 0x3FE) >> 1))) / 13825)
529
530
507#define QLAFX00_LOOP_DOWN_TIME 615 /* 600 */ 531#define QLAFX00_LOOP_DOWN_TIME 615 /* 600 */
508#define QLAFX00_HEARTBEAT_INTERVAL 6 /* number of seconds */ 532#define QLAFX00_HEARTBEAT_INTERVAL 6 /* number of seconds */
509#define QLAFX00_HEARTBEAT_MISS_CNT 3 /* number of miss */ 533#define QLAFX00_HEARTBEAT_MISS_CNT 3 /* number of miss */
510#define QLAFX00_RESET_INTERVAL 120 /* number of seconds */ 534#define QLAFX00_RESET_INTERVAL 120 /* number of seconds */
511#define QLAFX00_MAX_RESET_INTERVAL 600 /* number of seconds */ 535#define QLAFX00_MAX_RESET_INTERVAL 600 /* number of seconds */
536#define QLAFX00_CRITEMP_INTERVAL 60 /* number of seconds */
512#endif 537#endif
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 17a86b69cb08..7a81ede19dde 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2575,6 +2575,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2575 ha->port_down_retry_count = 30; /* default value */ 2575 ha->port_down_retry_count = 30; /* default value */
2576 ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL; 2576 ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
2577 ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL; 2577 ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
2578 ha->mr.fw_critemp_timer_tick = QLAFX00_CRITEMP_INTERVAL;
2578 ha->mr.fw_hbt_en = 1; 2579 ha->mr.fw_hbt_en = 1;
2579 } 2580 }
2580 2581