[][Add Ethernet ADMAv1/v2 RSS Support for NETSYS-2.0]

[Description]
Add Ethernet ADMAv1/v2 RSS Support for NETSYS-2.0

[Release-log]
N/A

Change-Id: I6f3d11a9d10815b975087a298e715b017718ab29
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/4776973
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ac5ddd4..89c6a3e 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1312,9 +1312,6 @@
 	struct mtk_rx_ring *ring;
 	int idx;
 
-	if (!eth->hwlro)
-		return &eth->rx_ring[0];
-
 	for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
 		if (!IS_NORMAL_RING(i) && !IS_HW_LRO_RING(i))
 			continue;
@@ -1330,13 +1327,14 @@
 	return NULL;
 }
 
-static void mtk_update_rx_cpu_idx(struct mtk_eth *eth)
+static void mtk_update_rx_cpu_idx(struct mtk_eth *eth, struct mtk_rx_ring *ring)
 {
-	struct mtk_rx_ring *ring;
 	int i;
 
 	if (!eth->hwlro) {
-		ring = &eth->rx_ring[0];
+		if (unlikely(!ring))
+			dev_info(eth->dev, "Update Rx cpu index failed !\n");
+
 		mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
 	} else {
 		for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
@@ -1352,20 +1350,26 @@
 static int mtk_poll_rx(struct napi_struct *napi, int budget,
 		       struct mtk_eth *eth)
 {
-	struct mtk_rx_ring *ring;
+	struct mtk_napi *rx_napi = container_of(napi, struct mtk_napi, napi);
+	struct mtk_rx_ring *ring = rx_napi->rx_ring;
 	int idx;
 	struct sk_buff *skb;
 	u8 *data, *new_data;
 	struct mtk_rx_dma *rxd, trxd;
 	int done = 0;
 
+	if (unlikely(!ring))
+		goto rx_done;
+
 	while (done < budget) {
 		struct net_device *netdev;
 		unsigned int pktlen;
 		dma_addr_t dma_addr;
 		int mac;
 
-		ring = mtk_get_rx_ring(eth);
+		if (eth->hwlro)
+			ring = mtk_get_rx_ring(eth);
+
 		if (unlikely(!ring))
 			goto rx_done;
 
@@ -1515,7 +1519,7 @@
 		 * we continue
 		 */
 		wmb();
-		mtk_update_rx_cpu_idx(eth);
+		mtk_update_rx_cpu_idx(eth, ring);
 	}
 
 	return done;
@@ -1683,7 +1687,9 @@
 
 static int mtk_napi_rx(struct napi_struct *napi, int budget)
 {
-	struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
+	struct mtk_napi *rx_napi = container_of(napi, struct mtk_napi, napi);
+	struct mtk_eth *eth = rx_napi->eth;
+	struct mtk_rx_ring *ring = rx_napi->rx_ring;
 	u32 status, mask;
 	int rx_done = 0;
 	int remain_budget = budget;
@@ -1691,7 +1697,7 @@
 	mtk_handle_status_irq(eth);
 
 poll_again:
-	mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_STATUS);
+	mtk_w32(eth, MTK_RX_DONE_INT(ring->ring_no), MTK_PDMA_INT_STATUS);
 	rx_done = mtk_poll_rx(napi, remain_budget, eth);
 
 	if (unlikely(netif_msg_intr(eth))) {
@@ -1705,13 +1711,13 @@
 		return budget;
 
 	status = mtk_r32(eth, MTK_PDMA_INT_STATUS);
-	if (status & MTK_RX_DONE_INT) {
+	if (status & MTK_RX_DONE_INT(ring->ring_no)) {
 		remain_budget -= rx_done;
 		goto poll_again;
 	}
 
 	if (napi_complete(napi))
-		mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
+		mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(ring->ring_no));
 
 	return rx_done + budget - remain_budget;
 }
@@ -1876,8 +1882,10 @@
 					       &ring->phys, GFP_ATOMIC);
 	else {
 		struct mtk_tx_ring *tx_ring = &eth->tx_ring;
-		ring->dma =  (struct mtk_rx_dma *)(tx_ring->dma + MTK_DMA_SIZE);
-		ring->phys = tx_ring->phys + MTK_DMA_SIZE * sizeof(*tx_ring->dma);
+		ring->dma = (struct mtk_rx_dma *)(tx_ring->dma +
+			     MTK_DMA_SIZE * (ring_no + 1));
+		ring->phys = tx_ring->phys + MTK_DMA_SIZE *
+			     sizeof(*tx_ring->dma) * (ring_no + 1);
 	}
 
 	if (!ring->dma)
@@ -2220,6 +2228,84 @@
 	return 0;
 }
 
+static int mtk_rss_init(struct mtk_eth *eth)
+{
+	u32 val;
+
+	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+		/* Set RSS rings to PSE modes */
+		val =  mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(1));
+		val |= MTK_RING_PSE_MODE;
+		mtk_w32(eth, val, MTK_LRO_CTRL_DW2_CFG(1));
+
+		/* Enable non-lro multiple rx */
+		val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0);
+		val |= MTK_NON_LRO_MULTI_EN;
+		mtk_w32(eth, val, MTK_PDMA_LRO_CTRL_DW0);
+
+		/* Enable RSS dly int supoort */
+		val |= MTK_LRO_DLY_INT_EN;
+		mtk_w32(eth, val, MTK_PDMA_LRO_CTRL_DW0);
+
+		/* Set RSS delay config int ring1 */
+		mtk_w32(eth, MTK_MAX_DELAY_INT, MTK_LRO_RX1_DLY_INT);
+	}
+
+	/* Hash Type */
+	val = mtk_r32(eth, MTK_PDMA_RSS_GLO_CFG);
+	val |= MTK_RSS_IPV4_STATIC_HASH;
+	val |= MTK_RSS_IPV6_STATIC_HASH;
+	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+
+	/* Select the size of indirection table */
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW0);
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW1);
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW2);
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW3);
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW4);
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW5);
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW6);
+	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW7);
+
+	/* Pause */
+	val |= MTK_RSS_CFG_REQ;
+	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+
+	/* Enable RSS*/
+	val |= MTK_RSS_EN;
+	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+
+	/* Release pause */
+	val &= ~(MTK_RSS_CFG_REQ);
+	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+
+	/* Set perRSS GRP INT */
+	mtk_w32(eth, MTK_RX_DONE_INT(MTK_RSS_RING1), MTK_PDMA_INT_GRP3);
+
+	/* Set GRP INT */
+	mtk_w32(eth, 0x21021030, MTK_FE_INT_GRP);
+
+	return 0;
+}
+
+static void mtk_rss_uninit(struct mtk_eth *eth)
+{
+	u32 val;
+
+	/* Pause */
+	val = mtk_r32(eth, MTK_PDMA_RSS_GLO_CFG);
+	val |= MTK_RSS_CFG_REQ;
+	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+
+	/* Disable RSS*/
+	val &= ~(MTK_RSS_EN);
+	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+
+	/* Release pause */
+	val &= ~(MTK_RSS_CFG_REQ);
+	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
+}
+
 static netdev_features_t mtk_fix_features(struct net_device *dev,
 					  netdev_features_t features)
 {
@@ -2330,6 +2416,17 @@
 			return err;
 	}
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
+			err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_NORMAL);
+			if (err)
+				return err;
+		}
+		err = mtk_rss_init(eth);
+		if (err)
+                        return err;
+	}
+
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
 		/* Enable random early drop and set drop threshold
 		 * automatically
@@ -2369,6 +2466,13 @@
 			mtk_rx_clean(eth, &eth->rx_ring[i], 0);
 	}
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		mtk_rss_uninit(eth);
+
+		for (i = 1; i < MTK_RX_NAPI_NUM; i++)
+			mtk_rx_clean(eth, &eth->rx_ring[i], 1);
+	}
+
 	kfree(eth->scratch_head);
 }
 
@@ -2383,13 +2487,15 @@
 	schedule_work(&eth->pending_work);
 }
 
-static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
+static irqreturn_t mtk_handle_irq_rx(int irq, void *priv)
 {
-	struct mtk_eth *eth = _eth;
+	struct mtk_napi *rx_napi = priv;
+	struct mtk_eth *eth = rx_napi->eth;
+	struct mtk_rx_ring *ring = rx_napi->rx_ring;
 
-	if (likely(napi_schedule_prep(&eth->rx_napi))) {
-		__napi_schedule(&eth->rx_napi);
-		mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
+	if (likely(napi_schedule_prep(&rx_napi->napi))) {
+		__napi_schedule(&rx_napi->napi);
+		mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(ring->ring_no));
 	}
 
 	return IRQ_HANDLED;
@@ -2411,9 +2517,9 @@
 {
 	struct mtk_eth *eth = _eth;
 
-	if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT) {
-		if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT)
-			mtk_handle_irq_rx(irq, _eth);
+	if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT(0)) {
+		if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT(0))
+			mtk_handle_irq_rx(irq, &eth->rx_napi[0]);
 	}
 	if (mtk_r32(eth, eth->tx_int_mask_reg) & MTK_TX_DONE_INT) {
 		if (mtk_r32(eth, eth->tx_int_status_reg) & MTK_TX_DONE_INT)
@@ -2430,10 +2536,10 @@
 	struct mtk_eth *eth = mac->hw;
 
 	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
-	mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
-	mtk_handle_irq_rx(eth->irq[2], dev);
+	mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(0));
+	mtk_handle_irq_rx(eth->irq[2], &eth->rx_napi[0]);
 	mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
-	mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
+	mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0));
 }
 #endif
 
@@ -2517,7 +2623,7 @@
 {
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
-	int err;
+	int err, i;
 
 	err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
 	if (err) {
@@ -2545,9 +2651,17 @@
 		}
 
 		napi_enable(&eth->tx_napi);
-		napi_enable(&eth->rx_napi);
+		napi_enable(&eth->rx_napi[0].napi);
 		mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
-		mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
+		mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0));
+
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+			for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
+				napi_enable(&eth->rx_napi[i].napi);
+				mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(i));
+			}
+		}
+
 		refcount_set(&eth->dma_refcnt, 1);
 	}
 	else
@@ -2585,6 +2699,7 @@
 {
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
+	int i;
 
 	phylink_stop(mac->phylink);
 
@@ -2599,9 +2714,16 @@
 	mtk_gdm_config(eth, MTK_GDMA_DROP_ALL);
 
 	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
-	mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
+	mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(0));
 	napi_disable(&eth->tx_napi);
-	napi_disable(&eth->rx_napi);
+	napi_disable(&eth->rx_napi[0].napi);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
+			mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(i));
+			napi_disable(&eth->rx_napi[i].napi);
+		}
+	}
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
 		mtk_stop_dma(eth, MTK_QDMA_GLO_CFG);
@@ -2652,6 +2774,27 @@
 	return ret;
 }
 
+static int mtk_napi_init(struct mtk_eth *eth)
+{
+	struct mtk_napi *rx_napi = &eth->rx_napi[0];
+	int i;
+
+	rx_napi->eth = eth;
+	rx_napi->rx_ring = &eth->rx_ring[0];
+	rx_napi->irq_grp_no = 2;
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
+			rx_napi = &eth->rx_napi[i];
+			rx_napi->eth = eth;
+			rx_napi->rx_ring = &eth->rx_ring[i];
+			rx_napi->irq_grp_no = 2 + i;
+		}
+	}
+
+	return 0;
+}
+
 static int mtk_hw_init(struct mtk_eth *eth)
 {
 	int i, ret;
@@ -2732,9 +2875,9 @@
 
 	/* FE int grouping */
 	mtk_w32(eth, MTK_TX_DONE_INT, MTK_PDMA_INT_GRP1);
