Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1394975

[PATCH 03/12] net-next: mediatek: fix missing free of scratch memory

From John Crispin <john@phrozen.org>
Newsgroups linux.kernel
Subject [PATCH 03/12] net-next: mediatek: fix missing free of scratch memory
Date 2016-05-05 11:40 +0200
Message-ID <rvnVg-5Rb-31@gated-at.bofh.it> (permalink)
References <rvnLA-5Kz-9@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


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 0ed49a4..e415986 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -469,14 +469,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;
@@ -493,19 +493,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);
@@ -1205,6 +1205,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

Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 00/12] net-next: mediatek: bug fixes and tx stall fixes John Crispin <john@phrozen.org> - 2016-05-05 11:30 +0200
  [PATCH 01/12] net-next: mediatek: fix DQL support John Crispin <john@phrozen.org> - 2016-05-05 11:30 +0200
  [PATCH 09/12] net-next: mediatek: increase watchdog_timeo John Crispin <john@phrozen.org> - 2016-05-05 11:30 +0200
  [PATCH 06/12] net-next: mediatek: add next data pointer coherency protection John Crispin <john@phrozen.org> - 2016-05-05 11:30 +0200
  [PATCH 04/12] net-next: mediatek: invalid buffer lookup in mtk_tx_map() John Crispin <john@phrozen.org> - 2016-05-05 11:40 +0200
  [PATCH 08/12] net-next: mediatek: fix threshold value John Crispin <john@phrozen.org> - 2016-05-05 11:40 +0200
  [PATCH 03/12] net-next: mediatek: fix missing free of scratch memory John Crispin <john@phrozen.org> - 2016-05-05 11:40 +0200
  [PATCH 02/12] net-next: mediatek: add missing return code check John Crispin <john@phrozen.org> - 2016-05-05 11:40 +0200
  [PATCH 12/12] net-next: mediatek: remove superfluous queue wake up call John Crispin <john@phrozen.org> - 2016-05-05 12:00 +0200
  [PATCH 10/12] net-next: mediatek: fix off by one in the TX ring allocation John Crispin <john@phrozen.org> - 2016-05-05 12:00 +0200
  [PATCH 11/12] net-next: mediatek: only wake the queue if it is stopped John Crispin <john@phrozen.org> - 2016-05-05 12:00 +0200
  Re: [PATCH 00/12] net-next: mediatek: bug fixes and tx stall fixes Andrew Lunn <andrew@lunn.ch> - 2016-05-05 14:30 +0200

csiph-web