diff --git a/patches/lede/0102-ar71xx-ag71xx_ar7240_get_port_link-fix-off-by-one-check-on-argument-port.patch b/patches/lede/0102-ar71xx-ag71xx_ar7240_get_port_link-fix-off-by-one-check-on-argument-port.patch new file mode 100644 index 00000000..d7f19d3d --- /dev/null +++ b/patches/lede/0102-ar71xx-ag71xx_ar7240_get_port_link-fix-off-by-one-check-on-argument-port.patch @@ -0,0 +1,29 @@ +From: Alexander Couzens +Date: Sun, 11 Jun 2017 12:43:24 +0200 +Subject: ar71xx/ag71xx_ar7240_get_port_link: fix off-by-one check on argument `port` + +Found-by: Coverity Scan #1329901 +Signed-off-by: Alexander Couzens + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c +index c5aed0d2dbfcc726f54ca7eaf7dde2f7aba03ca7..e457acb50cf03e2ece5584843d6ce437da8bb8cb 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c +@@ -963,7 +963,7 @@ ar7240_get_port_link(struct switch_dev *dev, int port, + struct mii_bus *mii = as->mii_bus; + u32 status; + +- if (port > AR7240_NUM_PORTS) ++ if (port >= AR7240_NUM_PORTS) + return -EINVAL; + + status = ar7240sw_reg_read(mii, AR7240_REG_PORT_STATUS(port)); +@@ -1000,7 +1000,7 @@ ar7240_get_port_stats(struct switch_dev *dev, int port, + { + struct ar7240sw *as = sw_to_ar7240(dev); + +- if (port > AR7240_NUM_PORTS) ++ if (port >= AR7240_NUM_PORTS) + return -EINVAL; + + ar7240sw_capture_stats(as); diff --git a/patches/lede/0103-ar71xx-ag71xx_mdio_probe-fix-a-memory-leak-when-probe-fails.patch b/patches/lede/0103-ar71xx-ag71xx_mdio_probe-fix-a-memory-leak-when-probe-fails.patch new file mode 100644 index 00000000..38f44916 --- /dev/null +++ b/patches/lede/0103-ar71xx-ag71xx_mdio_probe-fix-a-memory-leak-when-probe-fails.patch @@ -0,0 +1,20 @@ +From: Alexander Couzens +Date: Sun, 11 Jun 2017 12:49:19 +0200 +Subject: ar71xx/ag71xx_mdio_probe: fix a memory leak when probe fails + +Found-by: Coverity Scan #1330233 +Signed-off-by: Alexander Couzens + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +index 71ae8258b2ef20f7d20ceacec59011ab3babfe23..b63a4b7f9d9f4b997843aa4a91c385ea186d67e2 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c +@@ -234,7 +234,7 @@ static int ag71xx_mdio_probe(struct platform_device *pdev) + if (!res) { + dev_err(&pdev->dev, "no iomem resource found\n"); + err = -ENXIO; +- goto err_out; ++ goto err_free_mdio; + } + + am->mdio_base = ioremap_nocache(res->start, res->end - res->start + 1); diff --git a/patches/lede/0104-ar71xx-ag71xx_ethtool-don-t-return-uninitialized-return-value-on-success.patch b/patches/lede/0104-ar71xx-ag71xx_ethtool-don-t-return-uninitialized-return-value-on-success.patch new file mode 100644 index 00000000..494baedd --- /dev/null +++ b/patches/lede/0104-ar71xx-ag71xx_ethtool-don-t-return-uninitialized-return-value-on-success.patch @@ -0,0 +1,23 @@ +From: Alexander Couzens +Date: Sun, 11 Jun 2017 12:51:58 +0200 +Subject: ar71xx/ag71xx_ethtool: don't return uninitialized return value on success + +ag71xx_ethtool_set_ringparam() will return an uninitialized value on +success. + +Found-by: Coverity Scan #1330877 +Signed-off-by: Alexander Couzens + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c +index dfcbb54e93a298eee7858d6b26e533e0aeefb00b..f0e102152f269c6604925421de6ca27ccc6bb6ad 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c +@@ -86,7 +86,7 @@ static int ag71xx_ethtool_set_ringparam(struct net_device *dev, + struct ag71xx *ag = netdev_priv(dev); + unsigned tx_size; + unsigned rx_size; +- int err; ++ int err = 0; + + if (er->rx_mini_pending != 0|| + er->rx_jumbo_pending != 0 || diff --git a/patches/lede/0105-ag71xx-Switch-from-driver-to-kernel-macro-for-NAPI_WEIGHT.patch b/patches/lede/0105-ag71xx-Switch-from-driver-to-kernel-macro-for-NAPI_WEIGHT.patch new file mode 100644 index 00000000..9e2ae6b4 --- /dev/null +++ b/patches/lede/0105-ag71xx-Switch-from-driver-to-kernel-macro-for-NAPI_WEIGHT.patch @@ -0,0 +1,75 @@ +From: Rosen Penev +Date: Tue, 17 Oct 2017 09:25:56 -0700 +Subject: ag71xx: Switch from driver to kernel macro for NAPI_WEIGHT. + +NAPI_POLL_WEIGHT was introduced in the kernel for exactly this purpose 5 years ago. + +Signed-off-by: Rosen Penev + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +index 898bde1d257bb70801f4f585c1aa278ebb9d0030..7b1cc1e1032f7b87430a9be1507ddb3e3faa26bc 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +@@ -40,7 +40,6 @@ + #define AG71XX_DRV_NAME "ag71xx" + #define AG71XX_DRV_VERSION "0.5.35" + +-#define AG71XX_NAPI_WEIGHT 64 + #define AG71XX_OOM_REFILL (1 + HZ/10) + + #define AG71XX_INT_ERR (AG71XX_INT_RX_BE | AG71XX_INT_TX_BE) +@@ -136,8 +135,8 @@ struct ag71xx_napi_stats { + unsigned long tx_packets; + unsigned long tx_packets_max; + +- unsigned long rx[AG71XX_NAPI_WEIGHT + 1]; +- unsigned long tx[AG71XX_NAPI_WEIGHT + 1]; ++ unsigned long rx[NAPI_POLL_WEIGHT + 1]; ++ unsigned long tx[NAPI_POLL_WEIGHT + 1]; + }; + + struct ag71xx_debug { +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c +index c86803c9ceda7c57f643df29acc8254768b3d264..89cea0c0f5ae97c9917cd13e1ee89bd31fe45e58 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c +@@ -78,7 +78,7 @@ void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx) + if (rx) { + stats->rx_count++; + stats->rx_packets += rx; +- if (rx <= AG71XX_NAPI_WEIGHT) ++ if (rx <= NAPI_POLL_WEIGHT) + stats->rx[rx]++; + if (rx > stats->rx_packets_max) + stats->rx_packets_max = rx; +@@ -87,7 +87,7 @@ void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx) + if (tx) { + stats->tx_count++; + stats->tx_packets += tx; +- if (tx <= AG71XX_NAPI_WEIGHT) ++ if (tx <= NAPI_POLL_WEIGHT) + stats->tx[tx]++; + if (tx > stats->tx_packets_max) + stats->tx_packets_max = tx; +@@ -121,7 +121,7 @@ static ssize_t read_file_napi_stats(struct file *file, char __user *user_buf, + len += snprintf(buf + len, buflen - len, "%3s %10s %10s\n", + "len", "rx", "tx"); + +- for (i = 1; i <= AG71XX_NAPI_WEIGHT; i++) ++ for (i = 1; i <= NAPI_POLL_WEIGHT; i++) + len += snprintf(buf + len, buflen - len, + "%3d: %10lu %10lu\n", + i, stats->rx[i], stats->tx[i]); +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +index 72dd654a691355c881b15d796fad0d640e05fc15..b675c99f168bd5a6ea238c8321534bb0b8925521 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -1376,7 +1376,7 @@ static int ag71xx_probe(struct platform_device *pdev) + + memcpy(dev->dev_addr, pdata->mac_addr, ETH_ALEN); + +- netif_napi_add(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); ++ netif_napi_add(dev, &ag->napi, ag71xx_poll, NAPI_POLL_WEIGHT); + + ag71xx_dump_regs(ag); + diff --git a/patches/lede/0106-ag71xx-Reduce-NAPI-weight-to-32.patch b/patches/lede/0106-ag71xx-Reduce-NAPI-weight-to-32.patch new file mode 100644 index 00000000..c759e085 --- /dev/null +++ b/patches/lede/0106-ag71xx-Reduce-NAPI-weight-to-32.patch @@ -0,0 +1,33 @@ +From: Rosen Penev +Date: Mon, 4 Dec 2017 11:40:22 -0800 +Subject: ag71xx: Reduce NAPI weight to 32. + +Qualcomm claims this reduces cache misses. Original commit message below: + +From: Ben Menchaca +Date: Tue, 11 Jun 2013 12:18:46 -0500 +Subject: [ag71xx] reduce NAPI weight + +In an attempt to increase our cache warmth, we are decreasing NAPI. +This increases the warmth of the reused SKBs. + +Signed-off-by: Ben Menchaca +Signed-off-by: Rosen Penev + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +index 7b1cc1e1032f7b87430a9be1507ddb3e3faa26bc..71fbe8975b22c291ed13bb549f6b4d2951ff67c0 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +@@ -40,6 +40,12 @@ + #define AG71XX_DRV_NAME "ag71xx" + #define AG71XX_DRV_VERSION "0.5.35" + ++/* ++ * For our NAPI weight bigger does *NOT* mean better - it means more ++ * D-cache misses and lots more wasted cycles than we'll ever ++ * possibly gain from saving instructions. ++ */ ++#define AG71XX_NAPI_WEIGHT 32 + #define AG71XX_OOM_REFILL (1 + HZ/10) + + #define AG71XX_INT_ERR (AG71XX_INT_RX_BE | AG71XX_INT_TX_BE) diff --git a/patches/lede/0107-ag71xx-Reorder-ag71xx-struct-members-for-better-cache-performance.patch b/patches/lede/0107-ag71xx-Reorder-ag71xx-struct-members-for-better-cache-performance.patch new file mode 100644 index 00000000..40d41490 --- /dev/null +++ b/patches/lede/0107-ag71xx-Reorder-ag71xx-struct-members-for-better-cache-performance.patch @@ -0,0 +1,70 @@ +From: Rosen Penev +Date: Mon, 4 Dec 2017 11:40:23 -0800 +Subject: ag71xx: Reorder ag71xx struct members for better cache performance + +Qualcomm claims this improves the D-cache footprint. Origina commit message below: + +From: Ben Menchaca +Date: Fri, 7 Jun 2013 10:57:28 -0500 +Subject: [ag71xx] cluster/align structs for cache perf + +Cluster the frequently used, per-packet structures in ag71xx near +to each other, and cacheline-align them. Some other re-ordering +occurred to move "warmer" structures near the per-packet structures. + +Signed-off-by: Ben Menchaca +Signed-off-by: Rosen Penev + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +index 71fbe8975b22c291ed13bb549f6b4d2951ff67c0..d50ea81263744b5dd7e2ffa0c1d9c1061ef0ba8d 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +@@ -153,20 +153,31 @@ struct ag71xx_debug { + }; + + struct ag71xx { +- void __iomem *mac_base; ++ /* ++ * Critical data related to the per-packet data path are clustered ++ * early in this structure to help improve the D-cache footprint. ++ */ ++ struct ag71xx_ring rx_ring ____cacheline_aligned; ++ struct ag71xx_ring tx_ring ____cacheline_aligned; ++ ++ unsigned int max_frame_len; ++ unsigned int desc_pktlen_mask; ++ unsigned int rx_buf_size; + +- spinlock_t lock; +- struct platform_device *pdev; + struct net_device *dev; ++ struct platform_device *pdev; ++ spinlock_t lock; + struct napi_struct napi; + u32 msg_enable; + ++ /* ++ * From this point onwards we're not looking at per-packet fields. ++ */ ++ void __iomem *mac_base; ++ + struct ag71xx_desc *stop_desc; + dma_addr_t stop_desc_dma; + +- struct ag71xx_ring rx_ring; +- struct ag71xx_ring tx_ring; +- + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + void *phy_priv; +@@ -175,10 +186,6 @@ struct ag71xx { + unsigned int speed; + int duplex; + +- unsigned int max_frame_len; +- unsigned int desc_pktlen_mask; +- unsigned int rx_buf_size; +- + struct delayed_work restart_work; + struct delayed_work link_work; + struct timer_list oom_timer; diff --git a/patches/lede/0108-ar71xx-allocate-rx-tx-descriptor-buffers-in-one-chunk.patch b/patches/lede/0108-ar71xx-allocate-rx-tx-descriptor-buffers-in-one-chunk.patch new file mode 100644 index 00000000..9f6c3150 --- /dev/null +++ b/patches/lede/0108-ar71xx-allocate-rx-tx-descriptor-buffers-in-one-chunk.patch @@ -0,0 +1,123 @@ +From: Felix Fietkau +Date: Tue, 5 Dec 2017 14:17:24 +0100 +Subject: ar71xx: allocate rx/tx descriptor/buffers in one chunk + +Reduces false sharing due to cache aliases + +Signed-off-by: Felix Fietkau + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +index b675c99f168bd5a6ea238c8321534bb0b8925521..1cb590fad044d54fe1cfd0e765aa43ee981ae9c1 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -97,41 +97,6 @@ static inline void ag71xx_dump_intr(struct ag71xx *ag, char *label, u32 intr) + (intr & AG71XX_INT_RX_BE) ? "RXBE " : ""); + } + +-static void ag71xx_ring_free(struct ag71xx_ring *ring) +-{ +- int ring_size = BIT(ring->order); +- kfree(ring->buf); +- +- if (ring->descs_cpu) +- dma_free_coherent(NULL, ring_size * AG71XX_DESC_SIZE, +- ring->descs_cpu, ring->descs_dma); +-} +- +-static int ag71xx_ring_alloc(struct ag71xx_ring *ring) +-{ +- int ring_size = BIT(ring->order); +- int err; +- +- ring->descs_cpu = dma_alloc_coherent(NULL, ring_size * AG71XX_DESC_SIZE, +- &ring->descs_dma, GFP_ATOMIC); +- if (!ring->descs_cpu) { +- err = -ENOMEM; +- goto err; +- } +- +- +- ring->buf = kzalloc(ring_size * sizeof(*ring->buf), GFP_KERNEL); +- if (!ring->buf) { +- err = -ENOMEM; +- goto err; +- } +- +- return 0; +- +-err: +- return err; +-} +- + static void ag71xx_ring_tx_clean(struct ag71xx *ag) + { + struct ag71xx_ring *ring = &ag->tx_ring; +@@ -322,30 +287,56 @@ static int ag71xx_ring_rx_refill(struct ag71xx *ag) + + static int ag71xx_rings_init(struct ag71xx *ag) + { +- int ret; ++ struct ag71xx_ring *tx = &ag->tx_ring; ++ struct ag71xx_ring *rx = &ag->rx_ring; ++ int ring_size = BIT(tx->order) + BIT(rx->order); ++ int tx_size = BIT(tx->order); ++ ++ tx->buf = kzalloc(ring_size * sizeof(*tx->buf), GFP_KERNEL); ++ if (!tx->buf) ++ return -ENOMEM; ++ ++ tx->descs_cpu = dma_alloc_coherent(NULL, ring_size * AG71XX_DESC_SIZE, ++ &tx->descs_dma, GFP_ATOMIC); ++ if (!tx->descs_cpu) { ++ kfree(tx->buf); ++ tx->buf = NULL; ++ return -ENOMEM; ++ } + +- ret = ag71xx_ring_alloc(&ag->tx_ring); +- if (ret) +- return ret; ++ rx->buf = &tx->buf[BIT(tx->order)]; ++ rx->descs_cpu = ((void *)tx->descs_cpu) + tx_size * AG71XX_DESC_SIZE; ++ rx->descs_dma = tx->descs_dma + tx_size * AG71XX_DESC_SIZE; + + ag71xx_ring_tx_init(ag); ++ return ag71xx_ring_rx_init(ag); ++} + +- ret = ag71xx_ring_alloc(&ag->rx_ring); +- if (ret) +- return ret; ++static void ag71xx_rings_free(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *tx = &ag->tx_ring; ++ struct ag71xx_ring *rx = &ag->rx_ring; ++ int ring_size = BIT(tx->order) + BIT(rx->order); + +- ret = ag71xx_ring_rx_init(ag); +- return ret; ++ if (tx->descs_cpu) ++ dma_free_coherent(NULL, ring_size * AG71XX_DESC_SIZE, ++ tx->descs_cpu, tx->descs_dma); ++ ++ kfree(tx->buf); ++ ++ tx->descs_cpu = NULL; ++ rx->descs_cpu = NULL; ++ tx->buf = NULL; ++ rx->buf = NULL; + } + + static void ag71xx_rings_cleanup(struct ag71xx *ag) + { + ag71xx_ring_rx_clean(ag); +- ag71xx_ring_free(&ag->rx_ring); +- + ag71xx_ring_tx_clean(ag); ++ ag71xx_rings_free(ag); ++ + netdev_reset_queue(ag->dev); +- ag71xx_ring_free(&ag->tx_ring); + } + + static unsigned char *ag71xx_speed_str(struct ag71xx *ag) diff --git a/patches/lede/0109-ar71xx-only-access-device-stats-in-tx-handler-if-packets-were-processed.patch b/patches/lede/0109-ar71xx-only-access-device-stats-in-tx-handler-if-packets-were-processed.patch new file mode 100644 index 00000000..a9546d82 --- /dev/null +++ b/patches/lede/0109-ar71xx-only-access-device-stats-in-tx-handler-if-packets-were-processed.patch @@ -0,0 +1,26 @@ +From: Felix Fietkau +Date: Tue, 5 Dec 2017 14:23:59 +0100 +Subject: ar71xx: only access device stats in tx handler if packets were processed + +Signed-off-by: Felix Fietkau + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +index 1cb590fad044d54fe1cfd0e765aa43ee981ae9c1..6a8558284ed6a1feb1fddfe2875ba182c78a95d4 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -1006,12 +1006,12 @@ static int ag71xx_tx_packets(struct ag71xx *ag, bool flush) + + DBG("%s: %d packets sent out\n", ag->dev->name, sent); + +- ag->dev->stats.tx_bytes += bytes_compl; +- ag->dev->stats.tx_packets += sent; +- + if (!sent) + return 0; + ++ ag->dev->stats.tx_bytes += bytes_compl; ++ ag->dev->stats.tx_packets += sent; ++ + netdev_completed_queue(ag->dev, sent, bytes_compl); + if ((ring->curr - ring->dirty) < (ring_size * 3) / 4) + netif_wake_queue(ag->dev); diff --git a/patches/lede/0110-ar71xx-use-global-timestamp-for-hang-check.patch b/patches/lede/0110-ar71xx-use-global-timestamp-for-hang-check.patch new file mode 100644 index 00000000..877f99ae --- /dev/null +++ b/patches/lede/0110-ar71xx-use-global-timestamp-for-hang-check.patch @@ -0,0 +1,69 @@ +From: Felix Fietkau +Date: Tue, 5 Dec 2017 14:40:32 +0100 +Subject: ar71xx: use global timestamp for hang check + +Shrink the size of struct ag71xx_buf to 8 bytes, which improves cache +footprint + +Signed-off-by: Felix Fietkau + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +index d50ea81263744b5dd7e2ffa0c1d9c1061ef0ba8d..24ed2f56e41cf5fe1974c24786194620627a192b 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +@@ -100,9 +100,8 @@ struct ag71xx_buf { + }; + union { + dma_addr_t dma_addr; +- unsigned long timestamp; ++ unsigned int len; + }; +- unsigned int len; + }; + + struct ag71xx_ring { +@@ -170,6 +169,8 @@ struct ag71xx { + struct napi_struct napi; + u32 msg_enable; + ++ unsigned long timestamp; ++ + /* + * From this point onwards we're not looking at per-packet fields. + */ +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +index 6a8558284ed6a1feb1fddfe2875ba182c78a95d4..bc876e9d73e3e26143cfac0d5484e7900dd9db01 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -823,7 +823,7 @@ static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, + i = (ring->curr + n - 1) & ring_mask; + ring->buf[i].len = skb->len; + ring->buf[i].skb = skb; +- ring->buf[i].timestamp = jiffies; ++ ag->timestamp = jiffies; + + netdev_sent_queue(dev, skb->len); + +@@ -933,11 +933,11 @@ static void ag71xx_restart_work_func(struct work_struct *work) + rtnl_unlock(); + } + +-static bool ag71xx_check_dma_stuck(struct ag71xx *ag, unsigned long timestamp) ++static bool ag71xx_check_dma_stuck(struct ag71xx *ag) + { + u32 rx_sm, tx_sm, rx_fd; + +- if (likely(time_before(jiffies, timestamp + HZ/10))) ++ if (likely(time_before(jiffies, ag->timestamp + HZ/10))) + return false; + + if (!netif_carrier_ok(ag->dev)) +@@ -976,7 +976,7 @@ static int ag71xx_tx_packets(struct ag71xx *ag, bool flush) + + if (!flush && !ag71xx_desc_empty(desc)) { + if (pdata->is_ar724x && +- ag71xx_check_dma_stuck(ag, ring->buf[i].timestamp)) { ++ ag71xx_check_dma_stuck(ag)) { + schedule_delayed_work(&ag->restart_work, HZ / 2); + dma_stuck = true; + } diff --git a/patches/lede/0111-ag71xx-Move-timestamp-struct-member-outside-of-struct.patch b/patches/lede/0111-ag71xx-Move-timestamp-struct-member-outside-of-struct.patch new file mode 100644 index 00000000..a670737b --- /dev/null +++ b/patches/lede/0111-ag71xx-Move-timestamp-struct-member-outside-of-struct.patch @@ -0,0 +1,55 @@ +From: Rosen Penev +Date: Wed, 7 Feb 2018 13:57:30 -0800 +Subject: ag71xx: Move timestamp struct member outside of struct. + +With this change, the timestamp variable is only used in ag71xx_check_dma_stuck. Small tx speedup. + +Based on a Qualcomm commit. ag->timestamp = jiffies was not replaced with netif_trans_update(dev) because of this quote: + +It should be noted that after this series several instances +of netif_trans_update() are useless (if they occur in +.ndo_start_xmit and driver doesn't set LLTX flag -- stack already +did an update). + +From: http://lists.openwall.net/netdev/2016/05/03/87 + +Signed-off-by: Rosen Penev + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +index 24ed2f56e41cf5fe1974c24786194620627a192b..0927b1871ee6dbf76b7775c7882e67a0cf5b2503 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +@@ -169,8 +169,6 @@ struct ag71xx { + struct napi_struct napi; + u32 msg_enable; + +- unsigned long timestamp; +- + /* + * From this point onwards we're not looking at per-packet fields. + */ +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +index bc876e9d73e3e26143cfac0d5484e7900dd9db01..2f4218e08a9749ffc45c8265e7931f205e8e7935 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -823,7 +823,6 @@ static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, + i = (ring->curr + n - 1) & ring_mask; + ring->buf[i].len = skb->len; + ring->buf[i].skb = skb; +- ag->timestamp = jiffies; + + netdev_sent_queue(dev, skb->len); + +@@ -935,9 +934,11 @@ static void ag71xx_restart_work_func(struct work_struct *work) + + static bool ag71xx_check_dma_stuck(struct ag71xx *ag) + { ++ unsigned long timestamp; + u32 rx_sm, tx_sm, rx_fd; + +- if (likely(time_before(jiffies, ag->timestamp + HZ/10))) ++ timestamp = netdev_get_tx_queue(ag->dev, 0)->trans_start; ++ if (likely(time_before(jiffies, timestamp + HZ/10))) + return false; + + if (!netif_carrier_ok(ag->dev)) diff --git a/patches/lede/0112-ar71xx-fix-build-with-ag71xx-debugfs-support-enabled.patch b/patches/lede/0112-ar71xx-fix-build-with-ag71xx-debugfs-support-enabled.patch new file mode 100644 index 00000000..651466bf --- /dev/null +++ b/patches/lede/0112-ar71xx-fix-build-with-ag71xx-debugfs-support-enabled.patch @@ -0,0 +1,45 @@ +From: Felix Fietkau +Date: Wed, 28 Feb 2018 13:57:58 +0100 +Subject: ar71xx: fix build with ag71xx debugfs support enabled + +Signed-off-by: Felix Fietkau + +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c +index 89cea0c0f5ae97c9917cd13e1ee89bd31fe45e58..20910b9681a54e53f3e089d0a589e1b2b45c1833 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c +@@ -175,8 +175,8 @@ static ssize_t read_file_ring(struct file *file, char __user *user_buf, + return -ENOMEM; + + len += snprintf(buf + len, buflen - len, +- "Idx ... %-8s %-8s %-8s %-8s . %-10s\n", +- "desc", "next", "data", "ctrl", "timestamp"); ++ "Idx ... %-8s %-8s %-8s %-8s .\n", ++ "desc", "next", "data", "ctrl"); + + spin_lock_irqsave(&ag->lock, flags); + +@@ -184,12 +184,11 @@ static ssize_t read_file_ring(struct file *file, char __user *user_buf, + dirty = (ring->dirty & ring_mask); + desc_hw = ag71xx_rr(ag, desc_reg); + for (i = 0; i < ring_size; i++) { +- struct ag71xx_buf *ab = &ring->buf[i]; + struct ag71xx_desc *desc = ag71xx_ring_desc(ring, i); + u32 desc_dma = ((u32) ring->descs_dma) + i * AG71XX_DESC_SIZE; + + len += snprintf(buf + len, buflen - len, +- "%3d %c%c%c %08x %08x %08x %08x %c %10lu\n", ++ "%3d %c%c%c %08x %08x %08x %08x %c\n", + i, + (i == curr) ? 'C' : ' ', + (i == dirty) ? 'D' : ' ', +@@ -198,8 +197,7 @@ static ssize_t read_file_ring(struct file *file, char __user *user_buf, + desc->next, + desc->data, + desc->ctrl, +- (desc->ctrl & DESC_EMPTY) ? 'E' : '*', +- ab->timestamp); ++ (desc->ctrl & DESC_EMPTY) ? 'E' : '*'); + } + + spin_unlock_irqrestore(&ag->lock, flags); diff --git a/patches/lede/0113-ar71xx-remove-pdata-fifo_cfg.patch b/patches/lede/0113-ar71xx-remove-pdata-fifo_cfg.patch new file mode 100644 index 00000000..cdb3cbb3 --- /dev/null +++ b/patches/lede/0113-ar71xx-remove-pdata-fifo_cfg.patch @@ -0,0 +1,149 @@ +From: Felix Fietkau +Date: Fri, 2 Mar 2018 21:30:10 +0100 +Subject: ar71xx: remove pdata->fifo_cfg* + +The values are the same for all chipsets that use it + +Signed-off-by: Felix Fietkau + +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c +index 5f971ea32d35035617229076b7a7fc30ed4d2dcc..b46bab7886c363a1559da6f4d7ad0c8e27b7ae10 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c +@@ -900,13 +900,6 @@ void __init ath79_register_eth(unsigned int id) + } + pdata->has_gbit = 1; + pdata->is_ar724x = 1; +- +- if (!pdata->fifo_cfg1) +- pdata->fifo_cfg1 = 0x0010ffff; +- if (!pdata->fifo_cfg2) +- pdata->fifo_cfg2 = 0x015500aa; +- if (!pdata->fifo_cfg3) +- pdata->fifo_cfg3 = 0x01f00140; + break; + + case ATH79_SOC_AR7241: +@@ -936,13 +929,6 @@ void __init ath79_register_eth(unsigned int id) + pdata->is_ar724x = 1; + if (ath79_soc == ATH79_SOC_AR7240) + pdata->is_ar7240 = 1; +- +- if (!pdata->fifo_cfg1) +- pdata->fifo_cfg1 = 0x0010ffff; +- if (!pdata->fifo_cfg2) +- pdata->fifo_cfg2 = 0x015500aa; +- if (!pdata->fifo_cfg3) +- pdata->fifo_cfg3 = 0x01f00140; + break; + + case ATH79_SOC_AR9132: +@@ -979,13 +965,6 @@ void __init ath79_register_eth(unsigned int id) + } + + pdata->is_ar724x = 1; +- +- if (!pdata->fifo_cfg1) +- pdata->fifo_cfg1 = 0x0010ffff; +- if (!pdata->fifo_cfg2) +- pdata->fifo_cfg2 = 0x015500aa; +- if (!pdata->fifo_cfg3) +- pdata->fifo_cfg3 = 0x01f00140; + break; + + case ATH79_SOC_AR9341: +@@ -1016,13 +995,6 @@ void __init ath79_register_eth(unsigned int id) + + pdata->max_frame_len = SZ_16K - 1; + pdata->desc_pktlen_mask = SZ_16K - 1; +- +- if (!pdata->fifo_cfg1) +- pdata->fifo_cfg1 = 0x0010ffff; +- if (!pdata->fifo_cfg2) +- pdata->fifo_cfg2 = 0x015500aa; +- if (!pdata->fifo_cfg3) +- pdata->fifo_cfg3 = 0x01f00140; + break; + + case ATH79_SOC_TP9343: +@@ -1048,13 +1020,6 @@ void __init ath79_register_eth(unsigned int id) + + pdata->has_gbit = 1; + pdata->is_ar724x = 1; +- +- if (!pdata->fifo_cfg1) +- pdata->fifo_cfg1 = 0x0010ffff; +- if (!pdata->fifo_cfg2) +- pdata->fifo_cfg2 = 0x015500aa; +- if (!pdata->fifo_cfg3) +- pdata->fifo_cfg3 = 0x01f00140; + break; + + case ATH79_SOC_QCA9556: +@@ -1082,13 +1047,6 @@ void __init ath79_register_eth(unsigned int id) + */ + pdata->max_frame_len = SZ_4K - 1; + pdata->desc_pktlen_mask = SZ_16K - 1; +- +- if (!pdata->fifo_cfg1) +- pdata->fifo_cfg1 = 0x0010ffff; +- if (!pdata->fifo_cfg2) +- pdata->fifo_cfg2 = 0x015500aa; +- if (!pdata->fifo_cfg3) +- pdata->fifo_cfg3 = 0x01f00140; + break; + + case ATH79_SOC_QCA956X: +@@ -1121,13 +1079,6 @@ void __init ath79_register_eth(unsigned int id) + + pdata->has_gbit = 1; + pdata->is_ar724x = 1; +- +- if (!pdata->fifo_cfg1) +- pdata->fifo_cfg1 = 0x0010ffff; +- if (!pdata->fifo_cfg2) +- pdata->fifo_cfg2 = 0x015500aa; +- if (!pdata->fifo_cfg3) +- pdata->fifo_cfg3 = 0x01f00140; + break; + + default: +diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h +index 5fdc59c7b78b84670daefa9fd831b154ded84ddc..c4c3a6d44c935b84b5d6dae58a4f441e5492463c 100644 +--- a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h ++++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ath79/ag71xx_platform.h +@@ -45,10 +45,6 @@ struct ag71xx_platform_data { + void (*set_speed)(int speed); + void (*update_pll)(u32 pll_10, u32 pll_100, u32 pll_1000); + +- u32 fifo_cfg1; +- u32 fifo_cfg2; +- u32 fifo_cfg3; +- + unsigned int max_frame_len; + unsigned int desc_pktlen_mask; + }; +diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +index 2f4218e08a9749ffc45c8265e7931f205e8e7935..33237e01e6b191ff30449458f1a22ee44ba6d9e2 100644 +--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c ++++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +@@ -460,8 +460,8 @@ static void ag71xx_hw_setup(struct ag71xx *ag) + /* setup FIFO configuration registers */ + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT); + if (pdata->is_ar724x) { +- ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, pdata->fifo_cfg1); +- ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, pdata->fifo_cfg2); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0010ffff); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x015500aa); + } else { + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000); + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff); +@@ -603,7 +603,7 @@ __ag71xx_link_adjust(struct ag71xx *ag, bool update) + if (pdata->is_ar91xx) + fifo3 = 0x00780fff; + else if (pdata->is_ar724x) +- fifo3 = pdata->fifo_cfg3; ++ fifo3 = 0x01f00140; + else + fifo3 = 0x008001ff; +