PageRenderTime 42ms CodeModel.GetById 17ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/net/wireless/ath/key.c

https://bitbucket.org/wisechild/galaxy-nexus
C | 604 lines | 403 code | 91 blank | 110 comment | 79 complexity | 668870ec76895ed641b7312e219439b6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * Copyright (c) 2009 Atheros Communications Inc.
  3 * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
  4 *
  5 * Permission to use, copy, modify, and/or distribute this software for any
  6 * purpose with or without fee is hereby granted, provided that the above
  7 * copyright notice and this permission notice appear in all copies.
  8 *
  9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 16 */
 17
 18#include <asm/unaligned.h>
 19#include <net/mac80211.h>
 20
 21#include "ath.h"
 22#include "reg.h"
 23
 24#define REG_READ			(common->ops->read)
 25#define REG_WRITE(_ah, _reg, _val)	(common->ops->write)(_ah, _val, _reg)
 26#define ENABLE_REGWRITE_BUFFER(_ah)			\
 27	if (common->ops->enable_write_buffer)		\
 28		common->ops->enable_write_buffer((_ah));
 29
 30#define REGWRITE_BUFFER_FLUSH(_ah)			\
 31	if (common->ops->write_flush)			\
 32		common->ops->write_flush((_ah));
 33
 34
 35#define IEEE80211_WEP_NKID      4       /* number of key ids */
 36
 37/************************/
 38/* Key Cache Management */
 39/************************/
 40
 41bool ath_hw_keyreset(struct ath_common *common, u16 entry)
 42{
 43	u32 keyType;
 44	void *ah = common->ah;
 45
 46	if (entry >= common->keymax) {
 47		ath_err(common, "keycache entry %u out of range\n", entry);
 48		return false;
 49	}
 50
 51	keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
 52
 53	ENABLE_REGWRITE_BUFFER(ah);
 54
 55	REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
 56	REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
 57	REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
 58	REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
 59	REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
 60	REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
 61	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
 62	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
 63
 64	if (keyType == AR_KEYTABLE_TYPE_TKIP) {
 65		u16 micentry = entry + 64;
 66
 67		REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
 68		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
 69		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
 70		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
 71		if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
 72			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
 73			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
 74				  AR_KEYTABLE_TYPE_CLR);
 75		}
 76
 77	}
 78
 79	REGWRITE_BUFFER_FLUSH(ah);
 80
 81	return true;
 82}
 83EXPORT_SYMBOL(ath_hw_keyreset);
 84
 85static bool ath_hw_keysetmac(struct ath_common *common,
 86			     u16 entry, const u8 *mac)
 87{
 88	u32 macHi, macLo;
 89	u32 unicast_flag = AR_KEYTABLE_VALID;
 90	void *ah = common->ah;
 91
 92	if (entry >= common->keymax) {
 93		ath_err(common, "keycache entry %u out of range\n", entry);
 94		return false;
 95	}
 96
 97	if (mac != NULL) {
 98		/*
 99		 * AR_KEYTABLE_VALID indicates that the address is a unicast
100		 * address, which must match the transmitter address for
101		 * decrypting frames.
102		 * Not setting this bit allows the hardware to use the key
103		 * for multicast frame decryption.
104		 */
105		if (mac[0] & 0x01)
106			unicast_flag = 0;
107
108		macHi = (mac[5] << 8) | mac[4];
109		macLo = (mac[3] << 24) |
110			(mac[2] << 16) |
111			(mac[1] << 8) |
112			mac[0];
113		macLo >>= 1;
114		macLo |= (macHi & 1) << 31;
115		macHi >>= 1;
116	} else {
117		macLo = macHi = 0;
118	}
119	ENABLE_REGWRITE_BUFFER(ah);
120
121	REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
122	REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
123
124	REGWRITE_BUFFER_FLUSH(ah);
125
126	return true;
127}
128
129static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
130				      const struct ath_keyval *k,
131				      const u8 *mac)
132{
133	void *ah = common->ah;
134	u32 key0, key1, key2, key3, key4;
135	u32 keyType;
136
137	if (entry >= common->keymax) {
138		ath_err(common, "keycache entry %u out of range\n", entry);
139		return false;
140	}
141
142	switch (k->kv_type) {
143	case ATH_CIPHER_AES_OCB:
144		keyType = AR_KEYTABLE_TYPE_AES;
145		break;
146	case ATH_CIPHER_AES_CCM:
147		if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
148			ath_dbg(common, ATH_DBG_ANY,
149				"AES-CCM not supported by this mac rev\n");
150			return false;
151		}
152		keyType = AR_KEYTABLE_TYPE_CCM;
153		break;
154	case ATH_CIPHER_TKIP:
155		keyType = AR_KEYTABLE_TYPE_TKIP;
156		if (entry + 64 >= common->keymax) {
157			ath_dbg(common, ATH_DBG_ANY,
158				"entry %u inappropriate for TKIP\n", entry);
159			return false;
160		}
161		break;
162	case ATH_CIPHER_WEP:
163		if (k->kv_len < WLAN_KEY_LEN_WEP40) {
164			ath_dbg(common, ATH_DBG_ANY,
165				"WEP key length %u too small\n", k->kv_len);
166			return false;
167		}
168		if (k->kv_len <= WLAN_KEY_LEN_WEP40)
169			keyType = AR_KEYTABLE_TYPE_40;
170		else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
171			keyType = AR_KEYTABLE_TYPE_104;
172		else
173			keyType = AR_KEYTABLE_TYPE_128;
174		break;
175	case ATH_CIPHER_CLR:
176		keyType = AR_KEYTABLE_TYPE_CLR;
177		break;
178	default:
179		ath_err(common, "cipher %u not supported\n", k->kv_type);
180		return false;
181	}
182
183	key0 = get_unaligned_le32(k->kv_val + 0);
184	key1 = get_unaligned_le16(k->kv_val + 4);
185	key2 = get_unaligned_le32(k->kv_val + 6);
186	key3 = get_unaligned_le16(k->kv_val + 10);
187	key4 = get_unaligned_le32(k->kv_val + 12);
188	if (k->kv_len <= WLAN_KEY_LEN_WEP104)
189		key4 &= 0xff;
190
191	/*
192	 * Note: Key cache registers access special memory area that requires
193	 * two 32-bit writes to actually update the values in the internal
194	 * memory. Consequently, the exact order and pairs used here must be
195	 * maintained.
196	 */
197
198	if (keyType == AR_KEYTABLE_TYPE_TKIP) {
199		u16 micentry = entry + 64;
200
201		/*
202		 * Write inverted key[47:0] first to avoid Michael MIC errors
203		 * on frames that could be sent or received at the same time.
204		 * The correct key will be written in the end once everything
205		 * else is ready.
206		 */
207		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
208		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
209
210		/* Write key[95:48] */
211		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
212		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
213
214		/* Write key[127:96] and key type */
215		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
216		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
217
218		/* Write MAC address for the entry */
219		(void) ath_hw_keysetmac(common, entry, mac);
220
221		if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
222			/*
223			 * TKIP uses two key cache entries:
224			 * Michael MIC TX/RX keys in the same key cache entry
225			 * (idx = main index + 64):
226			 * key0 [31:0] = RX key [31:0]
227			 * key1 [15:0] = TX key [31:16]
228			 * key1 [31:16] = reserved
229			 * key2 [31:0] = RX key [63:32]
230			 * key3 [15:0] = TX key [15:0]
231			 * key3 [31:16] = reserved
232			 * key4 [31:0] = TX key [63:32]
233			 */
234			u32 mic0, mic1, mic2, mic3, mic4;
235
236			mic0 = get_unaligned_le32(k->kv_mic + 0);
237			mic2 = get_unaligned_le32(k->kv_mic + 4);
238			mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
239			mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
240			mic4 = get_unaligned_le32(k->kv_txmic + 4);
241
242			ENABLE_REGWRITE_BUFFER(ah);
243
244			/* Write RX[31:0] and TX[31:16] */
245			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
246			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
247
248			/* Write RX[63:32] and TX[15:0] */
249			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
250			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
251
252			/* Write TX[63:32] and keyType(reserved) */
253			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
254			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
255				  AR_KEYTABLE_TYPE_CLR);
256
257			REGWRITE_BUFFER_FLUSH(ah);
258
259		} else {
260			/*
261			 * TKIP uses four key cache entries (two for group
262			 * keys):
263			 * Michael MIC TX/RX keys are in different key cache
264			 * entries (idx = main index + 64 for TX and
265			 * main index + 32 + 96 for RX):
266			 * key0 [31:0] = TX/RX MIC key [31:0]
267			 * key1 [31:0] = reserved
268			 * key2 [31:0] = TX/RX MIC key [63:32]
269			 * key3 [31:0] = reserved
270			 * key4 [31:0] = reserved
271			 *
272			 * Upper layer code will call this function separately
273			 * for TX and RX keys when these registers offsets are
274			 * used.
275			 */
276			u32 mic0, mic2;
277
278			mic0 = get_unaligned_le32(k->kv_mic + 0);
279			mic2 = get_unaligned_le32(k->kv_mic + 4);
280
281			ENABLE_REGWRITE_BUFFER(ah);
282
283			/* Write MIC key[31:0] */
284			REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
285			REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
286
287			/* Write MIC key[63:32] */
288			REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
289			REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
290
291			/* Write TX[63:32] and keyType(reserved) */
292			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
293			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
294				  AR_KEYTABLE_TYPE_CLR);
295
296			REGWRITE_BUFFER_FLUSH(ah);
297		}
298
299		ENABLE_REGWRITE_BUFFER(ah);
300
301		/* MAC address registers are reserved for the MIC entry */
302		REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
303		REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
304
305		/*
306		 * Write the correct (un-inverted) key[47:0] last to enable
307		 * TKIP now that all other registers are set with correct
308		 * values.
309		 */
310		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
311		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
312
313		REGWRITE_BUFFER_FLUSH(ah);
314	} else {
315		ENABLE_REGWRITE_BUFFER(ah);
316
317		/* Write key[47:0] */
318		REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
319		REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
320
321		/* Write key[95:48] */
322		REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
323		REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
324
325		/* Write key[127:96] and key type */
326		REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
327		REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
328
329		REGWRITE_BUFFER_FLUSH(ah);
330
331		/* Write MAC address for the entry */
332		(void) ath_hw_keysetmac(common, entry, mac);
333	}
334
335	return true;
336}
337
338static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
339			   struct ath_keyval *hk, const u8 *addr,
340			   bool authenticator)
341{
342	const u8 *key_rxmic;
343	const u8 *key_txmic;
344
345	key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
346	key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
347
348	if (addr == NULL) {
349		/*
350		 * Group key installation - only two key cache entries are used
351		 * regardless of splitmic capability since group key is only
352		 * used either for TX or RX.
353		 */
354		if (authenticator) {
355			memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
356			memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
357		} else {
358			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
359			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
360		}
361		return ath_hw_set_keycache_entry(common, keyix, hk, addr);
362	}
363	if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
364		/* TX and RX keys share the same key cache entry. */
365		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
366		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
367		return ath_hw_set_keycache_entry(common, keyix, hk, addr);
368	}
369
370	/* Separate key cache entries for TX and RX */
371
372	/* TX key goes at first index, RX key at +32. */
373	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
374	if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) {
375		/* TX MIC entry failed. No need to proceed further */
376		ath_err(common, "Setting TX MIC Key Failed\n");
377		return 0;
378	}
379
380	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
381	/* XXX delete tx key on failure? */
382	return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr);
383}
384
385static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
386{
387	int i;
388
389	for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
390		if (test_bit(i, common->keymap) ||
391		    test_bit(i + 64, common->keymap))
392			continue; /* At least one part of TKIP key allocated */
393		if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) &&
394		    (test_bit(i + 32, common->keymap) ||
395		     test_bit(i + 64 + 32, common->keymap)))
396			continue; /* At least one part of TKIP key allocated */
397
398		/* Found a free slot for a TKIP key */
399		return i;
400	}
401	return -1;
402}
403
404static int ath_reserve_key_cache_slot(struct ath_common *common,
405				      u32 cipher)
406{
407	int i;
408
409	if (cipher == WLAN_CIPHER_SUITE_TKIP)
410		return ath_reserve_key_cache_slot_tkip(common);
411
412	/* First, try to find slots that would not be available for TKIP. */
413	if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
414		for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
415			if (!test_bit(i, common->keymap) &&
416			    (test_bit(i + 32, common->keymap) ||
417			     test_bit(i + 64, common->keymap) ||
418			     test_bit(i + 64 + 32, common->keymap)))
419				return i;
420			if (!test_bit(i + 32, common->keymap) &&
421			    (test_bit(i, common->keymap) ||
422			     test_bit(i + 64, common->keymap) ||
423			     test_bit(i + 64 + 32, common->keymap)))
424				return i + 32;
425			if (!test_bit(i + 64, common->keymap) &&
426			    (test_bit(i , common->keymap) ||
427			     test_bit(i + 32, common->keymap) ||
428			     test_bit(i + 64 + 32, common->keymap)))
429				return i + 64;
430			if (!test_bit(i + 64 + 32, common->keymap) &&
431			    (test_bit(i, common->keymap) ||
432			     test_bit(i + 32, common->keymap) ||
433			     test_bit(i + 64, common->keymap)))
434				return i + 64 + 32;
435		}
436	} else {
437		for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
438			if (!test_bit(i, common->keymap) &&
439			    test_bit(i + 64, common->keymap))
440				return i;
441			if (test_bit(i, common->keymap) &&
442			    !test_bit(i + 64, common->keymap))
443				return i + 64;
444		}
445	}
446
447	/* No partially used TKIP slots, pick any available slot */
448	for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
449		/* Do not allow slots that could be needed for TKIP group keys
450		 * to be used. This limitation could be removed if we know that
451		 * TKIP will not be used. */
452		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
453			continue;
454		if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
455			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
456				continue;
457			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
458				continue;
459		}
460
461		if (!test_bit(i, common->keymap))
462			return i; /* Found a free slot for a key */
463	}
464
465	/* No free slot found */
466	return -1;
467}
468
469/*
470 * Configure encryption in the HW.
471 */
472int ath_key_config(struct ath_common *common,
473			  struct ieee80211_vif *vif,
474			  struct ieee80211_sta *sta,
475			  struct ieee80211_key_conf *key)
476{
477	struct ath_keyval hk;
478	const u8 *mac = NULL;
479	u8 gmac[ETH_ALEN];
480	int ret = 0;
481	int idx;
482
483	memset(&hk, 0, sizeof(hk));
484
485	switch (key->cipher) {
486	case 0:
487		hk.kv_type = ATH_CIPHER_CLR;
488		break;
489	case WLAN_CIPHER_SUITE_WEP40:
490	case WLAN_CIPHER_SUITE_WEP104:
491		hk.kv_type = ATH_CIPHER_WEP;
492		break;
493	case WLAN_CIPHER_SUITE_TKIP:
494		hk.kv_type = ATH_CIPHER_TKIP;
495		break;
496	case WLAN_CIPHER_SUITE_CCMP:
497		hk.kv_type = ATH_CIPHER_AES_CCM;
498		break;
499	default:
500		return -EOPNOTSUPP;
501	}
502
503	hk.kv_len = key->keylen;
504	if (key->keylen)
505		memcpy(hk.kv_val, key->key, key->keylen);
506
507	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
508		switch (vif->type) {
509		case NL80211_IFTYPE_AP:
510			memcpy(gmac, vif->addr, ETH_ALEN);
511			gmac[0] |= 0x01;
512			mac = gmac;
513			idx = ath_reserve_key_cache_slot(common, key->cipher);
514			break;
515		case NL80211_IFTYPE_ADHOC:
516			if (!sta) {
517				idx = key->keyidx;
518				break;
519			}
520			memcpy(gmac, sta->addr, ETH_ALEN);
521			gmac[0] |= 0x01;
522			mac = gmac;
523			idx = ath_reserve_key_cache_slot(common, key->cipher);
524			break;
525		default:
526			idx = key->keyidx;
527			break;
528		}
529	} else if (key->keyidx) {
530		if (WARN_ON(!sta))
531			return -EOPNOTSUPP;
532		mac = sta->addr;
533
534		if (vif->type != NL80211_IFTYPE_AP) {
535			/* Only keyidx 0 should be used with unicast key, but
536			 * allow this for client mode for now. */
537			idx = key->keyidx;
538		} else
539			return -EIO;
540	} else {
541		if (WARN_ON(!sta))
542			return -EOPNOTSUPP;
543		mac = sta->addr;
544
545		idx = ath_reserve_key_cache_slot(common, key->cipher);
546	}
547
548	if (idx < 0)
549		return -ENOSPC; /* no free key cache entries */
550
551	if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
552		ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
553				      vif->type == NL80211_IFTYPE_AP);
554	else
555		ret = ath_hw_set_keycache_entry(common, idx, &hk, mac);
556
557	if (!ret)
558		return -EIO;
559
560	set_bit(idx, common->keymap);
561	if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
562		set_bit(idx + 64, common->keymap);
563		set_bit(idx, common->tkip_keymap);
564		set_bit(idx + 64, common->tkip_keymap);
565		if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
566			set_bit(idx + 32, common->keymap);
567			set_bit(idx + 64 + 32, common->keymap);
568			set_bit(idx + 32, common->tkip_keymap);
569			set_bit(idx + 64 + 32, common->tkip_keymap);
570		}
571	}
572
573	return idx;
574}
575EXPORT_SYMBOL(ath_key_config);
576
577/*
578 * Delete Key.
579 */
580void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
581{
582	ath_hw_keyreset(common, key->hw_key_idx);
583	if (key->hw_key_idx < IEEE80211_WEP_NKID)
584		return;
585
586	clear_bit(key->hw_key_idx, common->keymap);
587	if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
588		return;
589
590	clear_bit(key->hw_key_idx + 64, common->keymap);
591
592	clear_bit(key->hw_key_idx, common->tkip_keymap);
593	clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
594
595	if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
596		ath_hw_keyreset(common, key->hw_key_idx + 32);
597		clear_bit(key->hw_key_idx + 32, common->keymap);
598		clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
599
600		clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
601		clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
602	}
603}
604EXPORT_SYMBOL(ath_key_delete);