efab833cf7ec49f18a60c12c0bca138e0eac9a08
[openwrt/staging/ldir.git] /
1 From 1ffba0c4d1122688268e59832a5e2bbc0917cac7 Mon Sep 17 00:00:00 2001
2 From: Camelia Groza <camelia.groza@nxp.com>
3 Date: Wed, 3 Oct 2018 16:37:06 +0300
4 Subject: [PATCH] sdk_dpaa: ceetm: avoid double frees on error paths
5
6 The stack calls the destroy() callback when a qdisc init() fails.
7 We stop calling it ourselves and trust the stack do the cleanup.
8
9 Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
10 ---
11 .../ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c | 94 ++++++++--------------
12 1 file changed, 34 insertions(+), 60 deletions(-)
13
14 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c
15 +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_ceetm.c
16 @@ -687,16 +687,13 @@ static int ceetm_init_root(struct Qdisc
17
18 /* Validate inputs */
19 if (sch->parent != TC_H_ROOT) {
20 - pr_err("CEETM: a root ceetm qdisc can not be attached to a class\n");
21 - tcf_block_put(priv->block);
22 - qdisc_class_hash_destroy(&priv->clhash);
23 + pr_err("CEETM: a root ceetm qdisc must be root\n");
24 return -EINVAL;
25 }
26
27 if (!mac_dev) {
28 pr_err("CEETM: the interface is lacking a mac\n");
29 - err = -EINVAL;
30 - goto err_init_root;
31 + return -EINVAL;
32 }
33
34 /* Pre-allocate underlying pfifo qdiscs.
35 @@ -713,8 +710,7 @@ static int ceetm_init_root(struct Qdisc
36 sizeof(priv->root.qdiscs[0]),
37 GFP_KERNEL);
38 if (!priv->root.qdiscs) {
39 - err = -ENOMEM;
40 - goto err_init_root;
41 + return -ENOMEM;
42 }
43
44 for (i = 0; i < dev->num_tx_queues; i++) {
45 @@ -724,10 +720,8 @@ static int ceetm_init_root(struct Qdisc
46
47 qdisc = qdisc_create_dflt(dev_queue, &pfifo_qdisc_ops,
48 parent_id, extack);
49 - if (!qdisc) {
50 - err = -ENOMEM;
51 - goto err_init_root;
52 - }
53 + if (!qdisc)
54 + return -ENOMEM;
55
56 priv->root.qdiscs[i] = qdisc;
57 qdisc->flags |= TCQ_F_ONETXQUEUE;
58 @@ -739,8 +733,7 @@ static int ceetm_init_root(struct Qdisc
59 if (!priv->root.qstats) {
60 pr_err(KBUILD_BASENAME " : %s : alloc_percpu() failed\n",
61 __func__);
62 - err = -ENOMEM;
63 - goto err_init_root;
64 + return -ENOMEM;
65 }
66
67 priv->shaped = qopt->shaped;
68 @@ -754,7 +747,7 @@ static int ceetm_init_root(struct Qdisc
69 if (err) {
70 pr_err(KBUILD_BASENAME " : %s : failed to claim the SP\n",
71 __func__);
72 - goto err_init_root;
73 + return err;
74 }
75
76 priv->root.sp = sp;
77 @@ -766,7 +759,7 @@ static int ceetm_init_root(struct Qdisc
78 if (err) {
79 pr_err(KBUILD_BASENAME " : %s : failed to claim the LNI\n",
80 __func__);
81 - goto err_init_root;
82 + return err;
83 }
84
85 priv->root.lni = lni;
86 @@ -775,7 +768,7 @@ static int ceetm_init_root(struct Qdisc
87 if (err) {
88 pr_err(KBUILD_BASENAME " : %s : failed to link the SP and LNI\n",
89 __func__);
90 - goto err_init_root;
91 + return err;
92 }
93
94 lni->sp = sp;
95 @@ -786,7 +779,7 @@ static int ceetm_init_root(struct Qdisc
96 if (err) {
97 pr_err(KBUILD_BASENAME " : %s : failed to configure the LNI shaper\n",
98 __func__);
99 - goto err_init_root;
100 + return err;
101 }
102
103 bps = priv->root.rate << 3; /* Bps -> bps */
104 @@ -794,7 +787,7 @@ static int ceetm_init_root(struct Qdisc
105 if (err) {
106 pr_err(KBUILD_BASENAME " : %s : failed to configure the LNI shaper\n",
107 __func__);
108 - goto err_init_root;
109 + return err;
110 }
111
112 bps = priv->root.ceil << 3; /* Bps -> bps */
113 @@ -802,7 +795,7 @@ static int ceetm_init_root(struct Qdisc
114 if (err) {
115 pr_err(KBUILD_BASENAME " : %s : failed to configure the LNI shaper\n",
116 __func__);
117 - goto err_init_root;
118 + return err;
119 }
120 }
121
122 @@ -810,10 +803,6 @@ static int ceetm_init_root(struct Qdisc
123
124 dpa_enable_ceetm(dev);
125 return 0;
126 -
127 -err_init_root:
128 - ceetm_destroy(sch);
129 - return err;
130 }
131
132 /* Configure a prio ceetm qdisc */
133 @@ -830,15 +819,13 @@ static int ceetm_init_prio(struct Qdisc
134
135 if (sch->parent == TC_H_ROOT) {
136 pr_err("CEETM: a prio ceetm qdisc can not be root\n");
137 - err = -EINVAL;
138 - goto err_init_prio;
139 + return -EINVAL;
140 }
141
142 parent_qdisc = qdisc_lookup(dev, TC_H_MAJ(sch->parent));
143 if (strcmp(parent_qdisc->ops->id, ceetm_qdisc_ops.id)) {
144 pr_err("CEETM: a ceetm qdisc can not be attached to other qdisc/class types\n");
145 - err = -EINVAL;
146 - goto err_init_prio;
147 + return -EINVAL;
148 }
149
150 /* Obtain the parent root ceetm_class */
151 @@ -846,8 +833,7 @@ static int ceetm_init_prio(struct Qdisc
152
153 if (!parent_cl || parent_cl->type != CEETM_ROOT) {
154 pr_err("CEETM: a prio ceetm qdiscs can be added only under a root ceetm class\n");
155 - err = -EINVAL;
156 - goto err_init_prio;
157 + return -EINVAL;
158 }
159
160 priv->prio.parent = parent_cl;
161 @@ -863,8 +849,7 @@ static int ceetm_init_prio(struct Qdisc
162 if (!child_cl) {
163 pr_err(KBUILD_BASENAME " : %s : kzalloc() failed\n",
164 __func__);
165 - err = -ENOMEM;
166 - goto err_init_prio;
167 + return -ENOMEM;
168 }
169
170 child_cl->prio.cstats = alloc_percpu(struct ceetm_class_stats);
171 @@ -907,8 +892,7 @@ static int ceetm_init_prio(struct Qdisc
172
173 err_init_prio_cls:
174 ceetm_cls_destroy(sch, child_cl);
175 -err_init_prio:
176 - ceetm_destroy(sch);
177 + /* Note: ceetm_destroy() will be called by our caller */
178 return err;
179 }
180
181 @@ -928,16 +912,14 @@ static int ceetm_init_wbfs(struct Qdisc
182 /* Validate inputs */
183 if (sch->parent == TC_H_ROOT) {
184 pr_err("CEETM: a wbfs ceetm qdiscs can not be root\n");
185 - err = -EINVAL;
186 - goto err_init_wbfs;
187 + return -EINVAL;
188 }
189
190 /* Obtain the parent prio ceetm qdisc */
191 parent_qdisc = qdisc_lookup(dev, TC_H_MAJ(sch->parent));
192 if (strcmp(parent_qdisc->ops->id, ceetm_qdisc_ops.id)) {
193 pr_err("CEETM: a ceetm qdisc can not be attached to other qdisc/class types\n");
194 - err = -EINVAL;
195 - goto err_init_wbfs;
196 + return -EINVAL;
197 }
198
199 /* Obtain the parent prio ceetm class */
200 @@ -946,28 +928,24 @@ static int ceetm_init_wbfs(struct Qdisc
201
202 if (!parent_cl || parent_cl->type != CEETM_PRIO) {
203 pr_err("CEETM: a wbfs ceetm qdiscs can be added only under a prio ceetm class\n");
204 - err = -EINVAL;
205 - goto err_init_wbfs;
206 + return -EINVAL;
207 }
208
209 if (!qopt->qcount || !qopt->qweight[0]) {
210 pr_err("CEETM: qcount and qweight are mandatory for a wbfs ceetm qdisc\n");
211 - err = -EINVAL;
212 - goto err_init_wbfs;
213 + return -EINVAL;
214 }
215
216 priv->shaped = parent_cl->shaped;
217
218 if (!priv->shaped && (qopt->cr || qopt->er)) {
219 pr_err("CEETM: CR/ER can be enabled only for shaped wbfs ceetm qdiscs\n");
220 - err = -EINVAL;
221 - goto err_init_wbfs;
222 + return -EINVAL;
223 }
224
225 if (priv->shaped && !(qopt->cr || qopt->er)) {
226 pr_err("CEETM: either CR or ER must be enabled for shaped wbfs ceetm qdiscs\n");
227 - err = -EINVAL;
228 - goto err_init_wbfs;
229 + return -EINVAL;
230 }
231
232 /* Obtain the parent root ceetm class */
233 @@ -975,16 +953,14 @@ static int ceetm_init_wbfs(struct Qdisc
234 if ((root_cl->root.wbfs_grp_a && root_cl->root.wbfs_grp_b) ||
235 root_cl->root.wbfs_grp_large) {
236 pr_err("CEETM: no more wbfs classes are available\n");
237 - err = -EINVAL;
238 - goto err_init_wbfs;
239 + return -EINVAL;
240 }
241
242 if ((root_cl->root.wbfs_grp_a || root_cl->root.wbfs_grp_b) &&
243 qopt->qcount == CEETM_MAX_WBFS_QCOUNT) {
244 pr_err("CEETM: only %d wbfs classes are available\n",
245 CEETM_MIN_WBFS_QCOUNT);
246 - err = -EINVAL;
247 - goto err_init_wbfs;
248 + return -EINVAL;
249 }
250
251 priv->wbfs.parent = parent_cl;
252 @@ -1013,7 +989,7 @@ static int ceetm_init_wbfs(struct Qdisc
253 if (err) {
254 pr_err(KBUILD_BASENAME " : %s : failed to get group details\n",
255 __func__);
256 - goto err_init_wbfs;
257 + return err;
258 }
259
260 small_group = true;
261 @@ -1031,7 +1007,7 @@ static int ceetm_init_wbfs(struct Qdisc
262 if (err) {
263 pr_err(KBUILD_BASENAME " : %s : failed to get group details\n",
264 __func__);
265 - goto err_init_wbfs;
266 + return err;
267 }
268
269 small_group = true;
270 @@ -1044,7 +1020,7 @@ static int ceetm_init_wbfs(struct Qdisc
271 err = qman_ceetm_channel_set_group(priv->wbfs.ch, small_group, prio_a,
272 prio_b);
273 if (err)
274 - goto err_init_wbfs;
275 + return err;
276
277 if (priv->shaped) {
278 err = qman_ceetm_channel_set_group_cr_eligibility(priv->wbfs.ch,
279 @@ -1053,7 +1029,7 @@ static int ceetm_init_wbfs(struct Qdisc
280 if (err) {
281 pr_err(KBUILD_BASENAME " : %s : failed to set group CR eligibility\n",
282 __func__);
283 - goto err_init_wbfs;
284 + return err;
285 }
286
287 err = qman_ceetm_channel_set_group_er_eligibility(priv->wbfs.ch,
288 @@ -1062,7 +1038,7 @@ static int ceetm_init_wbfs(struct Qdisc
289 if (err) {
290 pr_err(KBUILD_BASENAME " : %s : failed to set group ER eligibility\n",
291 __func__);
292 - goto err_init_wbfs;
293 + return err;
294 }
295 }
296
297 @@ -1072,8 +1048,7 @@ static int ceetm_init_wbfs(struct Qdisc
298 if (!child_cl) {
299 pr_err(KBUILD_BASENAME " : %s : kzalloc() failed\n",
300 __func__);
301 - err = -ENOMEM;
302 - goto err_init_wbfs;
303 + return -ENOMEM;
304 }
305
306 child_cl->wbfs.cstats = alloc_percpu(struct ceetm_class_stats);
307 @@ -1130,8 +1105,7 @@ static int ceetm_init_wbfs(struct Qdisc
308
309 err_init_wbfs_cls:
310 ceetm_cls_destroy(sch, child_cl);
311 -err_init_wbfs:
312 - ceetm_destroy(sch);
313 + /* Note: ceetm_destroy() will be called by our caller */
314 return err;
315 }
316
317 @@ -1202,7 +1176,7 @@ static int ceetm_init(struct Qdisc *sch,
318 break;
319 default:
320 pr_err(KBUILD_BASENAME " : %s : invalid qdisc\n", __func__);
321 - ceetm_destroy(sch);
322 + /* Note: ceetm_destroy() will be called by our caller */
323 ret = -EINVAL;
324 }
325
326 @@ -1549,7 +1523,7 @@ static int ceetm_cls_change(struct Qdisc
327 }
328
329 if (!cl && priv->type != CEETM_ROOT) {
330 - pr_err("CEETM: only root ceetm classes can be attached to the root ceetm qdisc\n");
331 + pr_err("CEETM: root ceetm classes can be attached to the root ceetm qdisc only\n");
332 return -EINVAL;
333 }
334