diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2013-08-08 06:14:20 -0400 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2013-08-27 17:29:56 -0400 |
commit | d4fbdcfe93928fbcb7374ea490e41f7b69d95380 (patch) | |
tree | 153ce5ee26d6d128d0d5a0d157dda322ac2fc0e5 /drivers/net/ethernet/sfc/mcdi_mon.c | |
parent | 8c4e720f181f251948c52913c74a86f68aed9c50 (diff) |
sfc: Use extended MC_CMD_SENSOR_INFO and MC_CMD_READ_SENSORS
We need to use extended requests to read and get metadata for sensors
numbered > 31.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/mcdi_mon.c')
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi_mon.c | 139 |
1 files changed, 95 insertions, 44 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c index 544889bacecc..d7d45662d684 100644 --- a/drivers/net/ethernet/sfc/mcdi_mon.c +++ b/drivers/net/ethernet/sfc/mcdi_mon.c | |||
@@ -28,7 +28,7 @@ static const struct { | |||
28 | const char *label; | 28 | const char *label; |
29 | enum efx_hwmon_type hwmon_type; | 29 | enum efx_hwmon_type hwmon_type; |
30 | int port; | 30 | int port; |
31 | } efx_mcdi_sensor_type[MC_CMD_SENSOR_ENTRY_MAXNUM] = { | 31 | } efx_mcdi_sensor_type[] = { |
32 | #define SENSOR(name, label, hwmon_type, port) \ | 32 | #define SENSOR(name, label, hwmon_type, port) \ |
33 | [MC_CMD_SENSOR_##name] = { label, hwmon_type, port } | 33 | [MC_CMD_SENSOR_##name] = { label, hwmon_type, port } |
34 | SENSOR(CONTROLLER_TEMP, "Controller temp.", EFX_HWMON_TEMP, -1), | 34 | SENSOR(CONTROLLER_TEMP, "Controller temp.", EFX_HWMON_TEMP, -1), |
@@ -86,6 +86,7 @@ struct efx_mcdi_mon_attribute { | |||
86 | struct device_attribute dev_attr; | 86 | struct device_attribute dev_attr; |
87 | unsigned int index; | 87 | unsigned int index; |
88 | unsigned int type; | 88 | unsigned int type; |
89 | enum efx_hwmon_type hwmon_type; | ||
89 | unsigned int limit_value; | 90 | unsigned int limit_value; |
90 | char name[12]; | 91 | char name[12]; |
91 | }; | 92 | }; |
@@ -93,11 +94,12 @@ struct efx_mcdi_mon_attribute { | |||
93 | static int efx_mcdi_mon_update(struct efx_nic *efx) | 94 | static int efx_mcdi_mon_update(struct efx_nic *efx) |
94 | { | 95 | { |
95 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); | 96 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); |
96 | MCDI_DECLARE_BUF(inbuf, MC_CMD_READ_SENSORS_IN_LEN); | 97 | MCDI_DECLARE_BUF(inbuf, MC_CMD_READ_SENSORS_EXT_IN_LEN); |
97 | int rc; | 98 | int rc; |
98 | 99 | ||
99 | MCDI_SET_QWORD(inbuf, READ_SENSORS_IN_DMA_ADDR, | 100 | MCDI_SET_QWORD(inbuf, READ_SENSORS_EXT_IN_DMA_ADDR, |
100 | hwmon->dma_buf.dma_addr); | 101 | hwmon->dma_buf.dma_addr); |
102 | MCDI_SET_DWORD(inbuf, READ_SENSORS_EXT_IN_LENGTH, hwmon->dma_buf.len); | ||
101 | 103 | ||
102 | rc = efx_mcdi_rpc(efx, MC_CMD_READ_SENSORS, | 104 | rc = efx_mcdi_rpc(efx, MC_CMD_READ_SENSORS, |
103 | inbuf, sizeof(inbuf), NULL, 0, NULL); | 105 | inbuf, sizeof(inbuf), NULL, 0, NULL); |
@@ -159,7 +161,7 @@ static ssize_t efx_mcdi_mon_show_value(struct device *dev, | |||
159 | value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); | 161 | value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); |
160 | 162 | ||
161 | /* Convert temperature from degrees to milli-degrees Celsius */ | 163 | /* Convert temperature from degrees to milli-degrees Celsius */ |
162 | if (efx_mcdi_sensor_type[mon_attr->type].hwmon_type == EFX_HWMON_TEMP) | 164 | if (mon_attr->hwmon_type == EFX_HWMON_TEMP) |
163 | value *= 1000; | 165 | value *= 1000; |
164 | 166 | ||
165 | return sprintf(buf, "%u\n", value); | 167 | return sprintf(buf, "%u\n", value); |
@@ -176,7 +178,7 @@ static ssize_t efx_mcdi_mon_show_limit(struct device *dev, | |||
176 | value = mon_attr->limit_value; | 178 | value = mon_attr->limit_value; |
177 | 179 | ||
178 | /* Convert temperature from degrees to milli-degrees Celsius */ | 180 | /* Convert temperature from degrees to milli-degrees Celsius */ |
179 | if (efx_mcdi_sensor_type[mon_attr->type].hwmon_type == EFX_HWMON_TEMP) | 181 | if (mon_attr->hwmon_type == EFX_HWMON_TEMP) |
180 | value *= 1000; | 182 | value *= 1000; |
181 | 183 | ||
182 | return sprintf(buf, "%u\n", value); | 184 | return sprintf(buf, "%u\n", value); |
@@ -224,6 +226,10 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, | |||
224 | strlcpy(attr->name, name, sizeof(attr->name)); | 226 | strlcpy(attr->name, name, sizeof(attr->name)); |
225 | attr->index = index; | 227 | attr->index = index; |
226 | attr->type = type; | 228 | attr->type = type; |
229 | if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) | ||
230 | attr->hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; | ||
231 | else | ||
232 | attr->hwmon_type = EFX_HWMON_UNKNOWN; | ||
227 | attr->limit_value = limit_value; | 233 | attr->limit_value = limit_value; |
228 | sysfs_attr_init(&attr->dev_attr.attr); | 234 | sysfs_attr_init(&attr->dev_attr.attr); |
229 | attr->dev_attr.attr.name = attr->name; | 235 | attr->dev_attr.attr.name = attr->name; |
@@ -238,35 +244,42 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, | |||
238 | int efx_mcdi_mon_probe(struct efx_nic *efx) | 244 | int efx_mcdi_mon_probe(struct efx_nic *efx) |
239 | { | 245 | { |
240 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); | 246 | struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); |
241 | unsigned int n_attrs, n_temp = 0, n_cool = 0, n_in = 0; | 247 | unsigned int n_temp = 0, n_cool = 0, n_in = 0; |
248 | MCDI_DECLARE_BUF(inbuf, MC_CMD_SENSOR_INFO_EXT_IN_LEN); | ||
242 | MCDI_DECLARE_BUF(outbuf, MC_CMD_SENSOR_INFO_OUT_LENMAX); | 249 | MCDI_DECLARE_BUF(outbuf, MC_CMD_SENSOR_INFO_OUT_LENMAX); |
250 | unsigned int n_pages, n_sensors, n_attrs, page; | ||
243 | size_t outlen; | 251 | size_t outlen; |
244 | char name[12]; | 252 | char name[12]; |
245 | u32 mask; | 253 | u32 mask; |
246 | int rc, i, type; | 254 | int rc, i, j, type; |
247 | 255 | ||
248 | BUILD_BUG_ON(MC_CMD_SENSOR_INFO_IN_LEN != 0); | 256 | /* Find out how many sensors are present */ |
257 | n_sensors = 0; | ||
258 | page = 0; | ||
259 | do { | ||
260 | MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, page); | ||
249 | 261 | ||
250 | rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, NULL, 0, | 262 | rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, inbuf, sizeof(inbuf), |
251 | outbuf, sizeof(outbuf), &outlen); | 263 | outbuf, sizeof(outbuf), &outlen); |
252 | if (rc) | 264 | if (rc) |
253 | return rc; | 265 | return rc; |
254 | if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) | 266 | if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) |
255 | return -EIO; | 267 | return -EIO; |
256 | 268 | ||
257 | /* Find out which sensors are present. Don't create a device | 269 | mask = MCDI_DWORD(outbuf, SENSOR_INFO_OUT_MASK); |
258 | * if there are none. | 270 | n_sensors += hweight32(mask & ~(1 << MC_CMD_SENSOR_PAGE0_NEXT)); |
259 | */ | 271 | ++page; |
260 | mask = MCDI_DWORD(outbuf, SENSOR_INFO_OUT_MASK); | 272 | } while (mask & (1 << MC_CMD_SENSOR_PAGE0_NEXT)); |
261 | if (mask == 0) | 273 | n_pages = page; |
274 | |||
275 | /* Don't create a device if there are none */ | ||
276 | if (n_sensors == 0) | ||
262 | return 0; | 277 | return 0; |
263 | 278 | ||
264 | /* Check again for short response */ | 279 | rc = efx_nic_alloc_buffer( |
265 | if (outlen < MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask))) | 280 | efx, &hwmon->dma_buf, |
266 | return -EIO; | 281 | n_sensors * MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN, |
267 | 282 | GFP_KERNEL); | |
268 | rc = efx_nic_alloc_buffer(efx, &hwmon->dma_buf, | ||
269 | 4 * MC_CMD_SENSOR_ENTRY_MAXNUM, GFP_KERNEL); | ||
270 | if (rc) | 283 | if (rc) |
271 | return rc; | 284 | return rc; |
272 | 285 | ||
@@ -277,7 +290,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
277 | * attributes for this set of sensors: name of the driver plus | 290 | * attributes for this set of sensors: name of the driver plus |
278 | * value, min, max, crit, alarm and label for each sensor. | 291 | * value, min, max, crit, alarm and label for each sensor. |
279 | */ | 292 | */ |
280 | n_attrs = 1 + 6 * hweight32(mask); | 293 | n_attrs = 1 + 6 * n_sensors; |
281 | hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); | 294 | hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); |
282 | if (!hwmon->attrs) { | 295 | if (!hwmon->attrs) { |
283 | rc = -ENOMEM; | 296 | rc = -ENOMEM; |
@@ -294,26 +307,63 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
294 | if (rc) | 307 | if (rc) |
295 | goto fail; | 308 | goto fail; |
296 | 309 | ||
297 | for (i = 0, type = -1; ; i++) { | 310 | for (i = 0, j = -1, type = -1; ; i++) { |
311 | enum efx_hwmon_type hwmon_type; | ||
298 | const char *hwmon_prefix; | 312 | const char *hwmon_prefix; |
299 | unsigned hwmon_index; | 313 | unsigned hwmon_index; |
300 | u16 min1, max1, min2, max2; | 314 | u16 min1, max1, min2, max2; |
301 | 315 | ||
302 | /* Find next sensor type or exit if there is none */ | 316 | /* Find next sensor type or exit if there is none */ |
303 | type++; | 317 | do { |
304 | while (!(mask & (1 << type))) { | ||
305 | type++; | 318 | type++; |
306 | if (type == 32) | ||
307 | return 0; | ||
308 | } | ||
309 | 319 | ||
310 | /* Skip sensors specific to a different port */ | 320 | if ((type % 32) == 0) { |
311 | if (efx_mcdi_sensor_type[type].hwmon_type != EFX_HWMON_UNKNOWN && | 321 | page = type / 32; |
312 | efx_mcdi_sensor_type[type].port >= 0 && | 322 | j = -1; |
313 | efx_mcdi_sensor_type[type].port != efx_port_num(efx)) | 323 | if (page == n_pages) |
314 | continue; | 324 | return 0; |
325 | |||
326 | MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, | ||
327 | page); | ||
328 | rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, | ||
329 | inbuf, sizeof(inbuf), | ||
330 | outbuf, sizeof(outbuf), | ||
331 | &outlen); | ||
332 | if (rc) | ||
333 | goto fail; | ||
334 | if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) { | ||
335 | rc = -EIO; | ||
336 | goto fail; | ||
337 | } | ||
338 | |||
339 | mask = (MCDI_DWORD(outbuf, | ||
340 | SENSOR_INFO_OUT_MASK) & | ||
341 | ~(1 << MC_CMD_SENSOR_PAGE0_NEXT)); | ||
342 | |||
343 | /* Check again for short response */ | ||
344 | if (outlen < | ||
345 | MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask))) { | ||
346 | rc = -EIO; | ||
347 | goto fail; | ||
348 | } | ||
349 | } | ||
350 | } while (!(mask & (1 << type % 32))); | ||
351 | j++; | ||
352 | |||
353 | if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) { | ||
354 | hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; | ||
355 | |||
356 | /* Skip sensors specific to a different port */ | ||
357 | if (hwmon_type != EFX_HWMON_UNKNOWN && | ||
358 | efx_mcdi_sensor_type[type].port >= 0 && | ||
359 | efx_mcdi_sensor_type[type].port != | ||
360 | efx_port_num(efx)) | ||
361 | continue; | ||
362 | } else { | ||
363 | hwmon_type = EFX_HWMON_UNKNOWN; | ||
364 | } | ||
315 | 365 | ||
316 | switch (efx_mcdi_sensor_type[type].hwmon_type) { | 366 | switch (hwmon_type) { |
317 | case EFX_HWMON_TEMP: | 367 | case EFX_HWMON_TEMP: |
318 | hwmon_prefix = "temp"; | 368 | hwmon_prefix = "temp"; |
319 | hwmon_index = ++n_temp; /* 1-based */ | 369 | hwmon_index = ++n_temp; /* 1-based */ |
@@ -333,13 +383,13 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
333 | } | 383 | } |
334 | 384 | ||
335 | min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, | 385 | min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, |
336 | SENSOR_INFO_ENTRY, i, MIN1); | 386 | SENSOR_INFO_ENTRY, j, MIN1); |
337 | max1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, | 387 | max1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, |
338 | SENSOR_INFO_ENTRY, i, MAX1); | 388 | SENSOR_INFO_ENTRY, j, MAX1); |
339 | min2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, | 389 | min2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, |
340 | SENSOR_INFO_ENTRY, i, MIN2); | 390 | SENSOR_INFO_ENTRY, j, MIN2); |
341 | max2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, | 391 | max2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, |
342 | SENSOR_INFO_ENTRY, i, MAX2); | 392 | SENSOR_INFO_ENTRY, j, MAX2); |
343 | 393 | ||
344 | if (min1 != max1) { | 394 | if (min1 != max1) { |
345 | snprintf(name, sizeof(name), "%s%u_input", | 395 | snprintf(name, sizeof(name), "%s%u_input", |
@@ -386,7 +436,8 @@ int efx_mcdi_mon_probe(struct efx_nic *efx) | |||
386 | if (rc) | 436 | if (rc) |
387 | goto fail; | 437 | goto fail; |
388 | 438 | ||
389 | if (efx_mcdi_sensor_type[type].label) { | 439 | if (type < ARRAY_SIZE(efx_mcdi_sensor_type) && |
440 | efx_mcdi_sensor_type[type].label) { | ||
390 | snprintf(name, sizeof(name), "%s%u_label", | 441 | snprintf(name, sizeof(name), "%s%u_label", |
391 | hwmon_prefix, hwmon_index); | 442 | hwmon_prefix, hwmon_index); |
392 | rc = efx_mcdi_mon_add_attr( | 443 | rc = efx_mcdi_mon_add_attr( |