diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-01 09:42:51 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-01 09:42:51 -0700 |
commit | 989253cc46ff3f4973495b58e02c7fcb1ffb713e (patch) | |
tree | 8d2630b2b154e32bf56b3772a413b57e1657993c /drivers/hwmon/hwmon.c | |
parent | 57cf7a603b6d2524edffaa3068d9aa7a41641d93 (diff) | |
parent | 76bb6969a8cfc5e00ca142fdad86ffd0a6ed9ecd (diff) |
Merge tag 'hwmon-for-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck:
"New drivers:
- Kontron SMARC-sAM67
- GPD device sensors
- MP29502
- MP2869, MP29608, MP29612 and MP29816 series
Added chip support to existing drivers:
- asus-ec-sensors:
Add B650E-I
Add PRIME Z270-A
Add Pro WS WRX90E-SAGE SE
Add ROG STRIX X670E-E GAMING WIFI
Add ROG STRIX X870-I GAMING WIFI
Add ROG STRIX X870E-E GAMING WIFI
Add ROG STRIX Z690-E GAMING WIFI
Add ROG STRIX Z790E GAMING WIFI II
Add STRIX B850-I GAMING WIFI
Add TUF GAMING X670E PLUS WIFI
Add X670E-I GAMING WIFI
Add Z790-I GAMING WIFI
- dell-smm: Add support for Dell OptiPlex 7040
- ina238: Major cleanup, and
Add support for INA700
Add support for INA780
- k10temp:
Add device ID for Strix Halo
Add support for AMD Family 1Ah-based models
- lenovo-ec-sensors: Update P8 supprt
- lm75: Add NXP P3T1750 support
- pmbus/adm1275: Add sq24905c support
- pmbus/isl68137: Add support for Renesas RAA228244 and RAA228246
- pmbus/mp5990: Add support for MP5998
- sht21: Add support for SHT20, SHT25
- sl28cpld: Add sa67mcu compatible
Other notable changes:
- core:
Handle locking internally
Introduce 64-bit energy attribute support
- cros_ec: Register into thermal framework, improve PWM control
- lm75: allow interrupt for ti,tmp75
- mlxreg-fan: Add support for new flavour of capability register
- sbtsi_temp: AMD CPU extended temperature range support
- sht21: Add devicetree support
Various other minor improvements and fixes"
* tag 'hwmon-for-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (86 commits)
dt-bindings: hwmon: (lm75) allow interrupt for ti,tmp75
hwmon: (mlxreg-fan) Add support for new flavour of capability register
hwmon: (mlxreg-fan) Separate methods of fan setting coming from different subsystems
hwmon: (cros_ec) register fans into thermal framework cooling devices
hwmon: (cros_ec) add PWM control over fans
platform/chrome: update pwm fan control host commands
hwmon: add SMARC-sAM67 support
dt-bindings: hwmon: sl28cpld: add sa67mcu compatible
hwmon: (asus-ec-sensors) add TUF GAMING X670E PLUS WIFI
hwmon: (dell-smm) Add support for Dell OptiPlex 7040
hwmon: (dell-smm) Add support for automatic fan mode
hwmon: (gpd-fan) complete Kconfig dependencies
hwmon: (asus-ec-sensors) increase timeout for locking ACPI mutex
hwmon: (asus-ec-sensors) add ROG STRIX X870E-E GAMING WIFI
hwmon: (dell-smm) Move clamping of fan speed out of i8k_set_fan()
hwmon: (dell-smm) Remove Dell Precision 490 custom config data
hwmon: (asus-ec-sensors) add ROG STRIX X670E-E GAMING WIFI
hwmon: (gpd-fan) Fix range check for pwm input
hwmon: (pmbus/mp5990) add support for MP5998
dt-bindings: trivial-devices: add mps,mp5998
...
Diffstat (limited to 'drivers/hwmon/hwmon.c')
-rw-r--r-- | drivers/hwmon/hwmon.c | 56 |
1 files changed, 45 insertions, 11 deletions
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 1688c210888a..0b4bdcd33c7b 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -19,6 +19,7 @@ #include <linux/kstrtox.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/pci.h> #include <linux/property.h> #include <linux/slab.h> @@ -36,6 +37,7 @@ struct hwmon_device { const char *label; struct device dev; const struct hwmon_chip_info *chip; + struct mutex lock; struct list_head tzdata; struct attribute_group group; const struct attribute_group **groups; @@ -165,6 +167,8 @@ static int hwmon_thermal_get_temp(struct thermal_zone_device *tz, int *temp) int ret; long t; + guard(mutex)(&hwdev->lock); + ret = hwdev->chip->ops->read(tdata->dev, hwmon_temp, hwmon_temp_input, tdata->index, &t); if (ret < 0) @@ -193,6 +197,8 @@ static int hwmon_thermal_set_trips(struct thermal_zone_device *tz, int low, int if (!info[i]) return 0; + guard(mutex)(&hwdev->lock); + if (info[i]->config[tdata->index] & HWMON_T_MIN) { err = chip->ops->write(tdata->dev, hwmon_temp, hwmon_temp_min, tdata->index, low); @@ -330,8 +336,6 @@ static int hwmon_attr_base(enum hwmon_sensor_types type) * attached to an i2c client device. */ -static DEFINE_MUTEX(hwmon_pec_mutex); - static int hwmon_match_device(struct device *dev, const void *data) { return dev->class == &hwmon_class; @@ -362,17 +366,16 @@ static ssize_t pec_store(struct device *dev, struct device_attribute *devattr, if (!hdev) return -ENODEV; - mutex_lock(&hwmon_pec_mutex); - /* * If there is no write function, we assume that chip specific * handling is not required. */ hwdev = to_hwmon_device(hdev); + guard(mutex)(&hwdev->lock); if (hwdev->chip->ops->write) { err = hwdev->chip->ops->write(hdev, hwmon_chip, hwmon_chip_pec, 0, val); if (err && err != -EOPNOTSUPP) - goto unlock; + goto put; } if (!val) @@ -381,8 +384,7 @@ static ssize_t pec_store(struct device *dev, struct device_attribute *devattr, client->flags |= I2C_CLIENT_PEC; err = count; -unlock: - mutex_unlock(&hwmon_pec_mutex); +put: put_device(hdev); return err; @@ -426,18 +428,25 @@ static ssize_t hwmon_attr_show(struct device *dev, struct device_attribute *devattr, char *buf) { struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr); + struct hwmon_device *hwdev = to_hwmon_device(dev); + s64 val64; long val; int ret; + guard(mutex)(&hwdev->lock); + ret = hattr->ops->read(dev, hattr->type, hattr->attr, hattr->index, - &val); + (hattr->type == hwmon_energy64) ? (long *)&val64 : &val); if (ret < 0) return ret; + if (hattr->type != hwmon_energy64) + val64 = val; + trace_hwmon_attr_show(hattr->index + hwmon_attr_base(hattr->type), - hattr->name, val); + hattr->name, val64); - return sprintf(buf, "%ld\n", val); + return sprintf(buf, "%lld\n", val64); } static ssize_t hwmon_attr_show_string(struct device *dev, @@ -445,10 +454,13 @@ static ssize_t hwmon_attr_show_string(struct device *dev, char *buf) { struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr); + struct hwmon_device *hwdev = to_hwmon_device(dev); enum hwmon_sensor_types type = hattr->type; const char *s; int ret; + guard(mutex)(&hwdev->lock); + ret = hattr->ops->read_string(dev, hattr->type, hattr->attr, hattr->index, &s); if (ret < 0) @@ -465,6 +477,7 @@ static ssize_t hwmon_attr_store(struct device *dev, const char *buf, size_t count) { struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr); + struct hwmon_device *hwdev = to_hwmon_device(dev); long val; int ret; @@ -472,13 +485,15 @@ static ssize_t hwmon_attr_store(struct device *dev, if (ret < 0) return ret; + guard(mutex)(&hwdev->lock); + ret = hattr->ops->write(dev, hattr->type, hattr->attr, hattr->index, val); if (ret < 0) return ret; trace_hwmon_attr_store(hattr->index + hwmon_attr_base(hattr->type), - hattr->name, val); + hattr->name, (s64)val); return count; } @@ -734,6 +749,7 @@ static const char * const *__templates[] = { [hwmon_curr] = hwmon_curr_attr_templates, [hwmon_power] = hwmon_power_attr_templates, [hwmon_energy] = hwmon_energy_attr_templates, + [hwmon_energy64] = hwmon_energy_attr_templates, [hwmon_humidity] = hwmon_humidity_attr_templates, [hwmon_fan] = hwmon_fan_attr_templates, [hwmon_pwm] = hwmon_pwm_attr_templates, @@ -747,6 +763,7 @@ static const int __templates_size[] = { [hwmon_curr] = ARRAY_SIZE(hwmon_curr_attr_templates), [hwmon_power] = ARRAY_SIZE(hwmon_power_attr_templates), [hwmon_energy] = ARRAY_SIZE(hwmon_energy_attr_templates), + [hwmon_energy64] = ARRAY_SIZE(hwmon_energy_attr_templates), [hwmon_humidity] = ARRAY_SIZE(hwmon_humidity_attr_templates), [hwmon_fan] = ARRAY_SIZE(hwmon_fan_attr_templates), [hwmon_pwm] = ARRAY_SIZE(hwmon_pwm_attr_templates), @@ -785,6 +802,22 @@ int hwmon_notify_event(struct device *dev, enum hwmon_sensor_types type, } EXPORT_SYMBOL_GPL(hwmon_notify_event); +void hwmon_lock(struct device *dev) +{ + struct hwmon_device *hwdev = to_hwmon_device(dev); + + mutex_lock(&hwdev->lock); +} +EXPORT_SYMBOL_GPL(hwmon_lock); + +void hwmon_unlock(struct device *dev) +{ + struct hwmon_device *hwdev = to_hwmon_device(dev); + + mutex_unlock(&hwdev->lock); +} +EXPORT_SYMBOL_GPL(hwmon_unlock); + static int hwmon_num_channel_attrs(const struct hwmon_channel_info *info) { int i, n; @@ -945,6 +978,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, tdev = tdev->parent; hdev->of_node = tdev ? tdev->of_node : NULL; hwdev->chip = chip; + mutex_init(&hwdev->lock); dev_set_drvdata(hdev, drvdata); dev_set_name(hdev, HWMON_ID_FORMAT, id); err = device_register(hdev); |