switch (sattr->nr) { case 0:
val = get_unaligned_be16(&temp->sensor_id); break; case 1: /* * If a sensor reading has expired and couldn't be refreshed, * OCC returns 0xFFFF for that sensor.
*/ if (temp->value == 0xFFFF) return -EREMOTEIO;
val = get_unaligned_be16(&temp->value) * 1000; break; default: return -EINVAL;
}
switch (sattr->nr) { case 0:
val = get_unaligned_be32(&temp->sensor_id); break; case 1:
val = temp->value; if (val == OCC_TEMP_SENSOR_FAULT) return -EREMOTEIO;
/* * VRM doesn't return temperature, only alarm bit. This * attribute maps to tempX_alarm instead of tempX_input for * VRM
*/ if (temp->fru_type != OCC_FRU_TYPE_VRM) { /* sensor not ready */ if (val == 0) return -EAGAIN;
val *= 1000;
} break; case 2:
val = temp->fru_type; break; case 3:
val = temp->value == OCC_TEMP_SENSOR_FAULT; break; default: return -EINVAL;
}
switch (sattr->nr) { case 0:
val = get_unaligned_be32(&temp->sensor_id); break; case 1:
val = temp->value; if (val == OCC_TEMP_SENSOR_FAULT) return -EREMOTEIO;
/* sensor not ready */ if (val == 0) return -EAGAIN;
val *= 1000; break; case 2:
val = temp->fru_type; break; case 3:
val = temp->value == OCC_TEMP_SENSOR_FAULT; break; case 4:
val = temp->throttle * 1000; break; default: return -EINVAL;
}
switch (sattr->nr) { case 0:
val = get_unaligned_be16(&freq->sensor_id); break; case 1:
val = get_unaligned_be16(&freq->value); break; default: return -EINVAL;
}
switch (sattr->nr) { case 0:
val = get_unaligned_be32(&freq->sensor_id); break; case 1:
val = get_unaligned_be16(&freq->value); break; default: return -EINVAL;
}
power = ((struct power_sensor_1 *)sensors->power.data) + sattr->index;
switch (sattr->nr) { case 0:
val = get_unaligned_be16(&power->sensor_id); break; case 1:
val = get_unaligned_be32(&power->accumulator) /
get_unaligned_be32(&power->update_tag);
val *= 1000000ULL; break; case 2:
val = (u64)get_unaligned_be32(&power->update_tag) *
occ->powr_sample_time_us; break; case 3:
val = get_unaligned_be16(&power->value) * 1000000ULL; break; default: return -EINVAL;
}
power = ((struct power_sensor_a0 *)sensors->power.data) + sattr->index;
switch (sattr->nr) { case 0: return sysfs_emit(buf, "%u_system\n",
get_unaligned_be32(&power->sensor_id)); case 1:
val = occ_get_powr_avg(get_unaligned_be64(&power->system.accumulator),
get_unaligned_be32(&power->system.update_tag)); break; case 2:
val = (u64)get_unaligned_be32(&power->system.update_tag) *
occ->powr_sample_time_us; break; case 3:
val = get_unaligned_be16(&power->system.value) * 1000000ULL; break; case 4: return sysfs_emit(buf, "%u_proc\n",
get_unaligned_be32(&power->sensor_id)); case 5:
val = occ_get_powr_avg(get_unaligned_be64(&power->proc.accumulator),
get_unaligned_be32(&power->proc.update_tag)); break; case 6:
val = (u64)get_unaligned_be32(&power->proc.update_tag) *
occ->powr_sample_time_us; break; case 7:
val = get_unaligned_be16(&power->proc.value) * 1000000ULL; break; case 8: return sysfs_emit(buf, "%u_vdd\n",
get_unaligned_be32(&power->sensor_id)); case 9:
val = occ_get_powr_avg(get_unaligned_be64(&power->vdd.accumulator),
get_unaligned_be32(&power->vdd.update_tag)); break; case 10:
val = (u64)get_unaligned_be32(&power->vdd.update_tag) *
occ->powr_sample_time_us; break; case 11:
val = get_unaligned_be16(&power->vdd.value) * 1000000ULL; break; case 12: return sysfs_emit(buf, "%u_vdn\n",
get_unaligned_be32(&power->sensor_id)); case 13:
val = occ_get_powr_avg(get_unaligned_be64(&power->vdn.accumulator),
get_unaligned_be32(&power->vdn.update_tag)); break; case 14:
val = (u64)get_unaligned_be32(&power->vdn.update_tag) *
occ->powr_sample_time_us; break; case 15:
val = get_unaligned_be16(&power->vdn.value) * 1000000ULL; break; default: return -EINVAL;
}
switch (sattr->nr) { case 0: return sysfs_emit(buf, "system\n"); case 1:
val = get_unaligned_be16(&caps->cap) * 1000000ULL; break; case 2:
val = get_unaligned_be16(&caps->system_power) * 1000000ULL; break; case 3:
val = get_unaligned_be16(&caps->n_cap) * 1000000ULL; break; case 4:
val = get_unaligned_be16(&caps->max) * 1000000ULL; break; case 5:
val = get_unaligned_be16(&caps->min) * 1000000ULL; break; case 6:
val = get_unaligned_be16(&caps->user) * 1000000ULL; break; case 7: if (occ->sensors.caps.version == 1) return -EINVAL;
val = caps->user_source; break; default: return -EINVAL;
}
switch (sattr->nr) { case 0: return sysfs_emit(buf, "system\n"); case 1:
val = get_unaligned_be16(&caps->cap) * 1000000ULL; break; case 2:
val = get_unaligned_be16(&caps->system_power) * 1000000ULL; break; case 3:
val = get_unaligned_be16(&caps->n_cap) * 1000000ULL; break; case 4:
val = get_unaligned_be16(&caps->max) * 1000000ULL; break; case 5:
val = get_unaligned_be16(&caps->hard_min) * 1000000ULL; break; case 6:
val = get_unaligned_be16(&caps->user) * 1000000ULL; break; case 7:
val = caps->user_source; break; case 8:
val = get_unaligned_be16(&caps->soft_min) * 1000000ULL; break; default: return -EINVAL;
}
/* * A helper to make it easier to define an occ_attribute. Since these * are dynamically allocated, we cannot use the existing kernel macros which * stringify the name argument.
*/ staticvoid occ_init_attribute(struct occ_attribute *attr, int mode,
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf),
ssize_t (*store)(struct device *dev, struct device_attribute *attr, constchar *buf, size_t count), int nr, int index, constchar *fmt, ...)
{
va_list args;
occ->attrs = devm_kcalloc(dev, num_attrs, sizeof(*occ->attrs),
GFP_KERNEL); if (!occ->attrs) return -ENOMEM;
/* null-terminated list */
occ->group.attrs = devm_kcalloc(dev, num_attrs + 1, sizeof(*occ->group.attrs),
GFP_KERNEL); if (!occ->group.attrs) return -ENOMEM;
attr = occ->attrs;
for (i = 0; i < sensors->temp.num_sensors; ++i) {
s = i + 1;
temp = ((struct temp_sensor_2 *)sensors->temp.data) + i;
occ_init_attribute(attr, 0444, show_temp, NULL,
0, i, "temp%d_label", s);
attr++;
if (sensors->temp.version == 2 &&
temp->fru_type == OCC_FRU_TYPE_VRM) {
occ_init_attribute(attr, 0444, show_temp, NULL,
1, i, "temp%d_alarm", s);
} else {
occ_init_attribute(attr, 0444, show_temp, NULL,
1, i, "temp%d_input", s);
}
attr++;
if (sensors->temp.version > 1) {
occ_init_attribute(attr, 0444, show_temp, NULL,
2, i, "temp%d_fru_type", s);
attr++;
occ_init_attribute(attr, 0444, show_temp, NULL,
3, i, "temp%d_fault", s);
attr++;
if (sensors->temp.version == 0x10) {
occ_init_attribute(attr, 0444, show_temp, NULL,
4, i, "temp%d_max", s);
attr++;
}
}
}
for (i = 0; i < sensors->freq.num_sensors; ++i) {
s = i + 1;
occ_init_attribute(attr, 0444, show_freq, NULL,
0, i, "freq%d_label", s);
attr++;
occ_init_attribute(attr, 0444, show_freq, NULL,
1, i, "freq%d_input", s);
attr++;
}
if (sensors->power.version == 0xA0) { /* * Special case for many-attribute power sensor. Split it into * a sensor number per power type, emulating several sensors.
*/ for (i = 0; i < sensors->power.num_sensors; ++i) { unsignedint j; unsignedint nr = 0;
s = (i * 4) + 1;
for (j = 0; j < 4; ++j) {
occ_init_attribute(attr, 0444, show_power,
NULL, nr++, i, "power%d_label", s);
attr++;
occ_init_attribute(attr, 0444, show_power,
NULL, nr++, i, "power%d_average", s);
attr++;
occ_init_attribute(attr, 0444, show_power,
NULL, nr++, i, "power%d_average_interval", s);
attr++;
occ_init_attribute(attr, 0444, show_power,
NULL, nr++, i, "power%d_input", s);
attr++;
s++;
}
}
s = (sensors->power.num_sensors * 4) + 1;
} else { for (i = 0; i < sensors->power.num_sensors; ++i) {
s = i + 1;
occ_init_attribute(attr, 0444, show_power, NULL,
0, i, "power%d_label", s);
attr++;
occ_init_attribute(attr, 0444, show_power, NULL,
1, i, "power%d_average", s);
attr++;
occ_init_attribute(attr, 0444, show_power, NULL,
2, i, "power%d_average_interval", s);
attr++;
occ_init_attribute(attr, 0444, show_power, NULL,
3, i, "power%d_input", s);
attr++;
}
for (i = 0; i < sensors->extended.num_sensors; ++i) {
s = i + 1;
occ_init_attribute(attr, 0444, occ_show_extended, NULL,
0, i, "extn%d_label", s);
attr++;
occ_init_attribute(attr, 0444, occ_show_extended, NULL,
1, i, "extn%d_flags", s);
attr++;
occ_init_attribute(attr, 0444, occ_show_extended, NULL,
2, i, "extn%d_input", s);
attr++;
}
/* put the sensors in the group */ for (i = 0; i < num_attrs; ++i) {
sysfs_attr_init(&occ->attrs[i].sensor.dev_attr.attr);
occ->group.attrs[i] = &occ->attrs[i].sensor.dev_attr.attr;
}
return 0;
}
/* only need to do this once at startup, as OCC won't change sensors on us */ staticvoid occ_parse_poll_response(struct occ *occ)
{ unsignedint i, old_offset, offset = 0, size = 0; struct occ_sensor *sensor; struct occ_sensors *sensors = &occ->sensors; struct occ_response *resp = &occ->resp; struct occ_poll_response *poll =
(struct occ_poll_response *)&resp->data[0]; struct occ_poll_response_header *header = &poll->header; struct occ_sensor_data_block *block = &poll->block;
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.