From 348223d1ddff76f7aee20c62cd4e0acd995fa310 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(-) --- a/drivers/firmware/rp1.c +++ b/drivers/firmware/rp1.c @@ -114,7 +114,8 @@ static void rp1_firmware_delete(struct k 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(st 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(st 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(st 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_g 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 pla 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 void rp1_firmware_remove(struct platform_device *pdev)