]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:21:54 +0000 (14:21 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:21:54 +0000 (14:21 -0700)
added patches:
b43-a-fix-for-dma-transmission-sequence-errors.patch

queue-3.0/b43-a-fix-for-dma-transmission-sequence-errors.patch [new file with mode: 0644]
queue-3.0/series

diff --git a/queue-3.0/b43-a-fix-for-dma-transmission-sequence-errors.patch b/queue-3.0/b43-a-fix-for-dma-transmission-sequence-errors.patch
new file mode 100644 (file)
index 0000000..5f9f364
--- /dev/null
@@ -0,0 +1,155 @@
+From b251412db99ccd4495ce372fec7daee27bf06923 Mon Sep 17 00:00:00 2001
+From: "Iestyn C. Elfick" <isedev@gmail.com>
+Date: Wed, 20 Mar 2013 14:02:31 -0500
+Subject: b43: A fix for DMA transmission sequence errors
+
+From: "Iestyn C. Elfick" <isedev@gmail.com>
+
+commit b251412db99ccd4495ce372fec7daee27bf06923 upstream.
+
+Intermittently, b43 will report "Out of order TX status report on DMA ring".
+When this happens, the driver must be reset before communication can resume.
+The cause of the problem is believed to be an error in the closed-source
+firmware; however, all versions of the firmware are affected.
+
+This change uses the observation that the expected status is always 2 less
+than the observed value, and supplies a fake status report to skip one
+header/data pair.
+
+Not all devices suffer from this problem, but it can occur several times
+per second under heavy load. As each occurence kills the unmodified driver,
+this patch makes if possible for the affected devices to function. The patch
+logs only the first instance of the reset operation to prevent spamming
+the logs.
+
+Tested-by: Chris Vine <chris@cvine.freeserve.co.uk>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/b43/dma.c |   65 +++++++++++++++++++++++++++++++++--------
+ 1 file changed, 53 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/wireless/b43/dma.c
++++ b/drivers/net/wireless/b43/dma.c
+@@ -1390,8 +1390,12 @@ void b43_dma_handle_txstatus(struct b43_
+       struct b43_dmaring *ring;
+       struct b43_dmadesc_generic *desc;
+       struct b43_dmadesc_meta *meta;
++      static const struct b43_txstatus fake; /* filled with 0 */
++      const struct b43_txstatus *txstat;
+       int slot, firstused;
+       bool frame_succeed;
++      int skip;
++      static u8 err_out1, err_out2;
+       ring = parse_cookie(dev, status->cookie, &slot);
+       if (unlikely(!ring))
+@@ -1404,13 +1408,36 @@ void b43_dma_handle_txstatus(struct b43_
+       firstused = ring->current_slot - ring->used_slots + 1;
+       if (firstused < 0)
+               firstused = ring->nr_slots + firstused;
++
++      skip = 0;
+       if (unlikely(slot != firstused)) {
+               /* This possibly is a firmware bug and will result in
+-               * malfunction, memory leaks and/or stall of DMA functionality. */
+-              b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
+-                     "Expected %d, but got %d\n",
+-                     ring->index, firstused, slot);
+-              return;
++               * malfunction, memory leaks and/or stall of DMA functionality.
++               */
++              if (slot == next_slot(ring, next_slot(ring, firstused))) {
++                      /* If a single header/data pair was missed, skip over
++                       * the first two slots in an attempt to recover.
++                       */
++                      slot = firstused;
++                      skip = 2;
++                      if (!err_out1) {
++                              /* Report the error once. */
++                              b43dbg(dev->wl,
++                                     "Skip on DMA ring %d slot %d.\n",
++                                     ring->index, slot);
++                              err_out1 = 1;
++                      }
++              } else {
++                      /* More than a single header/data pair were missed.
++                       * Report this error once.
++                       */
++                      if (!err_out2)
++                              b43dbg(dev->wl,
++                                     "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
++                                     ring->index, firstused, slot);
++                      err_out2 = 1;
++                      return;
++              }
+       }
+       ops = ring->ops;
+@@ -1424,11 +1451,13 @@ void b43_dma_handle_txstatus(struct b43_
+                              slot, firstused, ring->index);
+                       break;
+               }
++
+               if (meta->skb) {
+                       struct b43_private_tx_info *priv_info =
+-                              b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
++                           b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+-                      unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
++                      unmap_descbuffer(ring, meta->dmaaddr,
++                                       meta->skb->len, 1);
+                       kfree(priv_info->bouncebuffer);
+                       priv_info->bouncebuffer = NULL;
+               } else {
+@@ -1440,8 +1469,9 @@ void b43_dma_handle_txstatus(struct b43_
+                       struct ieee80211_tx_info *info;
+                       if (unlikely(!meta->skb)) {
+-                              /* This is a scatter-gather fragment of a frame, so
+-                               * the skb pointer must not be NULL. */
++                              /* This is a scatter-gather fragment of a frame,
++                               * so the skb pointer must not be NULL.
++                               */
+                               b43dbg(dev->wl, "TX status unexpected NULL skb "
+                                      "at slot %d (first=%d) on ring %d\n",
+                                      slot, firstused, ring->index);
+@@ -1452,9 +1482,18 @@ void b43_dma_handle_txstatus(struct b43_
+                       /*
+                        * Call back to inform the ieee80211 subsystem about
+-                       * the status of the transmission.
++                       * the status of the transmission. When skipping over
++                       * a missed TX status report, use a status structure
++                       * filled with zeros to indicate that the frame was not
++                       * sent (frame_count 0) and not acknowledged
+                        */
+-                      frame_succeed = b43_fill_txstatus_report(dev, info, status);
++                      if (unlikely(skip))
++                              txstat = &fake;
++                      else
++                              txstat = status;
++
++                      frame_succeed = b43_fill_txstatus_report(dev, info,
++                                                               txstat);
+ #ifdef CONFIG_B43_DEBUG
+                       if (frame_succeed)
+                               ring->nr_succeed_tx_packets++;
+@@ -1482,12 +1521,14 @@ void b43_dma_handle_txstatus(struct b43_
+               /* Everything unmapped and free'd. So it's not used anymore. */
+               ring->used_slots--;
+-              if (meta->is_last_fragment) {
++              if (meta->is_last_fragment && !skip) {
+                       /* This is the last scatter-gather
+                        * fragment of the frame. We are done. */
+                       break;
+               }
+               slot = next_slot(ring, slot);
++              if (skip > 0)
++                      --skip;
+       }
+       if (ring->stopped) {
+               B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
index 24f41db5d8bb67507dd69c4730be6dc5aac59747..74d461aef5e9dbec89ceaebf998e4c77a2647f21 100644 (file)
@@ -5,3 +5,4 @@ bluetooth-add-support-for-dell_2.patch
 staging-comedi-s626-fix-continuous-acquisition.patch
 sysfs-fix-race-between-readdir-and-lseek.patch
 sysfs-handle-failure-path-correctly-for-readdir.patch
+b43-a-fix-for-dma-transmission-sequence-errors.patch