mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 15:32:33 +00:00
a105eac4dd
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
93 lines
3.4 KiB
Diff
93 lines
3.4 KiB
Diff
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(-)
|
|
|
|
--- 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(struc
|
|
/* 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,
|
|
+ ð->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_et
|
|
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
|
|
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);
|
|
--- 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;
|