diff options
| -rw-r--r-- | package/mac80211/patches/300-pending_work.patch | 171 | 
1 files changed, 133 insertions, 38 deletions
diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index 6f35a07be..56f5af959 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); ++		}  + - 		acked = info->flags & IEEE80211_TX_STAT_ACK; ++		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(); ++	} ++ ++	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); +  + 	/* 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); +-	} - 	if (unlikely(info->ack_frame_id)) { ++	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  | 