-	mtk_w32(eth, MTK_RX_DONE_INT, MTK_PDMA_INT_GRP2);
+	mtk_w32(eth, MTK_RX_DONE_INT(0), MTK_PDMA_INT_GRP2);
 	mtk_w32(eth, MTK_TX_DONE_INT, MTK_QDMA_INT_GRP1);
-	mtk_w32(eth, MTK_RX_DONE_INT, MTK_QDMA_INT_GRP2);
+	mtk_w32(eth, MTK_RX_DONE_INT(0), MTK_QDMA_INT_GRP2);
 	mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
 
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
@@ -3316,7 +3459,7 @@
 		}
 	}
 
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < MTK_MAX_IRQ_NUM; i++) {
 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0)
 			eth->irq[i] = eth->irq[0];
 		else
@@ -3366,6 +3509,10 @@
 		}
 	}
 
+	err = mtk_napi_init(eth);
+	if (err)
+		goto err_free_dev;
+
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
 		err = devm_request_irq(eth->dev, eth->irq[0],
 				       mtk_handle_irq, 0,
@@ -3379,7 +3526,21 @@
 
 		err = devm_request_irq(eth->dev, eth->irq[2],
 				       mtk_handle_irq_rx, 0,
-				       dev_name(eth->dev), eth);
+				       dev_name(eth->dev), &eth->rx_napi[0]);
+		if (err)
+			goto err_free_dev;
+
+		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+			for (i = 1; i < MTK_RX_NAPI_NUM; i++) {
+				err = devm_request_irq(eth->dev,
+						eth->irq[2 + i],
+						mtk_handle_irq_rx, 0,
+						dev_name(eth->dev),
+						&eth->rx_napi[i]);
+				if (err)
+					goto err_free_dev;
+			}
+		}
 	}
 	if (err)
 		goto err_free_dev;
