[PATCH] b43: use rx desc underrun interrupt
Jonas Gorski
jonas.gorski at gmail.com
Fri Apr 19 10:32:00 EDT 2013
Hi,
On Mon, Apr 15, 2013 at 10:02 AM, Thommy Jakobsson <thommyj at gmail.com> wrote:
> Hi,
>
> long user of b43 driver under openwrt. Not sure if it has been posted
> previously but using slow and old hardware (as routers running openwrt
> most of the time is), the CPU is sometimes slower than the NIC. So
> recently I, and several others, has had problem of wifi going down.
> See ticket 7552 at openwrt for more info
> (https://dev.openwrt.org/ticket/7552)
>
> I have tracked down the problem to the nic getting into a rx
> descriptor underrun. Since the driver don't listen to that (or take
> care of it in any other way), the Wifi seemingly just dies. The CPU is
> waiting for data from the nic and the nic is waiting for a
> confirmation that it can keep sending.
>
> I created a patch for handling of that interrupt. I have tested it by
> reducing the number of rx slots to 16 and sending a couple of 100GB of
> data. Previously Wifi went down within a minute when maxing out the
> uplink (so rx for AP), now it has been working flawless for a 1.5week.
Nice, very good to hear. Looks like you found the real issue the rx
descriptor count increase was just papering over. Some comments
regarding your patch.
>
> BR,
> Thommy Jakobsson
>
You are missing a "Signed-off-by" - without it the patch can never be
accepted. Also your patch is has broken tabs (they were converted to
spaces), as well as is line-broken, so it doesn't apply anymore. You
can't use gmail's web interface for sending patches.
> Index: drivers/net/wireless/b43/dma.c
> ===================================================================
> --- compat-wireless-2012-09-07.orig/drivers/net/wireless/b43/dma.c
> 2013-04-09 17:33:54.325322046 +0200
> +++ compat-wireless-2012-09-07/drivers/net/wireless/b43/dma.c
You should make your patch against the newest git tree, so usually
wireless-testing or Rafał's b43-next.
> 2013-04-09 17:34:43.473565843 +0200
> @@ -1688,6 +1688,21 @@
> b43_poison_rx_buffer(ring, skb);
> sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
> }
> +void b43_dma_rx_discard(struct b43_dmaring *ring)
> +{
> + B43_WARN_ON(ring->tx);
> +
> + /* Device has filled all buffers, drop all packets in buffers
> + * and let TCP decrease speed.
> + * Set index to one desc after the last one (which is marked)
> + * so the device will see all slots as free again
> + */
> + /*
> + *TODO: How to increase rx_drop in mac80211
> + */
> + b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
> + sizeof(struct b43_dmadesc32));
> +}
>
> void b43_dma_rx(struct b43_dmaring *ring)
> {
>
> Index: drivers/net/wireless/b43/dma.h
> ===================================================================
> --- compat-wireless-2012-09-07.orig/drivers/net/wireless/b43/dma.h
> 2013-04-09 17:34:09.561397686 +0200
> +++ compat-wireless-2012-09-07/drivers/net/wireless/b43/dma.h
> 2013-04-09 17:34:43.461565780 +0200
> @@ -10,7 +10,8 @@
> #define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
> | (1 << 14) | (1 << 15))
> #define B43_DMAIRQ_NONFATALMASK (1 << 13)
> -#define B43_DMAIRQ_RX_DONE (1 << 16)
> +#define B43_DMAIRQ_RX_DONE (1 << 16)
Unnecessary whitespace change.
> +#define B43_DMAIRQ_RDESC_UFLOW (1 << 13)
Why not just rename B43_DMAIRQ_NONFATALMASK ?
>
> /*** 32-bit DMA Engine. ***/
>
> @@ -295,6 +296,8 @@
> void b43_dma_handle_txstatus(struct b43_wldev *dev,
> const struct b43_txstatus *status);
>
> +void b43_dma_rx_discard(struct b43_dmaring *ring);
> +
> void b43_dma_rx(struct b43_dmaring *ring);
>
> void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
>
> Index: drivers/net/wireless/b43/main.c
> ===================================================================
> --- compat-wireless-2012-09-07.orig/drivers/net/wireless/b43/main.c
> 2013-04-09 17:33:54.325322046 +0200
> +++ compat-wireless-2012-09-07/drivers/net/wireless/b43/main.c
> 2013-04-09 18:08:01.011471215 +0200
> @@ -1894,14 +1894,6 @@
> 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]);
> - }
You should say why you remove this one, and you should remove the
B43_DMAIRQ_NONFATALMASK from the if (unlikely()) enclosing it.
> }
>
> if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
> @@ -1920,6 +1912,14 @@
> handle_irq_noise(dev);
>
> /* Check the DMA reason registers for received data. */
> + if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) {
> + //only print 256 time to not flood log
> + if(!(dev->stats.rxdesc_underruns++&0xFF)){
> + b43warn(dev->wl, "Rx descriptor underrun
> (high cpu load?), throwing packets\n");
Apart from the style problems, maybe doing a
if (printk_ratelimit())
b43warn(...);
which will ensure that it won't flood the log, but still won't stop
reporting them after the 256th time.
> + }
> + b43_dma_rx_discard(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);
> @@ -1977,7 +1977,7 @@
> 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)
> @@ -3081,7 +3081,7 @@
> 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);
>
> ===================================================================
> --- compat-wireless-2012-09-07.orig/drivers/net/wireless/b43/b43.h
> 2013-04-09 17:04:51.552680190 +0200
> +++ compat-wireless-2012-09-07/drivers/net/wireless/b43/b43.h
> 2013-04-09 17:46:08.472962612 +0200
> @@ -671,6 +671,7 @@
>
> struct b43_stats {
> u8 link_noise;
> + u32 rxdesc_underruns;
> };
>
> struct b43_key {
Jonas
More information about the b43-dev
mailing list