b55950e13d6745a93e6a5cf4dc088f6fdece3c36
[openwrt/staging/chunkeey.git] / target / linux / mediatek / patches-4.4 / 0083-net-next-mediatek-fix-missing-free-of-scratch-memory.patch
1 From b48745c534ced06005d2ba57198b54a6a160b39d Mon Sep 17 00:00:00 2001
2 From: John Crispin <john@phrozen.org>
3 Date: Sat, 23 Apr 2016 09:18:28 +0200
4 Subject: [PATCH 083/102] net-next: mediatek: fix missing free of scratch
5 memory
6
7 Scratch memory gets allocated in mtk_init_fq_dma() but the corresponding
8 code to free it is missing inside mtk_dma_free() causing a memory leak.
9 With this patch applied, we can run ifconfig/up/down several thousand
10 times without any problems.
11
12 Signed-off-by: John Crispin <john@phrozen.org>
13 ---
14 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 18 +++++++++++++-----
15 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++
16 2 files changed, 15 insertions(+), 5 deletions(-)
17
18 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
19 index fefbf16..d9664e5 100644
20 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
21 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
22 @@ -484,14 +484,14 @@ static inline void mtk_rx_get_desc(struct mtk_rx_dma *rxd,
23 /* the qdma core needs scratch memory to be setup */
24 static int mtk_init_fq_dma(struct mtk_eth *eth)
25 {
26 - dma_addr_t phy_ring_head, phy_ring_tail;
27 + dma_addr_t phy_ring_tail;
28 int cnt = MTK_DMA_SIZE;
29 dma_addr_t dma_addr;
30 int i;
31
32 eth->scratch_ring = dma_alloc_coherent(eth->dev,
33 cnt * sizeof(struct mtk_tx_dma),
34 - &phy_ring_head,
35 + &eth->phy_scratch_ring,
36 GFP_ATOMIC | __GFP_ZERO);
37 if (unlikely(!eth->scratch_ring))
38 return -ENOMEM;
39 @@ -508,19 +508,19 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
40 return -ENOMEM;
41
42 memset(eth->scratch_ring, 0x0, sizeof(struct mtk_tx_dma) * cnt);
43 - phy_ring_tail = phy_ring_head +
44 + phy_ring_tail = eth->phy_scratch_ring +
45 (sizeof(struct mtk_tx_dma) * (cnt - 1));
46
47 for (i = 0; i < cnt; i++) {
48 eth->scratch_ring[i].txd1 =
49 (dma_addr + (i * MTK_QDMA_PAGE_SIZE));
50 if (i < cnt - 1)
51 - eth->scratch_ring[i].txd2 = (phy_ring_head +
52 + eth->scratch_ring[i].txd2 = (eth->phy_scratch_ring +
53 ((i + 1) * sizeof(struct mtk_tx_dma)));
54 eth->scratch_ring[i].txd3 = TX_DMA_SDL(MTK_QDMA_PAGE_SIZE);
55 }
56
57 - mtk_w32(eth, phy_ring_head, MTK_QDMA_FQ_HEAD);
58 + mtk_w32(eth, eth->phy_scratch_ring, MTK_QDMA_FQ_HEAD);
59 mtk_w32(eth, phy_ring_tail, MTK_QDMA_FQ_TAIL);
60 mtk_w32(eth, (cnt << 16) | cnt, MTK_QDMA_FQ_CNT);
61 mtk_w32(eth, MTK_QDMA_PAGE_SIZE << 16, MTK_QDMA_FQ_BLEN);
62 @@ -1220,6 +1220,14 @@ static void mtk_dma_free(struct mtk_eth *eth)
63 for (i = 0; i < MTK_MAC_COUNT; i++)
64 if (eth->netdev[i])
65 netdev_reset_queue(eth->netdev[i]);
66 + if (eth->scratch_ring) {
67 + dma_free_coherent(eth->dev,
68 + MTK_DMA_SIZE * sizeof(struct mtk_tx_dma),
69 + eth->scratch_ring,
70 + eth->phy_scratch_ring);
71 + eth->scratch_ring = NULL;
72 + eth->phy_scratch_ring = 0;
73 + }
74 mtk_tx_clean(eth);
75 mtk_rx_clean(eth);
76 kfree(eth->scratch_head);
77 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
78 index eed626d..57f7e8a 100644
79 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
80 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
81 @@ -357,6 +357,7 @@ struct mtk_rx_ring {
82 * @rx_ring: Pointer to the memore holding info about the RX ring
83 * @rx_napi: The NAPI struct
84 * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring
85 + * @phy_scratch_ring: physical address of scratch_ring
86 * @scratch_head: The scratch memory that scratch_ring points to.
87 * @clk_ethif: The ethif clock
88 * @clk_esw: The switch clock
89 @@ -384,6 +385,7 @@ struct mtk_eth {
90 struct mtk_rx_ring rx_ring;
91 struct napi_struct rx_napi;
92 struct mtk_tx_dma *scratch_ring;
93 + dma_addr_t phy_scratch_ring;
94 void *scratch_head;
95 struct clk *clk_ethif;
96 struct clk *clk_esw;
97 --
98 1.7.10.4
99