@@ -3411,9 +3572,15 @@
 	init_dummy_netdev(&eth->dummy_dev);
 	netif_napi_add(&eth->dummy_dev, &eth->tx_napi, mtk_napi_tx,
 		       MTK_NAPI_WEIGHT);
-	netif_napi_add(&eth->dummy_dev, &eth->rx_napi, mtk_napi_rx,
+	netif_napi_add(&eth->dummy_dev, &eth->rx_napi[0].napi, mtk_napi_rx,
 		       MTK_NAPI_WEIGHT);
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		for (i = 1; i < MTK_RX_NAPI_NUM; i++)
+			netif_napi_add(&eth->dummy_dev, &eth->rx_napi[i].napi,
+				       mtk_napi_rx, MTK_NAPI_WEIGHT);
+	}
+
 	mtketh_debugfs_init(eth);
 	debug_proc_init(eth);
 
@@ -3449,7 +3616,13 @@
 	mtk_hw_deinit(eth);
 
 	netif_napi_del(&eth->tx_napi);
-	netif_napi_del(&eth->rx_napi);
+	netif_napi_del(&eth->rx_napi[0].napi);
+
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		for (i = 1; i < MTK_RX_NAPI_NUM; i++)
+			netif_napi_del(&eth->rx_napi[i].napi);
+	}
+
 	mtk_cleanup(eth);
 	mtk_mdio_cleanup(eth);
 
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 4cb2fee..bb27d95 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -180,6 +180,8 @@
 
 #define IS_NORMAL_RING(ring_no)		((ring_no) == 0)
 #define MTK_LRO_EN			BIT(0)
