]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.8-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:21:38 +0000 (14:21 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2013 21:21:38 +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
iwlwifi-fix-length-check-in-multi-tb-hcmd.patch
mac80211-always-synchronize_net-during-station-removal.patch
tg3-fix-length-overflow-in-vpd-firmware-parsing.patch

queue-3.8/b43-a-fix-for-dma-transmission-sequence-errors.patch [new file with mode: 0644]
queue-3.8/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch [new file with mode: 0644]
queue-3.8/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch [new file with mode: 0644]
queue-3.8/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch [new file with mode: 0644]
queue-3.8/iwlwifi-fix-length-check-in-multi-tb-hcmd.patch [new file with mode: 0644]
queue-3.8/mac80211-always-synchronize_net-during-station-removal.patch [new file with mode: 0644]
queue-3.8/series
queue-3.8/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch [new file with mode: 0644]

diff --git a/queue-3.8/b43-a-fix-for-dma-transmission-sequence-errors.patch b/queue-3.8/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.8/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch b/queue-3.8/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch
new file mode 100644 (file)
index 0000000..01c447a
--- /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
+@@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struc
+               }
+               for (i = 0; i < 4; i += 2) {
+                       s32 curr;
+-                      s32 mind = 40;
++                      s32 mind = 0x100000;
+                       s32 minpoll = 249;
+                       u8 minvcm = 0;
+                       if (2 * core != i)
+@@ -1799,7 +1799,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.8/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch b/queue-3.8/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch
new file mode 100644 (file)
index 0000000..1839912
--- /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
+@@ -1564,7 +1564,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] = { };
+@@ -1732,7 +1732,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.8/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch b/queue-3.8/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch
new file mode 100644 (file)
index 0000000..7d2eb62
--- /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
+@@ -2466,18 +2466,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;
diff --git a/queue-3.8/iwlwifi-fix-length-check-in-multi-tb-hcmd.patch b/queue-3.8/iwlwifi-fix-length-check-in-multi-tb-hcmd.patch
new file mode 100644 (file)
index 0000000..f852884
--- /dev/null
@@ -0,0 +1,32 @@
+From cc904c7188c29847817f35e6966fec3014c7479b Mon Sep 17 00:00:00 2001
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Date: Thu, 14 Mar 2013 08:35:06 +0200
+Subject: iwlwifi: fix length check in multi-TB HCMD
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+commit cc904c7188c29847817f35e6966fec3014c7479b upstream.
+
+As reported by Ben Hutchings, there was a harmless issue in
+the checks being done on the lengths of the TBs while
+building the TFD for a multi-TB host command.
+
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/iwlwifi/pcie/tx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
++++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
+@@ -1242,7 +1242,7 @@ static int iwl_pcie_enqueue_hcmd(struct
+       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               int copy = 0;
+-              if (!cmd->len)
++              if (!cmd->len[i])
+                       continue;
+               /* need at least IWL_HCMD_MIN_COPY_SIZE copied */
diff --git a/queue-3.8/mac80211-always-synchronize_net-during-station-removal.patch b/queue-3.8/mac80211-always-synchronize_net-during-station-removal.patch
new file mode 100644 (file)
index 0000000..4e9ef2e
--- /dev/null
@@ -0,0 +1,58 @@
+From 27a737ff7cb062fb9cbceba9b44d60aa74862bfa Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Wed, 6 Mar 2013 23:17:08 +0100
+Subject: mac80211: always synchronize_net() during station removal
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 27a737ff7cb062fb9cbceba9b44d60aa74862bfa upstream.
+
+If there are keys left during station removal, then a
+synchronize_net() will be done (for each key, I have a
+patch to address this for 3.10), otherwise it won't be
+done at all which causes issues because the station
+could be used for TX while it's being removed from the
+driver -- that might confuse the driver.
+
+Fix this by always doing synchronize_net() if no key
+was present any more.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/sta_info.c |   12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -756,6 +756,7 @@ int __must_check __sta_info_destroy(stru
+       struct ieee80211_local *local;
+       struct ieee80211_sub_if_data *sdata;
+       int ret, i;
++      bool have_key = false;
+       might_sleep();
+@@ -783,12 +784,19 @@ int __must_check __sta_info_destroy(stru
+       list_del_rcu(&sta->list);
+       mutex_lock(&local->key_mtx);
+-      for (i = 0; i < NUM_DEFAULT_KEYS; i++)
++      for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+               __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
+-      if (sta->ptk)
++              have_key = true;
++      }
++      if (sta->ptk) {
+               __ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
++              have_key = true;
++      }
+       mutex_unlock(&local->key_mtx);
++      if (!have_key)
++              synchronize_net();
++
+       sta->dead = true;
+       local->num_sta--;
index 0d0e5f5ae7c050e34302e2d15162460fd388962f..92796c6dd14fcf7ca9fd36f6a2718c6147408bb4 100644 (file)
@@ -16,3 +16,10 @@ hid-usbhid-quirk-for-realtek-multi-card-reader.patch
 hid-usbhid-quirk-for-msi-gx680r-led-panel.patch
 hid-usbhid-fix-build-problem.patch
 rtlwifi-usb-add-missing-freeing-of-skbuff.patch
+iwlwifi-fix-length-check-in-multi-tb-hcmd.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
+mac80211-always-synchronize_net-during-station-removal.patch
+iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch
diff --git a/queue-3.8/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch b/queue-3.8/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch
new file mode 100644 (file)
index 0000000..6e96127
--- /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
+@@ -14403,8 +14403,11 @@ static void tg3_read_vpd(struct tg3 *tp)
+               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: