[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>
This commit is contained in:
Родитель
4247934397
Коммит
71e5600362
|
@ -11,7 +11,7 @@
|
||||||
* ----------------------------------------------------------------------
|
* ----------------------------------------------------------------------
|
||||||
* | Level | Last Value Used | Holes |
|
* | Level | Last Value Used | Holes |
|
||||||
* ----------------------------------------------------------------------
|
* ----------------------------------------------------------------------
|
||||||
* | Module Init and Probe | 0x0151 | 0x4b,0xba,0xfa |
|
* | Module Init and Probe | 0x0152 | 0x4b,0xba,0xfa |
|
||||||
* | Mailbox commands | 0x1181 | 0x111a-0x111b |
|
* | Mailbox commands | 0x1181 | 0x111a-0x111b |
|
||||||
* | | | 0x1155-0x1158 |
|
* | | | 0x1155-0x1158 |
|
||||||
* | | | 0x1018-0x1019 |
|
* | | | 0x1018-0x1019 |
|
||||||
|
@ -26,11 +26,11 @@
|
||||||
* | | | 0x3036,0x3038 |
|
* | | | 0x3036,0x3038 |
|
||||||
* | | | 0x303a |
|
* | | | 0x303a |
|
||||||
* | DPC Thread | 0x4022 | 0x4002,0x4013 |
|
* | DPC Thread | 0x4022 | 0x4002,0x4013 |
|
||||||
* | Async Events | 0x5081 | 0x502b-0x502f |
|
* | Async Events | 0x5083 | 0x502b-0x502f |
|
||||||
* | | | 0x5047,0x5052 |
|
* | | | 0x5047,0x5052 |
|
||||||
* | | | 0x5040,0x5075 |
|
* | | | 0x5040,0x5075 |
|
||||||
* | | | 0x503d,0x5044 |
|
* | | | 0x503d,0x5044 |
|
||||||
* | Timer Routines | 0x6011 | |
|
* | Timer Routines | 0x6012 | |
|
||||||
* | User Space Interactions | 0x70dd | 0x7018,0x702e, |
|
* | User Space Interactions | 0x70dd | 0x7018,0x702e, |
|
||||||
* | | | 0x7020,0x7024, |
|
* | | | 0x7020,0x7024, |
|
||||||
* | | | 0x7039,0x7045, |
|
* | | | 0x7039,0x7045, |
|
||||||
|
|
|
@ -3369,6 +3369,7 @@ typedef struct scsi_qla_host {
|
||||||
#define PORT_UPDATE_NEEDED 24
|
#define PORT_UPDATE_NEEDED 24
|
||||||
#define FX00_RESET_RECOVERY 25
|
#define FX00_RESET_RECOVERY 25
|
||||||
#define FX00_TARGET_SCAN 26
|
#define FX00_TARGET_SCAN 26
|
||||||
|
#define FX00_CRITEMP_RECOVERY 27
|
||||||
|
|
||||||
uint32_t device_flags;
|
uint32_t device_flags;
|
||||||
#define SWITCH_FOUND BIT_0
|
#define SWITCH_FOUND BIT_0
|
||||||
|
|
|
@ -1372,21 +1372,22 @@ qlafx00_configure_devices(scsi_qla_host_t *vha)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha)
|
qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha, bool critemp)
|
||||||
{
|
{
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
fc_port_t *fcport;
|
fc_port_t *fcport;
|
||||||
|
|
||||||
vha->flags.online = 0;
|
vha->flags.online = 0;
|
||||||
ha->flags.chip_reset_done = 0;
|
|
||||||
ha->mr.fw_hbt_en = 0;
|
ha->mr.fw_hbt_en = 0;
|
||||||
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
|
||||||
vha->qla_stats.total_isp_aborts++;
|
|
||||||
|
|
||||||
ql_log(ql_log_info, vha, 0x013f,
|
if (!critemp) {
|
||||||
"Performing ISP error recovery - ha = %p.\n", ha);
|
ha->flags.chip_reset_done = 0;
|
||||||
|
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||||
ha->isp_ops->reset_chip(vha);
|
vha->qla_stats.total_isp_aborts++;
|
||||||
|
ql_log(ql_log_info, vha, 0x013f,
|
||||||
|
"Performing ISP error recovery - ha = %p.\n", ha);
|
||||||
|
ha->isp_ops->reset_chip(vha);
|
||||||
|
}
|
||||||
|
|
||||||
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
|
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
|
||||||
atomic_set(&vha->loop_state, LOOP_DOWN);
|
atomic_set(&vha->loop_state, LOOP_DOWN);
|
||||||
|
@ -1406,12 +1407,19 @@ qlafx00_abort_isp_cleanup(scsi_qla_host_t *vha)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ha->flags.eeh_busy) {
|
if (!ha->flags.eeh_busy) {
|
||||||
/* Requeue all commands in outstanding command list. */
|
if (critemp) {
|
||||||
qla2x00_abort_all_cmds(vha, DID_RESET << 16);
|
qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
|
||||||
|
} else {
|
||||||
|
/* Requeue all commands in outstanding command list. */
|
||||||
|
qla2x00_abort_all_cmds(vha, DID_RESET << 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qla2x00_free_irqs(vha);
|
qla2x00_free_irqs(vha);
|
||||||
set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
|
if (critemp)
|
||||||
|
set_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags);
|
||||||
|
else
|
||||||
|
set_bit(FX00_RESET_RECOVERY, &vha->dpc_flags);
|
||||||
|
|
||||||
/* Clear the Interrupts */
|
/* Clear the Interrupts */
|
||||||
QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
|
QLAFX00_CLR_INTR_REG(ha, QLAFX00_HST_INT_STS_BITS);
|
||||||
|
@ -1498,6 +1506,7 @@ qlafx00_timer_routine(scsi_qla_host_t *vha)
|
||||||
uint32_t fw_heart_beat;
|
uint32_t fw_heart_beat;
|
||||||
uint32_t aenmbx0;
|
uint32_t aenmbx0;
|
||||||
struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
|
struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
|
||||||
|
uint32_t tempc;
|
||||||
|
|
||||||
/* Check firmware health */
|
/* Check firmware health */
|
||||||
if (ha->mr.fw_hbt_cnt)
|
if (ha->mr.fw_hbt_cnt)
|
||||||
|
@ -1569,6 +1578,29 @@ qlafx00_timer_routine(scsi_qla_host_t *vha)
|
||||||
ha->mr.old_aenmbx0_state = aenmbx0;
|
ha->mr.old_aenmbx0_state = aenmbx0;
|
||||||
ha->mr.fw_reset_timer_tick--;
|
ha->mr.fw_reset_timer_tick--;
|
||||||
}
|
}
|
||||||
|
if (test_bit(FX00_CRITEMP_RECOVERY, &vha->dpc_flags)) {
|
||||||
|
/*
|
||||||
|
* Critical temperature recovery to be
|
||||||
|
* performed in timer routine
|
||||||
|
*/
|
||||||
|
if (ha->mr.fw_critemp_timer_tick == 0) {
|
||||||
|
tempc = QLAFX00_GET_TEMPERATURE(ha);
|
||||||
|
ql_log(ql_dbg_timer, vha, 0x6012,
|
||||||
|
"ISPFx00(%s): Critical temp timer, "
|
||||||
|
"current SOC temperature: %d\n",
|
||||||
|
__func__, tempc);
|
||||||
|
if (tempc < ha->mr.critical_temperature) {
|
||||||
|
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||||
|
clear_bit(FX00_CRITEMP_RECOVERY,
|
||||||
|
&vha->dpc_flags);
|
||||||
|
qla2xxx_wake_dpc(vha);
|
||||||
|
}
|
||||||
|
ha->mr.fw_critemp_timer_tick =
|
||||||
|
QLAFX00_CRITEMP_INTERVAL;
|
||||||
|
} else {
|
||||||
|
ha->mr.fw_critemp_timer_tick--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1596,7 +1628,7 @@ qlafx00_reset_initialize(scsi_qla_host_t *vha)
|
||||||
|
|
||||||
if (vha->flags.online) {
|
if (vha->flags.online) {
|
||||||
scsi_block_requests(vha->host);
|
scsi_block_requests(vha->host);
|
||||||
qlafx00_abort_isp_cleanup(vha);
|
qlafx00_abort_isp_cleanup(vha, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ql_log(ql_log_info, vha, 0x0143,
|
ql_log(ql_log_info, vha, 0x0143,
|
||||||
|
@ -1628,7 +1660,7 @@ qlafx00_abort_isp(scsi_qla_host_t *vha)
|
||||||
}
|
}
|
||||||
|
|
||||||
scsi_block_requests(vha->host);
|
scsi_block_requests(vha->host);
|
||||||
qlafx00_abort_isp_cleanup(vha);
|
qlafx00_abort_isp_cleanup(vha, false);
|
||||||
} else {
|
} else {
|
||||||
scsi_block_requests(vha->host);
|
scsi_block_requests(vha->host);
|
||||||
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
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)
|
||||||
aen_code = FCH_EVT_LINKDOWN;
|
aen_code = FCH_EVT_LINKDOWN;
|
||||||
aen_data = 0;
|
aen_data = 0;
|
||||||
break;
|
break;
|
||||||
|
case QLAFX00_MBA_TEMP_OVER:
|
||||||
|
case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */
|
||||||
|
ql_log(ql_log_info, vha, 0x5082,
|
||||||
|
"Process critical temperature event "
|
||||||
|
"aenmb[0]: %x\n",
|
||||||
|
evt->u.aenfx.evtcode);
|
||||||
|
scsi_block_requests(vha->host);
|
||||||
|
qlafx00_abort_isp_cleanup(vha, true);
|
||||||
|
scsi_unblock_requests(vha->host);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fc_host_post_event(vha->host, fc_get_event_number(),
|
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)
|
||||||
sizeof(vha->hw->mr.uboot_version));
|
sizeof(vha->hw->mr.uboot_version));
|
||||||
memcpy(&vha->hw->mr.fru_serial_num, pinfo->fru_serial_num,
|
memcpy(&vha->hw->mr.fru_serial_num, pinfo->fru_serial_num,
|
||||||
sizeof(vha->hw->mr.fru_serial_num));
|
sizeof(vha->hw->mr.fru_serial_num));
|
||||||
|
vha->hw->mr.critical_temperature = pinfo->nominal_temp_value;
|
||||||
} else if (fx_type == FXDISC_GET_PORT_INFO) {
|
} else if (fx_type == FXDISC_GET_PORT_INFO) {
|
||||||
struct port_info_data *pinfo =
|
struct port_info_data *pinfo =
|
||||||
(struct port_info_data *) fdisc->u.fxiocb.rsp_addr;
|
(struct port_info_data *) fdisc->u.fxiocb.rsp_addr;
|
||||||
|
@ -2055,6 +2098,7 @@ qlafx00_initialize_adapter(scsi_qla_host_t *vha)
|
||||||
{
|
{
|
||||||
int rval;
|
int rval;
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
uint32_t tempc;
|
||||||
|
|
||||||
/* Clear adapter flags. */
|
/* Clear adapter flags. */
|
||||||
vha->flags.online = 0;
|
vha->flags.online = 0;
|
||||||
|
@ -2105,6 +2149,11 @@ qlafx00_initialize_adapter(scsi_qla_host_t *vha)
|
||||||
rval = qla2x00_init_rings(vha);
|
rval = qla2x00_init_rings(vha);
|
||||||
ha->flags.chip_reset_done = 1;
|
ha->flags.chip_reset_done = 1;
|
||||||
|
|
||||||
|
tempc = QLAFX00_GET_TEMPERATURE(ha);
|
||||||
|
ql_dbg(ql_dbg_init, vha, 0x0152,
|
||||||
|
"ISPFx00(%s): Critical temp timer, current SOC temperature: 0x%x\n",
|
||||||
|
__func__, tempc);
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2854,6 +2903,17 @@ qlafx00_async_event(scsi_qla_host_t *vha)
|
||||||
ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3]);
|
ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3]);
|
||||||
data_size = 4;
|
data_size = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QLAFX00_MBA_TEMP_OVER: /* Over temperature event */
|
||||||
|
case QLAFX00_MBA_TEMP_CRIT: /* Critical temperature event */
|
||||||
|
ql_log(ql_log_info, vha, 0x5083,
|
||||||
|
"Asynchronous critical temperature event received "
|
||||||
|
"aenmb[0]: %x\n",
|
||||||
|
ha->aenmb[0]);
|
||||||
|
qlafx00_post_aenfx_work(vha, ha->aenmb[0],
|
||||||
|
(uint32_t *)ha->aenmb, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ha->aenmb[1] = RD_REG_WORD(®->aenmailbox1);
|
ha->aenmb[1] = RD_REG_WORD(®->aenmailbox1);
|
||||||
ha->aenmb[2] = RD_REG_WORD(®->aenmailbox2);
|
ha->aenmb[2] = RD_REG_WORD(®->aenmailbox2);
|
||||||
|
|
|
@ -329,11 +329,13 @@ struct config_info_data {
|
||||||
uint64_t adapter_id;
|
uint64_t adapter_id;
|
||||||
|
|
||||||
uint32_t cluster_key_len;
|
uint32_t cluster_key_len;
|
||||||
uint8_t cluster_key[10];
|
uint8_t cluster_key[16];
|
||||||
|
|
||||||
uint64_t cluster_master_id;
|
uint64_t cluster_master_id;
|
||||||
uint64_t cluster_slave_id;
|
uint64_t cluster_slave_id;
|
||||||
uint8_t cluster_flags;
|
uint8_t cluster_flags;
|
||||||
|
uint32_t enabled_capabilities;
|
||||||
|
uint32_t nominal_temp_value;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define FXDISC_GET_CONFIG_INFO 0x01
|
#define FXDISC_GET_CONFIG_INFO 0x01
|
||||||
|
@ -346,6 +348,7 @@ struct config_info_data {
|
||||||
#define QLAFX00_ICR_ENB_MASK 0x80000000
|
#define QLAFX00_ICR_ENB_MASK 0x80000000
|
||||||
#define QLAFX00_ICR_DIS_MASK 0x7fffffff
|
#define QLAFX00_ICR_DIS_MASK 0x7fffffff
|
||||||
#define QLAFX00_HST_RST_REG 0x18264
|
#define QLAFX00_HST_RST_REG 0x18264
|
||||||
|
#define QLAFX00_SOC_TEMP_REG 0x184C4
|
||||||
#define QLAFX00_HST_TO_HBA_REG 0x20A04
|
#define QLAFX00_HST_TO_HBA_REG 0x20A04
|
||||||
#define QLAFX00_HBA_TO_HOST_REG 0x21B70
|
#define QLAFX00_HBA_TO_HOST_REG 0x21B70
|
||||||
#define QLAFX00_HST_INT_STS_BITS 0x7
|
#define QLAFX00_HST_INT_STS_BITS 0x7
|
||||||
|
@ -361,6 +364,9 @@ struct config_info_data {
|
||||||
#define QLAFX00_INTR_ALL_CMPLT 0x7
|
#define QLAFX00_INTR_ALL_CMPLT 0x7
|
||||||
|
|
||||||
#define QLAFX00_MBA_SYSTEM_ERR 0x8002
|
#define QLAFX00_MBA_SYSTEM_ERR 0x8002
|
||||||
|
#define QLAFX00_MBA_TEMP_OVER 0x8005
|
||||||
|
#define QLAFX00_MBA_TEMP_NORM 0x8006
|
||||||
|
#define QLAFX00_MBA_TEMP_CRIT 0x8007
|
||||||
#define QLAFX00_MBA_LINK_UP 0x8011
|
#define QLAFX00_MBA_LINK_UP 0x8011
|
||||||
#define QLAFX00_MBA_LINK_DOWN 0x8012
|
#define QLAFX00_MBA_LINK_DOWN 0x8012
|
||||||
#define QLAFX00_MBA_PORT_UPDATE 0x8014
|
#define QLAFX00_MBA_PORT_UPDATE 0x8014
|
||||||
|
@ -501,12 +507,31 @@ struct mr_data_fx00 {
|
||||||
uint32_t old_fw_hbt_cnt;
|
uint32_t old_fw_hbt_cnt;
|
||||||
uint16_t fw_reset_timer_tick;
|
uint16_t fw_reset_timer_tick;
|
||||||
uint8_t fw_reset_timer_exp;
|
uint8_t fw_reset_timer_exp;
|
||||||
|
uint16_t fw_critemp_timer_tick;
|
||||||
uint32_t old_aenmbx0_state;
|
uint32_t old_aenmbx0_state;
|
||||||
|
uint32_t critical_temperature;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SoC Junction Temperature is stored in
|
||||||
|
* bits 9:1 of SoC Junction Temperature Register
|
||||||
|
* in a firmware specific format format.
|
||||||
|
* To get the temperature in Celsius degrees
|
||||||
|
* the value from this bitfiled should be converted
|
||||||
|
* using this formula:
|
||||||
|
* Temperature (degrees C) = ((3,153,000 - (10,000 * X)) / 13,825)
|
||||||
|
* where X is the bit field value
|
||||||
|
* this macro reads the register, extracts the bitfield value,
|
||||||
|
* performs the calcualtions and returns temperature in Celsius
|
||||||
|
*/
|
||||||
|
#define QLAFX00_GET_TEMPERATURE(ha) ((3153000 - (10000 * \
|
||||||
|
((QLAFX00_RD_REG(ha, QLAFX00_SOC_TEMP_REG) & 0x3FE) >> 1))) / 13825)
|
||||||
|
|
||||||
|
|
||||||
#define QLAFX00_LOOP_DOWN_TIME 615 /* 600 */
|
#define QLAFX00_LOOP_DOWN_TIME 615 /* 600 */
|
||||||
#define QLAFX00_HEARTBEAT_INTERVAL 6 /* number of seconds */
|
#define QLAFX00_HEARTBEAT_INTERVAL 6 /* number of seconds */
|
||||||
#define QLAFX00_HEARTBEAT_MISS_CNT 3 /* number of miss */
|
#define QLAFX00_HEARTBEAT_MISS_CNT 3 /* number of miss */
|
||||||
#define QLAFX00_RESET_INTERVAL 120 /* number of seconds */
|
#define QLAFX00_RESET_INTERVAL 120 /* number of seconds */
|
||||||
#define QLAFX00_MAX_RESET_INTERVAL 600 /* number of seconds */
|
#define QLAFX00_MAX_RESET_INTERVAL 600 /* number of seconds */
|
||||||
|
#define QLAFX00_CRITEMP_INTERVAL 60 /* number of seconds */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2575,6 +2575,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
ha->port_down_retry_count = 30; /* default value */
|
ha->port_down_retry_count = 30; /* default value */
|
||||||
ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
|
ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
|
||||||
ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
|
ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
|
||||||
|
ha->mr.fw_critemp_timer_tick = QLAFX00_CRITEMP_INTERVAL;
|
||||||
ha->mr.fw_hbt_en = 1;
|
ha->mr.fw_hbt_en = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче