[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