Commit | Line | Data |
---|---|---|
db86f07e | 1 | /* |
5b68138e | 2 | * Copyright (c) 2009-2011 Atheros Communications Inc. |
db86f07e LR |
3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
17 | /* | |
18 | * Module for common driver code between ath9k and ath9k_htc | |
19 | */ | |
20 | ||
21 | #include <linux/kernel.h> | |
22 | #include <linux/module.h> | |
23 | ||
24 | #include "common.h" | |
25 | ||
26 | MODULE_AUTHOR("Atheros Communications"); | |
27 | MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); | |
28 | MODULE_LICENSE("Dual BSD/GPL"); | |
29 | ||
6438696e OR |
30 | /* Assumes you've already done the endian to CPU conversion */ |
31 | bool ath9k_cmn_rx_accept(struct ath_common *common, | |
32 | struct ieee80211_hdr *hdr, | |
33 | struct ieee80211_rx_status *rxs, | |
34 | struct ath_rx_status *rx_stats, | |
35 | bool *decrypt_error, | |
36 | unsigned int rxfilter) | |
37 | { | |
38 | struct ath_hw *ah = common->ah; | |
39 | bool is_mc, is_valid_tkip, strip_mic, mic_error; | |
40 | __le16 fc; | |
41 | ||
42 | fc = hdr->frame_control; | |
43 | ||
44 | is_mc = !!is_multicast_ether_addr(hdr->addr1); | |
45 | is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && | |
46 | test_bit(rx_stats->rs_keyix, common->tkip_keymap); | |
47 | strip_mic = is_valid_tkip && ieee80211_is_data(fc) && | |
48 | ieee80211_has_protected(fc) && | |
49 | !(rx_stats->rs_status & | |
50 | (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC | | |
51 | ATH9K_RXERR_KEYMISS)); | |
52 | ||
53 | /* | |
54 | * Key miss events are only relevant for pairwise keys where the | |
55 | * descriptor does contain a valid key index. This has been observed | |
56 | * mostly with CCMP encryption. | |
57 | */ | |
58 | if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID || | |
59 | !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) | |
60 | rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; | |
61 | ||
62 | mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) && | |
63 | !ieee80211_has_morefrags(fc) && | |
64 | !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && | |
65 | (rx_stats->rs_status & ATH9K_RXERR_MIC); | |
66 | ||
67 | /* | |
68 | * The rx_stats->rs_status will not be set until the end of the | |
69 | * chained descriptors so it can be ignored if rs_more is set. The | |
70 | * rs_more will be false at the last element of the chained | |
71 | * descriptors. | |
72 | */ | |
73 | if (rx_stats->rs_status != 0) { | |
74 | u8 status_mask; | |
75 | ||
76 | if (rx_stats->rs_status & ATH9K_RXERR_CRC) { | |
77 | rxs->flag |= RX_FLAG_FAILED_FCS_CRC; | |
78 | mic_error = false; | |
79 | } | |
80 | ||
81 | if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) || | |
82 | (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) { | |
83 | *decrypt_error = true; | |
84 | mic_error = false; | |
85 | } | |
86 | ||
87 | ||
88 | /* | |
89 | * Reject error frames with the exception of | |
90 | * decryption and MIC failures. For monitor mode, | |
91 | * we also ignore the CRC error. | |
92 | */ | |
93 | status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | |
94 | ATH9K_RXERR_KEYMISS; | |
95 | ||
96 | if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL)) | |
97 | status_mask |= ATH9K_RXERR_CRC; | |
98 | ||
99 | if (rx_stats->rs_status & ~status_mask) | |
100 | return false; | |
101 | } | |
102 | ||
103 | /* | |
104 | * For unicast frames the MIC error bit can have false positives, | |
105 | * so all MIC error reports need to be validated in software. | |
106 | * False negatives are not common, so skip software verification | |
107 | * if the hardware considers the MIC valid. | |
108 | */ | |
109 | if (strip_mic) | |
110 | rxs->flag |= RX_FLAG_MMIC_STRIPPED; | |
111 | else if (is_mc && mic_error) | |
112 | rxs->flag |= RX_FLAG_MMIC_ERROR; | |
113 | ||
114 | return true; | |
115 | } | |
116 | EXPORT_SYMBOL(ath9k_cmn_rx_accept); | |
117 | ||
5a078fcb OR |
118 | void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, |
119 | struct sk_buff *skb, | |
120 | struct ath_rx_status *rx_stats, | |
121 | struct ieee80211_rx_status *rxs, | |
122 | bool decrypt_error) | |
123 | { | |
124 | struct ath_hw *ah = common->ah; | |
125 | struct ieee80211_hdr *hdr; | |
126 | int hdrlen, padpos, padsize; | |
127 | u8 keyix; | |
128 | __le16 fc; | |
129 | ||
130 | /* see if any padding is done by the hw and remove it */ | |
131 | hdr = (struct ieee80211_hdr *) skb->data; | |
132 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | |
133 | fc = hdr->frame_control; | |
134 | padpos = ieee80211_hdrlen(fc); | |
135 | ||
136 | /* The MAC header is padded to have 32-bit boundary if the | |
137 | * packet payload is non-zero. The general calculation for | |
138 | * padsize would take into account odd header lengths: | |
139 | * padsize = (4 - padpos % 4) % 4; However, since only | |
140 | * even-length headers are used, padding can only be 0 or 2 | |
141 | * bytes and we can optimize this a bit. In addition, we must | |
142 | * not try to remove padding from short control frames that do | |
143 | * not have payload. */ | |
144 | padsize = padpos & 3; | |
145 | if (padsize && skb->len>=padpos+padsize+FCS_LEN) { | |
146 | memmove(skb->data + padsize, skb->data, padpos); | |
147 | skb_pull(skb, padsize); | |
148 | } | |
149 | ||
150 | keyix = rx_stats->rs_keyix; | |
151 | ||
152 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && | |
153 | ieee80211_has_protected(fc)) { | |
154 | rxs->flag |= RX_FLAG_DECRYPTED; | |
155 | } else if (ieee80211_has_protected(fc) | |
156 | && !decrypt_error && skb->len >= hdrlen + 4) { | |
157 | keyix = skb->data[hdrlen + 3] >> 6; | |
158 | ||
159 | if (test_bit(keyix, common->keymap)) | |
160 | rxs->flag |= RX_FLAG_DECRYPTED; | |
161 | } | |
e6510b11 | 162 | if (ah->sw_mgmt_crypto_rx && |
5a078fcb OR |
163 | (rxs->flag & RX_FLAG_DECRYPTED) && |
164 | ieee80211_is_mgmt(fc)) | |
165 | /* Use software decrypt for management frames. */ | |
166 | rxs->flag &= ~RX_FLAG_DECRYPTED; | |
167 | } | |
168 | EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); | |
169 | ||
12746036 OR |
170 | int ath9k_cmn_process_rate(struct ath_common *common, |
171 | struct ieee80211_hw *hw, | |
172 | struct ath_rx_status *rx_stats, | |
173 | struct ieee80211_rx_status *rxs) | |
174 | { | |
175 | struct ieee80211_supported_band *sband; | |
176 | enum ieee80211_band band; | |
177 | unsigned int i = 0; | |
178 | struct ath_hw *ah = common->ah; | |
179 | ||
180 | band = ah->curchan->chan->band; | |
181 | sband = hw->wiphy->bands[band]; | |
182 | ||
183 | if (IS_CHAN_QUARTER_RATE(ah->curchan)) | |
184 | rxs->flag |= RX_FLAG_5MHZ; | |
185 | else if (IS_CHAN_HALF_RATE(ah->curchan)) | |
186 | rxs->flag |= RX_FLAG_10MHZ; | |
187 | ||
188 | if (rx_stats->rs_rate & 0x80) { | |
189 | /* HT rate */ | |
190 | rxs->flag |= RX_FLAG_HT; | |
191 | rxs->flag |= rx_stats->flag; | |
192 | rxs->rate_idx = rx_stats->rs_rate & 0x7f; | |
193 | return 0; | |
194 | } | |
195 | ||
196 | for (i = 0; i < sband->n_bitrates; i++) { | |
197 | if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { | |
198 | rxs->rate_idx = i; | |
199 | return 0; | |
200 | } | |
201 | if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { | |
202 | rxs->flag |= RX_FLAG_SHORTPRE; | |
203 | rxs->rate_idx = i; | |
204 | return 0; | |
205 | } | |
206 | } | |
207 | ||
208 | return -EINVAL; | |
209 | } | |
210 | EXPORT_SYMBOL(ath9k_cmn_process_rate); | |
211 | ||
32efb0cc OR |
212 | void ath9k_cmn_process_rssi(struct ath_common *common, |
213 | struct ieee80211_hw *hw, | |
214 | struct ath_rx_status *rx_stats, | |
215 | struct ieee80211_rx_status *rxs) | |
216 | { | |
217 | struct ath_hw *ah = common->ah; | |
218 | int last_rssi; | |
219 | int rssi = rx_stats->rs_rssi; | |
220 | int i, j; | |
221 | ||
222 | /* | |
223 | * RSSI is not available for subframes in an A-MPDU. | |
224 | */ | |
225 | if (rx_stats->rs_moreaggr) { | |
226 | rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; | |
227 | return; | |
228 | } | |
229 | ||
230 | /* | |
231 | * Check if the RSSI for the last subframe in an A-MPDU | |
232 | * or an unaggregated frame is valid. | |
233 | */ | |
234 | if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) { | |
235 | rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; | |
236 | return; | |
237 | } | |
238 | ||
239 | for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) { | |
240 | s8 rssi; | |
241 | ||
242 | if (!(ah->rxchainmask & BIT(i))) | |
243 | continue; | |
244 | ||
245 | rssi = rx_stats->rs_rssi_ctl[i]; | |
246 | if (rssi != ATH9K_RSSI_BAD) { | |
247 | rxs->chains |= BIT(j); | |
248 | rxs->chain_signal[j] = ah->noise + rssi; | |
249 | } | |
250 | j++; | |
251 | } | |
252 | ||
253 | /* | |
254 | * Update Beacon RSSI, this is used by ANI. | |
255 | */ | |
256 | if (rx_stats->is_mybeacon && | |
257 | ((ah->opmode == NL80211_IFTYPE_STATION) || | |
258 | (ah->opmode == NL80211_IFTYPE_ADHOC))) { | |
259 | ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi); | |
260 | last_rssi = common->last_rssi; | |
261 | ||
262 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | |
263 | rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); | |
264 | if (rssi < 0) | |
265 | rssi = 0; | |
266 | ||
267 | ah->stats.avgbrssi = rssi; | |
268 | } | |
269 | ||
270 | rxs->signal = ah->noise + rx_stats->rs_rssi; | |
271 | } | |
272 | EXPORT_SYMBOL(ath9k_cmn_process_rssi); | |
273 | ||
fb9987d0 S |
274 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) |
275 | { | |
276 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | |
277 | ||
278 | if (tx_info->control.hw_key) { | |
97359d12 JB |
279 | switch (tx_info->control.hw_key->cipher) { |
280 | case WLAN_CIPHER_SUITE_WEP40: | |
281 | case WLAN_CIPHER_SUITE_WEP104: | |
fb9987d0 | 282 | return ATH9K_KEY_TYPE_WEP; |
97359d12 | 283 | case WLAN_CIPHER_SUITE_TKIP: |
fb9987d0 | 284 | return ATH9K_KEY_TYPE_TKIP; |
97359d12 | 285 | case WLAN_CIPHER_SUITE_CCMP: |
fb9987d0 | 286 | return ATH9K_KEY_TYPE_AES; |
97359d12 JB |
287 | default: |
288 | break; | |
289 | } | |
fb9987d0 S |
290 | } |
291 | ||
292 | return ATH9K_KEY_TYPE_CLEAR; | |
293 | } | |
294 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); | |
295 | ||
fb9987d0 S |
296 | /* |
297 | * Update internal channel flags. | |
298 | */ | |
2297f1c7 FF |
299 | static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
300 | struct cfg80211_chan_def *chandef) | |
fb9987d0 | 301 | { |
6b21fd20 FF |
302 | struct ieee80211_channel *chan = chandef->chan; |
303 | u16 flags = 0; | |
304 | ||
305 | ichan->channel = chan->center_freq; | |
306 | ichan->chan = chan; | |
307 | ||
308 | if (chan->band == IEEE80211_BAND_5GHZ) | |
309 | flags |= CHANNEL_5GHZ; | |
fb9987d0 | 310 | |
0671894f SW |
311 | switch (chandef->width) { |
312 | case NL80211_CHAN_WIDTH_5: | |
6b21fd20 | 313 | flags |= CHANNEL_QUARTER; |
0671894f SW |
314 | break; |
315 | case NL80211_CHAN_WIDTH_10: | |
6b21fd20 | 316 | flags |= CHANNEL_HALF; |
0671894f SW |
317 | break; |
318 | case NL80211_CHAN_WIDTH_20_NOHT: | |
319 | break; | |
320 | case NL80211_CHAN_WIDTH_20: | |
6b21fd20 FF |
321 | flags |= CHANNEL_HT; |
322 | break; | |
0671894f | 323 | case NL80211_CHAN_WIDTH_40: |
6b21fd20 FF |
324 | if (chandef->center_freq1 > chandef->chan->center_freq) |
325 | flags |= CHANNEL_HT40PLUS | CHANNEL_HT; | |
326 | else | |
327 | flags |= CHANNEL_HT40MINUS | CHANNEL_HT; | |
0671894f SW |
328 | break; |
329 | default: | |
330 | WARN_ON(1); | |
331 | } | |
6b21fd20 FF |
332 | |
333 | ichan->channelFlags = flags; | |
fb9987d0 | 334 | } |
fb9987d0 S |
335 | |
336 | /* | |
337 | * Get the internal channel reference. | |
338 | */ | |
2297f1c7 FF |
339 | struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, |
340 | struct ath_hw *ah, | |
341 | struct cfg80211_chan_def *chandef) | |
fb9987d0 | 342 | { |
2297f1c7 | 343 | struct ieee80211_channel *curchan = chandef->chan; |
fb9987d0 | 344 | struct ath9k_channel *channel; |
fb9987d0 | 345 | |
f40c4608 | 346 | channel = &ah->channels[curchan->hw_value]; |
2297f1c7 | 347 | ath9k_cmn_update_ichannel(channel, chandef); |
fb9987d0 S |
348 | |
349 | return channel; | |
350 | } | |
2297f1c7 | 351 | EXPORT_SYMBOL(ath9k_cmn_get_channel); |
fb9987d0 | 352 | |
61389f3e S |
353 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) |
354 | { | |
355 | int streams = 0; | |
356 | ||
357 | do { | |
358 | if (++streams == max) | |
359 | break; | |
360 | } while ((chainmask = chainmask & (chainmask - 1))); | |
361 | ||
362 | return streams; | |
363 | } | |
364 | EXPORT_SYMBOL(ath9k_cmn_count_streams); | |
365 | ||
5048e8c3 RM |
366 | void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, |
367 | u16 new_txpow, u16 *txpower) | |
368 | { | |
ca2c68cc FF |
369 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); |
370 | ||
76325451 | 371 | if (reg->power_limit != new_txpow) |
5048e8c3 | 372 | ath9k_hw_set_txpowerlimit(ah, new_txpow, false); |
76325451 FF |
373 | |
374 | /* read back in case value is clamped */ | |
375 | *txpower = reg->max_power_level; | |
5048e8c3 RM |
376 | } |
377 | EXPORT_SYMBOL(ath9k_cmn_update_txpow); | |
378 | ||
f82b4bde RM |
379 | void ath9k_cmn_init_crypto(struct ath_hw *ah) |
380 | { | |
381 | struct ath_common *common = ath9k_hw_common(ah); | |
382 | int i = 0; | |
383 | ||
384 | /* Get the hardware key cache size. */ | |
385 | common->keymax = AR_KEYTABLE_SIZE; | |
386 | ||
387 | /* | |
388 | * Check whether the separate key cache entries | |
389 | * are required to handle both tx+rx MIC keys. | |
390 | * With split mic keys the number of stations is limited | |
391 | * to 27 otherwise 59. | |
392 | */ | |
393 | if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) | |
394 | common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; | |
395 | ||
396 | /* | |
397 | * Reset the key cache since some parts do not | |
398 | * reset the contents on initial power up. | |
399 | */ | |
400 | for (i = 0; i < common->keymax; i++) | |
401 | ath_hw_keyreset(common, (u16) i); | |
402 | } | |
403 | EXPORT_SYMBOL(ath9k_cmn_init_crypto); | |
404 | ||
db86f07e LR |
405 | static int __init ath9k_cmn_init(void) |
406 | { | |
407 | return 0; | |
408 | } | |
409 | module_init(ath9k_cmn_init); | |
410 | ||
411 | static void __exit ath9k_cmn_exit(void) | |
412 | { | |
413 | return; | |
414 | } | |
415 | module_exit(ath9k_cmn_exit); |