+#define MTK_NON_LRO_MULTI_EN   		BIT(2)
+#define MTK_LRO_DLY_INT_EN		BIT(5)
 #define MTK_LRO_ALT_PKT_CNT_MODE	BIT(21)
 #define MTK_LRO_L4_CTRL_PSH_EN		BIT(23)
 #define MTK_CTRL_DW0_SDL_OFFSET		(3)
@@ -191,6 +193,31 @@
 #define MTK_ADMA_MODE		BIT(15)
 #define MTK_LRO_MIN_RXD_SDL	(MTK_HW_LRO_SDL_REMAIN_ROOM << 16)
 
+/* PDMA RSS Control Registers */
+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#define MTK_PDMA_RSS_GLO_CFG		(PDMA_BASE + 0x800)
+#define MTK_RX_NAPI_NUM			(2)
+#define MTK_MAX_IRQ_NUM			(4)
+#else
+#define MTK_PDMA_RSS_GLO_CFG		0x3000
+#define MTK_RX_NAPI_NUM			(1)
+#define MTK_MAX_IRQ_NUM			(3)
+#endif
+#define MTK_RSS_RING1			(1)
+#define MTK_RSS_EN			BIT(0)
+#define MTK_RSS_CFG_REQ			BIT(2)
+#define MTK_RSS_IPV6_STATIC_HASH	(0x7 << 8)
+#define MTK_RSS_IPV4_STATIC_HASH	(0x7 << 12)
+#define MTK_RSS_INDR_TABLE_DW0		(MTK_PDMA_RSS_GLO_CFG + 0x50)
+#define MTK_RSS_INDR_TABLE_DW1		(MTK_PDMA_RSS_GLO_CFG + 0x54)
+#define MTK_RSS_INDR_TABLE_DW2		(MTK_PDMA_RSS_GLO_CFG + 0x58)
+#define MTK_RSS_INDR_TABLE_DW3		(MTK_PDMA_RSS_GLO_CFG + 0x5C)
+#define MTK_RSS_INDR_TABLE_DW4		(MTK_PDMA_RSS_GLO_CFG + 0x60)
+#define MTK_RSS_INDR_TABLE_DW5		(MTK_PDMA_RSS_GLO_CFG + 0x64)
+#define MTK_RSS_INDR_TABLE_DW6		(MTK_PDMA_RSS_GLO_CFG + 0x68)
+#define MTK_RSS_INDR_TABLE_DW7		(MTK_PDMA_RSS_GLO_CFG + 0x6C)
+#define MTK_RSS_INDR_TABLE_SIZE4	0x44444444
+
 /* PDMA Global Configuration Register */
 #define MTK_PDMA_GLO_CFG	(PDMA_BASE + 0x204)
 #define MTK_RX_DMA_LRO_EN	BIT(8)
