]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/net/wireless/ath/ath9k/common.c
Merge branch 'for-patrick' of git://git.kernel.org/pub/scm/linux/kernel/git/horms...
[mv-sheeva.git] / drivers / net / wireless / ath / ath9k / common.c
1 /*
2  * Copyright (c) 2009 Atheros Communications Inc.
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
30 int ath9k_cmn_padpos(__le16 frame_control)
31 {
32         int padpos = 24;
33         if (ieee80211_has_a4(frame_control)) {
34                 padpos += ETH_ALEN;
35         }
36         if (ieee80211_is_data_qos(frame_control)) {
37                 padpos += IEEE80211_QOS_CTL_LEN;
38         }
39
40         return padpos;
41 }
42 EXPORT_SYMBOL(ath9k_cmn_padpos);
43
44 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
45 {
46         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
47
48         if (tx_info->control.hw_key) {
49                 switch (tx_info->control.hw_key->cipher) {
50                 case WLAN_CIPHER_SUITE_WEP40:
51                 case WLAN_CIPHER_SUITE_WEP104:
52                         return ATH9K_KEY_TYPE_WEP;
53                 case WLAN_CIPHER_SUITE_TKIP:
54                         return ATH9K_KEY_TYPE_TKIP;
55                 case WLAN_CIPHER_SUITE_CCMP:
56                         return ATH9K_KEY_TYPE_AES;
57                 default:
58                         break;
59                 }
60         }
61
62         return ATH9K_KEY_TYPE_CLEAR;
63 }
64 EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
65
66 static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
67                                  enum nl80211_channel_type channel_type)
68 {
69         u32 chanmode = 0;
70
71         switch (chan->band) {
72         case IEEE80211_BAND_2GHZ:
73                 switch (channel_type) {
74                 case NL80211_CHAN_NO_HT:
75                 case NL80211_CHAN_HT20:
76                         chanmode = CHANNEL_G_HT20;
77                         break;
78                 case NL80211_CHAN_HT40PLUS:
79                         chanmode = CHANNEL_G_HT40PLUS;
80                         break;
81                 case NL80211_CHAN_HT40MINUS:
82                         chanmode = CHANNEL_G_HT40MINUS;
83                         break;
84                 }
85                 break;
86         case IEEE80211_BAND_5GHZ:
87                 switch (channel_type) {
88                 case NL80211_CHAN_NO_HT:
89                 case NL80211_CHAN_HT20:
90                         chanmode = CHANNEL_A_HT20;
91                         break;
92                 case NL80211_CHAN_HT40PLUS:
93                         chanmode = CHANNEL_A_HT40PLUS;
94                         break;
95                 case NL80211_CHAN_HT40MINUS:
96                         chanmode = CHANNEL_A_HT40MINUS;
97                         break;
98                 }
99                 break;
100         default:
101                 break;
102         }
103
104         return chanmode;
105 }
106
107 /*
108  * Update internal channel flags.
109  */
110 void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
111                                struct ath9k_channel *ichan)
112 {
113         struct ieee80211_channel *chan = hw->conf.channel;
114         struct ieee80211_conf *conf = &hw->conf;
115
116         ichan->channel = chan->center_freq;
117         ichan->chan = chan;
118
119         if (chan->band == IEEE80211_BAND_2GHZ) {
120                 ichan->chanmode = CHANNEL_G;
121                 ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G;
122         } else {
123                 ichan->chanmode = CHANNEL_A;
124                 ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
125         }
126
127         if (conf_is_ht(conf))
128                 ichan->chanmode = ath9k_get_extchanmode(chan,
129                                                         conf->channel_type);
130 }
131 EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
132
133 /*
134  * Get the internal channel reference.
135  */
136 struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
137                                                struct ath_hw *ah)
138 {
139         struct ieee80211_channel *curchan = hw->conf.channel;
140         struct ath9k_channel *channel;
141         u8 chan_idx;
142
143         chan_idx = curchan->hw_value;
144         channel = &ah->channels[chan_idx];
145         ath9k_cmn_update_ichannel(hw, channel);
146
147         return channel;
148 }
149 EXPORT_SYMBOL(ath9k_cmn_get_curchannel);
150
151 static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
152                            struct ath9k_keyval *hk, const u8 *addr,
153                            bool authenticator)
154 {
155         struct ath_hw *ah = common->ah;
156         const u8 *key_rxmic;
157         const u8 *key_txmic;
158
159         key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
160         key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
161
162         if (addr == NULL) {
163                 /*
164                  * Group key installation - only two key cache entries are used
165                  * regardless of splitmic capability since group key is only
166                  * used either for TX or RX.
167                  */
168                 if (authenticator) {
169                         memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
170                         memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
171                 } else {
172                         memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
173                         memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
174                 }
175                 return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
176         }
177         if (!common->splitmic) {
178                 /* TX and RX keys share the same key cache entry. */
179                 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
180                 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
181                 return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
182         }
183
184         /* Separate key cache entries for TX and RX */
185
186         /* TX key goes at first index, RX key at +32. */
187         memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
188         if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
189                 /* TX MIC entry failed. No need to proceed further */
190                 ath_print(common, ATH_DBG_FATAL,
191                           "Setting TX MIC Key Failed\n");
192                 return 0;
193         }
194
195         memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
196         /* XXX delete tx key on failure? */
197         return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
198 }
199
200 static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
201 {
202         int i;
203
204         for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
205                 if (test_bit(i, common->keymap) ||
206                     test_bit(i + 64, common->keymap))
207                         continue; /* At least one part of TKIP key allocated */
208                 if (common->splitmic &&
209                     (test_bit(i + 32, common->keymap) ||
210                      test_bit(i + 64 + 32, common->keymap)))
211                         continue; /* At least one part of TKIP key allocated */
212
213                 /* Found a free slot for a TKIP key */
214                 return i;
215         }
216         return -1;
217 }
218
219 static int ath_reserve_key_cache_slot(struct ath_common *common,
220                                       u32 cipher)
221 {
222         int i;
223
224         if (cipher == WLAN_CIPHER_SUITE_TKIP)
225                 return ath_reserve_key_cache_slot_tkip(common);
226
227         /* First, try to find slots that would not be available for TKIP. */
228         if (common->splitmic) {
229                 for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
230                         if (!test_bit(i, common->keymap) &&
231                             (test_bit(i + 32, common->keymap) ||
232                              test_bit(i + 64, common->keymap) ||
233                              test_bit(i + 64 + 32, common->keymap)))
234                                 return i;
235                         if (!test_bit(i + 32, common->keymap) &&
236                             (test_bit(i, common->keymap) ||
237                              test_bit(i + 64, common->keymap) ||
238                              test_bit(i + 64 + 32, common->keymap)))
239                                 return i + 32;
240                         if (!test_bit(i + 64, common->keymap) &&
241                             (test_bit(i , common->keymap) ||
242                              test_bit(i + 32, common->keymap) ||
243                              test_bit(i + 64 + 32, common->keymap)))
244                                 return i + 64;
245                         if (!test_bit(i + 64 + 32, common->keymap) &&
246                             (test_bit(i, common->keymap) ||
247                              test_bit(i + 32, common->keymap) ||
248                              test_bit(i + 64, common->keymap)))
249                                 return i + 64 + 32;
250                 }
251         } else {
252                 for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
253                         if (!test_bit(i, common->keymap) &&
254                             test_bit(i + 64, common->keymap))
255                                 return i;
256                         if (test_bit(i, common->keymap) &&
257                             !test_bit(i + 64, common->keymap))
258                                 return i + 64;
259                 }
260         }
261
262         /* No partially used TKIP slots, pick any available slot */
263         for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
264                 /* Do not allow slots that could be needed for TKIP group keys
265                  * to be used. This limitation could be removed if we know that
266                  * TKIP will not be used. */
267                 if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
268                         continue;
269                 if (common->splitmic) {
270                         if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
271                                 continue;
272                         if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
273                                 continue;
274                 }
275
276                 if (!test_bit(i, common->keymap))
277                         return i; /* Found a free slot for a key */
278         }
279
280         /* No free slot found */
281         return -1;
282 }
283
284 /*
285  * Configure encryption in the HW.
286  */
287 int ath9k_cmn_key_config(struct ath_common *common,
288                          struct ieee80211_vif *vif,
289                          struct ieee80211_sta *sta,
290                          struct ieee80211_key_conf *key)
291 {
292         struct ath_hw *ah = common->ah;
293         struct ath9k_keyval hk;
294         const u8 *mac = NULL;
295         u8 gmac[ETH_ALEN];
296         int ret = 0;
297         int idx;
298
299         memset(&hk, 0, sizeof(hk));
300
301         switch (key->cipher) {
302         case WLAN_CIPHER_SUITE_WEP40:
303         case WLAN_CIPHER_SUITE_WEP104:
304                 hk.kv_type = ATH9K_CIPHER_WEP;
305                 break;
306         case WLAN_CIPHER_SUITE_TKIP:
307                 hk.kv_type = ATH9K_CIPHER_TKIP;
308                 break;
309         case WLAN_CIPHER_SUITE_CCMP:
310                 hk.kv_type = ATH9K_CIPHER_AES_CCM;
311                 break;
312         default:
313                 return -EOPNOTSUPP;
314         }
315
316         hk.kv_len = key->keylen;
317         memcpy(hk.kv_val, key->key, key->keylen);
318
319         if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
320                 switch (vif->type) {
321                 case NL80211_IFTYPE_AP:
322                         memcpy(gmac, vif->addr, ETH_ALEN);
323                         gmac[0] |= 0x01;
324                         mac = gmac;
325                         idx = ath_reserve_key_cache_slot(common, key->cipher);
326                         break;
327                 case NL80211_IFTYPE_ADHOC:
328                         if (!sta) {
329                                 idx = key->keyidx;
330                                 break;
331                         }
332                         memcpy(gmac, sta->addr, ETH_ALEN);
333                         gmac[0] |= 0x01;
334                         mac = gmac;
335                         idx = ath_reserve_key_cache_slot(common, key->cipher);
336                         break;
337                 default:
338                         idx = key->keyidx;
339                         break;
340                 }
341         } else if (key->keyidx) {
342                 if (WARN_ON(!sta))
343                         return -EOPNOTSUPP;
344                 mac = sta->addr;
345
346                 if (vif->type != NL80211_IFTYPE_AP) {
347                         /* Only keyidx 0 should be used with unicast key, but
348                          * allow this for client mode for now. */
349                         idx = key->keyidx;
350                 } else
351                         return -EIO;
352         } else {
353                 if (WARN_ON(!sta))
354                         return -EOPNOTSUPP;
355                 mac = sta->addr;
356
357                 idx = ath_reserve_key_cache_slot(common, key->cipher);
358         }
359
360         if (idx < 0)
361                 return -ENOSPC; /* no free key cache entries */
362
363         if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
364                 ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
365                                       vif->type == NL80211_IFTYPE_AP);
366         else
367                 ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
368
369         if (!ret)
370                 return -EIO;
371
372         set_bit(idx, common->keymap);
373         if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
374                 set_bit(idx + 64, common->keymap);
375                 set_bit(idx, common->tkip_keymap);
376                 set_bit(idx + 64, common->tkip_keymap);
377                 if (common->splitmic) {
378                         set_bit(idx + 32, common->keymap);
379                         set_bit(idx + 64 + 32, common->keymap);
380                         set_bit(idx + 32, common->tkip_keymap);
381                         set_bit(idx + 64 + 32, common->tkip_keymap);
382                 }
383         }
384
385         return idx;
386 }
387 EXPORT_SYMBOL(ath9k_cmn_key_config);
388
389 /*
390  * Delete Key.
391  */
392 void ath9k_cmn_key_delete(struct ath_common *common,
393                           struct ieee80211_key_conf *key)
394 {
395         struct ath_hw *ah = common->ah;
396
397         ath9k_hw_keyreset(ah, key->hw_key_idx);
398         if (key->hw_key_idx < IEEE80211_WEP_NKID)
399                 return;
400
401         clear_bit(key->hw_key_idx, common->keymap);
402         if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
403                 return;
404
405         clear_bit(key->hw_key_idx + 64, common->keymap);
406
407         clear_bit(key->hw_key_idx, common->tkip_keymap);
408         clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
409
410         if (common->splitmic) {
411                 ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
412                 clear_bit(key->hw_key_idx + 32, common->keymap);
413                 clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
414
415                 clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
416                 clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
417         }
418 }
419 EXPORT_SYMBOL(ath9k_cmn_key_delete);
420
421 int ath9k_cmn_count_streams(unsigned int chainmask, int max)
422 {
423         int streams = 0;
424
425         do {
426                 if (++streams == max)
427                         break;
428         } while ((chainmask = chainmask & (chainmask - 1)));
429
430         return streams;
431 }
432 EXPORT_SYMBOL(ath9k_cmn_count_streams);
433
434 /*
435  * Configures appropriate weight based on stomp type.
436  */
437 void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
438                                   enum ath_stomp_type stomp_type)
439 {
440         struct ath_hw *ah = common->ah;
441
442         switch (stomp_type) {
443         case ATH_BTCOEX_STOMP_ALL:
444                 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
445                                            AR_STOMP_ALL_WLAN_WGHT);
446                 break;
447         case ATH_BTCOEX_STOMP_LOW:
448                 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
449                                            AR_STOMP_LOW_WLAN_WGHT);
450                 break;
451         case ATH_BTCOEX_STOMP_NONE:
452                 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
453                                            AR_STOMP_NONE_WLAN_WGHT);
454                 break;
455         default:
456                 ath_print(common, ATH_DBG_BTCOEX,
457                           "Invalid Stomptype\n");
458                 break;
459         }
460
461         ath9k_hw_btcoex_enable(ah);
462 }
463 EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp);
464
465 static int __init ath9k_cmn_init(void)
466 {
467         return 0;
468 }
469 module_init(ath9k_cmn_init);
470
471 static void __exit ath9k_cmn_exit(void)
472 {
473         return;
474 }
475 module_exit(ath9k_cmn_exit);