1 /**************************************************************************** 2 * Driver for Solarflare network controllers and boards 3 * Copyright 2011-2013 Solarflare Communications Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 as published 7 * by the Free Software Foundation, incorporated herein by reference. 8 */ 9 10 #include <linux/bitops.h> 11 #include <linux/slab.h> 12 #include <linux/hwmon.h> 13 #include <linux/stat.h> 14 15 #include "net_driver.h" 16 #include "mcdi.h" 17 #include "mcdi_pcol.h" 18 #include "nic.h" 19 20 enum efx_hwmon_type { 21 EFX_HWMON_UNKNOWN, 22 EFX_HWMON_TEMP, /* temperature */ 23 EFX_HWMON_COOL, /* cooling device, probably a heatsink */ 24 EFX_HWMON_IN, /* voltage */ 25 EFX_HWMON_CURR, /* current */ 26 EFX_HWMON_POWER, /* power */ 27 }; 28 29 static const struct { 30 const char *label; 31 enum efx_hwmon_type hwmon_type; 32 int port; 33 } efx_mcdi_sensor_type[] = { 34 #define SENSOR(name, label, hwmon_type, port) \ 35 [MC_CMD_SENSOR_##name] = { label, EFX_HWMON_ ## hwmon_type, port } 36 SENSOR(CONTROLLER_TEMP, "Controller ext. temp.", TEMP, -1), 37 SENSOR(PHY_COMMON_TEMP, "PHY temp.", TEMP, -1), 38 SENSOR(CONTROLLER_COOLING, "Controller cooling", COOL, -1), 39 SENSOR(PHY0_TEMP, "PHY temp.", TEMP, 0), 40 SENSOR(PHY0_COOLING, "PHY cooling", COOL, 0), 41 SENSOR(PHY1_TEMP, "PHY temp.", TEMP, 1), 42 SENSOR(PHY1_COOLING, "PHY cooling", COOL, 1), 43 SENSOR(IN_1V0, "1.0V supply", IN, -1), 44 SENSOR(IN_1V2, "1.2V supply", IN, -1), 45 SENSOR(IN_1V8, "1.8V supply", IN, -1), 46 SENSOR(IN_2V5, "2.5V supply", IN, -1), 47 SENSOR(IN_3V3, "3.3V supply", IN, -1), 48 SENSOR(IN_12V0, "12.0V supply", IN, -1), 49 SENSOR(IN_1V2A, "1.2V analogue supply", IN, -1), 50 SENSOR(IN_VREF, "ref. voltage", IN, -1), 51 SENSOR(OUT_VAOE, "AOE power supply", IN, -1), 52 SENSOR(AOE_TEMP, "AOE temp.", TEMP, -1), 53 SENSOR(PSU_AOE_TEMP, "AOE PSU temp.", TEMP, -1), 54 SENSOR(PSU_TEMP, "Controller PSU temp.", TEMP, -1), 55 SENSOR(FAN_0, NULL, COOL, -1), 56 SENSOR(FAN_1, NULL, COOL, -1), 57 SENSOR(FAN_2, NULL, COOL, -1), 58 SENSOR(FAN_3, NULL, COOL, -1), 59 SENSOR(FAN_4, NULL, COOL, -1), 60 SENSOR(IN_VAOE, "AOE input supply", IN, -1), 61 SENSOR(OUT_IAOE, "AOE output current", CURR, -1), 62 SENSOR(IN_IAOE, "AOE input current", CURR, -1), 63 SENSOR(NIC_POWER, "Board power use", POWER, -1), 64 SENSOR(IN_0V9, "0.9V supply", IN, -1), 65 SENSOR(IN_I0V9, "0.9V input current", CURR, -1), 66 SENSOR(IN_I1V2, "1.2V input current", CURR, -1), 67 SENSOR(IN_0V9_ADC, "0.9V supply (at ADC)", IN, -1), 68 SENSOR(CONTROLLER_2_TEMP, "Controller ext. temp. 2", TEMP, -1), 69 SENSOR(VREG_INTERNAL_TEMP, "Voltage regulator temp.", TEMP, -1), 70 SENSOR(VREG_0V9_TEMP, "0.9V regulator temp.", TEMP, -1), 71 SENSOR(VREG_1V2_TEMP, "1.2V regulator temp.", TEMP, -1), 72 SENSOR(CONTROLLER_VPTAT, "Controller int. temp. raw", IN, -1), 73 SENSOR(CONTROLLER_INTERNAL_TEMP, "Controller int. temp.", TEMP, -1), 74 SENSOR(CONTROLLER_VPTAT_EXTADC, 75 "Controller int. temp. raw (at ADC)", IN, -1), 76 SENSOR(CONTROLLER_INTERNAL_TEMP_EXTADC, 77 "Controller int. temp. (via ADC)", TEMP, -1), 78 SENSOR(AMBIENT_TEMP, "Ambient temp.", TEMP, -1), 79 SENSOR(AIRFLOW, "Air flow raw", IN, -1), 80 #undef SENSOR 81 }; 82 83 static const char *const sensor_status_names[] = { 84 [MC_CMD_SENSOR_STATE_OK] = "OK", 85 [MC_CMD_SENSOR_STATE_WARNING] = "Warning", 86 [MC_CMD_SENSOR_STATE_FATAL] = "Fatal", 87 [MC_CMD_SENSOR_STATE_BROKEN] = "Device failure", 88 [MC_CMD_SENSOR_STATE_NO_READING] = "No reading", 89 }; 90 91 void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev) 92 { 93 unsigned int type, state, value; 94 const char *name = NULL, *state_txt; 95 96 type = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR); 97 state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE); 98 value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE); 99 100 /* Deal gracefully with the board having more drivers than we 101 * know about, but do not expect new sensor states. */ 102 if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) 103 name = efx_mcdi_sensor_type[type].label; 104 if (!name) 105 name = "No sensor name available"; 106 EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names)); 107 state_txt = sensor_status_names[state]; 108 109 netif_err(efx, hw, efx->net_dev, 110 "Sensor %d (%s) reports condition '%s' for raw value %d\n", 111 type, name, state_txt, value); 112 } 113 114 #ifdef CONFIG_SFC_MCDI_MON 115 116 struct efx_mcdi_mon_attribute { 117 struct device_attribute dev_attr; 118 unsigned int index; 119 unsigned int type; 120 enum efx_hwmon_type hwmon_type; 121 unsigned int limit_value; 122 char name[12]; 123 }; 124 125 static int efx_mcdi_mon_update(struct efx_nic *efx) 126 { 127 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 128 MCDI_DECLARE_BUF(inbuf, MC_CMD_READ_SENSORS_EXT_IN_LEN); 129 int rc; 130 131 MCDI_SET_QWORD(inbuf, READ_SENSORS_EXT_IN_DMA_ADDR, 132 hwmon->dma_buf.dma_addr); 133 MCDI_SET_DWORD(inbuf, READ_SENSORS_EXT_IN_LENGTH, hwmon->dma_buf.len); 134 135 rc = efx_mcdi_rpc(efx, MC_CMD_READ_SENSORS, 136 inbuf, sizeof(inbuf), NULL, 0, NULL); 137 if (rc == 0) 138 hwmon->last_update = jiffies; 139 return rc; 140 } 141 142 static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index, 143 efx_dword_t *entry) 144 { 145 struct efx_nic *efx = dev_get_drvdata(dev->parent); 146 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 147 int rc; 148 149 BUILD_BUG_ON(MC_CMD_READ_SENSORS_OUT_LEN != 0); 150 151 mutex_lock(&hwmon->update_lock); 152 153 /* Use cached value if last update was < 1 s ago */ 154 if (time_before(jiffies, hwmon->last_update + HZ)) 155 rc = 0; 156 else 157 rc = efx_mcdi_mon_update(efx); 158 159 /* Copy out the requested entry */ 160 *entry = ((efx_dword_t *)hwmon->dma_buf.addr)[index]; 161 162 mutex_unlock(&hwmon->update_lock); 163 164 return rc; 165 } 166 167 static ssize_t efx_mcdi_mon_show_value(struct device *dev, 168 struct device_attribute *attr, 169 char *buf) 170 { 171 struct efx_mcdi_mon_attribute *mon_attr = 172 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 173 efx_dword_t entry; 174 unsigned int value, state; 175 int rc; 176 177 rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry); 178 if (rc) 179 return rc; 180 181 state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); 182 if (state == MC_CMD_SENSOR_STATE_NO_READING) 183 return -EBUSY; 184 185 value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); 186 187 switch (mon_attr->hwmon_type) { 188 case EFX_HWMON_TEMP: 189 /* Convert temperature from degrees to milli-degrees Celsius */ 190 value *= 1000; 191 break; 192 case EFX_HWMON_POWER: 193 /* Convert power from watts to microwatts */ 194 value *= 1000000; 195 break; 196 default: 197 /* No conversion needed */ 198 break; 199 } 200 201 return sprintf(buf, "%u\n", value); 202 } 203 204 static ssize_t efx_mcdi_mon_show_limit(struct device *dev, 205 struct device_attribute *attr, 206 char *buf) 207 { 208 struct efx_mcdi_mon_attribute *mon_attr = 209 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 210 unsigned int value; 211 212 value = mon_attr->limit_value; 213 214 switch (mon_attr->hwmon_type) { 215 case EFX_HWMON_TEMP: 216 /* Convert temperature from degrees to milli-degrees Celsius */ 217 value *= 1000; 218 break; 219 case EFX_HWMON_POWER: 220 /* Convert power from watts to microwatts */ 221 value *= 1000000; 222 break; 223 default: 224 /* No conversion needed */ 225 break; 226 } 227 228 return sprintf(buf, "%u\n", value); 229 } 230 231 static ssize_t efx_mcdi_mon_show_alarm(struct device *dev, 232 struct device_attribute *attr, 233 char *buf) 234 { 235 struct efx_mcdi_mon_attribute *mon_attr = 236 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 237 efx_dword_t entry; 238 int state; 239 int rc; 240 241 rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry); 242 if (rc) 243 return rc; 244 245 state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); 246 return sprintf(buf, "%d\n", state != MC_CMD_SENSOR_STATE_OK); 247 } 248 249 static ssize_t efx_mcdi_mon_show_label(struct device *dev, 250 struct device_attribute *attr, 251 char *buf) 252 { 253 struct efx_mcdi_mon_attribute *mon_attr = 254 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); 255 return sprintf(buf, "%s\n", 256 efx_mcdi_sensor_type[mon_attr->type].label); 257 } 258 259 static void 260 efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, 261 ssize_t (*reader)(struct device *, 262 struct device_attribute *, char *), 263 unsigned int index, unsigned int type, 264 unsigned int limit_value) 265 { 266 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 267 struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs]; 268 269 strlcpy(attr->name, name, sizeof(attr->name)); 270 attr->index = index; 271 attr->type = type; 272 if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) 273 attr->hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; 274 else 275 attr->hwmon_type = EFX_HWMON_UNKNOWN; 276 attr->limit_value = limit_value; 277 sysfs_attr_init(&attr->dev_attr.attr); 278 attr->dev_attr.attr.name = attr->name; 279 attr->dev_attr.attr.mode = S_IRUGO; 280 attr->dev_attr.show = reader; 281 hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr; 282 } 283 284 int efx_mcdi_mon_probe(struct efx_nic *efx) 285 { 286 unsigned int n_temp = 0, n_cool = 0, n_in = 0, n_curr = 0, n_power = 0; 287 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 288 MCDI_DECLARE_BUF(inbuf, MC_CMD_SENSOR_INFO_EXT_IN_LEN); 289 MCDI_DECLARE_BUF(outbuf, MC_CMD_SENSOR_INFO_OUT_LENMAX); 290 unsigned int n_pages, n_sensors, n_attrs, page; 291 size_t outlen; 292 char name[12]; 293 u32 mask; 294 int rc, i, j, type; 295 296 /* Find out how many sensors are present */ 297 n_sensors = 0; 298 page = 0; 299 do { 300 MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, page); 301 302 rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, inbuf, sizeof(inbuf), 303 outbuf, sizeof(outbuf), &outlen); 304 if (rc) 305 return rc; 306 if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) 307 return -EIO; 308 309 mask = MCDI_DWORD(outbuf, SENSOR_INFO_OUT_MASK); 310 n_sensors += hweight32(mask & ~(1 << MC_CMD_SENSOR_PAGE0_NEXT)); 311 ++page; 312 } while (mask & (1 << MC_CMD_SENSOR_PAGE0_NEXT)); 313 n_pages = page; 314 315 /* Don't create a device if there are none */ 316 if (n_sensors == 0) 317 return 0; 318 319 rc = efx_nic_alloc_buffer( 320 efx, &hwmon->dma_buf, 321 n_sensors * MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN, 322 GFP_KERNEL); 323 if (rc) 324 return rc; 325 326 mutex_init(&hwmon->update_lock); 327 efx_mcdi_mon_update(efx); 328 329 /* Allocate space for the maximum possible number of 330 * attributes for this set of sensors: 331 * value, min, max, crit, alarm and label for each sensor. 332 */ 333 n_attrs = 6 * n_sensors; 334 hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); 335 if (!hwmon->attrs) { 336 rc = -ENOMEM; 337 goto fail; 338 } 339 hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *), 340 GFP_KERNEL); 341 if (!hwmon->group.attrs) { 342 rc = -ENOMEM; 343 goto fail; 344 } 345 346 for (i = 0, j = -1, type = -1; ; i++) { 347 enum efx_hwmon_type hwmon_type; 348 const char *hwmon_prefix; 349 unsigned hwmon_index; 350 u16 min1, max1, min2, max2; 351 352 /* Find next sensor type or exit if there is none */ 353 do { 354 type++; 355 356 if ((type % 32) == 0) { 357 page = type / 32; 358 j = -1; 359 if (page == n_pages) 360 goto hwmon_register; 361 362 MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, 363 page); 364 rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, 365 inbuf, sizeof(inbuf), 366 outbuf, sizeof(outbuf), 367 &outlen); 368 if (rc) 369 goto fail; 370 if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) { 371 rc = -EIO; 372 goto fail; 373 } 374 375 mask = (MCDI_DWORD(outbuf, 376 SENSOR_INFO_OUT_MASK) & 377 ~(1 << MC_CMD_SENSOR_PAGE0_NEXT)); 378 379 /* Check again for short response */ 380 if (outlen < 381 MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask))) { 382 rc = -EIO; 383 goto fail; 384 } 385 } 386 } while (!(mask & (1 << type % 32))); 387 j++; 388 389 if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) { 390 hwmon_type = efx_mcdi_sensor_type[type].hwmon_type; 391 392 /* Skip sensors specific to a different port */ 393 if (hwmon_type != EFX_HWMON_UNKNOWN && 394 efx_mcdi_sensor_type[type].port >= 0 && 395 efx_mcdi_sensor_type[type].port != 396 efx_port_num(efx)) 397 continue; 398 } else { 399 hwmon_type = EFX_HWMON_UNKNOWN; 400 } 401 402 switch (hwmon_type) { 403 case EFX_HWMON_TEMP: 404 hwmon_prefix = "temp"; 405 hwmon_index = ++n_temp; /* 1-based */ 406 break; 407 case EFX_HWMON_COOL: 408 /* This is likely to be a heatsink, but there 409 * is no convention for representing cooling 410 * devices other than fans. 411 */ 412 hwmon_prefix = "fan"; 413 hwmon_index = ++n_cool; /* 1-based */ 414 break; 415 default: 416 hwmon_prefix = "in"; 417 hwmon_index = n_in++; /* 0-based */ 418 break; 419 case EFX_HWMON_CURR: 420 hwmon_prefix = "curr"; 421 hwmon_index = ++n_curr; /* 1-based */ 422 break; 423 case EFX_HWMON_POWER: 424 hwmon_prefix = "power"; 425 hwmon_index = ++n_power; /* 1-based */ 426 break; 427 } 428 429 min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 430 SENSOR_INFO_ENTRY, j, MIN1); 431 max1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 432 SENSOR_INFO_ENTRY, j, MAX1); 433 min2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 434 SENSOR_INFO_ENTRY, j, MIN2); 435 max2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, 436 SENSOR_INFO_ENTRY, j, MAX2); 437 438 if (min1 != max1) { 439 snprintf(name, sizeof(name), "%s%u_input", 440 hwmon_prefix, hwmon_index); 441 efx_mcdi_mon_add_attr( 442 efx, name, efx_mcdi_mon_show_value, i, type, 0); 443 444 if (hwmon_type != EFX_HWMON_POWER) { 445 snprintf(name, sizeof(name), "%s%u_min", 446 hwmon_prefix, hwmon_index); 447 efx_mcdi_mon_add_attr( 448 efx, name, efx_mcdi_mon_show_limit, 449 i, type, min1); 450 } 451 452 snprintf(name, sizeof(name), "%s%u_max", 453 hwmon_prefix, hwmon_index); 454 efx_mcdi_mon_add_attr( 455 efx, name, efx_mcdi_mon_show_limit, 456 i, type, max1); 457 458 if (min2 != max2) { 459 /* Assume max2 is critical value. 460 * But we have no good way to expose min2. 461 */ 462 snprintf(name, sizeof(name), "%s%u_crit", 463 hwmon_prefix, hwmon_index); 464 efx_mcdi_mon_add_attr( 465 efx, name, efx_mcdi_mon_show_limit, 466 i, type, max2); 467 } 468 } 469 470 snprintf(name, sizeof(name), "%s%u_alarm", 471 hwmon_prefix, hwmon_index); 472 efx_mcdi_mon_add_attr( 473 efx, name, efx_mcdi_mon_show_alarm, i, type, 0); 474 475 if (type < ARRAY_SIZE(efx_mcdi_sensor_type) && 476 efx_mcdi_sensor_type[type].label) { 477 snprintf(name, sizeof(name), "%s%u_label", 478 hwmon_prefix, hwmon_index); 479 efx_mcdi_mon_add_attr( 480 efx, name, efx_mcdi_mon_show_label, i, type, 0); 481 } 482 } 483 484 hwmon_register: 485 hwmon->groups[0] = &hwmon->group; 486 hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev, 487 KBUILD_MODNAME, NULL, 488 hwmon->groups); 489 if (IS_ERR(hwmon->device)) { 490 rc = PTR_ERR(hwmon->device); 491 goto fail; 492 } 493 494 return 0; 495 496 fail: 497 efx_mcdi_mon_remove(efx); 498 return rc; 499 } 500 501 void efx_mcdi_mon_remove(struct efx_nic *efx) 502 { 503 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); 504 505 if (hwmon->device) 506 hwmon_device_unregister(hwmon->device); 507 kfree(hwmon->attrs); 508 kfree(hwmon->group.attrs); 509 efx_nic_free_buffer(efx, &hwmon->dma_buf); 510 } 511 512 #endif /* CONFIG_SFC_MCDI_MON */ 513