Add driver support for ESWIN EIC7700 PVT controller
Subsystems (2)
v5 cover Add driver support for ESWIN EIC7700 PVT controller
From: Huan He <[email protected]>
Add support for the ESWIN EIC7700 PVT (Voltage, Temperature) sensor
Features:
The driver supports monitoring of voltage and temperature parameters through the hardware monitoring subsystem. It provides an access to the sampled Temperature and Voltage.
Test:
Tested this patch on the SiFive HiFive Premier P550 (which uses the ESWIN EIC7700 SoC).
Updates:
Changes in v5:
- Update eswin,eic7700-pvt.yaml
- Drop the label enum constraint and remove label from the required list
- Add '#thermal-sensor-cells' to the required list
- Rename the example node to the generic sensor@... form
- Update the binding description to describe one temperature sensor and one voltage sensor
- Update eic7700-pvt.c
- Register the hwmon device with the fixed name "pvt"
- Remove label-based instance identification from the driver
- Fix CONFIG_PM=n support by keeping the clock enabled when runtime PM is unavailable
- Add pm_runtime_force_suspend() in the cleanup path to avoid leaving the device active during unbind
- Switch system sleep callbacks to pm_runtime_force_suspend() and pm_runtime_force_resume()
- Guard ISR register accesses with pm_runtime_get_if_active()
- Add synchronize_irq() on the timeout path to avoid stale completion races
- Remove temp_offset support because the raw trim register does not match the hwmon ABI
- Align the commit message with the implementation (one temperature sensor, one voltage sensor)
Changes in v4:
- Update eswin,eic7700-pvt.yaml
- Delete reviewed-by tag of Conor Dooley, because the label enum constraint is introduced
- Update eic7700-pvt.c and eic7700-pvt.h
- Remove the unused LVT/ULVT/SVT process-monitoring channels
- Remove the probe-time power check since the PVT block is always powered on EIC7700 and the extra verification is unnecessary
- Stop requesting the interrupt as shared and use the dedicated PVT IRQ only
- Reorder probe initialization so the interface is initialized before the clock is disabled, avoiding register accesses with the clock gated
- Fix runtime PM reference handling on error paths by balancing pm_runtime_get_noresume() with pm_runtime_put_noidle()
- Add pm_runtime_put_noidle() handling for failed pm_runtime_get_sync() calls in hwmon read/write paths
- Switch the PM callback registration from pm_sleep_ptr() to pm_ptr()
Changes in v3:
- Update eswin,eic7700-pvt.yaml
- Remove redundant label property description and use 'label: true' to reference the definition in hwmon-common.yaml
- Replace 'additionalProperties: false' with 'unevaluatedProperties: false'
- Remove the description for '#thermal-sensor-cells'
- Update eic7700-pvt.c and eic7700-pvt.h
- Fix clock reference count imbalance with Runtime PM:
Replace devm_clk_get_enabled() with devm_clk_get() and manually manage clock enable/disable to avoid double-disable in remove() when Runtime PM is active. Clock is now enabled only during probe for eic7700_pvt_check_pwr(), then disabled before enabling Runtime PM, which takes full control of the clock thereafter
- Add detailed comment explaining the spurious interrupt risk in eic7700_pvt_check_pwr()
- Replace wait_for_completion_interruptible() with wait_for_completion_timeout() to prevent infinite wait
Changes in v2:
- Update eswin,eic7700-pvt.yaml
- Reference the hwmon-common.yaml file
- Remove the clock-names and reset-names properties
- Move additionalProperties: false after the required block
- Remove one example node to avoid redundancy
- Update eic7700-pvt.c and eic7700-pvt.h
- Remove unused sensor macros (PVT_SENSOR_FIRST, PVT_SENSOR_LAST, PVT_SENSORS_NUM)
- Drop the unnecessary hwmon-sysfs.h header
- Replace dynamic sensor info allocation with a static array and unify sensor labels
- Remove unused hwmon_temp_type attribute
- Eliminate redundant validation checks
- Remove mutex and related locking, relying on hwmon core serialization
- Replace per-sensor caches and completions with a single data cache and completion object
- Remove pvt->sensor tracking. ISR no longer depends on the currently selected sensor
- Move devm_add_action() registration after init_completion() for safer cleanup, and update cleanup function (pvt_clear_data)
- Replace devm_reset_control_get_optional_exclusive() with devm_reset_control_get_exclusive_deasserted()
- Replace eic7700_pvt_remove() with eic7700_pvt_disable_pm_runtime() and move it after PM runtime enable to avoid resource leaks on probe failure and remove clock disable and reset assert from eic7700_pvt_disable_pm_runtime() as it is already handled by devm_* framework
- Remove redundant clock presence check in runtime_resume
- Link to v1: https://lore.kernel.org/all/[email protected]/
Huan He (2):
dt-bindings: hwmon: Add Eswin EIC7700 PVT sensor
hwmon: Add Eswin EIC7700 PVT sensor driver
.../bindings/hwmon/eswin,eic7700-pvt.yaml | 63 +++ drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 + drivers/hwmon/eic7700-pvt.c | 506 ++++++++++++++++++ drivers/hwmon/eic7700-pvt.h | 99 ++++ 5 files changed, 681 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/eswin,eic7700-pvt.yaml create mode 100644 drivers/hwmon/eic7700-pvt.c create mode 100644 drivers/hwmon/eic7700-pvt.h
Signature · 1 line
2.25.1
PATCH v5 1/2 dt-bindings: hwmon: Add Eswin EIC7700 PVT sensor
From: Huan He <[email protected]>
Add device tree binding documentation for ESWIN EIC7700 Voltage and Temperature sensor.
The EIC7700 SoC integrates two PVT instances for monitoring SoC and DDR power domains respectively.
--- .../bindings/hwmon/eswin,eic7700-pvt.yaml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/eswin,eic7700-pvt.yaml
Documentation/devicetree/bindings/hwmon/eswin,eic7700-pvt.yaml new file +63 -0
@@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/eswin,eic7700-pvt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ESWIN EIC7700 PVT Sensor + +maintainers: + - Yulin Lu <[email protected]> + - Huan He <[email protected]> + +description: + ESWIN EIC7700 SoC integrates embedded voltage and temperature sensors to + monitor the internal SoC environment. The system includes two PVT sensor + instances. The PVT0 monitors the main SoC power domain. The PVT1 sensor + monitors the DDR core power domain. + +allOf: + - $ref: /schemas/hwmon/hwmon-common.yaml# + +properties: + compatible: + const: eswin,eic7700-pvt + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + '#thermal-sensor-cells': + const: 0 + +required: + - compatible + - reg + - clocks + - interrupts + - resets + - '#thermal-sensor-cells' + +unevaluatedProperties: false + +examples: + - | + sensor@50b00000 { + compatible = "eswin,eic7700-pvt"; + reg = <0x50b00000 0x10000>; + clocks = <&clocks 244>; + interrupts = <349>; + interrupt-parent = <&plic>; + label = "pvt0"; + resets = <&reset 111>; + #thermal-sensor-cells = <0>; + }; +...
Signature · 1 line
2.25.1
Re: [PATCH v5 1/2] dt-bindings: hwmon: Add Eswin EIC7700 PVT sensor
Quoted 8 lines · On Fri, May 15, 2026 at 05:20:56PM +0800, [email protected] wrote:
From: Huan He <[email protected]>
Add device tree binding documentation for ESWIN EIC7700 Voltage and Temperature sensor.
The EIC7700 SoC integrates two PVT instances for monitoring SoC and DDR power domains respectively.
Quoted 6 lines
Signed-off-by Yulin Lu <[email protected]>Signed-off-by Huan He <[email protected]>--- .../bindings/hwmon/eswin,eic7700-pvt.yaml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/eswin,eic7700-pvt.yaml
Best regards,
Krzysztof
PATCH v5 2/2 hwmon: Add Eswin EIC7700 PVT sensor driver
In reply to [email protected]From: Huan He <[email protected]>
Add support for ESWIN EIC7700 Voltage and Temperature sensor. The driver supports temperature and voltage monitoring with polynomial conversion, and provides sysfs interface for sensor data access.
The PVT IP contains one temperature sensor and one voltage sensors.
--- drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 + drivers/hwmon/eic7700-pvt.c | 506 ++++++++++++++++++++++++++++++++++++ drivers/hwmon/eic7700-pvt.h | 99 +++++++ 4 files changed, 618 insertions(+) create mode 100644 drivers/hwmon/eic7700-pvt.c create mode 100644 drivers/hwmon/eic7700-pvt.h
drivers/hwmon/Kconfig +12 -0
@@ -2033,6 +2033,18 @@ config SENSORS_DME1737 This driver can also be built as a module. If so, the module will be called dme1737. +config SENSORS_EIC7700_PVT + tristate "Eswin EIC7700 Voltage, Temperature sensor driver" + depends on ARCH_ESWIN || COMPILE_TEST + depends on HWMON + select POLYNOMIAL + help + If you say yes here you get support for Eswin EIC7700 PVT sensor + embedded into the SoC. + + This driver can also be built as a module. If so, the module will be + called eic7700-pvt. + config SENSORS_EMC1403 tristate "SMSC EMC1403/23 thermal sensor" depends on I2C
drivers/hwmon/Makefile +1 -0
@@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o obj-$(CONFIG_SENSORS_DS620) += ds620.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o +obj-$(CONFIG_SENSORS_EIC7700_PVT) += eic7700-pvt.o obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o obj-$(CONFIG_SENSORS_EMC2305) += emc2305.o
drivers/hwmon/eic7700-pvt.c new file +506 -0
506 lines not on this page · raw message
drivers/hwmon/eic7700-pvt.h new file +99 -0
99 lines not on this page · raw message
Signature · 1 line
2.25.1
[email protected]
AI reviewRe: [PATCH v5 2/2] hwmon: Add Eswin EIC7700 PVT sensor driver
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider: - [Critical] The timeout calculation for sensor conversion evaluates to 0 jiffies, causing all reads to…
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] The timeout calculation for sensor conversion evaluates to 0 jiffies, causing all reads to instantly fail.
- [High] Missing pm_runtime_disable() in the devres cleanup path leads to an unbalanced disable_depth.
- [High] Clock leakage on the IRQ request error path when CONFIG_PM is disabled.
- [High] Race condition between ISR and main thread leaks PM runtime active state.
- [High] Incorrect initialization order causes an IRQ storm during probe if an interrupt fires early.
- [High] Lack of internal locking in eic7700_pvt_hwmon_read allows concurrent hardware state corruption.
- [Medium] Useless and incorrectly ordered devres action for unblocking sysfs readers.
--
commit fe78922d5101b3a07ca5ea0fbd0fd5e9cba0dcc9
Author: Huan He <[email protected]>
hwmon: Add Eswin EIC7700 PVT sensor driver
Add support for ESWIN EIC7700 Voltage and Temperature sensor. The driver supports temperature and voltage monitoring with polynomial conversion, and provides sysfs interface for sensor data access.
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +0
-0
[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static irqreturn_t eic7700_pvt_hard_isr (int irq,void *data) +{
[ ... ]
drivers/hwmon/eic7700-pvt.c line 135
Quoted 9 lines
drivers/hwmon/eic7700-pvt.c new file +9
-0+ val =readl (pvt->regs +PVT_DATA ); +WRITE_ONCE (pvt->data_cache,FIELD_GET (PVT_DATA_OUT , val)); +complete (&pvt->conversion); + +if (IS_ENABLED (CONFIG_PM )) +pm_runtime_put_noidle (pvt->dev); + +return IRQ_HANDLED ; +}
If the main thread in eic7700_pvt_hwmon_read() drops the usage count from 2 to 1 before the ISR drops it from 1 to 0, will both threads fail to trigger the idle callback?
This could leave the device indefinitely in the active state. Should the ISR use pm_runtime_put_autosuspend() or pm_runtime_put() instead of pm_runtime_put_noidle()?
[ ... ]
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +4
-0+static int eic7700_pvt_read_data (struct pvt_hwmon *pvt, +enum pvt_sensor_type type,long *val) +{ +unsigned long timeout;
[ ... ]
drivers/hwmon/eic7700-pvt.c line 162
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ timeout =2 *usecs_to_jiffies (ktime_to_us (pvt->timeout)); + ret =wait_for_completion_timeout (&pvt->conversion, timeout);
Because pvt->timeout is 333 microseconds, will usecs_to_jiffies(333) evaluate to 0 on standard kernel configurations like HZ=1000?
If so, this acts as a non-blocking check and wait_for_completion_timeout() could instantly return 0, causing all reads to permanently fail with -ETIMEDOUT.
[ ... ]
drivers/hwmon/eic7700-pvt.c line 220
Quoted 5 lines
drivers/hwmon/eic7700-pvt.c new file +5
-0+static int eic7700_pvt_hwmon_read (struct device *dev, +enum hwmon_sensor_types type,u32 attr, +int ch,long *val) +{ +struct pvt_hwmon *pvt =dev_get_drvdata (dev);
The driver registers the temperature sensor with the thermal subsystem via the HWMON_C_REGISTER_TZ flag.
If thermal zone background polling directly invokes this read callback while a user concurrently reads a hwmon sysfs attribute, is there a race condition? Does this need an internal mutex to prevent concurrent hardware state corruption?
[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static struct pvt_hwmon *eic7700_pvt_create_data (struct platform_device *pdev) +{
[ ... ]
drivers/hwmon/eic7700-pvt.c line 310
Quoted 1 line
drivers/hwmon/eic7700-pvt.c new file +1
-0+ ret =devm_add_action (dev, pvt_clear_data, pvt);
Because devres actions execute in reverse order of registration (LIFO), will this action run after the hwmon device is unregistered?
Since hwmon unregistration blocks until all active sysfs read operations finish, the reader would have already completed before pvt_clear_data runs, which might make it ineffective for unblocking sysfs readers.
[ ... ]
drivers/hwmon/eic7700-pvt.c line 387
Quoted 10 lines
drivers/hwmon/eic7700-pvt.c new file +10
-0+static void eic7700_pvt_disable_pm_runtime (void *data) +{ +struct pvt_hwmon *pvt = data; + +pm_runtime_dont_use_autosuspend (pvt->dev); +pm_runtime_force_suspend (pvt->dev); + +if (!IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); +}
Should this custom devres cleanup action call pm_runtime_disable()?
If the module is unloaded and then re-probed, could the unbalanced disable_depth cause an "Unbalanced pm_runtime_enable!" warning and corrupt the power management state?
Quoted 3 lines
drivers/hwmon/eic7700-pvt.c new file +3
-0+ +static int eic7700_pvt_probe (struct platform_device *pdev) +{
[ ... ]
drivers/hwmon/eic7700-pvt.c line 430
Quoted 6 lines
drivers/hwmon/eic7700-pvt.c new file +6
-0+if (IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); + + ret =eic7700_pvt_request_irq (pvt); +if (ret) +return ret;
If CONFIG_PM is disabled, the clock remains enabled. If eic7700_pvt_request_irq() fails here, does the function return without disabling the clock? This could permanently leak the clock reference because the devres cleanup action is not yet registered.
drivers/hwmon/eic7700-pvt.c line 432
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ +pm_runtime_enable (&pdev->dev);
Since the IRQ is unmasked before pm_runtime_enable() is called, what happens if the hardware asserts an interrupt in this window?
If eic7700_pvt_hard_isr() fires, pm_runtime_get_if_active() would return -EINVAL and the handler would return IRQ_NONE without clearing the interrupt. Since the interrupt is level-triggered (IRQF_TRIGGER_HIGH), could this cause an infinite IRQ storm that locks up the CPU?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Guenter Roeck
maintainerRe: [PATCH v5 2/2] hwmon: Add Eswin EIC7700 PVT sensor driver
Quoted 71 lines · On 5/15/26 03:03, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] The timeout calculation for sensor conversion evaluates to 0 jiffies, causing all reads to instantly fail.
- [High] Missingpm_runtime_disable()in the devres cleanup path leads to an unbalanceddisable_depth.
- [High] Clock leakage on the IRQ request error path whenCONFIG_PMis disabled.
- [High] Race condition between ISR and main thread leaks PM runtime active state.
- [High] Incorrect initialization order causes an IRQ storm during probe if an interrupt fires early.
- [High] Lack of internal locking ineic7700_pvt_hwmon_readallows concurrent hardware state corruption.
- [Medium] Useless and incorrectly ordered devres action for unblocking sysfs readers.
--commit
fe78922d5101b3a07ca5ea0fbd0fd5e9cba0dcc9
Author: Huan He <[email protected]>hwmon: Add Eswin EIC7700 PVT sensor driver
Add support for ESWIN EIC7700 Voltage and Temperature sensor. The driver supports temperature and voltage monitoring with polynomial conversion, and provides sysfs interface for sensor data access.
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +0
-0[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static irqreturn_t eic7700_pvt_hard_isr (int irq,void *data) +{[ ... ]
drivers/hwmon/eic7700-pvt.c line 135
Quoted 9 lines
drivers/hwmon/eic7700-pvt.c new file +9
-0+ val =readl (pvt->regs +PVT_DATA ); +WRITE_ONCE (pvt->data_cache,FIELD_GET (PVT_DATA_OUT , val)); +complete (&pvt->conversion); + +if (IS_ENABLED (CONFIG_PM )) +pm_runtime_put_noidle (pvt->dev); + +return IRQ_HANDLED ; +}If the main thread in
eic7700_pvt_hwmon_read()drops the usage count from 2 to 1 before the ISR drops it from 1 to 0, will both threads fail to trigger the idle callback?This could leave the device indefinitely in the active state. Should the ISR use
pm_runtime_put_autosuspend()orpm_runtime_put()instead ofpm_runtime_put_noidle()?[ ... ]
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +4
-0+static int eic7700_pvt_read_data (struct pvt_hwmon *pvt, +enum pvt_sensor_type type,long *val) +{ +unsigned long timeout;[ ... ]
drivers/hwmon/eic7700-pvt.c line 162
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ timeout =2 *usecs_to_jiffies (ktime_to_us (pvt->timeout)); + ret =wait_for_completion_timeout (&pvt->conversion, timeout);Because
pvt->timeoutis 333 microseconds, willusecs_to_jiffies(333)evaluate to 0 on standard kernel configurations like HZ=1000?If so, this acts as a non-blocking check and
wait_for_completion_timeout()could instantly return 0, causing all reads to permanently fail with-ETIMEDOUT.[ ... ]
drivers/hwmon/eic7700-pvt.c line 220
Quoted 5 lines
drivers/hwmon/eic7700-pvt.c new file +5
-0+static int eic7700_pvt_hwmon_read (struct device *dev, +enum hwmon_sensor_types type,u32 attr, +int ch,long *val) +{ +struct pvt_hwmon *pvt =dev_get_drvdata (dev);The driver registers the temperature sensor with the thermal subsystem via the
HWMON_C_REGISTER_TZflag.
Quoted 5 lines
If thermal zone background polling directly invokes this read callback while a user concurrently reads a hwmon sysfs attribute, is there a race condition? Does this need an internal mutex to prevent concurrent hardware state corruption?
False positive. Polling is through the hwmon subsystem, which protects such accesses with the hwmon subsystem lock.
The other concerns seem real. Please address.
Thanks,
Guenter
Quoted 58 lines
[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static struct pvt_hwmon *eic7700_pvt_create_data (struct platform_device *pdev) +{[ ... ]
drivers/hwmon/eic7700-pvt.c line 310
Quoted 1 line
drivers/hwmon/eic7700-pvt.c new file +1
-0+ ret =devm_add_action (dev, pvt_clear_data, pvt);Because devres actions execute in reverse order of registration (LIFO), will this action run after the hwmon device is unregistered?
Since hwmon unregistration blocks until all active sysfs read operations finish, the reader would have already completed before
pvt_clear_dataruns, which might make it ineffective for unblocking sysfs readers.[ ... ]
drivers/hwmon/eic7700-pvt.c line 387
Quoted 10 lines
drivers/hwmon/eic7700-pvt.c new file +10
-0+static void eic7700_pvt_disable_pm_runtime (void *data) +{ +struct pvt_hwmon *pvt = data; + +pm_runtime_dont_use_autosuspend (pvt->dev); +pm_runtime_force_suspend (pvt->dev); + +if (!IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); +}Should this custom devres cleanup action call
pm_runtime_disable()?If the module is unloaded and then re-probed, could the unbalanced
disable_depthcause an "Unbalancedpm_runtime_enable!" warning and corrupt the power management state?Quoted 3 lines
drivers/hwmon/eic7700-pvt.c new file +3
-0+ +static int eic7700_pvt_probe (struct platform_device *pdev) +{[ ... ]
drivers/hwmon/eic7700-pvt.c line 430
Quoted 6 lines
drivers/hwmon/eic7700-pvt.c new file +6
-0+if (IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); + + ret =eic7700_pvt_request_irq (pvt); +if (ret) +return ret;If
CONFIG_PMis disabled, the clock remains enabled. Ifeic7700_pvt_request_irq()fails here, does the function return without disabling the clock? This could permanently leak the clock reference because the devres cleanup action is not yet registered.drivers/hwmon/eic7700-pvt.c line 432
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ +pm_runtime_enable (&pdev->dev);Since the IRQ is unmasked before
pm_runtime_enable()is called, what happens if the hardware asserts an interrupt in this window?If
eic7700_pvt_hard_isr()fires,pm_runtime_get_if_active()would return-EINVALand the handler would returnIRQ_NONEwithout clearing the interrupt. Since the interrupt is level-triggered (IRQF_TRIGGER_HIGH), could this cause an infinite IRQ storm that locks up the CPU?
Re: Re: [PATCH v5 2/2] hwmon: Add Eswin EIC7700 PVT sensor driver
Hi Sashiko, Guenter,
Thank you very much for your detailed review. We appreciate the feedback.
Quoted 42 lines · On 5/15/26 03:03, [email protected] wrote:
Quoted 41 lines
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] The timeout calculation for sensor conversion evaluates to 0 jiffies, causing all reads to instantly fail.
- [High] Missingpm_runtime_disable()in the devres cleanup path leads to an unbalanceddisable_depth.
- [High] Clock leakage on the IRQ request error path whenCONFIG_PMis disabled.
- [High] Race condition between ISR and main thread leaks PM runtime active state.
- [High] Incorrect initialization order causes an IRQ storm during probe if an interrupt fires early.
- [High] Lack of internal locking ineic7700_pvt_hwmon_readallows concurrent hardware state corruption.
- [Medium] Useless and incorrectly ordered devres action for unblocking sysfs readers.
--commit
fe78922d5101b3a07ca5ea0fbd0fd5e9cba0dcc9
Author: Huan He <[email protected]>hwmon: Add Eswin EIC7700 PVT sensor driver
Add support for ESWIN EIC7700 Voltage and Temperature sensor. The driver supports temperature and voltage monitoring with polynomial conversion, and provides sysfs interface for sensor data access.
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +0
-0[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static irqreturn_t eic7700_pvt_hard_isr (int irq,void *data) +{[ ... ]
drivers/hwmon/eic7700-pvt.c line 135
Quoted 9 lines
drivers/hwmon/eic7700-pvt.c new file +9
-0+ val =readl (pvt->regs +PVT_DATA ); +WRITE_ONCE (pvt->data_cache,FIELD_GET (PVT_DATA_OUT , val)); +complete (&pvt->conversion); + +if (IS_ENABLED (CONFIG_PM )) +pm_runtime_put_noidle (pvt->dev); + +return IRQ_HANDLED ; +}If the main thread in
eic7700_pvt_hwmon_read()drops the usage count from 2 to 1 before the ISR drops it from 1 to 0, will both threads fail to trigger the idle callback?
Quoted 3 lines
Quoted 3 lines
This could leave the device indefinitely in the active state. Should the ISR use
pm_runtime_put_autosuspend()orpm_runtime_put()instead ofpm_runtime_put_noidle()?
I will fix this by replacing pm_runtime_put_noidle() in the ISR with pm_runtime_put(), so the final reference drop can still trigger runtime PM idle handling.
The ISR will be changed along these lines:
complete(&pvt->conversion);
if (IS_ENABLED(CONFIG_PM))
- pm_runtime_put_noidle(pvt->dev);
+ pm_runtime_put(pvt->dev);
Quoted 13 lines
Quoted 13 lines
[ ... ]
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +4
-0+static int eic7700_pvt_read_data (struct pvt_hwmon *pvt, +enum pvt_sensor_type type,long *val) +{ +unsigned long timeout;[ ... ]
drivers/hwmon/eic7700-pvt.c line 162
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ timeout =2 *usecs_to_jiffies (ktime_to_us (pvt->timeout)); + ret =wait_for_completion_timeout (&pvt->conversion, timeout);Because
pvt->timeoutis 333 microseconds, willusecs_to_jiffies(333)evaluate to 0 on standard kernel configurations like HZ=1000?
Quoted 3 lines
Quoted 3 lines
If so, this acts as a non-blocking check and
wait_for_completion_timeout()could instantly return 0, causing all reads to permanently fail with-ETIMEDOUT.
This looks like a false positive.
usecs_to_jiffies() eventually goes through _usecs_to_jiffies(), which rounds up instead of truncating to zero:
static inline unsigned long _usecs_to_jiffies(const unsigned int u) {
return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ); }
So with HZ=1000:
usecs_to_jiffies(333) = (333 + 1000 - 1) / 1000 = 1
Therefore for pvt->timeout = 333 us, the timeout does not collapse to 0 jiffies. The current code evaluates to 2 jiffies, so wait_for_completion_timeout() remains blocking rather than becoming a non-blocking check.
Quoted 17 lines
Quoted 11 lines
[ ... ]
drivers/hwmon/eic7700-pvt.c line 220
Quoted 5 lines
drivers/hwmon/eic7700-pvt.c new file +5
-0+static int eic7700_pvt_hwmon_read (struct device *dev, +enum hwmon_sensor_types type,u32 attr, +int ch,long *val) +{ +struct pvt_hwmon *pvt =dev_get_drvdata (dev);The driver registers the temperature sensor with the thermal subsystem via the
HWMON_C_REGISTER_TZflag.Quoted 5 lines
If thermal zone background polling directly invokes this read callback while a user concurrently reads a hwmon sysfs attribute, is there a race condition? Does this need an internal mutex to prevent concurrent hardware state corruption?
Quoted 21 lines
False positive. Polling is through the hwmon subsystem, which protects such accesses with the hwmon subsystem lock.
The other concerns seem real. Please address.
Thanks,
GuenterQuoted 12 lines
[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static struct pvt_hwmon *eic7700_pvt_create_data (struct platform_device *pdev) +{[ ... ]
drivers/hwmon/eic7700-pvt.c line 310
Quoted 1 line
drivers/hwmon/eic7700-pvt.c new file +1
-0+ ret =devm_add_action (dev, pvt_clear_data, pvt);Because devres actions execute in reverse order of registration (LIFO), will this action run after the hwmon device is unregistered?
Since hwmon unregistration blocks until all active sysfs read operations finish, the reader would have already completed before
pvt_clear_dataruns, which might make it ineffective for unblocking sysfs readers.
I will remove pvt_clear_data() and the associated devm_add_action() call.
Quoted 15 lines
Quoted 15 lines
[ ... ]
drivers/hwmon/eic7700-pvt.c line 387
Quoted 10 lines
drivers/hwmon/eic7700-pvt.c new file +10
-0+static void eic7700_pvt_disable_pm_runtime (void *data) +{ +struct pvt_hwmon *pvt = data; + +pm_runtime_dont_use_autosuspend (pvt->dev); +pm_runtime_force_suspend (pvt->dev); + +if (!IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); +}Should this custom devres cleanup action call
pm_runtime_disable()?
Quoted 3 lines
Quoted 3 lines
If the module is unloaded and then re-probed, could the unbalanced
disable_depthcause an "Unbalancedpm_runtime_enable!" warning and corrupt the power management state?
This looks like a false positive.
The cleanup path already calls pm_runtime_force_suspend(), and pm_runtime_force_suspend() itself invokes pm_runtime_disable() in the PM core.
Adding another explicit pm_runtime_disable() after pm_runtime_force_suspend() would over-increment disable_depth and break the reprobe path.
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +3
-0+ +static int eic7700_pvt_probe (struct platform_device *pdev) +{[ ... ]
Quoted 11 lines
Quoted 11 lines
drivers/hwmon/eic7700-pvt.c line 430
Quoted 6 lines
drivers/hwmon/eic7700-pvt.c new file +6
-0+if (IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); + + ret =eic7700_pvt_request_irq (pvt); +if (ret) +return ret;If
CONFIG_PMis disabled, the clock remains enabled. Ifeic7700_pvt_request_irq()fails here, does the function return without disabling the clock? This could permanently leak the clock reference because the devres cleanup action is not yet registered.
This concern is valid.
When CONFIG_PM is disabled, the clock remains enabled after probe-time initialization. If eic7700_pvt_request_irq() fails before the devres PM cleanup action is registered, the clock can indeed be leaked.
I will fix this by explicitly disabling the clock on the IRQ request error path when CONFIG_PM is disabled.
The probe will be changed along these lines:
ret = eic7700_pvt_request_irq(pvt);
- if (ret)
+ if (ret) {
+ if (!IS_ENABLED(CONFIG_PM))
+ clk_disable_unprepare(pvt->clk);
return ret;
+ }
Quoted 11 lines
Quoted 11 lines
drivers/hwmon/eic7700-pvt.c line 432
Quoted 3 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ +pm_runtime_enable (&pdev->dev);Since the IRQ is unmasked before
pm_runtime_enable()is called, what happens if the hardware asserts an interrupt in this window?If
eic7700_pvt_hard_isr()fires,pm_runtime_get_if_active()would return-EINVALand the handler would returnIRQ_NONEwithout clearing the interrupt. Since the interrupt is level-triggered (IRQF_TRIGGER_HIGH), could this cause an infinite IRQ storm that locks up the CPU?
My understanding is that eic7700_pvt_init_iface() already clears the interrupt status and disables PVT_ENA_EN before the IRQ is requested, so no new interrupt is expected in the request_irq() -> pm_runtime_enable() window.
Given that, do you think an additional change is still needed here?
Best regards,
Huan He
Re: Re: Re: [PATCH v5 2/2] hwmon: Add Eswin EIC7700 PVT sensor driver
Hi Guenter, Sashiko,
Gentle ping on this.
I am preparing the next revision and would like to confirm whether the remaining interrupt-ordering concern still needs a code change.
My understanding is that eic7700_pvt_init_iface() clears the interrupt status and disables PVT_ENA_EN before the IRQ is requested, so no new interrupt is expected in the request_irq() -> pm_runtime_enable() window.
I plan to address the confirmed issues in the next revision, including:
- replacing pm_runtime_put_noidle() in the ISR with pm_runtime_put()
- removing pvt_clear_data() and the related devm_add_action()
- disabling the clock on the IRQ request error path when !CONFIG_PM
Could you please let me know whether you still expect an additional change for this part?
Thanks for your time and review.
Best regards,
Huan He
Quoted 222 lines
Hi Sashiko, Guenter,
Thank you very much for your detailed review. We appreciate the feedback.
Quoted 42 lines · On 5/15/26 03:03, [email protected] wrote:
Quoted 41 lines
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] The timeout calculation for sensor conversion evaluates to 0 jiffies, causing all reads to instantly fail.
- [High] Missingpm_runtime_disable()in the devres cleanup path leads to an unbalanceddisable_depth.
- [High] Clock leakage on the IRQ request error path whenCONFIG_PMis disabled.
- [High] Race condition between ISR and main thread leaks PM runtime active state.
- [High] Incorrect initialization order causes an IRQ storm during probe if an interrupt fires early.
- [High] Lack of internal locking ineic7700_pvt_hwmon_readallows concurrent hardware state corruption.
- [Medium] Useless and incorrectly ordered devres action for unblocking sysfs readers.
--commit
fe78922d5101b3a07ca5ea0fbd0fd5e9cba0dcc9
Author: Huan He <[email protected]>hwmon: Add Eswin EIC7700 PVT sensor driver
Add support for ESWIN EIC7700 Voltage and Temperature sensor. The driver supports temperature and voltage monitoring with polynomial conversion, and provides sysfs interface for sensor data access.
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +0
-0[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static irqreturn_t eic7700_pvt_hard_isr (int irq,void *data) +{[ ... ]
drivers/hwmon/eic7700-pvt.c line 135
Quoted 9 lines
drivers/hwmon/eic7700-pvt.c new file +9
-0+ val =readl (pvt->regs +PVT_DATA ); +WRITE_ONCE (pvt->data_cache,FIELD_GET (PVT_DATA_OUT , val)); +complete (&pvt->conversion); + +if (IS_ENABLED (CONFIG_PM )) +pm_runtime_put_noidle (pvt->dev); + +return IRQ_HANDLED ; +}If the main thread in
eic7700_pvt_hwmon_read()drops the usage count from 2 to 1 before the ISR drops it from 1 to 0, will both threads fail to trigger the idle callback?Quoted 3 lines
Quoted 3 lines
This could leave the device indefinitely in the active state. Should the ISR use
pm_runtime_put_autosuspend()orpm_runtime_put()instead ofpm_runtime_put_noidle()?I will fix this by replacing
pm_runtime_put_noidle()in the ISR withpm_runtime_put(), so the final reference drop can still trigger runtime PM idle handling.The ISR will be changed along these lines:
complete(&pvt->conversion);if (
IS_ENABLED(CONFIG_PM))
-pm_runtime_put_noidle(pvt->dev);
+pm_runtime_put(pvt->dev);Quoted 13 lines
Quoted 13 lines
[ ... ]
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +4
-0+static int eic7700_pvt_read_data (struct pvt_hwmon *pvt, +enum pvt_sensor_type type,long *val) +{ +unsigned long timeout;[ ... ]
drivers/hwmon/eic7700-pvt.c line 162
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ timeout =2 *usecs_to_jiffies (ktime_to_us (pvt->timeout)); + ret =wait_for_completion_timeout (&pvt->conversion, timeout);Because
pvt->timeoutis 333 microseconds, willusecs_to_jiffies(333)evaluate to 0 on standard kernel configurations like HZ=1000?Quoted 3 lines
Quoted 3 lines
If so, this acts as a non-blocking check and
wait_for_completion_timeout()could instantly return 0, causing all reads to permanently fail with-ETIMEDOUT.This looks like a false positive.
usecs_to_jiffies()eventually goes through_usecs_to_jiffies(), which rounds up instead of truncating to zero:static inline unsigned long
_usecs_to_jiffies(const unsigned int u){
return (u + (USEC_PER_SEC/ HZ) - 1) / (USEC_PER_SEC/ HZ); }So with HZ=1000:
usecs_to_jiffies(333)= (333 + 1000 - 1) / 1000 = 1Therefore for
pvt->timeout= 333 us, the timeout does not collapse to 0 jiffies. The current code evaluates to 2 jiffies, sowait_for_completion_timeout()remains blocking rather than becoming a non-blocking check.Quoted 17 lines
Quoted 11 lines
[ ... ]
drivers/hwmon/eic7700-pvt.c line 220
Quoted 5 lines
drivers/hwmon/eic7700-pvt.c new file +5
-0+static int eic7700_pvt_hwmon_read (struct device *dev, +enum hwmon_sensor_types type,u32 attr, +int ch,long *val) +{ +struct pvt_hwmon *pvt =dev_get_drvdata (dev);The driver registers the temperature sensor with the thermal subsystem via the
HWMON_C_REGISTER_TZflag.Quoted 5 lines
If thermal zone background polling directly invokes this read callback while a user concurrently reads a hwmon sysfs attribute, is there a race condition? Does this need an internal mutex to prevent concurrent hardware state corruption?
Quoted 21 lines
False positive. Polling is through the hwmon subsystem, which protects such accesses with the hwmon subsystem lock.
The other concerns seem real. Please address.
Thanks,
GuenterQuoted 12 lines
[ ... ]
Quoted 2 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+static struct pvt_hwmon *eic7700_pvt_create_data (struct platform_device *pdev) +{[ ... ]
drivers/hwmon/eic7700-pvt.c line 310
Quoted 1 line
drivers/hwmon/eic7700-pvt.c new file +1
-0+ ret =devm_add_action (dev, pvt_clear_data, pvt);Because devres actions execute in reverse order of registration (LIFO), will this action run after the hwmon device is unregistered?
Since hwmon unregistration blocks until all active sysfs read operations finish, the reader would have already completed before
pvt_clear_dataruns, which might make it ineffective for unblocking sysfs readers.I will remove
pvt_clear_data()and the associateddevm_add_action()call.Quoted 15 lines
Quoted 15 lines
[ ... ]
drivers/hwmon/eic7700-pvt.c line 387
Quoted 10 lines
drivers/hwmon/eic7700-pvt.c new file +10
-0+static void eic7700_pvt_disable_pm_runtime (void *data) +{ +struct pvt_hwmon *pvt = data; + +pm_runtime_dont_use_autosuspend (pvt->dev); +pm_runtime_force_suspend (pvt->dev); + +if (!IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); +}Should this custom devres cleanup action call
pm_runtime_disable()?Quoted 3 lines
Quoted 3 lines
If the module is unloaded and then re-probed, could the unbalanced
disable_depthcause an "Unbalancedpm_runtime_enable!" warning and corrupt the power management state?This looks like a false positive.
The cleanup path already calls
pm_runtime_force_suspend(), andpm_runtime_force_suspend()itself invokespm_runtime_disable()in the PM core.
Adding another explicitpm_runtime_disable()afterpm_runtime_force_suspend()would over-incrementdisable_depthand break the reprobe path.Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
drivers/hwmon/eic7700-pvt.c new file +3
-0+ +static int eic7700_pvt_probe (struct platform_device *pdev) +{[ ... ]
Quoted 11 lines
Quoted 11 lines
drivers/hwmon/eic7700-pvt.c line 430
Quoted 6 lines
drivers/hwmon/eic7700-pvt.c new file +6
-0+if (IS_ENABLED (CONFIG_PM )) +clk_disable_unprepare (pvt->clk); + + ret =eic7700_pvt_request_irq (pvt); +if (ret) +return ret;If
CONFIG_PMis disabled, the clock remains enabled. Ifeic7700_pvt_request_irq()fails here, does the function return without disabling the clock? This could permanently leak the clock reference because the devres cleanup action is not yet registered.This concern is valid.
When
CONFIG_PMis disabled, the clock remains enabled after probe-time initialization. Ifeic7700_pvt_request_irq()fails before the devres PM cleanup action is registered, the clock can indeed be leaked.I will fix this by explicitly disabling the clock on the IRQ request error path when
CONFIG_PMis disabled.The probe will be changed along these lines:
ret =
eic7700_pvt_request_irq(pvt);
- if (ret)
+ if (ret) {
+ if (!IS_ENABLED(CONFIG_PM))
+clk_disable_unprepare(pvt->clk);
return ret;
+ }Quoted 11 lines
Quoted 11 lines
drivers/hwmon/eic7700-pvt.c line 432
Quoted 3 lines
drivers/hwmon/eic7700-pvt.c new file +2
-0+ +pm_runtime_enable (&pdev->dev);Since the IRQ is unmasked before
pm_runtime_enable()is called, what happens if the hardware asserts an interrupt in this window?If
eic7700_pvt_hard_isr()fires,pm_runtime_get_if_active()would return-EINVALand the handler would returnIRQ_NONEwithout clearing the interrupt. Since the interrupt is level-triggered (IRQF_TRIGGER_HIGH), could this cause an infinite IRQ storm that locks up the CPU?My understanding is that
eic7700_pvt_init_iface()already clears the interrupt status and disablesPVT_ENA_ENbefore the IRQ is requested, so no new interrupt is expected in therequest_irq()->pm_runtime_enable()window.Given that, do you think an additional change is still needed here?