From bf4f9f928bb4410f79e9900219e8ad392b25f9d4 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 0b0760ca777641..5e99fc280121c5 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(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 { + kfree(fw); + platform_set_drvdata(pdev, ERR_PTR(-ENOENT)); } - return ret; + return 0; } static int rp1_firmware_remove(struct platform_device *pdev)