Message ID | 146ace9856b8576eea83a1a5dc6329315831c44e.1578257976.git.mkubecek@suse.cz (mailing list archive) |
---|---|
State | Not Applicable |
Delegated to: | Johannes Berg |
Headers | show |
Series | ethtool: allow nesting of begin() and complete() callbacks | expand |
> @@ -1435,8 +1436,10 @@ static int ethtool_begin(struct net_device *dev) > struct epic_private *ep = netdev_priv(dev); > void __iomem *ioaddr = ep->ioaddr; > > + if (ep->ethtool_ops_nesting == U32_MAX) > + return -EBUSY; > /* power-up, if interface is down */ > - if (!netif_running(dev)) { > + if (ep->ethtool_ops_nesting++ && !netif_running(dev)) { > ew32(GENCTL, 0x0200); > ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800); > } Hi Michal In the via-velocity you added: + if (vptr->ethtool_ops_nesting == U32_MAX) + return -EBUSY; + if (!vptr->ethtool_ops_nesting++ && !netif_running(dev)) velocity_set_power_state(vptr, PCI_D0); return 0; These two fragments differ by a ! . Is that correct? Andrew
On Sun, Jan 05, 2020 at 11:08:32PM +0100, Andrew Lunn wrote: > > @@ -1435,8 +1436,10 @@ static int ethtool_begin(struct net_device *dev) > > struct epic_private *ep = netdev_priv(dev); > > void __iomem *ioaddr = ep->ioaddr; > > > > + if (ep->ethtool_ops_nesting == U32_MAX) > > + return -EBUSY; > > /* power-up, if interface is down */ > > - if (!netif_running(dev)) { > > + if (ep->ethtool_ops_nesting++ && !netif_running(dev)) { > > ew32(GENCTL, 0x0200); > > ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800); > > } > > Hi Michal > > In the via-velocity you added: > > + if (vptr->ethtool_ops_nesting == U32_MAX) > + return -EBUSY; > + if (!vptr->ethtool_ops_nesting++ && !netif_running(dev)) > velocity_set_power_state(vptr, PCI_D0); > return 0; > > These two fragments differ by a ! . Is that correct? You are right, thank you for catching it. This should be if (!ep->ethtool_ops_nesting++ && !netif_running(dev)) { as well, we only want to wake the device up in the first (outermost) ->begin(). (It would probably do no harm to do it each time but not doing it in the first would be wrong.) I'll send v2 in a moment. Michal
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index 912760e8514c..b9915645412c 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c @@ -280,6 +280,7 @@ struct epic_private { signed char phys[4]; /* MII device addresses. */ u16 advertising; /* NWay media advertisement */ int mii_phy_cnt; + u32 ethtool_ops_nesting; struct mii_if_info mii; unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int default_port:4; /* Last dev->if_port value. */ @@ -1435,8 +1436,10 @@ static int ethtool_begin(struct net_device *dev) struct epic_private *ep = netdev_priv(dev); void __iomem *ioaddr = ep->ioaddr; + if (ep->ethtool_ops_nesting == U32_MAX) + return -EBUSY; /* power-up, if interface is down */ - if (!netif_running(dev)) { + if (ep->ethtool_ops_nesting++ && !netif_running(dev)) { ew32(GENCTL, 0x0200); ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800); } @@ -1449,7 +1452,7 @@ static void ethtool_complete(struct net_device *dev) void __iomem *ioaddr = ep->ioaddr; /* power-down, if interface is down */ - if (!netif_running(dev)) { + if (!--ep->ethtool_ops_nesting && !netif_running(dev)) { ew32(GENCTL, 0x0008); ew32(NVCTL, (er32(NVCTL) & ~0x483c) | 0x0000); }
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: Michal Kubecek <mkubecek@suse.cz> --- drivers/net/ethernet/smsc/epic100.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)