Commit 1838d6c6 authored by Yuusuke Ashizuka's avatar Yuusuke Ashizuka Committed by David S. Miller

ravb: Fixed to be able to unload modules

When this driver is built as a module, I cannot rmmod it after insmoding
it.
This is because that this driver calls ravb_mdio_init() at the time of
probe, and module->refcnt is incremented by alloc_mdio_bitbang() called
after that.
Therefore, even if ifup is not performed, the driver is in use and rmmod
cannot be performed.

$ lsmod
Module                  Size  Used by
ravb                   40960  1
$ rmmod ravb
rmmod: ERROR: Module ravb is in use

Call ravb_mdio_init() at open and free_mdio_bitbang() at close, thereby
rmmod is possible in the ifdown state.

Fixes: c156633f ("Renesas Ethernet AVB driver proper")
Signed-off-by: default avatarYuusuke Ashizuka <ashiduka@fujitsu.com>
Reviewed-by: default avatarSergei Shtylyov <sergei.shtylyov@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3622adb0
...@@ -1342,6 +1342,51 @@ static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler, ...@@ -1342,6 +1342,51 @@ static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
return error; return error;
} }
/* MDIO bus init function */
static int ravb_mdio_init(struct ravb_private *priv)
{
struct platform_device *pdev = priv->pdev;
struct device *dev = &pdev->dev;
int error;
/* Bitbang init */
priv->mdiobb.ops = &bb_ops;
/* MII controller setting */
priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
if (!priv->mii_bus)
return -ENOMEM;
/* Hook up MII support for ethtool */
priv->mii_bus->name = "ravb_mii";
priv->mii_bus->parent = dev;
snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
pdev->name, pdev->id);
/* Register MDIO bus */
error = of_mdiobus_register(priv->mii_bus, dev->of_node);
if (error)
goto out_free_bus;
return 0;
out_free_bus:
free_mdio_bitbang(priv->mii_bus);
return error;
}
/* MDIO bus release function */
static int ravb_mdio_release(struct ravb_private *priv)
{
/* Unregister mdio bus */
mdiobus_unregister(priv->mii_bus);
/* Free bitbang info */
free_mdio_bitbang(priv->mii_bus);
return 0;
}
/* Network device open function for Ethernet AVB */ /* Network device open function for Ethernet AVB */
static int ravb_open(struct net_device *ndev) static int ravb_open(struct net_device *ndev)
{ {
...@@ -1350,6 +1395,13 @@ static int ravb_open(struct net_device *ndev) ...@@ -1350,6 +1395,13 @@ static int ravb_open(struct net_device *ndev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int error; int error;
/* MDIO bus init */
error = ravb_mdio_init(priv);
if (error) {
netdev_err(ndev, "failed to initialize MDIO\n");
return error;
}
napi_enable(&priv->napi[RAVB_BE]); napi_enable(&priv->napi[RAVB_BE]);
napi_enable(&priv->napi[RAVB_NC]); napi_enable(&priv->napi[RAVB_NC]);
...@@ -1427,6 +1479,7 @@ static int ravb_open(struct net_device *ndev) ...@@ -1427,6 +1479,7 @@ static int ravb_open(struct net_device *ndev)
out_napi_off: out_napi_off:
napi_disable(&priv->napi[RAVB_NC]); napi_disable(&priv->napi[RAVB_NC]);
napi_disable(&priv->napi[RAVB_BE]); napi_disable(&priv->napi[RAVB_BE]);
ravb_mdio_release(priv);
return error; return error;
} }
...@@ -1736,6 +1789,8 @@ static int ravb_close(struct net_device *ndev) ...@@ -1736,6 +1789,8 @@ static int ravb_close(struct net_device *ndev)
ravb_ring_free(ndev, RAVB_BE); ravb_ring_free(ndev, RAVB_BE);
ravb_ring_free(ndev, RAVB_NC); ravb_ring_free(ndev, RAVB_NC);
ravb_mdio_release(priv);
return 0; return 0;
} }
...@@ -1887,51 +1942,6 @@ static const struct net_device_ops ravb_netdev_ops = { ...@@ -1887,51 +1942,6 @@ static const struct net_device_ops ravb_netdev_ops = {
.ndo_set_features = ravb_set_features, .ndo_set_features = ravb_set_features,
}; };
/* MDIO bus init function */
static int ravb_mdio_init(struct ravb_private *priv)
{
struct platform_device *pdev = priv->pdev;
struct device *dev = &pdev->dev;
int error;
/* Bitbang init */
priv->mdiobb.ops = &bb_ops;
/* MII controller setting */
priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
if (!priv->mii_bus)
return -ENOMEM;
/* Hook up MII support for ethtool */
priv->mii_bus->name = "ravb_mii";
priv->mii_bus->parent = dev;
snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
pdev->name, pdev->id);
/* Register MDIO bus */
error = of_mdiobus_register(priv->mii_bus, dev->of_node);
if (error)
goto out_free_bus;
return 0;
out_free_bus:
free_mdio_bitbang(priv->mii_bus);
return error;
}
/* MDIO bus release function */
static int ravb_mdio_release(struct ravb_private *priv)
{
/* Unregister mdio bus */
mdiobus_unregister(priv->mii_bus);
/* Free bitbang info */
free_mdio_bitbang(priv->mii_bus);
return 0;
}
static const struct of_device_id ravb_match_table[] = { static const struct of_device_id ravb_match_table[] = {
{ .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 },
{ .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 },
...@@ -2174,13 +2184,6 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2174,13 +2184,6 @@ static int ravb_probe(struct platform_device *pdev)
eth_hw_addr_random(ndev); eth_hw_addr_random(ndev);
} }
/* MDIO bus init */
error = ravb_mdio_init(priv);
if (error) {
dev_err(&pdev->dev, "failed to initialize MDIO\n");
goto out_dma_free;
}
netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll, 64); netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll, 64);
netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll, 64); netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll, 64);
...@@ -2202,8 +2205,6 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2202,8 +2205,6 @@ static int ravb_probe(struct platform_device *pdev)
out_napi_del: out_napi_del:
netif_napi_del(&priv->napi[RAVB_NC]); netif_napi_del(&priv->napi[RAVB_NC]);
netif_napi_del(&priv->napi[RAVB_BE]); netif_napi_del(&priv->napi[RAVB_BE]);
ravb_mdio_release(priv);
out_dma_free:
dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
priv->desc_bat_dma); priv->desc_bat_dma);
...@@ -2235,7 +2236,6 @@ static int ravb_remove(struct platform_device *pdev) ...@@ -2235,7 +2236,6 @@ static int ravb_remove(struct platform_device *pdev)
unregister_netdev(ndev); unregister_netdev(ndev);
netif_napi_del(&priv->napi[RAVB_NC]); netif_napi_del(&priv->napi[RAVB_NC]);
netif_napi_del(&priv->napi[RAVB_BE]); netif_napi_del(&priv->napi[RAVB_BE]);
ravb_mdio_release(priv);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
free_netdev(ndev); free_netdev(ndev);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
......
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