aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/dma.c
diff options
context:
space:
mode:
authorThommy Jakobsson <thommyj@gmail.com>2013-04-23 21:45:11 +0200
committerJohn W. Linville <linville@tuxdriver.com>2013-05-08 17:15:06 -0400
commit73b82bf0bfbf58e6ff328d3726934370585f6e78 (patch)
tree19c23412ef8e7fbf7353eeb7084bf96c962ed725 /drivers/net/wireless/b43/dma.c
parentath5k: do not reschedule tx_complete_work on stop (diff)
downloadlinux-dev-73b82bf0bfbf58e6ff328d3726934370585f6e78.tar.xz
linux-dev-73b82bf0bfbf58e6ff328d3726934370585f6e78.zip
B43: Handle DMA RX descriptor underrun
Add handling of rx descriptor underflow. This fixes a fault that could happen on slow machines, where data is received faster than the CPU can handle. In such a case the device will use up all rx descriptors and refuse to send any more data before confirming that it is ok. This patch enables necessary interrupt to discover such a situation and will handle them by dropping everything in the ring buffer. Reviewed-by: Michael Buesch <m@bues.ch> Signed-off-by: Thommy Jakobsson <thommyj@gmail.com> Cc: stable <stable@vger.kernel.org> 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.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 122146943bf2..ee3d6403c795 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1733,6 +1733,25 @@ drop_recycle_buffer:
sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
}
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring)
+{
+ int current_slot, previous_slot;
+
+ B43_WARN_ON(ring->tx);
+
+ /* Device has filled all buffers, drop all packets and let TCP
+ * decrease speed.
+ * Decrement RX index by one will let the device to see all slots
+ * as free again
+ */
+ /*
+ *TODO: How to increase rx_drop in mac80211?
+ */
+ current_slot = ring->ops->get_current_rxslot(ring);
+ previous_slot = prev_slot(ring, current_slot);
+ ring->ops->set_current_rxslot(ring, previous_slot);
+}
+
void b43_dma_rx(struct b43_dmaring *ring)
{
const struct b43_dma_ops *ops = ring->ops;