ti_am335x_xbar_route_allocate() calls of_find_device_by_node() which increments the reference count of the platform device, but fails to call put_device() to decrement the reference count before returning. This could cause a reference count leak each time the function is called, preventing the platform device from being properly cleaned up and leading to memory leakage.
Add proper put_device() calls in all exit paths to fix the reference count imbalance.
Found by code review.
Cc: stable@vger.kernel.org Fixes: 42dbdcc6bf96 ("dmaengine: ti-dma-crossbar: Add support for crossbar on AM33xx/AM43xx") Signed-off-by: Ma Ke make24@iscas.ac.cn --- drivers/dma/ti/dma-crossbar.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/ti/dma-crossbar.c b/drivers/dma/ti/dma-crossbar.c index 7f17ee87a6dc..58bc515ec8b3 100644 --- a/drivers/dma/ti/dma-crossbar.c +++ b/drivers/dma/ti/dma-crossbar.c @@ -80,33 +80,40 @@ static void *ti_am335x_xbar_route_allocate(struct of_phandle_args *dma_spec, struct platform_device *pdev = of_find_device_by_node(ofdma->of_node); struct ti_am335x_xbar_data *xbar = platform_get_drvdata(pdev); struct ti_am335x_xbar_map *map; + int ret;
- if (dma_spec->args_count != 3) - return ERR_PTR(-EINVAL); + if (dma_spec->args_count != 3) { + ret = -EINVAL; + goto err_put_device; + }
if (dma_spec->args[2] >= xbar->xbar_events) { dev_err(&pdev->dev, "Invalid XBAR event number: %d\n", dma_spec->args[2]); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto err_put_device; }
if (dma_spec->args[0] >= xbar->dma_requests) { dev_err(&pdev->dev, "Invalid DMA request line number: %d\n", dma_spec->args[0]); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto err_put_device; }
/* The of_node_put() will be done in the core for the node */ dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0); if (!dma_spec->np) { dev_err(&pdev->dev, "Can't get DMA master\n"); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto err_put_device; }
map = kzalloc(sizeof(*map), GFP_KERNEL); if (!map) { of_node_put(dma_spec->np); - return ERR_PTR(-ENOMEM); + ret = -ENOMEM; + goto err_put_device; }
map->dma_line = (u16)dma_spec->args[0]; @@ -120,7 +127,12 @@ static void *ti_am335x_xbar_route_allocate(struct of_phandle_args *dma_spec,
ti_am335x_xbar_write(xbar->iomem, map->dma_line, map->mux_val);
+ put_device(&pdev->dev); return map; + +err_put_device: + put_device(&pdev->dev); + return ERR_PTR(ret); }
static const struct of_device_id ti_am335x_master_match[] __maybe_unused = {
Add proper put_device() calls in all exit paths to fix the reference count imbalance.
How do you think about to apply the attribute “__free(put_device)” in this function implementation? https://elixir.bootlin.com/linux/v6.18-rc5/source/include/linux/device.h#L11...
Regards, Markus
linux-stable-mirror@lists.linaro.org