* [PATCH v3 1/5] firmware: raspberrypi: Add blank line after declaration in response_callback
2026-11-10 16:47 [PATCH v3 0/5] firmware: raspberrypi: Style cleanups and fix child device lifetime Sander Speetjens
@ 2026-11-10 16:47 ` Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 2/5] firmware: raspberrypi: Fix indentation of return statement Sander Speetjens
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Sander Speetjens @ 2026-11-10 16:47 UTC (permalink / raw)
To: Florian Fainelli, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Stephen Boyd, Nicolas Saenz Julienne
Cc: linux-rpi-kernel, linux-arm-kernel, linux-kernel,
sander.speetjens, Manuel Ebner
Add a blank line after the local variable declaration.
Reviewed-by: Manuel Ebner <manuelebnerli@mailbox.org>
Signed-off-by: Sander Speetjens <sander.speetjens@gmail.com>
---
drivers/firmware/raspberrypi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 443459c8c90f..8f3653c4a669 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -40,6 +40,7 @@ static DEFINE_MUTEX(transaction_lock);
static void response_callback(struct mbox_client *cl, void *msg)
{
struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl);
+
complete(&fw->c);
}
--
2.56.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v3 2/5] firmware: raspberrypi: Fix indentation of return statement
2026-11-10 16:47 [PATCH v3 0/5] firmware: raspberrypi: Style cleanups and fix child device lifetime Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 1/5] firmware: raspberrypi: Add blank line after declaration in response_callback Sander Speetjens
@ 2026-11-10 16:47 ` Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 3/5] firmware: raspberrypi: Add blank line after declaration in probe error path Sander Speetjens
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Sander Speetjens @ 2026-11-10 16:47 UTC (permalink / raw)
To: Florian Fainelli, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Stephen Boyd, Nicolas Saenz Julienne
Cc: linux-rpi-kernel, linux-arm-kernel, linux-kernel,
sander.speetjens, Manuel Ebner
The return was over-indented; statements should start on a tab stop.
Reviewed-by: Manuel Ebner <manuelebnerli@mailbox.org>
Signed-off-by: Sander Speetjens <sander.speetjens@gmail.com>
---
drivers/firmware/raspberrypi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 8f3653c4a669..e0c91719b4d0 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -267,7 +267,7 @@ unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw, unsigned int
* assume the maximum clock rate is absolute maximum we can
* store over our type.
*/
- return UINT_MAX;
+ return UINT_MAX;
return le32_to_cpu(msg.rate);
}
--
2.56.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v3 3/5] firmware: raspberrypi: Add blank line after declaration in probe error path
2026-11-10 16:47 [PATCH v3 0/5] firmware: raspberrypi: Style cleanups and fix child device lifetime Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 1/5] firmware: raspberrypi: Add blank line after declaration in response_callback Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 2/5] firmware: raspberrypi: Fix indentation of return statement Sander Speetjens
@ 2026-11-10 16:47 ` Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 4/5] firmware: raspberrypi: Document memory barriers in property list path Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 5/5] firmware: raspberrypi: Store child devices in struct rpi_firmware Sander Speetjens
4 siblings, 0 replies; 6+ messages in thread
From: Sander Speetjens @ 2026-11-10 16:47 UTC (permalink / raw)
To: Florian Fainelli, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Stephen Boyd, Nicolas Saenz Julienne
Cc: linux-rpi-kernel, linux-arm-kernel, linux-kernel,
sander.speetjens, Manuel Ebner
Add the conventional blank line after the local variable declaration.
Reviewed-by: Manuel Ebner <manuelebnerli@mailbox.org>
Signed-off-by: Sander Speetjens <sander.speetjens@gmail.com>
---
drivers/firmware/raspberrypi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index e0c91719b4d0..04163c3f385d 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -315,6 +315,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
fw->chan = mbox_request_channel(&fw->cl, 0);
if (IS_ERR(fw->chan)) {
int ret = PTR_ERR(fw->chan);
+
kfree(fw);
return dev_err_probe(dev, ret, "Failed to get mbox channel\n");
}
--
2.56.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v3 4/5] firmware: raspberrypi: Document memory barriers in property list path
2026-11-10 16:47 [PATCH v3 0/5] firmware: raspberrypi: Style cleanups and fix child device lifetime Sander Speetjens
` (2 preceding siblings ...)
2026-11-10 16:47 ` [PATCH v3 3/5] firmware: raspberrypi: Add blank line after declaration in probe error path Sander Speetjens
@ 2026-11-10 16:47 ` Sander Speetjens
2026-11-10 16:47 ` [PATCH v3 5/5] firmware: raspberrypi: Store child devices in struct rpi_firmware Sander Speetjens
4 siblings, 0 replies; 6+ messages in thread
From: Sander Speetjens @ 2026-11-10 16:47 UTC (permalink / raw)
To: Florian Fainelli, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Stephen Boyd, Nicolas Saenz Julienne
Cc: linux-rpi-kernel, linux-arm-kernel, linux-kernel,
sander.speetjens, Manuel Ebner
Add comments explaining the wmb() before the firmware transaction and
the rmb() before reading the response, as required by coding style.
Reviewed-by: Manuel Ebner <manuelebnerli@mailbox.org>
Signed-off-by: Sander Speetjens <sander.speetjens@gmail.com>
---
drivers/firmware/raspberrypi.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 04163c3f385d..ef3326d5cf30 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -111,10 +111,12 @@ int rpi_firmware_property_list(struct rpi_firmware *fw,
buf[1] = RPI_FIRMWARE_STATUS_REQUEST;
memcpy(&buf[2], data, tag_size);
buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END;
+ /* Make sure the writes to the buffer are visible to the firmware. */
wmb();
ret = rpi_firmware_transaction(fw, MBOX_CHAN_PROPERTY, bus_addr);
+ /* Make sure we see the firmware's response before reading it. */
rmb();
memcpy(data, &buf[2], tag_size);
if (ret == 0 && buf[1] != RPI_FIRMWARE_STATUS_SUCCESS) {
--
2.56.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v3 5/5] firmware: raspberrypi: Store child devices in struct rpi_firmware
2026-11-10 16:47 [PATCH v3 0/5] firmware: raspberrypi: Style cleanups and fix child device lifetime Sander Speetjens
` (3 preceding siblings ...)
2026-11-10 16:47 ` [PATCH v3 4/5] firmware: raspberrypi: Document memory barriers in property list path Sander Speetjens
@ 2026-11-10 16:47 ` Sander Speetjens
4 siblings, 0 replies; 6+ messages in thread
From: Sander Speetjens @ 2026-11-10 16:47 UTC (permalink / raw)
To: Florian Fainelli, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Stephen Boyd, Nicolas Saenz Julienne
Cc: linux-rpi-kernel, linux-arm-kernel, linux-kernel, sander.speetjens
When the raspberrypi-firmware driver is probed multiple times
(e.g. via multiple device tree nodes or dynamically loaded overlays),
rpi_firmware_probe() blindly overwrites the
global child platform device pointers rpi_hwmon and rpi_clk.
During initialization, rpi_firmware_probe() calls
rpi_register_hwmon_driver(), rpi_register_clk_driver() and
rpi_register_rtc_driver() to allocate and register new child platform
devices, storing them in global static variables. On a subsequent probe
the same platform device names are already in use, so
platform_device_register_data() fails and returns an ERR_PTR. The old
code never checked this return value and stored the error pointer
directly into the globals, overwriting the previous valid references.
When an instance is later unbound, rpi_firmware_remove() would then call
platform_device_unregister() on that error pointer (or on a pointer that
belonged to a different instance), while the previously allocated devices
were permanently leaked.
Move the hwmon, clock and rtc platform devices into struct rpi_firmware
so each instance owns its own children
and their lifetimes are correctly paired with the parent.
Also check the return value of platform_device_register_data()
so that an error pointer is never stored.
The child devices are optional; do not propagate registration
failures so the main firmware interface remains available.
Fixes: 70eea1bbb556 ("firmware: raspberrypi: Register hwmon driver")
Fixes: 91f2cf4a6b21 ("firmware: raspberrypi: register clk device")
Closes: https://sashiko.dev/#/bug/linux-667c4859-a44e-4461-aa3f-5b04056cc1d3
Signed-off-by: Sander Speetjens <sander.speetjens@gmail.com>
---
drivers/firmware/raspberrypi.c | 50 ++++++++++++++++++++++++++----------------
1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index ef3326d5cf30..7d8b89aeaf02 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -22,10 +22,6 @@
#define MBOX_DATA28(msg) ((msg) & ~0xf)
#define MBOX_CHAN_PROPERTY 8
-static struct platform_device *rpi_hwmon;
-static struct platform_device *rpi_clk;
-static struct platform_device *rpi_rtc;
-
struct rpi_firmware {
struct mbox_client cl;
struct mbox_chan *chan; /* The property channel. */
@@ -33,6 +29,10 @@ struct rpi_firmware {
u32 enabled;
struct kref consumers;
+
+ struct platform_device *hwmon_dev;
+ struct platform_device *clk_dev;
+ struct platform_device *rtc_dev;
};
static DEFINE_MUTEX(transaction_lock);
@@ -204,6 +204,7 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
static void
rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
{
+ struct platform_device *pdev;
u32 packet;
int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
&packet, sizeof(packet));
@@ -211,13 +212,19 @@ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
if (ret)
return;
- rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
- -1, NULL, 0);
+ pdev = platform_device_register_data(dev, "raspberrypi-hwmon",
+ -1, NULL, 0);
+
+ if (IS_ERR(pdev))
+ return;
+
+ fw->hwmon_dev = pdev;
}
-static void rpi_register_clk_driver(struct device *dev)
+static void rpi_register_clk_driver(struct device *dev, struct rpi_firmware *fw)
{
struct device_node *firmware;
+ struct platform_device *pdev;
/*
* Earlier DTs don't have a node for the firmware clocks but
@@ -231,11 +238,16 @@ static void rpi_register_clk_driver(struct device *dev)
return;
}
- rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
- -1, NULL, 0);
+ pdev = platform_device_register_data(dev, "raspberrypi-clk",
+ -1, NULL, 0);
+
+ if (IS_ERR(pdev))
+ return;
+
+ fw->clk_dev = pdev;
}
-static void rpi_register_rtc_driver(struct device *dev)
+static void rpi_register_rtc_driver(struct device *dev, struct rpi_firmware *fw)
{
struct platform_device *pdev;
@@ -252,7 +264,7 @@ static void rpi_register_rtc_driver(struct device *dev)
if (IS_ERR(pdev))
return;
- rpi_rtc = pdev;
+ fw->rtc_dev = pdev;
}
unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw, unsigned int id)
@@ -329,8 +341,8 @@ static int rpi_firmware_probe(struct platform_device *pdev)
rpi_firmware_print_firmware_revision(fw);
rpi_register_hwmon_driver(dev, fw);
- rpi_register_clk_driver(dev);
- rpi_register_rtc_driver(dev);
+ rpi_register_clk_driver(dev, fw);
+ rpi_register_rtc_driver(dev, fw);
return 0;
}
@@ -349,12 +361,12 @@ static void rpi_firmware_remove(struct platform_device *pdev)
{
struct rpi_firmware *fw = platform_get_drvdata(pdev);
- platform_device_unregister(rpi_hwmon);
- rpi_hwmon = NULL;
- platform_device_unregister(rpi_clk);
- rpi_clk = NULL;
- platform_device_unregister(rpi_rtc);
- rpi_rtc = NULL;
+ platform_device_unregister(fw->hwmon_dev);
+ fw->hwmon_dev = NULL;
+ platform_device_unregister(fw->clk_dev);
+ fw->clk_dev = NULL;
+ platform_device_unregister(fw->rtc_dev);
+ fw->rtc_dev = NULL;
rpi_firmware_put(fw);
}
--
2.56.0
^ permalink raw reply [flat|nested] 6+ messages in thread