X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=package%2Fmac80211%2Fpatches%2F300-pending_work.patch;h=bd21e534058318b641ca2bcf409b195b06b8f8cc;hb=120f4d380e6afa6df6e05ff9a952b72368a12929;hp=e711ccf0b581d106d56c69ef86b1a16c2e814ce9;hpb=68ab66f3f00b188f0ff8ad1f7559bdd4b1a51094;p=openwrt.git diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index e711ccf0b5..bd21e53405 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -1,114 +1,3 @@ ---- a/drivers/net/wireless/ath/ath9k/common.h -+++ b/drivers/net/wireless/ath/ath9k/common.h -@@ -27,7 +27,7 @@ - #define WME_MAX_BA WME_BA_BMP_SIZE - #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) - --#define ATH_RSSI_DUMMY_MARKER 0x127 -+#define ATH_RSSI_DUMMY_MARKER 127 - #define ATH_RSSI_LPF_LEN 10 - #define RSSI_LPF_THRESHOLD -20 - #define ATH_RSSI_EP_MULTIPLIER (1<<7) ---- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c -+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c -@@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9 - - last_rssi = priv->rx.last_rssi; - -- if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) -- rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, -- ATH_RSSI_EP_MULTIPLIER); -+ if (ieee80211_is_beacon(hdr->frame_control) && -+ !is_zero_ether_addr(common->curbssid) && -+ ether_addr_equal(hdr->addr3, common->curbssid)) { -+ s8 rssi = rxbuf->rxstatus.rs_rssi; - -- if (rxbuf->rxstatus.rs_rssi < 0) -- rxbuf->rxstatus.rs_rssi = 0; -+ if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) -+ rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); - -- if (ieee80211_is_beacon(fc)) -- priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; -+ if (rssi < 0) -+ rssi = 0; -+ -+ priv->ah->stats.avgbrssi = rssi; -+ } - - rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); - rx_status->band = hw->conf.channel->band; ---- a/include/linux/ieee80211.h -+++ b/include/linux/ieee80211.h -@@ -185,7 +185,7 @@ struct ieee80211_hdr { - u8 addr3[6]; - __le16 seq_ctrl; - u8 addr4[6]; --} __packed; -+} __packed __aligned(2); - - struct ieee80211_hdr_3addr { - __le16 frame_control; -@@ -194,7 +194,7 @@ struct ieee80211_hdr_3addr { - u8 addr2[6]; - u8 addr3[6]; - __le16 seq_ctrl; --} __packed; -+} __packed __aligned(2); - - struct ieee80211_qos_hdr { - __le16 frame_control; -@@ -204,7 +204,7 @@ struct ieee80211_qos_hdr { - u8 addr3[6]; - __le16 seq_ctrl; - __le16 qos_ctrl; --} __packed; -+} __packed __aligned(2); - - /** - * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set -@@ -581,7 +581,7 @@ struct ieee80211s_hdr { - __le32 seqnum; - u8 eaddr1[6]; - u8 eaddr2[6]; --} __packed; -+} __packed __aligned(2); - - /* Mesh flags */ - #define MESH_FLAGS_AE_A4 0x1 -@@ -875,7 +875,7 @@ struct ieee80211_mgmt { - } u; - } __packed action; - } u; --} __packed; -+} __packed __aligned(2); - - /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ - #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 -@@ -906,20 +906,20 @@ struct ieee80211_rts { - __le16 duration; - u8 ra[6]; - u8 ta[6]; --} __packed; -+} __packed __aligned(2); - - struct ieee80211_cts { - __le16 frame_control; - __le16 duration; - u8 ra[6]; --} __packed; -+} __packed __aligned(2); - - struct ieee80211_pspoll { - __le16 frame_control; - __le16 aid; - u8 bssid[6]; - u8 ta[6]; --} __packed; -+} __packed __aligned(2); - - /* TDLS */ - --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -204,6 +204,8 @@ static void ieee80211_send_addba_resp(st @@ -142,7 +31,7 @@ --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c -@@ -65,11 +65,11 @@ static ssize_t sta_flags_read(struct fil +@@ -66,11 +66,11 @@ static ssize_t sta_flags_read(struct fil test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" int res = scnprintf(buf, sizeof(buf), @@ -156,18 +45,35 @@ 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 -@@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80 +--- a/net/mac80211/ht.c ++++ b/net/mac80211/ht.c +@@ -281,13 +281,14 @@ void ieee80211_ba_session_work(struct wo + sta, tid, WLAN_BACK_RECIPIENT, + WLAN_REASON_UNSPECIFIED, true); - lockdep_assert_held(&local->mtx); - -- active = !list_empty(&local->chanctx_list); -+ active = !list_empty(&local->chanctx_list) || local->monitors; ++ spin_lock_bh(&sta->lock); ++ + tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; + if (tid_tx) { + /* + * Assign it over to the normal tid_tx array + * where it "goes live". + */ +- spin_lock_bh(&sta->lock); + + sta->ampdu_mlme.tid_start_tx[tid] = NULL; + /* could there be a race? */ +@@ -300,6 +301,7 @@ void ieee80211_ba_session_work(struct wo + ieee80211_tx_ba_session_handle_start(sta, tid); + continue; + } ++ spin_unlock_bh(&sta->lock); - if (!local->ops->remain_on_channel) { - list_for_each_entry(roc, &local->roc_list, list) { -@@ -436,7 +436,6 @@ int ieee80211_do_open(struct wireless_de + tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -463,7 +463,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; @@ -175,17 +81,7 @@ u32 changed = 0; int res; u32 hw_reconf_flags = 0; -@@ -541,6 +540,9 @@ int ieee80211_do_open(struct wireless_de - - ieee80211_adjust_monitor_flags(sdata, 1); - ieee80211_configure_filter(local); -+ mutex_lock(&local->mtx); -+ ieee80211_recalc_idle(local); -+ mutex_unlock(&local->mtx); - - netif_carrier_on(dev); - break; -@@ -595,30 +597,8 @@ int ieee80211_do_open(struct wireless_de +@@ -629,30 +628,8 @@ int ieee80211_do_open(struct wireless_de set_bit(SDATA_STATE_RUNNING, &sdata->state); @@ -217,17 +113,7 @@ /* * set_multicast_list will be invoked by the networking core -@@ -817,6 +797,9 @@ static void ieee80211_do_stop(struct iee - - ieee80211_adjust_monitor_flags(sdata, -1); - ieee80211_configure_filter(local); -+ mutex_lock(&local->mtx); -+ ieee80211_recalc_idle(local); -+ mutex_unlock(&local->mtx); - break; - case NL80211_IFTYPE_P2P_DEVICE: - /* relies on synchronize_rcu() below */ -@@ -1022,6 +1005,72 @@ static void ieee80211_if_setup(struct ne +@@ -1116,6 +1093,74 @@ static void ieee80211_if_setup(struct ne dev->destructor = free_netdev; } @@ -243,10 +129,12 @@ + 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]; ++ enum ieee80211_band band; ++ struct ieee80211_supported_band *sband; + + rx_status = IEEE80211_SKB_RXCB(skb); ++ band = rx_status->band; ++ sband = local->hw.wiphy->bands[band]; + mgmt = (struct ieee80211_mgmt *) skb->data; + stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; + @@ -258,7 +146,7 @@ + return; + + ieee802_11_parse_elems(mgmt->u.probe_resp.variable, -+ skb->len - baselen, &elems); ++ skb->len - baselen, false, &elems); + + rates = ieee80211_sta_get_rates(local, &elems, band, NULL); + @@ -277,7 +165,7 @@ + } + + sta->last_rx = jiffies; -+ sta->sta.supp_rates[local->hw.conf.channel->band] = rates; ++ sta->sta.supp_rates[band] = rates; + + if (elems.ht_cap_elem) + ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, @@ -300,7 +188,7 @@ static void ieee80211_iface_work(struct work_struct *work) { struct ieee80211_sub_if_data *sdata = -@@ -1126,6 +1175,9 @@ static void ieee80211_iface_work(struct +@@ -1220,6 +1265,9 @@ static void ieee80211_iface_work(struct break; ieee80211_mesh_rx_queued_mgmt(sdata, skb); break; @@ -312,7 +200,7 @@ break; --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -2365,6 +2365,7 @@ ieee80211_rx_h_action(struct ieee80211_r +@@ -2369,6 +2369,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 && @@ -320,7 +208,7 @@ sdata->vif.type != NL80211_IFTYPE_ADHOC) break; -@@ -2692,14 +2693,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_ +@@ -2720,14 +2721,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_ if (!ieee80211_vif_is_mesh(&sdata->vif) && sdata->vif.type != NL80211_IFTYPE_ADHOC && @@ -338,7 +226,7 @@ break; case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): -@@ -3028,10 +3030,16 @@ static int prepare_for_handlers(struct i +@@ -3059,10 +3061,16 @@ static int prepare_for_handlers(struct i } break; case NL80211_IFTYPE_WDS: @@ -357,6 +245,16 @@ break; case NL80211_IFTYPE_P2P_DEVICE: if (!ieee80211_is_public_action(hdr, skb->len) && +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -149,6 +149,7 @@ static void cleanup_single_sta(struct st + * directly by station destruction. + */ + for (i = 0; i < IEEE80211_NUM_TIDS; i++) { ++ kfree(sta->ampdu_mlme.tid_start_tx[i]); + tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); + if (!tid_tx) + continue; --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -32,7 +32,6 @@ @@ -375,487 +273,41 @@ WLAN_STA_CLEAR_PS_FILT, WLAN_STA_MFP, WLAN_STA_BLOCK_BA, ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ie - if (local->queue_stop_reasons[q] || - (!txpending && !skb_queue_empty(&local->pending[q]))) { - if (unlikely(info->flags & -- IEEE80211_TX_INTFL_OFFCHAN_TX_OK && -- local->queue_stop_reasons[q] & -- ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { -+ IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) { -+ if (local->queue_stop_reasons[q] & -+ ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) { -+ /* -+ * Drop off-channel frames if queues -+ * are stopped for any reason other -+ * than off-channel operation. Never -+ * queue them. -+ */ -+ spin_unlock_irqrestore( -+ &local->queue_stop_reason_lock, -+ flags); -+ ieee80211_purge_tx_queue(&local->hw, -+ skbs); -+ return true; -+ } -+ } else { -+ - /* -- * Drop off-channel frames if queues are stopped -- * for any reason other than off-channel -- * operation. Never queue them. -+ * Since queue is stopped, queue up frames for -+ * later transmission from the tx-pending -+ * tasklet when the queue is woken again. - */ -- spin_unlock_irqrestore( -- &local->queue_stop_reason_lock, flags); -- ieee80211_purge_tx_queue(&local->hw, skbs); -- return true; -+ if (txpending) -+ skb_queue_splice_init(skbs, -+ &local->pending[q]); -+ else -+ skb_queue_splice_tail_init(skbs, -+ &local->pending[q]); -+ -+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, -+ flags); -+ return false; - } -- -- /* -- * Since queue is stopped, queue up frames for later -- * transmission from the tx-pending tasklet when the -- * queue is woken again. -- */ -- if (txpending) -- skb_queue_splice_init(skbs, &local->pending[q]); -- else -- skb_queue_splice_tail_init(skbs, -- &local->pending[q]); -- -- spin_unlock_irqrestore(&local->queue_stop_reason_lock, -- flags); -- return false; - } - spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); - -@@ -1848,9 +1854,24 @@ netdev_tx_t ieee80211_subif_start_xmit(s - } - - if (!is_multicast_ether_addr(skb->data)) { -+ struct sta_info *next_hop; -+ bool mpp_lookup = true; -+ - mpath = mesh_path_lookup(sdata, skb->data); -- if (!mpath) -+ if (mpath) { -+ mpp_lookup = false; -+ next_hop = rcu_dereference(mpath->next_hop); -+ if (!next_hop || -+ !(mpath->flags & (MESH_PATH_ACTIVE | -+ MESH_PATH_RESOLVING))) -+ mpp_lookup = true; -+ } -+ -+ if (mpp_lookup) - mppath = mpp_path_lookup(sdata, skb->data); -+ -+ if (mppath && mpath) -+ mesh_path_del(mpath->sdata, mpath->dst); - } - - /* ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -554,16 +554,9 @@ static int nl80211_msg_put_channel(struc - if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) - goto nla_put_failure; -- if (chan->flags & IEEE80211_CHAN_RADAR) { -- u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered); -- if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) -- goto nla_put_failure; -- if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, -- chan->dfs_state)) -- goto nla_put_failure; -- if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time)) -- goto nla_put_failure; -- } -+ if ((chan->flags & IEEE80211_CHAN_RADAR) && -+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) -+ goto nla_put_failure; - if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) - goto nla_put_failure; -@@ -900,9 +893,6 @@ static int nl80211_put_iface_combination - nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, - c->max_interfaces)) - goto nla_put_failure; -- if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, -- c->radar_detect_widths)) -- goto nla_put_failure; - - nla_nest_end(msg, nl_combi); - } -@@ -914,48 +904,6 @@ nla_put_failure: - return -ENOBUFS; - } - --#ifdef CONFIG_PM --static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, -- struct sk_buff *msg) --{ -- const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp; -- struct nlattr *nl_tcp; -- -- if (!tcp) -- return 0; -- -- nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION); -- if (!nl_tcp) -- return -ENOBUFS; -- -- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, -- tcp->data_payload_max)) -- return -ENOBUFS; -- -- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, -- tcp->data_payload_max)) -- return -ENOBUFS; -- -- if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ)) -- return -ENOBUFS; -- -- if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, -- sizeof(*tcp->tok), tcp->tok)) -- return -ENOBUFS; -- -- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL, -- tcp->data_interval_max)) -- return -ENOBUFS; -- -- if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD, -- tcp->wake_payload_max)) -- return -ENOBUFS; -- -- nla_nest_end(msg, nl_tcp); -- return 0; --} --#endif -- - static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, - struct cfg80211_registered_device *dev) - { -@@ -1330,9 +1278,6 @@ static int nl80211_send_wiphy(struct sk_ - goto nla_put_failure; - } - -- if (nl80211_send_wowlan_tcp_caps(dev, msg)) -- goto nla_put_failure; -- - nla_nest_end(msg, nl_wowlan); - } - #endif ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -3285,13 +3285,19 @@ static int ieee80211_cfg_get_channel(str - struct cfg80211_chan_def *chandef) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); -+ struct ieee80211_local *local = wiphy_priv(wiphy); - struct ieee80211_chanctx_conf *chanctx_conf; - int ret = -ENODATA; - - rcu_read_lock(); -- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); -- if (chanctx_conf) { -- *chandef = chanctx_conf->def; -+ if (local->use_chanctx) { -+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); -+ if (chanctx_conf) { -+ *chandef = chanctx_conf->def; -+ ret = 0; -+ } -+ } else if (local->open_count == local->monitors) { -+ *chandef = local->monitor_chandef; - ret = 0; - } - rcu_read_unlock(); ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct a - reset_type = ATH9K_RESET_POWER_ON; - else - reset_type = ATH9K_RESET_COLD; -- } -+ } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || -+ (REG_READ(ah, AR_CR) & AR_CR_RXE)) -+ reset_type = ATH9K_RESET_COLD; - - if (!ath9k_hw_set_reset_reg(ah, reset_type)) - return false; ---- a/drivers/net/wireless/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c -@@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_comb - */ - if_limit = &rt2x00dev->if_limits_ap; - if_limit->max = rt2x00dev->ops->max_ap_intf; -- if_limit->types = BIT(NL80211_IFTYPE_AP) | -- BIT(NL80211_IFTYPE_MESH_POINT); -+ if_limit->types = BIT(NL80211_IFTYPE_AP); -+#ifdef CONFIG_MAC80211_MESH -+ if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); -+#endif - - /* - * Build up AP interface combinations structure. -@@ -1309,7 +1311,9 @@ int rt2x00lib_probe_dev(struct rt2x00_de - rt2x00dev->hw->wiphy->interface_modes |= - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | -+#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -+#endif - BIT(NL80211_IFTYPE_WDS); - - rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -26,11 +26,11 @@ - /* Number of symbols for a packet with (bps) bits per symbol */ - #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) - --/* Transmission time for a packet containing (syms) symbols */ -+/* Transmission time (nanoseconds) for a packet containing (syms) symbols */ - #define MCS_SYMBOL_TIME(sgi, syms) \ - (sgi ? \ -- ((syms) * 18 + 4) / 5 : /* syms * 3.6 us */ \ -- (syms) << 2 /* syms * 4 us */ \ -+ ((syms) * 18000 + 4000) / 5 : /* syms * 3.6 us */ \ -+ ((syms) * 1000) << 2 /* syms * 4 us */ \ - ) - - /* Transmit duration for the raw data part of an average sized packet */ -@@ -64,9 +64,9 @@ - } - - #define CCK_DURATION(_bitrate, _short, _len) \ -- (10 /* SIFS */ + \ -+ (1000 * (10 /* SIFS */ + \ - (_short ? 72 + 24 : 144 + 48 ) + \ -- (8 * (_len + 4) * 10) / (_bitrate)) -+ (8 * (_len + 4) * 10) / (_bitrate))) - - #define CCK_ACK_DURATION(_bitrate, _short) \ - (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ -@@ -211,7 +211,8 @@ static void - minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) - { - struct minstrel_rate_stats *mr; -- unsigned int usecs = 0; -+ unsigned int nsecs = 0; -+ unsigned int tp; - - mr = &mi->groups[group].rates[rate]; - -@@ -221,10 +222,12 @@ minstrel_ht_calc_tp(struct minstrel_ht_s - } - - if (group != MINSTREL_CCK_GROUP) -- usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); -+ nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); - -- usecs += minstrel_mcs_groups[group].duration[rate]; -- mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability); -+ nsecs += minstrel_mcs_groups[group].duration[rate]; -+ tp = 1000000 * ((mr->probability * 1000) / nsecs); -+ -+ mr->cur_tp = MINSTREL_TRUNC(tp); - } - - /* -@@ -308,8 +311,8 @@ minstrel_ht_update_stats(struct minstrel - } - } - -- /* try to sample up to half of the available rates during each interval */ -- mi->sample_count *= 4; -+ /* try to sample all available rates during each interval */ -+ mi->sample_count *= 8; - - cur_prob = 0; - cur_prob_tp = 0; -@@ -320,20 +323,13 @@ minstrel_ht_update_stats(struct minstrel - if (!mg->supported) - continue; - -- mr = minstrel_get_ratestats(mi, mg->max_prob_rate); -- if (cur_prob_tp < mr->cur_tp && -- minstrel_mcs_groups[group].streams == 1) { -- mi->max_prob_rate = mg->max_prob_rate; -- cur_prob = mr->cur_prob; -- cur_prob_tp = mr->cur_tp; -- } -- - mr = minstrel_get_ratestats(mi, mg->max_tp_rate); - if (cur_tp < mr->cur_tp) { - mi->max_tp_rate2 = mi->max_tp_rate; - cur_tp2 = cur_tp; - mi->max_tp_rate = mg->max_tp_rate; - cur_tp = mr->cur_tp; -+ mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1; - } - - mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); -@@ -343,6 +339,23 @@ minstrel_ht_update_stats(struct minstrel - } +@@ -203,6 +201,7 @@ struct tid_ampdu_rx { + * driver requested to close until the work for it runs + * @mtx: mutex to protect all TX data (except non-NULL assignments + * to tid_tx[idx], which are protected by the sta spinlock) ++ * tid_start_tx is also protected by sta->lock. + */ + struct sta_ampdu_mlme { + struct mutex mtx; +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -1778,9 +1778,13 @@ static void ath_tx_txqaddbuf(struct ath_ } -+ if (mi->max_prob_streams < 1) -+ mi->max_prob_streams = 1; + if (!internal) { +- txq->axq_depth++; +- if (bf_is_ampdu_not_probing(bf)) +- txq->axq_ampdu_depth++; ++ while (bf) { ++ txq->axq_depth++; ++ if (bf_is_ampdu_not_probing(bf)) ++ txq->axq_ampdu_depth++; + -+ for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { -+ mg = &mi->groups[group]; -+ if (!mg->supported) -+ continue; -+ mr = minstrel_get_ratestats(mi, mg->max_prob_rate); -+ if (cur_prob_tp < mr->cur_tp && -+ minstrel_mcs_groups[group].streams <= mi->max_prob_streams) { -+ mi->max_prob_rate = mg->max_prob_rate; -+ cur_prob = mr->cur_prob; -+ cur_prob_tp = mr->cur_tp; ++ bf = bf->bf_lastbf->bf_next; + } -+ } -+ -+ - mi->stats_update = jiffies; - } - -@@ -467,7 +480,7 @@ minstrel_ht_tx_status(void *priv, struct - - if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { - mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); -- mi->sample_tries = 2; -+ mi->sample_tries = 1; - mi->sample_count--; } - -@@ -536,7 +549,7 @@ minstrel_calc_retransmit(struct minstrel - mr->retry_updated = true; - - group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; -- tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; -+ tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000; - - /* Contention time for first 2 tries */ - ctime = (t_slot * cw) >> 1; -@@ -616,6 +629,7 @@ minstrel_get_sample_rate(struct minstrel - { - struct minstrel_rate_stats *mr; - struct minstrel_mcs_group_data *mg; -+ unsigned int sample_dur, sample_group; - int sample_idx = 0; - - if (mi->sample_wait > 0) { -@@ -626,11 +640,11 @@ minstrel_get_sample_rate(struct minstrel - if (!mi->sample_tries) - return -1; - -- mi->sample_tries--; - mg = &mi->groups[mi->sample_group]; - sample_idx = sample_table[mg->column][mg->index]; - mr = &mg->rates[sample_idx]; -- sample_idx += mi->sample_group * MCS_GROUP_RATES; -+ sample_group = mi->sample_group; -+ sample_idx += sample_group * MCS_GROUP_RATES; - minstrel_next_sample_idx(mi); - - /* -@@ -651,14 +665,18 @@ minstrel_get_sample_rate(struct minstrel - * Make sure that lower rates get sampled only occasionally, - * if the link is working perfectly. - */ -- if (minstrel_get_duration(sample_idx) > -- minstrel_get_duration(mi->max_tp_rate)) { -+ sample_dur = minstrel_get_duration(sample_idx); -+ if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) && -+ (mi->max_prob_streams < -+ minstrel_mcs_groups[sample_group].streams || -+ sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { - if (mr->sample_skipped < 20) - return -1; - - if (mi->sample_slow++ > 2) - return -1; - } -+ mi->sample_tries--; - - return sample_idx; } ---- a/net/mac80211/rc80211_minstrel_ht.h -+++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -85,6 +85,7 @@ struct minstrel_ht_sta { - - /* best probability rate */ - unsigned int max_prob_rate; -+ unsigned int max_prob_streams; - - /* time of last status update */ - unsigned long stats_update; ---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c -@@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct at - AR_PHY_AGC_CONTROL_FLTR_CAL | - AR_PHY_AGC_CONTROL_PKDET_CAL; - -+ /* Use chip chainmask only for calibration */ - ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); - - if (rtt) { -@@ -1150,6 +1151,9 @@ skip_tx_iqcal: - ar9003_hw_rtt_disable(ah); - } - -+ /* Revert chainmask to runtime parameters */ -+ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); -+ - /* Initialize list pointers */ - ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; ---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c -@@ -3606,6 +3606,12 @@ static void ar9003_hw_ant_ctrl_apply(str - value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); - REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); +--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +@@ -1183,7 +1183,7 @@ static int ath9k_htc_config(struct ieee8 + mutex_lock(&priv->htc_pm_lock); -+ if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { -+ value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); -+ REG_RMW_FIELD(ah, switch_chain_reg[0], -+ AR_SWITCH_TABLE_ALL, value); -+ } -+ - for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if ((ah->rxchainmask & BIT(chain)) || - (ah->txchainmask & BIT(chain))) { -@@ -3772,6 +3778,17 @@ static void ar9003_hw_atten_apply(struct - AR_PHY_EXT_ATTEN_CTL_2, - }; + priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); +- if (priv->ps_idle) ++ if (!priv->ps_idle) + chip_reset = true; -+ if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) { -+ value = ar9003_hw_atten_chain_get(ah, 1, chan); -+ REG_RMW_FIELD(ah, ext_atten_reg[0], -+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); -+ -+ value = ar9003_hw_atten_chain_get_margin(ah, 1, chan); -+ REG_RMW_FIELD(ah, ext_atten_reg[0], -+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, -+ value); -+ } -+ - /* Test value. if 0 then attenuation is unused. Don't load anything. */ - for (i = 0; i < 3; i++) { - if (ah->txchainmask & BIT(i)) { + mutex_unlock(&priv->htc_pm_lock);