From a45263c32edfd7efa0c28628c389201f86bf2915 Mon Sep 17 00:00:00 2001 From: hauke Date: Sun, 28 Apr 2013 16:55:53 +0000 Subject: mac80211: b43: Handle DMA RX descriptor underrun git-svn-id: svn://svn.openwrt.org/openwrt/trunk@36474 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...840-b43-Handle-DMA-RX-descriptor-underrun.patch | 145 +++++++++++++++++++++ .../841-b43-reduce-number-of-RX-slots.patch | 11 ++ 2 files changed, 156 insertions(+) create mode 100644 package/mac80211/patches/840-b43-Handle-DMA-RX-descriptor-underrun.patch create mode 100644 package/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch (limited to 'package/mac80211') diff --git a/package/mac80211/patches/840-b43-Handle-DMA-RX-descriptor-underrun.patch b/package/mac80211/patches/840-b43-Handle-DMA-RX-descriptor-underrun.patch new file mode 100644 index 000000000..461e4ddb0 --- /dev/null +++ b/package/mac80211/patches/840-b43-Handle-DMA-RX-descriptor-underrun.patch @@ -0,0 +1,145 @@ +From 5921f167baf30255ebc079c6e751a7ed31cd986d Mon Sep 17 00:00:00 2001 +From: Thommy Jakobsson +Date: Tue, 23 Apr 2013 21:45:11 +0200 +Subject: [PATCH 2/3] 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 +Signed-off-by: Thommy Jakobsson +Cc: stable +--- + drivers/net/wireless/b43/dma.c | 19 +++++++++++++++++ + drivers/net/wireless/b43/dma.h | 4 +++- + drivers/net/wireless/b43/main.c | 43 ++++++++++++++++----------------------- + 3 files changed, 40 insertions(+), 26 deletions(-) + +--- 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; +--- a/drivers/net/wireless/b43/dma.h ++++ b/drivers/net/wireless/b43/dma.h +@@ -9,7 +9,7 @@ + /* DMA-Interrupt reasons. */ + #define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ + | (1 << 14) | (1 << 15)) +-#define B43_DMAIRQ_NONFATALMASK (1 << 13) ++#define B43_DMAIRQ_RDESC_UFLOW (1 << 13) + #define B43_DMAIRQ_RX_DONE (1 << 16) + + /*** 32-bit DMA Engine. ***/ +@@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev, + void b43_dma_handle_txstatus(struct b43_wldev *dev, + const struct b43_txstatus *status); + ++void b43_dma_handle_rx_overflow(struct b43_dmaring *ring); ++ + void b43_dma_rx(struct b43_dmaring *ring); + + void b43_dma_direct_fifo_rx(struct b43_wldev *dev, +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -1907,32 +1907,20 @@ static void b43_do_interrupt_thread(stru + } + } + +- if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK | +- B43_DMAIRQ_NONFATALMASK))) { +- if (merged_dma_reason & B43_DMAIRQ_FATALMASK) { +- b43err(dev->wl, "Fatal DMA error: " +- "0x%08X, 0x%08X, 0x%08X, " +- "0x%08X, 0x%08X, 0x%08X\n", +- dma_reason[0], dma_reason[1], +- dma_reason[2], dma_reason[3], +- dma_reason[4], dma_reason[5]); ++ if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) { ++ b43err(dev->wl, ++ "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n", ++ dma_reason[0], dma_reason[1], ++ dma_reason[2], dma_reason[3], ++ dma_reason[4], dma_reason[5]); + #ifdef CONFIG_B43_PIO +- b43err(dev->wl, "This device does not support DMA " ++ b43err(dev->wl, "This device does not support DMA " + "on your system. It will now be switched to PIO.\n"); +- /* Fall back to PIO transfers if we get fatal DMA errors! */ +- dev->use_pio = true; ++ /* Fall back to PIO transfers if we get fatal DMA errors! */ ++ dev->use_pio = true; + #endif +- b43_controller_restart(dev, "DMA error"); +- return; +- } +- if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { +- b43err(dev->wl, "DMA error: " +- "0x%08X, 0x%08X, 0x%08X, " +- "0x%08X, 0x%08X, 0x%08X\n", +- dma_reason[0], dma_reason[1], +- dma_reason[2], dma_reason[3], +- dma_reason[4], dma_reason[5]); +- } ++ b43_controller_restart(dev, "DMA error"); ++ return; + } + + if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) +@@ -1951,6 +1939,11 @@ static void b43_do_interrupt_thread(stru + handle_irq_noise(dev); + + /* Check the DMA reason registers for received data. */ ++ if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) { ++ if (B43_DEBUG) ++ b43warn(dev->wl, "RX descriptor underrun\n"); ++ b43_dma_handle_rx_overflow(dev->dma.rx_ring); ++ } + if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { + if (b43_using_pio_transfers(dev)) + b43_pio_rx(dev->pio.rx_queue); +@@ -2008,7 +2001,7 @@ static irqreturn_t b43_do_interrupt(stru + return IRQ_NONE; + + dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) +- & 0x0001DC00; ++ & 0x0001FC00; + dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) + & 0x0000DC00; + dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) +@@ -3137,7 +3130,7 @@ static int b43_chip_init(struct b43_wlde + b43_write32(dev, 0x018C, 0x02000000); + } + b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); +- b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00); ++ b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00); + b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); + b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); + b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); diff --git a/package/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch b/package/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch new file mode 100644 index 000000000..9c51ac63d --- /dev/null +++ b/package/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/b43/dma.h ++++ b/drivers/net/wireless/b43/dma.h +@@ -169,7 +169,7 @@ struct b43_dmadesc_generic { + + /* DMA engine tuning knobs */ + #define B43_TXRING_SLOTS 256 +-#define B43_RXRING_SLOTS 256 ++#define B43_RXRING_SLOTS 32 + #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) + #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) + -- cgit v1.2.3