mac80211: update to 2011-11-15 from trunk
[openwrt-10.03/.git] / package / mac80211 / patches / 551-ath9k_per_chain_signal_strength.patch
1 --- a/include/net/mac80211.h
2 +++ b/include/net/mac80211.h
3 @@ -684,6 +684,9 @@ enum mac80211_rx_flags {
4   * @mactime: value in microseconds of the 64-bit Time Synchronization Function
5   *     (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
6   * @band: the active band when this frame was received
7 + * @chains: bitmask of receive chains for which separate signal strength
8 + *     values were filled.
9 + * @chain_signal: per-chain signal strength, same format as @signal
10   * @freq: frequency the radio was tuned to when receiving this frame, in MHz
11   * @signal: signal strength when receiving this frame, either in dBm, in dB or
12   *     unspecified depending on the hardware capabilities flags
13 @@ -697,6 +700,10 @@ enum mac80211_rx_flags {
14  struct ieee80211_rx_status {
15         u64 mactime;
16         enum ieee80211_band band;
17 +
18 +       u8 chains;
19 +       s8 chain_signal[4];
20 +
21         int freq;
22         int signal;
23         int antenna;
24 --- a/net/mac80211/sta_info.h
25 +++ b/net/mac80211/sta_info.h
26 @@ -302,6 +302,11 @@ struct sta_info {
27         unsigned long rx_dropped;
28         int last_signal;
29         struct ewma avg_signal;
30 +
31 +       u8 chains;
32 +       s8 chain_signal_last[4];
33 +       struct ewma chain_signal_avg[4];
34 +
35         /* Plus 1 for non-QoS frames */
36         __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1];
37  
38 --- a/net/mac80211/rx.c
39 +++ b/net/mac80211/rx.c
40 @@ -1267,6 +1267,7 @@ ieee80211_rx_h_sta_process(struct ieee80
41         struct sk_buff *skb = rx->skb;
42         struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
43         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
44 +       int i;
45  
46         if (!sta)
47                 return RX_CONTINUE;
48 @@ -1309,6 +1310,19 @@ ieee80211_rx_h_sta_process(struct ieee80
49         sta->last_signal = status->signal;
50         ewma_add(&sta->avg_signal, -status->signal);
51  
52 +       if (status->chains) {
53 +               sta->chains = status->chains;
54 +               for (i = 0; i < 4; i++) {
55 +                       int signal = status->chain_signal[i];
56 +
57 +                       if (!(status->chains & BIT(i)))
58 +                               continue;
59 +
60 +                       sta->chain_signal_last[i] = signal;
61 +                       ewma_add(&sta->chain_signal_avg[i], -signal);
62 +               }
63 +       }
64 +
65         /*
66          * Change STA power saving mode only at the end of a frame
67          * exchange sequence.
68 --- a/net/mac80211/sta_info.c
69 +++ b/net/mac80211/sta_info.c
70 @@ -304,6 +304,8 @@ struct sta_info *sta_info_alloc(struct i
71         do_posix_clock_monotonic_gettime(&uptime);
72         sta->last_connected = uptime.tv_sec;
73         ewma_init(&sta->avg_signal, 1024, 8);
74 +       for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
75 +               ewma_init(&sta->chain_signal_avg[i], 1024, 8);
76  
77         if (sta_prepare_rate_control(local, sta, gfp)) {
78                 kfree(sta);
79 --- a/include/net/cfg80211.h
80 +++ b/include/net/cfg80211.h
81 @@ -505,6 +505,8 @@ struct station_parameters {
82   * @STATION_INFO_CONNECTED_TIME: @connected_time filled
83   * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled
84   * @STATION_INFO_STA_FLAGS: @sta_flags filled
85 + * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
86 + * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
87   */
88  enum station_info_flags {
89         STATION_INFO_INACTIVE_TIME      = 1<<0,
90 @@ -525,7 +527,9 @@ enum station_info_flags {
91         STATION_INFO_BSS_PARAM          = 1<<15,
92         STATION_INFO_CONNECTED_TIME     = 1<<16,
93         STATION_INFO_ASSOC_REQ_IES      = 1<<17,
94 -       STATION_INFO_STA_FLAGS          = 1<<18
95 +       STATION_INFO_STA_FLAGS          = 1<<18,
96 +       STATION_INFO_CHAIN_SIGNAL       = 1<<19,
97 +       STATION_INFO_CHAIN_SIGNAL_AVG   = 1<<20,
98  };
99  
100  /**
101 @@ -605,6 +609,9 @@ struct sta_bss_parameters {
102   * @plink_state: mesh peer link state
103   * @signal: signal strength of last received packet in dBm
104   * @signal_avg: signal strength average in dBm
105 + * @chains: bitmask for filled values in @chain_signal, @chain_signal_avg
106 + * @chain_signal: per-chain signal strength of last received packet in dBm
107 + * @chain_signal_avg: per-chain signal strength average in dBm
108   * @txrate: current unicast bitrate from this station
109   * @rxrate: current unicast bitrate to this station
110   * @rx_packets: packets received from this station
111 @@ -635,6 +642,11 @@ struct station_info {
112         u8 plink_state;
113         s8 signal;
114         s8 signal_avg;
115 +
116 +       u8 chains;
117 +       s8 chain_signal[4];
118 +       s8 chain_signal_avg[4];
119 +
120         struct rate_info txrate;
121         struct rate_info rxrate;
122         u32 rx_packets;
123 --- a/drivers/net/wireless/ath/ath9k/mac.h
124 +++ b/drivers/net/wireless/ath/ath9k/mac.h
125 @@ -133,12 +133,8 @@ struct ath_rx_status {
126         u8 rs_rate;
127         u8 rs_antenna;
128         u8 rs_more;
129 -       int8_t rs_rssi_ctl0;
130 -       int8_t rs_rssi_ctl1;
131 -       int8_t rs_rssi_ctl2;
132 -       int8_t rs_rssi_ext0;
133 -       int8_t rs_rssi_ext1;
134 -       int8_t rs_rssi_ext2;
135 +       int8_t rs_rssi_ctl[3];
136 +       int8_t rs_rssi_ext[3];
137         u8 rs_isaggr;
138         u8 rs_moreaggr;
139         u8 rs_num_delims;
140 --- a/drivers/net/wireless/ath/ath9k/recv.c
141 +++ b/drivers/net/wireless/ath/ath9k/recv.c
142 @@ -981,6 +981,7 @@ static int ath9k_rx_skb_preprocess(struc
143                                    bool *decrypt_error)
144  {
145         struct ath_hw *ah = common->ah;
146 +       int i, j;
147  
148         memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
149  
150 @@ -1006,6 +1007,20 @@ static int ath9k_rx_skb_preprocess(struc
151         rx_status->antenna = rx_stats->rs_antenna;
152         rx_status->flag |= RX_FLAG_MACTIME_MPDU;
153  
154 +       for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
155 +               s8 rssi;
156 +
157 +               if (!(ah->rxchainmask & BIT(i)))
158 +                       continue;
159 +
160 +               rssi = rx_stats->rs_rssi_ctl[i];
161 +               if (rssi != ATH9K_RSSI_BAD) {
162 +                   rx_status->chains |= BIT(j);
163 +                   rx_status->chain_signal[j] = ah->noise + rssi;
164 +               }
165 +               j++;
166 +       }
167 +
168         return 0;
169  }
170  
171 @@ -1536,14 +1551,14 @@ static void ath_ant_comb_scan(struct ath
172         struct ath_ant_comb *antcomb = &sc->ant_comb;
173         int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
174         int curr_main_set;
175 -       int main_rssi = rs->rs_rssi_ctl0;
176 -       int alt_rssi = rs->rs_rssi_ctl1;
177 +       int main_rssi = rs->rs_rssi_ctl[0];
178 +       int alt_rssi = rs->rs_rssi_ctl[1];
179         int rx_ant_conf,  main_ant_conf;
180         bool short_scan = false;
181  
182 -       rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
183 +       rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
184                        ATH_ANT_RX_MASK;
185 -       main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
186 +       main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
187                          ATH_ANT_RX_MASK;
188  
189         /* Record packet only when both main_rssi and  alt_rssi is positive */
190 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
191 +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
192 @@ -452,12 +452,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
193  
194         /* XXX: Keycache */
195         rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
196 -       rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
197 -       rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
198 -       rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
199 -       rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
200 -       rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
201 -       rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
202 +       rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
203 +       rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
204 +       rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
205 +       rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
206 +       rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
207 +       rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
208  
209         if (rxsp->status11 & AR_RxKeyIdxValid)
210                 rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
211 --- a/drivers/net/wireless/ath/ath9k/mac.c
212 +++ b/drivers/net/wireless/ath/ath9k/mac.c
213 @@ -559,25 +559,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
214  
215         if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
216                 rs->rs_rssi = ATH9K_RSSI_BAD;
217 -               rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
218 -               rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
219 -               rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
220 -               rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
221 -               rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
222 -               rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
223 +               rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
224 +               rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
225 +               rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
226 +               rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
227 +               rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
228 +               rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
229         } else {
230                 rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
231 -               rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
232 +               rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
233                                                 AR_RxRSSIAnt00);
234 -               rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
235 +               rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
236                                                 AR_RxRSSIAnt01);
237 -               rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
238 +               rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
239                                                 AR_RxRSSIAnt02);
240 -               rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
241 +               rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
242                                                 AR_RxRSSIAnt10);
243 -               rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
244 +               rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
245                                                 AR_RxRSSIAnt11);
246 -               rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
247 +               rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
248                                                 AR_RxRSSIAnt12);
249         }
250         if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
251 --- a/drivers/net/wireless/ath/ath9k/debug.c
252 +++ b/drivers/net/wireless/ath/ath9k/debug.c
253 @@ -1047,12 +1047,12 @@ void ath_debug_stat_rx(struct ath_softc 
254  
255         spin_lock(&sc->debug.samp_lock);
256         RX_SAMP_DBG(jiffies) = jiffies;
257 -       RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
258 -       RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
259 -       RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
260 -       RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
261 -       RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
262 -       RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
263 +       RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl[0];
264 +       RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl[1];
265 +       RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl[2];
266 +       RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext[0];
267 +       RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext[1];
268 +       RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext[2];
269         RX_SAMP_DBG(antenna) = rs->rs_antenna;
270         RX_SAMP_DBG(rssi) = rs->rs_rssi;
271         RX_SAMP_DBG(rate) = rs->rs_rate;
272 --- a/include/linux/nl80211.h
273 +++ b/include/linux/nl80211.h
274 @@ -1621,6 +1621,8 @@ enum nl80211_sta_bss_param {
275   *     containing info as possible, see &enum nl80211_sta_bss_param
276   * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected
277   * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
278 + * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
279 + * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
280   * @__NL80211_STA_INFO_AFTER_LAST: internal
281   * @NL80211_STA_INFO_MAX: highest possible station info attribute
282   */
283 @@ -1643,6 +1645,8 @@ enum nl80211_sta_info {
284         NL80211_STA_INFO_BSS_PARAM,
285         NL80211_STA_INFO_CONNECTED_TIME,
286         NL80211_STA_INFO_STA_FLAGS,
287 +       NL80211_STA_INFO_CHAIN_SIGNAL,
288 +       NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
289  
290         /* keep last */
291         __NL80211_STA_INFO_AFTER_LAST,
292 --- a/net/wireless/nl80211.c
293 +++ b/net/wireless/nl80211.c
294 @@ -2287,6 +2287,33 @@ nla_put_failure:
295         return false;
296  }
297  
298 +static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
299 +                              int id)
300 +{
301 +       void *attr;
302 +       int i = 0;
303 +
304 +       if (!mask)
305 +               return true;
306 +
307 +       attr = nla_nest_start(msg, id);
308 +       if (!attr)
309 +               goto nla_put_failure;
310 +
311 +       for (i = 0; i < 4; i++) {
312 +               if (!(mask & BIT(i)))
313 +                       continue;
314 +
315 +               NLA_PUT_U8(msg, i, signal[i]);
316 +       }
317 +
318 +       nla_nest_end(msg, attr);
319 +
320 +       return true;
321 +nla_put_failure:
322 +       return false;
323 +}
324 +
325  static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
326                                 int flags, struct net_device *dev,
327                                 const u8 *mac_addr, struct station_info *sinfo)
328 @@ -2333,6 +2360,18 @@ static int nl80211_send_station(struct s
329         if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
330                 NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
331                            sinfo->signal_avg);
332 +       if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {
333 +               if (!nl80211_put_signal(msg, sinfo->chains,
334 +                                       sinfo->chain_signal,
335 +                                       NL80211_STA_INFO_CHAIN_SIGNAL))
336 +                       goto nla_put_failure;
337 +       }
338 +       if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {
339 +               if (!nl80211_put_signal(msg, sinfo->chains,
340 +                                       sinfo->chain_signal_avg,
341 +                                       NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
342 +                       goto nla_put_failure;
343 +       }
344         if (sinfo->filled & STATION_INFO_TX_BITRATE) {
345                 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
346                                           NL80211_STA_INFO_TX_BITRATE))
347 --- a/net/mac80211/cfg.c
348 +++ b/net/mac80211/cfg.c
349 @@ -330,6 +330,7 @@ static void sta_set_sinfo(struct sta_inf
350  {
351         struct ieee80211_sub_if_data *sdata = sta->sdata;
352         struct timespec uptime;
353 +       int i;
354  
355         sinfo->generation = sdata->local->sta_generation;
356  
357 @@ -365,6 +366,17 @@ static void sta_set_sinfo(struct sta_inf
358                 sinfo->signal = (s8)sta->last_signal;
359                 sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
360         }
361 +       if (sta->chains) {
362 +               sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
363 +                                STATION_INFO_CHAIN_SIGNAL_AVG;
364 +
365 +               sinfo->chains = sta->chains;
366 +               for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
367 +                       sinfo->chain_signal[i] = sta->chain_signal_last[i];
368 +                       sinfo->chain_signal_avg[i] =
369 +                               (s8) -ewma_read(&sta->chain_signal_avg[i]);
370 +               }
371 +       }
372  
373         sinfo->txrate.flags = 0;
374         if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)