Skip to content

Commit 20a41fb

Browse files
tlendackydavem330
authored andcommitted
amd-xgbe: Use wmb before updating current descriptor count
The code currently uses the lightweight dma_wmb barrier before updating the current descriptor count. Under heavy load, the Tx cleanup routine was seeing the updated current descriptor count before the updated descriptor information. As a result, the Tx descriptor was being cleaned up before it was used because it was not "owned" by the hardware yet, resulting in a Tx queue hang. Using the wmb barrier insures that the descriptor is updated before the descriptor counter preventing the Tx queue hang. For extra insurance, the Tx cleanup routine is changed to grab the current decriptor count on entry and uses that initial value in the processing loop rather than trying to chase the current value. Signed-off-by: Tom Lendacky <[email protected]> Tested-by: Christoffer Dall <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d2fd719 commit 20a41fb

File tree

2 files changed

+4
-2
lines changed

2 files changed

+4
-2
lines changed

drivers/net/ethernet/amd/xgbe/xgbe-dev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
15951595
packet->rdesc_count, 1);
15961596

15971597
/* Make sure ownership is written to the descriptor */
1598-
dma_wmb();
1598+
wmb();
15991599

16001600
ring->cur = cur_index + 1;
16011601
if (!packet->skb->xmit_more ||

drivers/net/ethernet/amd/xgbe/xgbe-drv.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1807,17 +1807,19 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
18071807
struct netdev_queue *txq;
18081808
int processed = 0;
18091809
unsigned int tx_packets = 0, tx_bytes = 0;
1810+
unsigned int cur;
18101811

18111812
DBGPR("-->xgbe_tx_poll\n");
18121813

18131814
/* Nothing to do if there isn't a Tx ring for this channel */
18141815
if (!ring)
18151816
return 0;
18161817

1818+
cur = ring->cur;
18171819
txq = netdev_get_tx_queue(netdev, channel->queue_index);
18181820

18191821
while ((processed < XGBE_TX_DESC_MAX_PROC) &&
1820-
(ring->dirty != ring->cur)) {
1822+
(ring->dirty != cur)) {
18211823
rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
18221824
rdesc = rdata->rdesc;
18231825

0 commit comments

Comments
 (0)