0001
0002
0003
0004
0005
0006
0007 #include <linux/bitops.h>
0008 #include <linux/slab.h>
0009 #include <linux/hwmon.h>
0010 #include <linux/stat.h>
0011
0012 #include "net_driver.h"
0013 #include "mcdi.h"
0014 #include "mcdi_pcol.h"
0015 #include "nic.h"
0016
0017 enum efx_hwmon_type {
0018 EFX_HWMON_UNKNOWN,
0019 EFX_HWMON_TEMP,
0020 EFX_HWMON_COOL,
0021 EFX_HWMON_IN,
0022 EFX_HWMON_CURR,
0023 EFX_HWMON_POWER,
0024 EFX_HWMON_TYPES_COUNT
0025 };
0026
0027 static const char *const efx_hwmon_unit[EFX_HWMON_TYPES_COUNT] = {
0028 [EFX_HWMON_TEMP] = " degC",
0029 [EFX_HWMON_COOL] = " rpm",
0030 [EFX_HWMON_IN] = " mV",
0031 [EFX_HWMON_CURR] = " mA",
0032 [EFX_HWMON_POWER] = " W",
0033 };
0034
0035 static const struct {
0036 const char *label;
0037 enum efx_hwmon_type hwmon_type;
0038 int port;
0039 } efx_mcdi_sensor_type[] = {
0040 #define SENSOR(name, label, hwmon_type, port) \
0041 [MC_CMD_SENSOR_##name] = { label, EFX_HWMON_ ## hwmon_type, port }
0042 SENSOR(CONTROLLER_TEMP, "Controller board temp.", TEMP, -1),
0043 SENSOR(PHY_COMMON_TEMP, "PHY temp.", TEMP, -1),
0044 SENSOR(CONTROLLER_COOLING, "Controller heat sink", COOL, -1),
0045 SENSOR(PHY0_TEMP, "PHY temp.", TEMP, 0),
0046 SENSOR(PHY0_COOLING, "PHY heat sink", COOL, 0),
0047 SENSOR(PHY1_TEMP, "PHY temp.", TEMP, 1),
0048 SENSOR(PHY1_COOLING, "PHY heat sink", COOL, 1),
0049 SENSOR(IN_1V0, "1.0V supply", IN, -1),
0050 SENSOR(IN_1V2, "1.2V supply", IN, -1),
0051 SENSOR(IN_1V8, "1.8V supply", IN, -1),
0052 SENSOR(IN_2V5, "2.5V supply", IN, -1),
0053 SENSOR(IN_3V3, "3.3V supply", IN, -1),
0054 SENSOR(IN_12V0, "12.0V supply", IN, -1),
0055 SENSOR(IN_1V2A, "1.2V analogue supply", IN, -1),
0056 SENSOR(IN_VREF, "Ref. voltage", IN, -1),
0057 SENSOR(OUT_VAOE, "AOE FPGA supply", IN, -1),
0058 SENSOR(AOE_TEMP, "AOE FPGA temp.", TEMP, -1),
0059 SENSOR(PSU_AOE_TEMP, "AOE regulator temp.", TEMP, -1),
0060 SENSOR(PSU_TEMP, "Controller regulator temp.",
0061 TEMP, -1),
0062 SENSOR(FAN_0, "Fan 0", COOL, -1),
0063 SENSOR(FAN_1, "Fan 1", COOL, -1),
0064 SENSOR(FAN_2, "Fan 2", COOL, -1),
0065 SENSOR(FAN_3, "Fan 3", COOL, -1),
0066 SENSOR(FAN_4, "Fan 4", COOL, -1),
0067 SENSOR(IN_VAOE, "AOE input supply", IN, -1),
0068 SENSOR(OUT_IAOE, "AOE output current", CURR, -1),
0069 SENSOR(IN_IAOE, "AOE input current", CURR, -1),
0070 SENSOR(NIC_POWER, "Board power use", POWER, -1),
0071 SENSOR(IN_0V9, "0.9V supply", IN, -1),
0072 SENSOR(IN_I0V9, "0.9V supply current", CURR, -1),
0073 SENSOR(IN_I1V2, "1.2V supply current", CURR, -1),
0074 SENSOR(IN_0V9_ADC, "0.9V supply (ext. ADC)", IN, -1),
0075 SENSOR(CONTROLLER_2_TEMP, "Controller board temp. 2", TEMP, -1),
0076 SENSOR(VREG_INTERNAL_TEMP, "Regulator die temp.", TEMP, -1),
0077 SENSOR(VREG_0V9_TEMP, "0.9V regulator temp.", TEMP, -1),
0078 SENSOR(VREG_1V2_TEMP, "1.2V regulator temp.", TEMP, -1),
0079 SENSOR(CONTROLLER_VPTAT,
0080 "Controller PTAT voltage (int. ADC)", IN, -1),
0081 SENSOR(CONTROLLER_INTERNAL_TEMP,
0082 "Controller die temp. (int. ADC)", TEMP, -1),
0083 SENSOR(CONTROLLER_VPTAT_EXTADC,
0084 "Controller PTAT voltage (ext. ADC)", IN, -1),
0085 SENSOR(CONTROLLER_INTERNAL_TEMP_EXTADC,
0086 "Controller die temp. (ext. ADC)", TEMP, -1),
0087 SENSOR(AMBIENT_TEMP, "Ambient temp.", TEMP, -1),
0088 SENSOR(AIRFLOW, "Air flow raw", IN, -1),
0089 SENSOR(VDD08D_VSS08D_CSR, "0.9V die (int. ADC)", IN, -1),
0090 SENSOR(VDD08D_VSS08D_CSR_EXTADC, "0.9V die (ext. ADC)", IN, -1),
0091 SENSOR(HOTPOINT_TEMP, "Controller board temp. (hotpoint)", TEMP, -1),
0092 #undef SENSOR
0093 };
0094
0095 static const char *const sensor_status_names[] = {
0096 [MC_CMD_SENSOR_STATE_OK] = "OK",
0097 [MC_CMD_SENSOR_STATE_WARNING] = "Warning",
0098 [MC_CMD_SENSOR_STATE_FATAL] = "Fatal",
0099 [MC_CMD_SENSOR_STATE_BROKEN] = "Device failure",
0100 [MC_CMD_SENSOR_STATE_NO_READING] = "No reading",
0101 };
0102
0103 void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
0104 {
0105 unsigned int type, state, value;
0106 enum efx_hwmon_type hwmon_type = EFX_HWMON_UNKNOWN;
0107 const char *name = NULL, *state_txt, *unit;
0108
0109 type = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR);
0110 state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE);
0111 value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE);
0112
0113
0114
0115 if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) {
0116 name = efx_mcdi_sensor_type[type].label;
0117 hwmon_type = efx_mcdi_sensor_type[type].hwmon_type;
0118 }
0119 if (!name)
0120 name = "No sensor name available";
0121 EFX_WARN_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
0122 state_txt = sensor_status_names[state];
0123 EFX_WARN_ON_PARANOID(hwmon_type >= EFX_HWMON_TYPES_COUNT);
0124 unit = efx_hwmon_unit[hwmon_type];
0125 if (!unit)
0126 unit = "";
0127
0128 netif_err(efx, hw, efx->net_dev,
0129 "Sensor %d (%s) reports condition '%s' for value %d%s\n",
0130 type, name, state_txt, value, unit);
0131 }
0132
0133 #ifdef CONFIG_SFC_MCDI_MON
0134
0135 struct efx_mcdi_mon_attribute {
0136 struct device_attribute dev_attr;
0137 unsigned int index;
0138 unsigned int type;
0139 enum efx_hwmon_type hwmon_type;
0140 unsigned int limit_value;
0141 char name[12];
0142 };
0143
0144 static int efx_mcdi_mon_update(struct efx_nic *efx)
0145 {
0146 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
0147 MCDI_DECLARE_BUF(inbuf, MC_CMD_READ_SENSORS_EXT_IN_LEN);
0148 int rc;
0149
0150 MCDI_SET_QWORD(inbuf, READ_SENSORS_EXT_IN_DMA_ADDR,
0151 hwmon->dma_buf.dma_addr);
0152 MCDI_SET_DWORD(inbuf, READ_SENSORS_EXT_IN_LENGTH, hwmon->dma_buf.len);
0153
0154 rc = efx_mcdi_rpc(efx, MC_CMD_READ_SENSORS,
0155 inbuf, sizeof(inbuf), NULL, 0, NULL);
0156 if (rc == 0)
0157 hwmon->last_update = jiffies;
0158 return rc;
0159 }
0160
0161 static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index,
0162 efx_dword_t *entry)
0163 {
0164 struct efx_nic *efx = dev_get_drvdata(dev->parent);
0165 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
0166 int rc;
0167
0168 BUILD_BUG_ON(MC_CMD_READ_SENSORS_OUT_LEN != 0);
0169
0170 mutex_lock(&hwmon->update_lock);
0171
0172
0173 if (time_before(jiffies, hwmon->last_update + HZ))
0174 rc = 0;
0175 else
0176 rc = efx_mcdi_mon_update(efx);
0177
0178
0179 *entry = ((efx_dword_t *)hwmon->dma_buf.addr)[index];
0180
0181 mutex_unlock(&hwmon->update_lock);
0182
0183 return rc;
0184 }
0185
0186 static ssize_t efx_mcdi_mon_show_value(struct device *dev,
0187 struct device_attribute *attr,
0188 char *buf)
0189 {
0190 struct efx_mcdi_mon_attribute *mon_attr =
0191 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
0192 efx_dword_t entry;
0193 unsigned int value, state;
0194 int rc;
0195
0196 rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry);
0197 if (rc)
0198 return rc;
0199
0200 state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
0201 if (state == MC_CMD_SENSOR_STATE_NO_READING)
0202 return -EBUSY;
0203
0204 value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
0205
0206 switch (mon_attr->hwmon_type) {
0207 case EFX_HWMON_TEMP:
0208
0209 value *= 1000;
0210 break;
0211 case EFX_HWMON_POWER:
0212
0213 value *= 1000000;
0214 break;
0215 default:
0216
0217 break;
0218 }
0219
0220 return sprintf(buf, "%u\n", value);
0221 }
0222
0223 static ssize_t efx_mcdi_mon_show_limit(struct device *dev,
0224 struct device_attribute *attr,
0225 char *buf)
0226 {
0227 struct efx_mcdi_mon_attribute *mon_attr =
0228 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
0229 unsigned int value;
0230
0231 value = mon_attr->limit_value;
0232
0233 switch (mon_attr->hwmon_type) {
0234 case EFX_HWMON_TEMP:
0235
0236 value *= 1000;
0237 break;
0238 case EFX_HWMON_POWER:
0239
0240 value *= 1000000;
0241 break;
0242 default:
0243
0244 break;
0245 }
0246
0247 return sprintf(buf, "%u\n", value);
0248 }
0249
0250 static ssize_t efx_mcdi_mon_show_alarm(struct device *dev,
0251 struct device_attribute *attr,
0252 char *buf)
0253 {
0254 struct efx_mcdi_mon_attribute *mon_attr =
0255 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
0256 efx_dword_t entry;
0257 int state;
0258 int rc;
0259
0260 rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry);
0261 if (rc)
0262 return rc;
0263
0264 state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
0265 return sprintf(buf, "%d\n", state != MC_CMD_SENSOR_STATE_OK);
0266 }
0267
0268 static ssize_t efx_mcdi_mon_show_label(struct device *dev,
0269 struct device_attribute *attr,
0270 char *buf)
0271 {
0272 struct efx_mcdi_mon_attribute *mon_attr =
0273 container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
0274 return sprintf(buf, "%s\n",
0275 efx_mcdi_sensor_type[mon_attr->type].label);
0276 }
0277
0278 static void
0279 efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
0280 ssize_t (*reader)(struct device *,
0281 struct device_attribute *, char *),
0282 unsigned int index, unsigned int type,
0283 unsigned int limit_value)
0284 {
0285 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
0286 struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
0287
0288 strlcpy(attr->name, name, sizeof(attr->name));
0289 attr->index = index;
0290 attr->type = type;
0291 if (type < ARRAY_SIZE(efx_mcdi_sensor_type))
0292 attr->hwmon_type = efx_mcdi_sensor_type[type].hwmon_type;
0293 else
0294 attr->hwmon_type = EFX_HWMON_UNKNOWN;
0295 attr->limit_value = limit_value;
0296 sysfs_attr_init(&attr->dev_attr.attr);
0297 attr->dev_attr.attr.name = attr->name;
0298 attr->dev_attr.attr.mode = 0444;
0299 attr->dev_attr.show = reader;
0300 hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr;
0301 }
0302
0303 int efx_mcdi_mon_probe(struct efx_nic *efx)
0304 {
0305 unsigned int n_temp = 0, n_cool = 0, n_in = 0, n_curr = 0, n_power = 0;
0306 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
0307 MCDI_DECLARE_BUF(inbuf, MC_CMD_SENSOR_INFO_EXT_IN_LEN);
0308 MCDI_DECLARE_BUF(outbuf, MC_CMD_SENSOR_INFO_OUT_LENMAX);
0309 unsigned int n_pages, n_sensors, n_attrs, page;
0310 size_t outlen;
0311 char name[12];
0312 u32 mask;
0313 int rc, i, j, type;
0314
0315
0316 n_sensors = 0;
0317 page = 0;
0318 do {
0319 MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE, page);
0320
0321 rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, inbuf, sizeof(inbuf),
0322 outbuf, sizeof(outbuf), &outlen);
0323 if (rc)
0324 return rc;
0325 if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN)
0326 return -EIO;
0327
0328 mask = MCDI_DWORD(outbuf, SENSOR_INFO_OUT_MASK);
0329 n_sensors += hweight32(mask & ~(1 << MC_CMD_SENSOR_PAGE0_NEXT));
0330 ++page;
0331 } while (mask & (1 << MC_CMD_SENSOR_PAGE0_NEXT));
0332 n_pages = page;
0333
0334
0335 if (n_sensors == 0)
0336 return 0;
0337
0338 rc = efx_nic_alloc_buffer(
0339 efx, &hwmon->dma_buf,
0340 n_sensors * MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN,
0341 GFP_KERNEL);
0342 if (rc)
0343 return rc;
0344
0345 mutex_init(&hwmon->update_lock);
0346 efx_mcdi_mon_update(efx);
0347
0348
0349
0350
0351
0352 n_attrs = 6 * n_sensors;
0353 hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL);
0354 if (!hwmon->attrs) {
0355 rc = -ENOMEM;
0356 goto fail;
0357 }
0358 hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *),
0359 GFP_KERNEL);
0360 if (!hwmon->group.attrs) {
0361 rc = -ENOMEM;
0362 goto fail;
0363 }
0364
0365 for (i = 0, j = -1, type = -1; ; i++) {
0366 enum efx_hwmon_type hwmon_type;
0367 const char *hwmon_prefix;
0368 unsigned hwmon_index;
0369 u16 min1, max1, min2, max2;
0370
0371
0372 do {
0373 type++;
0374
0375 if ((type % 32) == 0) {
0376 page = type / 32;
0377 j = -1;
0378 if (page == n_pages)
0379 goto hwmon_register;
0380
0381 MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE,
0382 page);
0383 rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO,
0384 inbuf, sizeof(inbuf),
0385 outbuf, sizeof(outbuf),
0386 &outlen);
0387 if (rc)
0388 goto fail;
0389 if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) {
0390 rc = -EIO;
0391 goto fail;
0392 }
0393
0394 mask = (MCDI_DWORD(outbuf,
0395 SENSOR_INFO_OUT_MASK) &
0396 ~(1 << MC_CMD_SENSOR_PAGE0_NEXT));
0397
0398
0399 if (outlen <
0400 MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask))) {
0401 rc = -EIO;
0402 goto fail;
0403 }
0404 }
0405 } while (!(mask & (1 << type % 32)));
0406 j++;
0407
0408 if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) {
0409 hwmon_type = efx_mcdi_sensor_type[type].hwmon_type;
0410
0411
0412 if (hwmon_type != EFX_HWMON_UNKNOWN &&
0413 efx_mcdi_sensor_type[type].port >= 0 &&
0414 efx_mcdi_sensor_type[type].port !=
0415 efx_port_num(efx))
0416 continue;
0417 } else {
0418 hwmon_type = EFX_HWMON_UNKNOWN;
0419 }
0420
0421 switch (hwmon_type) {
0422 case EFX_HWMON_TEMP:
0423 hwmon_prefix = "temp";
0424 hwmon_index = ++n_temp;
0425 break;
0426 case EFX_HWMON_COOL:
0427
0428
0429
0430
0431 hwmon_prefix = "fan";
0432 hwmon_index = ++n_cool;
0433 break;
0434 default:
0435 hwmon_prefix = "in";
0436 hwmon_index = n_in++;
0437 break;
0438 case EFX_HWMON_CURR:
0439 hwmon_prefix = "curr";
0440 hwmon_index = ++n_curr;
0441 break;
0442 case EFX_HWMON_POWER:
0443 hwmon_prefix = "power";
0444 hwmon_index = ++n_power;
0445 break;
0446 }
0447
0448 min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
0449 SENSOR_INFO_ENTRY, j, MIN1);
0450 max1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
0451 SENSOR_INFO_ENTRY, j, MAX1);
0452 min2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
0453 SENSOR_INFO_ENTRY, j, MIN2);
0454 max2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
0455 SENSOR_INFO_ENTRY, j, MAX2);
0456
0457 if (min1 != max1) {
0458 snprintf(name, sizeof(name), "%s%u_input",
0459 hwmon_prefix, hwmon_index);
0460 efx_mcdi_mon_add_attr(
0461 efx, name, efx_mcdi_mon_show_value, i, type, 0);
0462
0463 if (hwmon_type != EFX_HWMON_POWER) {
0464 snprintf(name, sizeof(name), "%s%u_min",
0465 hwmon_prefix, hwmon_index);
0466 efx_mcdi_mon_add_attr(
0467 efx, name, efx_mcdi_mon_show_limit,
0468 i, type, min1);
0469 }
0470
0471 snprintf(name, sizeof(name), "%s%u_max",
0472 hwmon_prefix, hwmon_index);
0473 efx_mcdi_mon_add_attr(
0474 efx, name, efx_mcdi_mon_show_limit,
0475 i, type, max1);
0476
0477 if (min2 != max2) {
0478
0479
0480
0481 snprintf(name, sizeof(name), "%s%u_crit",
0482 hwmon_prefix, hwmon_index);
0483 efx_mcdi_mon_add_attr(
0484 efx, name, efx_mcdi_mon_show_limit,
0485 i, type, max2);
0486 }
0487 }
0488
0489 snprintf(name, sizeof(name), "%s%u_alarm",
0490 hwmon_prefix, hwmon_index);
0491 efx_mcdi_mon_add_attr(
0492 efx, name, efx_mcdi_mon_show_alarm, i, type, 0);
0493
0494 if (type < ARRAY_SIZE(efx_mcdi_sensor_type) &&
0495 efx_mcdi_sensor_type[type].label) {
0496 snprintf(name, sizeof(name), "%s%u_label",
0497 hwmon_prefix, hwmon_index);
0498 efx_mcdi_mon_add_attr(
0499 efx, name, efx_mcdi_mon_show_label, i, type, 0);
0500 }
0501 }
0502
0503 hwmon_register:
0504 hwmon->groups[0] = &hwmon->group;
0505 hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev,
0506 KBUILD_MODNAME, NULL,
0507 hwmon->groups);
0508 if (IS_ERR(hwmon->device)) {
0509 rc = PTR_ERR(hwmon->device);
0510 goto fail;
0511 }
0512
0513 return 0;
0514
0515 fail:
0516 efx_mcdi_mon_remove(efx);
0517 return rc;
0518 }
0519
0520 void efx_mcdi_mon_remove(struct efx_nic *efx)
0521 {
0522 struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
0523
0524 if (hwmon->device)
0525 hwmon_device_unregister(hwmon->device);
0526 kfree(hwmon->attrs);
0527 kfree(hwmon->group.attrs);
0528 efx_nic_free_buffer(efx, &hwmon->dma_buf);
0529 }
0530
0531 #endif