aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/dma.c
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2009-07-29 11:54:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-04 16:43:26 -0400
commit18c6951091eca7645005a71b556106cc99a6f4b1 (patch)
treef8e67fe0f40a6d846931653fc50fe25d8d623b91 /drivers/net/wireless/b43/dma.c
parentae6f53f25f9803212d1985b5eb5a03111f439c24 (diff)
b43: Work around mac80211 race condition
As shown in http://thread.gmane.org/gmane.linux.kernel.wireless.general/36497, mac80211 has a bug that allows a call to the TX routine after the queues have been stopped. This situation will only occur under extreme stress. Although b43 does not crash when this condition occurs, it does generate a WARN_ON and also logs a queue overrun message. This patch recognizes b43 is not at fault and logs a message only when the most verbose debugging mode is enabled. In the unlikely event that the queue is not stopped when the DMA queue becomes full, then a warning is issued. During testing of this patch with one output stream running repeated tcpperf writes and a second running a flood ping, this routine was entered with the DMA ring stopped about once per hour. The condition where the DMA queue is full but the ring has not been stopped has never been seen by me. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43/dma.c')
-rw-r--r--drivers/net/wireless/b43/dma.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 7964cc32b258..41a0e9c2b339 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1334,13 +1334,22 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1334 spin_lock_irqsave(&ring->lock, flags); 1334 spin_lock_irqsave(&ring->lock, flags);
1335 1335
1336 B43_WARN_ON(!ring->tx); 1336 B43_WARN_ON(!ring->tx);
1337 /* Check if the queue was stopped in mac80211,
1338 * but we got called nevertheless.
1339 * That would be a mac80211 bug. */
1340 B43_WARN_ON(ring->stopped);
1341 1337
1342 if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) { 1338 if (unlikely(ring->stopped)) {
1343 b43warn(dev->wl, "DMA queue overflow\n"); 1339 /* We get here only because of a bug in mac80211.
1340 * Because of a race, one packet may be queued after
1341 * the queue is stopped, thus we got called when we shouldn't.
1342 * For now, just refuse the transmit. */
1343 if (b43_debug(dev, B43_DBG_DMAVERBOSE))
1344 b43err(dev->wl, "Packet after queue stopped\n");
1345 err = -ENOSPC;
1346 goto out_unlock;
1347 }
1348
1349 if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
1350 /* If we get here, we have a real error with the queue
1351 * full, but queues not stopped. */
1352 b43err(dev->wl, "DMA queue overflow\n");
1344 err = -ENOSPC; 1353 err = -ENOSPC;
1345 goto out_unlock; 1354 goto out_unlock;
1346 } 1355 }