Commit 6001f340 authored by David S. Miller's avatar David S. Miller

Merge branch 'mvpp2-fixes'

Marcin Wojtas says:

====================
Marvell Armada 375 mvpp2 fixes

During my work on mvneta driver I revised mvpp2, and it occurred that the
initial version of Marvell Armada 375 SoC comprised bugs around
DMA-unmapping in both ingress and egress paths - not all buffers were
umapped in TX path and none(!) in RX. Three patches that I send fix
this situation.

Any feedback would be welcome.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3cf92222 b5015854
...@@ -3413,16 +3413,23 @@ static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv, ...@@ -3413,16 +3413,23 @@ static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv,
} }
/* Free all buffers from the pool */ /* Free all buffers from the pool */
static void mvpp2_bm_bufs_free(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool) static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
struct mvpp2_bm_pool *bm_pool)
{ {
int i; int i;
for (i = 0; i < bm_pool->buf_num; i++) { for (i = 0; i < bm_pool->buf_num; i++) {
dma_addr_t buf_phys_addr;
u32 vaddr; u32 vaddr;
/* Get buffer virtual address (indirect access) */ /* Get buffer virtual address (indirect access) */
mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id)); buf_phys_addr = mvpp2_read(priv,
MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
vaddr = mvpp2_read(priv, MVPP2_BM_VIRT_ALLOC_REG); vaddr = mvpp2_read(priv, MVPP2_BM_VIRT_ALLOC_REG);
dma_unmap_single(dev, buf_phys_addr,
bm_pool->buf_size, DMA_FROM_DEVICE);
if (!vaddr) if (!vaddr)
break; break;
dev_kfree_skb_any((struct sk_buff *)vaddr); dev_kfree_skb_any((struct sk_buff *)vaddr);
...@@ -3439,7 +3446,7 @@ static int mvpp2_bm_pool_destroy(struct platform_device *pdev, ...@@ -3439,7 +3446,7 @@ static int mvpp2_bm_pool_destroy(struct platform_device *pdev,
{ {
u32 val; u32 val;
mvpp2_bm_bufs_free(priv, bm_pool); mvpp2_bm_bufs_free(&pdev->dev, priv, bm_pool);
if (bm_pool->buf_num) { if (bm_pool->buf_num) {
WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id); WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
return 0; return 0;
...@@ -3692,7 +3699,8 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type, ...@@ -3692,7 +3699,8 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
MVPP2_BM_LONG_BUF_NUM : MVPP2_BM_LONG_BUF_NUM :
MVPP2_BM_SHORT_BUF_NUM; MVPP2_BM_SHORT_BUF_NUM;
else else
mvpp2_bm_bufs_free(port->priv, new_pool); mvpp2_bm_bufs_free(port->dev->dev.parent,
port->priv, new_pool);
new_pool->pkt_size = pkt_size; new_pool->pkt_size = pkt_size;
...@@ -3756,7 +3764,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu) ...@@ -3756,7 +3764,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
int pkt_size = MVPP2_RX_PKT_SIZE(mtu); int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
/* Update BM pool with new buffer size */ /* Update BM pool with new buffer size */
mvpp2_bm_bufs_free(port->priv, port_pool); mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool);
if (port_pool->buf_num) { if (port_pool->buf_num) {
WARN(1, "cannot free all buffers in pool %d\n", port_pool->id); WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
return -EIO; return -EIO;
...@@ -4401,11 +4409,10 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port, ...@@ -4401,11 +4409,10 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
mvpp2_txq_inc_get(txq_pcpu); mvpp2_txq_inc_get(txq_pcpu);
if (!skb)
continue;
dma_unmap_single(port->dev->dev.parent, buf_phys_addr, dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
skb_headlen(skb), DMA_TO_DEVICE); skb_headlen(skb), DMA_TO_DEVICE);
if (!skb)
continue;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
} }
} }
...@@ -5092,7 +5099,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, ...@@ -5092,7 +5099,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
struct mvpp2_rx_queue *rxq) struct mvpp2_rx_queue *rxq)
{ {
struct net_device *dev = port->dev; struct net_device *dev = port->dev;
int rx_received, rx_filled, i; int rx_received;
int rx_done = 0;
u32 rcvd_pkts = 0; u32 rcvd_pkts = 0;
u32 rcvd_bytes = 0; u32 rcvd_bytes = 0;
...@@ -5101,17 +5109,18 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, ...@@ -5101,17 +5109,18 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
if (rx_todo > rx_received) if (rx_todo > rx_received)
rx_todo = rx_received; rx_todo = rx_received;
rx_filled = 0; while (rx_done < rx_todo) {
for (i = 0; i < rx_todo; i++) {
struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq); struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
struct mvpp2_bm_pool *bm_pool; struct mvpp2_bm_pool *bm_pool;
struct sk_buff *skb; struct sk_buff *skb;
dma_addr_t phys_addr;
u32 bm, rx_status; u32 bm, rx_status;
int pool, rx_bytes, err; int pool, rx_bytes, err;
rx_filled++; rx_done++;
rx_status = rx_desc->status; rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE; rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
phys_addr = rx_desc->buf_phys_addr;
bm = mvpp2_bm_cookie_build(rx_desc); bm = mvpp2_bm_cookie_build(rx_desc);
pool = mvpp2_bm_cookie_pool_get(bm); pool = mvpp2_bm_cookie_pool_get(bm);
...@@ -5128,8 +5137,10 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, ...@@ -5128,8 +5137,10 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
* comprised by the RX descriptor. * comprised by the RX descriptor.
*/ */
if (rx_status & MVPP2_RXD_ERR_SUMMARY) { if (rx_status & MVPP2_RXD_ERR_SUMMARY) {
err_drop_frame:
dev->stats.rx_errors++; dev->stats.rx_errors++;
mvpp2_rx_error(port, rx_desc); mvpp2_rx_error(port, rx_desc);
/* Return the buffer to the pool */
mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr, mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
rx_desc->buf_cookie); rx_desc->buf_cookie);
continue; continue;
...@@ -5137,6 +5148,15 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, ...@@ -5137,6 +5148,15 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
skb = (struct sk_buff *)rx_desc->buf_cookie; skb = (struct sk_buff *)rx_desc->buf_cookie;
err = mvpp2_rx_refill(port, bm_pool, bm, 0);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
goto err_drop_frame;
}
dma_unmap_single(dev->dev.parent, phys_addr,
bm_pool->buf_size, DMA_FROM_DEVICE);
rcvd_pkts++; rcvd_pkts++;
rcvd_bytes += rx_bytes; rcvd_bytes += rx_bytes;
atomic_inc(&bm_pool->in_use); atomic_inc(&bm_pool->in_use);
...@@ -5147,12 +5167,6 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, ...@@ -5147,12 +5167,6 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
mvpp2_rx_csum(port, rx_status, skb); mvpp2_rx_csum(port, rx_status, skb);
napi_gro_receive(&port->napi, skb); napi_gro_receive(&port->napi, skb);
err = mvpp2_rx_refill(port, bm_pool, bm, 0);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
rx_filled--;
}
} }
if (rcvd_pkts) { if (rcvd_pkts) {
...@@ -5166,7 +5180,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo, ...@@ -5166,7 +5180,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
/* Update Rx queue management counters */ /* Update Rx queue management counters */
wmb(); wmb();
mvpp2_rxq_status_update(port, rxq->id, rx_todo, rx_filled); mvpp2_rxq_status_update(port, rxq->id, rx_done, rx_done);
return rx_todo; return rx_todo;
} }
......
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