Skip to contentSkip to conversation

hwmon: add Altera SoC FPGA hardware monitoring support

PATCH Superseded [email protected] 3 participants 9 messages Jul 20

Subsystems (4)

v6 of 8 Superseded Latest is v8 →

lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

v6 cover hwmon: add Altera SoC FPGA hardware monitoring support

From: Tze Yee Ng <[email protected]>

This series adds hardware monitor support for Altera SoC FPGA devices. Temperature and voltage sensors are accessed through the Stratix 10 service layer and Secure Device Manager (SDM).

Patch 1 adds async HWMON SMC support to stratix10-svc and registers the socfpga-hwmon platform device.

Patch 2 adds the socfpga-hwmon driver, documentation, Kconfig, and MAINTAINERS entry.

Changes in v6:
- Rebase on torvalds/master (given “Linux 7.2-rc4”)
- No functional changes in Patch 1 and Patch 2

Changes in v5:
- Rebase on dinguyen/socfpga_svc_fixes_for_v7.2
- Address Sashiko review feedback on socfpga-hwmon (Patch 2):
- Poll async responses until HWMON_TIMEOUT instead of a fixed 3-iteration retry loop (~3 ms), fixing premature timeouts on silicon
- Add MODULE_ALIAS("platform:socfpga-hwmon")
- No functional changes in Patch 1

Changes in v4:
- Address maintainer and review feedback on socfpga-hwmon (Patch 2):
- Register devm_add_action_or_reset() before devm_hwmon_device_register_with_info() to fix devres teardown order
- Remove unreferenced completion and pre-poll wait_for_completion_io_timeout() from async reads; poll directly with a retry loop after async_send()
- No functional changes in Patch 1

Changes in v3:
- Address review feedback on socfpga-hwmon (Patch 2):
- Fix 16-bit Q8.8 temperature sign extension
- Drop unused async callback; pass NULL to stratix10_svc_async_send()
- Document and retain pre-poll wait (RSU pattern; firmware needs time before async_poll())
- Align async poll retry behaviour with RSU
- Use uninterruptible wait_for_completion_timeout() for sync reads
- Handle -EINVAL and -EOPNOTSUPP when falling back to sync mode
- Defer SVC channel cleanup via devm_add_action_or_reset()
- No functional changes in Patch 1

Changes in v2:
- Drop altr,stratix10-hwmon DT binding and intel,stratix10-svc hwmon child property
- Drop Stratix 10 SoCDK DTS hwmon node
- Register socfpga-hwmon from stratix10-svc (RSU-style)
- Replace DT channel parsing with hardcoded Stratix 10 and Agilex tables
- Rename driver/module to socfpga-hwmon (CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON)
- Add Agilex channel support
- Fix SDM value conversion (Q8.8 degrees Celsius and Q16 volts to hwmon millidegrees/millivolts)
- Improve sync-mode error handling via last_err

Previous version:
https://lore.kernel.org/all/[email protected]/

Tze Yee Ng (2):
firmware: stratix10-svc: add async HWMON read commands and register
socfpga-hwmon device
hwmon: add Altera SoC FPGA hardware monitoring driver

 Documentation/hwmon/index.rst                |   1 +
 Documentation/hwmon/socfpga-hwmon.rst        |  34 ++
 MAINTAINERS                                  |   8 +
 drivers/firmware/stratix10-svc.c             |  46 +-
 drivers/hwmon/Kconfig                        |  10 +
 drivers/hwmon/Makefile                       |   1 +
 drivers/hwmon/socfpga-hwmon.c                | 579 +++++++++++++++++++
 include/linux/firmware/intel/stratix10-smc.h |  38 ++
 8 files changed, 714 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/hwmon/socfpga-hwmon.rst
 create mode 100644 drivers/hwmon/socfpga-hwmon.c
Signature · 1 line
2.43.7
author maintainer
#1 lore raw

PATCH v6 1/2 firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device

From: Tze Yee Ng <[email protected]>

Add asynchronous Stratix 10 service layer support for hardware monitor temperature and voltage read commands in stratix10_svc_async_send() and stratix10_svc_async_prepare_response().

Register a socfpga-hwmon platform device from the service layer driver when hardware monitor support is enabled, similar to the RSU device.

---
Changes in v6:
- No functional changes from v5

Changes in v5:
- No functional changes from v4

Changes in v3:
- No functional changes from v2

Changes in v2:
- Extend patch scope beyond async SMC support: register socfpga-hwmon platform device from stratix10-svc when CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON is enabled
- Follow RSU-style registration; RSU probe error handling is unchanged
- Add err_unregister_clients to unregister hwmon and RSU on populate failure
- Unregister hwmon platform device in stratix10-svc remove()

---
 drivers/firmware/stratix10-svc.c             | 46 ++++++++++++++++++--
 include/linux/firmware/intel/stratix10-smc.h | 38 ++++++++++++++++
 2 files changed, 81 insertions(+), 3 deletions(-)
drivers/firmware/stratix10-svc.c +43 -3
index c24ca5823078..fc38afed5b7f 100644
@@ -45,6 +45,7 @@
 
 /* stratix10 service layer clients */
 #define STRATIX10_RSU				"stratix10-rsu"
+#define SOCFPGA_HWMON				"socfpga-hwmon"
 
 /* Maximum number of SDM client IDs. */
 #define MAX_SDM_CLIENT_IDS			16
