mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
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: c156633f13
("Renesas Ethernet AVB driver proper")
Signed-off-by: Yuusuke Ashizuka <ashiduka@fujitsu.com>
Reviewed-by: Sergei Shtylyov <sergei.shtylyov@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
3622adb026
commit
1838d6c62f
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 = {
|
|||||||
.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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user