aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-08-08 06:14:20 -0400
committerBen Hutchings <bhutchings@solarflare.com>2013-08-27 17:29:56 -0400
commitd4fbdcfe93928fbcb7374ea490e41f7b69d95380 (patch)
tree153ce5ee26d6d128d0d5a0d157dda322ac2fc0e5 /drivers/net/ethernet/sfc
parent8c4e720f181f251948c52913c74a86f68aed9c50 (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')
-rw-r--r--drivers/net/ethernet/sfc/mcdi_mon.c139
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 {
93static int efx_mcdi_mon_update(struct efx_nic *efx) 94static 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,
238int efx_mcdi_mon_probe(struct efx_nic *efx) 244int 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(