forked from Minki/linux
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: John Crispin <john@phrozen.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
562c5a7040
commit
605e4fe476
@ -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 */
|
||||
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;
|
||||
@ -505,19 +505,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);
|
||||
@ -1210,6 +1210,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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user