Skip to content

Commit 8624145

Browse files
authored
Backport RPi patches for PIO/RP1 firmware probing errors (home-assistant#3972)
One of the reason for failures after update to OS 15.0 was missing support for the kernel PIO driver in EEPROM firmware. Backport upstream patches from raspberrypi/linux#6645 and raspberrypi/linux#6642 that handle this situation more gracefully. These patches could be dropped after the next RPi kernel release. Refs home-assistant#3943
1 parent 46441da commit 8624145

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
From ab1d73e2b5101689fcd1737e588119b4fde3a5ff Mon Sep 17 00:00:00 2001
2+
From: Phil Elwell <phil@raspberrypi.com>
3+
Date: Mon, 3 Feb 2025 14:44:08 +0000
4+
Subject: [PATCH] misc: rp1-pio: Error out on incompatible firmware
5+
6+
If the RP1 firmware has reported an error then return that from the PIO
7+
probe function, otherwise defer the probing.
8+
9+
Link: https://github.com/raspberrypi/linux/issues/6642
10+
11+
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
12+
---
13+
drivers/misc/rp1-pio.c | 11 +++++++++--
14+
1 file changed, 9 insertions(+), 2 deletions(-)
15+
16+
diff --git a/drivers/misc/rp1-pio.c b/drivers/misc/rp1-pio.c
17+
index dbf69279e313d..7e875811509f8 100644
18+
--- a/drivers/misc/rp1-pio.c
19+
+++ b/drivers/misc/rp1-pio.c
20+
@@ -1268,8 +1268,10 @@ static int rp1_pio_probe(struct platform_device *pdev)
21+
return dev_err_probe(dev, pdev->id, "alias is missing\n");
22+
23+
fw = devm_rp1_firmware_get(dev, dev->of_node);
24+
- if (IS_ERR_OR_NULL(fw))
25+
- return dev_err_probe(dev, -ENOENT, "failed to contact RP1 firmware\n");
26+
+ if (!fw)
27+
+ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find RP1 firmware driver\n");
28+
+ if (IS_ERR(fw))
29+
+ return dev_err_probe(dev, PTR_ERR(fw), "failed to contact RP1 firmware\n");
30+
ret = rp1_firmware_get_feature(fw, FOURCC_PIO, &op_base, &op_count);
31+
if (ret < 0)
32+
return ret;
33+
@@ -1346,6 +1348,11 @@ static void rp1_pio_remove(struct platform_device *pdev)
34+
35+
if (g_pio == pio)
36+
g_pio = NULL;
37+
+
38+
+ device_destroy(pio->dev_class, pio->dev_num);
39+
+ cdev_del(&pio->cdev);
40+
+ class_destroy(pio->dev_class);
41+
+ unregister_chrdev_region(pio->dev_num, 1);
42+
}
43+
44+
static const struct of_device_id rp1_pio_ids[] = {
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
From b1bcedb44c54a65a8e494158385eb23199572217 Mon Sep 17 00:00:00 2001
2+
From: Phil Elwell <phil@raspberrypi.com>
3+
Date: Mon, 3 Feb 2025 14:51:52 +0000
4+
Subject: [PATCH] firmware: rp1: Linger on firmware failure
5+
6+
To avoid pointless retries, let the probe function succeed if the
7+
firmware interface is configured correctly but the firmware is
8+
incompatible. The value of the private drvdata field holds the outcome.
9+
10+
Link: https://github.com/raspberrypi/linux/issues/6642
11+
12+
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
13+
---
14+
drivers/firmware/rp1.c | 28 ++++++++++++++--------------
15+
1 file changed, 14 insertions(+), 14 deletions(-)
16+
17+
diff --git a/drivers/firmware/rp1.c b/drivers/firmware/rp1.c
18+
index 0b0760ca77764..a258452c8b33e 100644
19+
--- a/drivers/firmware/rp1.c
20+
+++ b/drivers/firmware/rp1.c
21+
@@ -114,7 +114,8 @@ static void rp1_firmware_delete(struct kref *kref)
22+
23+
void rp1_firmware_put(struct rp1_firmware *fw)
24+
{
25+
- kref_put(&fw->consumers, rp1_firmware_delete);
26+
+ if (!IS_ERR_OR_NULL(fw))
27+
+ kref_put(&fw->consumers, rp1_firmware_delete);
28+
}
29+
EXPORT_SYMBOL_GPL(rp1_firmware_put);
30+
31+
@@ -157,7 +158,7 @@ struct rp1_firmware *rp1_firmware_get(struct device_node *client)
32+
const char *match = rp1_firmware_of_match[0].compatible;
33+
struct platform_device *pdev;
34+
struct device_node *fwnode;
35+
- struct rp1_firmware *fw;
36+
+ struct rp1_firmware *fw = NULL;
37+
38+
if (!client)
39+
return NULL;
40+
@@ -166,17 +167,17 @@ struct rp1_firmware *rp1_firmware_get(struct device_node *client)
41+
return NULL;
42+
if (!of_device_is_compatible(fwnode, match)) {
43+
of_node_put(fwnode);
44+
- return NULL;
45+
+ return ERR_PTR(-ENXIO);
46+
}
47+
48+
pdev = of_find_device_by_node(fwnode);
49+
of_node_put(fwnode);
50+
51+
if (!pdev)
52+
- goto err_exit;
53+
+ return ERR_PTR(-ENXIO);
54+
55+
fw = platform_get_drvdata(pdev);
56+
- if (!fw)
57+
+ if (IS_ERR_OR_NULL(fw))
58+
goto err_exit;
59+
60+
if (!kref_get_unless_zero(&fw->consumers))
61+
@@ -188,7 +189,7 @@ struct rp1_firmware *rp1_firmware_get(struct device_node *client)
62+
63+
err_exit:
64+
put_device(&pdev->dev);
65+
- return NULL;
66+
+ return fw;
67+
}
68+
EXPORT_SYMBOL_GPL(rp1_firmware_get);
69+
70+
@@ -204,8 +205,8 @@ struct rp1_firmware *devm_rp1_firmware_get(struct device *dev, struct device_nod
71+
int ret;
72+
73+
fw = rp1_firmware_get(client);
74+
- if (!fw)
75+
- return NULL;
76+
+ if (IS_ERR_OR_NULL(fw))
77+
+ return fw;
78+
79+
ret = devm_add_action_or_reset(dev, devm_rp1_firmware_put, fw);
80+
if (ret)
81+
@@ -270,19 +271,18 @@ static int rp1_firmware_probe(struct platform_device *pdev)
82+
init_completion(&fw->c);
83+
kref_init(&fw->consumers);
84+
85+
- platform_set_drvdata(pdev, fw);
86+
-
87+
ret = rp1_firmware_message(fw, GET_FIRMWARE_VERSION,
88+
NULL, 0, &version, sizeof(version));
89+
if (ret == sizeof(version)) {
90+
dev_info(dev, "RP1 Firmware version %08x%08x%08x%08x%08x\n",
91+
version[0], version[1], version[2], version[3], version[4]);
92+
- ret = 0;
93+
- } else if (ret >= 0) {
94+
- ret = -EIO;
95+
+ platform_set_drvdata(pdev, fw);
96+
+ } else {
97+
+ rp1_firmware_put(fw);
98+
+ platform_set_drvdata(pdev, ERR_PTR(-ENOENT));
99+
}
100+
101+
- return ret;
102+
+ return 0;
103+
}
104+
105+
static int rp1_firmware_remove(struct platform_device *pdev)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
From 97e6955cef61340165e8ec276084841d335335e9 Mon Sep 17 00:00:00 2001
2+
From: Phil Elwell <phil@raspberrypi.com>
3+
Date: Tue, 4 Feb 2025 13:18:45 +0000
4+
Subject: [PATCH] mailbox: rp1: Don't claim channels in of_xlate
5+
6+
The of_xlate method saves the calculated event mask in the con_priv
7+
field. It also rejects subsequent attempt to use that channel because
8+
the mask is non-zero, which causes a repeated instantiation of a client
9+
driver to fail.
10+
11+
The of_xlate method is not meant to be a point of resource acquisition.
12+
Leave the con_priv initialisation, but drop the test that it was
13+
previously zero.
14+
15+
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
16+
---
17+
drivers/mailbox/rp1-mailbox.c | 2 --
18+
1 file changed, 2 deletions(-)
19+
20+
diff --git a/drivers/mailbox/rp1-mailbox.c b/drivers/mailbox/rp1-mailbox.c
21+
index bf71db1dd9fae..0e8af098b62b2 100644
22+
--- a/drivers/mailbox/rp1-mailbox.c
23+
+++ b/drivers/mailbox/rp1-mailbox.c
24+
@@ -133,8 +133,6 @@ static struct mbox_chan *rp1_mbox_xlate(struct mbox_controller *mbox,
25+
return ERR_PTR(-EINVAL);
26+
27+
chan = &mbox->chans[doorbell];
28+
- if (chan->con_priv)
29+
- return ERR_PTR(-EBUSY);
30+
31+
chan->con_priv = (void *)(uintptr_t)(1 << doorbell);
32+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
From c8cf0694d8ecd5acaa03c26fc404e66dea9308fd Mon Sep 17 00:00:00 2001
2+
From: Phil Elwell <phil@raspberrypi.com>
3+
Date: Tue, 25 Feb 2025 12:16:33 +0000
4+
Subject: [PATCH] misc: rp1-pio: Demote fw probe error to warning
5+
6+
Support for the RP1 firmware mailbox API is rolling out to Pi 5 EEPROM
7+
images. For most users, the fact that the PIO is not available is no
8+
cause for alarm. Change the message to a warning, so that it does not
9+
appear with "quiet" in cmdline.txt.
10+
11+
Link: https://github.com/raspberrypi/linux/issues/6642
12+
13+
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
14+
---
15+
drivers/misc/rp1-pio.c | 6 ++++--
16+
1 file changed, 4 insertions(+), 2 deletions(-)
17+
18+
diff --git a/drivers/misc/rp1-pio.c b/drivers/misc/rp1-pio.c
19+
index 7e875811509f8..a04dc8edcf5b8 100644
20+
--- a/drivers/misc/rp1-pio.c
21+
+++ b/drivers/misc/rp1-pio.c
22+
@@ -1270,8 +1270,10 @@ static int rp1_pio_probe(struct platform_device *pdev)
23+
fw = devm_rp1_firmware_get(dev, dev->of_node);
24+
if (!fw)
25+
return dev_err_probe(dev, -EPROBE_DEFER, "failed to find RP1 firmware driver\n");
26+
- if (IS_ERR(fw))
27+
- return dev_err_probe(dev, PTR_ERR(fw), "failed to contact RP1 firmware\n");
28+
+ if (IS_ERR(fw)) {
29+
+ dev_warn(dev, "failed to contact RP1 firmware\n");
30+
+ return PTR_ERR(fw);
31+
+ }
32+
ret = rp1_firmware_get_feature(fw, FOURCC_PIO, &op_base, &op_count);
33+
if (ret < 0)
34+
return ret;

0 commit comments

Comments
 (0)