Commit 4ac0ac84 authored by Michal Kubecek's avatar Michal Kubecek Committed by David S. Miller

epic100: allow nesting of ethtool_ops begin() and complete()

Unlike most networking drivers using begin() and complete() ethtool_ops
callbacks to resume a device which is down and suspend it again when done,
epic100 does not use standard refcounted infrastructure but sets device
sleep state directly.

With the introduction of netlink ethtool interface, we may have nested
begin-complete blocks so that inner complete() would put the device back to
sleep for the rest of the outer block.

To avoid rewriting an old and not very actively developed driver, just add
a nesting counter and only perform resume and suspend on the outermost
level.
Signed-off-by: default avatarMichal Kubecek <mkubecek@suse.cz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 71f711a4
...@@ -280,6 +280,7 @@ struct epic_private { ...@@ -280,6 +280,7 @@ struct epic_private {
signed char phys[4]; /* MII device addresses. */ signed char phys[4]; /* MII device addresses. */
u16 advertising; /* NWay media advertisement */ u16 advertising; /* NWay media advertisement */
int mii_phy_cnt; int mii_phy_cnt;
u32 ethtool_ops_nesting;
struct mii_if_info mii; struct mii_if_info mii;
unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int tx_full:1; /* The Tx queue is full. */
unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int default_port:4; /* Last dev->if_port value. */
...@@ -1435,8 +1436,10 @@ static int ethtool_begin(struct net_device *dev) ...@@ -1435,8 +1436,10 @@ static int ethtool_begin(struct net_device *dev)
struct epic_private *ep = netdev_priv(dev); struct epic_private *ep = netdev_priv(dev);
void __iomem *ioaddr = ep->ioaddr; void __iomem *ioaddr = ep->ioaddr;
if (ep->ethtool_ops_nesting == U32_MAX)
return -EBUSY;
/* power-up, if interface is down */ /* power-up, if interface is down */
if (!netif_running(dev)) { if (!ep->ethtool_ops_nesting++ && !netif_running(dev)) {
ew32(GENCTL, 0x0200); ew32(GENCTL, 0x0200);
ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800); ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800);
} }
...@@ -1449,7 +1452,7 @@ static void ethtool_complete(struct net_device *dev) ...@@ -1449,7 +1452,7 @@ static void ethtool_complete(struct net_device *dev)
void __iomem *ioaddr = ep->ioaddr; void __iomem *ioaddr = ep->ioaddr;
/* power-down, if interface is down */ /* power-down, if interface is down */
if (!netif_running(dev)) { if (!--ep->ethtool_ops_nesting && !netif_running(dev)) {
ew32(GENCTL, 0x0008); ew32(GENCTL, 0x0008);
ew32(NVCTL, (er32(NVCTL) & ~0x483c) | 0x0000); ew32(NVCTL, (er32(NVCTL) & ~0x483c) | 0x0000);
} }
......
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