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: f524f829b7
("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>
This commit is contained in:
Родитель
a8c22f5b0c
Коммит
85816aba46
|
@ -1856,7 +1856,6 @@ pm_runtime_fail:
|
|||
if (ret) {
|
||||
if (m_can_dev->pm_clock_support)
|
||||
pm_runtime_disable(m_can_dev->dev);
|
||||
free_candev(m_can_dev->net);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -518,8 +524,10 @@ out_clk:
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче