Memory and switch reset gpio pin must be allocated on switch/module init and freed on removal. At least they should not be allocated 2 or more times in a row.
Signed-off-by: Fedor Konstantinov <[email protected]> --- Comments: Following cmd sequence calls b53_switch_init() twice, so causes leak of memory. Last ifconfig will fail also on targets which support switch reset gpio pin, because devm_gpio_request_one() will be called twice in a row. ifconfig eth0 up ifconfig eth0 down ifconfig eth0 up mmap/spi/srab drivers were not tested yet because I don't have such hardware. --- .../generic/files/drivers/net/phy/b53/b53_common.c | 19 +++++++++++++++ .../generic/files/drivers/net/phy/b53/b53_mdio.c | 6 +++++ .../generic/files/drivers/net/phy/b53/b53_mmap.c | 28 +++++++++++++++++----- .../generic/files/drivers/net/phy/b53/b53_priv.h | 7 +++--- .../generic/files/drivers/net/phy/b53/b53_spi.c | 20 ++++++++++++---- .../generic/files/drivers/net/phy/b53/b53_srab.c | 28 +++++++++++++++++----- 6 files changed, 88 insertions(+), 20 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c index 47b5a8b..2e2f6aa 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c @@ -1362,6 +1362,12 @@ struct b53_device *b53_switch_alloc(struct device *base, struct b53_io_ops *ops, } EXPORT_SYMBOL(b53_switch_alloc); +void b53_switch_free(struct device *dev, struct b53_device *priv) +{ + devm_kfree(dev, priv); +} +EXPORT_SYMBOL(b53_switch_free); + int b53_switch_detect(struct b53_device *dev) { u32 id32; @@ -1452,6 +1458,19 @@ int b53_switch_register(struct b53_device *dev) } EXPORT_SYMBOL(b53_switch_register); +void b53_switch_remove(struct b53_device *dev) +{ + unregister_switch(&dev->sw_dev); + + if (dev->reset_gpio >= 0) + devm_gpio_free(dev->dev, dev->reset_gpio); + + devm_kfree(dev->dev, dev->buf); + devm_kfree(dev->dev, dev->vlans); + devm_kfree(dev->dev, dev->ports); +} +EXPORT_SYMBOL(b53_switch_remove); + MODULE_AUTHOR("Jonas Gorski <[email protected]>"); MODULE_DESCRIPTION("B53 switch library"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c b/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c index 3c25f0e..9a5f058 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_mdio.c @@ -285,6 +285,10 @@ static int b53_phy_config_init(struct phy_device *phydev) struct b53_device *dev; int ret; + /* check if already initialized */ + if (phydev->priv) + return 0; + dev = b53_switch_alloc(&phydev->dev, &b53_mdio_ops, phydev->bus); if (!dev) return -ENOMEM; @@ -314,6 +318,8 @@ static void b53_phy_remove(struct phy_device *phydev) b53_switch_remove(priv); + b53_switch_free(&phydev->dev, priv); + phydev->priv = NULL; } diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c b/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c index ab1895e..7c83758 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_mmap.c @@ -200,7 +200,12 @@ static struct b53_io_ops b53_mmap_ops = { static int b53_mmap_probe(struct platform_device *pdev) { struct b53_platform_data *pdata = pdev->dev.platform_data; - struct b53_device *dev; + struct b53_device *dev = platform_get_drvdata(pdev); + int ret; + + /* check if already initialized */ + if (dev) + return 0; if (!pdata) return -EINVAL; @@ -209,20 +214,31 @@ static int b53_mmap_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - if (pdata) - dev->pdata = pdata; + dev->pdata = pdata; + + ret = b53_switch_register(dev); + if (ret) { + dev_err(dev->dev, "failed to register switch: %i\n", ret); + return ret; + } platform_set_drvdata(pdev, dev); - return b53_switch_register(dev); + return 0; } static int b53_mmap_remove(struct platform_device *pdev) { struct b53_device *dev = platform_get_drvdata(pdev); - if (dev) - b53_switch_remove(dev); + if (!dev) + return 0; + + b53_switch_remove(dev); + + b53_switch_free(&pdev->dev, dev); + + platform_set_drvdata(pdev, NULL); return 0; } diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h b/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h index 4336fdb..8ef68a1 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h @@ -176,14 +176,13 @@ static inline struct b53_device *sw_to_b53(struct switch_dev *sw) struct b53_device *b53_switch_alloc(struct device *base, struct b53_io_ops *ops, void *priv); +void b53_switch_free(struct device *base, struct b53_device *priv); + int b53_switch_detect(struct b53_device *dev); int b53_switch_register(struct b53_device *dev); -static inline void b53_switch_remove(struct b53_device *dev) -{ - unregister_switch(&dev->sw_dev); -} +void b53_switch_remove(struct b53_device *dev); static inline int b53_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) { diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c b/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c index 469a8dd..7cfb120 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c @@ -284,9 +284,13 @@ static struct b53_io_ops b53_spi_ops = { static int b53_spi_probe(struct spi_device *spi) { - struct b53_device *dev; + struct b53_device *dev = spi_get_drvdata(spi); int ret; + /* check if already initialized */ + if (dev) + return 0; + dev = b53_switch_alloc(&spi->dev, &b53_spi_ops, spi); if (!dev) return -ENOMEM; @@ -295,8 +299,10 @@ static int b53_spi_probe(struct spi_device *spi) dev->pdata = spi->dev.platform_data; ret = b53_switch_register(dev); - if (ret) + if (ret) { + dev_err(dev->dev, "failed to register switch: %i\n", ret); return ret; + } spi_set_drvdata(spi, dev); @@ -307,8 +313,14 @@ static int b53_spi_remove(struct spi_device *spi) { struct b53_device *dev = spi_get_drvdata(spi); - if (dev) - b53_switch_remove(dev); + if (!dev) + return 0; + + b53_switch_remove(dev); + + b53_switch_free(&spi->dev, dev); + + spi_set_drvdata(spi, NULL); return 0; } diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c b/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c index 012daa3..00eb0fe 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_srab.c @@ -337,7 +337,12 @@ static struct b53_io_ops b53_srab_ops = { static int b53_srab_probe(struct platform_device *pdev) { struct b53_platform_data *pdata = pdev->dev.platform_data; - struct b53_device *dev; + struct b53_device *dev = platform_get_drvdata(pdev); + int ret; + + /* check if already initialized */ + if (dev) + return 0; if (!pdata) return -EINVAL; @@ -346,20 +351,31 @@ static int b53_srab_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - if (pdata) - dev->pdata = pdata; + dev->pdata = pdata; + + ret = b53_switch_register(dev); + if (ret) { + dev_err(dev->dev, "failed to register switch: %i\n", ret); + return ret; + } platform_set_drvdata(pdev, dev); - return b53_switch_register(dev); + return 0; } static int b53_srab_remove(struct platform_device *pdev) { struct b53_device *dev = platform_get_drvdata(pdev); - if (dev) - b53_switch_remove(dev); + if (!dev) + return 0; + + b53_switch_remove(dev); + + b53_switch_free(&pdev->dev, dev); + + platform_set_drvdata(pdev, NULL); return 0; } -- 2.1.4 _______________________________________________ openwrt-devel mailing list [email protected] https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
