Skip to content

Commit 3fd2f4b

Browse files
axiqiavinodkoul
authored andcommitted
dmaengine: idxd: fix memory leak in error handling path of idxd_setup_wqs
Memory allocated for wqs is not freed if an error occurs during idxd_setup_wqs(). To fix it, free the allocated memory in the reverse order of allocation before exiting the function in case of an error. Fixes: 7c5dd23 ("dmaengine: idxd: fix wq conf_dev 'struct device' lifetime") Fixes: 700af3a ("dmaengine: idxd: add 'struct idxd_dev' as wrapper for conf_dev") Fixes: de5819b ("dmaengine: idxd: track enabled workqueues in bitmap") Fixes: b0325ae ("dmaengine: idxd: add WQ operation cap restriction support") Cc: stable@vger.kernel.org Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Fenghua Yu <fenghuay@nvidia.com> Link: https://lore.kernel.org/r/20250404120217.48772-2-xueshuai@linux.alibaba.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 305245a commit 3fd2f4b

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

drivers/dma/idxd/init.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
169169

170170
idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev));
171171
if (!idxd->wq_enable_map) {
172-
kfree(idxd->wqs);
173-
return -ENOMEM;
172+
rc = -ENOMEM;
173+
goto err_bitmap;
174174
}
175175

176176
for (i = 0; i < idxd->max_wqs; i++) {
@@ -189,10 +189,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
189189
conf_dev->bus = &dsa_bus_type;
190190
conf_dev->type = &idxd_wq_device_type;
191191
rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id);
192-
if (rc < 0) {
193-
put_device(conf_dev);
192+
if (rc < 0)
194193
goto err;
195-
}
196194

197195
mutex_init(&wq->wq_lock);
198196
init_waitqueue_head(&wq->err_queue);
@@ -203,17 +201,15 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
203201
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
204202
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
205203
if (!wq->wqcfg) {
206-
put_device(conf_dev);
207204
rc = -ENOMEM;
208205
goto err;
209206
}
210207

211208
if (idxd->hw.wq_cap.op_config) {
212209
wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
213210
if (!wq->opcap_bmap) {
214-
put_device(conf_dev);
215211
rc = -ENOMEM;
216-
goto err;
212+
goto err_opcap_bmap;
217213
}
218214
bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
219215
}
@@ -224,12 +220,28 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
224220

225221
return 0;
226222

227-
err:
223+
err_opcap_bmap:
224+
kfree(wq->wqcfg);
225+
226+
err:
227+
put_device(conf_dev);
228+
kfree(wq);
229+
228230
while (--i >= 0) {
229231
wq = idxd->wqs[i];
232+
if (idxd->hw.wq_cap.op_config)
233+
bitmap_free(wq->opcap_bmap);
234+
kfree(wq->wqcfg);
230235
conf_dev = wq_confdev(wq);
231236
put_device(conf_dev);
237+
kfree(wq);
238+
232239
}
240+
bitmap_free(idxd->wq_enable_map);
241+
242+
err_bitmap:
243+
kfree(idxd->wqs);
244+
233245
return rc;
234246
}
235247

0 commit comments

Comments
 (0)