aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/common.c
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2010-03-17 04:55:25 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-03-23 16:50:17 -0400
commitfb9987d0f748c983bb795a86f47522313f701a08 (patch)
treee70d809b887ba25ed1a5da018e8baae829d0b8ad /drivers/net/wireless/ath/ath9k/common.c
parent736b3a27b3c50c4a23717b802240435a69e8d0ff (diff)
ath9k_htc: Support for AR9271 chipset.
Features: * Station mode * IBSS mode * Monitor mode * Legacy support * HT support * TX/RX 11n Aggregation * HW encryption * LED * Suspend/Resume For more information: http://wireless.kernel.org/en/users/Drivers/ath9k_htc Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com> Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/common.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 4d775ae141db..7902d287f671 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -286,6 +286,427 @@ int ath9k_cmn_padpos(__le16 frame_control)
286} 286}
287EXPORT_SYMBOL(ath9k_cmn_padpos); 287EXPORT_SYMBOL(ath9k_cmn_padpos);
288 288
289int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
290{
291 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
292
293 if (tx_info->control.hw_key) {
294 if (tx_info->control.hw_key->alg == ALG_WEP)
295 return ATH9K_KEY_TYPE_WEP;
296 else if (tx_info->control.hw_key->alg == ALG_TKIP)
297 return ATH9K_KEY_TYPE_TKIP;
298 else if (tx_info->control.hw_key->alg == ALG_CCMP)
299 return ATH9K_KEY_TYPE_AES;
300 }
301
302 return ATH9K_KEY_TYPE_CLEAR;
303}
304EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
305
306/*
307 * Calculate the RX filter to be set in the HW.
308 */
309u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah,
310 unsigned int rxfilter)
311{
312#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
313
314 u32 rfilt;
315
316 rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE)
317 | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
318 | ATH9K_RX_FILTER_MCAST;
319
320 /* If not a STA, enable processing of Probe Requests */
321 if (ah->opmode != NL80211_IFTYPE_STATION)
322 rfilt |= ATH9K_RX_FILTER_PROBEREQ;
323
324 /*
325 * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
326 * mode interface or when in monitor mode. AP mode does not need this
327 * since it receives all in-BSS frames anyway.
328 */
329 if (((ah->opmode != NL80211_IFTYPE_AP) &&
330 (rxfilter & FIF_PROMISC_IN_BSS)) ||
331 (ah->opmode == NL80211_IFTYPE_MONITOR))
332 rfilt |= ATH9K_RX_FILTER_PROM;
333
334 if (rxfilter & FIF_CONTROL)
335 rfilt |= ATH9K_RX_FILTER_CONTROL;
336
337 if ((ah->opmode == NL80211_IFTYPE_STATION) &&
338 !(rxfilter & FIF_BCN_PRBRESP_PROMISC))
339 rfilt |= ATH9K_RX_FILTER_MYBEACON;
340 else
341 rfilt |= ATH9K_RX_FILTER_BEACON;
342
343 if ((AR_SREV_9280_10_OR_LATER(ah) ||
344 AR_SREV_9285_10_OR_LATER(ah)) &&
345 (ah->opmode == NL80211_IFTYPE_AP) &&
346 (rxfilter & FIF_PSPOLL))
347 rfilt |= ATH9K_RX_FILTER_PSPOLL;
348
349 if (conf_is_ht(&hw->conf))
350 rfilt |= ATH9K_RX_FILTER_COMP_BAR;
351
352 return rfilt;
353
354#undef RX_FILTER_PRESERVE
355}
356EXPORT_SYMBOL(ath9k_cmn_calcrxfilter);
357
358/*
359 * Recv initialization for opmode change.
360 */
361void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah,
362 unsigned int rxfilter)
363{
364 struct ath_common *common = ath9k_hw_common(ah);
365
366 u32 rfilt, mfilt[2];
367
368 /* configure rx filter */
369 rfilt = ath9k_cmn_calcrxfilter(hw, ah, rxfilter);
370 ath9k_hw_setrxfilter(ah, rfilt);
371
372 /* configure bssid mask */
373 if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
374 ath_hw_setbssidmask(common);
375
376 /* configure operational mode */
377 ath9k_hw_setopmode(ah);
378
379 /* Handle any link-level address change. */
380 ath9k_hw_setmac(ah, common->macaddr);
381
382 /* calculate and install multicast filter */
383 mfilt[0] = mfilt[1] = ~0;
384 ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
385}
386EXPORT_SYMBOL(ath9k_cmn_opmode_init);
387
388static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
389 enum nl80211_channel_type channel_type)
390{
391 u32 chanmode = 0;
392
393 switch (chan->band) {
394 case IEEE80211_BAND_2GHZ:
395 switch (channel_type) {
396 case NL80211_CHAN_NO_HT:
397 case NL80211_CHAN_HT20:
398 chanmode = CHANNEL_G_HT20;
399 break;
400 case NL80211_CHAN_HT40PLUS:
401 chanmode = CHANNEL_G_HT40PLUS;
402 break;
403 case NL80211_CHAN_HT40MINUS:
404 chanmode = CHANNEL_G_HT40MINUS;
405 break;
406 }
407 break;
408 case IEEE80211_BAND_5GHZ:
409 switch (channel_type) {
410 case NL80211_CHAN_NO_HT:
411 case NL80211_CHAN_HT20:
412 chanmode = CHANNEL_A_HT20;
413 break;
414 case NL80211_CHAN_HT40PLUS:
415 chanmode = CHANNEL_A_HT40PLUS;
416 break;
417 case NL80211_CHAN_HT40MINUS:
418 chanmode = CHANNEL_A_HT40MINUS;
419 break;
420 }
421 break;
422 default:
423 break;
424 }
425
426 return chanmode;
427}
428
429/*
430 * Update internal channel flags.
431 */
432void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
433 struct ath9k_channel *ichan)
434{
435 struct ieee80211_channel *chan = hw->conf.channel;
436 struct ieee80211_conf *conf = &hw->conf;
437
438 ichan->channel = chan->center_freq;
439 ichan->chan = chan;
440
441 if (chan->band == IEEE80211_BAND_2GHZ) {
442 ichan->chanmode = CHANNEL_G;
443 ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G;
444 } else {
445 ichan->chanmode = CHANNEL_A;
446 ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
447 }
448
449 if (conf_is_ht(conf))
450 ichan->chanmode = ath9k_get_extchanmode(chan,
451 conf->channel_type);
452}
453EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
454
455/*
456 * Get the internal channel reference.
457 */
458struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
459 struct ath_hw *ah)
460{
461 struct ieee80211_channel *curchan = hw->conf.channel;
462 struct ath9k_channel *channel;
463 u8 chan_idx;
464
465 chan_idx = curchan->hw_value;
466 channel = &ah->channels[chan_idx];
467 ath9k_cmn_update_ichannel(hw, channel);
468
469 return channel;
470}
471EXPORT_SYMBOL(ath9k_cmn_get_curchannel);
472
473static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
474 struct ath9k_keyval *hk, const u8 *addr,
475 bool authenticator)
476{
477 struct ath_hw *ah = common->ah;
478 const u8 *key_rxmic;
479 const u8 *key_txmic;
480
481 key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
482 key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
483
484 if (addr == NULL) {
485 /*
486 * Group key installation - only two key cache entries are used
487 * regardless of splitmic capability since group key is only
488 * used either for TX or RX.
489 */
490 if (authenticator) {
491 memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
492 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
493 } else {
494 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
495 memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
496 }
497 return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
498 }
499 if (!common->splitmic) {
500 /* TX and RX keys share the same key cache entry. */
501 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
502 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
503 return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
504 }
505
506 /* Separate key cache entries for TX and RX */
507
508 /* TX key goes at first index, RX key at +32. */
509 memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
510 if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
511 /* TX MIC entry failed. No need to proceed further */
512 ath_print(common, ATH_DBG_FATAL,
513 "Setting TX MIC Key Failed\n");
514 return 0;
515 }
516
517 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
518 /* XXX delete tx key on failure? */
519 return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
520}
521
522static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
523{
524 int i;
525
526 for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
527 if (test_bit(i, common->keymap) ||
528 test_bit(i + 64, common->keymap))
529 continue; /* At least one part of TKIP key allocated */
530 if (common->splitmic &&
531 (test_bit(i + 32, common->keymap) ||
532 test_bit(i + 64 + 32, common->keymap)))
533 continue; /* At least one part of TKIP key allocated */
534
535 /* Found a free slot for a TKIP key */
536 return i;
537 }
538 return -1;
539}
540
541static int ath_reserve_key_cache_slot(struct ath_common *common)
542{
543 int i;
544
545 /* First, try to find slots that would not be available for TKIP. */
546 if (common->splitmic) {
547 for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
548 if (!test_bit(i, common->keymap) &&
549 (test_bit(i + 32, common->keymap) ||
550 test_bit(i + 64, common->keymap) ||
551 test_bit(i + 64 + 32, common->keymap)))
552 return i;
553 if (!test_bit(i + 32, common->keymap) &&
554 (test_bit(i, common->keymap) ||
555 test_bit(i + 64, common->keymap) ||
556 test_bit(i + 64 + 32, common->keymap)))
557 return i + 32;
558 if (!test_bit(i + 64, common->keymap) &&
559 (test_bit(i , common->keymap) ||
560 test_bit(i + 32, common->keymap) ||
561 test_bit(i + 64 + 32, common->keymap)))
562 return i + 64;
563 if (!test_bit(i + 64 + 32, common->keymap) &&
564 (test_bit(i, common->keymap) ||
565 test_bit(i + 32, common->keymap) ||
566 test_bit(i + 64, common->keymap)))
567 return i + 64 + 32;
568 }
569 } else {
570 for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
571 if (!test_bit(i, common->keymap) &&
572 test_bit(i + 64, common->keymap))
573 return i;
574 if (test_bit(i, common->keymap) &&
575 !test_bit(i + 64, common->keymap))
576 return i + 64;
577 }
578 }
579
580 /* No partially used TKIP slots, pick any available slot */
581 for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
582 /* Do not allow slots that could be needed for TKIP group keys
583 * to be used. This limitation could be removed if we know that
584 * TKIP will not be used. */
585 if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
586 continue;
587 if (common->splitmic) {
588 if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
589 continue;
590 if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
591 continue;
592 }
593
594 if (!test_bit(i, common->keymap))
595 return i; /* Found a free slot for a key */
596 }
597
598 /* No free slot found */
599 return -1;
600}
601
602/*
603 * Configure encryption in the HW.
604 */
605int ath9k_cmn_key_config(struct ath_common *common,
606 struct ieee80211_vif *vif,
607 struct ieee80211_sta *sta,
608 struct ieee80211_key_conf *key)
609{
610 struct ath_hw *ah = common->ah;
611 struct ath9k_keyval hk;
612 const u8 *mac = NULL;
613 int ret = 0;
614 int idx;
615
616 memset(&hk, 0, sizeof(hk));
617
618 switch (key->alg) {
619 case ALG_WEP:
620 hk.kv_type = ATH9K_CIPHER_WEP;
621 break;
622 case ALG_TKIP:
623 hk.kv_type = ATH9K_CIPHER_TKIP;
624 break;
625 case ALG_CCMP:
626 hk.kv_type = ATH9K_CIPHER_AES_CCM;
627 break;
628 default:
629 return -EOPNOTSUPP;
630 }
631
632 hk.kv_len = key->keylen;
633 memcpy(hk.kv_val, key->key, key->keylen);
634
635 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
636 /* For now, use the default keys for broadcast keys. This may
637 * need to change with virtual interfaces. */
638 idx = key->keyidx;
639 } else if (key->keyidx) {
640 if (WARN_ON(!sta))
641 return -EOPNOTSUPP;
642 mac = sta->addr;
643
644 if (vif->type != NL80211_IFTYPE_AP) {
645 /* Only keyidx 0 should be used with unicast key, but
646 * allow this for client mode for now. */
647 idx = key->keyidx;
648 } else
649 return -EIO;
650 } else {
651 if (WARN_ON(!sta))
652 return -EOPNOTSUPP;
653 mac = sta->addr;
654
655 if (key->alg == ALG_TKIP)
656 idx = ath_reserve_key_cache_slot_tkip(common);
657 else
658 idx = ath_reserve_key_cache_slot(common);
659 if (idx < 0)
660 return -ENOSPC; /* no free key cache entries */
661 }
662
663 if (key->alg == ALG_TKIP)
664 ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
665 vif->type == NL80211_IFTYPE_AP);
666 else
667 ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
668
669 if (!ret)
670 return -EIO;
671
672 set_bit(idx, common->keymap);
673 if (key->alg == ALG_TKIP) {
674 set_bit(idx + 64, common->keymap);
675 if (common->splitmic) {
676 set_bit(idx + 32, common->keymap);
677 set_bit(idx + 64 + 32, common->keymap);
678 }
679 }
680
681 return idx;
682}
683EXPORT_SYMBOL(ath9k_cmn_key_config);
684
685/*
686 * Delete Key.
687 */
688void ath9k_cmn_key_delete(struct ath_common *common,
689 struct ieee80211_key_conf *key)
690{
691 struct ath_hw *ah = common->ah;
692
693 ath9k_hw_keyreset(ah, key->hw_key_idx);
694 if (key->hw_key_idx < IEEE80211_WEP_NKID)
695 return;
696
697 clear_bit(key->hw_key_idx, common->keymap);
698 if (key->alg != ALG_TKIP)
699 return;
700
701 clear_bit(key->hw_key_idx + 64, common->keymap);
702 if (common->splitmic) {
703 ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
704 clear_bit(key->hw_key_idx + 32, common->keymap);
705 clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
706 }
707}
708EXPORT_SYMBOL(ath9k_cmn_key_delete);
709
289static int __init ath9k_cmn_init(void) 710static int __init ath9k_cmn_init(void)
290{ 711{
291 return 0; 712 return 0;