[Bugfix][API-1269]fix ethernet memory leak

Only Configure: No
Affected branch: GSW3.0-no-connman
Affected module: ethernet
Is it affected on both ZXIC and MTK: only MTK
Self-test: No
Doc Update: No

Change-Id: Id9ed2413ca852f2414f65a84daf8ce16134d5fa9
(cherry picked from commit 02517cbb318c5bc2b3535e025f205d955423d7a7)
diff --git a/meta/meta-mediatek-mt2735/recipes-core/initial/files/smp.sh b/meta/meta-mediatek-mt2735/recipes-core/initial/files/smp.sh
index fc7da74..c090b4b 100644
--- a/meta/meta-mediatek-mt2735/recipes-core/initial/files/smp.sh
+++ b/meta/meta-mediatek-mt2735/recipes-core/initial/files/smp.sh
@@ -40,6 +40,7 @@
 	MBOX_ISR=454
 	usb_11201000=128
 	DPMAIF_AP=241
+	eth2=337
 
 
 	# Please update the CPU binding in each cases.
@@ -48,14 +49,14 @@
 	dbg "[MT6890_CPE]"
 	if [ "$num_of_wifi" = "0" ]; then
 		CPU0_AFFINITY="$MMC $usb_11201000 $DPMAIF_AP"
-		CPU1_AFFINITY="$eth_rx"
+		CPU1_AFFINITY="$eth_rx $eth2"
 		CPU2_AFFINITY="$eth_tx $eth_e0rx0"
 		CPU3_AFFINITY="$CCIF_AP_DATA $MBOX_ISR $eth_e1rx0"
 
-		CPU0_RPS="$ethif1 $ethif2"
-		CPU1_RPS="ccmni0 ccmni1 rndis0 $ethif1 $ethif2"
-		CPU2_RPS="ccmni0 ccmni1 rndis0 $ethif1 $ethif2"
-		CPU3_RPS="$ethif1 $ethif2"
+		CPU0_RPS="$ethif1 $ethif2 $ethif3"
+		CPU1_RPS="ccmni0 ccmni1 rndis0 $ethif1 $ethif2 $ethif3"
+		CPU2_RPS="ccmni0 ccmni1 rndis0 $ethif1 $ethif2 $ethif3"
+		CPU3_RPS="$ethif1 $ethif2 $ethif3"
 	elif [ "$num_of_wifi" = "1" ]; then
 		CPU0_AFFINITY="$MMC $usb_11201000 $DPMAIF_AP"
 		CPU1_AFFINITY="$eth_rx"
@@ -91,6 +92,33 @@
 	fi
 }
 
