From 03d2d499ef7bdc31307112debbcc02844a2a02f9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Apr 2013 14:21:47 -0700 Subject: [PATCH] 3.4-stable patches 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 --- ...for-dma-transmission-sequence-errors.patch | 155 ++++++++++++++++++ ...al-value-of-mind-in-rssi-calibration.patch | 46 ++++++ ...-bits-for-offset-in-rssi-calibration.patch | 46 ++++++ ...-dma_ops-are-set-for-hotplug-devices.patch | 52 ++++++ queue-3.4/series | 5 + ...s-fix-race-between-readdir-and-lseek.patch | 2 +- ...gth-overflow-in-vpd-firmware-parsing.patch | 47 ++++++ 7 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 queue-3.4/b43-a-fix-for-dma-transmission-sequence-errors.patch create mode 100644 queue-3.4/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch create mode 100644 queue-3.4/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch create mode 100644 queue-3.4/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch create mode 100644 queue-3.4/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch 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 index 00000000000..a33a87eccfa --- /dev/null +++ b/queue-3.4/b43-a-fix-for-dma-transmission-sequence-errors.patch @@ -0,0 +1,155 @@ +From b251412db99ccd4495ce372fec7daee27bf06923 Mon Sep 17 00:00:00 2001 +From: "Iestyn C. Elfick" +Date: Wed, 20 Mar 2013 14:02:31 -0500 +Subject: b43: A fix for DMA transmission sequence errors + +From: "Iestyn C. Elfick" + +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 +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..69d673cea1b --- /dev/null +++ b/queue-3.4/b43-n-phy-increase-initial-value-of-mind-in-rssi-calibration.patch @@ -0,0 +1,46 @@ +From e67dd874e60529dbd2e8232babb1e23479ba2ffa Mon Sep 17 00:00:00 2001 +From: Rafał Miłecki +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 + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..6dbc93fc06d --- /dev/null +++ b/queue-3.4/b43-n-phy-use-more-bits-for-offset-in-rssi-calibration.patch @@ -0,0 +1,46 @@ +From 2e1253d640eb7f8707d2591c93097c1e9f9c71d5 Mon Sep 17 00:00:00 2001 +From: Rafał Miłecki +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 + +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 +Signed-off-by: John W. Linville + +--- + 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 index 00000000000..76cf442ac44 --- /dev/null +++ b/queue-3.4/iommu-amd-make-sure-dma_ops-are-set-for-hotplug-devices.patch @@ -0,0 +1,52 @@ +From c2a2876e863356b092967ea62bebdb4dd663af80 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 26 Mar 2013 22:48:23 +0100 +Subject: iommu/amd: Make sure dma_ops are set for hotplug devices + +From: Joerg Roedel + +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 +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-3.4/series b/queue-3.4/series index 2bbdac2b3db..06a1371c429 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -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 diff --git a/queue-3.4/sysfs-fix-race-between-readdir-and-lseek.patch b/queue-3.4/sysfs-fix-race-between-readdir-and-lseek.patch index 4e38d99a95c..7214c3a3995 100644 --- a/queue-3.4/sysfs-fix-race-between-readdir-and-lseek.patch +++ b/queue-3.4/sysfs-fix-race-between-readdir-and-lseek.patch @@ -32,7 +32,7 @@ Signed-off-by: Greg Kroah-Hartman +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 index 00000000000..9c6811bad0d --- /dev/null +++ b/queue-3.4/tg3-fix-length-overflow-in-vpd-firmware-parsing.patch @@ -0,0 +1,47 @@ +From 715230a44310a8cf66fbfb5a46f9a62a9b2de424 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 27 Mar 2013 06:40:50 +0000 +Subject: tg3: fix length overflow in VPD firmware parsing + +From: Kees Cook + +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 +Reported-by: Oded Horovitz +Reported-by: Brad Spengler +Cc: Matt Carlson +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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: -- 2.47.3