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 41 bool 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 } 83 EXPORT_SYMBOL(ath_hw_keyreset); 84 85 static 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 129 static 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 338 static 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 385 static 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 404 static 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 */ 472 int 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 WLAN_CIPHER_SUITE_WEP40: 487 case WLAN_CIPHER_SUITE_WEP104: 488 hk.kv_type = ATH_CIPHER_WEP; 489 break; 490 case WLAN_CIPHER_SUITE_TKIP: 491 hk.kv_type = ATH_CIPHER_TKIP; 492 break; 493 case WLAN_CIPHER_SUITE_CCMP: 494 hk.kv_type = ATH_CIPHER_AES_CCM; 495 break; 496 default: 497 return -EOPNOTSUPP; 498 } 499 500 hk.kv_len = key->keylen; 501 memcpy(hk.kv_val, key->key, key->keylen); 502 503 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { 504 switch (vif->type) { 505 case NL80211_IFTYPE_AP: 506 memcpy(gmac, vif->addr, ETH_ALEN); 507 gmac[0] |= 0x01; 508 mac = gmac; 509 idx = ath_reserve_key_cache_slot(common, key->cipher); 510 break; 511 case NL80211_IFTYPE_ADHOC: 512 if (!sta) { 513 idx = key->keyidx; 514 break; 515 } 516 memcpy(gmac, sta->addr, ETH_ALEN); 517 gmac[0] |= 0x01; 518 mac = gmac; 519 idx = ath_reserve_key_cache_slot(common, key->cipher); 520 break; 521 default: 522 idx = key->keyidx; 523 break; 524 } 525 } else if (key->keyidx) { 526 if (WARN_ON(!sta)) 527 return -EOPNOTSUPP; 528 mac = sta->addr; 529 530 if (vif->type != NL80211_IFTYPE_AP) { 531 /* Only keyidx 0 should be used with unicast key, but 532 * allow this for client mode for now. */ 533 idx = key->keyidx; 534 } else 535 return -EIO; 536 } else { 537 if (WARN_ON(!sta)) 538 return -EOPNOTSUPP; 539 mac = sta->addr; 540 541 idx = ath_reserve_key_cache_slot(common, key->cipher); 542 } 543 544 if (idx < 0) 545 return -ENOSPC; /* no free key cache entries */ 546 547 if (key->cipher == WLAN_CIPHER_SUITE_TKIP) 548 ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, 549 vif->type == NL80211_IFTYPE_AP); 550 else 551 ret = ath_hw_set_keycache_entry(common, idx, &hk, mac); 552 553 if (!ret) 554 return -EIO; 555 556 set_bit(idx, common->keymap); 557 if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { 558 set_bit(idx + 64, common->keymap); 559 set_bit(idx, common->tkip_keymap); 560 set_bit(idx + 64, common->tkip_keymap); 561 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { 562 set_bit(idx + 32, common->keymap); 563 set_bit(idx + 64 + 32, common->keymap); 564 set_bit(idx + 32, common->tkip_keymap); 565 set_bit(idx + 64 + 32, common->tkip_keymap); 566 } 567 } 568 569 return idx; 570 } 571 EXPORT_SYMBOL(ath_key_config); 572 573 /* 574 * Delete Key. 575 */ 576 void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key) 577 { 578 ath_hw_keyreset(common, key->hw_key_idx); 579 if (key->hw_key_idx < IEEE80211_WEP_NKID) 580 return; 581 582 clear_bit(key->hw_key_idx, common->keymap); 583 if (key->cipher != WLAN_CIPHER_SUITE_TKIP) 584 return; 585 586 clear_bit(key->hw_key_idx + 64, common->keymap); 587 588 clear_bit(key->hw_key_idx, common->tkip_keymap); 589 clear_bit(key->hw_key_idx + 64, common->tkip_keymap); 590 591 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) { 592 ath_hw_keyreset(common, key->hw_key_idx + 32); 593 clear_bit(key->hw_key_idx + 32, common->keymap); 594 clear_bit(key->hw_key_idx + 64 + 32, common->keymap); 595 596 clear_bit(key->hw_key_idx + 32, common->tkip_keymap); 597 clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap); 598 } 599 } 600 EXPORT_SYMBOL(ath_key_delete); 601