net-next: ax88796: Attach MII bus only when open
Call ax_mii_init in ax_open(), and unregister/remove mdiobus resources in ax_close(). This is needed to be able to unload the module, as the module is busy while the MII bus is attached. Signed-off-by: Michael Karcher <kernel@mkarcher.dialup.fu-berlin.de> Signed-off-by: Michael Schmitz <schmitzmic@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7a0907bd39
commit
fd5f375c16
|
@ -387,6 +387,90 @@ static void ax_phy_switch(struct net_device *dev, int on)
|
|||
ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17));
|
||||
}
|
||||
|
||||
static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
|
||||
if (level)
|
||||
ax->reg_memr |= AX_MEMR_MDC;
|
||||
else
|
||||
ax->reg_memr &= ~AX_MEMR_MDC;
|
||||
|
||||
ei_outb(ax->reg_memr, ax->addr_memr);
|
||||
}
|
||||
|
||||
static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
|
||||
if (output)
|
||||
ax->reg_memr &= ~AX_MEMR_MDIR;
|
||||
else
|
||||
ax->reg_memr |= AX_MEMR_MDIR;
|
||||
|
||||
ei_outb(ax->reg_memr, ax->addr_memr);
|
||||
}
|
||||
|
||||
static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
|
||||
if (value)
|
||||
ax->reg_memr |= AX_MEMR_MDO;
|
||||
else
|
||||
ax->reg_memr &= ~AX_MEMR_MDO;
|
||||
|
||||
ei_outb(ax->reg_memr, ax->addr_memr);
|
||||
}
|
||||
|
||||
static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
int reg_memr = ei_inb(ax->addr_memr);
|
||||
|
||||
return reg_memr & AX_MEMR_MDI ? 1 : 0;
|
||||
}
|
||||
|
||||
static const struct mdiobb_ops bb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.set_mdc = ax_bb_mdc,
|
||||
.set_mdio_dir = ax_bb_dir,
|
||||
.set_mdio_data = ax_bb_set_data,
|
||||
.get_mdio_data = ax_bb_get_data,
|
||||
};
|
||||
|
||||
static int ax_mii_init(struct net_device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev->dev.parent);
|
||||
struct ei_device *ei_local = netdev_priv(dev);
|
||||
struct ax_device *ax = to_ax_dev(dev);
|
||||
int err;
|
||||
|
||||
ax->bb_ctrl.ops = &bb_ops;
|
||||
ax->addr_memr = ei_local->mem + AX_MEMR;
|
||||
ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
|
||||
if (!ax->mii_bus) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ax->mii_bus->name = "ax88796_mii_bus";
|
||||
ax->mii_bus->parent = dev->dev.parent;
|
||||
snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
|
||||
pdev->name, pdev->id);
|
||||
|
||||
err = mdiobus_register(ax->mii_bus);
|
||||
if (err)
|
||||
goto out_free_mdio_bitbang;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_mdio_bitbang:
|
||||
free_mdio_bitbang(ax->mii_bus);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ax_open(struct net_device *dev)
|
||||
{
|
||||
struct ax_device *ax = to_ax_dev(dev);
|
||||
|
@ -394,6 +478,10 @@ static int ax_open(struct net_device *dev)
|
|||
|
||||
netdev_dbg(dev, "open\n");
|
||||
|
||||
ret = ax_mii_init(dev);
|
||||
if (ret)
|
||||
goto failed_mii;
|
||||
|
||||
ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
|
||||
dev->name, dev);
|
||||
if (ret)
|
||||
|
@ -421,6 +509,10 @@ static int ax_open(struct net_device *dev)
|
|||
ax_phy_switch(dev, 0);
|
||||
free_irq(dev->irq, dev);
|
||||
failed_request_irq:
|
||||
/* unregister mdiobus */
|
||||
mdiobus_unregister(ax->mii_bus);
|
||||
free_mdio_bitbang(ax->mii_bus);
|
||||
failed_mii:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -440,6 +532,9 @@ static int ax_close(struct net_device *dev)
|
|||
phy_disconnect(dev->phydev);
|
||||
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
mdiobus_unregister(ax->mii_bus);
|
||||
free_mdio_bitbang(ax->mii_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -539,92 +634,8 @@ static const struct net_device_ops ax_netdev_ops = {
|
|||
#endif
|
||||
};
|
||||
|
||||
static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
|
||||
if (level)
|
||||
ax->reg_memr |= AX_MEMR_MDC;
|
||||
else
|
||||
ax->reg_memr &= ~AX_MEMR_MDC;
|
||||
|
||||
ei_outb(ax->reg_memr, ax->addr_memr);
|
||||
}
|
||||
|
||||
static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
|
||||
if (output)
|
||||
ax->reg_memr &= ~AX_MEMR_MDIR;
|
||||
else
|
||||
ax->reg_memr |= AX_MEMR_MDIR;
|
||||
|
||||
ei_outb(ax->reg_memr, ax->addr_memr);
|
||||
}
|
||||
|
||||
static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
|
||||
if (value)
|
||||
ax->reg_memr |= AX_MEMR_MDO;
|
||||
else
|
||||
ax->reg_memr &= ~AX_MEMR_MDO;
|
||||
|
||||
ei_outb(ax->reg_memr, ax->addr_memr);
|
||||
}
|
||||
|
||||
static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
|
||||
{
|
||||
struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
|
||||
int reg_memr = ei_inb(ax->addr_memr);
|
||||
|
||||
return reg_memr & AX_MEMR_MDI ? 1 : 0;
|
||||
}
|
||||
|
||||
static const struct mdiobb_ops bb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.set_mdc = ax_bb_mdc,
|
||||
.set_mdio_dir = ax_bb_dir,
|
||||
.set_mdio_data = ax_bb_set_data,
|
||||
.get_mdio_data = ax_bb_get_data,
|
||||
};
|
||||
|
||||
/* setup code */
|
||||
|
||||
static int ax_mii_init(struct net_device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev->dev.parent);
|
||||
struct ei_device *ei_local = netdev_priv(dev);
|
||||
struct ax_device *ax = to_ax_dev(dev);
|
||||
int err;
|
||||
|
||||
ax->bb_ctrl.ops = &bb_ops;
|
||||
ax->addr_memr = ei_local->mem + AX_MEMR;
|
||||
ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
|
||||
if (!ax->mii_bus) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ax->mii_bus->name = "ax88796_mii_bus";
|
||||
ax->mii_bus->parent = dev->dev.parent;
|
||||
snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
|
||||
pdev->name, pdev->id);
|
||||
|
||||
err = mdiobus_register(ax->mii_bus);
|
||||
if (err)
|
||||
goto out_free_mdio_bitbang;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_mdio_bitbang:
|
||||
free_mdio_bitbang(ax->mii_bus);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
|
||||
{
|
||||
void __iomem *ioaddr = ei_local->mem;
|
||||
|
@ -755,10 +766,6 @@ static int ax_init_dev(struct net_device *dev)
|
|||
dev->netdev_ops = &ax_netdev_ops;
|
||||
dev->ethtool_ops = &ax_ethtool_ops;
|
||||
|
||||
ret = ax_mii_init(dev);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
ax_NS8390_init(dev, 0);
|
||||
|
||||
ret = register_netdev(dev);
|
||||
|
|
Loading…
Reference in New Issue