ath5k: fix spontaneus AR5312 freezes
[openwrt.git] / package / kernel / mac80211 / patches / 318-mac80211-add-ieee80211_tx_status_noskb.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Sat, 15 Nov 2014 23:50:27 +0100
3 Subject: [PATCH] mac80211: add ieee80211_tx_status_noskb
4
5 This can be used by drivers that cannot reliably map tx status
6 information onto specific skbs.
7
8 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
9 ---
10
11 --- a/include/net/mac80211.h
12 +++ b/include/net/mac80211.h
13 @@ -3517,6 +3517,28 @@ void ieee80211_tx_status(struct ieee8021
14                          struct sk_buff *skb);
15  
16  /**
17 + * ieee80211_tx_status_noskb - transmit status callback without skb
18 + *
19 + * This function can be used as a replacement for ieee80211_tx_status
20 + * in drivers that cannot reliably map tx status information back to
21 + * specific skbs.
22 + *
23 + * This function may not be called in IRQ context. Calls to this function
24 + * for a single hardware must be synchronized against each other. Calls
25 + * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
26 + * may not be mixed for a single hardware. Must not run concurrently with
27 + * ieee80211_rx() or ieee80211_rx_ni().
28 + *
29 + * @hw: the hardware the frame was transmitted by
30 + * @sta: the receiver station to which this packet is sent
31 + *     (NULL for multicast packets)
32 + * @info: tx status information
33 + */
34 +void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
35 +                              struct ieee80211_sta *sta,
36 +                              struct ieee80211_tx_info *info);
37 +
38 +/**
39   * ieee80211_tx_status_ni - transmit status callback (in process context)
40   *
41   * Like ieee80211_tx_status() but can be called in process context.
42 --- a/net/mac80211/rate.h
43 +++ b/net/mac80211/rate.h
44 @@ -49,6 +49,23 @@ static inline void rate_control_tx_statu
45  }
46  
47  
48 +static inline void
49 +rate_control_tx_status_noskb(struct ieee80211_local *local,
50 +                            struct ieee80211_supported_band *sband,
51 +                            struct sta_info *sta,
52 +                            struct ieee80211_tx_info *info)
53 +{
54 +       struct rate_control_ref *ref = local->rate_ctrl;
55 +       struct ieee80211_sta *ista = &sta->sta;
56 +       void *priv_sta = sta->rate_ctrl_priv;
57 +
58 +       if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
59 +               return;
60 +
61 +       ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
62 +}
63 +
64 +
65  static inline void rate_control_rate_init(struct sta_info *sta)
66  {
67         struct ieee80211_local *local = sta->sdata->local;
68 --- a/net/mac80211/status.c
69 +++ b/net/mac80211/status.c
70 @@ -541,10 +541,9 @@ static void ieee80211_tx_latency_end_msr
71  #define STA_LOST_TDLS_PKT_THRESHOLD    10
72  #define STA_LOST_TDLS_PKT_TIME         (10*HZ) /* 10secs since last ACK */
73  
74 -static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
75 +static void ieee80211_lost_packet(struct sta_info *sta,
76 +                                 struct ieee80211_tx_info *info)
77  {
78 -       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
79 -
80         /* This packet was aggregated but doesn't carry status info */
81         if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
82             !(info->flags & IEEE80211_TX_STAT_AMPDU))
83 @@ -571,24 +570,13 @@ static void ieee80211_lost_packet(struct
84         sta->lost_packets = 0;
85  }
86  
87 -void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
88 +static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
89 +                                 struct ieee80211_tx_info *info,
90 +                                 int *retry_count)
91  {
92 -       struct sk_buff *skb2;
93 -       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
94 -       struct ieee80211_local *local = hw_to_local(hw);
95 -       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
96 -       __le16 fc;
97 -       struct ieee80211_supported_band *sband;
98 -       struct ieee80211_sub_if_data *sdata;
99 -       struct net_device *prev_dev = NULL;
100 -       struct sta_info *sta, *tmp;
101 -       int retry_count = -1, i;
102         int rates_idx = -1;
103 -       bool send_to_cooked;
104 -       bool acked;
105 -       struct ieee80211_bar *bar;
106 -       int rtap_len;
107 -       int shift = 0;
108 +       int count = -1;
109 +       int i;
110  
111         for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
112                 if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
113 @@ -606,12 +594,94 @@ void ieee80211_tx_status(struct ieee8021
114                         break;
115                 }
116  
117 -               retry_count += info->status.rates[i].count;
118 +               count += info->status.rates[i].count;
119         }
120         rates_idx = i - 1;
121  
122 -       if (retry_count < 0)
123 -               retry_count = 0;
124 +       if (count < 0)
125 +               count = 0;
126 +
127 +       *retry_count = count;
128 +       return rates_idx;
129 +}
130 +
131 +void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
132 +                              struct ieee80211_sta *pubsta,
133 +                              struct ieee80211_tx_info *info)
134 +{
135 +       struct ieee80211_local *local = hw_to_local(hw);
136 +       struct ieee80211_supported_band *sband;
137 +       int retry_count;
138 +       int rates_idx;
139 +       bool acked;
140 +
141 +       rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
142 +
143 +       sband = hw->wiphy->bands[info->band];
144 +
145 +       acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
146 +       if (pubsta) {
147 +               struct sta_info *sta;
148 +
149 +               sta = container_of(pubsta, struct sta_info, sta);
150 +
151 +               if (info->flags & IEEE80211_TX_STATUS_EOSP)
152 +                       clear_sta_flag(sta, WLAN_STA_SP);
153 +
154 +               if (!acked)
155 +                       sta->tx_retry_failed++;
156 +               sta->tx_retry_count += retry_count;
157 +
158 +               if (acked) {
159 +                       sta->last_rx = jiffies;
160 +
161 +                       if (sta->lost_packets)
162 +                               sta->lost_packets = 0;
163 +
164 +                       /* Track when last TDLS packet was ACKed */
165 +                       if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
166 +                               sta->last_tdls_pkt_time = jiffies;
167 +               } else {
168 +                       ieee80211_lost_packet(sta, info);
169 +               }
170 +
171 +               rate_control_tx_status_noskb(local, sband, sta, info);
172 +       }
173 +
174 +       if (acked) {
175 +                   local->dot11TransmittedFrameCount++;
176 +                   if (!pubsta)
177 +                           local->dot11MulticastTransmittedFrameCount++;
178 +                   if (retry_count > 0)
179 +                           local->dot11RetryCount++;
180 +                   if (retry_count > 1)
181 +                           local->dot11MultipleRetryCount++;
182 +       } else {
183 +               local->dot11FailedCount++;
184 +       }
185 +}
186 +EXPORT_SYMBOL(ieee80211_tx_status_noskb);
187 +
188 +void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
189 +{
190 +       struct sk_buff *skb2;
191 +       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
192 +       struct ieee80211_local *local = hw_to_local(hw);
193 +       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
194 +       __le16 fc;
195 +       struct ieee80211_supported_band *sband;
196 +       struct ieee80211_sub_if_data *sdata;
197 +       struct net_device *prev_dev = NULL;
198 +       struct sta_info *sta, *tmp;
199 +       int retry_count;
200 +       int rates_idx;
201 +       bool send_to_cooked;
202 +       bool acked;
203 +       struct ieee80211_bar *bar;
204 +       int rtap_len;
205 +       int shift = 0;
206 +
207 +       rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
208  
209         rcu_read_lock();
210  
211 @@ -716,7 +786,7 @@ void ieee80211_tx_status(struct ieee8021
212                                 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
213                                         sta->last_tdls_pkt_time = jiffies;
214                         } else {
215 -                               ieee80211_lost_packet(sta, skb);
216 +                               ieee80211_lost_packet(sta, info);
217                         }
218                 }
219