Commit 57e8f26a authored by Sebastian Siewior's avatar Sebastian Siewior Committed by David S. Miller

net/mv643xx: don't disable the mib timer too early and lock properly

mib_counters_update() also restarts the timer.
So the timer is dequeued, the stats are read and then the timer is
enqueued again. This is "okay" unless someone unloads the module.
The locking here is also broken:
mib_counters_update() grabs just a simple spinlock. The only thing the
lock is good for is to protect the timer func against other callers
namely mv643xx_eth_stop() && mv643xx_eth_get_ethtool_stats(). That means
if the spinlock is taken via the ethtool path and than the timer kicks
in then the box will lock up.
Signed-off-by: default avatarSebastian Andrzej Siewior <sebastian@breakpoint.cc>
Acked-by: default avatarLennert Buytenhek <buytenh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 82a5bd6a
...@@ -1175,7 +1175,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) ...@@ -1175,7 +1175,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
{ {
struct mib_counters *p = &mp->mib_counters; struct mib_counters *p = &mp->mib_counters;
spin_lock(&mp->mib_counters_lock); spin_lock_bh(&mp->mib_counters_lock);
p->good_octets_received += mib_read(mp, 0x00); p->good_octets_received += mib_read(mp, 0x00);
p->good_octets_received += (u64)mib_read(mp, 0x04) << 32; p->good_octets_received += (u64)mib_read(mp, 0x04) << 32;
p->bad_octets_received += mib_read(mp, 0x08); p->bad_octets_received += mib_read(mp, 0x08);
...@@ -1208,7 +1208,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) ...@@ -1208,7 +1208,7 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
p->bad_crc_event += mib_read(mp, 0x74); p->bad_crc_event += mib_read(mp, 0x74);
p->collision += mib_read(mp, 0x78); p->collision += mib_read(mp, 0x78);
p->late_collision += mib_read(mp, 0x7c); p->late_collision += mib_read(mp, 0x7c);
spin_unlock(&mp->mib_counters_lock); spin_unlock_bh(&mp->mib_counters_lock);
mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
} }
...@@ -2216,8 +2216,6 @@ static int mv643xx_eth_stop(struct net_device *dev) ...@@ -2216,8 +2216,6 @@ static int mv643xx_eth_stop(struct net_device *dev)
wrlp(mp, INT_MASK, 0x00000000); wrlp(mp, INT_MASK, 0x00000000);
rdlp(mp, INT_MASK); rdlp(mp, INT_MASK);
del_timer_sync(&mp->mib_counters_timer);
napi_disable(&mp->napi); napi_disable(&mp->napi);
del_timer_sync(&mp->rx_oom); del_timer_sync(&mp->rx_oom);
...@@ -2229,6 +2227,7 @@ static int mv643xx_eth_stop(struct net_device *dev) ...@@ -2229,6 +2227,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
port_reset(mp); port_reset(mp);
mv643xx_eth_get_stats(dev); mv643xx_eth_get_stats(dev);
mib_counters_update(mp); mib_counters_update(mp);
del_timer_sync(&mp->mib_counters_timer);
skb_queue_purge(&mp->rx_recycle); skb_queue_purge(&mp->rx_recycle);
......
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