Skip to content

Commit

Permalink
hwmon: (pmbus) Add mutex locking for sysfs reads
Browse files Browse the repository at this point in the history
As part of commit a919ba0 ("hwmon: (pmbus) Stop caching register
values"), the update of the sensor value is now triggered directly by the
sensor attribute value being read from sysfs. This created (or at least
made much more likely) a locking issue, since nothing protected the device
page selection from being unexpectedly modified by concurrent reads. If
sensor values on different pages on the same device were being concurrently
read by multiple threads, this could cause spurious read errors due to the
page register not reading back the same value last written, or sensor
values being read from the incorrect page.

Add locking of the update_lock mutex in pmbus_show_sensor and
pmbus_show_samples so that these cannot result in concurrent reads from the
underlying device.

Fixes: a919ba0 ("hwmon: (pmbus) Stop caching register values")
Signed-off-by: Robert Hancock <robert.hancock@calian.com>
Reviewed-by: Alex Qiu <xqiu@google.com>
Link: https://lore.kernel.org/r/20201103193315.3011800-1-robert.hancock@calian.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
  • Loading branch information
Robert Hancock authored and Guenter Roeck committed Nov 4, 2020
1 parent 402dab5 commit 18e8db7
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions drivers/hwmon/pmbus/pmbus_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -941,12 +941,16 @@ static ssize_t pmbus_show_sensor(struct device *dev,
struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
struct pmbus_data *data = i2c_get_clientdata(client);
ssize_t ret;

mutex_lock(&data->update_lock);
pmbus_update_sensor_data(client, sensor);
if (sensor->data < 0)
return sensor->data;

return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
ret = sensor->data;
else
ret = snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
mutex_unlock(&data->update_lock);
return ret;
}

static ssize_t pmbus_set_sensor(struct device *dev,
Expand Down Expand Up @@ -2012,8 +2016,11 @@ static ssize_t pmbus_show_samples(struct device *dev,
int 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);

mutex_lock(&data->update_lock);
val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
mutex_unlock(&data->update_lock);
if (val < 0)
return val;

Expand Down

0 comments on commit 18e8db7

Please sign in to comment.