Skip to content

Commit 8e8d68b

Browse files
committed
Backport RPi patches for PIO/RP1 firmware probing errors
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 #3943
1 parent ab6214b commit 8e8d68b

4 files changed

+215
-0
lines changed
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 <[email protected]>
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 <[email protected]>
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[] = {
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 <[email protected]>
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 <[email protected]>
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)
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 <[email protected]>
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 <[email protected]>
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+
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 <[email protected]>
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 <[email protected]>
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)