]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/wireless/b43/dma.c
b43: Work around mac80211 race condition
[net-next-2.6.git] / drivers / net / wireless / b43 / dma.c
index eae680b530527f639fcce2f1568188540e69e3cd..41a0e9c2b339d9043d0136adfa479fc7ebf17d3a 100644 (file)
@@ -1285,7 +1285,7 @@ static struct b43_dmaring *select_ring_by_priority(struct b43_wldev *dev,
 {
        struct b43_dmaring *ring;
 
-       if (b43_modparam_qos) {
+       if (dev->qos_enabled) {
                /* 0 = highest priority */
                switch (queue_prio) {
                default:
@@ -1334,13 +1334,22 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
        spin_lock_irqsave(&ring->lock, flags);
 
        B43_WARN_ON(!ring->tx);
-       /* Check if the queue was stopped in mac80211,
-        * but we got called nevertheless.
-        * That would be a mac80211 bug. */
-       B43_WARN_ON(ring->stopped);
 
-       if (unlikely(free_slots(ring) < TX_SLOTS_PER_FRAME)) {
-               b43warn(dev->wl, "DMA queue overflow\n");
+       if (unlikely(ring->stopped)) {
+               /* We get here only because of a bug in mac80211.
+                * Because of a race, one packet may be queued after
+                * the queue is stopped, thus we got called when we shouldn't.
+                * For now, just refuse the transmit. */
+               if (b43_debug(dev, B43_DBG_DMAVERBOSE))
+                       b43err(dev->wl, "Packet after queue stopped\n");
+               err = -ENOSPC;
+               goto out_unlock;
+       }
+
+       if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
+               /* If we get here, we have a real error with the queue
+                * full, but queues not stopped. */
+               b43err(dev->wl, "DMA queue overflow\n");
                err = -ENOSPC;
                goto out_unlock;
        }