+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -3984,18 +3984,20 @@ static void ar9003_hw_quick_drop_apply(s
+ int quick_drop;
+ s32 t[3], f[3] = {5180, 5500, 5785};
+
+- if (!(pBase->miscConfiguration & BIT(1)))
++ if (!(pBase->miscConfiguration & BIT(4)))
+ return;
+
+- if (freq < 4000)
+- quick_drop = eep->modalHeader2G.quick_drop;
+- else {
+- t[0] = eep->base_ext1.quick_drop_low;
+- t[1] = eep->modalHeader5G.quick_drop;
+- t[2] = eep->base_ext1.quick_drop_high;
+- quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9340(ah)) {
++ if (freq < 4000) {
++ quick_drop = eep->modalHeader2G.quick_drop;
++ } else {
++ t[0] = eep->base_ext1.quick_drop_low;
++ t[1] = eep->modalHeader5G.quick_drop;
++ t[2] = eep->base_ext1.quick_drop_high;
++ quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
++ }
++ REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
+ }
+- REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
+ }
+
+ static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
+@@ -4035,7 +4037,7 @@ static void ar9003_hw_xlna_bias_strength
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ u8 bias;
+
+- if (!(eep->baseEepHeader.featureEnable & 0x40))
++ if (!(eep->baseEepHeader.miscConfiguration & 0x40))
+ return;
+
+ if (!AR_SREV_9300(ah))
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -735,6 +735,7 @@ struct ieee80211_sub_if_data {
+ int csa_counter_offset_beacon;
+ int csa_counter_offset_presp;
+ bool csa_radar_required;
++ struct cfg80211_chan_def csa_chandef;
+
+ /* used to reconfigure hardware SM PS */
+ struct work_struct recalc_smps;
+@@ -811,6 +812,9 @@ static inline void sdata_unlock(struct i
+ __release(&sdata->wdev.mtx);
+ }
+
++#define sdata_dereference(p, sdata) \
++ rcu_dereference_protected(p, lockdep_is_held(&sdata->wdev.mtx))
++
+ static inline void
+ sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
+ {
+@@ -1098,7 +1102,6 @@ struct ieee80211_local {
+ enum mac80211_scan_state next_scan_state;
+ struct delayed_work scan_work;
+ struct ieee80211_sub_if_data __rcu *scan_sdata;
+- struct cfg80211_chan_def csa_chandef;
+ /* For backward compatibility only -- do not use */
+ struct cfg80211_chan_def _oper_chandef;
+
+@@ -1236,6 +1239,7 @@ struct ieee80211_csa_ie {
+ u8 mode;
+ u8 count;
+ u8 ttl;
++ u16 pre_value;
+ };
+
+ /* Parsed Information Elements */
+@@ -1738,7 +1742,6 @@ ieee80211_vif_change_bandwidth(struct ie
+ /* NOTE: only use ieee80211_vif_change_channel() for channel switch */
+ int __must_check
+ ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
+- const struct cfg80211_chan_def *chandef,
+ u32 *changed);
+ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -411,12 +411,12 @@ int ieee80211_vif_use_channel(struct iee
+ }
+
+ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
+- const struct cfg80211_chan_def *chandef,
+ u32 *changed)
+ {
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *conf;
+ struct ieee80211_chanctx *ctx;
++ const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
+ int ret;
+ u32 chanctx_changed = 0;
+
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -550,12 +550,12 @@ int ieee80211_ibss_finish_csa(struct iee
+ capability);
+ /* XXX: should not really modify cfg80211 data */
+ if (cbss) {
+- cbss->channel = sdata->local->csa_chandef.chan;
++ cbss->channel = sdata->csa_chandef.chan;
+ cfg80211_put_bss(sdata->local->hw.wiphy, cbss);
+ }
+ }
+
+- ifibss->chandef = sdata->local->csa_chandef;
++ ifibss->chandef = sdata->csa_chandef;
+
+ /* generate the beacon */
+ err = ieee80211_ibss_csa_beacon(sdata, NULL);
+@@ -922,7 +922,7 @@ ieee80211_ibss_process_chanswitch(struct
+ IEEE80211_MAX_QUEUE_MAP,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+
+- sdata->local->csa_chandef = params.chandef;
++ sdata->csa_chandef = params.chandef;
+ sdata->vif.csa_active = true;
+
+ ieee80211_bss_info_change_notify(sdata, err);
+--- a/net/mac80211/mesh.c
++++ b/net/mac80211/mesh.c
+@@ -943,14 +943,19 @@ ieee80211_mesh_process_chnswitch(struct
+ params.chandef.chan->center_freq);
+
+ params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
+- if (beacon)
++ if (beacon) {
+ ifmsh->chsw_ttl = csa_ie.ttl - 1;
+- else
+- ifmsh->chsw_ttl = 0;
++ if (ifmsh->pre_value >= csa_ie.pre_value)
++ return false;
++ ifmsh->pre_value = csa_ie.pre_value;
++ }
+
+- if (ifmsh->chsw_ttl > 0)
++ if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
+ if (ieee80211_mesh_csa_beacon(sdata, ¶ms, false) < 0)
+ return false;
++ } else {
++ return false;
++ }
+
+ sdata->csa_radar_required = params.radar_required;
+
+@@ -959,7 +964,7 @@ ieee80211_mesh_process_chnswitch(struct
+ IEEE80211_MAX_QUEUE_MAP,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+
+- sdata->local->csa_chandef = params.chandef;
++ sdata->csa_chandef = params.chandef;
+ sdata->vif.csa_active = true;
+
+ ieee80211_bss_info_change_notify(sdata, err);
+@@ -1163,7 +1168,6 @@ static int mesh_fwd_csa_frame(struct iee
+ offset_ttl = (len < 42) ? 7 : 10;
+ *(pos + offset_ttl) -= 1;
+ *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
+- sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
+
+ memcpy(mgmt_fwd, mgmt, len);
+ eth_broadcast_addr(mgmt_fwd->da);
+@@ -1182,7 +1186,7 @@ static void mesh_rx_csa_frame(struct iee
+ u16 pre_value;
+ bool fwd_csa = true;
+ size_t baselen;
+- u8 *pos, ttl;
++ u8 *pos;
+
+ if (mgmt->u.action.u.measurement.action_code !=
+ WLAN_ACTION_SPCT_CHL_SWITCH)
+@@ -1193,8 +1197,8 @@ static void mesh_rx_csa_frame(struct iee
+ u.action.u.chan_switch.variable);
+ ieee802_11_parse_elems(pos, len - baselen, false, &elems);
+
+- ttl = elems.mesh_chansw_params_ie->mesh_ttl;
+- if (!--ttl)
++ ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
++ if (!--ifmsh->chsw_ttl)
+ fwd_csa = false;
+
+ pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
+--- a/net/mac80211/spectmgmt.c
++++ b/net/mac80211/spectmgmt.c
+@@ -78,6 +78,8 @@ int ieee80211_parse_ch_switch_ie(struct
+ if (elems->mesh_chansw_params_ie) {
+ csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
+ csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
++ csa_ie->pre_value = le16_to_cpu(
++ elems->mesh_chansw_params_ie->mesh_pre_value);
+ }
+
+ new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
+--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
++++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
+@@ -1109,7 +1109,9 @@ void ath6kl_cfg80211_ch_switch_notify(st
+ (mode == WMI_11G_HT20) ?
+ NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
+
++ mutex_lock(vif->wdev->mtx);
+ cfg80211_ch_switch_notify(vif->ndev, &chandef);
++ mutex_unlock(vif->wdev->mtx);
+ }
+
+ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,