+MT2735_DUAL()
+{
+	DEFAULT_RPS=0
+
+	#Physical IRQ# setting
+	eth_tx=426
+	eth_rx=434
+	eth_e0rx0=422
+	eth_e1rx0=424
+	CCIF_AP_DATA=226
+	MMC=131
+	MBOX_ISR=454
+	usb_11201000=128
+	DPMAIF_AP=241
+	eth2=337
+
+
+	# Please update the CPU binding in each cases.
+	# CPU#_AFFINITY="add binding irq number here"
+	# CPU#_RPS="add binding interface name here"
+	dbg "[MT2735_DUAL]"
+	CPU0_AFFINITY="$MMC $usb_11201000 $DPMAIF_AP $eth_tx $eth_e0rx0 $MBOX_ISR"
+	CPU1_AFFINITY="$eth_rx $CCIF_AP_DATA $eth_e1rx0 $eth2"
+
+	CPU0_RPS="$ethif1 $ethif2 $ethif3"
+	CPU1_RPS="ccmni0 ccmni1 rndis0 $ethif1 $ethif2 $ethif3"
+}
 
 MT6890_MIFI()
 {
@@ -186,6 +214,7 @@
 {
 	ethif1="eth0"
 	ethif2="eth1"
+	ethif3="eth2"
 	dbg2 "# Ethernet interface list"
 	dbg2 "\$ethif1=$ethif1\n\$ethif2=$ethif2"
 	RPS_IF_LIST="$RPS_IF_LIST $ethif1 $ethif2"
@@ -335,6 +364,9 @@
 			dbg "setup_model:MT6890_CPE wifi#=$num_of_wifi"
 			MT6890_CPE $num_of_wifi
 		fi
+	else
+		dbg "setup_model:MT2735_DUAL"
+		MT2735_DUAL
 	fi
 }
 
@@ -449,7 +481,7 @@
 VAR_PREFIX="autogen"
 #IRQ_LIST=""	# setup by every model
 RPS_IF_LIST=""	# setup by getEthIfName/getWiFiIfName/every model
-sleep 20
+#sleep 20
 get_eth_if_name
 get_wifi_if_name	# It will add all wifi interfaces into $RPS_IF_LIST
 dbg2 "# default RPS_IF_LIST=$RPS_IF_LIST"
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 724193d..5b6cf08 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -55,6 +55,10 @@
 	MTK_ETHTOOL_STAT(rx_long_errors),
 	MTK_ETHTOOL_STAT(rx_checksum_errors),
 	MTK_ETHTOOL_STAT(rx_flow_control_packets),
+	MTK_ETHTOOL_STAT(tx_send_ppe_packets),
+	MTK_ETHTOOL_STAT(tx_send_gdm_packets),
+	MTK_ETHTOOL_STAT(tx_free_packets),
+	MTK_ETHTOOL_STAT(rx_kernel_packets),
 };
 
 static const char * const mtk_clks_source_name[] = {
@@ -866,6 +870,8 @@
 
 static void mtk_tx_unmap(struct mtk_eth *eth, struct mtk_tx_buf *tx_buf)
 {
+	struct mtk_mac *mac;
+
 	if (tx_buf->flags & MTK_TX_FLAGS_SINGLE0) {
 		dma_unmap_single(eth->dev,
 				 dma_unmap_addr(tx_buf, dma_addr0),
@@ -879,8 +885,11 @@
 	}
 	tx_buf->flags = 0;
 	if (tx_buf->skb &&
-	    (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC))
+	    (tx_buf->skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC)) {
+		mac = netdev_priv(tx_buf->skb->dev);
 		dev_kfree_skb_any(tx_buf->skb);
+		mac->hw_stats->tx_free_packets++;
+	}
 	tx_buf->skb = NULL;
 }
 
@@ -1026,6 +1035,11 @@
 
 	mtk_w32(eth, txd->txd2, MTK_QTX_CTX_PTR);
 
+	if (fport == (3 << TX_DMA_FPORT_SHIFT))
+		mac->hw_stats->tx_send_ppe_packets++;
+	else
+		mac->hw_stats->tx_send_gdm_packets++;
+
 	return 0;
 
 err_dma:
@@ -1324,6 +1338,7 @@
 #endif
 			skb_record_rx_queue(skb, 0);
 			napi_gro_receive(napi, skb);
+			eth->mac[mac]->hw_stats->rx_kernel_packets++;
 #if defined(CONFIG_HW_NAT)
 		}
 #endif
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 5af8aca..aedea77 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -697,6 +697,10 @@
 	u64 rx_long_errors;
 	u64 rx_checksum_errors;
 	u64 rx_flow_control_packets;
+	u64 tx_send_ppe_packets;
+	u64 tx_send_gdm_packets;
+	u64 tx_free_packets;
+	u64 rx_kernel_packets;
 
 	spinlock_t		stats_lock;
 	u32			reg_offset;
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/common.h b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/common.h
index cd33d84..de2088a 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -101,6 +101,11 @@
 	unsigned long threshold;
 	unsigned long tx_pkt_n;
 	unsigned long rx_pkt_n;
+	unsigned long rx_alloc;
+	unsigned long rx_build_skb;
+	unsigned long rx_timestamp_skb;
+	unsigned long rx_to_kernel;
+	unsigned long rx_to_swfp;
 	unsigned long normal_irq_n;
 	unsigned long rx_normal_irq_n;
 	unsigned long napi_poll;
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index a57df0c..abc9176 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -90,6 +90,11 @@
 	STMMAC_STAT(threshold),
 	STMMAC_STAT(tx_pkt_n),
 	STMMAC_STAT(rx_pkt_n),
