X-Git-Url: https://git.archive.openwrt.org/?p=openwrt.git;a=blobdiff_plain;f=package%2Fmac80211%2Fpatches%2F300-pending_work.patch;h=56f5af959b8de81cfda2314e5c3d34f49a045899;hp=f7a0aede533607339ff565ad19e405b1584ec924;hb=ccecd7e02326b661a07b090ba457d74666776c00;hpb=e3b2ecffb6e1a627f89931d64951fca496aa169d diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index f7a0aede53..56f5af959b 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -257,14 +257,90 @@ WLAN_STA_BLOCK_BA, --- a/net/mac80211/status.c +++ b/net/mac80211/status.c -@@ -517,29 +517,41 @@ void ieee80211_tx_status(struct ieee8021 +@@ -324,6 +324,75 @@ static void ieee80211_add_tx_radiotap_he - if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { - u64 cookie = (unsigned long)skb; -+ bool found = false; + } + ++static void ieee80211_report_used_skb(struct ieee80211_local *local, ++ struct sk_buff *skb, bool dropped) ++{ ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_hdr *hdr = (void *)skb->data; ++ bool acked = info->flags & IEEE80211_TX_STAT_ACK; ++ ++ if (dropped) ++ acked = false; ++ ++ if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { ++ struct ieee80211_sub_if_data *sdata = NULL; ++ struct ieee80211_sub_if_data *iter_sdata; ++ u64 cookie = (unsigned long)skb; ++ ++ rcu_read_lock(); ++ ++ if (skb->dev) { ++ list_for_each_entry_rcu(iter_sdata, &local->interfaces, ++ list) { ++ if (!iter_sdata->dev) ++ continue; ++ ++ if (skb->dev == iter_sdata->dev) { ++ sdata = iter_sdata; ++ break; ++ } ++ } ++ } else { ++ sdata = rcu_dereference(local->p2p_sdata); ++ } ++ ++ if (!sdata) ++ 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(); ++ } + - acked = info->flags & IEEE80211_TX_STAT_ACK; ++ if (unlikely(info->ack_frame_id)) { ++ struct sk_buff *ack_skb; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&local->ack_status_lock, flags); ++ ack_skb = idr_find(&local->ack_status_frames, ++ info->ack_frame_id); ++ if (ack_skb) ++ idr_remove(&local->ack_status_frames, ++ info->ack_frame_id); ++ spin_unlock_irqrestore(&local->ack_status_lock, flags); ++ ++ if (ack_skb) { ++ if (!dropped) { ++ /* consumes ack_skb */ ++ skb_complete_wifi_ack(ack_skb, acked); ++ } else { ++ dev_kfree_skb_any(ack_skb); ++ } ++ } ++ } ++} ++ + /* + * Use a static threshold for now, best value to be determined + * by testing ... +@@ -515,50 +584,7 @@ void ieee80211_tx_status(struct ieee8021 + msecs_to_jiffies(10)); + } +- if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { +- u64 cookie = (unsigned long)skb; +- 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, @@ -275,13 +351,9 @@ - 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; - +- - p2p_sdata = rcu_dereference(local->p2p_sdata); - if (p2p_sdata) { - cfg80211_mgmt_tx_status( @@ -289,34 +361,57 @@ - skb->len, acked, GFP_ATOMIC); - } - rcu_read_unlock(); -+ if (skb->dev != sdata->dev) -+ continue; -+ -+ found = true; -+ break; - } -+ -+ if (!skb->dev) { -+ sdata = rcu_dereference(local->p2p_sdata); -+ if (sdata) -+ found = 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(); - } +- } +- } +- +- if (unlikely(info->ack_frame_id)) { +- struct sk_buff *ack_skb; +- unsigned long flags; +- +- spin_lock_irqsave(&local->ack_status_lock, flags); +- ack_skb = idr_find(&local->ack_status_frames, +- info->ack_frame_id); +- if (ack_skb) +- idr_remove(&local->ack_status_frames, +- info->ack_frame_id); +- spin_unlock_irqrestore(&local->ack_status_lock, flags); +- +- /* consumes ack_skb */ +- if (ack_skb) +- skb_complete_wifi_ack(ack_skb, +- info->flags & IEEE80211_TX_STAT_ACK); +- } ++ ieee80211_report_used_skb(local, skb, false); - if (unlikely(info->ack_frame_id)) { + /* this was a transmitted frame, but now we want to reuse it */ + skb_orphan(skb); +@@ -634,25 +660,8 @@ EXPORT_SYMBOL(ieee80211_report_low_ack); + void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) + { + struct ieee80211_local *local = hw_to_local(hw); +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +- +- if (unlikely(info->ack_frame_id)) { +- struct sk_buff *ack_skb; +- unsigned long flags; +- +- spin_lock_irqsave(&local->ack_status_lock, flags); +- ack_skb = idr_find(&local->ack_status_frames, +- info->ack_frame_id); +- if (ack_skb) +- idr_remove(&local->ack_status_frames, +- info->ack_frame_id); +- spin_unlock_irqrestore(&local->ack_status_lock, flags); +- +- /* consumes ack_skb */ +- if (ack_skb) +- dev_kfree_skb_any(ack_skb); +- } + ++ ieee80211_report_used_skb(local, skb, true); + dev_kfree_skb_any(skb); + } + EXPORT_SYMBOL(ieee80211_free_txskb); --- 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 @@ -510,6 +605,29 @@ ieee80211_bss_info_change_notify(sdata, changed); } +@@ -3526,6 +3572,7 @@ int ieee80211_mgd_deauth(struct ieee8021 + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + u8 frame_buf[DEAUTH_DISASSOC_LEN]; ++ bool tx = !req->local_state_change; + + mutex_lock(&ifmgd->mtx); + +@@ -3542,12 +3589,12 @@ int ieee80211_mgd_deauth(struct ieee8021 + if (ifmgd->associated && + ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { + ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, +- req->reason_code, true, frame_buf); ++ req->reason_code, tx, frame_buf); + } else { + drv_mgd_prepare_tx(sdata->local, sdata); + ieee80211_send_deauth_disassoc(sdata, req->bssid, + IEEE80211_STYPE_DEAUTH, +- req->reason_code, true, ++ req->reason_code, tx, + frame_buf); + } + --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -674,7 +674,7 @@ int __must_check __sta_info_destroy(stru @@ -590,3 +708,69 @@ if (local->user_power_level >= 0) power = min(power, local->user_power_level); +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request { + const u8 *ie; + size_t ie_len; + u16 reason_code; ++ bool local_state_change; + }; + + /** +--- a/net/wireless/mlme.c ++++ b/net/wireless/mlme.c +@@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg802 + .reason_code = reason, + .ie = ie, + .ie_len = ie_len, ++ .local_state_change = local_state_change, + }; + + ASSERT_WDEV_LOCK(wdev); + +- if (local_state_change) { +- if (wdev->current_bss && +- ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { +- cfg80211_unhold_bss(wdev->current_bss); +- cfg80211_put_bss(&wdev->current_bss->pub); +- wdev->current_bss = NULL; +- } +- ++ if (local_state_change && (!wdev->current_bss || ++ !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) + return 0; +- } + + return rdev->ops->deauth(&rdev->wiphy, dev, &req); + } +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -386,7 +386,7 @@ static void ath_tx_complete_aggr(struct + u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; + u32 ba[WME_BA_BMP_SIZE >> 5]; + int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; +- bool rc_update = true; ++ bool rc_update = true, isba; + struct ieee80211_tx_rate rates[4]; + struct ath_frame_info *fi; + int nframes; +@@ -430,13 +430,17 @@ static void ath_tx_complete_aggr(struct + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + tid = ATH_AN_2_TID(an, tidno); + seq_first = tid->seq_start; ++ isba = ts->ts_flags & ATH9K_TX_BA; + + /* + * The hardware occasionally sends a tx status for the wrong TID. + * In this case, the BA status cannot be considered valid and all + * subframes need to be retransmitted ++ * ++ * Only BlockAcks have a TID and therefore normal Acks cannot be ++ * checked + */ +- if (tidno != ts->tid) ++ if (isba && tidno != ts->tid) + txok = false; + + isaggr = bf_isaggr(bf);