[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