diff options
author | Antoine Tenart <antoine.tenart@free-electrons.com> | 2017-11-28 08:19:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-28 10:09:50 -0500 |
commit | ba2d8d887d962c2f790e6dc01b2fd25b4608720b (patch) | |
tree | 8d64dacb5b60e2332c6c9679ba8a9bb1785f01d3 | |
parent | e2549970f469a88152ac0411780306f13653bcb8 (diff) |
net: mvpp2: fix the txq_init error path
When an allocation in the txq_init path fails, the allocated buffers
end-up being freed twice: in the txq_init error path, and in txq_deinit.
This lead to issues as txq_deinit would work on already freed memory
regions:
kernel BUG at mm/slub.c:3915!
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
This patch fixes this by removing the txq_init own error path, as the
txq_deinit function is always called on errors. This was introduced by
TSO as way more buffers are allocated.
Fixes: 186cd4d4e414 ("net: mvpp2: software tso support")
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/marvell/mvpp2.c | 20 |
1 files changed, 2 insertions, 18 deletions
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 6c20e811f973..79f01cd80dd7 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c | |||
@@ -5805,7 +5805,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port, | |||
5805 | sizeof(*txq_pcpu->buffs), | 5805 | sizeof(*txq_pcpu->buffs), |
5806 | GFP_KERNEL); | 5806 | GFP_KERNEL); |
5807 | if (!txq_pcpu->buffs) | 5807 | if (!txq_pcpu->buffs) |
5808 | goto cleanup; | 5808 | return -ENOMEM; |
5809 | 5809 | ||
5810 | txq_pcpu->count = 0; | 5810 | txq_pcpu->count = 0; |
5811 | txq_pcpu->reserved_num = 0; | 5811 | txq_pcpu->reserved_num = 0; |
@@ -5821,26 +5821,10 @@ static int mvpp2_txq_init(struct mvpp2_port *port, | |||
5821 | &txq_pcpu->tso_headers_dma, | 5821 | &txq_pcpu->tso_headers_dma, |
5822 | GFP_KERNEL); | 5822 | GFP_KERNEL); |
5823 | if (!txq_pcpu->tso_headers) | 5823 | if (!txq_pcpu->tso_headers) |
5824 | goto cleanup; | 5824 | return -ENOMEM; |
5825 | } | 5825 | } |
5826 | 5826 | ||
5827 | return 0; | 5827 | return 0; |
5828 | cleanup: | ||
5829 | for_each_present_cpu(cpu) { | ||
5830 | txq_pcpu = per_cpu_ptr(txq->pcpu, cpu); | ||
5831 | kfree(txq_pcpu->buffs); | ||
5832 | |||
5833 | dma_free_coherent(port->dev->dev.parent, | ||
5834 | txq_pcpu->size * TSO_HEADER_SIZE, | ||
5835 | txq_pcpu->tso_headers, | ||
5836 | txq_pcpu->tso_headers_dma); | ||
5837 | } | ||
5838 | |||
5839 | dma_free_coherent(port->dev->dev.parent, | ||
5840 | txq->size * MVPP2_DESC_ALIGNED_SIZE, | ||
5841 | txq->descs, txq->descs_dma); | ||
5842 | |||
5843 | return -ENOMEM; | ||
5844 | } | 5828 | } |
5845 | 5829 | ||
5846 | /* Free allocated TXQ resources */ | 5830 | /* Free allocated TXQ resources */ |