59f49ad66e90e6a6bafe9fedac1d6d6dcc7bc16b
[openwrt/staging/linusw.git] /
1 From 0fa7bdb855247b738d1d227d6f4b3417ebdf21a8 Mon Sep 17 00:00:00 2001
2 From: Ziyang Huang <hzyitc@outlook.com>
3 Date: Sun, 8 Sep 2024 16:40:12 +0800
4 Subject: [PATCH 2/2] remoteproc: qcom_q6v5_mpd: fix incorrent use of
5 rproc->node
6
7 1.817524] list_add corruption. next->prev should be prev (ffffffc0814bbfc8), but was ffffffc0814bc358. (next=ffffff8003b56800).
8 [ 1.822435] WARNING: CPU: 1 PID: 24 at lib/list_debug.c:29 __list_add_valid_or_report+0x8c/0xdc
9 [ 1.833923] Modules linked in:
10 [ 1.842425] CPU: 1 PID: 24 Comm: kworker/u4:1 Not tainted 6.6.47 #0
11 [ 1.845552] Hardware name: Qualcomm MP03 (DT)
12 [ 1.851716] Workqueue: events_unbound deferred_probe_work_func
13 [ 1.856229] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
14 [ 1.861959] pc : __list_add_valid_or_report+0x8c/0xdc
15 [ 1.868816] lr : __list_add_valid_or_report+0x8c/0xdc
16 [ 1.874022] sp : ffffffc081603a50
17 [ 1.879055] x29: ffffffc081603a50 x28: ffffff8000fa2810 x27: ffffff8003cba800
18 [ 1.882358] x26: ffffff8000fa2800 x25: ffffff8003cbac80 x24: 0000000000000000
19 [ 1.889476] x23: ffffffc08088b968 x22: ffffffc0814bb000 x21: ffffffc0814bbfc8
20 [ 1.896593] x20: ffffffc08088b8e8 x19: ffffff8003cba800 x18: 00000000000000b1
21 [ 1.903713] x17: 3863666262343138 x16: 3063666666666666 x15: ffffffc081416e20
22 [ 1.910830] x14: 0000000000000213 x13: 00000000000000b1 x12: 00000000ffffffea
23 [ 1.917948] x11: 00000000ffffefff x10: ffffffc08146ee20 x9 : ffffffc081416dc8
24 [ 1.925066] x8 : 0000000000017fe8 x7 : c0000000ffffefff x6 : 0000000000057fa8
25 [ 1.932184] x5 : 0000000000000fff x4 : 0000000000000000 x3 : ffffffc081603850
26 [ 1.939302] x2 : ffffffc081416d60 x1 : ffffffc081416d60 x0 : 0000000000000075
27 [ 1.946422] Call trace:
28 [ 1.953535] __list_add_valid_or_report+0x8c/0xdc
29 [ 1.955793] rproc_add+0x1f4/0x25c
30 [ 1.960653] q6_wcss_probe+0x510/0x634
31 [ 1.963950] platform_probe+0x68/0xc4
32 [ 1.967684] really_probe+0x148/0x2b0
33 [ 1.971417] __driver_probe_device+0x78/0x128
34 [ 1.975063] driver_probe_device+0x40/0xdc
35 [ 1.979402] __device_attach_driver+0xb8/0xf8
36 [ 1.983397] bus_for_each_drv+0x70/0xb8
37 [ 1.987823] __device_attach+0xa0/0x184
38 [ 1.991468] device_initial_probe+0x14/0x20
39 [ 1.995289] bus_probe_device+0xac/0xb0
40 [ 1.999455] deferred_probe_work_func+0xa4/0xec
41 [ 2.003275] process_one_work+0x178/0x2d4
42 [ 2.007788] worker_thread+0x2ec/0x4d8
43 [ 2.011954] kthread+0xdc/0xe0
44 [ 2.015600] ret_from_fork+0x10/0x20
45
46 Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
47 ---
48 drivers/remoteproc/qcom_q6v5_mpd.c | 53 +++++++++++++++++-------------
49 1 file changed, 30 insertions(+), 23 deletions(-)
50
51 --- a/drivers/remoteproc/qcom_q6v5_mpd.c
52 +++ b/drivers/remoteproc/qcom_q6v5_mpd.c
53 @@ -33,6 +33,7 @@
54
55 #define BUF_SIZE 35
56
57 +#define MAX_UPD 3
58 #define MAX_FIRMWARE 3
59
60 #define RPD_SWID MPD_WCNSS_PAS_ID
61 @@ -43,8 +44,6 @@
62 #define UPD_BOOT_INFO_SMEM_ID 507
63 #define VERSION2 2
64
65 -static LIST_HEAD(upd_rproc_list);
66 -
67 /**
68 * struct userpd_boot_info_header - header of user pd bootinfo
69 * @type: type of bootinfo passing over smem
70 @@ -80,6 +79,7 @@ struct q6_wcss {
71 size_t mem_size;
72 const struct wcss_data *desc;
73 const char **firmware;
74 + struct userpd *upd[MAX_UPD];
75 };
76
77 struct userpd {
78 @@ -270,13 +270,12 @@ static void *q6_wcss_da_to_va(struct rpr
79 */
80 static int share_upd_bootinfo_to_q6(struct rproc *rproc)
81 {
82 - int ret;
83 + int i, ret;
84 size_t size;
85 u16 cnt = 0, version;
86 void *ptr;
87 struct q6_wcss *wcss = rproc->priv;
88 struct userpd *upd;
89 - struct rproc *upd_rproc;
90 struct userpd_boot_info upd_bootinfo = {0};
91 const struct firmware *fw;
92
93 @@ -301,16 +300,19 @@ static int share_upd_bootinfo_to_q6(stru
94 memcpy_toio(ptr, &version, sizeof(version));
95 ptr += sizeof(version);
96
97 - list_for_each_entry(upd_rproc, &upd_rproc_list, node)
98 - cnt++;
99 + for (i = 0; i < ARRAY_SIZE(wcss->upd); i++)
100 + if (wcss->upd[i])
101 + cnt++;
102
103 /* No of elements */
104 cnt = (sizeof(upd_bootinfo) * cnt);
105 memcpy_toio(ptr, &cnt, sizeof(u16));
106 ptr += sizeof(u16);
107
108 - list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
109 - upd = upd_rproc->priv;
110 + for (i = 0; i < ARRAY_SIZE(wcss->upd); i++) {
111 + upd = wcss->upd[i];
112 + if (!upd)
113 + continue;
114
115 /* TYPE */
116 upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
117 @@ -322,14 +324,14 @@ static int share_upd_bootinfo_to_q6(stru
118 /* Process ID */
119 upd_bootinfo.pid = upd->pd_asid + 1;
120
121 - ret = request_firmware(&fw, upd_rproc->firmware, upd->dev);
122 + ret = request_firmware(&fw, upd->q6.rproc->firmware, upd->dev);
123 if (ret < 0) {
124 dev_err(upd->dev, "request_firmware failed: %d\n", ret);
125 return ret;
126 }
127
128 /* Load address */
129 - upd_bootinfo.bootaddr = rproc_get_boot_addr(upd_rproc, fw);
130 + upd_bootinfo.bootaddr = rproc_get_boot_addr(upd->q6.rproc, fw);
131
132 /* Firmware mem size */
133 upd_bootinfo.data_size = qcom_mdt_get_size(fw);
134 @@ -597,18 +599,23 @@ static int init_irq(struct qcom_q6v5 *q6
135 return 0;
136 }
137
138 -static void q6_release_resources(void)
139 +static void q6_release_resources(struct q6_wcss *wcss)
140 {
141 - struct rproc *upd_rproc;
142 + struct userpd *upd;
143 + int i;
144
145 /* Release userpd resources */
146 - list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
147 - rproc_del(upd_rproc);
148 - rproc_free(upd_rproc);
149 + for (i = 0; i < ARRAY_SIZE(wcss->upd); i++) {
150 + upd = wcss->upd[i];
151 + if (!upd)
152 + continue;
153 +
154 + rproc_del(upd->q6.rproc);
155 + rproc_free(upd->q6.rproc);
156 }
157 }
158
159 -static int q6_register_userpd(struct platform_device *pdev,
160 +static int q6_register_userpd(struct q6_wcss *wcss,
161 struct device_node *userpd_np)
162 {
163 struct userpd *upd;
164 @@ -633,16 +640,16 @@ static int q6_register_userpd(struct pla
165 return ret;
166 }
167
168 - dev_info(&pdev->dev, "%s node found\n", userpd_np->name);
169 + dev_info(wcss->dev, "%s node found\n", userpd_np->name);
170
171 userpd_pdev = of_platform_device_create(userpd_np, userpd_np->name,
172 - &pdev->dev);
173 + wcss->dev);
174 if (!userpd_pdev)
175 - return dev_err_probe(&pdev->dev, -ENODEV,
176 + return dev_err_probe(wcss->dev, -ENODEV,
177 "failed to create %s platform device\n",
178 userpd_np->name);
179
180 - userpd_pdev->dev.driver = pdev->dev.driver;
181 + userpd_pdev->dev.driver = wcss->dev->driver;
182 rproc = rproc_alloc(&userpd_pdev->dev, userpd_pdev->name, &wcss_ops,
183 firmware_name, sizeof(*upd));
184 if (!rproc) {
185 @@ -663,7 +670,7 @@ static int q6_register_userpd(struct pla
186 if (ret)
187 goto free_rproc;
188
189 - list_add(&rproc->node, &upd_rproc_list);
190 + wcss->upd[upd->pd_asid] = upd;
191 platform_set_drvdata(userpd_pdev, rproc);
192 qcom_add_ssr_subdev(rproc, &upd->ssr_subdev, userpd_pdev->name);
193 return 0;
194 @@ -728,10 +735,10 @@ static int q6_wcss_probe(struct platform
195
196 /* Iterate over userpd child's and register with rproc */
197 for_each_available_child_of_node(pdev->dev.of_node, userpd_np) {
198 - ret = q6_register_userpd(pdev, userpd_np);
199 + ret = q6_register_userpd(wcss, userpd_np);
200 if (ret) {
201 /* release resources of successfully allocated userpd rproc's */
202 - q6_release_resources();
203 + q6_release_resources(wcss);
204 return dev_err_probe(&pdev->dev, ret,
205 "Failed to register userpd(%s)\n",
206 userpd_np->name);