summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/b43/dma.c
diff options
context:
space:
mode:
authorfrancesco.gringoli@ing.unibs.it <francesco.gringoli@ing.unibs.it>2011-12-16 18:34:56 +0100
committerJohn W. Linville <linville@tuxdriver.com>2011-12-19 14:40:22 -0500
commitbad6919469662b7c92bc6353642aaaa777b36bac (patch)
tree35c1429e8216cc5ae4ef2f505a838d523045037f /drivers/net/wireless/b43/dma.c
parent1d8d3dec5fbba15864f25c734a7fda5703234091 (diff)
b43: avoid packet losses in the dma worker code.
Following Rafal request, we verified that on "modern" CPUs using one or more workers is equivalent. Here is patch V3 that addresses the packet loss bug in the dma engine using only one worker. ------- This patch addresses a bug in the dma worker code that keeps draining packets even when the hardware queues are full. In such cases packets can not be passed down to the device and are erroneusly dropped by the code. This problem was already discussed here http://www.mail-archive.com/b43-dev@lists.infradead.org/msg01413.html and acknowledged by Michael. Number of hardware queues is now defined in b43.h (B43_QOS_QUEUE_NUM). Acknowledgements to Riccardo Paolillo <riccardo.paolillo@gmail.com> and Michele Orru <michele.orru@hotmail.it> Signed-off-by: Francesco Gringoli <francesco.gringoli@ing.unibs.it> 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.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 5e45604f0f5d..56d37dc967aa 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1465,7 +1465,9 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
should_inject_overflow(ring)) {
/* This TX ring is full. */
- ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
+ unsigned int skb_mapping = skb_get_queue_mapping(skb);
+ ieee80211_stop_queue(dev->wl->hw, skb_mapping);
+ dev->wl->tx_queue_stopped[skb_mapping] = 1;
ring->stopped = 1;
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
@@ -1584,12 +1586,21 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
}
if (ring->stopped) {
B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
- ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
ring->stopped = 0;
+ }
+
+ if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
+ dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
+ } else {
+ /* If the driver queue is running wake the corresponding
+ * mac80211 queue. */
+ ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
}
}
+ /* Add work to the queue. */
+ ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work);
}
static void dma_rx(struct b43_dmaring *ring, int *slot)