1
0
mirror of https://github.com/home-assistant/operating-system.git synced 2025-12-19 18:08:29 +00:00
Files
operating-system/buildroot-external/board/raspberrypi/patches/linux/0006-firmware-rp1-Linger-on-firmware-failure.patch
Jan Čermák 5e9c47a318 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
2025-03-26 16:26:44 +01:00

106 lines
3.0 KiB
Diff

From b1bcedb44c54a65a8e494158385eb23199572217 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
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 <phil@raspberrypi.com>
---
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)