Skip to content

Commit 80b0260

Browse files
axiqiagregkh
authored andcommitted
dmaengine: idxd: Add missing cleanup for early error out in idxd_setup_internals
commit 61259fb upstream. The idxd_setup_internals() is missing some cleanup when things fail in the middle. Add the appropriate cleanup routines: - cleanup groups - cleanup enginces - cleanup wqs to make sure it exits gracefully. Fixes: defe49f ("dmaengine: idxd: fix group conf_dev lifetime") Cc: [email protected] Suggested-by: Fenghua Yu <[email protected]> Signed-off-by: Shuai Xue <[email protected]> Reviewed-by: Fenghua Yu <[email protected]> Reviewed-by: Dave Jiang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 56e2f09 commit 80b0260

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

drivers/dma/idxd/init.c

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,25 @@ static void idxd_cleanup_interrupts(struct idxd_device *idxd)
153153
pci_free_irq_vectors(pdev);
154154
}
155155

156+
static void idxd_clean_wqs(struct idxd_device *idxd)
157+
{
158+
struct idxd_wq *wq;
159+
struct device *conf_dev;
160+
int i;
161+
162+
for (i = 0; i < idxd->max_wqs; i++) {
163+
wq = idxd->wqs[i];
164+
if (idxd->hw.wq_cap.op_config)
165+
bitmap_free(wq->opcap_bmap);
166+
kfree(wq->wqcfg);
167+
conf_dev = wq_confdev(wq);
168+
put_device(conf_dev);
169+
kfree(wq);
170+
}
171+
bitmap_free(idxd->wq_enable_map);
172+
kfree(idxd->wqs);
173+
}
174+
156175
static int idxd_setup_wqs(struct idxd_device *idxd)
157176
{
158177
struct device *dev = &idxd->pdev->dev;
@@ -243,6 +262,21 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
243262
return rc;
244263
}
245264

265+
static void idxd_clean_engines(struct idxd_device *idxd)
266+
{
267+
struct idxd_engine *engine;
268+
struct device *conf_dev;
269+
int i;
270+
271+
for (i = 0; i < idxd->max_engines; i++) {
272+
engine = idxd->engines[i];
273+
conf_dev = engine_confdev(engine);
274+
put_device(conf_dev);
275+
kfree(engine);
276+
}
277+
kfree(idxd->engines);
278+
}
279+
246280
static int idxd_setup_engines(struct idxd_device *idxd)
247281
{
248282
struct idxd_engine *engine;
@@ -294,6 +328,19 @@ static int idxd_setup_engines(struct idxd_device *idxd)
294328
return rc;
295329
}
296330

331+
static void idxd_clean_groups(struct idxd_device *idxd)
332+
{
333+
struct idxd_group *group;
334+
int i;
335+
336+
for (i = 0; i < idxd->max_groups; i++) {
337+
group = idxd->groups[i];
338+
put_device(group_confdev(group));
339+
kfree(group);
340+
}
341+
kfree(idxd->groups);
342+
}
343+
297344
static int idxd_setup_groups(struct idxd_device *idxd)
298345
{
299346
struct device *dev = &idxd->pdev->dev;
@@ -408,7 +455,7 @@ static int idxd_init_evl(struct idxd_device *idxd)
408455
static int idxd_setup_internals(struct idxd_device *idxd)
409456
{
410457
struct device *dev = &idxd->pdev->dev;
411-
int rc, i;
458+
int rc;
412459

413460
init_waitqueue_head(&idxd->cmd_waitq);
414461

@@ -439,14 +486,11 @@ static int idxd_setup_internals(struct idxd_device *idxd)
439486
err_evl:
440487
destroy_workqueue(idxd->wq);
441488
err_wkq_create:
442-
for (i = 0; i < idxd->max_groups; i++)
443-
put_device(group_confdev(idxd->groups[i]));
489+
idxd_clean_groups(idxd);
444490
err_group:
445-
for (i = 0; i < idxd->max_engines; i++)
446-
put_device(engine_confdev(idxd->engines[i]));
491+
idxd_clean_engines(idxd);
447492
err_engine:
448-
for (i = 0; i < idxd->max_wqs; i++)
449-
put_device(wq_confdev(idxd->wqs[i]));
493+
idxd_clean_wqs(idxd);
450494
err_wqs:
451495
return rc;
452496
}

0 commit comments

Comments
 (0)