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
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
46 Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
48 drivers/remoteproc/qcom_q6v5_mpd.c | 53 +++++++++++++++++-------------
49 1 file changed, 30 insertions(+), 23 deletions(-)
51 --- a/drivers/remoteproc/qcom_q6v5_mpd.c
52 +++ b/drivers/remoteproc/qcom_q6v5_mpd.c
58 #define MAX_FIRMWARE 3
60 #define RPD_SWID MPD_WCNSS_PAS_ID
62 #define UPD_BOOT_INFO_SMEM_ID 507
65 -static LIST_HEAD(upd_rproc_list);
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 {
72 const struct wcss_data *desc;
73 const char **firmware;
74 + struct userpd *upd[MAX_UPD];
78 @@ -270,13 +270,12 @@ static void *q6_wcss_da_to_va(struct rpr
80 static int share_upd_bootinfo_to_q6(struct rproc *rproc)
87 struct q6_wcss *wcss = rproc->priv;
89 - struct rproc *upd_rproc;
90 struct userpd_boot_info upd_bootinfo = {0};
91 const struct firmware *fw;
93 @@ -301,16 +300,19 @@ static int share_upd_bootinfo_to_q6(stru
94 memcpy_toio(ptr, &version, sizeof(version));
95 ptr += sizeof(version);
97 - list_for_each_entry(upd_rproc, &upd_rproc_list, node)
99 + for (i = 0; i < ARRAY_SIZE(wcss->upd); i++)
104 cnt = (sizeof(upd_bootinfo) * cnt);
105 memcpy_toio(ptr, &cnt, sizeof(u16));
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];
116 upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
117 @@ -322,14 +324,14 @@ static int share_upd_bootinfo_to_q6(stru
119 upd_bootinfo.pid = upd->pd_asid + 1;
121 - ret = request_firmware(&fw, upd_rproc->firmware, upd->dev);
122 + ret = request_firmware(&fw, upd->q6.rproc->firmware, upd->dev);
124 dev_err(upd->dev, "request_firmware failed: %d\n", ret);
129 - upd_bootinfo.bootaddr = rproc_get_boot_addr(upd_rproc, fw);
130 + upd_bootinfo.bootaddr = rproc_get_boot_addr(upd->q6.rproc, fw);
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
138 -static void q6_release_resources(void)
139 +static void q6_release_resources(struct q6_wcss *wcss)
141 - struct rproc *upd_rproc;
142 + struct userpd *upd;
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];
154 + rproc_del(upd->q6.rproc);
155 + rproc_free(upd->q6.rproc);
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)
164 @@ -633,16 +640,16 @@ static int q6_register_userpd(struct pla
168 - dev_info(&pdev->dev, "%s node found\n", userpd_np->name);
169 + dev_info(wcss->dev, "%s node found\n", userpd_np->name);
171 userpd_pdev = of_platform_device_create(userpd_np, userpd_np->name,
175 - return dev_err_probe(&pdev->dev, -ENODEV,
176 + return dev_err_probe(wcss->dev, -ENODEV,
177 "failed to create %s platform device\n",
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));
185 @@ -663,7 +670,7 @@ static int q6_register_userpd(struct pla
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);
194 @@ -728,10 +735,10 @@ static int q6_wcss_probe(struct platform
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);
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",