Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc/tegra: fuse: Use resource-managed helpers

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 <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Dmitry Osipenko and committed by
Thierry Reding
88724b78 aeecc50a

+48 -17
+18 -14
drivers/soc/tegra/fuse/fuse-tegra.c
··· 182 182 }, 183 183 }; 184 184 185 + static void tegra_fuse_restore(void *base) 186 + { 187 + fuse->clk = NULL; 188 + fuse->base = base; 189 + } 190 + 185 191 static int tegra_fuse_probe(struct platform_device *pdev) 186 192 { 187 193 void __iomem *base = fuse->base; ··· 195 189 struct resource *res; 196 190 int err; 197 191 192 + err = devm_add_action(&pdev->dev, tegra_fuse_restore, base); 193 + if (err) 194 + return err; 195 + 198 196 /* take over the memory region from the early initialization */ 199 197 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 200 198 fuse->phys = res->start; 201 199 fuse->base = devm_ioremap_resource(&pdev->dev, res); 202 200 if (IS_ERR(fuse->base)) { 203 201 err = PTR_ERR(fuse->base); 204 - fuse->base = base; 205 202 return err; 206 203 } 207 204 ··· 214 205 dev_err(&pdev->dev, "failed to get FUSE clock: %ld", 215 206 PTR_ERR(fuse->clk)); 216 207 217 - fuse->base = base; 218 208 return PTR_ERR(fuse->clk); 219 209 } 220 210 221 211 platform_set_drvdata(pdev, fuse); 222 212 fuse->dev = &pdev->dev; 223 213 224 - pm_runtime_enable(&pdev->dev); 214 + err = devm_pm_runtime_enable(&pdev->dev); 215 + if (err) 216 + return err; 225 217 226 218 if (fuse->soc->probe) { 227 219 err = fuse->soc->probe(fuse); 228 220 if (err < 0) 229 - goto restore; 221 + return err; 230 222 } 231 223 232 224 memset(&nvmem, 0, sizeof(nvmem)); ··· 251 241 err = PTR_ERR(fuse->nvmem); 252 242 dev_err(&pdev->dev, "failed to register NVMEM device: %d\n", 253 243 err); 254 - goto restore; 244 + return err; 255 245 } 256 246 257 247 fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse"); ··· 259 249 err = PTR_ERR(fuse->rst); 260 250 dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n", 261 251 fuse->rst); 262 - goto restore; 252 + return err; 263 253 } 264 254 265 255 /* ··· 268 258 */ 269 259 err = pm_runtime_resume_and_get(&pdev->dev); 270 260 if (err) 271 - goto restore; 261 + return err; 272 262 273 263 err = reset_control_reset(fuse->rst); 274 264 pm_runtime_put(&pdev->dev); 275 265 276 266 if (err < 0) { 277 267 dev_err(&pdev->dev, "failed to reset FUSE: %d\n", err); 278 - goto restore; 268 + return err; 279 269 } 280 270 281 271 /* release the early I/O memory mapping */ 282 272 iounmap(base); 283 273 284 274 return 0; 285 - 286 - restore: 287 - fuse->clk = NULL; 288 - fuse->base = base; 289 - pm_runtime_disable(&pdev->dev); 290 - return err; 291 275 } 292 276 293 277 static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)
+30 -3
drivers/soc/tegra/fuse/fuse-tegra20.c
··· 94 94 return of_device_is_compatible(np, "nvidia,tegra20-apbdma"); 95 95 } 96 96 97 + static void tegra20_fuse_release_channel(void *data) 98 + { 99 + struct tegra_fuse *fuse = data; 100 + 101 + dma_release_channel(fuse->apbdma.chan); 102 + fuse->apbdma.chan = NULL; 103 + } 104 + 105 + static void tegra20_fuse_free_coherent(void *data) 106 + { 107 + struct tegra_fuse *fuse = data; 108 + 109 + dma_free_coherent(fuse->dev, sizeof(u32), fuse->apbdma.virt, 110 + fuse->apbdma.phys); 111 + fuse->apbdma.virt = NULL; 112 + fuse->apbdma.phys = 0x0; 113 + } 114 + 97 115 static int tegra20_fuse_probe(struct tegra_fuse *fuse) 98 116 { 99 117 dma_cap_mask_t mask; 118 + int err; 100 119 101 120 dma_cap_zero(mask); 102 121 dma_cap_set(DMA_SLAVE, mask); ··· 124 105 if (!fuse->apbdma.chan) 125 106 return -EPROBE_DEFER; 126 107 108 + err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_release_channel, 109 + fuse); 110 + if (err) 111 + return err; 112 + 127 113 fuse->apbdma.virt = dma_alloc_coherent(fuse->dev, sizeof(u32), 128 114 &fuse->apbdma.phys, 129 115 GFP_KERNEL); 130 - if (!fuse->apbdma.virt) { 131 - dma_release_channel(fuse->apbdma.chan); 116 + if (!fuse->apbdma.virt) 132 117 return -ENOMEM; 133 - } 118 + 119 + err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_free_coherent, 120 + fuse); 121 + if (err) 122 + return err; 134 123 135 124 fuse->apbdma.config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 136 125 fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;