@@ -226,6 +253,13 @@
 /* PDMA Interrupt grouping registers */
 #define MTK_PDMA_INT_GRP1	(PDMA_BASE + 0x250)
 #define MTK_PDMA_INT_GRP2	(PDMA_BASE + 0x254)
+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#define MTK_PDMA_INT_GRP3	(PDMA_BASE + 0x258)
+#else
+#define MTK_PDMA_INT_GRP3	(PDMA_BASE + 0x22c)
+#endif
+#define MTK_LRO_RX1_DLY_INT	0xa70
+#define MTK_MAX_DELAY_INT	0x8f0f8f0f
 
 /* PDMA HW LRO IP Setting Registers */
 #if defined(CONFIG_MEDIATEK_NETSYS_V2)
@@ -249,6 +283,7 @@
 #define MTK_LRO_CTRL_DW3_CFG(x)		(MTK_LRO_RX_RING0_CTRL_DW3 + (x * 0x40))
 #define MTK_RING_AGE_TIME_L		((MTK_HW_LRO_AGE_TIME & 0x3ff) << 22)
 #define MTK_RING_AGE_TIME_H		((MTK_HW_LRO_AGE_TIME >> 10) & 0x3f)
+#define MTK_RING_PSE_MODE        	(1 << 6)
 #define MTK_RING_AUTO_LERAN_MODE	(3 << 6)
 #define MTK_RING_VLD			BIT(8)
 #define MTK_RING_MAX_AGG_TIME		((MTK_HW_LRO_AGG_TIME & 0xffff) << 10)
