mac80211: brcmsmac: remove initial support for core rev 28
[openwrt.git] / package / mac80211 / patches / 840-b43-Handle-DMA-RX-descriptor-underrun.patch
1 From 5921f167baf30255ebc079c6e751a7ed31cd986d Mon Sep 17 00:00:00 2001
2 From: Thommy Jakobsson <thommyj@gmail.com>
3 Date: Tue, 23 Apr 2013 21:45:11 +0200
4 Subject: [PATCH 2/3] B43: Handle DMA RX descriptor underrun
5
6 Add handling of rx descriptor underflow. This fixes a fault that could
7 happen on slow machines, where data is received faster than the CPU can
8 handle. In such a case the device will use up all rx descriptors and
9 refuse to send any more data before confirming that it is ok. This
10 patch enables necessary interrupt to discover such a situation and will
11 handle them by dropping everything in the ring buffer.
12
13 Reviewed-by: Michael Buesch <m@bues.ch>
14 Signed-off-by: Thommy Jakobsson <thommyj@gmail.com>
15 Cc: stable <stable@vger.kernel.org>
16 ---
17  drivers/net/wireless/b43/dma.c  |   19 +++++++++++++++++
18  drivers/net/wireless/b43/dma.h  |    4 +++-
19  drivers/net/wireless/b43/main.c |   43 ++++++++++++++++-----------------------
20  3 files changed, 40 insertions(+), 26 deletions(-)
21
22 --- a/drivers/net/wireless/b43/dma.c
23 +++ b/drivers/net/wireless/b43/dma.c
24 @@ -1733,6 +1733,25 @@ drop_recycle_buffer:
25         sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
26  }
27  
28 +void b43_dma_handle_rx_overflow(struct b43_dmaring *ring)
29 +{
30 +       int current_slot, previous_slot;
31 +
32 +       B43_WARN_ON(ring->tx);
33 +
34 +       /* Device has filled all buffers, drop all packets and let TCP
35 +        * decrease speed.
36 +        * Decrement RX index by one will let the device to see all slots
37 +        * as free again
38 +        */
39 +       /*
40 +       *TODO: How to increase rx_drop in mac80211?
41 +       */
42 +       current_slot = ring->ops->get_current_rxslot(ring);
43 +       previous_slot = prev_slot(ring, current_slot);
44 +       ring->ops->set_current_rxslot(ring, previous_slot);
45 +}
46 +
47  void b43_dma_rx(struct b43_dmaring *ring)
48  {
49         const struct b43_dma_ops *ops = ring->ops;
50 --- a/drivers/net/wireless/b43/dma.h
51 +++ b/drivers/net/wireless/b43/dma.h
52 @@ -9,7 +9,7 @@
53  /* DMA-Interrupt reasons. */
54  #define B43_DMAIRQ_FATALMASK   ((1 << 10) | (1 << 11) | (1 << 12) \
55                                          | (1 << 14) | (1 << 15))
56 -#define B43_DMAIRQ_NONFATALMASK        (1 << 13)
57 +#define B43_DMAIRQ_RDESC_UFLOW         (1 << 13)
58  #define B43_DMAIRQ_RX_DONE             (1 << 16)
59  
60  /*** 32-bit DMA Engine. ***/
61 @@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev,
62  void b43_dma_handle_txstatus(struct b43_wldev *dev,
63                              const struct b43_txstatus *status);
64  
65 +void b43_dma_handle_rx_overflow(struct b43_dmaring *ring);
66 +
67  void b43_dma_rx(struct b43_dmaring *ring);
68  
69  void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
70 --- a/drivers/net/wireless/b43/main.c
71 +++ b/drivers/net/wireless/b43/main.c
72 @@ -1907,32 +1907,20 @@ static void b43_do_interrupt_thread(stru
73                 }
74         }
75  
76 -       if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
77 -                                         B43_DMAIRQ_NONFATALMASK))) {
78 -               if (merged_dma_reason & B43_DMAIRQ_FATALMASK) {
79 -                       b43err(dev->wl, "Fatal DMA error: "
80 -                              "0x%08X, 0x%08X, 0x%08X, "
81 -                              "0x%08X, 0x%08X, 0x%08X\n",
82 -                              dma_reason[0], dma_reason[1],
83 -                              dma_reason[2], dma_reason[3],
84 -                              dma_reason[4], dma_reason[5]);
85 +       if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) {
86 +               b43err(dev->wl,
87 +                       "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
88 +                       dma_reason[0], dma_reason[1],
89 +                       dma_reason[2], dma_reason[3],
90 +                       dma_reason[4], dma_reason[5]);
91  #ifdef CONFIG_B43_PIO
92 -                       b43err(dev->wl, "This device does not support DMA "
93 +               b43err(dev->wl, "This device does not support DMA "
94                                "on your system. It will now be switched to PIO.\n");
95 -                       /* Fall back to PIO transfers if we get fatal DMA errors! */
96 -                       dev->use_pio = true;
97 +               /* Fall back to PIO transfers if we get fatal DMA errors! */
98 +               dev->use_pio = true;
99  #endif
100 -                       b43_controller_restart(dev, "DMA error");
101 -                       return;
102 -               }
103 -               if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
104 -                       b43err(dev->wl, "DMA error: "
105 -                              "0x%08X, 0x%08X, 0x%08X, "
106 -                              "0x%08X, 0x%08X, 0x%08X\n",
107 -                              dma_reason[0], dma_reason[1],
108 -                              dma_reason[2], dma_reason[3],
109 -                              dma_reason[4], dma_reason[5]);
110 -               }
111 +               b43_controller_restart(dev, "DMA error");
112 +               return;
113         }
114  
115         if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
116 @@ -1951,6 +1939,11 @@ static void b43_do_interrupt_thread(stru
117                 handle_irq_noise(dev);
118  
119         /* Check the DMA reason registers for received data. */
120 +       if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) {
121 +               if (B43_DEBUG)
122 +                       b43warn(dev->wl, "RX descriptor underrun\n");
123 +               b43_dma_handle_rx_overflow(dev->dma.rx_ring);
124 +       }
125         if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
126                 if (b43_using_pio_transfers(dev))
127                         b43_pio_rx(dev->pio.rx_queue);
128 @@ -2008,7 +2001,7 @@ static irqreturn_t b43_do_interrupt(stru
129                 return IRQ_NONE;
130  
131         dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
132 -           & 0x0001DC00;
133 +           & 0x0001FC00;
134         dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
135             & 0x0000DC00;
136         dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
137 @@ -3137,7 +3130,7 @@ static int b43_chip_init(struct b43_wlde
138                 b43_write32(dev, 0x018C, 0x02000000);
139         }
140         b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
141 -       b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
142 +       b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00);
143         b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
144         b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
145         b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00);