On 1/10/25 1:22 AM, Shuai Xue wrote: > 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. > > Signed-off-by: Shuai Xue <xueshuai@xxxxxxxxxxxxxxxxx> Reviewed-by: Dave Jiang <dave.jiang@xxxxxxxxx> > --- > drivers/dma/idxd/init.c | 20 +++++++++++++++++--- > 1 file changed, 17 insertions(+), 3 deletions(-) > > diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c > index 234c1c658ec7..6772d9251cd7 100644 > --- a/drivers/dma/idxd/init.c > +++ b/drivers/dma/idxd/init.c > @@ -167,8 +167,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd) > > idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); > if (!idxd->wq_enable_map) { > - kfree(idxd->wqs); > - return -ENOMEM; > + rc = -ENOMEM; > + goto err_bitmap; > } > > for (i = 0; i < idxd->max_wqs; i++) { > @@ -189,6 +189,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd) > rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); > if (rc < 0) { > put_device(conf_dev); > + kfree(wq); > goto err; > } > > @@ -202,6 +203,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd) > wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); > if (!wq->wqcfg) { > put_device(conf_dev); > + kfree(wq); > rc = -ENOMEM; > goto err; > } > @@ -209,7 +211,9 @@ static int idxd_setup_wqs(struct idxd_device *idxd) > if (idxd->hw.wq_cap.op_config) { > wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); > if (!wq->opcap_bmap) { > + kfree(wq->wqcfg); > put_device(conf_dev); > + kfree(wq); > rc = -ENOMEM; > goto err; > } > @@ -223,11 +227,21 @@ static int idxd_setup_wqs(struct idxd_device *idxd) > return 0; > > err: > - while (--i >= 0) { > + while (i-- > 0) { > wq = idxd->wqs[i]; > + if (idxd->hw.wq_cap.op_config) > + bitmap_free(wq->opcap_bmap); > + kfree(wq->wqcfg); > conf_dev = wq_confdev(wq); > put_device(conf_dev); > + kfree(wq); > + > } > + bitmap_free(idxd->wq_enable_map); > + > +err_bitmap: > + kfree(idxd->wqs); > + > return rc; > } >