+	STMMAC_STAT(rx_alloc),
+	STMMAC_STAT(rx_build_skb),
+	STMMAC_STAT(rx_timestamp_skb),
+	STMMAC_STAT(rx_to_kernel),
+	STMMAC_STAT(rx_to_swfp),
 	STMMAC_STAT(normal_irq_n),
 	STMMAC_STAT(rx_normal_irq_n),
 	STMMAC_STAT(napi_poll),
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index b34725d..61ffe60 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1182,6 +1182,21 @@
 		stmmac_clear_tx_descriptors(priv, queue);
 }
 
+struct sk_buff *stmmac_alloc_skb(struct net_device *dev, unsigned int len, gfp_t flags)
+{
+	struct sk_buff *skb;
+
+	//skb = __netdev_alloc_skb_ip_align(dev, len, flags);
+	skb = __alloc_skb(len + NET_SKB_PAD + NET_IP_ALIGN, flags, SKB_ALLOC_RX, NUMA_NO_NODE);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
+	skb->dev = dev;
+
+	return skb;
+}
+
 /**
  * stmmac_init_rx_buffers - init the RX descriptor buffer.
  * @priv: driver private structure
@@ -1198,7 +1213,7 @@
 	struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
 	struct sk_buff *skb;
 
-	skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
+	skb = stmmac_alloc_skb(priv->dev, priv->dma_buf_sz, flags);
 	if (!skb) {
 		netdev_err(priv->dev,
 			   "%s: Rx init fails; skb is NULL\n", __func__);
@@ -3380,7 +3395,10 @@
 		if (likely(!rx_q->rx_skbuff[entry])) {
 			struct sk_buff *skb;
 
-			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
+			skb = stmmac_alloc_skb(priv->dev, bfsize, GFP_ATOMIC);
+
+			priv->xstats.rx_alloc++;
+
 			if (unlikely(!skb)) {
 				/* so for a while no zero-copy! */
 				rx_q->rx_zeroc_thresh = STMMAC_RX_THRESH;
@@ -3505,6 +3523,7 @@
 				 */
 				dev_kfree_skb_any(rx_q->rx_skbuff[entry]);
 				rx_q->rx_skbuff[entry] = NULL;
+				priv->xstats.rx_timestamp_skb++;
 				dma_unmap_single(priv->device,
 						 rx_q->rx_skbuff_dma[entry],
 						 priv->dma_buf_sz,
@@ -3555,8 +3574,7 @@
 			if (unlikely(!xmac &&
 				     ((frame_len < priv->rx_copybreak) ||
 				     stmmac_rx_threshold_count(rx_q)))) {
-				skb = netdev_alloc_skb_ip_align(priv->dev,
-								frame_len);
+				skb = stmmac_alloc_skb(priv->dev, frame_len, GFP_ATOMIC);
 				if (unlikely(!skb)) {
 					if (net_ratelimit())
 						dev_warn(priv->device,
@@ -3581,6 +3599,7 @@
 							   DMA_FROM_DEVICE);
 			} else {
 				skb = rx_q->rx_skbuff[entry];
+				priv->xstats.rx_build_skb++;
 				if (unlikely(!skb)) {
 					netdev_err(priv->dev,
 						   "%s: Inconsistent Rx chain\n",
@@ -3619,11 +3638,16 @@
 #if defined(CONFIG_HW_NAT)
 			if (ppe_hook_rx_snps) {
 				FOE_MAGIC_TAG(skb) = FOE_MAGIC_SNPS;
-				if (ppe_hook_rx_snps(skb))
+				if (ppe_hook_rx_snps(skb)) {
 					napi_gro_receive(&ch->rx_napi, skb);
+					priv->xstats.rx_to_kernel++;
+				} else {
+					priv->xstats.rx_to_swfp++;
+				}
 			} else {
 #endif
 				napi_gro_receive(&ch->rx_napi, skb);
+				priv->xstats.rx_to_kernel++;
 #if defined(CONFIG_HW_NAT)
 			}
 #endif