]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:21:47 +0000 (14:21 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:21:47 +0000 (14:21 -0700)
added patches:
b43-a-fix-for-dma-transmission-sequence-errors.patch
b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch
b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch
iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch
tg3-fix-length-overflow-in-vpd-firmware-parsing.patch

queue-3.4/b43-a-fix-for-dma-transmission-sequence-errors.patch [new file with mode: 0644]
queue-3.4/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch [new file with mode: 0644]
queue-3.4/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch [new file with mode: 0644]
queue-3.4/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/sysfs-fix-race-between-readdir-and-lseek.patch
queue-3.4/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch [new file with mode: 0644]

diff --git a/queue-3.4/b43-a-fix-for-dma-transmission-sequence-errors.patch b/queue-3.4/b43-a-fix-for-dma-transmission-sequence-errors.patch
new file mode 100644 (file)
index 0000000..a33a87e
--- /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
+@@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_
+       const struct b43_dma_ops *ops;
+       struct b43_dmaring *ring;
+       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))
+@@ -1501,13 +1505,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;
+@@ -1522,11 +1549,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 {
+@@ -1538,8 +1567,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);
+@@ -1550,9 +1580,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++;
+@@ -1580,12 +1619,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);
diff --git a/queue-3.4/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch b/queue-3.4/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch
new file mode 100644 (file)
index 0000000..69d673c
--- /dev/null
@@ -0,0 +1,46 @@
+From e67dd874e60529dbd2e8232babb1e23479ba2ffa Mon Sep 17 00:00:00 2001
+From: Rafał Miłecki <zajec5@gmail.com>
+Date: Tue, 19 Mar 2013 07:52:48 +0100
+Subject: b43: N-PHY: increase initial value of "mind" in RSSI calibration
+
+From: Rafał Miłecki <zajec5@gmail.com>
+
+commit e67dd874e60529dbd2e8232babb1e23479ba2ffa upstream.
+
+We're using "mind" variable to find the VCM that got the best polling
+results. For each VCM we calculte "currd" which is compared to the
+"mind". For PHY rev3+ "currd" gets values around 14k-40k. Looking for a
+value smaller than 40 makes no sense, so increase the initial value.
+
+This fixes a regression introduced in 3.4 by commit:
+e0c9a0219a8f542e3946fe972a68aacf8c3f906c
+(my BCM4322 performance dropped from 18,4Mb/s to 9,26Mb/s)
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/b43/phy_n.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/b43/phy_n.c
++++ b/drivers/net/wireless/b43/phy_n.c
+@@ -1371,7 +1371,7 @@ static void b43_nphy_rev3_rssi_cal(struc
+               }
+               for (i = 0; i < 4; i++) {
+                       s32 curr;
+-                      s32 mind = 40;
++                      s32 mind = 0x100000;
+                       s32 minpoll = 249;
+                       u8 minvcm = 0;
+                       if (2 * core != i)
+@@ -1554,7 +1554,7 @@ static void b43_nphy_rev2_rssi_cal(struc
+       }
+       for (i = 0; i < 4; i++) {
+-              s32 mind = 40;
++              s32 mind = 0x100000;
+               u8 minvcm = 0;
+               s32 minpoll = 249;
+               s32 curr;
diff --git a/queue-3.4/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch b/queue-3.4/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch
new file mode 100644 (file)
index 0000000..6dbc93f
--- /dev/null
@@ -0,0 +1,46 @@
+From 2e1253d640eb7f8707d2591c93097c1e9f9c71d5 Mon Sep 17 00:00:00 2001
+From: Rafał Miłecki <zajec5@gmail.com>
+Date: Wed, 27 Mar 2013 08:37:08 +0100
+Subject: b43: N-PHY: use more bits for offset in RSSI calibration
+
+From: Rafał Miłecki <zajec5@gmail.com>
+
+commit 2e1253d640eb7f8707d2591c93097c1e9f9c71d5 upstream.
+
+When calculating "offset" for final RSSI calibration we're using numbers
+bigger than s8 can hold. We have for example:
+offset[j] = 232 - poll_results[j];
+formula. If poll_results[j] is small enough (it usually is) we treat
+number's bit as a sign bit. For example 232 - 1 becomes:
+0xE8 - 0x1 = 0xE7, which is not 231 but -25.
+
+This code was introduced in e0c9a0219a8f542e3946fe972a68aacf8c3f906c
+and caused stability regression on some cards, for ex. BCM4322.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+
+---
+ drivers/net/wireless/b43/phy_n.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/b43/phy_n.c
++++ b/drivers/net/wireless/b43/phy_n.c
+@@ -1320,7 +1320,7 @@ static void b43_nphy_rev3_rssi_cal(struc
+       u16 clip_off[2] = { 0xFFFF, 0xFFFF };
+       u8 vcm_final = 0;
+-      s8 offset[4];
++      s32 offset[4];
+       s32 results[8][4] = { };
+       s32 results_min[4] = { };
+       s32 poll_results[4] = { };
+@@ -1487,7 +1487,7 @@ static void b43_nphy_rev2_rssi_cal(struc
+       u8 regs_save_radio[2];
+       u16 regs_save_phy[2];
+-      s8 offset[4];
++      s32 offset[4];
+       u8 core;
+       u8 rail;
diff --git a/queue-3.4/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch b/queue-3.4/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch
new file mode 100644 (file)
index 0000000..76cf442
--- /dev/null
@@ -0,0 +1,52 @@
+From c2a2876e863356b092967ea62bebdb4dd663af80 Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <joro@8bytes.org>
+Date: Tue, 26 Mar 2013 22:48:23 +0100
+Subject: iommu/amd: Make sure dma_ops are set for hotplug devices
+
+From: Joerg Roedel <joro@8bytes.org>
+
+commit c2a2876e863356b092967ea62bebdb4dd663af80 upstream.
+
+There is a bug introduced with commit 27c2127 that causes
+devices which are hot unplugged and then hot-replugged to
+not have per-device dma_ops set. This causes these devices
+to not function correctly. Fixed with this patch.
+
+Reported-by: Andreas Degert <andreas.degert@googlemail.com>
+Signed-off-by: Joerg Roedel <joro@8bytes.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/amd_iommu.c |   20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+--- a/drivers/iommu/amd_iommu.c
++++ b/drivers/iommu/amd_iommu.c
+@@ -2270,18 +2270,16 @@ static int device_change_notifier(struct
+               /* allocate a protection domain if a device is added */
+               dma_domain = find_protection_domain(devid);
+-              if (dma_domain)
+-                      goto out;
+-              dma_domain = dma_ops_domain_alloc();
+-              if (!dma_domain)
+-                      goto out;
+-              dma_domain->target_dev = devid;
++              if (!dma_domain) {
++                      dma_domain = dma_ops_domain_alloc();
++                      if (!dma_domain)
++                              goto out;
++                      dma_domain->target_dev = devid;
+-              spin_lock_irqsave(&iommu_pd_list_lock, flags);
+-              list_add_tail(&dma_domain->list, &iommu_pd_list);
+-              spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+-
+-              dev_data = get_dev_data(dev);
++                      spin_lock_irqsave(&iommu_pd_list_lock, flags);
++                      list_add_tail(&dma_domain->list, &iommu_pd_list);
++                      spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
++              }
+               dev->archdata.dma_ops = &amd_iommu_dma_ops;
index 2bbdac2b3dbd3ab46e9e44cae8244fbdefbf7b92..06a1371c429feae1929f31898a9dffd3ef165217 100644 (file)
@@ -5,6 +5,11 @@ bluetooth-add-support-for-dell.patch
 bluetooth-add-support-for-dell_2.patch
 staging-comedi-s626-fix-continuous-acquisition.patch
 sysfs-fix-race-between-readdir-and-lseek.patch
+b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch
+b43-a-fix-for-dma-transmission-sequence-errors.patch
+b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch
+tg3-fix-length-overflow-in-vpd-firmware-parsing.patch
+iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch
 sysfs-handle-failure-path-correctly-for-readdir.patch
 can-sja1000-fix-define-conflict-on-sh.patch
 ath9k_hw-revert-chainmask-to-user-configuration-after-calibration.patch
index 4e38d99a95c54fcaa665745cfa07a057875b5049..7214c3a399533177f3ac4ece6ae3c47334ffc5d5 100644 (file)
@@ -32,7 +32,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  
 +static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence)
 +{
-+      struct inode *inode = file_inode(file);
++      struct inode *inode = file->f_path.dentry->d_inode;
 +      loff_t ret;
 +
 +      mutex_lock(&inode->i_mutex);
diff --git a/queue-3.4/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch b/queue-3.4/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch
new file mode 100644 (file)
index 0000000..9c6811b
--- /dev/null
@@ -0,0 +1,47 @@
+From 715230a44310a8cf66fbfb5a46f9a62a9b2de424 Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 27 Mar 2013 06:40:50 +0000
+Subject: tg3: fix length overflow in VPD firmware parsing
+
+From: Kees Cook <keescook@chromium.org>
+
+commit 715230a44310a8cf66fbfb5a46f9a62a9b2de424 upstream.
+
+Commit 184b89044fb6e2a74611dafa69b1dce0d98612c6 ("tg3: Use VPD fw version
+when present") introduced VPD parsing that contained a potential length
+overflow.
+
+Limit the hardware's reported firmware string length (max 255 bytes) to
+stay inside the driver's firmware string length (32 bytes). On overflow,
+truncate the formatted firmware string instead of potentially overwriting
+portions of the tg3 struct.
+
+http://cansecwest.com/slides/2013/PrivateCore%20CSW%202013.pdf
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Reported-by: Oded Horovitz <oded@privatecore.com>
+Reported-by: Brad Spengler <spender@grsecurity.net>
+Cc: Matt Carlson <mcarlson@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/ethernet/broadcom/tg3.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/tg3.c
++++ b/drivers/net/ethernet/broadcom/tg3.c
+@@ -13590,8 +13590,11 @@ static void __devinit tg3_read_vpd(struc
+               if (j + len > block_end)
+                       goto partno;
+-              memcpy(tp->fw_ver, &vpd_data[j], len);
+-              strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
++              if (len >= sizeof(tp->fw_ver))
++                      len = sizeof(tp->fw_ver) - 1;
++              memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
++              snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len,
++                       &vpd_data[j]);
+       }
+ partno: