[OpenWrt-Devel] ath79: ag71xx: Fix tx queue timeouts during ifup

Message ID 1546482311-5046-1-git-send-email-ynezz@true.cz
State New
Headers show
Series
  • [OpenWrt-Devel] ath79: ag71xx: Fix tx queue timeouts during ifup
Related show

Commit Message

Petr Štetiar Jan. 3, 2019, 2:25 a.m.
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>
---
 .../ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Chuanhong Guo Jan. 22, 2019, 4:24 p.m. | #1
Hi!

On Thu, Jan 3, 2019 at 10:25 AM Petr Štetiar <ynezz@true.cz> wrote:
>
> 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
>  ...
> So I've looked at ag71xx_stop() in ar71xx, added the missing bits to ath79 and
> fixed this issue.
I ran into the same issue today on QCA9558 and this commit fixed the
problem for me, too :)
>
> 1. https://github.com/openwrt/openwrt/pull/1635#issuecomment-448638246
>
> Signed-off-by: Petr Štetiar <ynezz@true.cz>
> ...

Patch

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 70ca024..32e1e2a 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,12 +805,20 @@  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);
 	ag71xx_hw_disable(ag);
 
+	spin_lock_irqsave(&ag->lock, flags);
+	if (ag->link) {
+		ag->link = 0;
+		ag71xx_link_adjust(ag);
+	}
+	spin_unlock_irqrestore(&ag->lock, flags);
+
 	return 0;
 }