]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/wireless/ath/ath9k/common.c
d3063c21e16c7efbd67d073c756de2198e5794e5
[karo-tx-linux.git] / drivers / net / wireless / ath / ath9k / common.c
1 /*
2  * Copyright (c) 2009-2011 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_get_hw_crypto_keytype(struct sk_buff *skb)
31 {
32         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
33
34         if (tx_info->control.hw_key) {
35                 switch (tx_info->control.hw_key->cipher) {
36                 case WLAN_CIPHER_SUITE_WEP40:
37                 case WLAN_CIPHER_SUITE_WEP104:
38                         return ATH9K_KEY_TYPE_WEP;
39                 case WLAN_CIPHER_SUITE_TKIP:
40                         return ATH9K_KEY_TYPE_TKIP;
41                 case WLAN_CIPHER_SUITE_CCMP:
42                         return ATH9K_KEY_TYPE_AES;
43                 default:
44                         break;
45                 }
46         }
47
48         return ATH9K_KEY_TYPE_CLEAR;
49 }
50 EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
51
52 static u32 ath9k_get_extchanmode(struct cfg80211_chan_def *chandef)
53 {
54         u32 chanmode = 0;
55
56         switch (chandef->chan->band) {
57         case IEEE80211_BAND_2GHZ:
58                 switch (chandef->width) {
59                 case NL80211_CHAN_WIDTH_20_NOHT:
60                 case NL80211_CHAN_WIDTH_20:
61                         chanmode = CHANNEL_G_HT20;
62                         break;
63                 case NL80211_CHAN_WIDTH_40:
64                         if (chandef->center_freq1 > chandef->chan->center_freq)
65                                 chanmode = CHANNEL_G_HT40PLUS;
66                         else
67                                 chanmode = CHANNEL_G_HT40MINUS;
68                         break;
69                 default:
70                         break;
71                 }
72                 break;
73         case IEEE80211_BAND_5GHZ:
74                 switch (chandef->width) {
75                 case NL80211_CHAN_WIDTH_20_NOHT:
76                 case NL80211_CHAN_WIDTH_20:
77                         chanmode = CHANNEL_A_HT20;
78                         break;
79                 case NL80211_CHAN_WIDTH_40:
80                         if (chandef->center_freq1 > chandef->chan->center_freq)
81                                 chanmode = CHANNEL_A_HT40PLUS;
82                         else
83                                 chanmode = CHANNEL_A_HT40MINUS;
84                         break;
85                 default:
86                         break;
87                 }
88                 break;
89         default:
90                 break;
91         }
92
93         return chanmode;
94 }
95
96 /*
97  * Update internal channel flags.
98  */
99 void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
100                                struct cfg80211_chan_def *chandef)
101 {
102         ichan->channel = chandef->chan->center_freq;
103         ichan->chan = chandef->chan;
104
105         if (chandef->chan->band == IEEE80211_BAND_2GHZ) {
106                 ichan->chanmode = CHANNEL_G;
107                 ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
108         } else {
109                 ichan->chanmode = CHANNEL_A;
110                 ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
111         }
112
113         switch (chandef->width) {
114         case NL80211_CHAN_WIDTH_5:
115                 ichan->channelFlags |= CHANNEL_QUARTER;
116                 break;
117         case NL80211_CHAN_WIDTH_10:
118                 ichan->channelFlags |= CHANNEL_HALF;
119                 break;
120         case NL80211_CHAN_WIDTH_20_NOHT:
121                 break;
122         case NL80211_CHAN_WIDTH_20:
123         case NL80211_CHAN_WIDTH_40:
124                 ichan->chanmode = ath9k_get_extchanmode(chandef);
125                 break;
126         default:
127                 WARN_ON(1);
128         }
129 }
130 EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
131
132 /*
133  * Get the internal channel reference.
134  */
135 struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
136                                                struct ath_hw *ah)
137 {
138         struct ieee80211_channel *curchan = hw->conf.chandef.chan;
139         struct ath9k_channel *channel;
140         u8 chan_idx;
141
142         chan_idx = curchan->hw_value;
143         channel = &ah->channels[chan_idx];
144         ath9k_cmn_update_ichannel(channel, &hw->conf.chandef);
145
146         return channel;
147 }
148 EXPORT_SYMBOL(ath9k_cmn_get_curchannel);
149
150 int ath9k_cmn_count_streams(unsigned int chainmask, int max)
151 {
152         int streams = 0;
153
154         do {
155                 if (++streams == max)
156                         break;
157         } while ((chainmask = chainmask & (chainmask - 1)));
158
159         return streams;
160 }
161 EXPORT_SYMBOL(ath9k_cmn_count_streams);
162
163 void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
164                             u16 new_txpow, u16 *txpower)
165 {
166         struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
167
168         if (reg->power_limit != new_txpow) {
169                 ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
170                 /* read back in case value is clamped */
171                 *txpower = reg->max_power_level;
172         }
173 }
174 EXPORT_SYMBOL(ath9k_cmn_update_txpow);
175
176 void ath9k_cmn_init_crypto(struct ath_hw *ah)
177 {
178         struct ath_common *common = ath9k_hw_common(ah);
179         int i = 0;
180
181         /* Get the hardware key cache size. */
182         common->keymax = AR_KEYTABLE_SIZE;
183
184         /*
185          * Check whether the separate key cache entries
186          * are required to handle both tx+rx MIC keys.
187          * With split mic keys the number of stations is limited
188          * to 27 otherwise 59.
189          */
190         if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
191                 common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
192
193         /*
194          * Reset the key cache since some parts do not
195          * reset the contents on initial power up.
196          */
197         for (i = 0; i < common->keymax; i++)
198                 ath_hw_keyreset(common, (u16) i);
199 }
200 EXPORT_SYMBOL(ath9k_cmn_init_crypto);
201
202 static int __init ath9k_cmn_init(void)
203 {
204         return 0;
205 }
206 module_init(ath9k_cmn_init);
207
208 static void __exit ath9k_cmn_exit(void)
209 {
210         return;
211 }
212 module_exit(ath9k_cmn_exit);