aboutsummaryrefslogtreecommitdiffstats
path: root/package/mac80211/patches/561-mac80211_tx_status.patch
blob: 513dd0a6eca3e122e5d1481e56259df4a21f52ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2370,6 +2370,25 @@ static inline int ieee80211_sta_ps_trans
 void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
 
 /**
+ * ieee80211_tx_status_sta - transmit status callback
+ *
+ * Call this function for all transmitted frames after they have been
+ * transmitted. It is permissible to not call this function for
+ * multicast frames but this can affect statistics.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls
+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
+ * may not be mixed for a single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ * @sta: station for which the tx status is provided
+ */
+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
+			     struct ieee80211_sta *sta);
+
+/**
  * ieee80211_tx_status - transmit status callback
  *
  * Call this function for all transmitted frames after they have been
@@ -2384,8 +2403,11 @@ void ieee80211_sta_set_tim(struct ieee80
  * @hw: the hardware the frame was transmitted by
  * @skb: the frame that was transmitted, owned by mac80211 after this call
  */
-void ieee80211_tx_status(struct ieee80211_hw *hw,
-			 struct sk_buff *skb);
+static inline void ieee80211_tx_status(struct ieee80211_hw *hw,
+				       struct sk_buff *skb)
+{
+	ieee80211_tx_status_sta(hw, skb, NULL);
+}
 
 /**
  * ieee80211_tx_status_ni - transmit status callback (in process context)
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -202,7 +202,8 @@ static void ieee80211_set_bar_pending(st
  */
 #define STA_LOST_PKT_THRESHOLD	50
 
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
+			     struct ieee80211_sta *pubsta)
 {
 	struct sk_buff *skb2;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -214,7 +215,7 @@ void ieee80211_tx_status(struct ieee8021
 	struct ieee80211_tx_status_rtap_hdr *rthdr;
 	struct ieee80211_sub_if_data *sdata;
 	struct net_device *prev_dev = NULL;
-	struct sta_info *sta, *tmp;
+	struct sta_info *sta = NULL, *tmp, *tmp2;
 	int retry_count = -1, i;
 	int rates_idx = -1;
 	bool send_to_cooked;
@@ -244,11 +245,19 @@ void ieee80211_tx_status(struct ieee8021
 	sband = local->hw.wiphy->bands[info->band];
 	fc = hdr->frame_control;
 
-	for_each_sta_info(local, hdr->addr1, sta, tmp) {
-		/* skip wrong virtual interface */
-		if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
-			continue;
+	if (!pubsta) {
+		for_each_sta_info(local, hdr->addr1, tmp, tmp2) {
+			/* skip wrong virtual interface */
+			if (memcmp(hdr->addr2, tmp->sdata->vif.addr, ETH_ALEN))
+				continue;
+
+			sta = tmp;
+		}
+	} else {
+		sta = container_of(pubsta, struct sta_info, sta);
+	}
 
+	if (sta) {
 		acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
 		if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
 			/*
@@ -497,7 +506,7 @@ void ieee80211_tx_status(struct ieee8021
 	rcu_read_unlock();
 	dev_kfree_skb(skb);
 }
-EXPORT_SYMBOL(ieee80211_tx_status);
+EXPORT_SYMBOL(ieee80211_tx_status_sta);
 
 void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
 {