aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux
diff options
context:
space:
mode:
authorPetr Štetiar <ynezz@true.cz>2019-01-03 03:25:11 +0100
committerKoen Vandeputte <koen.vandeputte@ncentric.com>2019-02-07 14:19:46 +0100
commit5fd68d60e422492dfad0d4f77f1bef3d0ea079ba (patch)
tree29cb1c6eb874fea71e80747387144824c21553ac /target/linux
parentab18540d114385c9b3ffa230ba406723fd3af27b (diff)
downloadupstream-5fd68d60e422492dfad0d4f77f1bef3d0ea079ba.tar.gz
upstream-5fd68d60e422492dfad0d4f77f1bef3d0ea079ba.tar.bz2
upstream-5fd68d60e422492dfad0d4f77f1bef3d0ea079ba.zip
ath79: ag71xx: Fix tx queue timeouts during ifup
On ath79 and UBNT Bullet M XW (ar9342) I was experiencing weird issues during network setup[1] which I was able to reproduce easily with following commands: uci set network.lan.ipaddr='192.168.1.20' uci commit network ifup lan Which resulted after some time in: ... WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:461 dev_watchdog+0x16c/0x280 NETDEV WATCHDOG: eth0 (ag71xx): transmit queue 0 timed out ... Sometimes I wasn't able to use networking anymore, sometimes it was enough to just ifdown/ifup lan and network was backup. On ar71xx it was all working just fine. I've found out, that it was happening because ag71xx_poll() wasn't called, thus the TX queue wasn't emptied. The ag71xx_poll() is being called from napi hrtimer, which is enabled by napi_schedule() in ar71xx_interrupt(), but since no interrupts were ever fired again after ag71xx_stop() was called, it was always leading to tx queue timeouts: *** ag71xx_hard_start_xmit() eth0: packet injected into TX queue eth0: raw intr=00000001 TXPS POLL eth0: enable polling mode eth0: processing TX ring, flush=no eth0: disable polling mode, rx=1, tx=1,limit=32 ( `ifup lan done here` ) *** ag71xx_stop() *** ag71xx_open() *** ag71xx_hw_enable() IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready *** ag71xx_hard_start_xmit() eth0: packet injected into TX queue *** ag71xx_hard_start_xmit() eth0: packet injected into TX queue ... WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:320 dev_watchdog+0x164/0x274 So I've looked at ag71xx_stop() in ar71xx, added the missing bits to ath79 and fixed this issue. 1. https://github.com/openwrt/openwrt/pull/1635#issuecomment-448638246 Signed-off-by: Petr Štetiar <ynezz@true.cz> [move ag->link before ag71xx_hw_disable to retain ordering as original] Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
index 70ca0248c3..d809bbee80 100644
--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
+++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
@@ -805,10 +805,19 @@ err:
static int ag71xx_stop(struct net_device *dev)
{
+ unsigned long flags;
struct ag71xx *ag = netdev_priv(dev);
netif_carrier_off(dev);
phy_stop(ag->phy_dev);
+
+ spin_lock_irqsave(&ag->lock, flags);
+ if (ag->link) {
+ ag->link = 0;
+ ag71xx_link_adjust(ag);
+ }
+ spin_unlock_irqrestore(&ag->lock, flags);
+
ag71xx_hw_disable(ag);
return 0;