---- a/net/wireless/reg.c
-+++ b/net/wireless/reg.c
-@@ -1456,7 +1456,8 @@ static void reg_process_hint(struct regu
- * We only time out user hints, given that they should be the only
- * source of bogus requests.
- */
-- if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER)
-+ if (r != -EALREADY &&
-+ reg_request->initiator == NL80211_REGDOM_SET_BY_USER)
- schedule_delayed_work(®_timeout, msecs_to_jiffies(3142));
- }
-
---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
-@@ -18,13 +18,13 @@
- #include "hw-ops.h"
- #include "ar9003_phy.h"
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -325,6 +325,8 @@ ath5k_setup_channels(struct ath5k_hw *ah
+ if (!ath5k_is_standard_channel(ch, band))
+ continue;
--#define MPASS 3
- #define MAX_MEASUREMENT 8
--#define MAX_DIFFERENCE 10
-+#define MAX_MAG_DELTA 11
-+#define MAX_PHS_DELTA 10
++ channels[count].max_power = AR5K_TUNE_MAX_TXPOWER/2;
++
+ count++;
+ }
- struct coeff {
-- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
-- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
-+ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
-+ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
- int iqc_coeff[2];
- };
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -203,6 +203,8 @@ static void ieee80211_send_addba_resp(st
+ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
++ else if (sdata->vif.type == NL80211_IFTYPE_WDS)
++ memcpy(mgmt->bssid, da, ETH_ALEN);
+
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION);
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -81,7 +81,8 @@ static void ieee80211_send_addba_request
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+- sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
++ sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
++ sdata->vif.type == NL80211_IFTYPE_WDS)
+ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+@@ -460,6 +461,7 @@ int ieee80211_start_tx_ba_session(struct
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+ sdata->vif.type != NL80211_IFTYPE_AP &&
++ sdata->vif.type != NL80211_IFTYPE_WDS &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ return -EINVAL;
+
+@@ -869,7 +871,7 @@ void ieee80211_process_addba_resp(struct
-@@ -608,36 +608,48 @@ static bool ar9003_hw_calc_iq_corr(struc
- return true;
- }
+ } else {
+ ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
+- true);
++ false);
+ }
--static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
-+static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
-+ int max_delta)
- {
-- int diff[MPASS];
+ out:
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -63,11 +63,11 @@ static ssize_t sta_flags_read(struct fil
+ test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
+
+ int res = scnprintf(buf, sizeof(buf),
+- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
++ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
+ TEST(PS_DRIVER), TEST(AUTHORIZED),
+ TEST(SHORT_PREAMBLE),
+- TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
++ TEST(WME), TEST(CLEAR_PS_FILT),
+ TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
+ TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
+ TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -420,7 +420,6 @@ int ieee80211_do_open(struct wireless_de
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct net_device *dev = wdev->netdev;
+ struct ieee80211_local *local = sdata->local;
+- struct sta_info *sta;
+ u32 changed = 0;
+ int res;
+ u32 hw_reconf_flags = 0;
+@@ -575,30 +574,8 @@ int ieee80211_do_open(struct wireless_de
+
+ set_bit(SDATA_STATE_RUNNING, &sdata->state);
+
+- if (sdata->vif.type == NL80211_IFTYPE_WDS) {
+- /* Create STA entry for the WDS peer */
+- sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
+- GFP_KERNEL);
+- if (!sta) {
+- res = -ENOMEM;
+- goto err_del_interface;
+- }
-
-- diff[0] = abs(mp_coeff[0] - mp_coeff[1]);
-- diff[1] = abs(mp_coeff[1] - mp_coeff[2]);
-- diff[2] = abs(mp_coeff[2] - mp_coeff[0]);
+- sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
+- sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
+- sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
-
-- if (diff[0] > MAX_DIFFERENCE &&
-- diff[1] > MAX_DIFFERENCE &&
-- diff[2] > MAX_DIFFERENCE)
-- return false;
+- res = sta_info_insert(sta);
+- if (res) {
+- /* STA has been freed */
+- goto err_del_interface;
+- }
-
-- if (diff[0] <= diff[1] && diff[0] <= diff[2])
-- *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2;
-- else if (diff[1] <= diff[2])
-- *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2;
-- else
-- *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2;
-+ int mp_max = -64, max_idx = 0;
-+ int mp_min = 63, min_idx = 0;
-+ int mp_avg = 0, i, outlier_idx = 0;
-+
-+ /* find min/max mismatch across all calibrated gains */
-+ for (i = 0; i < nmeasurement; i++) {
-+ mp_avg += mp_coeff[i];
-+ if (mp_coeff[i] > mp_max) {
-+ mp_max = mp_coeff[i];
-+ max_idx = i;
-+ } else if (mp_coeff[i] < mp_min) {
-+ mp_min = mp_coeff[i];
-+ min_idx = i;
-+ }
-+ }
+- rate_control_rate_init(sta);
+- netif_carrier_on(dev);
+- } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
++ if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
+ rcu_assign_pointer(local->p2p_sdata, sdata);
+- }
-- return true;
-+ /* find average (exclude max abs value) */
-+ for (i = 0; i < nmeasurement; i++) {
-+ if ((abs(mp_coeff[i]) < abs(mp_max)) ||
-+ (abs(mp_coeff[i]) < abs(mp_min)))
-+ mp_avg += mp_coeff[i];
+ /*
+ * set_multicast_list will be invoked by the networking core
+@@ -997,6 +974,72 @@ static void ieee80211_if_setup(struct ne
+ dev->destructor = free_netdev;
+ }
+
++static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
++ struct sk_buff *skb)
++{
++ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_rx_status *rx_status;
++ struct ieee802_11_elems elems;
++ struct ieee80211_mgmt *mgmt;
++ struct sta_info *sta;
++ size_t baselen;
++ u32 rates = 0;
++ u16 stype;
++ bool new = false;
++ enum ieee80211_band band = local->hw.conf.channel->band;
++ struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
++
++ rx_status = IEEE80211_SKB_RXCB(skb);
++ mgmt = (struct ieee80211_mgmt *) skb->data;
++ stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
++
++ if (stype != IEEE80211_STYPE_BEACON)
++ return;
++
++ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
++ if (baselen > skb->len)
++ return;
++
++ ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
++ skb->len - baselen, &elems);
++
++ rates = ieee80211_sta_get_rates(local, &elems, band, NULL);
++
++ rcu_read_lock();
++
++ sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
++
++ if (!sta) {
++ rcu_read_unlock();
++ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
++ GFP_KERNEL);
++ if (!sta)
++ return;
++
++ new = true;
+ }
-+ mp_avg /= (nmeasurement - 1);
+
-+ /* detect outlier */
-+ if (abs(mp_max - mp_min) > max_delta) {
-+ if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
-+ outlier_idx = max_idx;
-+ else
-+ outlier_idx = min_idx;
++ sta->last_rx = jiffies;
++ sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
++
++ if (elems.ht_cap_elem)
++ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
++ elems.ht_cap_elem, &sta->sta.ht_cap);
++
++ if (elems.wmm_param)
++ set_sta_flag(sta, WLAN_STA_WME);
++
++ if (new) {
++ sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
++ sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
++ sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
++ rate_control_rate_init(sta);
++ sta_info_insert_rcu(sta);
+ }
-+ mp_coeff[outlier_idx] = mp_avg;
- }
-
- static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
- u8 num_chains,
- struct coeff *coeff)
++
++ rcu_read_unlock();
++}
++
+ static void ieee80211_iface_work(struct work_struct *work)
{
-- struct ath_common *common = ath9k_hw_common(ah);
- int i, im, nmeasurement;
-- int magnitude, phase;
- u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
-
- memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
-@@ -657,37 +669,28 @@ static void ar9003_hw_tx_iqcal_load_avg_
-
- /* Load the average of 2 passes */
- for (i = 0; i < num_chains; i++) {
-- if (AR_SREV_9485(ah))
-- nmeasurement = REG_READ_FIELD(ah,
-- AR_PHY_TX_IQCAL_STATUS_B0_9485,
-- AR_PHY_CALIBRATED_GAINS_0);
-- else
-- nmeasurement = REG_READ_FIELD(ah,
-- AR_PHY_TX_IQCAL_STATUS_B0,
-- AR_PHY_CALIBRATED_GAINS_0);
-+ nmeasurement = REG_READ_FIELD(ah,
-+ AR_PHY_TX_IQCAL_STATUS_B0,
-+ AR_PHY_CALIBRATED_GAINS_0);
-
- if (nmeasurement > MAX_MEASUREMENT)
- nmeasurement = MAX_MEASUREMENT;
-
-- for (im = 0; im < nmeasurement; im++) {
-- /*
-- * Determine which 2 passes are closest and compute avg
-- * magnitude
-- */
-- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
-- &magnitude))
-- goto disable_txiqcal;
-+ /* detect outlier only if nmeasurement > 1 */
-+ if (nmeasurement > 1) {
-+ /* Detect magnitude outlier */
-+ ar9003_hw_detect_outlier(coeff->mag_coeff[i],
-+ nmeasurement, MAX_MAG_DELTA);
+ struct ieee80211_sub_if_data *sdata =
+@@ -1101,6 +1144,9 @@ static void ieee80211_iface_work(struct
+ break;
+ ieee80211_mesh_rx_queued_mgmt(sdata, skb);
+ break;
++ case NL80211_IFTYPE_WDS:
++ ieee80211_wds_rx_queued_mgmt(sdata, skb);
++ break;
+ default:
+ WARN(1, "frame for unexpected interface type");
+ break;
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2279,6 +2279,7 @@ ieee80211_rx_h_action(struct ieee80211_r
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+ sdata->vif.type != NL80211_IFTYPE_AP &&
++ sdata->vif.type != NL80211_IFTYPE_WDS &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ break;
+
+@@ -2496,14 +2497,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+
+ if (!ieee80211_vif_is_mesh(&sdata->vif) &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+- sdata->vif.type != NL80211_IFTYPE_STATION)
++ sdata->vif.type != NL80211_IFTYPE_STATION &&
++ sdata->vif.type != NL80211_IFTYPE_WDS)
+ return RX_DROP_MONITOR;
+
+ switch (stype) {
+ case cpu_to_le16(IEEE80211_STYPE_AUTH):
+ case cpu_to_le16(IEEE80211_STYPE_BEACON):
+ case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+- /* process for all: mesh, mlme, ibss */
++ /* process for all: mesh, mlme, ibss, wds */
+ break;
+ case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
+ case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
+@@ -2827,10 +2829,16 @@ static int prepare_for_handlers(struct i
+ }
+ break;
+ case NL80211_IFTYPE_WDS:
+- if (bssid || !ieee80211_is_data(hdr->frame_control))
+- return 0;
+ if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
+ return 0;
+
-+ /* Detect phase outlier */
-+ ar9003_hw_detect_outlier(coeff->phs_coeff[i],
-+ nmeasurement, MAX_PHS_DELTA);
++ if (ieee80211_is_data(hdr->frame_control) ||
++ ieee80211_is_action(hdr->frame_control)) {
++ if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
++ return 0;
++ } else if (!ieee80211_is_beacon(hdr->frame_control))
++ return 0;
++
+ break;
+ case NL80211_IFTYPE_P2P_DEVICE:
+ if (!ieee80211_is_public_action(hdr, skb->len) &&
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -32,7 +32,6 @@
+ * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
+ * frames.
+ * @WLAN_STA_WME: Station is a QoS-STA.
+- * @WLAN_STA_WDS: Station is one of our WDS peers.
+ * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
+ * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
+ * frame to this station is transmitted.
+@@ -64,7 +63,6 @@ enum ieee80211_sta_info_flags {
+ WLAN_STA_AUTHORIZED,
+ WLAN_STA_SHORT_PREAMBLE,
+ WLAN_STA_WME,
+- WLAN_STA_WDS,
+ WLAN_STA_CLEAR_PS_FILT,
+ WLAN_STA_MFP,
+ WLAN_STA_BLOCK_BA,
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -517,29 +517,41 @@ void ieee80211_tx_status(struct ieee8021
+
+ if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
+ u64 cookie = (unsigned long)skb;
++ bool found = false;
++
+ acked = info->flags & IEEE80211_TX_STAT_ACK;
+
+- if (ieee80211_is_nullfunc(hdr->frame_control) ||
+- ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+- cfg80211_probe_status(skb->dev, hdr->addr1,
+- cookie, acked, GFP_ATOMIC);
+- } else if (skb->dev) {
+- cfg80211_mgmt_tx_status(
+- skb->dev->ieee80211_ptr, cookie, skb->data,
+- skb->len, acked, GFP_ATOMIC);
+- } else {
+- struct ieee80211_sub_if_data *p2p_sdata;
++ rcu_read_lock();
+
+- rcu_read_lock();
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++ if (!sdata->dev)
++ continue;
++
++ if (skb->dev != sdata->dev)
++ continue;
++
++ found = true;
++ break;
+ }
-- /*
-- * Determine which 2 passes are closest and compute avg
-- * phase
-- */
-- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im],
-- &phase))
-- goto disable_txiqcal;
-+ for (im = 0; im < nmeasurement; im++) {
-
-- coeff->iqc_coeff[0] = (magnitude & 0x7f) |
-- ((phase & 0x7f) << 7);
-+ coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
-+ ((coeff->phs_coeff[i][im] & 0x7f) << 7);
-
- if ((im % 2) == 0)
- REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
-@@ -707,141 +710,37 @@ static void ar9003_hw_tx_iqcal_load_avg_
-
- return;
-
--disable_txiqcal:
-- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
-- AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0);
-- REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
-- AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0);
--
-- ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
- }
-
--static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
-+static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
- {
- struct ath_common *common = ath9k_hw_common(ah);
-- static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
-- AR_PHY_TX_IQCAL_STATUS_B0,
-- AR_PHY_TX_IQCAL_STATUS_B1,
-- AR_PHY_TX_IQCAL_STATUS_B2,
-- };
-- static const u32 chan_info_tab[] = {
-- AR_PHY_CHAN_INFO_TAB_0,
-- AR_PHY_CHAN_INFO_TAB_1,
-- AR_PHY_CHAN_INFO_TAB_2,
-- };
-- struct coeff coeff;
-- s32 iq_res[6];
-- s32 i, j, ip, im, nmeasurement;
-- u8 nchains = get_streams(common->tx_chainmask);
--
-- for (ip = 0; ip < MPASS; ip++) {
-- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
-- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
-- DELPT);
-- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
-- AR_PHY_TX_IQCAL_START_DO_CAL,
-- AR_PHY_TX_IQCAL_START_DO_CAL);
--
-- if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
-- AR_PHY_TX_IQCAL_START_DO_CAL,
-- 0, AH_WAIT_TIMEOUT)) {
-- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "Tx IQ Cal not complete.\n");
-- goto TX_IQ_CAL_FAILED;
-- }
--
-- nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
-- AR_PHY_CALIBRATED_GAINS_0);
-- if (nmeasurement > MAX_MEASUREMENT)
-- nmeasurement = MAX_MEASUREMENT;
--
-- for (i = 0; i < nchains; i++) {
-- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "Doing Tx IQ Cal for chain %d.\n", i);
-- for (im = 0; im < nmeasurement; im++) {
-- if (REG_READ(ah, txiqcal_status[i]) &
-- AR_PHY_TX_IQCAL_STATUS_FAILED) {
-- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "Tx IQ Cal failed for chain %d.\n", i);
-- goto TX_IQ_CAL_FAILED;
-- }
--
-- for (j = 0; j < 3; j++) {
-- u8 idx = 2 * j,
-- offset = 4 * (3 * im + j);
--
-- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
-- AR_PHY_CHAN_INFO_TAB_S2_READ,
-- 0);
--
-- /* 32 bits */
-- iq_res[idx] = REG_READ(ah,
-- chan_info_tab[i] +
-- offset);
--
-- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
-- AR_PHY_CHAN_INFO_TAB_S2_READ,
-- 1);
--
-- /* 16 bits */
-- iq_res[idx+1] = 0xffff & REG_READ(ah,
-- chan_info_tab[i] +
-- offset);
--
-- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
-- idx, iq_res[idx], idx+1, iq_res[idx+1]);
-- }
--
-- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
-- coeff.iqc_coeff)) {
-- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "Failed in calculation of IQ correction.\n");
-- goto TX_IQ_CAL_FAILED;
-- }
-- coeff.mag_coeff[i][im][ip] =
-- coeff.iqc_coeff[0] & 0x7f;
-- coeff.phs_coeff[i][im][ip] =
-- (coeff.iqc_coeff[0] >> 7) & 0x7f;
--
-- if (coeff.mag_coeff[i][im][ip] > 63)
-- coeff.mag_coeff[i][im][ip] -= 128;
-- if (coeff.phs_coeff[i][im][ip] > 63)
-- coeff.phs_coeff[i][im][ip] -= 128;
--
+- p2p_sdata = rcu_dereference(local->p2p_sdata);
+- if (p2p_sdata) {
+- cfg80211_mgmt_tx_status(
+- &p2p_sdata->wdev, cookie, skb->data,
+- skb->len, acked, GFP_ATOMIC);
- }
-- }
-- }
--
-- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
--
-- return;
--
--TX_IQ_CAL_FAILED:
-- ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
--}
--
--static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
--{
- u8 tx_gain_forced;
-
-- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485,
-- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
- tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
- AR_PHY_TXGAIN_FORCE);
- if (tx_gain_forced)
- REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
- AR_PHY_TXGAIN_FORCE, 0);
-
-- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485,
-- AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1);
-+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
-+ AR_PHY_TX_IQCAL_START_DO_CAL, 1);
+- rcu_read_unlock();
++ if (!skb->dev) {
++ sdata = rcu_dereference(local->p2p_sdata);
++ if (sdata)
++ found = true;
+ }
+
-+ if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
-+ AR_PHY_TX_IQCAL_START_DO_CAL, 0,
-+ AH_WAIT_TIMEOUT)) {
-+ ath_dbg(common, ATH_DBG_CALIBRATE,
-+ "Tx IQ Cal is not completed.\n");
-+ return false;
-+ }
-+ return true;
- }
++ if (!found)
++ skb->dev = NULL;
++ else if (ieee80211_is_nullfunc(hdr->frame_control) ||
++ ieee80211_is_qos_nullfunc(hdr->frame_control)) {
++ cfg80211_probe_status(sdata->dev, hdr->addr1,
++ cookie, acked, GFP_ATOMIC);
++ } else {
++ cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
++ skb->len, acked, GFP_ATOMIC);
++ }
++
++ rcu_read_unlock();
+ }
- static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
+ if (unlikely(info->ack_frame_id)) {
+--- a/drivers/net/wireless/p54/main.c
++++ b/drivers/net/wireless/p54/main.c
+@@ -139,6 +139,7 @@ static int p54_beacon_format_ie_tim(stru
+ static int p54_beacon_update(struct p54_common *priv,
+ struct ieee80211_vif *vif)
{
- struct ath_common *common = ath9k_hw_common(ah);
- const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
-- AR_PHY_TX_IQCAL_STATUS_B0_9485,
-+ AR_PHY_TX_IQCAL_STATUS_B0,
- AR_PHY_TX_IQCAL_STATUS_B1,
- AR_PHY_TX_IQCAL_STATUS_B2,
- };
-@@ -853,7 +752,7 @@ static void ar9003_hw_tx_iq_cal_post_pro
- struct coeff coeff;
- s32 iq_res[6];
- u8 num_chains = 0;
-- int i, ip, im, j;
-+ int i, im, j;
- int nmeasurement;
++ struct ieee80211_tx_control control = { };
+ struct sk_buff *beacon;
+ int ret;
- for (i = 0; i < AR9300_MAX_CHAINS; i++) {
-@@ -861,71 +760,69 @@ static void ar9003_hw_tx_iq_cal_post_pro
- num_chains++;
- }
+@@ -158,7 +159,7 @@ static int p54_beacon_update(struct p54_
+ * to cancel the old beacon template by hand, instead the firmware
+ * will release the previous one through the feedback mechanism.
+ */
+- p54_tx_80211(priv->hw, NULL, beacon);
++ p54_tx_80211(priv->hw, &control, beacon);
+ priv->tsf_high32 = 0;
+ priv->tsf_low32 = 0;
-- for (ip = 0; ip < MPASS; ip++) {
-- for (i = 0; i < num_chains; i++) {
-- nmeasurement = REG_READ_FIELD(ah,
-- AR_PHY_TX_IQCAL_STATUS_B0_9485,
-- AR_PHY_CALIBRATED_GAINS_0);
-- if (nmeasurement > MAX_MEASUREMENT)
-- nmeasurement = MAX_MEASUREMENT;
-+ for (i = 0; i < num_chains; i++) {
-+ nmeasurement = REG_READ_FIELD(ah,
-+ AR_PHY_TX_IQCAL_STATUS_B0,
-+ AR_PHY_CALIBRATED_GAINS_0);
-+ if (nmeasurement > MAX_MEASUREMENT)
-+ nmeasurement = MAX_MEASUREMENT;
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -352,6 +352,9 @@ static void reg_regdb_search(struct work
+ struct reg_regdb_search_request *request;
+ const struct ieee80211_regdomain *curdom, *regdom;
+ int i, r;
++ bool set_reg = false;
+
-+ for (im = 0; im < nmeasurement; im++) {
-+ ath_dbg(common, ATH_DBG_CALIBRATE,
-+ "Doing Tx IQ Cal for chain %d.\n", i);
-
-- for (im = 0; im < nmeasurement; im++) {
-+ if (REG_READ(ah, txiqcal_status[i]) &
-+ AR_PHY_TX_IQCAL_STATUS_FAILED) {
- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "Doing Tx IQ Cal for chain %d.\n", i);
--
-- if (REG_READ(ah, txiqcal_status[i]) &
-- AR_PHY_TX_IQCAL_STATUS_FAILED) {
-- ath_dbg(common, ATH_DBG_CALIBRATE,
- "Tx IQ Cal failed for chain %d.\n", i);
-- goto tx_iqcal_fail;
-- }
-+ goto tx_iqcal_fail;
-+ }
-
-- for (j = 0; j < 3; j++) {
-- u32 idx = 2 * j, offset = 4 * (3 * im + j);
-+ for (j = 0; j < 3; j++) {
-+ u32 idx = 2 * j, offset = 4 * (3 * im + j);
-
-- REG_RMW_FIELD(ah,
-+ REG_RMW_FIELD(ah,
- AR_PHY_CHAN_INFO_MEMORY,
- AR_PHY_CHAN_INFO_TAB_S2_READ,
- 0);
-
-- /* 32 bits */
-- iq_res[idx] = REG_READ(ah,
-- chan_info_tab[i] +
-- offset);
-+ /* 32 bits */
-+ iq_res[idx] = REG_READ(ah,
-+ chan_info_tab[i] +
-+ offset);
-
-- REG_RMW_FIELD(ah,
-+ REG_RMW_FIELD(ah,
- AR_PHY_CHAN_INFO_MEMORY,
- AR_PHY_CHAN_INFO_TAB_S2_READ,
- 1);
-
-- /* 16 bits */
-- iq_res[idx + 1] = 0xffff & REG_READ(ah,
-- chan_info_tab[i] + offset);
--
-- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "IQ RES[%d]=0x%x"
-- "IQ_RES[%d]=0x%x\n",
-- idx, iq_res[idx], idx + 1,
-- iq_res[idx + 1]);
-- }
-+ /* 16 bits */
-+ iq_res[idx + 1] = 0xffff & REG_READ(ah,
-+ chan_info_tab[i] + offset);
-
-- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
-- coeff.iqc_coeff)) {
-- ath_dbg(common, ATH_DBG_CALIBRATE,
-- "Failed in calculation of IQ correction.\n");
-- goto tx_iqcal_fail;
-- }
-+ ath_dbg(common, ATH_DBG_CALIBRATE,
-+ "IQ RES[%d]=0x%x"
-+ "IQ_RES[%d]=0x%x\n",
-+ idx, iq_res[idx], idx + 1,
-+ iq_res[idx + 1]);
-+ }
-
-- coeff.mag_coeff[i][im][ip] =
-- coeff.iqc_coeff[0] & 0x7f;
-- coeff.phs_coeff[i][im][ip] =
-- (coeff.iqc_coeff[0] >> 7) & 0x7f;
--
-- if (coeff.mag_coeff[i][im][ip] > 63)
-- coeff.mag_coeff[i][im][ip] -= 128;
-- if (coeff.phs_coeff[i][im][ip] > 63)
-- coeff.phs_coeff[i][im][ip] -= 128;
-+ if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
-+ coeff.iqc_coeff)) {
-+ ath_dbg(common, ATH_DBG_CALIBRATE,
-+ "Failed in calculation of \
-+ IQ correction.\n");
-+ goto tx_iqcal_fail;
++ mutex_lock(&cfg80211_mutex);
+
+ mutex_lock(®_regdb_search_mutex);
+ while (!list_empty(®_regdb_search_list)) {
+@@ -367,9 +370,7 @@ static void reg_regdb_search(struct work
+ r = reg_copy_regd(®dom, curdom);
+ if (r)
+ break;
+- mutex_lock(&cfg80211_mutex);
+- set_regdom(regdom);
+- mutex_unlock(&cfg80211_mutex);
++ set_reg = true;
+ break;
}
-+
-+ coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
-+ coeff.phs_coeff[i][im] =
-+ (coeff.iqc_coeff[0] >> 7) & 0x7f;
-+
-+ if (coeff.mag_coeff[i][im] > 63)
-+ coeff.mag_coeff[i][im] -= 128;
-+ if (coeff.phs_coeff[i][im] > 63)
-+ coeff.phs_coeff[i][im] -= 128;
}
+@@ -377,6 +378,11 @@ static void reg_regdb_search(struct work
+ kfree(request);
}
- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
-@@ -941,6 +838,7 @@ static bool ar9003_hw_init_cal(struct at
- {
- struct ath_common *common = ath9k_hw_common(ah);
- int val;
-+ bool txiqcal_done = false;
-
- val = REG_READ(ah, AR_ENT_OTP);
- ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
-@@ -957,14 +855,22 @@ static bool ar9003_hw_init_cal(struct at
- ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
-
- /* Do Tx IQ Calibration */
-- if (AR_SREV_9485(ah))
-- ar9003_hw_tx_iq_cal_run(ah);
-- else
-- ar9003_hw_tx_iq_cal(ah);
-+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
-+ AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
-+ DELPT);
-
-- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
-- udelay(5);
-- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-+ /*
-+ * For AR9485 or later chips, TxIQ cal runs as part of
-+ * AGC calibration
-+ */
-+ if (AR_SREV_9485_OR_LATER(ah))
-+ txiqcal_done = true;
-+ else {
-+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
-+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
-+ udelay(5);
-+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-+ }
+ mutex_unlock(®_regdb_search_mutex);
++
++ if (set_reg)
++ set_regdom(regdom);
++
++ mutex_unlock(&cfg80211_mutex);
+ }
- /* Calibrate the AGC */
- REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-@@ -979,7 +885,7 @@ static bool ar9003_hw_init_cal(struct at
- return false;
+ static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -424,8 +424,8 @@ u32 ath_calcrxfilter(struct ath_softc *s
+ rfilt |= ATH9K_RX_FILTER_COMP_BAR;
+
+ if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
+- /* The following may also be needed for other older chips */
+- if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
++ /* This is needed for older chips */
++ if (sc->sc_ah->hw_version.macVersion <= AR_SREV_VERSION_9160)
+ rfilt |= ATH9K_RX_FILTER_PROM;
+ rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
}
-
-- if (AR_SREV_9485(ah))
-+ if (txiqcal_done)
- ar9003_hw_tx_iq_cal_post_proc(ah);
-
- /* Revert chainmasks to their original values before NF cal */
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-@@ -548,15 +548,12 @@
-
- #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300)
-
--#define AR_PHY_TX_IQCAL_START_9485 (AR_SM_BASE + 0x3c4)
--#define AR_PHY_TX_IQCAL_START_DO_CAL_9485 0x80000000
--#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S 31
--#define AR_PHY_TX_IQCAL_CONTROL_1_9485 (AR_SM_BASE + 0x3c8)
--#define AR_PHY_TX_IQCAL_STATUS_B0_9485 (AR_SM_BASE + 0x3f0)
--
--#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448)
--#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440)
--#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c)
-+#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \
-+ 0x3c8 : 0x448)
-+#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \
-+ 0x3c4 : 0x440)
-+#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \
-+ 0x3f0 : 0x48c)
- #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \
- (AR_SREV_9485(ah) ? \
- 0x3d0 : 0x450) + ((_i) << 2))
-@@ -758,10 +755,10 @@
- #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000
- #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
- #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004
--#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000
--#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18
--#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001
--#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0
-+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000
-+#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18
-+#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001
-+#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0
-
- #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001
- #define AR_PHY_CALIBRATED_GAINS_0 0x3e
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -453,6 +453,7 @@ void ath9k_btcoex_timer_pause(struct ath
-
- #define ATH_LED_PIN_DEF 1
- #define ATH_LED_PIN_9287 8
-+#define ATH_LED_PIN_9300 10
- #define ATH_LED_PIN_9485 6
-
- #ifdef CONFIG_MAC80211_LEDS
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -46,6 +46,8 @@ void ath_init_leds(struct ath_softc *sc)
- sc->sc_ah->led_pin = ATH_LED_PIN_9287;
- else if (AR_SREV_9485(sc->sc_ah))
- sc->sc_ah->led_pin = ATH_LED_PIN_9485;
-+ else if (AR_SREV_9300(sc->sc_ah))
-+ sc->sc_ah->led_pin = ATH_LED_PIN_9300;
- else
- sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1390,7 +1390,7 @@ static void ieee80211_set_disassoc(struc
+ sta = sta_info_get(sdata, ifmgd->bssid);
+ if (sta) {
+ set_sta_flag(sta, WLAN_STA_BLOCK_BA);
+- ieee80211_sta_tear_down_BA_sessions(sta, tx);
++ ieee80211_sta_tear_down_BA_sessions(sta, false);
}
---- a/drivers/net/wireless/ath/ath9k/reg.h
-+++ b/drivers/net/wireless/ath/ath9k/reg.h
-@@ -868,6 +868,8 @@
- #define AR_SREV_9485_11(_ah) \
- (AR_SREV_9485(_ah) && \
- ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11))
-+#define AR_SREV_9485_OR_LATER(_ah) \
-+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485))
-
- #define AR_SREV_9285E_20(_ah) \
- (AR_SREV_9285_12_OR_LATER(_ah) && \
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -652,7 +652,7 @@ static void ieee80211_sta_reorder_releas
- set_release_timer:
-
- mod_timer(&tid_agg_rx->reorder_timer,
-- tid_agg_rx->reorder_time[j] +
-+ tid_agg_rx->reorder_time[j] + 1 +
- HT_RX_REORDER_BUF_TIMEOUT);
- } else {
- del_timer(&tid_agg_rx->reorder_timer);
---- a/drivers/net/wireless/ath/ath9k/calib.c
-+++ b/drivers/net/wireless/ath/ath9k/calib.c
-@@ -69,15 +69,21 @@ static void ath9k_hw_update_nfcal_hist_b
- int16_t *nfarray)
- {
- struct ath_common *common = ath9k_hw_common(ah);
-+ struct ieee80211_conf *conf = &common->hw->conf;
- struct ath_nf_limits *limit;
- struct ath9k_nfcal_hist *h;
- bool high_nf_mid = false;
-+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
- int i;
-
- h = cal->nfCalHist;
- limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
+ mutex_unlock(&local->sta_mtx);
- for (i = 0; i < NUM_NF_READINGS; i++) {
-+ if (!(chainmask & (1 << i)) ||
-+ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
-+ continue;
-+
- h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
-
- if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
-@@ -225,6 +231,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah,
- int32_t val;
- u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
- struct ath_common *common = ath9k_hw_common(ah);
-+ struct ieee80211_conf *conf = &common->hw->conf;
- s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
-
- if (ah->caldata)
-@@ -234,6 +241,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah,
- if (chainmask & (1 << i)) {
- s16 nfval;
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -674,7 +674,7 @@ int __must_check __sta_info_destroy(stru
+ * will be sufficient.
+ */
+ set_sta_flag(sta, WLAN_STA_BLOCK_BA);
+- ieee80211_sta_tear_down_BA_sessions(sta, true);
++ ieee80211_sta_tear_down_BA_sessions(sta, false);
-+ if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
-+ continue;
-+
- if (h)
- nfval = h[i].privNF;
- else
-@@ -293,6 +303,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah,
- ENABLE_REGWRITE_BUFFER(ah);
- for (i = 0; i < NUM_NF_READINGS; i++) {
- if (chainmask & (1 << i)) {
-+ if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
-+ continue;
-+
- val = REG_READ(ah, ah->nf_regs[i]);
- val &= 0xFFFFFE00;
- val |= (((u32) (-50) << 1) & 0x1ff);
+ ret = sta_info_hash_del(local, sta);
+ if (ret)