diff options
Diffstat (limited to 'drivers/hwmon/occ')
-rw-r--r-- | drivers/hwmon/occ/Kconfig | 17 | ||||
-rw-r--r-- | drivers/hwmon/occ/Makefile | 6 | ||||
-rw-r--r-- | drivers/hwmon/occ/common.c | 17 | ||||
-rw-r--r-- | drivers/hwmon/occ/common.h | 3 | ||||
-rw-r--r-- | drivers/hwmon/occ/sysfs.c | 29 |
5 files changed, 51 insertions, 21 deletions
diff --git a/drivers/hwmon/occ/Kconfig b/drivers/hwmon/occ/Kconfig index 66686628fb53..1658634a053e 100644 --- a/drivers/hwmon/occ/Kconfig +++ b/drivers/hwmon/occ/Kconfig @@ -5,11 +5,14 @@ config SENSORS_OCC_P8_I2C tristate "POWER8 OCC through I2C" depends on I2C + depends on ARM || ARM64 || COMPILE_TEST select SENSORS_OCC help This option enables support for monitoring sensors provided by the - On-Chip Controller (OCC) on a POWER8 processor. Communications with - the OCC are established through I2C bus. + On-Chip Controller (OCC) on a POWER8 processor. However, this driver + can only run on a baseboard management controller (BMC) connected to + the P8, not the POWER processor itself. Communications with the OCC are + established through I2C bus. This driver can also be built as a module. If so, the module will be called occ-p8-hwmon. @@ -17,15 +20,17 @@ config SENSORS_OCC_P8_I2C config SENSORS_OCC_P9_SBE tristate "POWER9 OCC through SBE" depends on FSI_OCC + depends on ARM || ARM64 || COMPILE_TEST select SENSORS_OCC help This option enables support for monitoring sensors provided by the - On-Chip Controller (OCC) on a POWER9 processor. Communications with - the OCC are established through SBE fifo on an FSI bus. + On-Chip Controller (OCC) on a POWER9 processor. However, this driver + can only run on a baseboard management controller (BMC) connected to + the P9, not the POWER processor itself. Communications with the OCC are + established through SBE fifo on an FSI bus. This driver can also be built as a module. If so, the module will be called occ-p9-hwmon. config SENSORS_OCC - bool "POWER On-Chip Controller" - depends on SENSORS_OCC_P8_I2C || SENSORS_OCC_P9_SBE + tristate diff --git a/drivers/hwmon/occ/Makefile b/drivers/hwmon/occ/Makefile index 3fec12ddc7e7..493588d5a9d3 100644 --- a/drivers/hwmon/occ/Makefile +++ b/drivers/hwmon/occ/Makefile @@ -1,5 +1,7 @@ -occ-p8-hwmon-objs := common.o sysfs.o p8_i2c.o -occ-p9-hwmon-objs := common.o sysfs.o p9_sbe.o +occ-hwmon-common-objs := common.o sysfs.o +occ-p8-hwmon-objs := p8_i2c.o +occ-p9-hwmon-objs := p9_sbe.o +obj-$(CONFIG_SENSORS_OCC) += occ-hwmon-common.o obj-$(CONFIG_SENSORS_OCC_P8_I2C) += occ-p8-hwmon.o obj-$(CONFIG_SENSORS_OCC_P9_SBE) += occ-p9-hwmon.o diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index b91a80abf724..13a6290c8d25 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -2,11 +2,13 @@ // Copyright IBM Corp 2019 #include <linux/device.h> +#include <linux/export.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/math64.h> +#include <linux/module.h> #include <linux/mutex.h> #include <linux/sysfs.h> #include <asm/unaligned.h> @@ -139,6 +141,7 @@ static int occ_poll(struct occ *occ) /* mutex should already be locked if necessary */ rc = occ->send_cmd(occ, cmd); if (rc) { + occ->last_error = rc; if (occ->error_count++ > OCC_ERROR_COUNT_THRESHOLD) occ->error = rc; @@ -147,6 +150,7 @@ static int occ_poll(struct occ *occ) /* clear error since communication was successful */ occ->error_count = 0; + occ->last_error = 0; occ->error = 0; /* check for safe state */ @@ -208,6 +212,8 @@ int occ_update_response(struct occ *occ) if (time_after(jiffies, occ->last_update + OCC_UPDATE_FREQUENCY)) { rc = occ_poll(occ); occ->last_update = jiffies; + } else { + rc = occ->last_error; } mutex_unlock(&occ->lock); @@ -890,6 +896,8 @@ static int occ_setup_sensor_attrs(struct occ *occ) s++; } } + + s = (sensors->power.num_sensors * 4) + 1; } else { for (i = 0; i < sensors->power.num_sensors; ++i) { s = i + 1; @@ -918,11 +926,11 @@ static int occ_setup_sensor_attrs(struct occ *occ) show_power, NULL, 3, i); attr++; } - } - if (sensors->caps.num_sensors >= 1) { s = sensors->power.num_sensors + 1; + } + if (sensors->caps.num_sensors >= 1) { snprintf(attr->name, sizeof(attr->name), "power%d_label", s); attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, 0, 0); @@ -1097,3 +1105,8 @@ int occ_setup(struct occ *occ, const char *name) return rc; } +EXPORT_SYMBOL_GPL(occ_setup); + +MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>"); +MODULE_DESCRIPTION("Common OCC hwmon code"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h index ed2cf4245295..fc13f3c73c47 100644 --- a/drivers/hwmon/occ/common.h +++ b/drivers/hwmon/occ/common.h @@ -106,7 +106,8 @@ struct occ { struct attribute_group group; const struct attribute_group *groups[2]; - int error; /* latest transfer error */ + int error; /* final transfer error after retry */ + int last_error; /* latest transfer error */ unsigned int error_count; /* number of xfr errors observed */ unsigned long last_safe; /* time OCC entered "safe" state */ diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c index fe3d15e416e7..c73be0747e66 100644 --- a/drivers/hwmon/occ/sysfs.c +++ b/drivers/hwmon/occ/sysfs.c @@ -3,6 +3,7 @@ #include <linux/bitops.h> #include <linux/device.h> +#include <linux/export.h> #include <linux/hwmon-sysfs.h> #include <linux/kernel.h> #include <linux/sysfs.h> @@ -42,16 +43,16 @@ static ssize_t occ_sysfs_show(struct device *dev, val = !!(header->status & OCC_STAT_ACTIVE); break; case 2: - val = !!(header->status & OCC_EXT_STAT_DVFS_OT); + val = !!(header->ext_status & OCC_EXT_STAT_DVFS_OT); break; case 3: - val = !!(header->status & OCC_EXT_STAT_DVFS_POWER); + val = !!(header->ext_status & OCC_EXT_STAT_DVFS_POWER); break; case 4: - val = !!(header->status & OCC_EXT_STAT_MEM_THROTTLE); + val = !!(header->ext_status & OCC_EXT_STAT_MEM_THROTTLE); break; case 5: - val = !!(header->status & OCC_EXT_STAT_QUICK_DROP); + val = !!(header->ext_status & OCC_EXT_STAT_QUICK_DROP); break; case 6: val = header->occ_state; @@ -62,9 +63,6 @@ static ssize_t occ_sysfs_show(struct device *dev, else val = 1; break; - case 8: - val = occ->error; - break; default: return -EINVAL; } @@ -72,6 +70,16 @@ static ssize_t occ_sysfs_show(struct device *dev, return snprintf(buf, PAGE_SIZE - 1, "%d\n", val); } +static ssize_t occ_error_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct occ *occ = dev_get_drvdata(dev); + + occ_update_response(occ); + + return snprintf(buf, PAGE_SIZE - 1, "%d\n", occ->error); +} + static SENSOR_DEVICE_ATTR(occ_master, 0444, occ_sysfs_show, NULL, 0); static SENSOR_DEVICE_ATTR(occ_active, 0444, occ_sysfs_show, NULL, 1); static SENSOR_DEVICE_ATTR(occ_dvfs_overtemp, 0444, occ_sysfs_show, NULL, 2); @@ -80,7 +88,7 @@ static SENSOR_DEVICE_ATTR(occ_mem_throttle, 0444, occ_sysfs_show, NULL, 4); static SENSOR_DEVICE_ATTR(occ_quick_pwr_drop, 0444, occ_sysfs_show, NULL, 5); static SENSOR_DEVICE_ATTR(occ_state, 0444, occ_sysfs_show, NULL, 6); static SENSOR_DEVICE_ATTR(occs_present, 0444, occ_sysfs_show, NULL, 7); -static SENSOR_DEVICE_ATTR(occ_error, 0444, occ_sysfs_show, NULL, 8); +static DEVICE_ATTR_RO(occ_error); static struct attribute *occ_attributes[] = { &sensor_dev_attr_occ_master.dev_attr.attr, @@ -91,7 +99,7 @@ static struct attribute *occ_attributes[] = { &sensor_dev_attr_occ_quick_pwr_drop.dev_attr.attr, &sensor_dev_attr_occ_state.dev_attr.attr, &sensor_dev_attr_occs_present.dev_attr.attr, - &sensor_dev_attr_occ_error.dev_attr.attr, + &dev_attr_occ_error.attr, NULL }; @@ -155,7 +163,7 @@ void occ_sysfs_poll_done(struct occ *occ) } if (occ->error && occ->error != occ->prev_error) { - name = sensor_dev_attr_occ_error.dev_attr.attr.name; + name = dev_attr_occ_error.attr.name; sysfs_notify(&occ->bus_dev->kobj, NULL, name); } @@ -177,3 +185,4 @@ void occ_shutdown(struct occ *occ) { sysfs_remove_group(&occ->bus_dev->kobj, &occ_sysfs); } +EXPORT_SYMBOL_GPL(occ_shutdown); |