mediatek: various additional ethernet fixes
authorJohn Crispin <john@phrozen.org>
Wed, 30 Aug 2017 07:02:39 +0000 (09:02 +0200)
committerJohn Crispin <john@phrozen.org>
Wed, 30 Aug 2017 15:05:10 +0000 (17:05 +0200)
* fixes default affinity
* adds a napi watchdog - we were seeing stalled TX queues
* adds up/down locking

Signed-off-by: John Crispin <john@phrozen.org>
target/linux/mediatek/patches-4.9/0059-eth-fixes.patch
target/linux/mediatek/patches-4.9/0060-eth-debug.patch [new file with mode: 0644]
target/linux/mediatek/patches-4.9/0061-eth-up_down_lock.patch [new file with mode: 0644]

index 61b4b2615c11eb7eed45d7abb36e95b35a9a4f28..4991c52d36568c8be26615fc34fc1a450034ae7d 100644 (file)
@@ -1,5 +1,7 @@
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+Index: linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+===================================================================
+--- linux-4.9.44.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 @@ -24,6 +24,7 @@
  #include <linux/tcp.h>
  
        eth->netdev[id]->netdev_ops = &mtk_netdev_ops;
        eth->netdev[id]->base_addr = (unsigned long)eth->base;
  
-@@ -2584,15 +2665,19 @@ static int mtk_probe(struct platform_dev
-                       goto err_deinit_hw;
-       }
-+      cpumask_set_cpu(1, &eth->affinity_mask[1]);
-+      cpumask_set_cpu(0, &eth->affinity_mask[2]);
-       err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
-                              dev_name(eth->dev), eth);
-       if (err)
-               goto err_free_dev;
-+      irq_set_affinity_hint(eth->irq[1], &eth->affinity_mask[1]);
-       err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
-                              dev_name(eth->dev), eth);
-       if (err)
-               goto err_free_dev;
-+      irq_set_affinity_hint(eth->irq[2], &eth->affinity_mask[2]);
-       err = mtk_mdio_init(eth);
-       if (err)
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+Index: linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+===================================================================
+--- linux-4.9.44.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 @@ -80,7 +80,6 @@
  
  /* CDMP Ingress Control Register */
