]>
Commit | Line | Data |
---|---|---|
91861a69 SL |
1 | From 1393c7e9604122f58fccdbdb06f3ee989a6859f9 Mon Sep 17 00:00:00 2001 |
2 | From: Timo Alho <talho@nvidia.com> | |
3 | Date: Sun, 30 Dec 2018 17:58:08 +0200 | |
4 | Subject: soc/tegra: fuse: Fix illegal free of IO base address | |
5 | ||
6 | [ Upstream commit 51294bf6b9e897d595466dcda5a3f2751906a200 ] | |
7 | ||
8 | On cases where device tree entries for fuse and clock provider are in | |
9 | different order, fuse driver needs to defer probing. This leads to | |
10 | freeing incorrect IO base address as the fuse->base variable gets | |
11 | overwritten once during first probe invocation. This leads to the | |
12 | following spew during boot: | |
13 | ||
14 | [ 3.082285] Trying to vfree() nonexistent vm area (00000000cfe8fd94) | |
15 | [ 3.082308] WARNING: CPU: 5 PID: 126 at /hdd/l4t/kernel/stable/mm/vmalloc.c:1511 __vunmap+0xcc/0xd8 | |
16 | [ 3.082318] Modules linked in: | |
17 | [ 3.082330] CPU: 5 PID: 126 Comm: kworker/5:1 Tainted: G S 4.19.7-tegra-gce119d3 #1 | |
18 | [ 3.082340] Hardware name: quill (DT) | |
19 | [ 3.082353] Workqueue: events deferred_probe_work_func | |
20 | [ 3.082364] pstate: 40000005 (nZcv daif -PAN -UAO) | |
21 | [ 3.082372] pc : __vunmap+0xcc/0xd8 | |
22 | [ 3.082379] lr : __vunmap+0xcc/0xd8 | |
23 | [ 3.082385] sp : ffff00000a1d3b60 | |
24 | [ 3.082391] x29: ffff00000a1d3b60 x28: 0000000000000000 | |
25 | [ 3.082402] x27: 0000000000000000 x26: ffff000008e8b610 | |
26 | [ 3.082413] x25: 0000000000000000 x24: 0000000000000009 | |
27 | [ 3.082423] x23: ffff000009221a90 x22: ffff000009f6d000 | |
28 | [ 3.082432] x21: 0000000000000000 x20: 0000000000000000 | |
29 | [ 3.082442] x19: ffff000009f6d000 x18: ffffffffffffffff | |
30 | [ 3.082452] x17: 0000000000000000 x16: 0000000000000000 | |
31 | [ 3.082462] x15: ffff0000091396c8 x14: 0720072007200720 | |
32 | [ 3.082471] x13: 0720072007200720 x12: 0720072907340739 | |
33 | [ 3.082481] x11: 0764076607380765 x10: 0766076307300730 | |
34 | [ 3.082491] x9 : 0730073007300730 x8 : 0730073007280720 | |
35 | [ 3.082501] x7 : 0761076507720761 x6 : 0000000000000102 | |
36 | [ 3.082510] x5 : 0000000000000000 x4 : 0000000000000000 | |
37 | [ 3.082519] x3 : ffffffffffffffff x2 : ffff000009150ff8 | |
38 | [ 3.082528] x1 : 3d95b1429fff5200 x0 : 0000000000000000 | |
39 | [ 3.082538] Call trace: | |
40 | [ 3.082545] __vunmap+0xcc/0xd8 | |
41 | [ 3.082552] vunmap+0x24/0x30 | |
42 | [ 3.082561] __iounmap+0x2c/0x38 | |
43 | [ 3.082569] tegra_fuse_probe+0xc8/0x118 | |
44 | [ 3.082577] platform_drv_probe+0x50/0xa0 | |
45 | [ 3.082585] really_probe+0x1b0/0x288 | |
46 | [ 3.082593] driver_probe_device+0x58/0x100 | |
47 | [ 3.082601] __device_attach_driver+0x98/0xf0 | |
48 | [ 3.082609] bus_for_each_drv+0x64/0xc8 | |
49 | [ 3.082616] __device_attach+0xd8/0x130 | |
50 | [ 3.082624] device_initial_probe+0x10/0x18 | |
51 | [ 3.082631] bus_probe_device+0x90/0x98 | |
52 | [ 3.082638] deferred_probe_work_func+0x74/0xb0 | |
53 | [ 3.082649] process_one_work+0x1e0/0x318 | |
54 | [ 3.082656] worker_thread+0x228/0x450 | |
55 | [ 3.082664] kthread+0x128/0x130 | |
56 | [ 3.082672] ret_from_fork+0x10/0x18 | |
57 | [ 3.082678] ---[ end trace 0810fe6ba772c1c7 ]--- | |
58 | ||
59 | Fix this by retaining the value of fuse->base until driver has | |
60 | successfully probed. | |
61 | ||
62 | Signed-off-by: Timo Alho <talho@nvidia.com> | |
63 | Acked-by: Jon Hunter <jonathanh@nvidia.com> | |
64 | Signed-off-by: Thierry Reding <treding@nvidia.com> | |
65 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
66 | --- | |
67 | drivers/soc/tegra/fuse/fuse-tegra.c | 12 +++++++++--- | |
68 | 1 file changed, 9 insertions(+), 3 deletions(-) | |
69 | ||
70 | diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c | |
71 | index de2c1bfe28b5..c4f5e5bbb8dc 100644 | |
72 | --- a/drivers/soc/tegra/fuse/fuse-tegra.c | |
73 | +++ b/drivers/soc/tegra/fuse/fuse-tegra.c | |
74 | @@ -131,13 +131,17 @@ static int tegra_fuse_probe(struct platform_device *pdev) | |
75 | /* take over the memory region from the early initialization */ | |
76 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
77 | fuse->base = devm_ioremap_resource(&pdev->dev, res); | |
78 | - if (IS_ERR(fuse->base)) | |
79 | - return PTR_ERR(fuse->base); | |
80 | + if (IS_ERR(fuse->base)) { | |
81 | + err = PTR_ERR(fuse->base); | |
82 | + fuse->base = base; | |
83 | + return err; | |
84 | + } | |
85 | ||
86 | fuse->clk = devm_clk_get(&pdev->dev, "fuse"); | |
87 | if (IS_ERR(fuse->clk)) { | |
88 | dev_err(&pdev->dev, "failed to get FUSE clock: %ld", | |
89 | PTR_ERR(fuse->clk)); | |
90 | + fuse->base = base; | |
91 | return PTR_ERR(fuse->clk); | |
92 | } | |
93 | ||
94 | @@ -146,8 +150,10 @@ static int tegra_fuse_probe(struct platform_device *pdev) | |
95 | ||
96 | if (fuse->soc->probe) { | |
97 | err = fuse->soc->probe(fuse); | |
98 | - if (err < 0) | |
99 | + if (err < 0) { | |
100 | + fuse->base = base; | |
101 | return err; | |
102 | + } | |
103 | } | |
104 | ||
105 | if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size, | |
106 | -- | |
107 | 2.19.1 | |
108 |