From 5e9c47a318c6a51b28b49f5320916337d21cbdf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= Date: Wed, 26 Mar 2025 16:26:44 +0100 Subject: [PATCH] Backport RPi patches for PIO/RP1 firmware probing errors (#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 #3943 --- ...o-Error-out-on-incompatible-firmware.patch | 44 ++++++++ ...mware-rp1-Linger-on-firmware-failure.patch | 105 ++++++++++++++++++ ...rp1-Don-t-claim-channels-in-of_xlate.patch | 32 ++++++ ...pio-Demote-fw-probe-error-to-warning.patch | 34 ++++++ 4 files changed, 215 insertions(+) create mode 100644 buildroot-external/board/raspberrypi/patches/linux/0005-misc-rp1-pio-Error-out-on-incompatible-firmware.patch create mode 100644 buildroot-external/board/raspberrypi/patches/linux/0006-firmware-rp1-Linger-on-firmware-failure.patch create mode 100644 buildroot-external/board/raspberrypi/patches/linux/0007-mailbox-rp1-Don-t-claim-channels-in-of_xlate.patch create mode 100644 buildroot-external/board/raspberrypi/patches/linux/0008-misc-rp1-pio-Demote-fw-probe-error-to-warning.patch diff --git a/buildroot-external/board/raspberrypi/patches/linux/0005-misc-rp1-pio-Error-out-on-incompatible-firmware.patch b/buildroot-external/board/raspberrypi/patches/linux/0005-misc-rp1-pio-Error-out-on-incompatible-firmware.patch new file mode 100644 index 000000000..eaf408bbe --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/linux/0005-misc-rp1-pio-Error-out-on-incompatible-firmware.patch @@ -0,0 +1,44 @@ +From ab1d73e2b5101689fcd1737e588119b4fde3a5ff Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 3 Feb 2025 14:44:08 +0000 +Subject: [PATCH] misc: rp1-pio: Error out on incompatible firmware + +If the RP1 firmware has reported an error then return that from the PIO +probe function, otherwise defer the probing. + +Link: https://github.com/raspberrypi/linux/issues/6642 + +Signed-off-by: Phil Elwell +--- + drivers/misc/rp1-pio.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/rp1-pio.c b/drivers/misc/rp1-pio.c +index dbf69279e313d..7e875811509f8 100644 +--- a/drivers/misc/rp1-pio.c ++++ b/drivers/misc/rp1-pio.c +@@ -1268,8 +1268,10 @@ static int rp1_pio_probe(struct platform_device *pdev) + return dev_err_probe(dev, pdev->id, "alias is missing\n"); + + fw = devm_rp1_firmware_get(dev, dev->of_node); +- if (IS_ERR_OR_NULL(fw)) +- return dev_err_probe(dev, -ENOENT, "failed to contact RP1 firmware\n"); ++ if (!fw) ++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find RP1 firmware driver\n"); ++ if (IS_ERR(fw)) ++ return dev_err_probe(dev, PTR_ERR(fw), "failed to contact RP1 firmware\n"); + ret = rp1_firmware_get_feature(fw, FOURCC_PIO, &op_base, &op_count); + if (ret < 0) + return ret; +@@ -1346,6 +1348,11 @@ static void rp1_pio_remove(struct platform_device *pdev) + + if (g_pio == pio) + g_pio = NULL; ++ ++ device_destroy(pio->dev_class, pio->dev_num); ++ cdev_del(&pio->cdev); ++ class_destroy(pio->dev_class); ++ unregister_chrdev_region(pio->dev_num, 1); + } + + static const struct of_device_id rp1_pio_ids[] = { diff --git a/buildroot-external/board/raspberrypi/patches/linux/0006-firmware-rp1-Linger-on-firmware-failure.patch b/buildroot-external/board/raspberrypi/patches/linux/0006-firmware-rp1-Linger-on-firmware-failure.patch new file mode 100644 index 000000000..6fcec2f1c --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/linux/0006-firmware-rp1-Linger-on-firmware-failure.patch @@ -0,0 +1,105 @@ +From b1bcedb44c54a65a8e494158385eb23199572217 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 3 Feb 2025 14:51:52 +0000 +Subject: [PATCH] firmware: rp1: Linger on firmware failure + +To avoid pointless retries, let the probe function succeed if the +firmware interface is configured correctly but the firmware is +incompatible. The value of the private drvdata field holds the outcome. + +Link: https://github.com/raspberrypi/linux/issues/6642 + +Signed-off-by: Phil Elwell +--- + drivers/firmware/rp1.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/firmware/rp1.c b/drivers/firmware/rp1.c +index 0b0760ca77764..a258452c8b33e 100644 +--- a/drivers/firmware/rp1.c ++++ b/drivers/firmware/rp1.c +@@ -114,7 +114,8 @@ static void rp1_firmware_delete(struct kref *kref) + + void rp1_firmware_put(struct rp1_firmware *fw) + { +- kref_put(&fw->consumers, rp1_firmware_delete); ++ if (!IS_ERR_OR_NULL(fw)) ++ kref_put(&fw->consumers, rp1_firmware_delete); + } + EXPORT_SYMBOL_GPL(rp1_firmware_put); + +@@ -157,7 +158,7 @@ struct rp1_firmware *rp1_firmware_get(struct device_node *client) + const char *match = rp1_firmware_of_match[0].compatible; + struct platform_device *pdev; + struct device_node *fwnode; +- struct rp1_firmware *fw; ++ struct rp1_firmware *fw = NULL; + + if (!client) + return NULL; +@@ -166,17 +167,17 @@ struct rp1_firmware *rp1_firmware_get(struct device_node *client) + return NULL; + if (!of_device_is_compatible(fwnode, match)) { + of_node_put(fwnode); +- return NULL; ++ return ERR_PTR(-ENXIO); + } + + pdev = of_find_device_by_node(fwnode); + of_node_put(fwnode); + + if (!pdev) +- goto err_exit; ++ return ERR_PTR(-ENXIO); + + fw = platform_get_drvdata(pdev); +- if (!fw) ++ if (IS_ERR_OR_NULL(fw)) + goto err_exit; + + if (!kref_get_unless_zero(&fw->consumers)) +@@ -188,7 +189,7 @@ struct rp1_firmware *rp1_firmware_get(struct device_node *client) + + err_exit: + put_device(&pdev->dev); +- return NULL; ++ return fw; + } + EXPORT_SYMBOL_GPL(rp1_firmware_get); + +@@ -204,8 +205,8 @@ struct rp1_firmware *devm_rp1_firmware_get(struct device *dev, struct device_nod + int ret; + + fw = rp1_firmware_get(client); +- if (!fw) +- return NULL; ++ if (IS_ERR_OR_NULL(fw)) ++ return fw; + + ret = devm_add_action_or_reset(dev, devm_rp1_firmware_put, fw); + if (ret) +@@ -270,19 +271,18 @@ static int rp1_firmware_probe(struct platform_device *pdev) + init_completion(&fw->c); + kref_init(&fw->consumers); + +- platform_set_drvdata(pdev, fw); +- + ret = rp1_firmware_message(fw, GET_FIRMWARE_VERSION, + NULL, 0, &version, sizeof(version)); + if (ret == sizeof(version)) { + dev_info(dev, "RP1 Firmware version %08x%08x%08x%08x%08x\n", + version[0], version[1], version[2], version[3], version[4]); +- ret = 0; +- } else if (ret >= 0) { +- ret = -EIO; ++ platform_set_drvdata(pdev, fw); ++ } else { ++ rp1_firmware_put(fw); ++ platform_set_drvdata(pdev, ERR_PTR(-ENOENT)); + } + +- return ret; ++ return 0; + } + + static int rp1_firmware_remove(struct platform_device *pdev) diff --git a/buildroot-external/board/raspberrypi/patches/linux/0007-mailbox-rp1-Don-t-claim-channels-in-of_xlate.patch b/buildroot-external/board/raspberrypi/patches/linux/0007-mailbox-rp1-Don-t-claim-channels-in-of_xlate.patch new file mode 100644 index 000000000..e8555f384 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/linux/0007-mailbox-rp1-Don-t-claim-channels-in-of_xlate.patch @@ -0,0 +1,32 @@ +From 97e6955cef61340165e8ec276084841d335335e9 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 4 Feb 2025 13:18:45 +0000 +Subject: [PATCH] mailbox: rp1: Don't claim channels in of_xlate + +The of_xlate method saves the calculated event mask in the con_priv +field. It also rejects subsequent attempt to use that channel because +the mask is non-zero, which causes a repeated instantiation of a client +driver to fail. + +The of_xlate method is not meant to be a point of resource acquisition. +Leave the con_priv initialisation, but drop the test that it was +previously zero. + +Signed-off-by: Phil Elwell +--- + drivers/mailbox/rp1-mailbox.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/mailbox/rp1-mailbox.c b/drivers/mailbox/rp1-mailbox.c +index bf71db1dd9fae..0e8af098b62b2 100644 +--- a/drivers/mailbox/rp1-mailbox.c ++++ b/drivers/mailbox/rp1-mailbox.c +@@ -133,8 +133,6 @@ static struct mbox_chan *rp1_mbox_xlate(struct mbox_controller *mbox, + return ERR_PTR(-EINVAL); + + chan = &mbox->chans[doorbell]; +- if (chan->con_priv) +- return ERR_PTR(-EBUSY); + + chan->con_priv = (void *)(uintptr_t)(1 << doorbell); + diff --git a/buildroot-external/board/raspberrypi/patches/linux/0008-misc-rp1-pio-Demote-fw-probe-error-to-warning.patch b/buildroot-external/board/raspberrypi/patches/linux/0008-misc-rp1-pio-Demote-fw-probe-error-to-warning.patch new file mode 100644 index 000000000..6233a3249 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/linux/0008-misc-rp1-pio-Demote-fw-probe-error-to-warning.patch @@ -0,0 +1,34 @@ +From c8cf0694d8ecd5acaa03c26fc404e66dea9308fd Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 25 Feb 2025 12:16:33 +0000 +Subject: [PATCH] misc: rp1-pio: Demote fw probe error to warning + +Support for the RP1 firmware mailbox API is rolling out to Pi 5 EEPROM +images. For most users, the fact that the PIO is not available is no +cause for alarm. Change the message to a warning, so that it does not +appear with "quiet" in cmdline.txt. + +Link: https://github.com/raspberrypi/linux/issues/6642 + +Signed-off-by: Phil Elwell +--- + drivers/misc/rp1-pio.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/rp1-pio.c b/drivers/misc/rp1-pio.c +index 7e875811509f8..a04dc8edcf5b8 100644 +--- a/drivers/misc/rp1-pio.c ++++ b/drivers/misc/rp1-pio.c +@@ -1270,8 +1270,10 @@ static int rp1_pio_probe(struct platform_device *pdev) + fw = devm_rp1_firmware_get(dev, dev->of_node); + if (!fw) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find RP1 firmware driver\n"); +- if (IS_ERR(fw)) +- return dev_err_probe(dev, PTR_ERR(fw), "failed to contact RP1 firmware\n"); ++ if (IS_ERR(fw)) { ++ dev_warn(dev, "failed to contact RP1 firmware\n"); ++ return PTR_ERR(fw); ++ } + ret = rp1_firmware_get_feature(fw, FOURCC_PIO, &op_base, &op_count); + if (ret < 0) + return ret;