Skip to content

Commit 86b61a5

Browse files
tlfalcondavem330
authored andcommitted
ibmvnic: Improve TX buffer accounting
Improve TX pool buffer accounting to prevent the producer index from overruning the consumer. First, set the next free index to an invalid value if it is in use. If next buffer to be consumed is in use, drop the packet. Finally, if the transmit fails for some other reason, roll back the consumer index and set the free map entry to its original value. This should also be done if the DMA map fails. Signed-off-by: Thomas Falcon <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 06b3e35 commit 86b61a5

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,16 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
14261426

14271427
index = tx_pool->free_map[tx_pool->consumer_index];
14281428

1429+
if (index == IBMVNIC_INVALID_MAP) {
1430+
dev_kfree_skb_any(skb);
1431+
tx_send_failed++;
1432+
tx_dropped++;
1433+
ret = NETDEV_TX_OK;
1434+
goto out;
1435+
}
1436+
1437+
tx_pool->free_map[tx_pool->consumer_index] = IBMVNIC_INVALID_MAP;
1438+
14291439
offset = index * tx_pool->buf_size;
14301440
dst = tx_pool->long_term_buff.buff + offset;
14311441
memset(dst, 0, tx_pool->buf_size);
@@ -1522,7 +1532,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
15221532
tx_map_failed++;
15231533
tx_dropped++;
15241534
ret = NETDEV_TX_OK;
1525-
goto out;
1535+
goto tx_err_out;
15261536
}
15271537
lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
15281538
(u64)tx_buff->indir_dma,
@@ -1534,13 +1544,6 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
15341544
}
15351545
if (lpar_rc != H_SUCCESS) {
15361546
dev_err(dev, "tx failed with code %ld\n", lpar_rc);
1537-
1538-
if (tx_pool->consumer_index == 0)
1539-
tx_pool->consumer_index =
1540-
tx_pool->num_buffers - 1;
1541-
else
1542-
tx_pool->consumer_index--;
1543-
15441547
dev_kfree_skb_any(skb);
15451548
tx_buff->skb = NULL;
15461549

@@ -1556,7 +1559,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
15561559
tx_send_failed++;
15571560
tx_dropped++;
15581561
ret = NETDEV_TX_OK;
1559-
goto out;
1562+
goto tx_err_out;
15601563
}
15611564

15621565
if (atomic_add_return(num_entries, &tx_scrq->used)
@@ -1569,7 +1572,16 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
15691572
tx_bytes += skb->len;
15701573
txq->trans_start = jiffies;
15711574
ret = NETDEV_TX_OK;
1575+
goto out;
15721576

1577+
tx_err_out:
1578+
/* roll back consumer index and map array*/
1579+
if (tx_pool->consumer_index == 0)
1580+
tx_pool->consumer_index =
1581+
tx_pool->num_buffers - 1;
1582+
else
1583+
tx_pool->consumer_index--;
1584+
tx_pool->free_map[tx_pool->consumer_index] = index;
15731585
out:
15741586
netdev->stats.tx_dropped += tx_dropped;
15751587
netdev->stats.tx_bytes += tx_bytes;

0 commit comments

Comments
 (0)