Skip to content

Commit 88724b7

Browse files
digetxthierryreding
authored andcommitted
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>
1 parent aeecc50 commit 88724b7

2 files changed

Lines changed: 48 additions & 17 deletions

File tree

drivers/soc/tegra/fuse/fuse-tegra.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,29 @@ static const struct nvmem_cell_info tegra_fuse_cells[] = {
182182
},
183183
};
184184

185+
static void tegra_fuse_restore(void *base)
186+
{
187+
fuse->clk = NULL;
188+
fuse->base = base;
189+
}
190+
185191
static int tegra_fuse_probe(struct platform_device *pdev)
186192
{
187193
void __iomem *base = fuse->base;
188194
struct nvmem_config nvmem;
189195
struct resource *res;
190196
int err;
191197

198+
err = devm_add_action(&pdev->dev, tegra_fuse_restore, base);
199+
if (err)
200+
return err;
201+
192202
/* take over the memory region from the early initialization */
193203
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
194204
fuse->phys = res->start;
195205
fuse->base = devm_ioremap_resource(&pdev->dev, res);
196206
if (IS_ERR(fuse->base)) {
197207
err = PTR_ERR(fuse->base);
198-
fuse->base = base;
199208
return err;
200209
}
201210

@@ -205,19 +214,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
205214
dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
206215
PTR_ERR(fuse->clk));
207216

208-
fuse->base = base;
209217
return PTR_ERR(fuse->clk);
210218
}
211219

212220
platform_set_drvdata(pdev, fuse);
213221
fuse->dev = &pdev->dev;
214222

215-
pm_runtime_enable(&pdev->dev);
223+
err = devm_pm_runtime_enable(&pdev->dev);
224+
if (err)
225+
return err;
216226

217227
if (fuse->soc->probe) {
218228
err = fuse->soc->probe(fuse);
219229
if (err < 0)
220-
goto restore;
230+
return err;
221231
}
222232

223233
memset(&nvmem, 0, sizeof(nvmem));
@@ -241,15 +251,15 @@ static int tegra_fuse_probe(struct platform_device *pdev)
241251
err = PTR_ERR(fuse->nvmem);
242252
dev_err(&pdev->dev, "failed to register NVMEM device: %d\n",
243253
err);
244-
goto restore;
254+
return err;
245255
}
246256

247257
fuse->rst = devm_reset_control_get_optional(&pdev->dev, "fuse");
248258
if (IS_ERR(fuse->rst)) {
249259
err = PTR_ERR(fuse->rst);
250260
dev_err(&pdev->dev, "failed to get FUSE reset: %pe\n",
251261
fuse->rst);
252-
goto restore;
262+
return err;
253263
}
254264

255265
/*
@@ -258,26 +268,20 @@ static int tegra_fuse_probe(struct platform_device *pdev)
258268
*/
259269
err = pm_runtime_resume_and_get(&pdev->dev);
260270
if (err)
261-
goto restore;
271+
return err;
262272

263273
err = reset_control_reset(fuse->rst);
264274
pm_runtime_put(&pdev->dev);
265275

266276
if (err < 0) {
267277
dev_err(&pdev->dev, "failed to reset FUSE: %d\n", err);
268-
goto restore;
278+
return err;
269279
}
270280

271281
/* release the early I/O memory mapping */
272282
iounmap(base);
273283

274284
return 0;
275-
276-
restore:
277-
fuse->clk = NULL;
278-
fuse->base = base;
279-
pm_runtime_disable(&pdev->dev);
280-
return err;
281285
}
282286

283287
static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev)

drivers/soc/tegra/fuse/fuse-tegra20.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,28 @@ static bool dma_filter(struct dma_chan *chan, void *filter_param)
9494
return of_device_is_compatible(np, "nvidia,tegra20-apbdma");
9595
}
9696

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+
97115
static int tegra20_fuse_probe(struct tegra_fuse *fuse)
98116
{
99117
dma_cap_mask_t mask;
118+
int err;
100119

101120
dma_cap_zero(mask);
102121
dma_cap_set(DMA_SLAVE, mask);
@@ -105,13 +124,21 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)
105124
if (!fuse->apbdma.chan)
106125
return -EPROBE_DEFER;
107126

127+
err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_release_channel,
128+
fuse);
129+
if (err)
130+
return err;
131+
108132
fuse->apbdma.virt = dma_alloc_coherent(fuse->dev, sizeof(u32),
109133
&fuse->apbdma.phys,
110134
GFP_KERNEL);
111-
if (!fuse->apbdma.virt) {
112-
dma_release_channel(fuse->apbdma.chan);
135+
if (!fuse->apbdma.virt)
113136
return -ENOMEM;
114-
}
137+
138+
err = devm_add_action_or_reset(fuse->dev, tegra20_fuse_free_coherent,
139+
fuse);
140+
if (err)
141+
return err;
115142

116143
fuse->apbdma.config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
117144
fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;

0 commit comments

Comments
 (0)