@@ -104,9 +105,11 @@ struct stratix10_svc_chan;
 /**
  * struct stratix10_svc - svc private data
  * @stratix10_svc_rsu: pointer to stratix10 RSU device
+ * @stratix10_svc_hwmon: pointer to stratix10 HWMON device
  */
 struct stratix10_svc {
 	struct platform_device *stratix10_svc_rsu;
+	struct platform_device *stratix10_svc_hwmon;
 };
 
 /**
@@ -1329,6 +1332,14 @@ int stratix10_svc_async_send(struct stratix10_svc_chan *chan, void *msg,
 		args.a0 = INTEL_SIP_SMC_ASYNC_RSU_NOTIFY;
 		args.a2 = p_msg->arg[0];
 		break;
+	case COMMAND_HWMON_READTEMP:
+		args.a0 = INTEL_SIP_SMC_ASYNC_HWMON_READTEMP;
+		args.a2 = p_msg->arg[0];
+		break;
+	case COMMAND_HWMON_READVOLT:
+		args.a0 = INTEL_SIP_SMC_ASYNC_HWMON_READVOLT;
+		args.a2 = p_msg->arg[0];
+		break;
 	default:
 		dev_err(ctrl->dev, "Invalid command ,%d\n", p_msg->command);
 		ret = -EINVAL;
@@ -1422,6 +1433,10 @@ static int stratix10_svc_async_prepare_response(struct stratix10_svc_chan *chan,
 		 */
 		data->kaddr1 = (void *)&handle->res;
 		break;
+	case COMMAND_HWMON_READTEMP:
+	case COMMAND_HWMON_READVOLT:
+		data->kaddr1 = (void *)&handle->res.a2;
+		break;
 
 	default:
 		dev_alert(ctrl->dev, "Invalid command\n ,%d", p_msg->command);
@@ -2013,16 +2028,38 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_put_device;
 
+	if (IS_ENABLED(CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON)) {
+		svc->stratix10_svc_hwmon =
+			platform_device_alloc(SOCFPGA_HWMON, 0);
+		if (!svc->stratix10_svc_hwmon) {
+			dev_err(dev, "failed to allocate %s device\n",
+				SOCFPGA_HWMON);
+		} else {
+			svc->stratix10_svc_hwmon->dev.parent = dev;
+
+			ret = platform_device_add(svc->stratix10_svc_hwmon);
+			if (ret) {
+				dev_err(dev, "failed to add %s device: %d\n",
+					SOCFPGA_HWMON, ret);
+				platform_device_put(svc->stratix10_svc_hwmon);
+				svc->stratix10_svc_hwmon = NULL;
+			}
+		}
+	}
+
 	ret = of_platform_default_populate(dev_of_node(dev), NULL, dev);
 	if (ret)
-		goto err_unregister_rsu_dev;
+		goto err_unregister_clients;
 
 	pr_info("Intel Service Layer Driver Initialized\n");
 
 	return 0;
 
-err_unregister_rsu_dev:
-	platform_device_unregister(svc->stratix10_svc_rsu);
+err_unregister_clients:
+	if (svc->stratix10_svc_hwmon)
+		platform_device_unregister(svc->stratix10_svc_hwmon);
+	if (svc->stratix10_svc_rsu)
+		platform_device_unregister(svc->stratix10_svc_rsu);
 	goto err_free_fifos;
 err_put_device:
 	platform_device_put(svc->stratix10_svc_rsu);
@@ -2046,6 +2083,9 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
 	struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
 	struct stratix10_svc *svc = ctrl->svc;
 
+	if (svc->stratix10_svc_hwmon)
+		platform_device_unregister(svc->stratix10_svc_hwmon);
+
 	stratix10_svc_async_exit(ctrl);
 
 	of_platform_depopulate(ctrl->dev);
include/linux/firmware/intel/stratix10-smc.h +38 -0
index 9116512169dc..18ac6fe96d9d 100644
@@ -695,6 +695,44 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
 #define INTEL_SIP_SMC_ASYNC_POLL \
 	INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_POLL)
 
