Skip to content

Commit

Permalink
can: m_can: Fix freeing of can device from peripherials
Browse files Browse the repository at this point in the history
Fix leaking netdev device from peripherial devices. The call to allocate the
netdev device is made from and managed by the peripherial.

Fixes: f524f82 ("can: m_can: Create a m_can platform framework")
Reported-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Dan Murphy <dmurphy@ti.com>
Link: http://lore.kernel.org/r/20200227183829.21854-2-dmurphy@ti.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
  • Loading branch information
Dan Murphy authored and Marc Kleine-Budde committed Nov 15, 2020
1 parent a8c22f5 commit 85816ab
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 19 deletions.
3 changes: 0 additions & 3 deletions drivers/net/can/m_can/m_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,6 @@ int m_can_class_register(struct m_can_classdev *m_can_dev)
if (ret) {
if (m_can_dev->pm_clock_support)
pm_runtime_disable(m_can_dev->dev);
free_candev(m_can_dev->net);
}

return ret;
Expand Down Expand Up @@ -1914,8 +1913,6 @@ void m_can_class_unregister(struct m_can_classdev *m_can_dev)
unregister_candev(m_can_dev->net);

m_can_clk_stop(m_can_dev);

free_candev(m_can_dev->net);
}
EXPORT_SYMBOL_GPL(m_can_class_unregister);

Expand Down
23 changes: 15 additions & 8 deletions drivers/net/can/m_can/m_can_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,32 +67,36 @@ static int m_can_plat_probe(struct platform_device *pdev)
return -ENOMEM;

priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
if (!priv) {
ret = -ENOMEM;
goto probe_fail;
}

mcan_class->device_data = priv;

m_can_class_get_clocks(mcan_class);
ret = m_can_class_get_clocks(mcan_class);
if (ret)
goto probe_fail;

res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can");
addr = devm_ioremap_resource(&pdev->dev, res);
irq = platform_get_irq_byname(pdev, "int0");
if (IS_ERR(addr) || irq < 0) {
ret = -EINVAL;
goto failed_ret;
goto probe_fail;
}

/* message ram could be shared */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
if (!res) {
ret = -ENODEV;
goto failed_ret;
goto probe_fail;
}

mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!mram_addr) {
ret = -ENOMEM;
goto failed_ret;
goto probe_fail;
}

priv->base = addr;
Expand All @@ -111,9 +115,10 @@ static int m_can_plat_probe(struct platform_device *pdev)

m_can_init_ram(mcan_class);

ret = m_can_class_register(mcan_class);
return m_can_class_register(mcan_class);

failed_ret:
probe_fail:
m_can_class_free_dev(mcan_class->net);
return ret;
}

Expand All @@ -134,6 +139,8 @@ static int m_can_plat_remove(struct platform_device *pdev)

m_can_class_unregister(mcan_class);

m_can_class_free_dev(mcan_class->net);

platform_set_drvdata(pdev, NULL);

return 0;
Expand Down
26 changes: 18 additions & 8 deletions drivers/net/can/m_can/tcan4x5x.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,14 +440,18 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
return -ENOMEM;

priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
if (!priv) {
ret = -ENOMEM;
goto out_m_can_class_free_dev;
}

priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
if (PTR_ERR(priv->power) == -EPROBE_DEFER)
return -EPROBE_DEFER;
else
if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto out_m_can_class_free_dev;
} else {
priv->power = NULL;
}

mcan_class->device_data = priv;

Expand All @@ -460,8 +464,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
}

/* Sanity check */
if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF)
return -ERANGE;
if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) {
ret = -ERANGE;
goto out_m_can_class_free_dev;
}

priv->reg_offset = TCAN4X5X_MCAN_OFFSET;
priv->mram_start = TCAN4X5X_MRAM_START;
Expand Down Expand Up @@ -518,8 +524,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
clk_disable_unprepare(mcan_class->cclk);
clk_disable_unprepare(mcan_class->hclk);
}

out_m_can_class_free_dev:
m_can_class_free_dev(mcan_class->net);
dev_err(&spi->dev, "Probe failed, err=%d\n", ret);

return ret;
}

Expand All @@ -531,6 +539,8 @@ static int tcan4x5x_can_remove(struct spi_device *spi)

tcan4x5x_power_enable(priv->power, 0);

m_can_class_free_dev(priv->mcan_dev->net);

return 0;
}

Expand Down

0 comments on commit 85816ab

Please sign in to comment.