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