+/**
+ * Request INTEL_SIP_SMC_ASYNC_HWMON_READTEMP
+ * Async call to request temperature
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_ASYNC_HWMON_READTEMP
+ * a1 transaction job id
+ * a2 Temperature Channel
+ * a3-a17 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_REJECTED
+ * or INTEL_SIP_SMC_STATUS_BUSY
+ * a1-a17 not used
+ */
+#define INTEL_SIP_SMC_ASYNC_FUNC_ID_HWMON_READTEMP	0xE8
+#define INTEL_SIP_SMC_ASYNC_HWMON_READTEMP \
+	INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_HWMON_READTEMP)
+
+/**
+ * Request INTEL_SIP_SMC_ASYNC_HWMON_READVOLT
+ * Async call to request voltage
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_ASYNC_HWMON_READVOLT
+ * a1 transaction job id
+ * a2 Voltage Channel
+ * a3-a17 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_REJECTED
+ * or INTEL_SIP_SMC_STATUS_BUSY
+ * a1-a17 not used
+ */
+#define INTEL_SIP_SMC_ASYNC_FUNC_ID_HWMON_READVOLT	0xE9
+#define INTEL_SIP_SMC_ASYNC_HWMON_READVOLT \
+	INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_HWMON_READVOLT)
+
 /**
  * Request INTEL_SIP_SMC_ASYNC_RSU_GET_SPT
  * Async call to get RSU SPT from SDM.
Signature · 1 line
2.43.7
#2 lore raw

Re: [PATCH v6 1/2] firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] Hardware monitoring functionality is registered as a platform device rather than an auxiliary device, violating hwmon subsystem layering rules.

Pre-existing issues:
- [High] Asynchronous service layer APIs and resources are destroyed before client devices are unregistered, leading to a Use-After-Free and NULL pointer dereference race condition. --

--- Patch [1]: [PATCH v6 1/2] firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device --- commit 552947f984c2b5770daa9717c679362b5561cfa3
Author: Tze Yee Ng <[email protected]>

firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device

Add asynchronous Stratix 10 service layer support for hardware monitor temperature and voltage read commands in stratix10_svc_async_send() and stratix10_svc_async_prepare_response().

Register a socfpga-hwmon platform device from the service layer driver when hardware monitor support is enabled, similar to the RSU device.

Quoted 4 lines
drivers/firmware/stratix10-svc.c +0 -0
index c24ca5823078f..fc38afed5b7fe 100644

[ ... ]

Quoted 4 lines
drivers/firmware/stratix10-svc.c +0 -0
@@ -2013,16 +2028,38 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_put_device;
 

drivers/firmware/stratix10-svc.c static int stratix10_svc_drv_probe(struct platform_device *pdev) · line 2040

Quoted 10 lines
drivers/firmware/stratix10-svc.c +10 -0
+	if (IS_ENABLED(CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON)) {
+		svc->stratix10_svc_hwmon =
+			platform_device_alloc(SOCFPGA_HWMON, 0);
+		if (!svc->stratix10_svc_hwmon) {
+			dev_err(dev, "failed to allocate %s device\n",
+				SOCFPGA_HWMON);
+		} else {
+			svc->stratix10_svc_hwmon->dev.parent = dev;
+
+			ret = platform_device_add(svc->stratix10_svc_hwmon);

[Severity: Medium]
Should the hardware monitoring functionality be implemented as an auxiliary device driver instead of a platform device?

The hardware monitoring subsystem guidelines state that when hardware monitoring is a secondary function of a chip, it should be implemented as an auxiliary device and reside in drivers/hwmon/.

Does registering socfpga-hwmon directly as a platform device from this firmware service driver bypass the architectural layering rules for hwmon?

[ ... ]

drivers/firmware/stratix10-svc.c static void stratix10_svc_drv_remove(struct platform_device *pdev) · line 2091

Quoted 10 lines
drivers/firmware/stratix10-svc.c +3 -0
@@ -2046,6 +2083,9 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
 	struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
 	struct stratix10_svc *svc = ctrl->svc;
 
+	if (svc->stratix10_svc_hwmon)
+		platform_device_unregister(svc->stratix10_svc_hwmon);
+
 	stratix10_svc_async_exit(ctrl);
 
 	of_platform_depopulate(ctrl->dev);

[Severity: High]
This is a pre-existing issue, but can the destruction order in stratix10_svc_drv_remove() lead to a NULL pointer dereference or a use-after-free race condition?

When stratix10_svc_async_exit() is called, it destroys the async ID pool and sets actrl->invoke_fn to NULL:

drivers/firmware/stratix10-svc.c:stratix10_svc_async_exit() {
    ...
    ida_destroy(&actrl->async_id_pool);
    actrl->invoke_fn = NULL;
    ...
}

However, the RSU client device is unregistered after this destruction step via platform_device_unregister(svc->stratix10_svc_rsu).

If a user interacts with a client device's sysfs attribute while the module is being unloaded, could the still-active client device invoke stratix10_svc_async_send()?

If so, it would concurrently access freed asynchronous channels or attempt to execute actrl->invoke_fn(actrl, &args, &res) after it has been locklessly cleared, resulting in a kernel crash.

Would it be safer to unregister all child and client devices before the resources they depend on are torn down?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
maintainer
#3 lore raw

Re: [PATCH v6 1/2] firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device

Quoted 46 lines · On 7/19/26 20:37, [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] Hardware monitoring functionality is registered as a platform device rather than an auxiliary device, violating hwmon subsystem layering rules.

Pre-existing issues:
- [High] Asynchronous service layer APIs and resources are destroyed before client devices are unregistered, leading to a Use-After-Free and NULL pointer dereference race condition. --

--- Patch [1]: [PATCH v6 1/2] firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device --- commit 552947f984c2b5770daa9717c679362b5561cfa3
Author: Tze Yee Ng <[email protected]>

firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device

Add asynchronous Stratix 10 service layer support for hardware monitor temperature and voltage read commands in stratix10_svc_async_send() and stratix10_svc_async_prepare_response().

Register a socfpga-hwmon platform device from the service layer driver when hardware monitor support is enabled, similar to the RSU device.

Quoted 4 lines
drivers/firmware/stratix10-svc.c +0 -0
index c24ca5823078f..fc38afed5b7fe 100644

[ ... ]

Quoted 4 lines
drivers/firmware/stratix10-svc.c +0 -0
@@ -2013,16 +2028,38 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
  	if (ret)
  		goto err_put_device;
 

drivers/firmware/stratix10-svc.c static int stratix10_svc_drv_probe(struct platform_device *pdev) · line 2040

Quoted 10 lines
drivers/firmware/stratix10-svc.c +10 -0
+	if (IS_ENABLED(CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON)) {
+		svc->stratix10_svc_hwmon =
+			platform_device_alloc(SOCFPGA_HWMON, 0);
+		if (!svc->stratix10_svc_hwmon) {
+			dev_err(dev, "failed to allocate %s device\n",
+				SOCFPGA_HWMON);
+		} else {
+			svc->stratix10_svc_hwmon->dev.parent = dev;
+
+			ret = platform_device_add(svc->stratix10_svc_hwmon);

[Severity: Medium]
Should the hardware monitoring functionality be implemented as an auxiliary device driver instead of a platform device?

Quoted 7 lines

The hardware monitoring subsystem guidelines state that when hardware monitoring is a secondary function of a chip, it should be implemented as an auxiliary device and reside in drivers/hwmon/.

Does registering socfpga-hwmon directly as a platform device from this firmware service driver bypass the architectural layering rules for hwmon?

It should be implemented as auxiliary driver, but feel free to ignore since I only recently added this guidance to Sashiko.

Quoted 10 lines

[ ... ]

Quoted 9 lines
drivers/firmware/stratix10-svc.c +3 -0
@@ -2046,6 +2083,9 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
  	struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
  	struct stratix10_svc *svc = ctrl->svc;
 
+	if (svc->stratix10_svc_hwmon)
+		platform_device_unregister(svc->stratix10_svc_hwmon);
+
  	stratix10_svc_async_exit(ctrl);
 
Quoted 7 lines

drivers/firmware/stratix10-svc.c static void stratix10_svc_drv_remove(struct platform_device *pdev) · line 2091

Quoted 1 line
drivers/firmware/stratix10-svc.c +0 -0
  	of_platform_depopulate(ctrl->dev);

[Severity: High]
This is a pre-existing issue, but can the destruction order in stratix10_svc_drv_remove() lead to a NULL pointer dereference or a use-after-free race condition?

Pre-existing, so your call if you want to fix it or not.

Thanks,
Guenter

Quoted 24 lines

When stratix10_svc_async_exit() is called, it destroys the async ID pool and sets actrl->invoke_fn to NULL:

drivers/firmware/stratix10-svc.c:stratix10_svc_async_exit() {
     ...
     ida_destroy(&actrl->async_id_pool);
     actrl->invoke_fn = NULL;
     ...
}

However, the RSU client device is unregistered after this destruction step via platform_device_unregister(svc->stratix10_svc_rsu).

If a user interacts with a client device's sysfs attribute while the module is being unloaded, could the still-active client device invoke stratix10_svc_async_send()?

If so, it would concurrently access freed asynchronous channels or attempt to execute actrl->invoke_fn(actrl, &args, &res) after it has been locklessly cleared, resulting in a kernel crash.

Would it be safer to unregister all child and client devices before the resources they depend on are torn down?

author maintainer
#4 lore raw

Re: [PATCH v6 1/2] firmware: stratix10-svc: add async HWMON read commands and register socfpga-hwmon device

Quoted 61 lines · Guenter Roeck
Quoted 60 lines · On 7/19/26 20:37, [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] Hardware monitoring functionality is registered as a platform device rather than an auxiliary device, violating hwmon subsystem layering rules.

Pre-existing issues:
- [High] Asynchronous service layer APIs and resources are destroyed before client devices are unregistered, leading to a Use-After-Free and NULL pointer dereference race condition.

Signature · 14 lines
--- Patch [1]: [PATCH v6 1/2] firmware: stratix10-svc: add async HWMON 
read commands and register socfpga-hwmon device ---
commit 552947f984c2b5770daa9717c679362b5561cfa3
Author: Tze Yee Ng <[email protected]>

firmware: stratix10-svc: add async HWMON read commands and register 
socfpga-hwmon device

Add asynchronous Stratix 10 service layer support for hardware monitor
temperature and voltage read commands in stratix10_svc_async_send() and
stratix10_svc_async_prepare_response().

Register a socfpga-hwmon platform device from the service layer driver
when hardware monitor support is enabled, similar to the RSU device.
Quoted 5 lines
drivers/firmware/ renamed from drivers/firmware/stratix10-svc.c +0 -0

stratix10-svc.c
index c24ca5823078f..fc38afed5b7fe 100644

drivers/firmware/stratix10-svc.c +0 -0

[ ... ]

Quoted 4 lines
drivers/firmware/stratix10-svc.c +0 -0
@@ -2013,16 +2028,38 @@ static int stratix10_svc_drv_probe(struct 
 platform_device *pdev)
       if (ret)
           goto err_put_device;

drivers/firmware/stratix10-svc.c static int stratix10_svc_drv_probe(struct · line 2040

Quoted 10 lines
drivers/firmware/stratix10-svc.c +10 -0
+    if (IS_ENABLED(CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON)) {
+        svc->stratix10_svc_hwmon =
+            platform_device_alloc(SOCFPGA_HWMON, 0);
+        if (!svc->stratix10_svc_hwmon) {
+            dev_err(dev, "failed to allocate %s device\n",
+                SOCFPGA_HWMON);
+        } else {
+            svc->stratix10_svc_hwmon->dev.parent = dev;
+
+            ret = platform_device_add(svc->stratix10_svc_hwmon);

[Severity: Medium]
Should the hardware monitoring functionality be implemented as an auxiliary
device driver instead of a platform device?

The hardware monitoring subsystem guidelines state that when hardware monitoring is a secondary function of a chip, it should be implemented as an
auxiliary device and reside in drivers/hwmon/.

Quoted 8 lines
Quoted 4 lines

Does registering socfpga-hwmon directly as a platform device from this firmware service driver bypass the architectural layering rules for hwmon?

It should be implemented as auxiliary driver, but feel free to ignore since I only recently added this guidance to Sashiko.

Thanks. I'll keep the platform device registration for this series. I’m happy to look at converting socfpga-hwmon to an auxiliary device in a follow-up if preferred.

Quoted 17 lines
Quoted 17 lines

[ ... ]

Quoted 10 lines
drivers/firmware/stratix10-svc.c +0 -0
@@ -2046,6 +2083,9 @@ static void stratix10_svc_drv_remove(struct 
 platform_device *pdev)

      struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
      struct stratix10_svc *svc = ctrl->svc;
+    if (svc->stratix10_svc_hwmon)
+        platform_device_unregister(svc->stratix10_svc_hwmon); +
      stratix10_svc_async_exit(ctrl); of_platform_depopulate(ctrl->dev);

[Severity: High]
This is a pre-existing issue, but can the destruction order in stratix10_svc_drv_remove() lead to a NULL pointer dereference or a use-after-free race condition?

Quoted 5 lines

Pre-existing, so your call if you want to fix it or not.

Thanks,
Guenter

It is fixed in
https://lore.kernel.org/all/6630a1568f162d9455e0580f7ccadc262db4718e.1784007275.git.adrian.ho.yin.ng@altera.com/

Quoted 29 lines
Quoted 28 lines

When stratix10_svc_async_exit() is called, it destroys the async ID pool and sets actrl->invoke_fn to NULL:

drivers/firmware/stratix10-svc.c:stratix10_svc_async_exit() {
     ...
     ida_destroy(&actrl->async_id_pool); actrl->invoke_fn = NULL;
     ...
}

However, the RSU client device is unregistered after this destruction step
via platform_device_unregister(svc->stratix10_svc_rsu).

If a user interacts with a client device's sysfs attribute while the module
is being unloaded, could the still-active client device invoke stratix10_svc_async_send()?

If so, it would concurrently access freed asynchronous channels or attempt
to execute actrl->invoke_fn(actrl, &args, &res) after it has been locklessly
cleared, resulting in a kernel crash.

Would it be safer to unregister all child and client devices before the resources they depend on are torn down?

author maintainer
#5 lore raw

PATCH v6 2/2 hwmon: add Altera SoC FPGA hardware monitoring driver

In reply to [email protected]

From: Tze Yee Ng <[email protected]>

Add a hardware monitor driver for Altera SoC FPGA devices using the Stratix 10 service layer. Sensor channels are selected based on the service layer compatible string.

---
Changes in v6:
- No functional changes from v5

Changes in v5:
- Poll async responses until HWMON_TIMEOUT (2 s) instead of a fixed 3-iteration retry loop (~3 ms), fixing premature timeouts observed on silicon
- Add MODULE_ALIAS("platform:socfpga-hwmon")

Changes in v4:
- Register devm_add_action_or_reset() before devm_hwmon_device_register_with_info(); drop manual channel cleanup on hwmon registration failure
- Remove unreferenced async completion and pre-poll wait_for_completion_io_timeout(); poll directly after async_send() with the existing retry loop

Changes in v3:
- Fix 16-bit signed Q8.8 temperature conversion (cast through s16)
- Remove unused async callback; pass NULL to stratix10_svc_async_send()
- Keep wait_for_completion_io_timeout() before polling with comment explaining the service layer never invokes the callback but firmware needs time to complete the transaction (RSU pattern)
- Align async poll loop with RSU (retry on failure instead of aborting)
- Use wait_for_completion_timeout() for synchronous reads
- Handle -EINVAL and -EOPNOTSUPP when async client registration fails
- Defer SVC channel/async cleanup via devm_add_action_or_reset(); drop .remove()

Changes in v2:
- Drop altr,stratix10-hwmon OF compatible and DT channel parsing
- Select channels from hardcoded tables using parent SVC compatible (intel,stratix10-svc or intel,agilex-svc)
- Rename driver from stratix10-hwmon to socfpga-hwmon
- Rename Kconfig symbol to CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON
- Add Agilex voltage and temperature channel tables
- Convert SDM Q8.8 degrees Celsius to hwmon millidegrees
- Convert SDM Q16 volts to hwmon millivolts
- Use socfpga_hwmon as hwmon sysfs device name
- Add last_err for synchronous SVC read error propagation
- Update Documentation/hwmon and MAINTAINERS accordingly

---
 Documentation/hwmon/index.rst         |   1 +
 Documentation/hwmon/socfpga-hwmon.rst |  34 ++
 MAINTAINERS                           |   8 +
 drivers/hwmon/Kconfig                 |  10 +
 drivers/hwmon/Makefile                |   1 +
 drivers/hwmon/socfpga-hwmon.c         | 579 ++++++++++++++++++++++++++
 6 files changed, 633 insertions(+)
 create mode 100644 Documentation/hwmon/socfpga-hwmon.rst
 create mode 100644 drivers/hwmon/socfpga-hwmon.c
Documentation/hwmon/index.rst +1 -0
index 29130df44d12..3299417a24b8 100644
@@ -254,6 +254,7 @@ Hardware Monitoring Kernel Drivers
    sparx5-temp
    spd5118
    stpddc60
+   socfpga-hwmon
    surface_fan
    sy7636a-hwmon
    tc654
Documentation/hwmon/socfpga-hwmon.rst new file +34 -0
new file mode 100644
index 000000000000..e5da42556a62
@@ -0,0 +1,34 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver socfpga-hwmon
+=============================
+
+Supported chips:
+
+ * Altera Stratix 10 SoC FPGA
+ * Altera Agilex SoC FPGA
+
+Authors:
+      - Nazim Amirul <[email protected]>
+      - Tze Yee Ng <[email protected]>
+
+Description
+-----------
+
+This driver supports hardware monitoring for Altera SoC
+FPGA devices through the Secure Device Manager and Stratix 10 service layer.
+
+The following sensor types are supported:
+
+  * temperature
+  * voltage
+
+Usage Notes
+-----------
+
+The stratix10-svc driver registers a socfpga-hwmon platform device when
+hardware monitor support is enabled. Sensor channels are selected in the
+driver based on the service layer compatible string:
+
+  * intel,stratix10-svc
+  * intel,agilex-svc
MAINTAINERS +8 -0
index a674e36529f7..ab6cb215a02f 100644
@@ -965,6 +965,14 @@ L:	[email protected]
 S:	Maintained
 F:	drivers/gpio/gpio-altera.c
 
+ALTERA SoC FPGA HWMON DRIVER
+M:	Nazim Amirul <[email protected]>
+M:	Tze Yee Ng <[email protected]>
+L:	[email protected]
+S:	Maintained
+F:	Documentation/hwmon/socfpga-hwmon.rst
+F:	drivers/hwmon/socfpga-hwmon.c
+
 ALTERA TRIPLE SPEED ETHERNET DRIVER
 M:	Boon Khai Ng <[email protected]>
 L:	[email protected]
drivers/hwmon/Kconfig +10 -0
index 2bfbcc033d59..8e768661fec2 100644
@@ -2160,6 +2160,16 @@ config SENSORS_SMSC47M192
 	  This driver can also be built as a module. If so, the module
 	  will be called smsc47m192.
 
+config SENSORS_ALTERA_SOCFPGA_HWMON
+	tristate "Altera SoC FPGA hardware monitoring features"
+	depends on INTEL_STRATIX10_SERVICE
+	help
+	  If you say yes here you get support for the temperature and
+	  voltage sensors of Altera SoC FPGA devices.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called socfpga-hwmon.
+
 config SENSORS_SMSC47B397
 	tristate "SMSC LPC47B397-NC"
 	depends on HAS_IOPORT
drivers/hwmon/Makefile +1 -0
index 63effc0ab8d1..aeedee80e1f0 100644
@@ -221,6 +221,7 @@ obj-$(CONFIG_SENSORS_SMPRO)	+= smpro-hwmon.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
+obj-$(CONFIG_SENSORS_ALTERA_SOCFPGA_HWMON)	+= socfpga-hwmon.o
 obj-$(CONFIG_SENSORS_SPARX5)	+= sparx5-temp.o
 obj-$(CONFIG_SENSORS_SPD5118)	+= spd5118.o
 obj-$(CONFIG_SENSORS_STTS751)	+= stts751.o
drivers/hwmon/socfpga-hwmon.c new file +579 -0

579 lines not on this page · raw message

Signature · 1 line
2.43.7
#6 lore raw

Re: [PATCH v6 2/2] hwmon: add Altera SoC FPGA hardware monitoring driver

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Missing break in async poll loop causes severe kernel log spam and unnecessary blocking on hard…

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing break in async poll loop causes severe kernel log spam and unnecessary blocking on hard errors.
- [High] Synchronous read timeouts leave stale requests in the channel FIFO, causing all subsequent reads to process stale data and return mismatched sensor values. --

--- Patch [2]: [PATCH v6 2/2] hwmon: add Altera SoC FPGA hardware monitoring driver --- commit ab6c0c0f95d3890d759e04d9d9aecd151d6406fd
Author: Tze Yee Ng <[email protected]>
Subject: hwmon: add Altera SoC FPGA hardware monitoring driver

This commit adds a hardware monitoring driver for Altera SoC FPGA devices using the Stratix 10 service layer.

Quoted 5 lines
drivers/hwmon/socfpga-hwmon.c new file +0 -0
new file mode 100644
index 0000000000000..72418201b65d6

[ ... ]

Quoted 4 lines
drivers/hwmon/socfpga-hwmon.c new file +4 -0
+static int socfpga_hwmon_async_read(struct device *dev,
+				    enum hwmon_sensor_types type,
+				    struct stratix10_svc_client_msg *msg)
+{

[ ... ]

drivers/hwmon/socfpga-hwmon.c line 218

Quoted 8 lines
drivers/hwmon/socfpga-hwmon.c new file +8 -0
+	ret = -ETIMEDOUT;
+	while (!time_after(jiffies, deadline)) {
+		status = stratix10_svc_async_poll(priv->chan, handle, &data);
+		if (status == -EAGAIN) {
+			dev_dbg(dev, "Async message is still in progress\n");
+		} else if (status < 0) {
+			dev_alert(dev, "Failed to poll async message: %d\n", status);
+			ret = -ETIMEDOUT;

[Severity: High]
Does this loop need a break statement here when status < 0?

If stratix10_svc_async_poll() returns a hard error, the code sets ret = -ETIMEDOUT but continues to loop for up to 2 seconds. This could flood the kernel log with dev_alert() messages on every 1ms retry.

Quoted 6 lines
drivers/hwmon/socfpga-hwmon.c new file +6 -0
+		} else if (status == 0) {
+			ret = 0;
+			break;
+		}
+		msleep(HWMON_RETRY_SLEEP_MS);
+	}

[ ... ]

Quoted 4 lines
drivers/hwmon/socfpga-hwmon.c new file +4 -0
+static int socfpga_hwmon_sync_read(struct device *dev,
+				   enum hwmon_sensor_types type,
+				   struct stratix10_svc_client_msg *msg)
+{

[ ... ]

drivers/hwmon/socfpga-hwmon.c line 272

Quoted 9 lines
drivers/hwmon/socfpga-hwmon.c new file +9 -0
+	ret = stratix10_svc_send(priv->chan, msg);
+	if (ret < 0)
+		goto status_done;
+
+	ret = wait_for_completion_timeout(&priv->completion, HWMON_TIMEOUT);
+	if (!ret) {
+		dev_err(priv->client.dev, "timeout waiting for SMC call\n");
+		ret = -ETIMEDOUT;
+		goto status_done;

[Severity: High]
If a timeout occurs here, could the unfulfilled request remain in the SVC channel's FIFO?

When the timeout hits, this path calls stratix10_svc_done() which stops the worker thread, but it doesn't appear to remove the request from chan->svc_fifo.

Would the next sensor read enqueue a new request and receive the stale data from this timed-out request, permanently desynchronizing all subsequent sensor readings?

Quoted 8 lines
drivers/hwmon/socfpga-hwmon.c new file +8 -0
+	}
+
+	ret = priv->last_err;
+
+status_done:
+	stratix10_svc_done(priv->chan);
+	return ret;
+}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
maintainer
#7 lore raw

Re: [PATCH v6 2/2] hwmon: add Altera SoC FPGA hardware monitoring driver

Quoted 24 lines · On 7/19/26 20:36, [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing break in async poll loop causes severe kernel log spam and unnecessary blocking on hard errors.
- [High] Synchronous read timeouts leave stale requests in the channel FIFO, causing all subsequent reads to process stale data and return mismatched sensor values. --

--- Patch [2]: [PATCH v6 2/2] hwmon: add Altera SoC FPGA hardware monitoring driver --- commit ab6c0c0f95d3890d759e04d9d9aecd151d6406fd
Author: Tze Yee Ng <[email protected]>
Subject: hwmon: add Altera SoC FPGA hardware monitoring driver

This commit adds a hardware monitoring driver for Altera SoC FPGA devices using the Stratix 10 service layer.

Quoted 5 lines
drivers/hwmon/socfpga-hwmon.c new file +0 -0
new file mode 100644
index 0000000000000..72418201b65d6

[ ... ]

Quoted 4 lines
drivers/hwmon/socfpga-hwmon.c new file +4 -0
+static int socfpga_hwmon_async_read(struct device *dev,
+				    enum hwmon_sensor_types type,
+				    struct stratix10_svc_client_msg *msg)
+{

[ ... ]

Quoted 5 lines

drivers/hwmon/socfpga-hwmon.c line 215

Quoted 5 lines
drivers/hwmon/socfpga-hwmon.c new file +5 -0
+	ret = -ETIMEDOUT;
+	while (!time_after(jiffies, deadline)) {
+		status = stratix10_svc_async_poll(priv->chan, handle, &data);
+		if (status == -EAGAIN) {
+			dev_dbg(dev, "Async message is still in progress\n");

This also creates a lot of noise if debugging is active. I don't know how long the command usually takes, but it does seem to me that this debug message isn't really helpful.

Quoted 11 lines

drivers/hwmon/socfpga-hwmon.c line 218

Quoted 3 lines
drivers/hwmon/socfpga-hwmon.c new file +3 -0
+		} else if (status < 0) {
+			dev_alert(dev, "Failed to poll async message: %d\n", status);
+			ret = -ETIMEDOUT;

[Severity: High]
Does this loop need a break statement here when status < 0?

If stratix10_svc_async_poll() returns a hard error, the code sets ret = -ETIMEDOUT but continues to loop for up to 2 seconds. This could flood the kernel log with dev_alert() messages on every 1ms retry.

Sashiko has a good point, especially since the function returns -EINVAL which, if seen, seems to be _real_ hard error and retrying seems pointless. Also, why replace -EINVAL with -ETIMEDOUT ? That would need an explanation.

On top of that, "ret = -ETIMEDOUT;" is pointless here since ret is already set to -ETIMEDOUT.

Oh, and the called code already displays an error message unless the parameters are bad.

Quoted 5 lines

drivers/hwmon/socfpga-hwmon.c line 223

Quoted 5 lines
drivers/hwmon/socfpga-hwmon.c new file +5 -0
+		} else if (status == 0) {
+			ret = 0;
+			break;
+		}
+		msleep(HWMON_RETRY_SLEEP_MS);

I would suggest to use usleep_range().

Quoted 21 lines
Quoted 1 line
drivers/hwmon/socfpga-hwmon.c new file +1 -0
+	}

[ ... ]

Quoted 4 lines
drivers/hwmon/socfpga-hwmon.c new file +4 -0
+static int socfpga_hwmon_sync_read(struct device *dev,
+				   enum hwmon_sensor_types type,
+				   struct stratix10_svc_client_msg *msg)
+{

[ ... ]

drivers/hwmon/socfpga-hwmon.c line 272

Quoted 9 lines
drivers/hwmon/socfpga-hwmon.c new file +9 -0
+	ret = stratix10_svc_send(priv->chan, msg);
+	if (ret < 0)
+		goto status_done;
+
+	ret = wait_for_completion_timeout(&priv->completion, HWMON_TIMEOUT);
+	if (!ret) {
+		dev_err(priv->client.dev, "timeout waiting for SMC call\n");
+		ret = -ETIMEDOUT;
+		goto status_done;

[Severity: High]
If a timeout occurs here, could the unfulfilled request remain in the SVC channel's FIFO?

Quoted 7 lines

When the timeout hits, this path calls stratix10_svc_done() which stops the worker thread, but it doesn't appear to remove the request from chan->svc_fifo.

Would the next sensor read enqueue a new request and receive the stale data from this timed-out request, permanently desynchronizing all subsequent sensor readings?

Please either address or explain why it is not a problem.

Thanks,
Guenter

Quoted 9 lines
Quoted 8 lines
drivers/hwmon/socfpga-hwmon.c new file +8 -0
+	}
+
+	ret = priv->last_err;
+
+status_done:
+	stratix10_svc_done(priv->chan);
+	return ret;
+}
author maintainer
#8 lore raw

Re: [PATCH v6 2/2] hwmon: add Altera SoC FPGA hardware monitoring driver

Quoted 60 lines · Guenter Roeck
Quoted 36 lines · On 7/19/26 20:36, [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing break in async poll loop causes severe kernel log spam and unnecessary blocking on hard errors.
- [High] Synchronous read timeouts leave stale requests in the channel FIFO, causing all subsequent reads to process stale data and return mismatched sensor values.

Signature · 9 lines
--- Patch [2]: [PATCH v6 2/2] hwmon: add Altera SoC FPGA hardware 
monitoring driver ---
commit ab6c0c0f95d3890d759e04d9d9aecd151d6406fd
Author: Tze Yee Ng <[email protected]>
Subject: hwmon: add Altera SoC FPGA hardware monitoring driver

This commit adds a hardware monitoring driver for Altera SoC FPGA 
devices using
the Stratix 10 service layer.
Quoted 6 lines
drivers/hwmon/socfpga- renamed from drivers/hwmon/socfpga-hwmon.c +0 -0

hwmon.c
new file mode 100644
index 0000000000000..72418201b65d6

drivers/hwmon/socfpga-hwmon.c new file +0 -0

[ ... ]

Quoted 4 lines
drivers/hwmon/socfpga-hwmon.c new file +4 -0
+static int socfpga_hwmon_async_read(struct device *dev,
+                    enum hwmon_sensor_types type,
+                    struct stratix10_svc_client_msg *msg)
+{

[ ... ]

Quoted 5 lines

+    ret = -ETIMEDOUT;
+    while (!time_after(jiffies, deadline)) {
+        status = stratix10_svc_async_poll(priv->chan, handle, &data); +        if (status == -EAGAIN) {
+            dev_dbg(dev, "Async message is still in progress\n");

This also creates a lot of noise if debugging is active. I don't know how long the command usually takes, but it does seem to me that this debug message isn't really helpful.

Quoted 5 lines
Quoted 4 lines

+        } else if (status < 0) {
+            dev_alert(dev, "Failed to poll async message: %d\n", status);
+            ret = -ETIMEDOUT;

Quoted 7 lines

[Severity: High]
Does this loop need a break statement here when status < 0?

If stratix10_svc_async_poll() returns a hard error, the code sets ret = -ETIMEDOUT but continues to loop for up to 2 seconds. This could flood the kernel log with dev_alert() messages on every 1ms retry.

Sashiko has a good point, especially since the function returns -EINVAL which, if seen, seems to be  _real_ hard error and retrying seems pointless. Also, why replace -EINVAL with -ETIMEDOUT ? That would need an explanation.

Quoted 6 lines

On top of that, "ret = -ETIMEDOUT;" is pointless here since ret is already set to -ETIMEDOUT.

Oh, and the called code already displays an error message unless the parameters are bad.

Agreed. In v7 I'll break out of the poll loop on hard errors, return the real poll error instead of -ETIMEDOUT, drop the redundant alert (SVC already logs) and remove the -EAGAIN debug print.

Quoted 8 lines
Quoted 5 lines
Quoted 5 lines

+        } else if (status == 0) {
+            ret = 0;
+            break;
+        }
+        msleep(HWMON_RETRY_SLEEP_MS);

I would suggest to use usleep_range().

Agreed. In v7 I'll switch the short waits to usleep_range().

Quoted 33 lines
Quoted 25 lines
Quoted 1 line

+    }

[ ... ]

Quoted 4 lines
drivers/hwmon/socfpga-hwmon.c new file +4 -0
+static int socfpga_hwmon_sync_read(struct device *dev,
+                   enum hwmon_sensor_types type,
+                   struct stratix10_svc_client_msg *msg)
+{

[ ... ]

Quoted 10 lines

+    ret = stratix10_svc_send(priv->chan, msg);
+    if (ret < 0)
+        goto status_done;
+
+    ret = wait_for_completion_timeout(&priv->completion, HWMON_TIMEOUT);
+    if (!ret) {
+        dev_err(priv->client.dev, "timeout waiting for SMC call\n"); +        ret = -ETIMEDOUT;
+        goto status_done;

[Severity: High]
If a timeout occurs here, could the unfulfilled request remain in the SVC channel's FIFO?

When the timeout hits, this path calls stratix10_svc_done() which stops the
worker thread, but it doesn't appear to remove the request from chan-

Quoted 7 lines
Quoted 1 line

svc_fifo.

Would the next sensor read enqueue a new request and receive the stale data
from this timed-out request, permanently desynchronizing all subsequent sensor readings?

Quoted 5 lines

Please either address or explain why it is not a problem.

Thanks,
Guenter

Yes, that race is real if the worker exits via kthread_should_stop() before dequeuing. stratix10_svc_done() stops the thread but does not flush svc_fifo.

For this driver I will invalidate an in-flight transfer generation after a timeout so a late/stale callback cannot complete the next read. A proper FIFO drain in stratix10_svc_done() would still be useful as a follow-up in the service layer.

Quoted 10 lines
Quoted 9 lines
Quoted 8 lines

+    }

drivers/hwmon/socfpga-hwmon.c new file +7 -0
+
+    ret = priv->last_err;
+
+status_done:
+    stratix10_svc_done(priv->chan);
+    return ret;
+}