type = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR);
state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE);
value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE);
/* Deal gracefully with the board having more drivers than we
* know about, but do not expect new sensor states. */ if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) {
name = efx_mcdi_sensor_type[type].label;
hwmon_type = efx_mcdi_sensor_type[type].hwmon_type;
} if (!name)
name = "No sensor name available";
EFX_WARN_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
state_txt = sensor_status_names[state];
EFX_WARN_ON_PARANOID(hwmon_type >= EFX_HWMON_TYPES_COUNT);
unit = efx_hwmon_unit[hwmon_type]; if (!unit)
unit = "";
netif_err(efx, hw, efx->net_dev, "Sensor %d (%s) reports condition '%s' for value %d%s\n",
type, name, state_txt, value, unit);
}
rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry); if (rc) return rc;
state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); if (state == MC_CMD_SENSOR_STATE_NO_READING) return -EBUSY;
value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
switch (mon_attr->hwmon_type) { case EFX_HWMON_TEMP: /* Convert temperature from degrees to milli-degrees Celsius */
value *= 1000; break; case EFX_HWMON_POWER: /* Convert power from watts to microwatts */
value *= 1000000; break; default: /* No conversion needed */ break;
}
switch (mon_attr->hwmon_type) { case EFX_HWMON_TEMP: /* Convert temperature from degrees to milli-degrees Celsius */
value *= 1000; break; case EFX_HWMON_POWER: /* Convert power from watts to microwatts */
value *= 1000000; break; default: /* No conversion needed */ break;
}
/* Allocate space for the maximum possible number of * attributes for this set of sensors: * value, min, max, crit, alarm and label for each sensor.
*/
n_attrs = 6 * n_sensors;
hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); if (!hwmon->attrs) {
rc = -ENOMEM; goto fail;
}
hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *),
GFP_KERNEL); if (!hwmon->group.attrs) {
rc = -ENOMEM; goto fail;
}
for (i = 0, j = -1, type = -1; ; i++) { enum efx_hwmon_type hwmon_type; constchar *hwmon_prefix; unsigned hwmon_index;
u16 min1, max1, min2, max2;
/* Find next sensor type or exit if there is none */ do {
type++;
if ((type % 32) == 0) {
page = type / 32;
j = -1; if (page == n_pages) goto hwmon_register;
/* Check again for short response */ if (outlen <
MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask))) {
rc = -EIO; goto fail;
}
}
} while (!(mask & (1 << type % 32)));
j++;
if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) {
hwmon_type = efx_mcdi_sensor_type[type].hwmon_type;
/* Skip sensors specific to a different port */ if (hwmon_type != EFX_HWMON_UNKNOWN &&
efx_mcdi_sensor_type[type].port >= 0 &&
efx_mcdi_sensor_type[type].port !=
efx_port_num(efx)) continue;
} else {
hwmon_type = EFX_HWMON_UNKNOWN;
}
switch (hwmon_type) { case EFX_HWMON_TEMP:
hwmon_prefix = "temp";
hwmon_index = ++n_temp; /* 1-based */ break; case EFX_HWMON_COOL: /* This is likely to be a heatsink, but there * is no convention for representing cooling * devices other than fans.
*/
hwmon_prefix = "fan";
hwmon_index = ++n_cool; /* 1-based */ break; default:
hwmon_prefix = "in";
hwmon_index = n_in++; /* 0-based */ break; case EFX_HWMON_CURR:
hwmon_prefix = "curr";
hwmon_index = ++n_curr; /* 1-based */ break; case EFX_HWMON_POWER:
hwmon_prefix = "power";
hwmon_index = ++n_power; /* 1-based */ break;
}
if (min2 != max2) { /* Assume max2 is critical value. * But we have no good way to expose min2.
*/
snprintf(name, sizeof(name), "%s%u_crit",
hwmon_prefix, hwmon_index);
efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit,
i, type, max2);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.