diff options
author | Eddie James <eajames@linux.ibm.com> | 2023-04-12 19:15:25 +0300 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2023-04-19 17:08:40 +0300 |
commit | a7ac37183ac2a0cc46d857997b2dd24997ca2754 (patch) | |
tree | b5e6d12e068df9c2bbfaeb190655cee7b73d43c5 /drivers/hwmon | |
parent | ab3e00416a0078be6d4126edc139536286d816e2 (diff) | |
download | linux-a7ac37183ac2a0cc46d857997b2dd24997ca2754.tar.xz |
hwmon: (pmbus/core) Add lock and unlock functions
Debugfs operations may set the page number, which must be done
atomically with the subsequent i2c operation. Lock the update_lock
in the debugfs functions and provide a function for pmbus drivers
to lock and unlock the update_lock.
Signed-off-by: Eddie James <eajames@linux.ibm.com>
Link: https://lore.kernel.org/r/20230412161526.252294-2-eajames@linux.ibm.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.h | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 30 |
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 11e84e141126..b0832a4c690d 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -505,6 +505,8 @@ int pmbus_get_fan_rate_device(struct i2c_client *client, int page, int id, enum pmbus_fan_mode mode); int pmbus_get_fan_rate_cached(struct i2c_client *client, int page, int id, enum pmbus_fan_mode mode); +int pmbus_lock_interruptible(struct i2c_client *client); +void pmbus_unlock(struct i2c_client *client); int pmbus_update_fan(struct i2c_client *client, int page, int id, u8 config, u8 mask, u16 command); struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index bf561277c430..80ec4a5493b4 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -3263,8 +3263,13 @@ static int pmbus_debugfs_get(void *data, u64 *val) { int rc; struct pmbus_debugfs_entry *entry = data; + struct pmbus_data *pdata = i2c_get_clientdata(entry->client); + rc = mutex_lock_interruptible(&pdata->update_lock); + if (rc) + return rc; rc = _pmbus_read_byte_data(entry->client, entry->page, entry->reg); + mutex_unlock(&pdata->update_lock); if (rc < 0) return rc; @@ -3281,7 +3286,11 @@ static int pmbus_debugfs_get_status(void *data, u64 *val) struct pmbus_debugfs_entry *entry = data; struct pmbus_data *pdata = i2c_get_clientdata(entry->client); + rc = mutex_lock_interruptible(&pdata->update_lock); + if (rc) + return rc; rc = pdata->read_status(entry->client, entry->page); + mutex_unlock(&pdata->update_lock); if (rc < 0) return rc; @@ -3297,10 +3306,15 @@ static ssize_t pmbus_debugfs_mfr_read(struct file *file, char __user *buf, { int rc; struct pmbus_debugfs_entry *entry = file->private_data; + struct pmbus_data *pdata = i2c_get_clientdata(entry->client); char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 }; + rc = mutex_lock_interruptible(&pdata->update_lock); + if (rc) + return rc; rc = pmbus_read_block_data(entry->client, entry->page, entry->reg, data); + mutex_unlock(&pdata->update_lock); if (rc < 0) return rc; @@ -3638,6 +3652,22 @@ struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client) } EXPORT_SYMBOL_NS_GPL(pmbus_get_debugfs_dir, PMBUS); +int pmbus_lock_interruptible(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + + return mutex_lock_interruptible(&data->update_lock); +} +EXPORT_SYMBOL_NS_GPL(pmbus_lock_interruptible, PMBUS); + +void pmbus_unlock(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + + mutex_unlock(&data->update_lock); +} +EXPORT_SYMBOL_NS_GPL(pmbus_unlock, PMBUS); + static int __init pmbus_core_init(void) { pmbus_debugfs_dir = debugfs_create_dir("pmbus", NULL); |