diff --git a/target/linux/mediatek/patches-4.9/0060-eth-debug.patch b/target/linux/mediatek/patches-4.9/0060-eth-debug.patch
new file mode 100644 (file)
index 0000000..fb36ddf
--- /dev/null
@@ -0,0 +1,73 @@
+Index: linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+===================================================================
+--- linux-4.9.44.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -851,6 +851,7 @@ static void mtk_stop_queue(struct mtk_et
+                       continue;
+               netif_stop_queue(eth->netdev[i]);
+       }
++      mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+ }
+ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
+@@ -1885,6 +1886,19 @@ static int mtk_start_dma(struct mtk_eth
+       return 0;
+ }
++#define NAPI_TIMER_EXPIRE             HZ
++
++static void napi_timer_handler(unsigned long priv)
++{
++      struct mtk_eth *eth = (struct mtk_eth*) priv;
++
++      mtk_wake_queue(eth);
++      mtk_handle_irq_rx(0, eth);
++      mtk_handle_irq_tx(0, eth);
++
++      mod_timer(&eth->napi_timer, jiffies + NAPI_TIMER_EXPIRE);
++}
++
+ static int mtk_open(struct net_device *dev)
+ {
+       struct mtk_mac *mac = netdev_priv(dev);
+@@ -1901,6 +1915,9 @@ static int mtk_open(struct net_device *d
+               napi_enable(&eth->rx_napi);
+               mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+               mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
++
++              setup_timer(&eth->napi_timer, napi_timer_handler, (unsigned long) eth);
++              mod_timer(&eth->napi_timer, jiffies + NAPI_TIMER_EXPIRE);
+       }
+       atomic_inc(&eth->dma_refcnt);
+@@ -1945,6 +1962,8 @@ static int mtk_stop(struct net_device *d
+       if (!atomic_dec_and_test(&eth->dma_refcnt))
+               return 0;
++      del_timer(&eth->napi_timer);
++
+       mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+       mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
+       napi_disable(&eth->tx_napi);
+@@ -2524,7 +2543,7 @@ static int mtk_add_mac(struct mtk_eth *e
+       mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET;
+       SET_NETDEV_DEV(eth->netdev[id], eth->dev);
+-      eth->netdev[id]->watchdog_timeo = 15 * HZ;
++      eth->netdev[id]->watchdog_timeo = 30 * HZ;
+       eth->netdev[id]->netdev_ops = &mtk_netdev_ops;
+       eth->netdev[id]->base_addr = (unsigned long)eth->base;
+Index: linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+===================================================================
+--- linux-4.9.44.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -601,6 +601,8 @@ struct mtk_eth {
+       struct mii_bus                  *mii_bus;
+       struct work_struct              pending_work;
+       unsigned long                   state;
++
++      struct timer_list               napi_timer;
+ };
+ /* struct mtk_mac -   the structure that holds the info about the MACs of the
diff --git a/target/linux/mediatek/patches-4.9/0061-eth-up_down_lock.patch b/target/linux/mediatek/patches-4.9/0061-eth-up_down_lock.patch
new file mode 100644 (file)
index 0000000..20f10a3
--- /dev/null
@@ -0,0 +1,76 @@
+Index: linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+===================================================================
+--- linux-4.9.44.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -1904,12 +1904,16 @@ static int mtk_open(struct net_device *d
+       struct mtk_mac *mac = netdev_priv(dev);
+       struct mtk_eth *eth = mac->hw;
++      spin_lock(&eth->iface_lock);
++
+       /* we run 2 netdevs on the same dma ring so we only bring it up once */
+       if (!atomic_read(&eth->dma_refcnt)) {
+               int err = mtk_start_dma(eth);
+-              if (err)
++              if (err) {
++                      spin_unlock(&eth->iface_lock);
+                       return err;
++              }
+               napi_enable(&eth->tx_napi);
+               napi_enable(&eth->rx_napi);
+@@ -1923,6 +1927,7 @@ static int mtk_open(struct net_device *d
+       phy_start(dev->phydev);
+       netif_start_queue(dev);
++      spin_unlock(&eth->iface_lock);
+       return 0;
+ }
+@@ -1955,12 +1960,15 @@ static int mtk_stop(struct net_device *d
+       struct mtk_mac *mac = netdev_priv(dev);
+       struct mtk_eth *eth = mac->hw;
++      spin_lock(&eth->iface_lock);
+       netif_tx_disable(dev);
+       phy_stop(dev->phydev);
+       /* only shutdown DMA if this is the last user */
+-      if (!atomic_dec_and_test(&eth->dma_refcnt))
++      if (!atomic_dec_and_test(&eth->dma_refcnt)) {
++              spin_unlock(&eth->iface_lock);
+               return 0;
++      }
+       del_timer(&eth->napi_timer);
+@@ -1974,6 +1982,8 @@ static int mtk_stop(struct net_device *d
+       mtk_dma_free(eth);
++      spin_unlock(&eth->iface_lock);
++
+       return 0;
+ }
+@@ -2623,6 +2633,7 @@ static int mtk_probe(struct platform_dev
+       if (IS_ERR(eth->base))
+               return PTR_ERR(eth->base);
++      spin_lock_init(&eth->iface_lock);
+       spin_lock_init(&eth->page_lock);
+       spin_lock_init(&eth->tx_irq_lock);
+       spin_lock_init(&eth->rx_irq_lock);
+Index: linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+===================================================================
+--- linux-4.9.44.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ linux-4.9.44/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -573,6 +573,7 @@ struct mtk_rx_ring {
+ struct mtk_eth {
+       struct device                   *dev;
+       void __iomem                    *base;
++      spinlock_t                      iface_lock;
+       spinlock_t                      page_lock;
+       spinlock_t                      tx_irq_lock;
+       spinlock_t                      rx_irq_lock;