From c41dd48e21fae3e55b3670ccf2eb562fc1f6a67d Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 29 May 2019 19:56:04 -0700 Subject: hwmon: (core) add thermal sensors only if dev->of_node is present Drivers may register to hwmon and request for also registering with the thermal subsystem (HWMON_C_REGISTER_TZ). However, some of these driver, e.g. marvell phy, may be probed from Device Tree or being dynamically allocated, and in the later case, it will not have a dev->of_node entry. Registering with hwmon without the dev->of_node may result in different outcomes depending on the device tree, which may be a bit misleading. If the device tree blob has no 'thermal-zones' node, the *hwmon_device_register*() family functions are going to gracefully succeed, because of-thermal, *thermal_zone_of_sensor_register() return -ENODEV in this case, and the hwmon error path handles this error code as success to cover for the case where CONFIG_THERMAL_OF is not set. However, if the device tree blob has the 'thermal-zones' entry, the *hwmon_device_register*() will always fail on callers with no dev->of_node, propagating -EINVAL. If dev->of_node is not present, calling of-thermal does not make sense. For this reason, this patch checks first if the device has a of_node before going over the process of registering with the thermal subsystem of-thermal interface. And in this case, when a caller of *hwmon_device_register*() with HWMON_C_REGISTER_TZ and no dev->of_node will still register with hwmon, but not with the thermal subsystem. If all the hwmon part bits are in place, the registration will succeed. Fixes: d560168b5d0f ("hwmon: (core) New hwmon registration API") Cc: Jean Delvare Cc: Guenter Roeck Cc: linux-hwmon@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Guenter Roeck --- drivers/hwmon/hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index e694c46ff039..429784edd5ff 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -636,7 +636,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, if (err) goto free_hwmon; - if (dev && chip && chip->ops->read && + if (dev && dev->of_node && chip && chip->ops->read && chip->info[0]->type == hwmon_chip && (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) { const struct hwmon_channel_info **info = chip->info; -- cgit v1.2.3 From 38463721ec3c39acdabed3a89016ce6bb32a7543 Mon Sep 17 00:00:00 2001 From: "Adamski, Krzysztof (Nokia - PL/Wroclaw)" Date: Wed, 29 May 2019 14:33:52 +0000 Subject: hwmon: (pmbus/core) mutex_lock write in pmbus_set_samples update_lock is a mutex intended to protect write operations. It was not taken, however, when _pmbus_write_word_data is called from pmbus_set_samples() function which may cause problems especially when some PMBUS_VIRT_* operation is implemented as a read-modify-write cycle. This patch makes sure the lock is held during the operation. Fixes: 49c4455dccf2 ("hwmon: (pmbus) Introduce PMBUS_VIRT_*_SAMPLES registers") Signed-off-by: Krzysztof Adamski Reviewed-by: Alexander Sverdlin [groeck: Declared and initialized missing 'data' variable] Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/pmbus_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index ef7ee90ee785..48c2d5ae42a6 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -1942,11 +1942,14 @@ static ssize_t pmbus_set_samples(struct device *dev, long val; struct i2c_client *client = to_i2c_client(dev->parent); struct pmbus_samples_reg *reg = to_samples_reg(devattr); + struct pmbus_data *data = i2c_get_clientdata(client); if (kstrtol(buf, 0, &val) < 0) return -EINVAL; + mutex_lock(&data->update_lock); ret = _pmbus_write_word_data(client, reg->page, reg->attr->reg, val); + mutex_unlock(&data->update_lock); return ret ? : count; } -- cgit v1.2.3 From 4a60570dce658e3f8885bbcf852430b99f65aca5 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Wed, 5 Jun 2019 13:49:00 -0600 Subject: hwmon: (pmbus/core) Treat parameters as paged if on multiple pages Some chips have attributes which exist on more than one page but the attribute is not presently marked as paged. This causes the attributes to be generated with the same label, which makes it impossible for userspace to tell them apart. Marking all such attributes as paged would result in the page suffix being added regardless of whether they were present on more than one page or not, which might break existing setups. Therefore, we add a second check which treats the attribute as paged, even if not marked as such, if it is present on multiple pages. Fixes: b4ce237b7f7d ("hwmon: (pmbus) Introduce infrastructure to detect sensors and limit registers") Signed-off-by: Robert Hancock Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/pmbus_core.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 48c2d5ae42a6..8470097907bc 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -1217,7 +1217,8 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, const struct pmbus_driver_info *info, const char *name, int index, int page, - const struct pmbus_sensor_attr *attr) + const struct pmbus_sensor_attr *attr, + bool paged) { struct pmbus_sensor *base; bool upper = !!(attr->gbit & 0xff00); /* need to check STATUS_WORD */ @@ -1225,7 +1226,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, if (attr->label) { ret = pmbus_add_label(data, name, index, attr->label, - attr->paged ? page + 1 : 0); + paged ? page + 1 : 0); if (ret) return ret; } @@ -1258,6 +1259,30 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, return 0; } +static bool pmbus_sensor_is_paged(const struct pmbus_driver_info *info, + const struct pmbus_sensor_attr *attr) +{ + int p; + + if (attr->paged) + return true; + + /* + * Some attributes may be present on more than one page despite + * not being marked with the paged attribute. If that is the case, + * then treat the sensor as being paged and add the page suffix to the + * attribute name. + * We don't just add the paged attribute to all such attributes, in + * order to maintain the un-suffixed labels in the case where the + * attribute is only on page 0. + */ + for (p = 1; p < info->pages; p++) { + if (info->func[p] & attr->func) + return true; + } + return false; +} + static int pmbus_add_sensor_attrs(struct i2c_client *client, struct pmbus_data *data, const char *name, @@ -1271,14 +1296,15 @@ static int pmbus_add_sensor_attrs(struct i2c_client *client, index = 1; for (i = 0; i < nattrs; i++) { int page, pages; + bool paged = pmbus_sensor_is_paged(info, attrs); - pages = attrs->paged ? info->pages : 1; + pages = paged ? info->pages : 1; for (page = 0; page < pages; page++) { if (!(info->func[page] & attrs->func)) continue; ret = pmbus_add_sensor_attrs_one(client, data, info, name, index, page, - attrs); + attrs, paged); if (ret) return ret; index++; -- cgit v1.2.3