aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-12-02 08:46:24 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-03 12:08:03 -0500
commit71839f7d162f973f5931d30d1376a2dc5c0bed5a (patch)
tree0187d9996d6a2d4945acf1eaafa0f062935e4621 /drivers/net/sfc
parent4484cd7dedecf59aee0775c6658f95bdee65f277 (diff)
sfc: Distinguish critical and non-critical over-temperature conditions
Set both the 'maximum' and critical temperature limits for LM87 hardware monitors on Falcon boards. Do not shut down a port until the critical temperature is reached, but warn as soon as the 'maximum' temperature is reached. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/falcon_boards.c109
1 files changed, 80 insertions, 29 deletions
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index cfc29d76758..86180ee02ec 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -30,17 +30,28 @@
30#define FALCON_BOARD_SFN4112F 0x52 30#define FALCON_BOARD_SFN4112F 0x52
31 31
32/* Board temperature is about 15°C above ambient when air flow is 32/* Board temperature is about 15°C above ambient when air flow is
33 * limited. */ 33 * limited. The maximum acceptable ambient temperature varies
34 * depending on the PHY specifications but the critical temperature
35 * above which we should shut down to avoid damage is 80°C. */
34#define FALCON_BOARD_TEMP_BIAS 15 36#define FALCON_BOARD_TEMP_BIAS 15
37#define FALCON_BOARD_TEMP_CRIT (80 + FALCON_BOARD_TEMP_BIAS)
35 38
36/* SFC4000 datasheet says: 'The maximum permitted junction temperature 39/* SFC4000 datasheet says: 'The maximum permitted junction temperature
37 * is 125°C; the thermal design of the environment for the SFC4000 40 * is 125°C; the thermal design of the environment for the SFC4000
38 * should aim to keep this well below 100°C.' */ 41 * should aim to keep this well below 100°C.' */
42#define FALCON_JUNC_TEMP_MIN 0
39#define FALCON_JUNC_TEMP_MAX 90 43#define FALCON_JUNC_TEMP_MAX 90
44#define FALCON_JUNC_TEMP_CRIT 125
40 45
41/***************************************************************************** 46/*****************************************************************************
42 * Support for LM87 sensor chip used on several boards 47 * Support for LM87 sensor chip used on several boards
43 */ 48 */
49#define LM87_REG_TEMP_HW_INT_LOCK 0x13
50#define LM87_REG_TEMP_HW_EXT_LOCK 0x14
51#define LM87_REG_TEMP_HW_INT 0x17
52#define LM87_REG_TEMP_HW_EXT 0x18
53#define LM87_REG_TEMP_EXT1 0x26
54#define LM87_REG_TEMP_INT 0x27
44#define LM87_REG_ALARMS1 0x41 55#define LM87_REG_ALARMS1 0x41
45#define LM87_REG_ALARMS2 0x42 56#define LM87_REG_ALARMS2 0x42
46#define LM87_IN_LIMITS(nr, _min, _max) \ 57#define LM87_IN_LIMITS(nr, _min, _max) \
@@ -57,6 +68,27 @@
57 68
58#if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE) 69#if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE)
59 70
71static int efx_poke_lm87(struct i2c_client *client, const u8 *reg_values)
72{
73 while (*reg_values) {
74 u8 reg = *reg_values++;
75 u8 value = *reg_values++;
76 int rc = i2c_smbus_write_byte_data(client, reg, value);
77 if (rc)
78 return rc;
79 }
80 return 0;
81}
82
83static const u8 falcon_lm87_common_regs[] = {
84 LM87_REG_TEMP_HW_INT_LOCK, FALCON_BOARD_TEMP_CRIT,
85 LM87_REG_TEMP_HW_INT, FALCON_BOARD_TEMP_CRIT,
86 LM87_TEMP_EXT1_LIMITS(FALCON_JUNC_TEMP_MIN, FALCON_JUNC_TEMP_MAX),
87 LM87_REG_TEMP_HW_EXT_LOCK, FALCON_JUNC_TEMP_CRIT,
88 LM87_REG_TEMP_HW_EXT, FALCON_JUNC_TEMP_CRIT,
89 0
90};
91
60static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, 92static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
61 const u8 *reg_values) 93 const u8 *reg_values)
62{ 94{
@@ -67,13 +99,12 @@ static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
67 if (!client) 99 if (!client)
68 return -EIO; 100 return -EIO;
69 101
70 while (*reg_values) { 102 rc = efx_poke_lm87(client, reg_values);
71 u8 reg = *reg_values++; 103 if (rc)
72 u8 value = *reg_values++; 104 goto err;
73 rc = i2c_smbus_write_byte_data(client, reg, value); 105 rc = efx_poke_lm87(client, falcon_lm87_common_regs);
74 if (rc) 106 if (rc)
75 goto err; 107 goto err;
76 }
77 108
78 board->hwmon_client = client; 109 board->hwmon_client = client;
79 return 0; 110 return 0;
@@ -91,36 +122,56 @@ static void efx_fini_lm87(struct efx_nic *efx)
91static int efx_check_lm87(struct efx_nic *efx, unsigned mask) 122static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
92{ 123{
93 struct i2c_client *client = falcon_board(efx)->hwmon_client; 124 struct i2c_client *client = falcon_board(efx)->hwmon_client;
94 s32 alarms1, alarms2; 125 bool temp_crit, elec_fault, is_failure;
126 u16 alarms;
127 s32 reg;
95 128
96 /* If link is up then do not monitor temperature */ 129 /* If link is up then do not monitor temperature */
97 if (EFX_WORKAROUND_7884(efx) && efx->link_state.up) 130 if (EFX_WORKAROUND_7884(efx) && efx->link_state.up)
98 return 0; 131 return 0;
99 132
100 alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1); 133 reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
101 alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2); 134 if (reg < 0)
102 if (alarms1 < 0) 135 return reg;
103 return alarms1; 136 alarms = reg;
104 if (alarms2 < 0) 137 reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
105 return alarms2; 138 if (reg < 0)
106 alarms1 &= mask; 139 return reg;
107 alarms2 &= mask >> 8; 140 alarms |= reg << 8;
108 if (alarms1 || alarms2) { 141 alarms &= mask;
142
143 temp_crit = false;
144 if (alarms & LM87_ALARM_TEMP_INT) {
145 reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_INT);
146 if (reg < 0)
147 return reg;
148 if (reg > FALCON_BOARD_TEMP_CRIT)
149 temp_crit = true;
150 }
151 if (alarms & LM87_ALARM_TEMP_EXT1) {
152 reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_EXT1);
153 if (reg < 0)
154 return reg;
155 if (reg > FALCON_JUNC_TEMP_CRIT)
156 temp_crit = true;
157 }
158 elec_fault = alarms & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1);
159 is_failure = temp_crit || elec_fault;
160
161 if (alarms)
109 netif_err(efx, hw, efx->net_dev, 162 netif_err(efx, hw, efx->net_dev,
110 "LM87 detected a hardware failure (status %02x:%02x)" 163 "LM87 detected a hardware %s (status %02x:%02x)"
111 "%s%s%s\n", 164 "%s%s%s%s\n",
112 alarms1, alarms2, 165 is_failure ? "failure" : "problem",
113 (alarms1 & LM87_ALARM_TEMP_INT) ? 166 alarms & 0xff, alarms >> 8,
167 (alarms & LM87_ALARM_TEMP_INT) ?
114 "; board is overheating" : "", 168 "; board is overheating" : "",
115 (alarms1 & LM87_ALARM_TEMP_EXT1) ? 169 (alarms & LM87_ALARM_TEMP_EXT1) ?
116 "; controller is overheating" : "", 170 "; controller is overheating" : "",
117 (alarms1 & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1) 171 temp_crit ? "; reached critical temperature" : "",
118 || alarms2) ? 172 elec_fault ? "; electrical fault" : "");
119 "; electrical fault" : "");
120 return -ERANGE;
121 }
122 173
123 return 0; 174 return is_failure ? -ERANGE : 0;
124} 175}
125 176
126#else /* !CONFIG_SENSORS_LM87 */ 177#else /* !CONFIG_SENSORS_LM87 */