aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/patches-4.4/0083-net-next-mediatek-fix-missing-free-of-scratch-memory.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mediatek/patches-4.4/0083-net-next-mediatek-fix-missing-free-of-scratch-memory.patch')
-rw-r--r--target/linux/mediatek/patches-4.4/0083-net-next-mediatek-fix-missing-free-of-scratch-memory.patch99
1 files changed, 99 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-4.4/0083-net-next-mediatek-fix-missing-free-of-scratch-memory.patch b/target/linux/mediatek/patches-4.4/0083-net-next-mediatek-fix-missing-free-of-scratch-memory.patch
new file mode 100644
index 0000000000..b55950e13d
--- /dev/null
+++ b/target/linux/mediatek/patches-4.4/0083-net-next-mediatek-fix-missing-free-of-scratch-memory.patch
@@ -0,0 +1,99 @@
+From b48745c534ced06005d2ba57198b54a6a160b39d Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Apr 2016 09:18:28 +0200
+Subject: [PATCH 083/102] net-next: mediatek: fix missing free of scratch
+ memory
+
+Scratch memory gets allocated in mtk_init_fq_dma() but the corresponding
+code to free it is missing inside mtk_dma_free() causing a memory leak.
+With this patch applied, we can run ifconfig/up/down several thousand
+times without any problems.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 18 +++++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++
+ 2 files changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index fefbf16..d9664e5 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -484,14 +484,14 @@ static inline void mtk_rx_get_desc(struct mtk_rx_dma *rxd,
+ /* the qdma core needs scratch memory to be setup */
+ static int mtk_init_fq_dma(struct mtk_eth *eth)
+ {
+- dma_addr_t phy_ring_head, phy_ring_tail;
++ dma_addr_t phy_ring_tail;
+ int cnt = MTK_DMA_SIZE;
+ dma_addr_t dma_addr;
+ int i;
+
+ eth->scratch_ring = dma_alloc_coherent(eth->dev,
+ cnt * sizeof(struct mtk_tx_dma),
+- &phy_ring_head,
++ &eth->phy_scratch_ring,
+ GFP_ATOMIC | __GFP_ZERO);
+ if (unlikely(!eth->scratch_ring))
+ return -ENOMEM;
+@@ -508,19 +508,19 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
+ return -ENOMEM;
+
+ memset(eth->scratch_ring, 0x0, sizeof(struct mtk_tx_dma) * cnt);
+- phy_ring_tail = phy_ring_head +
++ phy_ring_tail = eth->phy_scratch_ring +
+ (sizeof(struct mtk_tx_dma) * (cnt - 1));
+
+ for (i = 0; i < cnt; i++) {
+ eth->scratch_ring[i].txd1 =
+ (dma_addr + (i * MTK_QDMA_PAGE_SIZE));
+ if (i < cnt - 1)
+- eth->scratch_ring[i].txd2 = (phy_ring_head +
++ eth->scratch_ring[i].txd2 = (eth->phy_scratch_ring +
+ ((i + 1) * sizeof(struct mtk_tx_dma)));
+ eth->scratch_ring[i].txd3 = TX_DMA_SDL(MTK_QDMA_PAGE_SIZE);
+ }
+
+- mtk_w32(eth, phy_ring_head, MTK_QDMA_FQ_HEAD);
++ mtk_w32(eth, eth->phy_scratch_ring, MTK_QDMA_FQ_HEAD);
+ mtk_w32(eth, phy_ring_tail, MTK_QDMA_FQ_TAIL);
+ mtk_w32(eth, (cnt << 16) | cnt, MTK_QDMA_FQ_CNT);
+ mtk_w32(eth, MTK_QDMA_PAGE_SIZE << 16, MTK_QDMA_FQ_BLEN);
+@@ -1220,6 +1220,14 @@ static void mtk_dma_free(struct mtk_eth *eth)
+ for (i = 0; i < MTK_MAC_COUNT; i++)
+ if (eth->netdev[i])
+ netdev_reset_queue(eth->netdev[i]);
++ if (eth->scratch_ring) {
++ dma_free_coherent(eth->dev,
++ MTK_DMA_SIZE * sizeof(struct mtk_tx_dma),
++ eth->scratch_ring,
++ eth->phy_scratch_ring);
++ eth->scratch_ring = NULL;
++ eth->phy_scratch_ring = 0;
++ }
+ mtk_tx_clean(eth);
+ mtk_rx_clean(eth);
+ kfree(eth->scratch_head);
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+index eed626d..57f7e8a 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -357,6 +357,7 @@ struct mtk_rx_ring {
+ * @rx_ring: Pointer to the memore holding info about the RX ring
+ * @rx_napi: The NAPI struct
+ * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring
++ * @phy_scratch_ring: physical address of scratch_ring
+ * @scratch_head: The scratch memory that scratch_ring points to.
+ * @clk_ethif: The ethif clock
+ * @clk_esw: The switch clock
+@@ -384,6 +385,7 @@ struct mtk_eth {
+ struct mtk_rx_ring rx_ring;
+ struct napi_struct rx_napi;
+ struct mtk_tx_dma *scratch_ring;
++ dma_addr_t phy_scratch_ring;
+ void *scratch_head;
+ struct clk *clk_ethif;
+ struct clk *clk_esw;
+--
+1.7.10.4
+