Commit 605e4fe4 authored by John Crispin's avatar John Crispin Committed by David S. Miller

net: 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: default avatarJohn Crispin <john@phrozen.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 562c5a70
...@@ -481,14 +481,14 @@ static inline void mtk_rx_get_desc(struct mtk_rx_dma *rxd, ...@@ -481,14 +481,14 @@ static inline void mtk_rx_get_desc(struct mtk_rx_dma *rxd,
/* the qdma core needs scratch memory to be setup */ /* the qdma core needs scratch memory to be setup */
static int mtk_init_fq_dma(struct mtk_eth *eth) 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; int cnt = MTK_DMA_SIZE;
dma_addr_t dma_addr; dma_addr_t dma_addr;
int i; int i;
eth->scratch_ring = dma_alloc_coherent(eth->dev, eth->scratch_ring = dma_alloc_coherent(eth->dev,
cnt * sizeof(struct mtk_tx_dma), cnt * sizeof(struct mtk_tx_dma),
&phy_ring_head, &eth->phy_scratch_ring,
GFP_ATOMIC | __GFP_ZERO); GFP_ATOMIC | __GFP_ZERO);
if (unlikely(!eth->scratch_ring)) if (unlikely(!eth->scratch_ring))
return -ENOMEM; return -ENOMEM;
...@@ -505,19 +505,19 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) ...@@ -505,19 +505,19 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
return -ENOMEM; return -ENOMEM;
memset(eth->scratch_ring, 0x0, sizeof(struct mtk_tx_dma) * cnt); 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)); (sizeof(struct mtk_tx_dma) * (cnt - 1));
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
eth->scratch_ring[i].txd1 = eth->scratch_ring[i].txd1 =
(dma_addr + (i * MTK_QDMA_PAGE_SIZE)); (dma_addr + (i * MTK_QDMA_PAGE_SIZE));
if (i < cnt - 1) 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))); ((i + 1) * sizeof(struct mtk_tx_dma)));
eth->scratch_ring[i].txd3 = TX_DMA_SDL(MTK_QDMA_PAGE_SIZE); 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, phy_ring_tail, MTK_QDMA_FQ_TAIL);
mtk_w32(eth, (cnt << 16) | cnt, MTK_QDMA_FQ_CNT); mtk_w32(eth, (cnt << 16) | cnt, MTK_QDMA_FQ_CNT);
mtk_w32(eth, MTK_QDMA_PAGE_SIZE << 16, MTK_QDMA_FQ_BLEN); mtk_w32(eth, MTK_QDMA_PAGE_SIZE << 16, MTK_QDMA_FQ_BLEN);
...@@ -1210,6 +1210,14 @@ static void mtk_dma_free(struct mtk_eth *eth) ...@@ -1210,6 +1210,14 @@ static void mtk_dma_free(struct mtk_eth *eth)
for (i = 0; i < MTK_MAC_COUNT; i++) for (i = 0; i < MTK_MAC_COUNT; i++)
if (eth->netdev[i]) if (eth->netdev[i])
netdev_reset_queue(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_tx_clean(eth);
mtk_rx_clean(eth); mtk_rx_clean(eth);
kfree(eth->scratch_head); kfree(eth->scratch_head);
......
...@@ -357,6 +357,7 @@ struct mtk_rx_ring { ...@@ -357,6 +357,7 @@ struct mtk_rx_ring {
* @rx_ring: Pointer to the memore holding info about the RX ring * @rx_ring: Pointer to the memore holding info about the RX ring
* @rx_napi: The NAPI struct * @rx_napi: The NAPI struct
* @scratch_ring: Newer SoCs need memory for a second HW managed TX ring * @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. * @scratch_head: The scratch memory that scratch_ring points to.
* @clk_ethif: The ethif clock * @clk_ethif: The ethif clock
* @clk_esw: The switch clock * @clk_esw: The switch clock
...@@ -384,6 +385,7 @@ struct mtk_eth { ...@@ -384,6 +385,7 @@ struct mtk_eth {
struct mtk_rx_ring rx_ring; struct mtk_rx_ring rx_ring;
struct napi_struct rx_napi; struct napi_struct rx_napi;
struct mtk_tx_dma *scratch_ring; struct mtk_tx_dma *scratch_ring;
dma_addr_t phy_scratch_ring;
void *scratch_head; void *scratch_head;
struct clk *clk_ethif; struct clk *clk_ethif;
struct clk *clk_esw; struct clk *clk_esw;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment