Commit 85816aba authored by Dan Murphy's avatar Dan Murphy Committed by Marc Kleine-Budde

can: m_can: Fix freeing of can device from peripherials

Fix leaking netdev device from peripherial devices. The call to allocate the
netdev device is made from and managed by the peripherial.

Fixes: f524f829 ("can: m_can: Create a m_can platform framework")
Reported-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarDan Murphy <dmurphy@ti.com>
Link: http://lore.kernel.org/r/20200227183829.21854-2-dmurphy@ti.comSigned-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent a8c22f5b
...@@ -1856,7 +1856,6 @@ int m_can_class_register(struct m_can_classdev *m_can_dev) ...@@ -1856,7 +1856,6 @@ int m_can_class_register(struct m_can_classdev *m_can_dev)
if (ret) { if (ret) {
if (m_can_dev->pm_clock_support) if (m_can_dev->pm_clock_support)
pm_runtime_disable(m_can_dev->dev); pm_runtime_disable(m_can_dev->dev);
free_candev(m_can_dev->net);
} }
return ret; return ret;
...@@ -1914,8 +1913,6 @@ void m_can_class_unregister(struct m_can_classdev *m_can_dev) ...@@ -1914,8 +1913,6 @@ void m_can_class_unregister(struct m_can_classdev *m_can_dev)
unregister_candev(m_can_dev->net); unregister_candev(m_can_dev->net);
m_can_clk_stop(m_can_dev); m_can_clk_stop(m_can_dev);
free_candev(m_can_dev->net);
} }
EXPORT_SYMBOL_GPL(m_can_class_unregister); EXPORT_SYMBOL_GPL(m_can_class_unregister);
......
...@@ -67,32 +67,36 @@ static int m_can_plat_probe(struct platform_device *pdev) ...@@ -67,32 +67,36 @@ static int m_can_plat_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv) {
return -ENOMEM; ret = -ENOMEM;
goto probe_fail;
}
mcan_class->device_data = priv; 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"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can");
addr = devm_ioremap_resource(&pdev->dev, res); addr = devm_ioremap_resource(&pdev->dev, res);
irq = platform_get_irq_byname(pdev, "int0"); irq = platform_get_irq_byname(pdev, "int0");
if (IS_ERR(addr) || irq < 0) { if (IS_ERR(addr) || irq < 0) {
ret = -EINVAL; ret = -EINVAL;
goto failed_ret; goto probe_fail;
} }
/* message ram could be shared */ /* message ram could be shared */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
if (!res) { if (!res) {
ret = -ENODEV; ret = -ENODEV;
goto failed_ret; goto probe_fail;
} }
mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!mram_addr) { if (!mram_addr) {
ret = -ENOMEM; ret = -ENOMEM;
goto failed_ret; goto probe_fail;
} }
priv->base = addr; priv->base = addr;
...@@ -111,9 +115,10 @@ static int m_can_plat_probe(struct platform_device *pdev) ...@@ -111,9 +115,10 @@ static int m_can_plat_probe(struct platform_device *pdev)
m_can_init_ram(mcan_class); 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; return ret;
} }
...@@ -134,6 +139,8 @@ static int m_can_plat_remove(struct platform_device *pdev) ...@@ -134,6 +139,8 @@ static int m_can_plat_remove(struct platform_device *pdev)
m_can_class_unregister(mcan_class); m_can_class_unregister(mcan_class);
m_can_class_free_dev(mcan_class->net);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
return 0; return 0;
......
...@@ -440,14 +440,18 @@ static int tcan4x5x_can_probe(struct spi_device *spi) ...@@ -440,14 +440,18 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv) {
return -ENOMEM; ret = -ENOMEM;
goto out_m_can_class_free_dev;
}
priv->power = devm_regulator_get_optional(&spi->dev, "vsup"); priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
if (PTR_ERR(priv->power) == -EPROBE_DEFER) if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
return -EPROBE_DEFER; ret = -EPROBE_DEFER;
else goto out_m_can_class_free_dev;
} else {
priv->power = NULL; priv->power = NULL;
}
mcan_class->device_data = priv; mcan_class->device_data = priv;
...@@ -460,8 +464,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi) ...@@ -460,8 +464,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
} }
/* Sanity check */ /* Sanity check */
if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF) {
return -ERANGE; ret = -ERANGE;
goto out_m_can_class_free_dev;
}
priv->reg_offset = TCAN4X5X_MCAN_OFFSET; priv->reg_offset = TCAN4X5X_MCAN_OFFSET;
priv->mram_start = TCAN4X5X_MRAM_START; priv->mram_start = TCAN4X5X_MRAM_START;
...@@ -518,8 +524,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi) ...@@ -518,8 +524,10 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
clk_disable_unprepare(mcan_class->cclk); clk_disable_unprepare(mcan_class->cclk);
clk_disable_unprepare(mcan_class->hclk); 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); dev_err(&spi->dev, "Probe failed, err=%d\n", ret);
return ret; return ret;
} }
...@@ -531,6 +539,8 @@ static int tcan4x5x_can_remove(struct spi_device *spi) ...@@ -531,6 +539,8 @@ static int tcan4x5x_can_remove(struct spi_device *spi)
tcan4x5x_power_enable(priv->power, 0); tcan4x5x_power_enable(priv->power, 0);
m_can_class_free_dev(priv->mcan_dev->net);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment