Use resource-managed helpers to make code cleaner and more correct,
properly releasing all resources in case of driver probe error.

Signed-off-by: Dmitry Osipenko <dig...@gmail.com>
---
 drivers/soc/tegra/fuse/fuse-tegra.c   | 32 ++++++++++++++------------
 drivers/soc/tegra/fuse/fuse-tegra20.c | 33 ++++++++++++++++++++++++---
 2 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c 
b/drivers/soc/tegra/fuse/fuse-tegra.c
index cc032729a143..fe4f935ce73a 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -182,6 +182,12 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = {
        },
 };
 
+static void tegra_fuse_restore(void *base)
+{
+       fuse->clk = NULL;
+       fuse->base = base;
+}
+
 static int tegra_fuse_probe(struct platform_device *pdev)
 {
        void __iomem *base = fuse->base;
@@ -189,13 +195,16 @@ static int tegra_fuse_probe(struct platform_device *pdev)
        struct resource *res;
        int err;
 
+       err = devm_add_action(&pdev->dev, tegra_fuse_restore, base);
+       if (err)
+               return err;
+
        /* take over the memory region from the early initialization */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        fuse->phys = res->start;
        fuse->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(fuse->base)) {
                err = PTR_ERR(fuse->base);
-               fuse->base = base;
                return err;
        }
 
@@ -205,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
                                PTR_ERR(fuse->clk));
 
-               fuse->base = base;
                return PTR_ERR(fuse->clk);
        }
 
        platform_set_drvdata(pdev, fuse);
        fuse->dev = &pdev->dev;
 
-       pm_runtime_enable(&pdev->dev);
+       err = devm_pm_runtime_enable(&pdev->dev);
+       if (err)
+               return err;
 
        if (fuse->soc->probe) {
                err = fuse->soc->probe(fuse);
                if (err < 0)
-                       goto restore;
+                       return err;
        }
 
        memset(&nvmem, 0, sizeof(nvmem));
@@ -241,7 +251,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
                err = PTR_ERR(fuse->nvmem);
                dev_err(&pdev->dev, "failed to register NVMEM device: %d\n",
                        err);
-               goto restore;
+               return err;
        }
 
        fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse");
@@ -249,7 +259,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
                err = PTR_ERR(fuse->rst);
                dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n",
                        fuse->rst);
-               goto restore;
+               return err;
        }
 
        /*
@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
         */
        err = pm_runtime_resume_and_get(&pdev->dev);
        if (err)
-               goto restore;
+               return err;
 
        err = reset_control_reset(fuse->rst);
        pm_runtime_put(&pdev->dev);
 
        if (err < 0) {
                dev_err(&pdev->dev, "failed to reset FUSE: %d\n", err);
-               goto restore;
+               return err;
        }
 
        /* release the early I/O memory mapping */
        iounmap(base);
 
        return 0;
-
-restore:
-       fuse->clk = NULL;
-       fuse->base = base;
-       pm_runtime_disable(&pdev->dev);
-       return err;
 }
 
 static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c 
b/drivers/soc/tegra/fuse/fuse-tegra20.c
index 8ec9fc5e5e4b..12503f563e36 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra20.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void 
*filter_param)
        return of_device_is_compatible(np, "nvidia,tegra20-apbdma");
 }
 
+static void tegra20_fuse_release_channel(void *data)
+{
+       struct tegra_fuse *fuse = data;
+
+       dma_release_channel(fuse->apbdma.chan);
+       fuse->apbdma.chan = NULL;
+}
+
+static void tegra20_fuse_free_coherent(void *data)
+{
+       struct tegra_fuse *fuse = data;
+
+       dma_free_coherent(fuse->dev, sizeof(u32), fuse->apbdma.virt,
+                         fuse->apbdma.phys);
+       fuse->apbdma.virt = NULL;
+       fuse->apbdma.phys = 0x0;
+}
+
 static int tegra20_fuse_probe(struct tegra_fuse *fuse)
 {
        dma_cap_mask_t mask;
+       int err;
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)
        if (!fuse->apbdma.chan)
                return -EPROBE_DEFER;
 
+       err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_release_channel,
+                                      fuse);
+       if (err)
+               return err;
+
        fuse->apbdma.virt = dma_alloc_coherent(fuse->dev, sizeof(u32),
                                               &fuse->apbdma.phys,
                                               GFP_KERNEL);
-       if (!fuse->apbdma.virt) {
-               dma_release_channel(fuse->apbdma.chan);
+       if (!fuse->apbdma.virt)
                return -ENOMEM;
-       }
+
+       err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_free_coherent,
+                                      fuse);
+       if (err)
+               return err;
 
        fuse->apbdma.config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-- 
2.32.0

Reply via email to