@@ -342,9 +377,11 @@
 /* QDMA Interrupt Status Register */
 #define MTK_QDMA_INT_STATUS	(QDMA_BASE + 0x218)
 #if defined(CONFIG_MEDIATEK_NETSYS_V2)
-#define MTK_RX_DONE_DLY 	BIT(14)
+#define MTK_RX_DONE_INT(ring_no)		\
+	((ring_no)? BIT(16 + (ring_no)) : BIT(14))
 #else
-#define MTK_RX_DONE_DLY 	BIT(30)
+#define MTK_RX_DONE_INT(ring_no)		\
+	((ring_no)? BIT(24 + (ring_no)) : BIT(30))
 #endif
 #define MTK_RX_DONE_INT3	BIT(19)
 #define MTK_RX_DONE_INT2	BIT(18)
@@ -354,7 +391,6 @@
 #define MTK_TX_DONE_INT2	BIT(2)
 #define MTK_TX_DONE_INT1	BIT(1)
 #define MTK_TX_DONE_INT0	BIT(0)
-#define MTK_RX_DONE_INT		MTK_RX_DONE_DLY
 #define MTK_TX_DONE_DLY         BIT(28)
 #define MTK_TX_DONE_INT         MTK_TX_DONE_DLY
 
@@ -891,6 +927,20 @@
 	u32 ring_no;
 };
 
+/* struct mtk_napi -	This is the structure holding NAPI-related information,
+ *			and a mtk_napi struct is binding to one interrupt group
+ * @napi:		The NAPI struct
+ * @rx_ring:		Pointer to the memory holding info about the RX ring
+ * @irq_grp_idx:	The index indicates which interrupt group that this
+ *			mtk_napi is binding to
+ */
+struct mtk_napi {
+	struct napi_struct	napi;
+	struct mtk_eth		*eth;
+	struct mtk_rx_ring	*rx_ring;
+	u32			irq_grp_no;
+};
+
 enum mkt_eth_capabilities {
 	MTK_RGMII_BIT = 0,
 	MTK_TRGMII_BIT,
@@ -901,6 +951,7 @@
 	MTK_INFRA_BIT,
 	MTK_SHARED_SGMII_BIT,
 	MTK_HWLRO_BIT,
+	MTK_RSS_BIT,
 	MTK_SHARED_INT_BIT,
 	MTK_TRGMII_MT7621_CLK_BIT,
 	MTK_QDMA_BIT,
@@ -935,6 +986,7 @@
 #define MTK_INFRA		BIT(MTK_INFRA_BIT)
 #define MTK_SHARED_SGMII	BIT(MTK_SHARED_SGMII_BIT)
 #define MTK_HWLRO		BIT(MTK_HWLRO_BIT)
+#define MTK_RSS			BIT(MTK_RSS_BIT)
 #define MTK_SHARED_INT		BIT(MTK_SHARED_INT_BIT)
 #define MTK_TRGMII_MT7621_CLK	BIT(MTK_TRGMII_MT7621_CLK_BIT)
 #define MTK_QDMA		BIT(MTK_QDMA_BIT)
@@ -1104,7 +1156,7 @@
 	struct net_device		dummy_dev;
 	struct net_device		*netdev[MTK_MAX_DEVS];
 	struct mtk_mac			*mac[MTK_MAX_DEVS];
-	int				irq[3];
+	int				irq[MTK_MAX_IRQ_NUM];
 	u32				msg_enable;
 	unsigned long			sysclk;
 	struct regmap			*ethsys;
@@ -1117,7 +1169,7 @@
 	struct mtk_rx_ring		rx_ring[MTK_MAX_RX_RING_NUM];
 	struct mtk_rx_ring		rx_ring_qdma;
 	struct napi_struct		tx_napi;
-	struct napi_struct		rx_napi;
+	struct mtk_napi			rx_napi[MTK_RX_NAPI_NUM];
 	struct mtk_tx_dma		*scratch_ring;
 	dma_addr_t			phy_scratch_ring;
 	void				*scratch_head;