From: Greg Kroah-Hartman Date: Tue, 10 Jul 2012 23:46:01 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.0.37~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f1ecbb92e1988c8884ca0a3f6f6e45d69c9e6848;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: asoc-tlv320aic3x-fix-codec-pll-configure-bug.patch asoc-wm2200-add-missing-bclk-rate.patch ath9k-enable-serialize_regmode-for-non-pcie-ar9287.patch ath9k-fix-a-tx-rate-duration-calculation-bug.patch ath9k-fix-a-warning-on-suspend-resume-with-ibss.patch ath9k-fix-dynamic-wep-related-regression.patch ath9k-fix-invalid-pointer-access-in-the-tx-path.patch ath9k-fix-softlockup-in-ar9485.patch ath9k_htc-configure-bssid-on-assoc-ibss-change.patch ath9k_hw-avoid-possible-infinite-loop-in.patch cifs-fix-parsing-of-password-mount-option.patch cifs-when-server-doesn-t-set-cap_large_read_x-cap-default-rsize-at-maxbuffersize.patch iommu-amd-fix-missing-iommu_shutdown-initialization-in-passthrough-mode.patch iommu-amd-initialize-dma_ops-for-hotplug-and-sriov-devices.patch iommu-tegra-smmu-fix-unsleepable-memory-allocation.patch rpmsg-avoid-premature-deallocation-of-endpoints.patch rpmsg-make-sure-inflight-messages-don-t-invoke-just-removed-callbacks.patch --- diff --git a/queue-3.4/asoc-tlv320aic3x-fix-codec-pll-configure-bug.patch b/queue-3.4/asoc-tlv320aic3x-fix-codec-pll-configure-bug.patch new file mode 100644 index 00000000000..1a10064a166 --- /dev/null +++ b/queue-3.4/asoc-tlv320aic3x-fix-codec-pll-configure-bug.patch @@ -0,0 +1,58 @@ +From c9fe573a6584034670c1a55ee8162d623519cbbf Mon Sep 17 00:00:00 2001 +From: "Hebbar, Gururaja" +Date: Tue, 26 Jun 2012 19:25:11 +0530 +Subject: ASoC: tlv320aic3x: Fix codec pll configure bug + +From: "Hebbar, Gururaja" + +commit c9fe573a6584034670c1a55ee8162d623519cbbf upstream. + +In sound/soc/codecs/tlv320aic3x.c + + data = snd_soc_read(codec, AIC3X_PLL_PROGA_REG); + snd_soc_write(codec, AIC3X_PLL_PROGA_REG, + data | (pll_p << PLLP_SHIFT)); + +In the above code, pll-p value is OR'ed with previous value without +clearing it. Bug is not seen if pll-p value doesn't change across +Sampling frequency. + +However on some platforms (like AM335x EVM-SK), pll-p may have different +values across different sampling frequencies. In such case, above code +configures the pll with a wrong value. +Because of this bug, when a audio stream is played with pll value +different from previous stream, audio is heard as differently(like its +stretched). + +Signed-off-by: Hebbar, Gururaja +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/tlv320aic3x.c | 4 +--- + sound/soc/codecs/tlv320aic3x.h | 1 + + 2 files changed, 2 insertions(+), 3 deletions(-) + +--- a/sound/soc/codecs/tlv320aic3x.c ++++ b/sound/soc/codecs/tlv320aic3x.c +@@ -936,9 +936,7 @@ static int aic3x_hw_params(struct snd_pc + } + + found: +- data = snd_soc_read(codec, AIC3X_PLL_PROGA_REG); +- snd_soc_write(codec, AIC3X_PLL_PROGA_REG, +- data | (pll_p << PLLP_SHIFT)); ++ snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLLP_MASK, pll_p); + snd_soc_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, + pll_r << PLLR_SHIFT); + snd_soc_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT); +--- a/sound/soc/codecs/tlv320aic3x.h ++++ b/sound/soc/codecs/tlv320aic3x.h +@@ -166,6 +166,7 @@ + + /* PLL registers bitfields */ + #define PLLP_SHIFT 0 ++#define PLLP_MASK 7 + #define PLLQ_SHIFT 3 + #define PLLR_SHIFT 0 + #define PLLJ_SHIFT 2 diff --git a/queue-3.4/asoc-wm2200-add-missing-bclk-rate.patch b/queue-3.4/asoc-wm2200-add-missing-bclk-rate.patch new file mode 100644 index 00000000000..9dc6a1e68c1 --- /dev/null +++ b/queue-3.4/asoc-wm2200-add-missing-bclk-rate.patch @@ -0,0 +1,29 @@ +From b0dfa4541e48ac4cc5f017285432c89923ad0f58 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Wed, 20 Jun 2012 14:16:57 +0100 +Subject: ASoC: wm2200: Add missing BCLK rate + +From: Mark Brown + +commit b0dfa4541e48ac4cc5f017285432c89923ad0f58 upstream. + +Without this very high BCLKs will be configured incorrectly. + +Reported-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm2200.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/codecs/wm2200.c ++++ b/sound/soc/codecs/wm2200.c +@@ -1491,6 +1491,7 @@ static int wm2200_bclk_rates_dat[WM2200_ + + static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = { + 5644800, ++ 3763200, + 2882400, + 1881600, + 1411200, diff --git a/queue-3.4/ath9k-enable-serialize_regmode-for-non-pcie-ar9287.patch b/queue-3.4/ath9k-enable-serialize_regmode-for-non-pcie-ar9287.patch new file mode 100644 index 00000000000..49d5f20cb66 --- /dev/null +++ b/queue-3.4/ath9k-enable-serialize_regmode-for-non-pcie-ar9287.patch @@ -0,0 +1,32 @@ +From 7508b657967cf664b5aa0f6367d05016e7e3bc2a Mon Sep 17 00:00:00 2001 +From: Panayiotis Karabassis +Date: Tue, 26 Jun 2012 23:37:17 +0300 +Subject: ath9k: enable serialize_regmode for non-PCIE AR9287 + +From: Panayiotis Karabassis + +commit 7508b657967cf664b5aa0f6367d05016e7e3bc2a upstream. + +https://bugzilla.kernel.org/show_bug.cgi?id=42903 + +Based on the work of + +Signed-off-by: Panayiotis Karabassis +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -558,7 +558,7 @@ static int __ath9k_hw_init(struct ath_hw + + if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) { + if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || +- ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) && ++ ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) && + !ah->is_pciexpress)) { + ah->config.serialize_regmode = + SER_REG_MODE_ON; diff --git a/queue-3.4/ath9k-fix-a-tx-rate-duration-calculation-bug.patch b/queue-3.4/ath9k-fix-a-tx-rate-duration-calculation-bug.patch new file mode 100644 index 00000000000..d197f9c25d9 --- /dev/null +++ b/queue-3.4/ath9k-fix-a-tx-rate-duration-calculation-bug.patch @@ -0,0 +1,39 @@ +From 76591bea9714a58d8924154068c78d702eb2cb17 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 15 Jun 2012 03:04:52 +0200 +Subject: ath9k: fix a tx rate duration calculation bug + +From: Felix Fietkau + +commit 76591bea9714a58d8924154068c78d702eb2cb17 upstream. + +The rate pointer variable for a rate series is used in a loop before it is +initialized. This went unnoticed because it was used earlier for the RTS/CTS +rate. This bug can lead to the wrong PHY type being passed to the +duration calculation function. + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/xmit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -1001,13 +1001,13 @@ static void ath_buf_set_rate(struct ath_ + } + + /* legacy rates */ ++ rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; + if ((tx_info->band == IEEE80211_BAND_2GHZ) && + !(rate->flags & IEEE80211_RATE_ERP_G)) + phy = WLAN_RC_PHY_CCK; + else + phy = WLAN_RC_PHY_OFDM; + +- rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; + info->rates[i].Rate = rate->hw_value; + if (rate->hw_value_short) { + if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) diff --git a/queue-3.4/ath9k-fix-a-warning-on-suspend-resume-with-ibss.patch b/queue-3.4/ath9k-fix-a-warning-on-suspend-resume-with-ibss.patch new file mode 100644 index 00000000000..7e206342b10 --- /dev/null +++ b/queue-3.4/ath9k-fix-a-warning-on-suspend-resume-with-ibss.patch @@ -0,0 +1,72 @@ +From 2031b4c2b4904f7448ab9e4bc6b9bf16e32709f5 Mon Sep 17 00:00:00 2001 +From: Mohammed Shafi Shajakhan +Date: Wed, 6 Jun 2012 10:33:10 +0530 +Subject: ath9k: Fix a WARNING on suspend/resume with IBSS + +From: Mohammed Shafi Shajakhan + +commit 2031b4c2b4904f7448ab9e4bc6b9bf16e32709f5 upstream. + +this patch is dependent on the patch "cfg80211: fix interface +combinations" + +In ath9k currently we have ADHOC interface as a single incompatible +interface. when drv_add_interface is called during resume we got to +consider number of vifs already present in addition to checking the +drivers 'opmode' information about ADHOC. we incorrectly assume +an ADHOC interface is already present. Then we may miss some driver +specific data for the ADHOC interface after resume. + +The above mentioned checks can be removed from the driver, +as the patch 'cfg80211: fix interface combinations' ensures that +if an interface type is not advertised by the driver in any of the +interface combinations(via ieee80211_iface_combination) then it shall +be treated as a single incompatible interface. Fixes the following +warning on suspend/resume with ibss interface. + + ath: phy0: Cannot create ADHOC interface when other + interfaces already exist. + WARNING: at net/mac80211/driver-ops.h:12 + ieee80211_reconfig+0x1882/0x1ca0 [mac80211]() + Hardware name: 2842RK1 + wlan2: Failed check-sdata-in-driver check, flags: 0x0 + + Call Trace: + [] warn_slowpath_common+0x72/0xa0 + [] ? ieee80211_reconfig+0x1882/0x1ca0 + [mac80211] + [] ? ieee80211_reconfig+0x1882/0x1ca0 + [mac80211] + [] warn_slowpath_fmt+0x33/0x40 + [] ieee80211_reconfig+0x1882/0x1ca0 [mac80211] + [] ? mutex_lock_nested+0x23a/0x2f0 + [] ieee80211_resume+0x27/0x70 [mac80211] + [] wiphy_resume+0x8f/0xa0 [cfg80211] + +Cc: Rajkumar Manoharan +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/main.c | 9 --------- + 1 file changed, 9 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -1419,15 +1419,6 @@ static int ath9k_add_interface(struct ie + } + } + +- if ((ah->opmode == NL80211_IFTYPE_ADHOC) || +- ((vif->type == NL80211_IFTYPE_ADHOC) && +- sc->nvifs > 0)) { +- ath_err(common, "Cannot create ADHOC interface when other" +- " interfaces already exist.\n"); +- ret = -EINVAL; +- goto out; +- } +- + ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); + + sc->nvifs++; diff --git a/queue-3.4/ath9k-fix-dynamic-wep-related-regression.patch b/queue-3.4/ath9k-fix-dynamic-wep-related-regression.patch new file mode 100644 index 00000000000..d929e228379 --- /dev/null +++ b/queue-3.4/ath9k-fix-dynamic-wep-related-regression.patch @@ -0,0 +1,74 @@ +From bed3d9c0b71f9afbfec905cb6db3b9f16be29d4d Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 23 Jun 2012 19:23:31 +0200 +Subject: ath9k: fix dynamic WEP related regression + +From: Felix Fietkau + +commit bed3d9c0b71f9afbfec905cb6db3b9f16be29d4d upstream. + +commit 7a532fe7131216a02c81a6c1b1f8632da1195a58 +ath9k_hw: fix interpretation of the rx KeyMiss flag + +This commit used the rx key miss indication to detect packets that were +passed from the hardware without being decrypted, however it seems that +this bit is not only undefined in the static WEP case, but also for +dynamically allocated WEP keys. This caused a regression when using +WEP-LEAP. + +This patch fixes the regression by keeping track of which key indexes +refer to CCMP keys and only using the key miss indication for those. + +Reported-by: Stanislaw Gruszka +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath.h | 1 + + drivers/net/wireless/ath/ath9k/recv.c | 3 ++- + drivers/net/wireless/ath/key.c | 4 ++++ + 3 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath.h ++++ b/drivers/net/wireless/ath/ath.h +@@ -143,6 +143,7 @@ struct ath_common { + u32 keymax; + DECLARE_BITMAP(keymap, ATH_KEYMAX); + DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); ++ DECLARE_BITMAP(ccmp_keymap, ATH_KEYMAX); + enum ath_crypt_caps crypt_caps; + + unsigned int clockrate; +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -821,7 +821,8 @@ static bool ath9k_rx_accept(struct ath_c + * descriptor does contain a valid key index. This has been observed + * mostly with CCMP encryption. + */ +- if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) ++ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID || ++ !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) + rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; + + if (!rx_stats->rs_datalen) +--- a/drivers/net/wireless/ath/key.c ++++ b/drivers/net/wireless/ath/key.c +@@ -556,6 +556,9 @@ int ath_key_config(struct ath_common *co + return -EIO; + + set_bit(idx, common->keymap); ++ if (key->cipher == WLAN_CIPHER_SUITE_CCMP) ++ set_bit(idx, common->ccmp_keymap); ++ + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { + set_bit(idx + 64, common->keymap); + set_bit(idx, common->tkip_keymap); +@@ -582,6 +585,7 @@ void ath_key_delete(struct ath_common *c + return; + + clear_bit(key->hw_key_idx, common->keymap); ++ clear_bit(key->hw_key_idx, common->ccmp_keymap); + if (key->cipher != WLAN_CIPHER_SUITE_TKIP) + return; + diff --git a/queue-3.4/ath9k-fix-invalid-pointer-access-in-the-tx-path.patch b/queue-3.4/ath9k-fix-invalid-pointer-access-in-the-tx-path.patch new file mode 100644 index 00000000000..ad15949d829 --- /dev/null +++ b/queue-3.4/ath9k-fix-invalid-pointer-access-in-the-tx-path.patch @@ -0,0 +1,104 @@ +From 80b08a8d8829a58b5db14b1417151094cc28face Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Fri, 15 Jun 2012 03:04:53 +0200 +Subject: ath9k: fix invalid pointer access in the tx path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Felix Fietkau + +commit 80b08a8d8829a58b5db14b1417151094cc28face upstream. + +After setup_frame_info has been called, only info->control.rates is still +valid, other control fields have been overwritten by the ath_frame_info +data. Move the access to info->control.vif for checking short preamble +to setup_frame_info before it gets overwritten. + +This regression was introduced in commit d47a61aa +"ath9k: Fix multi-VIF BSS handling" + +Signed-off-by: Felix Fietkau +Reported-by: Thomas Hühn +Acked-by: Sujith Manoharan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ath9k.h | 1 + + drivers/net/wireless/ath/ath9k/xmit.c | 29 +++++++++++++++++------------ + 2 files changed, 18 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -213,6 +213,7 @@ struct ath_frame_info { + enum ath9k_key_type keytype; + u8 keyix; + u8 retries; ++ u8 rtscts_rate; + }; + + struct ath_buf_state { +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -938,6 +938,7 @@ static void ath_buf_set_rate(struct ath_ + struct ieee80211_tx_rate *rates; + const struct ieee80211_rate *rate; + struct ieee80211_hdr *hdr; ++ struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); + int i; + u8 rix = 0; + +@@ -948,18 +949,7 @@ static void ath_buf_set_rate(struct ath_ + + /* set dur_update_en for l-sig computation except for PS-Poll frames */ + info->dur_update = !ieee80211_is_pspoll(hdr->frame_control); +- +- /* +- * We check if Short Preamble is needed for the CTS rate by +- * checking the BSS's global flag. +- * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. +- */ +- rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info); +- info->rtscts_rate = rate->hw_value; +- +- if (tx_info->control.vif && +- tx_info->control.vif->bss_conf.use_short_preamble) +- info->rtscts_rate |= rate->hw_value_short; ++ info->rtscts_rate = fi->rtscts_rate; + + for (i = 0; i < 4; i++) { + bool is_40, is_sgi, is_sp; +@@ -1776,10 +1766,22 @@ static void setup_frame_info(struct ieee + struct ieee80211_sta *sta = tx_info->control.sta; + struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ const struct ieee80211_rate *rate; + struct ath_frame_info *fi = get_frame_info(skb); + struct ath_node *an = NULL; + enum ath9k_key_type keytype; ++ bool short_preamble = false; ++ ++ /* ++ * We check if Short Preamble is needed for the CTS rate by ++ * checking the BSS's global flag. ++ * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. ++ */ ++ if (tx_info->control.vif && ++ tx_info->control.vif->bss_conf.use_short_preamble) ++ short_preamble = true; + ++ rate = ieee80211_get_rts_cts_rate(hw, tx_info); + keytype = ath9k_cmn_get_hw_crypto_keytype(skb); + + if (sta) +@@ -1794,6 +1796,9 @@ static void setup_frame_info(struct ieee + fi->keyix = ATH9K_TXKEYIX_INVALID; + fi->keytype = keytype; + fi->framelen = framelen; ++ fi->rtscts_rate = rate->hw_value; ++ if (short_preamble) ++ fi->rtscts_rate |= rate->hw_value_short; + } + + u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) diff --git a/queue-3.4/ath9k-fix-softlockup-in-ar9485.patch b/queue-3.4/ath9k-fix-softlockup-in-ar9485.patch new file mode 100644 index 00000000000..18217e39fac --- /dev/null +++ b/queue-3.4/ath9k-fix-softlockup-in-ar9485.patch @@ -0,0 +1,66 @@ +From bcb7ad7bcbef030e6ba71ede1f9866368aca7c99 Mon Sep 17 00:00:00 2001 +From: Mohammed Shafi Shajakhan +Date: Wed, 13 Jun 2012 21:28:09 +0530 +Subject: ath9k: Fix softlockup in AR9485 + +From: Mohammed Shafi Shajakhan + +commit bcb7ad7bcbef030e6ba71ede1f9866368aca7c99 upstream. + +steps to recreate: +load latest ath9k driver with AR9485 +stop the network-manager and wpa_supplicant +bring the interface up + + Call Trace: + [] ? ath_hw_check+0xe0/0xe0 [ath9k] + [] __const_udelay+0x28/0x30 + [] ar9003_get_pll_sqsum_dvc+0x4a/0x80 [ath9k_hw] + [] ath_hw_pll_work+0x5b/0xe0 [ath9k] + [] process_one_work+0x11e/0x470 + [] worker_thread+0x15f/0x360 + [] ? manage_workers+0x230/0x230 + [] kthread+0x93/0xa0 + [] kernel_thread_helper+0x4/0x10 + [] ? kthread_freezable_should_stop+0x70/0x70 + [] ? gs_change+0x13/0x13 + +ensure that the PLL-WAR for AR9485/AR9340 is executed only if the STA is +associated (or) IBSS/AP mode had started beaconing. Ideally this WAR +is needed to recover from some rare beacon stuck during stress testing. +Before the STA is associated/IBSS had started beaconing, PLL4(0x1618c) +always seem to have zero even though we had configured PLL3(0x16188) to +query about PLL's locking status. When we keep on polling infinitely PLL4's +8th bit(ie check for PLL locking measurements is done), machine hangs +due to softlockup. + +fixes https://bugzilla.redhat.com/show_bug.cgi?id=811142 + +Reported-by: Rolf Offermanns +Tested-by: Mohammed Shafi Shajakhan +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/main.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -960,6 +960,15 @@ void ath_hw_pll_work(struct work_struct + hw_pll_work.work); + u32 pll_sqsum; + ++ /* ++ * ensure that the PLL WAR is executed only ++ * after the STA is associated (or) if the ++ * beaconing had started in interfaces that ++ * uses beacons. ++ */ ++ if (!(sc->sc_flags & SC_OP_BEACONS)) ++ return; ++ + if (AR_SREV_9485(sc->sc_ah)) { + + ath9k_ps_wakeup(sc); diff --git a/queue-3.4/ath9k_htc-configure-bssid-on-assoc-ibss-change.patch b/queue-3.4/ath9k_htc-configure-bssid-on-assoc-ibss-change.patch new file mode 100644 index 00000000000..e822e6b0a7c --- /dev/null +++ b/queue-3.4/ath9k_htc-configure-bssid-on-assoc-ibss-change.patch @@ -0,0 +1,49 @@ +From 931cb03afed7b541392295f3afc4638da32f08a0 Mon Sep 17 00:00:00 2001 +From: Rajkumar Manoharan +Date: Wed, 20 Jun 2012 16:29:20 +0530 +Subject: ath9k_htc: configure bssid on ASSOC/IBSS change + +From: Rajkumar Manoharan + +commit 931cb03afed7b541392295f3afc4638da32f08a0 upstream. + +After the change "mac80211: remove spurious BSSID change flag", +BSS_CHANGED_BSSID will not be passed on association or IBSS +status changes. So it could be better to program bssid on ASSOC +or IBSS change notification. Not doing so, is affecting the +packet transmission. + +Reported-by: Michael Leun +Signed-off-by: Rajkumar Manoharan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +@@ -1496,6 +1496,7 @@ static void ath9k_htc_bss_info_changed(s + priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; + + if (priv->ah->opmode == NL80211_IFTYPE_STATION) { ++ ath9k_htc_choose_set_bssid(priv); + if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) + ath9k_htc_start_ani(priv); + else if (priv->num_sta_assoc_vif == 0) +@@ -1503,13 +1504,11 @@ static void ath9k_htc_bss_info_changed(s + } + } + +- if (changed & BSS_CHANGED_BSSID) { ++ if (changed & BSS_CHANGED_IBSS) { + if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { + common->curaid = bss_conf->aid; + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + ath9k_htc_set_bssid(priv); +- } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) { +- ath9k_htc_choose_set_bssid(priv); + } + } + diff --git a/queue-3.4/ath9k_hw-avoid-possible-infinite-loop-in.patch b/queue-3.4/ath9k_hw-avoid-possible-infinite-loop-in.patch new file mode 100644 index 00000000000..57c31673785 --- /dev/null +++ b/queue-3.4/ath9k_hw-avoid-possible-infinite-loop-in.patch @@ -0,0 +1,59 @@ +From f18e3c6b67f448ec47b3a5b242789bd3d5644879 Mon Sep 17 00:00:00 2001 +From: Mohammed Shafi Shajakhan +Date: Mon, 18 Jun 2012 13:13:30 +0530 +Subject: ath9k_hw: avoid possible infinite loop in + ar9003_get_pll_sqsum_dvc + +From: Mohammed Shafi Shajakhan + +commit f18e3c6b67f448ec47b3a5b242789bd3d5644879 upstream. + +"ath9k: Fix softlockup in AR9485" with commit id +64bc1239c790e051ff677e023435d770d2ffa174 fixed the reported +issue, yet its better to avoid the possible infinite loop +in ar9003_get_pll_sqsum_dvc by having a timeout as suggested +by ath9k maintainers. +http://www.spinics.net/lists/linux-wireless/msg92126.html. +Based on my testing PLL's locking measurement is done in +~200us (2 iterations). + +Cc: Rolf Offermanns +Cc: Sujith Manoharan +Cc: Senthil Balasubramanian +Signed-off-by: Mohammed Shafi Shajakhan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/hw.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -720,13 +720,25 @@ static void ath9k_hw_init_qos(struct ath + + u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) + { ++ struct ath_common *common = ath9k_hw_common(ah); ++ int i = 0; ++ + REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); + udelay(100); + REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); + +- while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) ++ while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) { ++ + udelay(100); + ++ if (WARN_ON_ONCE(i >= 100)) { ++ ath_err(common, "PLL4 meaurement not done\n"); ++ break; ++ } ++ ++ i++; ++ } ++ + return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; + } + EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); diff --git a/queue-3.4/cifs-fix-parsing-of-password-mount-option.patch b/queue-3.4/cifs-fix-parsing-of-password-mount-option.patch new file mode 100644 index 00000000000..1b2efff3f8b --- /dev/null +++ b/queue-3.4/cifs-fix-parsing-of-password-mount-option.patch @@ -0,0 +1,86 @@ +From e73f843a3235a19de38359c91586e9eadef12238 Mon Sep 17 00:00:00 2001 +From: Suresh Jayaraman +Date: Tue, 12 Jun 2012 07:15:50 +0530 +Subject: cifs: fix parsing of password mount option + +From: Suresh Jayaraman + +commit e73f843a3235a19de38359c91586e9eadef12238 upstream. + +The double delimiter check that allows a comma in the password parsing code is +unconditional. We set "tmp_end" to the end of the string and we continue to +check for double delimiter. In the case where the password doesn't contain a +comma we end up setting tmp_end to NULL and eventually setting "options" to +"end". This results in the premature termination of the options string and hence +the values of UNCip and UNC are being set to NULL. This results in mount failure +with "Connecting to DFS root not implemented yet" error. + +This error is usually not noticable as we have password as the last option in +the superblock mountdata. But when we call expand_dfs_referral() from +cifs_mount() and try to compose mount options for the submount, the resulting +mountdata will be of the form + + ",ver=1,user=foo,pass=bar,ip=x.x.x.x,unc=\\server\share" + +and hence results in the above error. This bug has been seen with older NAS +servers running Samba 3.0.24. + +Fix this by moving the double delimiter check inside the conditional loop. + +Changes since -v1 + + - removed the wrong strlen() micro optimization. + +Signed-off-by: Suresh Jayaraman +Acked-by: Sachin Prabhu +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1585,24 +1585,26 @@ cifs_parse_mount_options(const char *mou + * If yes, we have encountered a double deliminator + * reset the NULL character to the deliminator + */ +- if (tmp_end < end && tmp_end[1] == delim) ++ if (tmp_end < end && tmp_end[1] == delim) { + tmp_end[0] = delim; + +- /* Keep iterating until we get to a single deliminator +- * OR the end +- */ +- while ((tmp_end = strchr(tmp_end, delim)) != NULL && +- (tmp_end[1] == delim)) { +- tmp_end = (char *) &tmp_end[2]; +- } ++ /* Keep iterating until we get to a single ++ * deliminator OR the end ++ */ ++ while ((tmp_end = strchr(tmp_end, delim)) ++ != NULL && (tmp_end[1] == delim)) { ++ tmp_end = (char *) &tmp_end[2]; ++ } + +- /* Reset var options to point to next element */ +- if (tmp_end) { +- tmp_end[0] = '\0'; +- options = (char *) &tmp_end[1]; +- } else +- /* Reached the end of the mount option string */ +- options = end; ++ /* Reset var options to point to next element */ ++ if (tmp_end) { ++ tmp_end[0] = '\0'; ++ options = (char *) &tmp_end[1]; ++ } else ++ /* Reached the end of the mount option ++ * string */ ++ options = end; ++ } + + /* Now build new password string */ + temp_len = strlen(value); diff --git a/queue-3.4/cifs-when-server-doesn-t-set-cap_large_read_x-cap-default-rsize-at-maxbuffersize.patch b/queue-3.4/cifs-when-server-doesn-t-set-cap_large_read_x-cap-default-rsize-at-maxbuffersize.patch new file mode 100644 index 00000000000..0d4b93ec91e --- /dev/null +++ b/queue-3.4/cifs-when-server-doesn-t-set-cap_large_read_x-cap-default-rsize-at-maxbuffersize.patch @@ -0,0 +1,57 @@ +From ec01d738a1691dfc85b96b9f796020267a7be577 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Mon, 2 Jul 2012 07:24:25 -0400 +Subject: cifs: when server doesn't set CAP_LARGE_READ_X, cap default rsize at MaxBufferSize + +From: Jeff Layton + +commit ec01d738a1691dfc85b96b9f796020267a7be577 upstream. + +When the server doesn't advertise CAP_LARGE_READ_X, then MS-CIFS states +that you must cap the size of the read at the client's MaxBufferSize. +Unfortunately, testing with many older servers shows that they often +can't service a read larger than their own MaxBufferSize. + +Since we can't assume what the server will do in this situation, we must +be conservative here for the default. When the server can't do large +reads, then assume that it can't satisfy any read larger than its +MaxBufferSize either. + +Luckily almost all modern servers can do large reads, so this won't +affect them. This is really just for older win9x and OS/2 era servers. +Also, note that this patch just governs the default rsize. The admin can +always override this if he so chooses. + +Reported-by: David H. Durgee +Signed-off-by: Jeff Layton +Signed-off-by: Steven French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -3398,18 +3398,15 @@ cifs_negotiate_rsize(struct cifs_tcon *t + * MS-CIFS indicates that servers are only limited by the client's + * bufsize for reads, testing against win98se shows that it throws + * INVALID_PARAMETER errors if you try to request too large a read. ++ * OS/2 just sends back short reads. + * +- * If the server advertises a MaxBufferSize of less than one page, +- * assume that it also can't satisfy reads larger than that either. +- * +- * FIXME: Is there a better heuristic for this? ++ * If the server doesn't advertise CAP_LARGE_READ_X, then assume that ++ * it can't handle a read request larger than its MaxBufferSize either. + */ + if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP)) + defsize = CIFS_DEFAULT_IOSIZE; + else if (server->capabilities & CAP_LARGE_READ_X) + defsize = CIFS_DEFAULT_NON_POSIX_RSIZE; +- else if (server->maxBuf >= PAGE_CACHE_SIZE) +- defsize = CIFSMaxBufSize; + else + defsize = server->maxBuf - sizeof(READ_RSP); + diff --git a/queue-3.4/iommu-amd-fix-missing-iommu_shutdown-initialization-in-passthrough-mode.patch b/queue-3.4/iommu-amd-fix-missing-iommu_shutdown-initialization-in-passthrough-mode.patch new file mode 100644 index 00000000000..e3af57023a6 --- /dev/null +++ b/queue-3.4/iommu-amd-fix-missing-iommu_shutdown-initialization-in-passthrough-mode.patch @@ -0,0 +1,42 @@ +From f2f12b6fc032c7b1419fd6db84e2868b5f05a878 Mon Sep 17 00:00:00 2001 +From: Shuah Khan +Date: Wed, 6 Jun 2012 10:50:06 -0600 +Subject: iommu/amd: Fix missing iommu_shutdown initialization in passthrough mode + +From: Shuah Khan + +commit f2f12b6fc032c7b1419fd6db84e2868b5f05a878 upstream. + +The iommu_shutdown callback is not initialized when the AMD +IOMMU driver runs in passthrough mode. Fix that by moving +the callback initialization before the check for +passthrough mode. + +Signed-off-by: Shuah Khan +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/amd_iommu_init.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -1641,6 +1641,8 @@ static int __init amd_iommu_init(void) + + amd_iommu_init_api(); + ++ x86_platform.iommu_shutdown = disable_iommus; ++ + if (iommu_pass_through) + goto out; + +@@ -1649,8 +1651,6 @@ static int __init amd_iommu_init(void) + else + printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); + +- x86_platform.iommu_shutdown = disable_iommus; +- + out: + return ret; + diff --git a/queue-3.4/iommu-amd-initialize-dma_ops-for-hotplug-and-sriov-devices.patch b/queue-3.4/iommu-amd-initialize-dma_ops-for-hotplug-and-sriov-devices.patch new file mode 100644 index 00000000000..829b73e2f17 --- /dev/null +++ b/queue-3.4/iommu-amd-initialize-dma_ops-for-hotplug-and-sriov-devices.patch @@ -0,0 +1,49 @@ +From ac1534a55d1e87d59a21c09c570605933b551480 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Thu, 21 Jun 2012 14:52:40 +0200 +Subject: iommu/amd: Initialize dma_ops for hotplug and sriov devices + +From: Joerg Roedel + +commit ac1534a55d1e87d59a21c09c570605933b551480 upstream. + +When a device is added to the system at runtime the AMD +IOMMU driver initializes the necessary data structures to +handle translation for it. But it forgets to change the +per-device dma_ops to point to the AMD IOMMU driver. So +mapping actually never happens and all DMA accesses end in +an IO_PAGE_FAULT. Fix this. + +Reported-by: Stefan Assmann +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/amd_iommu.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -83,6 +83,8 @@ static struct iommu_ops amd_iommu_ops; + static ATOMIC_NOTIFIER_HEAD(ppr_notifier); + int amd_iommu_max_glx_val = -1; + ++static struct dma_map_ops amd_iommu_dma_ops; ++ + /* + * general struct to manage commands send to an IOMMU + */ +@@ -2267,6 +2269,13 @@ static int device_change_notifier(struct + list_add_tail(&dma_domain->list, &iommu_pd_list); + spin_unlock_irqrestore(&iommu_pd_list_lock, flags); + ++ dev_data = get_dev_data(dev); ++ ++ if (!dev_data->passthrough) ++ dev->archdata.dma_ops = &amd_iommu_dma_ops; ++ else ++ dev->archdata.dma_ops = &nommu_dma_ops; ++ + break; + case BUS_NOTIFY_DEL_DEVICE: + diff --git a/queue-3.4/iommu-tegra-smmu-fix-unsleepable-memory-allocation.patch b/queue-3.4/iommu-tegra-smmu-fix-unsleepable-memory-allocation.patch new file mode 100644 index 00000000000..5e7139426ce --- /dev/null +++ b/queue-3.4/iommu-tegra-smmu-fix-unsleepable-memory-allocation.patch @@ -0,0 +1,40 @@ +From 8f53dc724a83a0082184fa27df80c25c7df47340 Mon Sep 17 00:00:00 2001 +From: Hiroshi DOYU +Date: Wed, 27 Jun 2012 12:54:01 +0300 +Subject: iommu/tegra: smmu: Fix unsleepable memory allocation + +From: Hiroshi DOYU + +commit 8f53dc724a83a0082184fa27df80c25c7df47340 upstream. + +allo_pdir() is called in smmu_iommu_domain_init() with spin_lock +held. memory allocations in it have to be atomic/unsleepable. + +Signed-off-by: Hiroshi DOYU +Reported-by: Chris Wright +Acked-by: Chris Wright +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/tegra-smmu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/iommu/tegra-smmu.c ++++ b/drivers/iommu/tegra-smmu.c +@@ -550,13 +550,13 @@ static int alloc_pdir(struct smmu_as *as + return 0; + + as->pte_count = devm_kzalloc(smmu->dev, +- sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_KERNEL); ++ sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_ATOMIC); + if (!as->pte_count) { + dev_err(smmu->dev, + "failed to allocate smmu_device PTE cunters\n"); + return -ENOMEM; + } +- as->pdir_page = alloc_page(GFP_KERNEL | __GFP_DMA); ++ as->pdir_page = alloc_page(GFP_ATOMIC | __GFP_DMA); + if (!as->pdir_page) { + dev_err(smmu->dev, + "failed to allocate smmu_device page directory\n"); diff --git a/queue-3.4/rpmsg-avoid-premature-deallocation-of-endpoints.patch b/queue-3.4/rpmsg-avoid-premature-deallocation-of-endpoints.patch new file mode 100644 index 00000000000..ea5a034db38 --- /dev/null +++ b/queue-3.4/rpmsg-avoid-premature-deallocation-of-endpoints.patch @@ -0,0 +1,144 @@ +From 5a081caa0414b9bbb82c17ffab9d6fe66edbb72f Mon Sep 17 00:00:00 2001 +From: Ohad Ben-Cohen +Date: Wed, 6 Jun 2012 10:09:25 +0300 +Subject: rpmsg: avoid premature deallocation of endpoints + +From: Ohad Ben-Cohen + +commit 5a081caa0414b9bbb82c17ffab9d6fe66edbb72f upstream. + +When an inbound message arrives, the rpmsg core looks up its +associated endpoint and invokes the registered callback. + +If a message arrives while its endpoint is being removed (because +the rpmsg driver was removed, or a recovery of a remote processor +has kicked in) we must ensure atomicity, i.e.: + +- Either the ept is removed before it is found + +or + +- The ept is found but will not be freed until the callback returns + +This is achieved by maintaining a per-ept reference count, which, +when drops to zero, will trigger deallocation of the ept. + +With this in hand, it is now forbidden to directly deallocate +epts once they have been added to the endpoints idr. + +Reported-by: Fernando Guzman Lugo +Signed-off-by: Ohad Ben-Cohen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rpmsg/virtio_rpmsg_bus.c | 36 ++++++++++++++++++++++++++++++++++-- + include/linux/rpmsg.h | 3 +++ + 2 files changed, 37 insertions(+), 2 deletions(-) + +--- a/drivers/rpmsg/virtio_rpmsg_bus.c ++++ b/drivers/rpmsg/virtio_rpmsg_bus.c +@@ -188,6 +188,26 @@ static int rpmsg_uevent(struct device *d + rpdev->id.name); + } + ++/** ++ * __ept_release() - deallocate an rpmsg endpoint ++ * @kref: the ept's reference count ++ * ++ * This function deallocates an ept, and is invoked when its @kref refcount ++ * drops to zero. ++ * ++ * Never invoke this function directly! ++ */ ++static void __ept_release(struct kref *kref) ++{ ++ struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint, ++ refcount); ++ /* ++ * At this point no one holds a reference to ept anymore, ++ * so we can directly free it ++ */ ++ kfree(ept); ++} ++ + /* for more info, see below documentation of rpmsg_create_ept() */ + static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, + struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb, +@@ -206,6 +226,8 @@ static struct rpmsg_endpoint *__rpmsg_cr + return NULL; + } + ++ kref_init(&ept->refcount); ++ + ept->rpdev = rpdev; + ept->cb = cb; + ept->priv = priv; +@@ -238,7 +260,7 @@ rem_idr: + idr_remove(&vrp->endpoints, request); + free_ept: + mutex_unlock(&vrp->endpoints_lock); +- kfree(ept); ++ kref_put(&ept->refcount, __ept_release); + return NULL; + } + +@@ -306,7 +328,7 @@ __rpmsg_destroy_ept(struct virtproc_info + idr_remove(&vrp->endpoints, ept->addr); + mutex_unlock(&vrp->endpoints_lock); + +- kfree(ept); ++ kref_put(&ept->refcount, __ept_release); + } + + /** +@@ -790,7 +812,13 @@ static void rpmsg_recv_done(struct virtq + + /* use the dst addr to fetch the callback of the appropriate user */ + mutex_lock(&vrp->endpoints_lock); ++ + ept = idr_find(&vrp->endpoints, msg->dst); ++ ++ /* let's make sure no one deallocates ept while we use it */ ++ if (ept) ++ kref_get(&ept->refcount); ++ + mutex_unlock(&vrp->endpoints_lock); + + if (ept && ept->cb) +@@ -798,6 +826,10 @@ static void rpmsg_recv_done(struct virtq + else + dev_warn(dev, "msg received with no recepient\n"); + ++ /* farewell, ept, we don't need you anymore */ ++ if (ept) ++ kref_put(&ept->refcount, __ept_release); ++ + /* publish the real size of the buffer */ + sg_init_one(&sg, msg, RPMSG_BUF_SIZE); + +--- a/include/linux/rpmsg.h ++++ b/include/linux/rpmsg.h +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + /* The feature bitmap for virtio rpmsg */ + #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ +@@ -120,6 +121,7 @@ typedef void (*rpmsg_rx_cb_t)(struct rpm + /** + * struct rpmsg_endpoint - binds a local rpmsg address to its user + * @rpdev: rpmsg channel device ++ * @refcount: when this drops to zero, the ept is deallocated + * @cb: rx callback handler + * @addr: local rpmsg address + * @priv: private data for the driver's use +@@ -140,6 +142,7 @@ typedef void (*rpmsg_rx_cb_t)(struct rpm + */ + struct rpmsg_endpoint { + struct rpmsg_channel *rpdev; ++ struct kref refcount; + rpmsg_rx_cb_t cb; + u32 addr; + void *priv; diff --git a/queue-3.4/rpmsg-make-sure-inflight-messages-don-t-invoke-just-removed-callbacks.patch b/queue-3.4/rpmsg-make-sure-inflight-messages-don-t-invoke-just-removed-callbacks.patch new file mode 100644 index 00000000000..1962444ee12 --- /dev/null +++ b/queue-3.4/rpmsg-make-sure-inflight-messages-don-t-invoke-just-removed-callbacks.patch @@ -0,0 +1,109 @@ +From 15fd943af50dbc5f7f4de33835795c72595f7bf4 Mon Sep 17 00:00:00 2001 +From: Ohad Ben-Cohen +Date: Thu, 7 Jun 2012 15:39:35 +0300 +Subject: rpmsg: make sure inflight messages don't invoke just-removed callbacks + +From: Ohad Ben-Cohen + +commit 15fd943af50dbc5f7f4de33835795c72595f7bf4 upstream. + +When inbound messages arrive, rpmsg core looks up their associated +endpoint (by destination address) and then invokes their callback. + +We've made sure that endpoints will never be de-allocated after they +were found by rpmsg core, but we also need to protect against the +(rare) scenario where the rpmsg driver was just removed, and its +callback function isn't available anymore. + +This is achieved by introducing a callback mutex, which must be taken +before the callback is invoked, and, obviously, before it is removed. + +Reported-by: Fernando Guzman Lugo +Signed-off-by: Ohad Ben-Cohen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rpmsg/virtio_rpmsg_bus.c | 25 +++++++++++++++++++------ + include/linux/rpmsg.h | 3 +++ + 2 files changed, 22 insertions(+), 6 deletions(-) + +--- a/drivers/rpmsg/virtio_rpmsg_bus.c ++++ b/drivers/rpmsg/virtio_rpmsg_bus.c +@@ -227,6 +227,7 @@ static struct rpmsg_endpoint *__rpmsg_cr + } + + kref_init(&ept->refcount); ++ mutex_init(&ept->cb_lock); + + ept->rpdev = rpdev; + ept->cb = cb; +@@ -324,10 +325,16 @@ EXPORT_SYMBOL(rpmsg_create_ept); + static void + __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) + { ++ /* make sure new inbound messages can't find this ept anymore */ + mutex_lock(&vrp->endpoints_lock); + idr_remove(&vrp->endpoints, ept->addr); + mutex_unlock(&vrp->endpoints_lock); + ++ /* make sure in-flight inbound messages won't invoke cb anymore */ ++ mutex_lock(&ept->cb_lock); ++ ept->cb = NULL; ++ mutex_unlock(&ept->cb_lock); ++ + kref_put(&ept->refcount, __ept_release); + } + +@@ -821,14 +828,20 @@ static void rpmsg_recv_done(struct virtq + + mutex_unlock(&vrp->endpoints_lock); + +- if (ept && ept->cb) +- ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, msg->src); +- else +- dev_warn(dev, "msg received with no recepient\n"); ++ if (ept) { ++ /* make sure ept->cb doesn't go away while we use it */ ++ mutex_lock(&ept->cb_lock); + +- /* farewell, ept, we don't need you anymore */ +- if (ept) ++ if (ept->cb) ++ ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, ++ msg->src); ++ ++ mutex_unlock(&ept->cb_lock); ++ ++ /* farewell, ept, we don't need you anymore */ + kref_put(&ept->refcount, __ept_release); ++ } else ++ dev_warn(dev, "msg received with no recepient\n"); + + /* publish the real size of the buffer */ + sg_init_one(&sg, msg, RPMSG_BUF_SIZE); +--- a/include/linux/rpmsg.h ++++ b/include/linux/rpmsg.h +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + /* The feature bitmap for virtio rpmsg */ + #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ +@@ -123,6 +124,7 @@ typedef void (*rpmsg_rx_cb_t)(struct rpm + * @rpdev: rpmsg channel device + * @refcount: when this drops to zero, the ept is deallocated + * @cb: rx callback handler ++ * @cb_lock: must be taken before accessing/changing @cb + * @addr: local rpmsg address + * @priv: private data for the driver's use + * +@@ -144,6 +146,7 @@ struct rpmsg_endpoint { + struct rpmsg_channel *rpdev; + struct kref refcount; + rpmsg_rx_cb_t cb; ++ struct mutex cb_lock; + u32 addr; + void *priv; + }; diff --git a/queue-3.4/series b/queue-3.4/series index 79a33a9a6e5..9a9362e1afd 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -50,3 +50,20 @@ nilfs2-ensure-proper-cache-clearing-for-gc-inodes.patch udf-use-ret-instead-of-abusing-i-in-udf_load_logicalvol.patch udf-avoid-run-away-loop-when-partition-table-length-is-corrupted.patch udf-fortify-loading-of-sparing-table.patch +iommu-amd-fix-missing-iommu_shutdown-initialization-in-passthrough-mode.patch +iommu-amd-initialize-dma_ops-for-hotplug-and-sriov-devices.patch +iommu-tegra-smmu-fix-unsleepable-memory-allocation.patch +rpmsg-avoid-premature-deallocation-of-endpoints.patch +rpmsg-make-sure-inflight-messages-don-t-invoke-just-removed-callbacks.patch +cifs-fix-parsing-of-password-mount-option.patch +cifs-when-server-doesn-t-set-cap_large_read_x-cap-default-rsize-at-maxbuffersize.patch +ath9k-fix-a-warning-on-suspend-resume-with-ibss.patch +ath9k-fix-softlockup-in-ar9485.patch +ath9k-fix-a-tx-rate-duration-calculation-bug.patch +ath9k-fix-invalid-pointer-access-in-the-tx-path.patch +ath9k_hw-avoid-possible-infinite-loop-in.patch +ath9k_htc-configure-bssid-on-assoc-ibss-change.patch +ath9k-fix-dynamic-wep-related-regression.patch +ath9k-enable-serialize_regmode-for-non-pcie-ar9287.patch +asoc-wm2200-add-missing-bclk-rate.patch +asoc-tlv320aic3x-fix-codec-pll-configure-bug.patch