]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
net: mediatek: fix mtk_pending_work
authorJohn Crispin <blogic@openwrt.org>
Thu, 7 Apr 2016 22:54:09 +0000 (00:54 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 13 Apr 2016 02:41:32 +0000 (22:41 -0400)
The driver supports 2 MACs. Both run on the same DMA ring. If we hit a TX
timeout we need to stop both netdevs before restarting them again. If we
don't do this, mtk_stop() wont shutdown DMA and the consecutive call to
mtk_open() wont restart DMA and enable IRQs.

Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mediatek/mtk_eth_soc.c

index 7b760752d2c11b083a514363fc7d1b11c5b18a7b..cd5d0c97f0ce6024289faeb58c89ef55c371bdc3 100644 (file)
@@ -1432,17 +1432,29 @@ static void mtk_pending_work(struct work_struct *work)
 {
        struct mtk_mac *mac = container_of(work, struct mtk_mac, pending_work);
        struct mtk_eth *eth = mac->hw;
-       struct net_device *dev = eth->netdev[mac->id];
-       int err;
+       int err, i;
+       unsigned long restart = 0;
 
        rtnl_lock();
-       mtk_stop(dev);
 
-       err = mtk_open(dev);
-       if (err) {
-               netif_alert(eth, ifup, dev,
-                           "Driver up/down cycle failed, closing device.\n");
-               dev_close(dev);
+       /* stop all devices to make sure that dma is properly shut down */
+       for (i = 0; i < MTK_MAC_COUNT; i++) {
+               if (!netif_oper_up(eth->netdev[i]))
+                       continue;
+               mtk_stop(eth->netdev[i]);
+               __set_bit(i, &restart);
+       }
+
+       /* restart DMA and enable IRQs */
+       for (i = 0; i < MTK_MAC_COUNT; i++) {
+               if (!test_bit(i, &restart))
+                       continue;
+               err = mtk_open(eth->netdev[i]);
+               if (err) {
+                       netif_alert(eth, ifup, eth->netdev[i],
+                             "Driver up/down cycle failed, closing device.\n");
+                       dev_close(eth->netdev[i]);
+               }
        }
        rtnl_unlock();
 }