[RFC linux v4 6/6] hwmon: Add OCC CAPS sensors
eajames.ibm at gmail.com
eajames.ibm at gmail.com
Fri Oct 14 08:43:13 AEDT 2016
From: "Edward A. James" <eajames at us.ibm.com>
Add CAPS sensors to sysfs.
Signed-off-by: Edward A. James <eajames at us.ibm.com>
---
drivers/hwmon/occ/power8_occ.c | 118 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 117 insertions(+), 1 deletion(-)
diff --git a/drivers/hwmon/occ/power8_occ.c b/drivers/hwmon/occ/power8_occ.c
index d264bf5..1a85fa0 100644
--- a/drivers/hwmon/occ/power8_occ.c
+++ b/drivers/hwmon/occ/power8_occ.c
@@ -659,6 +659,49 @@ static ssize_t show_label(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);
}
+static ssize_t show_caps(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int val;
+ struct caps_sensor *sensor;
+ struct sensor_attr_data *sdata = container_of(attr,
+ struct sensor_attr_data,
+ dev_attr);
+ struct power8_driver *driver = dev_get_drvdata(dev);
+ int n = sdata->hwmon_index - 1;
+
+ sensor = occ_get_sensor(driver, CAPS);
+ if (!sensor) {
+ val = -1;
+ return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);
+ }
+
+ switch (sdata->attr_id) {
+ case 0:
+ val = sensor[n].curr_powercap;
+ break;
+ case 1:
+ val = sensor[n].curr_powerreading;
+ break;
+ case 2:
+ val = sensor[n].norm_powercap;
+ break;
+ case 3:
+ val = sensor[n].max_powercap;
+ break;
+ case 4:
+ val = sensor[n].min_powercap;
+ break;
+ case 5:
+ val = sensor[n].user_powerlimit;
+ break;
+ default:
+ val = -1;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);
+}
+
static ssize_t show_update_interval(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -822,6 +865,77 @@ err:
return rc;
}
+static void caps_sensor_attr_init(struct sensor_attr_data *sdata,
+ char *attr_name, uint32_t hwmon_index,
+ uint32_t attr_id)
+{
+ sdata->type = CAPS;
+ sdata->hwmon_index = hwmon_index;
+ sdata->attr_id = attr_id;
+
+ snprintf(sdata->name, MAX_SENSOR_ATTR_LEN, "%s%d_%s",
+ "caps", sdata->hwmon_index, attr_name);
+
+ sysfs_attr_init(&sdata->dev_attr.attr);
+ sdata->dev_attr.attr.name = sdata->name;
+ sdata->dev_attr.attr.mode = S_IRUGO;
+ sdata->dev_attr.show = show_caps;
+}
+
+static char *caps_sensor_name[] = {
+ "curr_powercap",
+ "curr_powerreading",
+ "norm_powercap",
+ "max_powercap",
+ "min_powercap",
+ "user_powerlimit",
+};
+
+static int create_caps_sensor_group(struct power8_driver *driver,
+ int sensor_num)
+{
+ struct device *dev = driver->dev;
+ struct sensor_group *sensor_groups = driver->sensor_groups;
+ int field_num = ARRAY_SIZE(caps_sensor_name);
+ struct sensor_attr_data *sdata;
+ int i, j, rc;
+
+ sensor_groups[CAPS].group.attrs =
+ devm_kzalloc(dev, sizeof(struct attribute *) * sensor_num *
+ field_num + 1, GFP_KERNEL);
+ if (!sensor_groups[CAPS].group.attrs) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ sensor_groups[CAPS].sattr =
+ devm_kzalloc(dev, sizeof(struct sensor_attr_data) *
+ sensor_num * field_num, GFP_KERNEL);
+ if (!sensor_groups[CAPS].sattr) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ for (j = 0; j < sensor_num; ++j) {
+ for (i = 0; i < field_num; ++i) {
+ sdata = &sensor_groups[CAPS].sattr[j * field_num + i];
+ caps_sensor_attr_init(sdata, caps_sensor_name[i],
+ j + 1, i);
+ sensor_groups[CAPS].group.attrs[j * field_num + i] =
+ &sdata->dev_attr.attr;
+ }
+ }
+
+ rc = sysfs_create_group(&dev->kobj, &sensor_groups[CAPS].group);
+ if (rc)
+ goto err;
+
+ return rc;
+err:
+ deinit_sensor_groups(dev, sensor_groups);
+ return rc;
+}
+
static void occ_remove_hwmon_attrs(struct power8_driver *driver)
{
struct device *dev = driver->dev;
@@ -876,7 +990,9 @@ static int occ_create_hwmon_attrs(struct power8_driver *driver)
continue;
sensor_num = resp->blocks[id].sensor_num;
- if (i != CAPS)
+ if (i == CAPS)
+ rc = create_caps_sensor_group(driver, sensor_num);
+ else
rc = create_sensor_group(driver, i, sensor_num);
if (rc)
goto error;
--
1.9.1
More information about the openbmc
mailing list