diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
34 files changed, 973 insertions, 860 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 35f23bdc442f..ad57a6d23110 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -32,6 +32,14 @@ config ATH9K_DEBUGFS | |||
32 | 32 | ||
33 | Also required for changing debug message flags at run time. | 33 | Also required for changing debug message flags at run time. |
34 | 34 | ||
35 | config ATH9K_RATE_CONTROL | ||
36 | bool "Atheros ath9k rate control" | ||
37 | depends on ATH9K | ||
38 | default y | ||
39 | ---help--- | ||
40 | Say Y, if you want to use the ath9k specific rate control | ||
41 | module instead of minstrel_ht. | ||
42 | |||
35 | config ATH9K_HTC | 43 | config ATH9K_HTC |
36 | tristate "Atheros HTC based wireless cards support" | 44 | tristate "Atheros HTC based wireless cards support" |
37 | depends on USB && MAC80211 | 45 | depends on USB && MAC80211 |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4555e9983903..aca01621c205 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -5,8 +5,8 @@ ath9k-y += beacon.o \ | |||
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o \ | 6 | xmit.o \ |
7 | virtual.o \ | 7 | virtual.o \ |
8 | rc.o | ||
9 | 8 | ||
9 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | ||
10 | ath9k-$(CONFIG_PCI) += pci.o | 10 | ath9k-$(CONFIG_PCI) += pci.o |
11 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o | 11 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o |
12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index cc648b6ae31c..0496f965314f 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
17 | #include "hw.h" | 18 | #include "hw.h" |
18 | #include "hw-ops.h" | 19 | #include "hw-ops.h" |
19 | 20 | ||
@@ -48,7 +49,7 @@ static const struct ani_ofdm_level_entry ofdm_level_table[] = { | |||
48 | { 7, 8, 0 } /* lvl 9 */ | 49 | { 7, 8, 0 } /* lvl 9 */ |
49 | }; | 50 | }; |
50 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ | 51 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ |
51 | (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0])) | 52 | ARRAY_SIZE(ofdm_level_table) |
52 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ | 53 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ |
53 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) | 54 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) |
54 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ | 55 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ |
@@ -94,7 +95,7 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
94 | }; | 95 | }; |
95 | 96 | ||
96 | #define ATH9K_ANI_CCK_NUM_LEVEL \ | 97 | #define ATH9K_ANI_CCK_NUM_LEVEL \ |
97 | (sizeof(cck_level_table)/sizeof(cck_level_table[0])) | 98 | ARRAY_SIZE(cck_level_table) |
98 | #define ATH9K_ANI_CCK_MAX_LEVEL \ | 99 | #define ATH9K_ANI_CCK_MAX_LEVEL \ |
99 | (ATH9K_ANI_CCK_NUM_LEVEL-1) | 100 | (ATH9K_ANI_CCK_NUM_LEVEL-1) |
100 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ | 101 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 303c63da5ea3..94392daebaa0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -580,3 +580,53 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) | |||
580 | else | 580 | else |
581 | ath9k_hw_attach_ani_ops_old(ah); | 581 | ath9k_hw_attach_ani_ops_old(ah); |
582 | } | 582 | } |
583 | |||
584 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | ||
585 | { | ||
586 | u32 modesIndex; | ||
587 | int i; | ||
588 | |||
589 | switch (chan->chanmode) { | ||
590 | case CHANNEL_A: | ||
591 | case CHANNEL_A_HT20: | ||
592 | modesIndex = 1; | ||
593 | break; | ||
594 | case CHANNEL_A_HT40PLUS: | ||
595 | case CHANNEL_A_HT40MINUS: | ||
596 | modesIndex = 2; | ||
597 | break; | ||
598 | case CHANNEL_G: | ||
599 | case CHANNEL_G_HT20: | ||
600 | case CHANNEL_B: | ||
601 | modesIndex = 4; | ||
602 | break; | ||
603 | case CHANNEL_G_HT40PLUS: | ||
604 | case CHANNEL_G_HT40MINUS: | ||
605 | modesIndex = 3; | ||
606 | break; | ||
607 | |||
608 | default: | ||
609 | return; | ||
610 | } | ||
611 | |||
612 | ENABLE_REGWRITE_BUFFER(ah); | ||
613 | |||
614 | for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) { | ||
615 | u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0); | ||
616 | u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex); | ||
617 | u32 val_orig; | ||
618 | |||
619 | if (reg == AR_PHY_CCK_DETECT) { | ||
620 | val_orig = REG_READ(ah, reg); | ||
621 | val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | ||
622 | val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | ||
623 | |||
624 | REG_WRITE(ah, reg, val|val_orig); | ||
625 | } else | ||
626 | REG_WRITE(ah, reg, val); | ||
627 | } | ||
628 | |||
629 | REGWRITE_BUFFER_FLUSH(ah); | ||
630 | DISABLE_REGWRITE_BUFFER(ah); | ||
631 | |||
632 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index adbf031fbc5a..cd56c8692705 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -530,3 +530,38 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | |||
530 | 530 | ||
531 | ar9002_hw_set_nf_limits(ah); | 531 | ar9002_hw_set_nf_limits(ah); |
532 | } | 532 | } |
533 | |||
534 | void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
535 | struct ath_hw_antcomb_conf *antconf) | ||
536 | { | ||
537 | u32 regval; | ||
538 | |||
539 | regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
540 | antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >> | ||
541 | AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S; | ||
542 | antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >> | ||
543 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; | ||
544 | antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> | ||
545 | AR_PHY_9285_FAST_DIV_BIAS_S; | ||
546 | } | ||
547 | EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_get); | ||
548 | |||
549 | void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
550 | struct ath_hw_antcomb_conf *antconf) | ||
551 | { | ||
552 | u32 regval; | ||
553 | |||
554 | regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
555 | regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | | ||
556 | AR_PHY_9285_ANT_DIV_ALT_LNACONF | | ||
557 | AR_PHY_9285_FAST_DIV_BIAS); | ||
558 | regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S) | ||
559 | & AR_PHY_9285_ANT_DIV_MAIN_LNACONF); | ||
560 | regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S) | ||
561 | & AR_PHY_9285_ANT_DIV_ALT_LNACONF); | ||
562 | regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S) | ||
563 | & AR_PHY_9285_FAST_DIV_BIAS); | ||
564 | |||
565 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); | ||
566 | } | ||
567 | EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_set); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index c5151a4dd10b..37663dbbcf57 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h | |||
@@ -302,6 +302,8 @@ | |||
302 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 | 302 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 |
303 | 303 | ||
304 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac | 304 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac |
305 | #define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00 | ||
306 | #define AR_PHY_9285_FAST_DIV_BIAS_S 9 | ||
305 | #define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 | 307 | #define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 |
306 | #define AR_PHY_9285_ANT_DIV_CTL 0x01000000 | 308 | #define AR_PHY_9285_ANT_DIV_CTL 0x01000000 |
307 | #define AR_PHY_9285_ANT_DIV_CTL_S 24 | 309 | #define AR_PHY_9285_ANT_DIV_CTL_S 24 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 057fb69ddf7f..c4182359bee4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -968,7 +968,7 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah) | |||
968 | } | 968 | } |
969 | 969 | ||
970 | static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, | 970 | static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, |
971 | enum ieee80211_band freq_band) | 971 | enum ath9k_hal_freq_band freq_band) |
972 | { | 972 | { |
973 | return 1; | 973 | return 1; |
974 | } | 974 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index a462da23e87e..3b424ca1ba84 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -616,7 +616,8 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
616 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | 616 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; |
617 | } else if (rxsp->status11 & AR_MichaelErr) { | 617 | } else if (rxsp->status11 & AR_MichaelErr) { |
618 | rxs->rs_status |= ATH9K_RXERR_MIC; | 618 | rxs->rs_status |= ATH9K_RXERR_MIC; |
619 | } | 619 | } else if (rxsp->status11 & AR_KeyMiss) |
620 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | ||
620 | } | 621 | } |
621 | 622 | ||
622 | return 0; | 623 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f0197a6046ab..9f8e542ef47e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -254,7 +254,7 @@ struct ath_atx_tid { | |||
254 | struct list_head buf_q; | 254 | struct list_head buf_q; |
255 | struct ath_node *an; | 255 | struct ath_node *an; |
256 | struct ath_atx_ac *ac; | 256 | struct ath_atx_ac *ac; |
257 | struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; | 257 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; |
258 | u16 seq_start; | 258 | u16 seq_start; |
259 | u16 seq_next; | 259 | u16 seq_next; |
260 | u16 baw_size; | 260 | u16 baw_size; |
@@ -345,9 +345,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
345 | void ath_tx_tasklet(struct ath_softc *sc); | 345 | void ath_tx_tasklet(struct ath_softc *sc); |
346 | void ath_tx_edma_tasklet(struct ath_softc *sc); | 346 | void ath_tx_edma_tasklet(struct ath_softc *sc); |
347 | void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); | 347 | void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); |
348 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); | 348 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
349 | void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 349 | u16 tid, u16 *ssn); |
350 | u16 tid, u16 *ssn); | ||
351 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 350 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
352 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 351 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
353 | void ath9k_enable_ps(struct ath_softc *sc); | 352 | void ath9k_enable_ps(struct ath_softc *sc); |
@@ -481,6 +480,60 @@ struct ath_led { | |||
481 | void ath_init_leds(struct ath_softc *sc); | 480 | void ath_init_leds(struct ath_softc *sc); |
482 | void ath_deinit_leds(struct ath_softc *sc); | 481 | void ath_deinit_leds(struct ath_softc *sc); |
483 | 482 | ||
483 | /* Antenna diversity/combining */ | ||
484 | #define ATH_ANT_RX_CURRENT_SHIFT 4 | ||
485 | #define ATH_ANT_RX_MAIN_SHIFT 2 | ||
486 | #define ATH_ANT_RX_MASK 0x3 | ||
487 | |||
488 | #define ATH_ANT_DIV_COMB_SHORT_SCAN_INTR 50 | ||
489 | #define ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT 0x100 | ||
490 | #define ATH_ANT_DIV_COMB_MAX_PKTCOUNT 0x200 | ||
491 | #define ATH_ANT_DIV_COMB_INIT_COUNT 95 | ||
492 | #define ATH_ANT_DIV_COMB_MAX_COUNT 100 | ||
493 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 | ||
494 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 | ||
495 | |||
496 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA -3 | ||
497 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 | ||
498 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 | ||
499 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 | ||
500 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 | ||
501 | |||
502 | enum ath9k_ant_div_comb_lna_conf { | ||
503 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, | ||
504 | ATH_ANT_DIV_COMB_LNA2, | ||
505 | ATH_ANT_DIV_COMB_LNA1, | ||
506 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2, | ||
507 | }; | ||
508 | |||
509 | struct ath_ant_comb { | ||
510 | u16 count; | ||
511 | u16 total_pkt_count; | ||
512 | bool scan; | ||
513 | bool scan_not_start; | ||
514 | int main_total_rssi; | ||
515 | int alt_total_rssi; | ||
516 | int alt_recv_cnt; | ||
517 | int main_recv_cnt; | ||
518 | int rssi_lna1; | ||
519 | int rssi_lna2; | ||
520 | int rssi_add; | ||
521 | int rssi_sub; | ||
522 | int rssi_first; | ||
523 | int rssi_second; | ||
524 | int rssi_third; | ||
525 | bool alt_good; | ||
526 | int quick_scan_cnt; | ||
527 | int main_conf; | ||
528 | enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; | ||
529 | enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; | ||
530 | int first_bias; | ||
531 | int second_bias; | ||
532 | bool first_ratio; | ||
533 | bool second_ratio; | ||
534 | unsigned long scan_start_time; | ||
535 | }; | ||
536 | |||
484 | /********************/ | 537 | /********************/ |
485 | /* Main driver core */ | 538 | /* Main driver core */ |
486 | /********************/ | 539 | /********************/ |
@@ -509,7 +562,6 @@ void ath_deinit_leds(struct ath_softc *sc); | |||
509 | #define SC_OP_RXFLUSH BIT(7) | 562 | #define SC_OP_RXFLUSH BIT(7) |
510 | #define SC_OP_LED_ASSOCIATED BIT(8) | 563 | #define SC_OP_LED_ASSOCIATED BIT(8) |
511 | #define SC_OP_LED_ON BIT(9) | 564 | #define SC_OP_LED_ON BIT(9) |
512 | #define SC_OP_SCANNING BIT(10) | ||
513 | #define SC_OP_TSF_RESET BIT(11) | 565 | #define SC_OP_TSF_RESET BIT(11) |
514 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) | 566 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) |
515 | #define SC_OP_BT_SCAN BIT(13) | 567 | #define SC_OP_BT_SCAN BIT(13) |
@@ -597,6 +649,8 @@ struct ath_softc { | |||
597 | struct ath_btcoex btcoex; | 649 | struct ath_btcoex btcoex; |
598 | 650 | ||
599 | struct ath_descdma txsdma; | 651 | struct ath_descdma txsdma; |
652 | |||
653 | struct ath_ant_comb ant_comb; | ||
600 | }; | 654 | }; |
601 | 655 | ||
602 | struct ath_wiphy { | 656 | struct ath_wiphy { |
@@ -663,7 +717,7 @@ static inline void ath_ahb_exit(void) {}; | |||
663 | void ath9k_ps_wakeup(struct ath_softc *sc); | 717 | void ath9k_ps_wakeup(struct ath_softc *sc); |
664 | void ath9k_ps_restore(struct ath_softc *sc); | 718 | void ath9k_ps_restore(struct ath_softc *sc); |
665 | 719 | ||
666 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw); | 720 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
667 | int ath9k_wiphy_add(struct ath_softc *sc); | 721 | int ath9k_wiphy_add(struct ath_softc *sc); |
668 | int ath9k_wiphy_del(struct ath_wiphy *aphy); | 722 | int ath9k_wiphy_del(struct ath_wiphy *aphy); |
669 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); | 723 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 2dab64bb23a8..f43a2d98421c 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -148,276 +148,6 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | |||
148 | } | 148 | } |
149 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); | 149 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); |
150 | 150 | ||
151 | static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, | ||
152 | struct ath9k_keyval *hk, const u8 *addr, | ||
153 | bool authenticator) | ||
154 | { | ||
155 | struct ath_hw *ah = common->ah; | ||
156 | const u8 *key_rxmic; | ||
157 | const u8 *key_txmic; | ||
158 | |||
159 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
160 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
161 | |||
162 | if (addr == NULL) { | ||
163 | /* | ||
164 | * Group key installation - only two key cache entries are used | ||
165 | * regardless of splitmic capability since group key is only | ||
166 | * used either for TX or RX. | ||
167 | */ | ||
168 | if (authenticator) { | ||
169 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
170 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); | ||
171 | } else { | ||
172 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
173 | memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); | ||
174 | } | ||
175 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
176 | } | ||
177 | if (!common->splitmic) { | ||
178 | /* TX and RX keys share the same key cache entry. */ | ||
179 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
180 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
181 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
182 | } | ||
183 | |||
184 | /* Separate key cache entries for TX and RX */ | ||
185 | |||
186 | /* TX key goes at first index, RX key at +32. */ | ||
187 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
188 | if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { | ||
189 | /* TX MIC entry failed. No need to proceed further */ | ||
190 | ath_print(common, ATH_DBG_FATAL, | ||
191 | "Setting TX MIC Key Failed\n"); | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
196 | /* XXX delete tx key on failure? */ | ||
197 | return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); | ||
198 | } | ||
199 | |||
200 | static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | ||
201 | { | ||
202 | int i; | ||
203 | |||
204 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
205 | if (test_bit(i, common->keymap) || | ||
206 | test_bit(i + 64, common->keymap)) | ||
207 | continue; /* At least one part of TKIP key allocated */ | ||
208 | if (common->splitmic && | ||
209 | (test_bit(i + 32, common->keymap) || | ||
210 | test_bit(i + 64 + 32, common->keymap))) | ||
211 | continue; /* At least one part of TKIP key allocated */ | ||
212 | |||
213 | /* Found a free slot for a TKIP key */ | ||
214 | return i; | ||
215 | } | ||
216 | return -1; | ||
217 | } | ||
218 | |||
219 | static int ath_reserve_key_cache_slot(struct ath_common *common, | ||
220 | u32 cipher) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | if (cipher == WLAN_CIPHER_SUITE_TKIP) | ||
225 | return ath_reserve_key_cache_slot_tkip(common); | ||
226 | |||
227 | /* First, try to find slots that would not be available for TKIP. */ | ||
228 | if (common->splitmic) { | ||
229 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | ||
230 | if (!test_bit(i, common->keymap) && | ||
231 | (test_bit(i + 32, common->keymap) || | ||
232 | test_bit(i + 64, common->keymap) || | ||
233 | test_bit(i + 64 + 32, common->keymap))) | ||
234 | return i; | ||
235 | if (!test_bit(i + 32, common->keymap) && | ||
236 | (test_bit(i, common->keymap) || | ||
237 | test_bit(i + 64, common->keymap) || | ||
238 | test_bit(i + 64 + 32, common->keymap))) | ||
239 | return i + 32; | ||
240 | if (!test_bit(i + 64, common->keymap) && | ||
241 | (test_bit(i , common->keymap) || | ||
242 | test_bit(i + 32, common->keymap) || | ||
243 | test_bit(i + 64 + 32, common->keymap))) | ||
244 | return i + 64; | ||
245 | if (!test_bit(i + 64 + 32, common->keymap) && | ||
246 | (test_bit(i, common->keymap) || | ||
247 | test_bit(i + 32, common->keymap) || | ||
248 | test_bit(i + 64, common->keymap))) | ||
249 | return i + 64 + 32; | ||
250 | } | ||
251 | } else { | ||
252 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
253 | if (!test_bit(i, common->keymap) && | ||
254 | test_bit(i + 64, common->keymap)) | ||
255 | return i; | ||
256 | if (test_bit(i, common->keymap) && | ||
257 | !test_bit(i + 64, common->keymap)) | ||
258 | return i + 64; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* No partially used TKIP slots, pick any available slot */ | ||
263 | for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { | ||
264 | /* Do not allow slots that could be needed for TKIP group keys | ||
265 | * to be used. This limitation could be removed if we know that | ||
266 | * TKIP will not be used. */ | ||
267 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
268 | continue; | ||
269 | if (common->splitmic) { | ||
270 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
271 | continue; | ||
272 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
273 | continue; | ||
274 | } | ||
275 | |||
276 | if (!test_bit(i, common->keymap)) | ||
277 | return i; /* Found a free slot for a key */ | ||
278 | } | ||
279 | |||
280 | /* No free slot found */ | ||
281 | return -1; | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Configure encryption in the HW. | ||
286 | */ | ||
287 | int ath9k_cmn_key_config(struct ath_common *common, | ||
288 | struct ieee80211_vif *vif, | ||
289 | struct ieee80211_sta *sta, | ||
290 | struct ieee80211_key_conf *key) | ||
291 | { | ||
292 | struct ath_hw *ah = common->ah; | ||
293 | struct ath9k_keyval hk; | ||
294 | const u8 *mac = NULL; | ||
295 | u8 gmac[ETH_ALEN]; | ||
296 | int ret = 0; | ||
297 | int idx; | ||
298 | |||
299 | memset(&hk, 0, sizeof(hk)); | ||
300 | |||
301 | switch (key->cipher) { | ||
302 | case WLAN_CIPHER_SUITE_WEP40: | ||
303 | case WLAN_CIPHER_SUITE_WEP104: | ||
304 | hk.kv_type = ATH9K_CIPHER_WEP; | ||
305 | break; | ||
306 | case WLAN_CIPHER_SUITE_TKIP: | ||
307 | hk.kv_type = ATH9K_CIPHER_TKIP; | ||
308 | break; | ||
309 | case WLAN_CIPHER_SUITE_CCMP: | ||
310 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | ||
311 | break; | ||
312 | default: | ||
313 | return -EOPNOTSUPP; | ||
314 | } | ||
315 | |||
316 | hk.kv_len = key->keylen; | ||
317 | memcpy(hk.kv_val, key->key, key->keylen); | ||
318 | |||
319 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
320 | switch (vif->type) { | ||
321 | case NL80211_IFTYPE_AP: | ||
322 | memcpy(gmac, vif->addr, ETH_ALEN); | ||
323 | gmac[0] |= 0x01; | ||
324 | mac = gmac; | ||
325 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
326 | break; | ||
327 | case NL80211_IFTYPE_ADHOC: | ||
328 | if (!sta) { | ||
329 | idx = key->keyidx; | ||
330 | break; | ||
331 | } | ||
332 | memcpy(gmac, sta->addr, ETH_ALEN); | ||
333 | gmac[0] |= 0x01; | ||
334 | mac = gmac; | ||
335 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
336 | break; | ||
337 | default: | ||
338 | idx = key->keyidx; | ||
339 | break; | ||
340 | } | ||
341 | } else if (key->keyidx) { | ||
342 | if (WARN_ON(!sta)) | ||
343 | return -EOPNOTSUPP; | ||
344 | mac = sta->addr; | ||
345 | |||
346 | if (vif->type != NL80211_IFTYPE_AP) { | ||
347 | /* Only keyidx 0 should be used with unicast key, but | ||
348 | * allow this for client mode for now. */ | ||
349 | idx = key->keyidx; | ||
350 | } else | ||
351 | return -EIO; | ||
352 | } else { | ||
353 | if (WARN_ON(!sta)) | ||
354 | return -EOPNOTSUPP; | ||
355 | mac = sta->addr; | ||
356 | |||
357 | idx = ath_reserve_key_cache_slot(common, key->cipher); | ||
358 | } | ||
359 | |||
360 | if (idx < 0) | ||
361 | return -ENOSPC; /* no free key cache entries */ | ||
362 | |||
363 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | ||
364 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | ||
365 | vif->type == NL80211_IFTYPE_AP); | ||
366 | else | ||
367 | ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); | ||
368 | |||
369 | if (!ret) | ||
370 | return -EIO; | ||
371 | |||
372 | set_bit(idx, common->keymap); | ||
373 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { | ||
374 | set_bit(idx + 64, common->keymap); | ||
375 | set_bit(idx, common->tkip_keymap); | ||
376 | set_bit(idx + 64, common->tkip_keymap); | ||
377 | if (common->splitmic) { | ||
378 | set_bit(idx + 32, common->keymap); | ||
379 | set_bit(idx + 64 + 32, common->keymap); | ||
380 | set_bit(idx + 32, common->tkip_keymap); | ||
381 | set_bit(idx + 64 + 32, common->tkip_keymap); | ||
382 | } | ||
383 | } | ||
384 | |||
385 | return idx; | ||
386 | } | ||
387 | EXPORT_SYMBOL(ath9k_cmn_key_config); | ||
388 | |||
389 | /* | ||
390 | * Delete Key. | ||
391 | */ | ||
392 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
393 | struct ieee80211_key_conf *key) | ||
394 | { | ||
395 | struct ath_hw *ah = common->ah; | ||
396 | |||
397 | ath9k_hw_keyreset(ah, key->hw_key_idx); | ||
398 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
399 | return; | ||
400 | |||
401 | clear_bit(key->hw_key_idx, common->keymap); | ||
402 | if (key->cipher != WLAN_CIPHER_SUITE_TKIP) | ||
403 | return; | ||
404 | |||
405 | clear_bit(key->hw_key_idx + 64, common->keymap); | ||
406 | |||
407 | clear_bit(key->hw_key_idx, common->tkip_keymap); | ||
408 | clear_bit(key->hw_key_idx + 64, common->tkip_keymap); | ||
409 | |||
410 | if (common->splitmic) { | ||
411 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | ||
412 | clear_bit(key->hw_key_idx + 32, common->keymap); | ||
413 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | ||
414 | |||
415 | clear_bit(key->hw_key_idx + 32, common->tkip_keymap); | ||
416 | clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap); | ||
417 | } | ||
418 | } | ||
419 | EXPORT_SYMBOL(ath9k_cmn_key_delete); | ||
420 | |||
421 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) | 151 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) |
422 | { | 152 | { |
423 | int streams = 0; | 153 | int streams = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 4aa4e7dbe4d2..fea3b3315391 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -66,12 +66,6 @@ void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | |||
66 | struct ath9k_channel *ichan); | 66 | struct ath9k_channel *ichan); |
67 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 67 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, |
68 | struct ath_hw *ah); | 68 | struct ath_hw *ah); |
69 | int ath9k_cmn_key_config(struct ath_common *common, | ||
70 | struct ieee80211_vif *vif, | ||
71 | struct ieee80211_sta *sta, | ||
72 | struct ieee80211_key_conf *key); | ||
73 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
74 | struct ieee80211_key_conf *key); | ||
75 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 69 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
76 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | 70 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, |
77 | enum ath_stomp_type stomp_type); | 71 | enum ath_stomp_type stomp_type); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 54aae931424e..d65a896a421d 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -492,12 +492,55 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
492 | unsigned int len = 0; | 492 | unsigned int len = 0; |
493 | int i; | 493 | int i; |
494 | u8 addr[ETH_ALEN]; | 494 | u8 addr[ETH_ALEN]; |
495 | u32 tmp; | ||
495 | 496 | ||
496 | len += snprintf(buf + len, sizeof(buf) - len, | 497 | len += snprintf(buf + len, sizeof(buf) - len, |
497 | "primary: %s (%s chan=%d ht=%d)\n", | 498 | "primary: %s (%s chan=%d ht=%d)\n", |
498 | wiphy_name(sc->pri_wiphy->hw->wiphy), | 499 | wiphy_name(sc->pri_wiphy->hw->wiphy), |
499 | ath_wiphy_state_str(sc->pri_wiphy->state), | 500 | ath_wiphy_state_str(sc->pri_wiphy->state), |
500 | sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); | 501 | sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); |
502 | |||
503 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | ||
504 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | ||
505 | len += snprintf(buf + len, sizeof(buf) - len, | ||
506 | "addr: %pM\n", addr); | ||
507 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr); | ||
508 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); | ||
509 | len += snprintf(buf + len, sizeof(buf) - len, | ||
510 | "addrmask: %pM\n", addr); | ||
511 | tmp = ath9k_hw_getrxfilter(sc->sc_ah); | ||
512 | len += snprintf(buf + len, sizeof(buf) - len, | ||
513 | "rfilt: 0x%x", tmp); | ||
514 | if (tmp & ATH9K_RX_FILTER_UCAST) | ||
515 | len += snprintf(buf + len, sizeof(buf) - len, " UCAST"); | ||
516 | if (tmp & ATH9K_RX_FILTER_MCAST) | ||
517 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST"); | ||
518 | if (tmp & ATH9K_RX_FILTER_BCAST) | ||
519 | len += snprintf(buf + len, sizeof(buf) - len, " BCAST"); | ||
520 | if (tmp & ATH9K_RX_FILTER_CONTROL) | ||
521 | len += snprintf(buf + len, sizeof(buf) - len, " CONTROL"); | ||
522 | if (tmp & ATH9K_RX_FILTER_BEACON) | ||
523 | len += snprintf(buf + len, sizeof(buf) - len, " BEACON"); | ||
524 | if (tmp & ATH9K_RX_FILTER_PROM) | ||
525 | len += snprintf(buf + len, sizeof(buf) - len, " PROM"); | ||
526 | if (tmp & ATH9K_RX_FILTER_PROBEREQ) | ||
527 | len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ"); | ||
528 | if (tmp & ATH9K_RX_FILTER_PHYERR) | ||
529 | len += snprintf(buf + len, sizeof(buf) - len, " PHYERR"); | ||
530 | if (tmp & ATH9K_RX_FILTER_MYBEACON) | ||
531 | len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON"); | ||
532 | if (tmp & ATH9K_RX_FILTER_COMP_BAR) | ||
533 | len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR"); | ||
534 | if (tmp & ATH9K_RX_FILTER_PSPOLL) | ||
535 | len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL"); | ||
536 | if (tmp & ATH9K_RX_FILTER_PHYRADAR) | ||
537 | len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR"); | ||
538 | if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL) | ||
539 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n"); | ||
540 | else | ||
541 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | ||
542 | |||
543 | /* Put variable-length stuff down here, and check for overflows. */ | ||
501 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 544 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
502 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 545 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
503 | if (aphy == NULL) | 546 | if (aphy == NULL) |
@@ -508,16 +551,6 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
508 | ath_wiphy_state_str(aphy->state), | 551 | ath_wiphy_state_str(aphy->state), |
509 | aphy->chan_idx, aphy->chan_is_ht); | 552 | aphy->chan_idx, aphy->chan_is_ht); |
510 | } | 553 | } |
511 | |||
512 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | ||
513 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | ||
514 | len += snprintf(buf + len, sizeof(buf) - len, | ||
515 | "addr: %pM\n", addr); | ||
516 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr); | ||
517 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); | ||
518 | len += snprintf(buf + len, sizeof(buf) - len, | ||
519 | "addrmask: %pM\n", addr); | ||
520 | |||
521 | if (len > sizeof(buf)) | 554 | if (len > sizeof(buf)) |
522 | len = sizeof(buf); | 555 | len = sizeof(buf); |
523 | 556 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 0b09db0f8e7d..3030564a0f21 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -266,6 +266,8 @@ enum eeprom_param { | |||
266 | EEP_INTERNAL_REGULATOR, | 266 | EEP_INTERNAL_REGULATOR, |
267 | EEP_SWREG, | 267 | EEP_SWREG, |
268 | EEP_PAPRD, | 268 | EEP_PAPRD, |
269 | EEP_MODAL_VER, | ||
270 | EEP_ANT_DIV_CTL1, | ||
269 | }; | 271 | }; |
270 | 272 | ||
271 | enum ar5416_rates { | 273 | enum ar5416_rates { |
@@ -670,7 +672,8 @@ struct eeprom_ops { | |||
670 | bool (*fill_eeprom)(struct ath_hw *hw); | 672 | bool (*fill_eeprom)(struct ath_hw *hw); |
671 | int (*get_eeprom_ver)(struct ath_hw *hw); | 673 | int (*get_eeprom_ver)(struct ath_hw *hw); |
672 | int (*get_eeprom_rev)(struct ath_hw *hw); | 674 | int (*get_eeprom_rev)(struct ath_hw *hw); |
673 | u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); | 675 | u8 (*get_num_ant_config)(struct ath_hw *hw, |
676 | enum ath9k_hal_freq_band band); | ||
674 | u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, | 677 | u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, |
675 | struct ath9k_channel *chan); | 678 | struct ath9k_channel *chan); |
676 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); | 679 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 9cccd12e8f21..ead8b0dd3b53 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -213,6 +213,10 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
213 | return 0; | 213 | return 0; |
214 | case EEP_PWR_TABLE_OFFSET: | 214 | case EEP_PWR_TABLE_OFFSET: |
215 | return AR5416_PWR_TABLE_OFFSET_DB; | 215 | return AR5416_PWR_TABLE_OFFSET_DB; |
216 | case EEP_MODAL_VER: | ||
217 | return pModal->version; | ||
218 | case EEP_ANT_DIV_CTL1: | ||
219 | return pModal->antdiv_ctl1; | ||
216 | default: | 220 | default: |
217 | return 0; | 221 | return 0; |
218 | } | 222 | } |
@@ -1157,7 +1161,7 @@ static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, | |||
1157 | } | 1161 | } |
1158 | 1162 | ||
1159 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, | 1163 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, |
1160 | enum ieee80211_band freq_band) | 1164 | enum ath9k_hal_freq_band freq_band) |
1161 | { | 1165 | { |
1162 | return 1; | 1166 | return 1; |
1163 | } | 1167 | } |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index dff2da777312..e6186515d05b 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -1126,7 +1126,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, | |||
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, | 1128 | static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, |
1129 | enum ieee80211_band freq_band) | 1129 | enum ath9k_hal_freq_band freq_band) |
1130 | { | 1130 | { |
1131 | return 1; | 1131 | return 1; |
1132 | } | 1132 | } |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index afa2b73ddbdd..23f480d4c770 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -1418,11 +1418,11 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, | 1420 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, |
1421 | enum ieee80211_band freq_band) | 1421 | enum ath9k_hal_freq_band freq_band) |
1422 | { | 1422 | { |
1423 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | 1423 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
1424 | struct modal_eep_header *pModal = | 1424 | struct modal_eep_header *pModal = |
1425 | &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); | 1425 | &(eep->modalHeader[freq_band]); |
1426 | struct base_eep_header *pBase = &eep->baseEepHeader; | 1426 | struct base_eep_header *pBase = &eep->baseEepHeader; |
1427 | u8 num_ant_config; | 1427 | u8 num_ant_config; |
1428 | 1428 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 495f18950ac9..728d904c74d7 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -92,10 +92,10 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |||
92 | cmd->skb = skb; | 92 | cmd->skb = skb; |
93 | cmd->hif_dev = hif_dev; | 93 | cmd->hif_dev = hif_dev; |
94 | 94 | ||
95 | usb_fill_int_urb(urb, hif_dev->udev, | 95 | usb_fill_bulk_urb(urb, hif_dev->udev, |
96 | usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE), | 96 | usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE), |
97 | skb->data, skb->len, | 97 | skb->data, skb->len, |
98 | hif_usb_regout_cb, cmd, 1); | 98 | hif_usb_regout_cb, cmd); |
99 | 99 | ||
100 | usb_anchor_urb(urb, &hif_dev->regout_submitted); | 100 | usb_anchor_urb(urb, &hif_dev->regout_submitted); |
101 | ret = usb_submit_urb(urb, GFP_KERNEL); | 101 | ret = usb_submit_urb(urb, GFP_KERNEL); |
@@ -541,7 +541,8 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
541 | } | 541 | } |
542 | 542 | ||
543 | usb_fill_int_urb(urb, hif_dev->udev, | 543 | usb_fill_int_urb(urb, hif_dev->udev, |
544 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | 544 | usb_rcvbulkpipe(hif_dev->udev, |
545 | USB_REG_IN_PIPE), | ||
545 | nskb->data, MAX_REG_IN_BUF_SIZE, | 546 | nskb->data, MAX_REG_IN_BUF_SIZE, |
546 | ath9k_hif_usb_reg_in_cb, nskb, 1); | 547 | ath9k_hif_usb_reg_in_cb, nskb, 1); |
547 | 548 | ||
@@ -720,7 +721,8 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) | |||
720 | goto err; | 721 | goto err; |
721 | 722 | ||
722 | usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, | 723 | usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, |
723 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | 724 | usb_rcvbulkpipe(hif_dev->udev, |
725 | USB_REG_IN_PIPE), | ||
724 | skb->data, MAX_REG_IN_BUF_SIZE, | 726 | skb->data, MAX_REG_IN_BUF_SIZE, |
725 | ath9k_hif_usb_reg_in_cb, skb, 1); | 727 | ath9k_hif_usb_reg_in_cb, skb, 1); |
726 | 728 | ||
@@ -822,7 +824,9 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
822 | 824 | ||
823 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | 825 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) |
824 | { | 826 | { |
825 | int ret; | 827 | int ret, idx; |
828 | struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; | ||
829 | struct usb_endpoint_descriptor *endp; | ||
826 | 830 | ||
827 | /* Request firmware */ | 831 | /* Request firmware */ |
828 | ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, | 832 | ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, |
@@ -850,6 +854,22 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | |||
850 | goto err_fw_download; | 854 | goto err_fw_download; |
851 | } | 855 | } |
852 | 856 | ||
857 | /* On downloading the firmware to the target, the USB descriptor of EP4 | ||
858 | * is 'patched' to change the type of the endpoint to Bulk. This will | ||
859 | * bring down CPU usage during the scan period. | ||
860 | */ | ||
861 | for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) { | ||
862 | endp = &alt->endpoint[idx].desc; | ||
863 | if (((endp->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) | ||
864 | == 0x04) && | ||
865 | ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
866 | == USB_ENDPOINT_XFER_INT)) { | ||
867 | endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK; | ||
868 | endp->bmAttributes |= USB_ENDPOINT_XFER_BULK; | ||
869 | endp->bInterval = 0; | ||
870 | } | ||
871 | } | ||
872 | |||
853 | return 0; | 873 | return 0; |
854 | 874 | ||
855 | err_fw_download: | 875 | err_fw_download: |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 695e2b088d10..33850c952314 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -566,7 +566,7 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) | |||
566 | * reset the contents on initial power up. | 566 | * reset the contents on initial power up. |
567 | */ | 567 | */ |
568 | for (i = 0; i < common->keymax; i++) | 568 | for (i = 0; i < common->keymax; i++) |
569 | ath9k_hw_keyreset(priv->ah, (u16) i); | 569 | ath_hw_keyreset(common, (u16) i); |
570 | } | 570 | } |
571 | 571 | ||
572 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | 572 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) |
@@ -601,8 +601,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
601 | common->tx_chainmask = priv->ah->caps.tx_chainmask; | 601 | common->tx_chainmask = priv->ah->caps.tx_chainmask; |
602 | common->rx_chainmask = priv->ah->caps.rx_chainmask; | 602 | common->rx_chainmask = priv->ah->caps.rx_chainmask; |
603 | 603 | ||
604 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 604 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
605 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
606 | 605 | ||
607 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 606 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
608 | } | 607 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f4672073ac0a..5124d04b240b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -137,8 +137,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
137 | if (priv->op_flags & OP_FULL_RESET) | 137 | if (priv->op_flags & OP_FULL_RESET) |
138 | fastcc = false; | 138 | fastcc = false; |
139 | 139 | ||
140 | /* Fiddle around with fastcc later on, for now just use full reset */ | ||
141 | fastcc = false; | ||
142 | ath9k_htc_ps_wakeup(priv); | 140 | ath9k_htc_ps_wakeup(priv); |
143 | htc_stop(priv->htc); | 141 | htc_stop(priv->htc); |
144 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 142 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
@@ -146,9 +144,10 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
146 | WMI_CMD(WMI_STOP_RECV_CMDID); | 144 | WMI_CMD(WMI_STOP_RECV_CMDID); |
147 | 145 | ||
148 | ath_print(common, ATH_DBG_CONFIG, | 146 | ath_print(common, ATH_DBG_CONFIG, |
149 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n", | 147 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", |
150 | priv->ah->curchan->channel, | 148 | priv->ah->curchan->channel, |
151 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); | 149 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), |
150 | fastcc); | ||
152 | 151 | ||
153 | caldata = &priv->caldata[channel->hw_value]; | 152 | caldata = &priv->caldata[channel->hw_value]; |
154 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 153 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
@@ -1591,7 +1590,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1591 | 1590 | ||
1592 | switch (cmd) { | 1591 | switch (cmd) { |
1593 | case SET_KEY: | 1592 | case SET_KEY: |
1594 | ret = ath9k_cmn_key_config(common, vif, sta, key); | 1593 | ret = ath_key_config(common, vif, sta, key); |
1595 | if (ret >= 0) { | 1594 | if (ret >= 0) { |
1596 | key->hw_key_idx = ret; | 1595 | key->hw_key_idx = ret; |
1597 | /* push IV and Michael MIC generation to stack */ | 1596 | /* push IV and Michael MIC generation to stack */ |
@@ -1605,7 +1604,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1605 | } | 1604 | } |
1606 | break; | 1605 | break; |
1607 | case DISABLE_KEY: | 1606 | case DISABLE_KEY: |
1608 | ath9k_cmn_key_delete(common, key); | 1607 | ath_key_delete(common, key); |
1609 | break; | 1608 | break; |
1610 | default: | 1609 | default: |
1611 | ret = -EINVAL; | 1610 | ret = -EINVAL; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2a6e45a293a9..c99600aff76d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -415,8 +415,7 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | |||
415 | ath9k_hw_setrxfilter(ah, rfilt); | 415 | ath9k_hw_setrxfilter(ah, rfilt); |
416 | 416 | ||
417 | /* configure bssid mask */ | 417 | /* configure bssid mask */ |
418 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 418 | ath_hw_setbssidmask(common); |
419 | ath_hw_setbssidmask(common); | ||
420 | 419 | ||
421 | /* configure operational mode */ | 420 | /* configure operational mode */ |
422 | ath9k_hw_setopmode(ah); | 421 | ath9k_hw_setopmode(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 3384ca164562..0b2ff98b6f33 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1258,11 +1258,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1258 | (chan->channel != ah->curchan->channel) && | 1258 | (chan->channel != ah->curchan->channel) && |
1259 | ((chan->channelFlags & CHANNEL_ALL) == | 1259 | ((chan->channelFlags & CHANNEL_ALL) == |
1260 | (ah->curchan->channelFlags & CHANNEL_ALL)) && | 1260 | (ah->curchan->channelFlags & CHANNEL_ALL)) && |
1261 | !AR_SREV_9280(ah)) { | 1261 | (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) { |
1262 | 1262 | ||
1263 | if (ath9k_hw_channel_change(ah, chan)) { | 1263 | if (ath9k_hw_channel_change(ah, chan)) { |
1264 | ath9k_hw_loadnf(ah, ah->curchan); | 1264 | ath9k_hw_loadnf(ah, ah->curchan); |
1265 | ath9k_hw_start_nfcal(ah, true); | 1265 | ath9k_hw_start_nfcal(ah, true); |
1266 | if (AR_SREV_9271(ah)) | ||
1267 | ar9002_hw_load_ani_reg(ah, chan); | ||
1266 | return 0; | 1268 | return 0; |
1267 | } | 1269 | } |
1268 | } | 1270 | } |
@@ -1474,283 +1476,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1474 | } | 1476 | } |
1475 | EXPORT_SYMBOL(ath9k_hw_reset); | 1477 | EXPORT_SYMBOL(ath9k_hw_reset); |
1476 | 1478 | ||
1477 | /************************/ | ||
1478 | /* Key Cache Management */ | ||
1479 | /************************/ | ||
1480 | |||
1481 | bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) | ||
1482 | { | ||
1483 | u32 keyType; | ||
1484 | |||
1485 | if (entry >= ah->caps.keycache_size) { | ||
1486 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
1487 | "keychache entry %u out of range\n", entry); | ||
1488 | return false; | ||
1489 | } | ||
1490 | |||
1491 | keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); | ||
1492 | |||
1493 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); | ||
1494 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); | ||
1495 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); | ||
1496 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); | ||
1497 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); | ||
1498 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); | ||
1499 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); | ||
1500 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); | ||
1501 | |||
1502 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
1503 | u16 micentry = entry + 64; | ||
1504 | |||
1505 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); | ||
1506 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
1507 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); | ||
1508 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
1509 | |||
1510 | } | ||
1511 | |||
1512 | return true; | ||
1513 | } | ||
1514 | EXPORT_SYMBOL(ath9k_hw_keyreset); | ||
1515 | |||
1516 | static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | ||
1517 | { | ||
1518 | u32 macHi, macLo; | ||
1519 | u32 unicast_flag = AR_KEYTABLE_VALID; | ||
1520 | |||
1521 | if (entry >= ah->caps.keycache_size) { | ||
1522 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
1523 | "keychache entry %u out of range\n", entry); | ||
1524 | return false; | ||
1525 | } | ||
1526 | |||
1527 | if (mac != NULL) { | ||
1528 | /* | ||
1529 | * AR_KEYTABLE_VALID indicates that the address is a unicast | ||
1530 | * address, which must match the transmitter address for | ||
1531 | * decrypting frames. | ||
1532 | * Not setting this bit allows the hardware to use the key | ||
1533 | * for multicast frame decryption. | ||
1534 | */ | ||
1535 | if (mac[0] & 0x01) | ||
1536 | unicast_flag = 0; | ||
1537 | |||
1538 | macHi = (mac[5] << 8) | mac[4]; | ||
1539 | macLo = (mac[3] << 24) | | ||
1540 | (mac[2] << 16) | | ||
1541 | (mac[1] << 8) | | ||
1542 | mac[0]; | ||
1543 | macLo >>= 1; | ||
1544 | macLo |= (macHi & 1) << 31; | ||
1545 | macHi >>= 1; | ||
1546 | } else { | ||
1547 | macLo = macHi = 0; | ||
1548 | } | ||
1549 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); | ||
1550 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); | ||
1551 | |||
1552 | return true; | ||
1553 | } | ||
1554 | |||
1555 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | ||
1556 | const struct ath9k_keyval *k, | ||
1557 | const u8 *mac) | ||
1558 | { | ||
1559 | const struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1560 | struct ath_common *common = ath9k_hw_common(ah); | ||
1561 | u32 key0, key1, key2, key3, key4; | ||
1562 | u32 keyType; | ||
1563 | |||
1564 | if (entry >= pCap->keycache_size) { | ||
1565 | ath_print(common, ATH_DBG_FATAL, | ||
1566 | "keycache entry %u out of range\n", entry); | ||
1567 | return false; | ||
1568 | } | ||
1569 | |||
1570 | switch (k->kv_type) { | ||
1571 | case ATH9K_CIPHER_AES_OCB: | ||
1572 | keyType = AR_KEYTABLE_TYPE_AES; | ||
1573 | break; | ||
1574 | case ATH9K_CIPHER_AES_CCM: | ||
1575 | if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { | ||
1576 | ath_print(common, ATH_DBG_ANY, | ||
1577 | "AES-CCM not supported by mac rev 0x%x\n", | ||
1578 | ah->hw_version.macRev); | ||
1579 | return false; | ||
1580 | } | ||
1581 | keyType = AR_KEYTABLE_TYPE_CCM; | ||
1582 | break; | ||
1583 | case ATH9K_CIPHER_TKIP: | ||
1584 | keyType = AR_KEYTABLE_TYPE_TKIP; | ||
1585 | if (ATH9K_IS_MIC_ENABLED(ah) | ||
1586 | && entry + 64 >= pCap->keycache_size) { | ||
1587 | ath_print(common, ATH_DBG_ANY, | ||
1588 | "entry %u inappropriate for TKIP\n", entry); | ||
1589 | return false; | ||
1590 | } | ||
1591 | break; | ||
1592 | case ATH9K_CIPHER_WEP: | ||
1593 | if (k->kv_len < WLAN_KEY_LEN_WEP40) { | ||
1594 | ath_print(common, ATH_DBG_ANY, | ||
1595 | "WEP key length %u too small\n", k->kv_len); | ||
1596 | return false; | ||
1597 | } | ||
1598 | if (k->kv_len <= WLAN_KEY_LEN_WEP40) | ||
1599 | keyType = AR_KEYTABLE_TYPE_40; | ||
1600 | else if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
1601 | keyType = AR_KEYTABLE_TYPE_104; | ||
1602 | else | ||
1603 | keyType = AR_KEYTABLE_TYPE_128; | ||
1604 | break; | ||
1605 | case ATH9K_CIPHER_CLR: | ||
1606 | keyType = AR_KEYTABLE_TYPE_CLR; | ||
1607 | break; | ||
1608 | default: | ||
1609 | ath_print(common, ATH_DBG_FATAL, | ||
1610 | "cipher %u not supported\n", k->kv_type); | ||
1611 | return false; | ||
1612 | } | ||
1613 | |||
1614 | key0 = get_unaligned_le32(k->kv_val + 0); | ||
1615 | key1 = get_unaligned_le16(k->kv_val + 4); | ||
1616 | key2 = get_unaligned_le32(k->kv_val + 6); | ||
1617 | key3 = get_unaligned_le16(k->kv_val + 10); | ||
1618 | key4 = get_unaligned_le32(k->kv_val + 12); | ||
1619 | if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
1620 | key4 &= 0xff; | ||
1621 | |||
1622 | /* | ||
1623 | * Note: Key cache registers access special memory area that requires | ||
1624 | * two 32-bit writes to actually update the values in the internal | ||
1625 | * memory. Consequently, the exact order and pairs used here must be | ||
1626 | * maintained. | ||
1627 | */ | ||
1628 | |||
1629 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
1630 | u16 micentry = entry + 64; | ||
1631 | |||
1632 | /* | ||
1633 | * Write inverted key[47:0] first to avoid Michael MIC errors | ||
1634 | * on frames that could be sent or received at the same time. | ||
1635 | * The correct key will be written in the end once everything | ||
1636 | * else is ready. | ||
1637 | */ | ||
1638 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); | ||
1639 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); | ||
1640 | |||
1641 | /* Write key[95:48] */ | ||
1642 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
1643 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
1644 | |||
1645 | /* Write key[127:96] and key type */ | ||
1646 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
1647 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
1648 | |||
1649 | /* Write MAC address for the entry */ | ||
1650 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
1651 | |||
1652 | if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { | ||
1653 | /* | ||
1654 | * TKIP uses two key cache entries: | ||
1655 | * Michael MIC TX/RX keys in the same key cache entry | ||
1656 | * (idx = main index + 64): | ||
1657 | * key0 [31:0] = RX key [31:0] | ||
1658 | * key1 [15:0] = TX key [31:16] | ||
1659 | * key1 [31:16] = reserved | ||
1660 | * key2 [31:0] = RX key [63:32] | ||
1661 | * key3 [15:0] = TX key [15:0] | ||
1662 | * key3 [31:16] = reserved | ||
1663 | * key4 [31:0] = TX key [63:32] | ||
1664 | */ | ||
1665 | u32 mic0, mic1, mic2, mic3, mic4; | ||
1666 | |||
1667 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
1668 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
1669 | mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; | ||
1670 | mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; | ||
1671 | mic4 = get_unaligned_le32(k->kv_txmic + 4); | ||
1672 | |||
1673 | /* Write RX[31:0] and TX[31:16] */ | ||
1674 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
1675 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); | ||
1676 | |||
1677 | /* Write RX[63:32] and TX[15:0] */ | ||
1678 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
1679 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); | ||
1680 | |||
1681 | /* Write TX[63:32] and keyType(reserved) */ | ||
1682 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); | ||
1683 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
1684 | AR_KEYTABLE_TYPE_CLR); | ||
1685 | |||
1686 | } else { | ||
1687 | /* | ||
1688 | * TKIP uses four key cache entries (two for group | ||
1689 | * keys): | ||
1690 | * Michael MIC TX/RX keys are in different key cache | ||
1691 | * entries (idx = main index + 64 for TX and | ||
1692 | * main index + 32 + 96 for RX): | ||
1693 | * key0 [31:0] = TX/RX MIC key [31:0] | ||
1694 | * key1 [31:0] = reserved | ||
1695 | * key2 [31:0] = TX/RX MIC key [63:32] | ||
1696 | * key3 [31:0] = reserved | ||
1697 | * key4 [31:0] = reserved | ||
1698 | * | ||
1699 | * Upper layer code will call this function separately | ||
1700 | * for TX and RX keys when these registers offsets are | ||
1701 | * used. | ||
1702 | */ | ||
1703 | u32 mic0, mic2; | ||
1704 | |||
1705 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
1706 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
1707 | |||
1708 | /* Write MIC key[31:0] */ | ||
1709 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
1710 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
1711 | |||
1712 | /* Write MIC key[63:32] */ | ||
1713 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
1714 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
1715 | |||
1716 | /* Write TX[63:32] and keyType(reserved) */ | ||
1717 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); | ||
1718 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
1719 | AR_KEYTABLE_TYPE_CLR); | ||
1720 | } | ||
1721 | |||
1722 | /* MAC address registers are reserved for the MIC entry */ | ||
1723 | REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); | ||
1724 | REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); | ||
1725 | |||
1726 | /* | ||
1727 | * Write the correct (un-inverted) key[47:0] last to enable | ||
1728 | * TKIP now that all other registers are set with correct | ||
1729 | * values. | ||
1730 | */ | ||
1731 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
1732 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
1733 | } else { | ||
1734 | /* Write key[47:0] */ | ||
1735 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
1736 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
1737 | |||
1738 | /* Write key[95:48] */ | ||
1739 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
1740 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
1741 | |||
1742 | /* Write key[127:96] and key type */ | ||
1743 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
1744 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
1745 | |||
1746 | /* Write MAC address for the entry */ | ||
1747 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
1748 | } | ||
1749 | |||
1750 | return true; | ||
1751 | } | ||
1752 | EXPORT_SYMBOL(ath9k_hw_set_keycache_entry); | ||
1753 | |||
1754 | /******************************/ | 1479 | /******************************/ |
1755 | /* Power Management (Chipset) */ | 1480 | /* Power Management (Chipset) */ |
1756 | /******************************/ | 1481 | /******************************/ |
@@ -2056,6 +1781,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2056 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 1781 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
2057 | 1782 | ||
2058 | u16 capField = 0, eeval; | 1783 | u16 capField = 0, eeval; |
1784 | u8 ant_div_ctl1; | ||
2059 | 1785 | ||
2060 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); | 1786 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); |
2061 | regulatory->current_rd = eeval; | 1787 | regulatory->current_rd = eeval; |
@@ -2140,24 +1866,13 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2140 | pCap->low_5ghz_chan = 4920; | 1866 | pCap->low_5ghz_chan = 4920; |
2141 | pCap->high_5ghz_chan = 6100; | 1867 | pCap->high_5ghz_chan = 6100; |
2142 | 1868 | ||
2143 | pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP; | 1869 | common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; |
2144 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP; | ||
2145 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM; | ||
2146 | |||
2147 | pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP; | ||
2148 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; | ||
2149 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; | ||
2150 | 1870 | ||
2151 | if (ah->config.ht_enable) | 1871 | if (ah->config.ht_enable) |
2152 | pCap->hw_caps |= ATH9K_HW_CAP_HT; | 1872 | pCap->hw_caps |= ATH9K_HW_CAP_HT; |
2153 | else | 1873 | else |
2154 | pCap->hw_caps &= ~ATH9K_HW_CAP_HT; | 1874 | pCap->hw_caps &= ~ATH9K_HW_CAP_HT; |
2155 | 1875 | ||
2156 | pCap->hw_caps |= ATH9K_HW_CAP_GTT; | ||
2157 | pCap->hw_caps |= ATH9K_HW_CAP_VEOL; | ||
2158 | pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK; | ||
2159 | pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH; | ||
2160 | |||
2161 | if (capField & AR_EEPROM_EEPCAP_MAXQCU) | 1876 | if (capField & AR_EEPROM_EEPCAP_MAXQCU) |
2162 | pCap->total_queues = | 1877 | pCap->total_queues = |
2163 | MS(capField, AR_EEPROM_EEPCAP_MAXQCU); | 1878 | MS(capField, AR_EEPROM_EEPCAP_MAXQCU); |
@@ -2170,8 +1885,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2170 | else | 1885 | else |
2171 | pCap->keycache_size = AR_KEYTABLE_SIZE; | 1886 | pCap->keycache_size = AR_KEYTABLE_SIZE; |
2172 | 1887 | ||
2173 | pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; | ||
2174 | |||
2175 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | 1888 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
2176 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; | 1889 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; |
2177 | else | 1890 | else |
@@ -2280,6 +1993,14 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2280 | if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) | 1993 | if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) |
2281 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; | 1994 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; |
2282 | 1995 | ||
1996 | if (AR_SREV_9285(ah)) | ||
1997 | if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) { | ||
1998 | ant_div_ctl1 = | ||
1999 | ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
2000 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) | ||
2001 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | ||
2002 | } | ||
2003 | |||
2283 | return 0; | 2004 | return 0; |
2284 | } | 2005 | } |
2285 | 2006 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 1601dd439890..df47f792cf4e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -181,29 +181,19 @@ enum wireless_mode { | |||
181 | }; | 181 | }; |
182 | 182 | ||
183 | enum ath9k_hw_caps { | 183 | enum ath9k_hw_caps { |
184 | ATH9K_HW_CAP_MIC_AESCCM = BIT(0), | 184 | ATH9K_HW_CAP_HT = BIT(0), |
185 | ATH9K_HW_CAP_MIC_CKIP = BIT(1), | 185 | ATH9K_HW_CAP_RFSILENT = BIT(1), |
186 | ATH9K_HW_CAP_MIC_TKIP = BIT(2), | 186 | ATH9K_HW_CAP_CST = BIT(2), |
187 | ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), | 187 | ATH9K_HW_CAP_ENHANCEDPM = BIT(3), |
188 | ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), | 188 | ATH9K_HW_CAP_AUTOSLEEP = BIT(4), |
189 | ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), | 189 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), |
190 | ATH9K_HW_CAP_VEOL = BIT(6), | 190 | ATH9K_HW_CAP_EDMA = BIT(6), |
191 | ATH9K_HW_CAP_BSSIDMASK = BIT(7), | 191 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7), |
192 | ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), | 192 | ATH9K_HW_CAP_LDPC = BIT(8), |
193 | ATH9K_HW_CAP_HT = BIT(9), | 193 | ATH9K_HW_CAP_FASTCLOCK = BIT(9), |
194 | ATH9K_HW_CAP_GTT = BIT(10), | 194 | ATH9K_HW_CAP_SGI_20 = BIT(10), |
195 | ATH9K_HW_CAP_FASTCC = BIT(11), | 195 | ATH9K_HW_CAP_PAPRD = BIT(11), |
196 | ATH9K_HW_CAP_RFSILENT = BIT(12), | 196 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), |
197 | ATH9K_HW_CAP_CST = BIT(13), | ||
198 | ATH9K_HW_CAP_ENHANCEDPM = BIT(14), | ||
199 | ATH9K_HW_CAP_AUTOSLEEP = BIT(15), | ||
200 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), | ||
201 | ATH9K_HW_CAP_EDMA = BIT(17), | ||
202 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), | ||
203 | ATH9K_HW_CAP_LDPC = BIT(19), | ||
204 | ATH9K_HW_CAP_FASTCLOCK = BIT(20), | ||
205 | ATH9K_HW_CAP_SGI_20 = BIT(21), | ||
206 | ATH9K_HW_CAP_PAPRD = BIT(22), | ||
207 | }; | 197 | }; |
208 | 198 | ||
209 | struct ath9k_hw_capabilities { | 199 | struct ath9k_hw_capabilities { |
@@ -495,6 +485,12 @@ struct ath_gen_timer_table { | |||
495 | } timer_mask; | 485 | } timer_mask; |
496 | }; | 486 | }; |
497 | 487 | ||
488 | struct ath_hw_antcomb_conf { | ||
489 | u8 main_lna_conf; | ||
490 | u8 alt_lna_conf; | ||
491 | u8 fast_div_bias; | ||
492 | }; | ||
493 | |||
498 | /** | 494 | /** |
499 | * struct ath_hw_private_ops - callbacks used internally by hardware code | 495 | * struct ath_hw_private_ops - callbacks used internally by hardware code |
500 | * | 496 | * |
@@ -874,12 +870,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
874 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); | 870 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
875 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); | 871 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
876 | 872 | ||
877 | /* Key Cache Management */ | ||
878 | bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); | ||
879 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | ||
880 | const struct ath9k_keyval *k, | ||
881 | const u8 *mac); | ||
882 | |||
883 | /* GPIO / RFKILL / Antennae */ | 873 | /* GPIO / RFKILL / Antennae */ |
884 | void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); | 874 | void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); |
885 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); | 875 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); |
@@ -888,6 +878,10 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, | |||
888 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); | 878 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); |
889 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); | 879 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); |
890 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); | 880 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); |
881 | void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
882 | struct ath_hw_antcomb_conf *antconf); | ||
883 | void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
884 | struct ath_hw_antcomb_conf *antconf); | ||
891 | 885 | ||
892 | /* General Operation */ | 886 | /* General Operation */ |
893 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); | 887 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
@@ -985,6 +979,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah); | |||
985 | void ar9002_hw_attach_ops(struct ath_hw *ah); | 979 | void ar9002_hw_attach_ops(struct ath_hw *ah); |
986 | void ar9003_hw_attach_ops(struct ath_hw *ah); | 980 | void ar9003_hw_attach_ops(struct ath_hw *ah); |
987 | 981 | ||
982 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); | ||
988 | /* | 983 | /* |
989 | * ANI work can be shared between all families but a next | 984 | * ANI work can be shared between all families but a next |
990 | * generation implementation of ANI will be used only for AR9003 only | 985 | * generation implementation of ANI will be used only for AR9003 only |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 3dbff8d07766..573899e27b3d 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -381,7 +381,7 @@ static void ath9k_init_crypto(struct ath_softc *sc) | |||
381 | * reset the contents on initial power up. | 381 | * reset the contents on initial power up. |
382 | */ | 382 | */ |
383 | for (i = 0; i < common->keymax; i++) | 383 | for (i = 0; i < common->keymax; i++) |
384 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); | 384 | ath_hw_keyreset(common, (u16) i); |
385 | 385 | ||
386 | /* | 386 | /* |
387 | * Check whether the separate key cache entries | 387 | * Check whether the separate key cache entries |
@@ -389,8 +389,8 @@ static void ath9k_init_crypto(struct ath_softc *sc) | |||
389 | * With split mic keys the number of stations is limited | 389 | * With split mic keys the number of stations is limited |
390 | * to 27 otherwise 59. | 390 | * to 27 otherwise 59. |
391 | */ | 391 | */ |
392 | if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)) | 392 | if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) |
393 | common->splitmic = 1; | 393 | common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; |
394 | } | 394 | } |
395 | 395 | ||
396 | static int ath9k_init_btcoex(struct ath_softc *sc) | 396 | static int ath9k_init_btcoex(struct ath_softc *sc) |
@@ -522,8 +522,7 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
522 | ath9k_hw_set_diversity(sc->sc_ah, true); | 522 | ath9k_hw_set_diversity(sc->sc_ah, true); |
523 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); | 523 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); |
524 | 524 | ||
525 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 525 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
526 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
527 | 526 | ||
528 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; | 527 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; |
529 | 528 | ||
@@ -531,6 +530,9 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
531 | sc->beacon.bslot[i] = NULL; | 530 | sc->beacon.bslot[i] = NULL; |
532 | sc->beacon.bslot_aphy[i] = NULL; | 531 | sc->beacon.bslot_aphy[i] = NULL; |
533 | } | 532 | } |
533 | |||
534 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | ||
535 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; | ||
534 | } | 536 | } |
535 | 537 | ||
536 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | 538 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, |
@@ -641,7 +643,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
641 | BIT(NL80211_IFTYPE_ADHOC) | | 643 | BIT(NL80211_IFTYPE_ADHOC) | |
642 | BIT(NL80211_IFTYPE_MESH_POINT); | 644 | BIT(NL80211_IFTYPE_MESH_POINT); |
643 | 645 | ||
644 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 646 | if (AR_SREV_5416(sc->sc_ah)) |
647 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
645 | 648 | ||
646 | hw->queues = 4; | 649 | hw->queues = 4; |
647 | hw->max_rates = 4; | 650 | hw->max_rates = 4; |
@@ -651,7 +654,9 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
651 | hw->sta_data_size = sizeof(struct ath_node); | 654 | hw->sta_data_size = sizeof(struct ath_node); |
652 | hw->vif_data_size = sizeof(struct ath_vif); | 655 | hw->vif_data_size = sizeof(struct ath_vif); |
653 | 656 | ||
657 | #ifdef CONFIG_ATH9K_RATE_CONTROL | ||
654 | hw->rate_control_algorithm = "ath9k_rate_control"; | 658 | hw->rate_control_algorithm = "ath9k_rate_control"; |
659 | #endif | ||
655 | 660 | ||
656 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | 661 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) |
657 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 662 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0b7d1253f0c0..3efda8a8a3c1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -714,6 +714,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
714 | else if ((ads.ds_rxstatus8 & AR_MichaelErr) && | 714 | else if ((ads.ds_rxstatus8 & AR_MichaelErr) && |
715 | rs->rs_keyix != ATH9K_RXKEYIX_INVALID) | 715 | rs->rs_keyix != ATH9K_RXKEYIX_INVALID) |
716 | rs->rs_status |= ATH9K_RXERR_MIC; | 716 | rs->rs_status |= ATH9K_RXERR_MIC; |
717 | else if (ads.ds_rxstatus8 & AR_KeyMiss) | ||
718 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | ||
717 | } | 719 | } |
718 | 720 | ||
719 | return 0; | 721 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 2633896d3998..7c1a34d64f6d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -660,17 +660,6 @@ struct ath9k_11n_rate_series { | |||
660 | u32 RateFlags; | 660 | u32 RateFlags; |
661 | }; | 661 | }; |
662 | 662 | ||
663 | struct ath9k_keyval { | ||
664 | u8 kv_type; | ||
665 | u8 kv_pad; | ||
666 | u16 kv_len; | ||
667 | u8 kv_val[16]; /* TK */ | ||
668 | u8 kv_mic[8]; /* Michael MIC key */ | ||
669 | u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware | ||
670 | * supports both MIC keys in the same key cache entry; | ||
671 | * in that case, kv_mic is the RX key) */ | ||
672 | }; | ||
673 | |||
674 | enum ath9k_key_type { | 663 | enum ath9k_key_type { |
675 | ATH9K_KEY_TYPE_CLEAR, | 664 | ATH9K_KEY_TYPE_CLEAR, |
676 | ATH9K_KEY_TYPE_WEP, | 665 | ATH9K_KEY_TYPE_WEP, |
@@ -678,16 +667,6 @@ enum ath9k_key_type { | |||
678 | ATH9K_KEY_TYPE_TKIP, | 667 | ATH9K_KEY_TYPE_TKIP, |
679 | }; | 668 | }; |
680 | 669 | ||
681 | enum ath9k_cipher { | ||
682 | ATH9K_CIPHER_WEP = 0, | ||
683 | ATH9K_CIPHER_AES_OCB = 1, | ||
684 | ATH9K_CIPHER_AES_CCM = 2, | ||
685 | ATH9K_CIPHER_CKIP = 3, | ||
686 | ATH9K_CIPHER_TKIP = 4, | ||
687 | ATH9K_CIPHER_CLR = 5, | ||
688 | ATH9K_CIPHER_MIC = 127 | ||
689 | }; | ||
690 | |||
691 | struct ath_hw; | 670 | struct ath_hw; |
692 | struct ath9k_channel; | 671 | struct ath9k_channel; |
693 | 672 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1165f909ef04..8b327bcad695 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -255,10 +255,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
255 | ath_update_txpow(sc); | 255 | ath_update_txpow(sc); |
256 | ath9k_hw_set_interrupts(ah, ah->imask); | 256 | ath9k_hw_set_interrupts(ah, ah->imask); |
257 | 257 | ||
258 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) { | 258 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { |
259 | ath_start_ani(common); | ||
260 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
261 | ath_beacon_config(sc, NULL); | 259 | ath_beacon_config(sc, NULL); |
260 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
261 | ath_start_ani(common); | ||
262 | } | 262 | } |
263 | 263 | ||
264 | ps_restore: | 264 | ps_restore: |
@@ -957,7 +957,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
957 | 957 | ||
958 | ath_update_txpow(sc); | 958 | ath_update_txpow(sc); |
959 | 959 | ||
960 | if (sc->sc_flags & SC_OP_BEACONS) | 960 | if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) |
961 | ath_beacon_config(sc, NULL); /* restart beacons */ | 961 | ath_beacon_config(sc, NULL); /* restart beacons */ |
962 | 962 | ||
963 | ath9k_hw_set_interrupts(ah, ah->imask); | 963 | ath9k_hw_set_interrupts(ah, ah->imask); |
@@ -1156,8 +1156,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1156 | else | 1156 | else |
1157 | ah->imask |= ATH9K_INT_RX; | 1157 | ah->imask |= ATH9K_INT_RX; |
1158 | 1158 | ||
1159 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) | 1159 | ah->imask |= ATH9K_INT_GTT; |
1160 | ah->imask |= ATH9K_INT_GTT; | ||
1161 | 1160 | ||
1162 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 1161 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1163 | ah->imask |= ATH9K_INT_CST; | 1162 | ah->imask |= ATH9K_INT_CST; |
@@ -1379,12 +1378,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1379 | 1378 | ||
1380 | mutex_lock(&sc->mutex); | 1379 | mutex_lock(&sc->mutex); |
1381 | 1380 | ||
1382 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && | ||
1383 | sc->nvifs > 0) { | ||
1384 | ret = -ENOBUFS; | ||
1385 | goto out; | ||
1386 | } | ||
1387 | |||
1388 | switch (vif->type) { | 1381 | switch (vif->type) { |
1389 | case NL80211_IFTYPE_STATION: | 1382 | case NL80211_IFTYPE_STATION: |
1390 | ic_opmode = NL80211_IFTYPE_STATION; | 1383 | ic_opmode = NL80211_IFTYPE_STATION; |
@@ -1414,8 +1407,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1414 | 1407 | ||
1415 | sc->nvifs++; | 1408 | sc->nvifs++; |
1416 | 1409 | ||
1417 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 1410 | ath9k_set_bssid_mask(hw, vif); |
1418 | ath9k_set_bssid_mask(hw); | ||
1419 | 1411 | ||
1420 | if (sc->nvifs > 1) | 1412 | if (sc->nvifs > 1) |
1421 | goto out; /* skip global settings for secondary vif */ | 1413 | goto out; /* skip global settings for secondary vif */ |
@@ -1562,6 +1554,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1562 | * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode. | 1554 | * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode. |
1563 | */ | 1555 | */ |
1564 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 1556 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
1557 | unsigned long flags; | ||
1558 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
1565 | if (conf->flags & IEEE80211_CONF_PS) { | 1559 | if (conf->flags & IEEE80211_CONF_PS) { |
1566 | sc->ps_flags |= PS_ENABLED; | 1560 | sc->ps_flags |= PS_ENABLED; |
1567 | /* | 1561 | /* |
@@ -1576,7 +1570,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1576 | sc->ps_enabled = false; | 1570 | sc->ps_enabled = false; |
1577 | sc->ps_flags &= ~(PS_ENABLED | | 1571 | sc->ps_flags &= ~(PS_ENABLED | |
1578 | PS_NULLFUNC_COMPLETED); | 1572 | PS_NULLFUNC_COMPLETED); |
1579 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | 1573 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); |
1580 | if (!(ah->caps.hw_caps & | 1574 | if (!(ah->caps.hw_caps & |
1581 | ATH9K_HW_CAP_AUTOSLEEP)) { | 1575 | ATH9K_HW_CAP_AUTOSLEEP)) { |
1582 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 1576 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
@@ -1591,6 +1585,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1591 | } | 1585 | } |
1592 | } | 1586 | } |
1593 | } | 1587 | } |
1588 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1594 | } | 1589 | } |
1595 | 1590 | ||
1596 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | 1591 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
@@ -1777,7 +1772,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1777 | 1772 | ||
1778 | switch (cmd) { | 1773 | switch (cmd) { |
1779 | case SET_KEY: | 1774 | case SET_KEY: |
1780 | ret = ath9k_cmn_key_config(common, vif, sta, key); | 1775 | ret = ath_key_config(common, vif, sta, key); |
1781 | if (ret >= 0) { | 1776 | if (ret >= 0) { |
1782 | key->hw_key_idx = ret; | 1777 | key->hw_key_idx = ret; |
1783 | /* push IV and Michael MIC generation to stack */ | 1778 | /* push IV and Michael MIC generation to stack */ |
@@ -1791,7 +1786,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1791 | } | 1786 | } |
1792 | break; | 1787 | break; |
1793 | case DISABLE_KEY: | 1788 | case DISABLE_KEY: |
1794 | ath9k_cmn_key_delete(common, key); | 1789 | ath_key_delete(common, key); |
1795 | break; | 1790 | break; |
1796 | default: | 1791 | default: |
1797 | ret = -EINVAL; | 1792 | ret = -EINVAL; |
@@ -1975,8 +1970,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1975 | break; | 1970 | break; |
1976 | case IEEE80211_AMPDU_TX_START: | 1971 | case IEEE80211_AMPDU_TX_START: |
1977 | ath9k_ps_wakeup(sc); | 1972 | ath9k_ps_wakeup(sc); |
1978 | ath_tx_aggr_start(sc, sta, tid, ssn); | 1973 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); |
1979 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1974 | if (!ret) |
1975 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1980 | ath9k_ps_restore(sc); | 1976 | ath9k_ps_restore(sc); |
1981 | break; | 1977 | break; |
1982 | case IEEE80211_AMPDU_TX_STOP: | 1978 | case IEEE80211_AMPDU_TX_STOP: |
@@ -2039,7 +2035,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
2039 | 2035 | ||
2040 | aphy->state = ATH_WIPHY_SCAN; | 2036 | aphy->state = ATH_WIPHY_SCAN; |
2041 | ath9k_wiphy_pause_all_forced(sc, aphy); | 2037 | ath9k_wiphy_pause_all_forced(sc, aphy); |
2042 | sc->sc_flags |= SC_OP_SCANNING; | ||
2043 | mutex_unlock(&sc->mutex); | 2038 | mutex_unlock(&sc->mutex); |
2044 | } | 2039 | } |
2045 | 2040 | ||
@@ -2054,7 +2049,6 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2054 | 2049 | ||
2055 | mutex_lock(&sc->mutex); | 2050 | mutex_lock(&sc->mutex); |
2056 | aphy->state = ATH_WIPHY_ACTIVE; | 2051 | aphy->state = ATH_WIPHY_ACTIVE; |
2057 | sc->sc_flags &= ~SC_OP_SCANNING; | ||
2058 | mutex_unlock(&sc->mutex); | 2052 | mutex_unlock(&sc->mutex); |
2059 | } | 2053 | } |
2060 | 2054 | ||
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index e724c2c1ae2a..17969af842f6 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -45,9 +45,6 @@ | |||
45 | } \ | 45 | } \ |
46 | } while (0) | 46 | } while (0) |
47 | 47 | ||
48 | #define ATH9K_IS_MIC_ENABLED(ah) \ | ||
49 | ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) | ||
50 | |||
51 | #define ANTSWAP_AB 0x0001 | 48 | #define ANTSWAP_AB 0x0001 |
52 | #define REDUCE_CHAIN_0 0x00000050 | 49 | #define REDUCE_CHAIN_0 0x00000050 |
53 | #define REDUCE_CHAIN_1 0x00000051 | 50 | #define REDUCE_CHAIN_1 0x00000051 |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e49be733d546..ce1cd6d85847 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1320,6 +1320,22 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1320 | return caps; | 1320 | return caps; |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, | ||
1324 | u8 tidno) | ||
1325 | { | ||
1326 | struct ath_atx_tid *txtid; | ||
1327 | |||
1328 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | ||
1329 | return false; | ||
1330 | |||
1331 | txtid = ATH_AN_2_TID(an, tidno); | ||
1332 | |||
1333 | if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) | ||
1334 | return true; | ||
1335 | return false; | ||
1336 | } | ||
1337 | |||
1338 | |||
1323 | /***********************************/ | 1339 | /***********************************/ |
1324 | /* mac80211 Rate Control callbacks */ | 1340 | /* mac80211 Rate Control callbacks */ |
1325 | /***********************************/ | 1341 | /***********************************/ |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index dc1082654501..268072fd3c1c 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -224,7 +224,18 @@ enum ath9k_internal_frame_type { | |||
224 | ATH9K_IFT_UNPAUSE | 224 | ATH9K_IFT_UNPAUSE |
225 | }; | 225 | }; |
226 | 226 | ||
227 | #ifdef CONFIG_ATH9K_RATE_CONTROL | ||
227 | int ath_rate_control_register(void); | 228 | int ath_rate_control_register(void); |
228 | void ath_rate_control_unregister(void); | 229 | void ath_rate_control_unregister(void); |
230 | #else | ||
231 | static inline int ath_rate_control_register(void) | ||
232 | { | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static inline void ath_rate_control_unregister(void) | ||
237 | { | ||
238 | } | ||
239 | #endif | ||
229 | 240 | ||
230 | #endif /* RC_H */ | 241 | #endif /* RC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 534a91bcc1d9..c5e7af4f51ab 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -19,6 +19,15 @@ | |||
19 | 19 | ||
20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) |
21 | 21 | ||
22 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | ||
23 | int mindelta, int main_rssi_avg, | ||
24 | int alt_rssi_avg, int pkt_count) | ||
25 | { | ||
26 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
27 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || | ||
28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | ||
29 | } | ||
30 | |||
22 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 31 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) |
23 | { | 32 | { |
24 | return sc->ps_enabled && | 33 | return sc->ps_enabled && |
@@ -110,8 +119,7 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
110 | ath9k_hw_setrxfilter(ah, rfilt); | 119 | ath9k_hw_setrxfilter(ah, rfilt); |
111 | 120 | ||
112 | /* configure bssid mask */ | 121 | /* configure bssid mask */ |
113 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 122 | ath_hw_setbssidmask(common); |
114 | ath_hw_setbssidmask(common); | ||
115 | 123 | ||
116 | /* configure operational mode */ | 124 | /* configure operational mode */ |
117 | ath9k_hw_setopmode(ah); | 125 | ath9k_hw_setopmode(ah); |
@@ -292,7 +300,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
292 | 300 | ||
293 | ath_opmode_init(sc); | 301 | ath_opmode_init(sc); |
294 | 302 | ||
295 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING)); | 303 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
296 | } | 304 | } |
297 | 305 | ||
298 | static void ath_edma_stop_recv(struct ath_softc *sc) | 306 | static void ath_edma_stop_recv(struct ath_softc *sc) |
@@ -440,6 +448,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
440 | rfilt |= ATH9K_RX_FILTER_CONTROL; | 448 | rfilt |= ATH9K_RX_FILTER_CONTROL; |
441 | 449 | ||
442 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | 450 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && |
451 | (sc->nvifs <= 1) && | ||
443 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) | 452 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) |
444 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | 453 | rfilt |= ATH9K_RX_FILTER_MYBEACON; |
445 | else | 454 | else |
@@ -454,9 +463,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
454 | if (conf_is_ht(&sc->hw->conf)) | 463 | if (conf_is_ht(&sc->hw->conf)) |
455 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 464 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
456 | 465 | ||
457 | if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) { | 466 | if (sc->sec_wiphy || (sc->nvifs > 1) || |
458 | /* TODO: only needed if more than one BSSID is in use in | 467 | (sc->rx.rxfilter & FIF_OTHER_BSS)) { |
459 | * station/adhoc mode */ | ||
460 | /* The following may also be needed for other older chips */ | 468 | /* The following may also be needed for other older chips */ |
461 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) | 469 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) |
462 | rfilt |= ATH9K_RX_FILTER_PROM; | 470 | rfilt |= ATH9K_RX_FILTER_PROM; |
@@ -498,7 +506,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
498 | start_recv: | 506 | start_recv: |
499 | spin_unlock_bh(&sc->rx.rxbuflock); | 507 | spin_unlock_bh(&sc->rx.rxbuflock); |
500 | ath_opmode_init(sc); | 508 | ath_opmode_init(sc); |
501 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING)); | 509 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
502 | 510 | ||
503 | return 0; | 511 | return 0; |
504 | } | 512 | } |
@@ -631,7 +639,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
631 | * No more broadcast/multicast frames to be received at this | 639 | * No more broadcast/multicast frames to be received at this |
632 | * point. | 640 | * point. |
633 | */ | 641 | */ |
634 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; | 642 | sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON); |
635 | ath_print(common, ATH_DBG_PS, | 643 | ath_print(common, ATH_DBG_PS, |
636 | "All PS CAB frames received, back to sleep\n"); | 644 | "All PS CAB frames received, back to sleep\n"); |
637 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && | 645 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && |
@@ -1076,6 +1084,539 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, | |||
1076 | rxs->flag &= ~RX_FLAG_DECRYPTED; | 1084 | rxs->flag &= ~RX_FLAG_DECRYPTED; |
1077 | } | 1085 | } |
1078 | 1086 | ||
1087 | static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | ||
1088 | struct ath_hw_antcomb_conf ant_conf, | ||
1089 | int main_rssi_avg) | ||
1090 | { | ||
1091 | antcomb->quick_scan_cnt = 0; | ||
1092 | |||
1093 | if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1094 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1095 | else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1096 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1097 | |||
1098 | switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { | ||
1099 | case (0x10): /* LNA2 A-B */ | ||
1100 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1101 | antcomb->first_quick_scan_conf = | ||
1102 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1103 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1104 | break; | ||
1105 | case (0x20): /* LNA1 A-B */ | ||
1106 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1107 | antcomb->first_quick_scan_conf = | ||
1108 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1109 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1110 | break; | ||
1111 | case (0x21): /* LNA1 LNA2 */ | ||
1112 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1113 | antcomb->first_quick_scan_conf = | ||
1114 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1115 | antcomb->second_quick_scan_conf = | ||
1116 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1117 | break; | ||
1118 | case (0x12): /* LNA2 LNA1 */ | ||
1119 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1120 | antcomb->first_quick_scan_conf = | ||
1121 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1122 | antcomb->second_quick_scan_conf = | ||
1123 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1124 | break; | ||
1125 | case (0x13): /* LNA2 A+B */ | ||
1126 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1127 | antcomb->first_quick_scan_conf = | ||
1128 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1129 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1130 | break; | ||
1131 | case (0x23): /* LNA1 A+B */ | ||
1132 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1133 | antcomb->first_quick_scan_conf = | ||
1134 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1135 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1136 | break; | ||
1137 | default: | ||
1138 | break; | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | ||
1143 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
1144 | int main_rssi_avg, int alt_rssi_avg, | ||
1145 | int alt_ratio) | ||
1146 | { | ||
1147 | /* alt_good */ | ||
1148 | switch (antcomb->quick_scan_cnt) { | ||
1149 | case 0: | ||
1150 | /* set alt to main, and alt to first conf */ | ||
1151 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1152 | div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
1153 | break; | ||
1154 | case 1: | ||
1155 | /* set alt to main, and alt to first conf */ | ||
1156 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1157 | div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
1158 | antcomb->rssi_first = main_rssi_avg; | ||
1159 | antcomb->rssi_second = alt_rssi_avg; | ||
1160 | |||
1161 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1162 | /* main is LNA1 */ | ||
1163 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1164 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1165 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1166 | main_rssi_avg, alt_rssi_avg, | ||
1167 | antcomb->total_pkt_count)) | ||
1168 | antcomb->first_ratio = true; | ||
1169 | else | ||
1170 | antcomb->first_ratio = false; | ||
1171 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1172 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1173 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1174 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1175 | main_rssi_avg, alt_rssi_avg, | ||
1176 | antcomb->total_pkt_count)) | ||
1177 | antcomb->first_ratio = true; | ||
1178 | else | ||
1179 | antcomb->first_ratio = false; | ||
1180 | } else { | ||
1181 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1182 | (alt_rssi_avg > main_rssi_avg + | ||
1183 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1184 | (alt_rssi_avg > main_rssi_avg)) && | ||
1185 | (antcomb->total_pkt_count > 50)) | ||
1186 | antcomb->first_ratio = true; | ||
1187 | else | ||
1188 | antcomb->first_ratio = false; | ||
1189 | } | ||
1190 | break; | ||
1191 | case 2: | ||
1192 | antcomb->alt_good = false; | ||
1193 | antcomb->scan_not_start = false; | ||
1194 | antcomb->scan = false; | ||
1195 | antcomb->rssi_first = main_rssi_avg; | ||
1196 | antcomb->rssi_third = alt_rssi_avg; | ||
1197 | |||
1198 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1199 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1200 | else if (antcomb->second_quick_scan_conf == | ||
1201 | ATH_ANT_DIV_COMB_LNA2) | ||
1202 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1203 | else if (antcomb->second_quick_scan_conf == | ||
1204 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | ||
1205 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1206 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1207 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1208 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1209 | } | ||
1210 | |||
1211 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | ||
1212 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | ||
1213 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1214 | else | ||
1215 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1216 | |||
1217 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1218 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1219 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1220 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1221 | main_rssi_avg, alt_rssi_avg, | ||
1222 | antcomb->total_pkt_count)) | ||
1223 | antcomb->second_ratio = true; | ||
1224 | else | ||
1225 | antcomb->second_ratio = false; | ||
1226 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1227 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1228 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1229 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1230 | main_rssi_avg, alt_rssi_avg, | ||
1231 | antcomb->total_pkt_count)) | ||
1232 | antcomb->second_ratio = true; | ||
1233 | else | ||
1234 | antcomb->second_ratio = false; | ||
1235 | } else { | ||
1236 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1237 | (alt_rssi_avg > main_rssi_avg + | ||
1238 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1239 | (alt_rssi_avg > main_rssi_avg)) && | ||
1240 | (antcomb->total_pkt_count > 50)) | ||
1241 | antcomb->second_ratio = true; | ||
1242 | else | ||
1243 | antcomb->second_ratio = false; | ||
1244 | } | ||
1245 | |||
1246 | /* set alt to the conf with maximun ratio */ | ||
1247 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
1248 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
1249 | /* first alt*/ | ||
1250 | if ((antcomb->first_quick_scan_conf == | ||
1251 | ATH_ANT_DIV_COMB_LNA1) || | ||
1252 | (antcomb->first_quick_scan_conf == | ||
1253 | ATH_ANT_DIV_COMB_LNA2)) | ||
1254 | /* Set alt LNA1 or LNA2*/ | ||
1255 | if (div_ant_conf->main_lna_conf == | ||
1256 | ATH_ANT_DIV_COMB_LNA2) | ||
1257 | div_ant_conf->alt_lna_conf = | ||
1258 | ATH_ANT_DIV_COMB_LNA1; | ||
1259 | else | ||
1260 | div_ant_conf->alt_lna_conf = | ||
1261 | ATH_ANT_DIV_COMB_LNA2; | ||
1262 | else | ||
1263 | /* Set alt to A+B or A-B */ | ||
1264 | div_ant_conf->alt_lna_conf = | ||
1265 | antcomb->first_quick_scan_conf; | ||
1266 | } else if ((antcomb->second_quick_scan_conf == | ||
1267 | ATH_ANT_DIV_COMB_LNA1) || | ||
1268 | (antcomb->second_quick_scan_conf == | ||
1269 | ATH_ANT_DIV_COMB_LNA2)) { | ||
1270 | /* Set alt LNA1 or LNA2 */ | ||
1271 | if (div_ant_conf->main_lna_conf == | ||
1272 | ATH_ANT_DIV_COMB_LNA2) | ||
1273 | div_ant_conf->alt_lna_conf = | ||
1274 | ATH_ANT_DIV_COMB_LNA1; | ||
1275 | else | ||
1276 | div_ant_conf->alt_lna_conf = | ||
1277 | ATH_ANT_DIV_COMB_LNA2; | ||
1278 | } else { | ||
1279 | /* Set alt to A+B or A-B */ | ||
1280 | div_ant_conf->alt_lna_conf = | ||
1281 | antcomb->second_quick_scan_conf; | ||
1282 | } | ||
1283 | } else if (antcomb->first_ratio) { | ||
1284 | /* first alt */ | ||
1285 | if ((antcomb->first_quick_scan_conf == | ||
1286 | ATH_ANT_DIV_COMB_LNA1) || | ||
1287 | (antcomb->first_quick_scan_conf == | ||
1288 | ATH_ANT_DIV_COMB_LNA2)) | ||
1289 | /* Set alt LNA1 or LNA2 */ | ||
1290 | if (div_ant_conf->main_lna_conf == | ||
1291 | ATH_ANT_DIV_COMB_LNA2) | ||
1292 | div_ant_conf->alt_lna_conf = | ||
1293 | ATH_ANT_DIV_COMB_LNA1; | ||
1294 | else | ||
1295 | div_ant_conf->alt_lna_conf = | ||
1296 | ATH_ANT_DIV_COMB_LNA2; | ||
1297 | else | ||
1298 | /* Set alt to A+B or A-B */ | ||
1299 | div_ant_conf->alt_lna_conf = | ||
1300 | antcomb->first_quick_scan_conf; | ||
1301 | } else if (antcomb->second_ratio) { | ||
1302 | /* second alt */ | ||
1303 | if ((antcomb->second_quick_scan_conf == | ||
1304 | ATH_ANT_DIV_COMB_LNA1) || | ||
1305 | (antcomb->second_quick_scan_conf == | ||
1306 | ATH_ANT_DIV_COMB_LNA2)) | ||
1307 | /* Set alt LNA1 or LNA2 */ | ||
1308 | if (div_ant_conf->main_lna_conf == | ||
1309 | ATH_ANT_DIV_COMB_LNA2) | ||
1310 | div_ant_conf->alt_lna_conf = | ||
1311 | ATH_ANT_DIV_COMB_LNA1; | ||
1312 | else | ||
1313 | div_ant_conf->alt_lna_conf = | ||
1314 | ATH_ANT_DIV_COMB_LNA2; | ||
1315 | else | ||
1316 | /* Set alt to A+B or A-B */ | ||
1317 | div_ant_conf->alt_lna_conf = | ||
1318 | antcomb->second_quick_scan_conf; | ||
1319 | } else { | ||
1320 | /* main is largest */ | ||
1321 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
1322 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
1323 | /* Set alt LNA1 or LNA2 */ | ||
1324 | if (div_ant_conf->main_lna_conf == | ||
1325 | ATH_ANT_DIV_COMB_LNA2) | ||
1326 | div_ant_conf->alt_lna_conf = | ||
1327 | ATH_ANT_DIV_COMB_LNA1; | ||
1328 | else | ||
1329 | div_ant_conf->alt_lna_conf = | ||
1330 | ATH_ANT_DIV_COMB_LNA2; | ||
1331 | else | ||
1332 | /* Set alt to A+B or A-B */ | ||
1333 | div_ant_conf->alt_lna_conf = antcomb->main_conf; | ||
1334 | } | ||
1335 | break; | ||
1336 | default: | ||
1337 | break; | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf) | ||
1342 | { | ||
1343 | /* Adjust the fast_div_bias based on main and alt lna conf */ | ||
1344 | switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { | ||
1345 | case (0x01): /* A-B LNA2 */ | ||
1346 | ant_conf->fast_div_bias = 0x3b; | ||
1347 | break; | ||
1348 | case (0x02): /* A-B LNA1 */ | ||
1349 | ant_conf->fast_div_bias = 0x3d; | ||
1350 | break; | ||
1351 | case (0x03): /* A-B A+B */ | ||
1352 | ant_conf->fast_div_bias = 0x1; | ||
1353 | break; | ||
1354 | case (0x10): /* LNA2 A-B */ | ||
1355 | ant_conf->fast_div_bias = 0x7; | ||
1356 | break; | ||
1357 | case (0x12): /* LNA2 LNA1 */ | ||
1358 | ant_conf->fast_div_bias = 0x2; | ||
1359 | break; | ||
1360 | case (0x13): /* LNA2 A+B */ | ||
1361 | ant_conf->fast_div_bias = 0x7; | ||
1362 | break; | ||
1363 | case (0x20): /* LNA1 A-B */ | ||
1364 | ant_conf->fast_div_bias = 0x6; | ||
1365 | break; | ||
1366 | case (0x21): /* LNA1 LNA2 */ | ||
1367 | ant_conf->fast_div_bias = 0x0; | ||
1368 | break; | ||
1369 | case (0x23): /* LNA1 A+B */ | ||
1370 | ant_conf->fast_div_bias = 0x6; | ||
1371 | break; | ||
1372 | case (0x30): /* A+B A-B */ | ||
1373 | ant_conf->fast_div_bias = 0x1; | ||
1374 | break; | ||
1375 | case (0x31): /* A+B LNA2 */ | ||
1376 | ant_conf->fast_div_bias = 0x3b; | ||
1377 | break; | ||
1378 | case (0x32): /* A+B LNA1 */ | ||
1379 | ant_conf->fast_div_bias = 0x3d; | ||
1380 | break; | ||
1381 | default: | ||
1382 | break; | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | /* Antenna diversity and combining */ | ||
1387 | static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | ||
1388 | { | ||
1389 | struct ath_hw_antcomb_conf div_ant_conf; | ||
1390 | struct ath_ant_comb *antcomb = &sc->ant_comb; | ||
1391 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | ||
1392 | int curr_main_set, curr_bias; | ||
1393 | int main_rssi = rs->rs_rssi_ctl0; | ||
1394 | int alt_rssi = rs->rs_rssi_ctl1; | ||
1395 | int rx_ant_conf, main_ant_conf; | ||
1396 | bool short_scan = false; | ||
1397 | |||
1398 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | ||
1399 | ATH_ANT_RX_MASK; | ||
1400 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | ||
1401 | ATH_ANT_RX_MASK; | ||
1402 | |||
1403 | /* Record packet only when alt_rssi is positive */ | ||
1404 | if (alt_rssi > 0) { | ||
1405 | antcomb->total_pkt_count++; | ||
1406 | antcomb->main_total_rssi += main_rssi; | ||
1407 | antcomb->alt_total_rssi += alt_rssi; | ||
1408 | if (main_ant_conf == rx_ant_conf) | ||
1409 | antcomb->main_recv_cnt++; | ||
1410 | else | ||
1411 | antcomb->alt_recv_cnt++; | ||
1412 | } | ||
1413 | |||
1414 | /* Short scan check */ | ||
1415 | if (antcomb->scan && antcomb->alt_good) { | ||
1416 | if (time_after(jiffies, antcomb->scan_start_time + | ||
1417 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
1418 | short_scan = true; | ||
1419 | else | ||
1420 | if (antcomb->total_pkt_count == | ||
1421 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
1422 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1423 | antcomb->total_pkt_count); | ||
1424 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
1425 | short_scan = true; | ||
1426 | } | ||
1427 | } | ||
1428 | |||
1429 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | ||
1430 | rs->rs_moreaggr) && !short_scan) | ||
1431 | return; | ||
1432 | |||
1433 | if (antcomb->total_pkt_count) { | ||
1434 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1435 | antcomb->total_pkt_count); | ||
1436 | main_rssi_avg = (antcomb->main_total_rssi / | ||
1437 | antcomb->total_pkt_count); | ||
1438 | alt_rssi_avg = (antcomb->alt_total_rssi / | ||
1439 | antcomb->total_pkt_count); | ||
1440 | } | ||
1441 | |||
1442 | |||
1443 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | ||
1444 | curr_alt_set = div_ant_conf.alt_lna_conf; | ||
1445 | curr_main_set = div_ant_conf.main_lna_conf; | ||
1446 | curr_bias = div_ant_conf.fast_div_bias; | ||
1447 | |||
1448 | antcomb->count++; | ||
1449 | |||
1450 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | ||
1451 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
1452 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | ||
1453 | main_rssi_avg); | ||
1454 | antcomb->alt_good = true; | ||
1455 | } else { | ||
1456 | antcomb->alt_good = false; | ||
1457 | } | ||
1458 | |||
1459 | antcomb->count = 0; | ||
1460 | antcomb->scan = true; | ||
1461 | antcomb->scan_not_start = true; | ||
1462 | } | ||
1463 | |||
1464 | if (!antcomb->scan) { | ||
1465 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
1466 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1467 | /* Switch main and alt LNA */ | ||
1468 | div_ant_conf.main_lna_conf = | ||
1469 | ATH_ANT_DIV_COMB_LNA2; | ||
1470 | div_ant_conf.alt_lna_conf = | ||
1471 | ATH_ANT_DIV_COMB_LNA1; | ||
1472 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1473 | div_ant_conf.main_lna_conf = | ||
1474 | ATH_ANT_DIV_COMB_LNA1; | ||
1475 | div_ant_conf.alt_lna_conf = | ||
1476 | ATH_ANT_DIV_COMB_LNA2; | ||
1477 | } | ||
1478 | |||
1479 | goto div_comb_done; | ||
1480 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
1481 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
1482 | /* Set alt to another LNA */ | ||
1483 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
1484 | div_ant_conf.alt_lna_conf = | ||
1485 | ATH_ANT_DIV_COMB_LNA1; | ||
1486 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
1487 | div_ant_conf.alt_lna_conf = | ||
1488 | ATH_ANT_DIV_COMB_LNA2; | ||
1489 | |||
1490 | goto div_comb_done; | ||
1491 | } | ||
1492 | |||
1493 | if ((alt_rssi_avg < (main_rssi_avg + | ||
1494 | ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA))) | ||
1495 | goto div_comb_done; | ||
1496 | } | ||
1497 | |||
1498 | if (!antcomb->scan_not_start) { | ||
1499 | switch (curr_alt_set) { | ||
1500 | case ATH_ANT_DIV_COMB_LNA2: | ||
1501 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1502 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1503 | antcomb->scan = true; | ||
1504 | /* set to A+B */ | ||
1505 | div_ant_conf.main_lna_conf = | ||
1506 | ATH_ANT_DIV_COMB_LNA1; | ||
1507 | div_ant_conf.alt_lna_conf = | ||
1508 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1509 | break; | ||
1510 | case ATH_ANT_DIV_COMB_LNA1: | ||
1511 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1512 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1513 | antcomb->scan = true; | ||
1514 | /* set to A+B */ | ||
1515 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1516 | div_ant_conf.alt_lna_conf = | ||
1517 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1518 | break; | ||
1519 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
1520 | antcomb->rssi_add = alt_rssi_avg; | ||
1521 | antcomb->scan = true; | ||
1522 | /* set to A-B */ | ||
1523 | div_ant_conf.alt_lna_conf = | ||
1524 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1525 | break; | ||
1526 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
1527 | antcomb->rssi_sub = alt_rssi_avg; | ||
1528 | antcomb->scan = false; | ||
1529 | if (antcomb->rssi_lna2 > | ||
1530 | (antcomb->rssi_lna1 + | ||
1531 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
1532 | /* use LNA2 as main LNA */ | ||
1533 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
1534 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1535 | /* set to A+B */ | ||
1536 | div_ant_conf.main_lna_conf = | ||
1537 | ATH_ANT_DIV_COMB_LNA2; | ||
1538 | div_ant_conf.alt_lna_conf = | ||
1539 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1540 | } else if (antcomb->rssi_sub > | ||
1541 | antcomb->rssi_lna1) { | ||
1542 | /* set to A-B */ | ||
1543 | div_ant_conf.main_lna_conf = | ||
1544 | ATH_ANT_DIV_COMB_LNA2; | ||
1545 | div_ant_conf.alt_lna_conf = | ||
1546 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1547 | } else { | ||
1548 | /* set to LNA1 */ | ||
1549 | div_ant_conf.main_lna_conf = | ||
1550 | ATH_ANT_DIV_COMB_LNA2; | ||
1551 | div_ant_conf.alt_lna_conf = | ||
1552 | ATH_ANT_DIV_COMB_LNA1; | ||
1553 | } | ||
1554 | } else { | ||
1555 | /* use LNA1 as main LNA */ | ||
1556 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
1557 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1558 | /* set to A+B */ | ||
1559 | div_ant_conf.main_lna_conf = | ||
1560 | ATH_ANT_DIV_COMB_LNA1; | ||
1561 | div_ant_conf.alt_lna_conf = | ||
1562 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1563 | } else if (antcomb->rssi_sub > | ||
1564 | antcomb->rssi_lna1) { | ||
1565 | /* set to A-B */ | ||
1566 | div_ant_conf.main_lna_conf = | ||
1567 | ATH_ANT_DIV_COMB_LNA1; | ||
1568 | div_ant_conf.alt_lna_conf = | ||
1569 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1570 | } else { | ||
1571 | /* set to LNA2 */ | ||
1572 | div_ant_conf.main_lna_conf = | ||
1573 | ATH_ANT_DIV_COMB_LNA1; | ||
1574 | div_ant_conf.alt_lna_conf = | ||
1575 | ATH_ANT_DIV_COMB_LNA2; | ||
1576 | } | ||
1577 | } | ||
1578 | break; | ||
1579 | default: | ||
1580 | break; | ||
1581 | } | ||
1582 | } else { | ||
1583 | if (!antcomb->alt_good) { | ||
1584 | antcomb->scan_not_start = false; | ||
1585 | /* Set alt to another LNA */ | ||
1586 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1587 | div_ant_conf.main_lna_conf = | ||
1588 | ATH_ANT_DIV_COMB_LNA2; | ||
1589 | div_ant_conf.alt_lna_conf = | ||
1590 | ATH_ANT_DIV_COMB_LNA1; | ||
1591 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1592 | div_ant_conf.main_lna_conf = | ||
1593 | ATH_ANT_DIV_COMB_LNA1; | ||
1594 | div_ant_conf.alt_lna_conf = | ||
1595 | ATH_ANT_DIV_COMB_LNA2; | ||
1596 | } | ||
1597 | goto div_comb_done; | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
1602 | main_rssi_avg, alt_rssi_avg, | ||
1603 | alt_ratio); | ||
1604 | |||
1605 | antcomb->quick_scan_cnt++; | ||
1606 | |||
1607 | div_comb_done: | ||
1608 | ath_ant_div_conf_fast_divbias(&div_ant_conf); | ||
1609 | |||
1610 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | ||
1611 | |||
1612 | antcomb->scan_start_time = jiffies; | ||
1613 | antcomb->total_pkt_count = 0; | ||
1614 | antcomb->main_total_rssi = 0; | ||
1615 | antcomb->alt_total_rssi = 0; | ||
1616 | antcomb->main_recv_cnt = 0; | ||
1617 | antcomb->alt_recv_cnt = 0; | ||
1618 | } | ||
1619 | |||
1079 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1620 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1080 | { | 1621 | { |
1081 | struct ath_buf *bf; | 1622 | struct ath_buf *bf; |
@@ -1099,6 +1640,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1099 | u8 rx_status_len = ah->caps.rx_status_len; | 1640 | u8 rx_status_len = ah->caps.rx_status_len; |
1100 | u64 tsf = 0; | 1641 | u64 tsf = 0; |
1101 | u32 tsf_lower = 0; | 1642 | u32 tsf_lower = 0; |
1643 | unsigned long flags; | ||
1102 | 1644 | ||
1103 | if (edma) | 1645 | if (edma) |
1104 | dma_type = DMA_BIDIRECTIONAL; | 1646 | dma_type = DMA_BIDIRECTIONAL; |
@@ -1207,11 +1749,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1207 | sc->rx.rxotherant = 0; | 1749 | sc->rx.rxotherant = 0; |
1208 | } | 1750 | } |
1209 | 1751 | ||
1752 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
1210 | if (unlikely(ath9k_check_auto_sleep(sc) || | 1753 | if (unlikely(ath9k_check_auto_sleep(sc) || |
1211 | (sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1754 | (sc->ps_flags & (PS_WAIT_FOR_BEACON | |
1212 | PS_WAIT_FOR_CAB | | 1755 | PS_WAIT_FOR_CAB | |
1213 | PS_WAIT_FOR_PSPOLL_DATA)))) | 1756 | PS_WAIT_FOR_PSPOLL_DATA)))) |
1214 | ath_rx_ps(sc, skb); | 1757 | ath_rx_ps(sc, skb); |
1758 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1759 | |||
1760 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | ||
1761 | ath_ant_comb_scan(sc, &rs); | ||
1215 | 1762 | ||
1216 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 1763 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); |
1217 | 1764 | ||
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index fd20241f57d8..ec7cf5ee56bc 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -19,45 +19,36 @@ | |||
19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
20 | 20 | ||
21 | struct ath9k_vif_iter_data { | 21 | struct ath9k_vif_iter_data { |
22 | int count; | 22 | const u8 *hw_macaddr; |
23 | u8 *addr; | 23 | u8 mask[ETH_ALEN]; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 26 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
27 | { | 27 | { |
28 | struct ath9k_vif_iter_data *iter_data = data; | 28 | struct ath9k_vif_iter_data *iter_data = data; |
29 | u8 *nbuf; | 29 | int i; |
30 | |||
31 | nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN, | ||
32 | GFP_ATOMIC); | ||
33 | if (nbuf == NULL) | ||
34 | return; | ||
35 | 30 | ||
36 | memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN); | 31 | for (i = 0; i < ETH_ALEN; i++) |
37 | iter_data->addr = nbuf; | 32 | iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); |
38 | iter_data->count++; | ||
39 | } | 33 | } |
40 | 34 | ||
41 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | 35 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
42 | { | 36 | { |
43 | struct ath_wiphy *aphy = hw->priv; | 37 | struct ath_wiphy *aphy = hw->priv; |
44 | struct ath_softc *sc = aphy->sc; | 38 | struct ath_softc *sc = aphy->sc; |
45 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 39 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
46 | struct ath9k_vif_iter_data iter_data; | 40 | struct ath9k_vif_iter_data iter_data; |
47 | int i, j; | 41 | int i; |
48 | u8 mask[ETH_ALEN]; | ||
49 | 42 | ||
50 | /* | 43 | /* |
51 | * Add primary MAC address even if it is not in active use since it | 44 | * Use the hardware MAC address as reference, the hardware uses it |
52 | * will be configured to the hardware as the starting point and the | 45 | * together with the BSSID mask when matching addresses. |
53 | * BSSID mask will need to be changed if another address is active. | ||
54 | */ | 46 | */ |
55 | iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); | 47 | iter_data.hw_macaddr = common->macaddr; |
56 | if (iter_data.addr) { | 48 | memset(&iter_data.mask, 0xff, ETH_ALEN); |
57 | memcpy(iter_data.addr, common->macaddr, ETH_ALEN); | 49 | |
58 | iter_data.count = 1; | 50 | if (vif) |
59 | } else | 51 | ath9k_vif_iter(&iter_data, vif->addr, vif); |
60 | iter_data.count = 0; | ||
61 | 52 | ||
62 | /* Get list of all active MAC addresses */ | 53 | /* Get list of all active MAC addresses */ |
63 | spin_lock_bh(&sc->wiphy_lock); | 54 | spin_lock_bh(&sc->wiphy_lock); |
@@ -71,31 +62,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | |||
71 | } | 62 | } |
72 | spin_unlock_bh(&sc->wiphy_lock); | 63 | spin_unlock_bh(&sc->wiphy_lock); |
73 | 64 | ||
74 | /* Generate an address mask to cover all active addresses */ | 65 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
75 | memset(mask, 0, ETH_ALEN); | ||
76 | for (i = 0; i < iter_data.count; i++) { | ||
77 | u8 *a1 = iter_data.addr + i * ETH_ALEN; | ||
78 | for (j = i + 1; j < iter_data.count; j++) { | ||
79 | u8 *a2 = iter_data.addr + j * ETH_ALEN; | ||
80 | mask[0] |= a1[0] ^ a2[0]; | ||
81 | mask[1] |= a1[1] ^ a2[1]; | ||
82 | mask[2] |= a1[2] ^ a2[2]; | ||
83 | mask[3] |= a1[3] ^ a2[3]; | ||
84 | mask[4] |= a1[4] ^ a2[4]; | ||
85 | mask[5] |= a1[5] ^ a2[5]; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | kfree(iter_data.addr); | ||
90 | |||
91 | /* Invert the mask and configure hardware */ | ||
92 | common->bssidmask[0] = ~mask[0]; | ||
93 | common->bssidmask[1] = ~mask[1]; | ||
94 | common->bssidmask[2] = ~mask[2]; | ||
95 | common->bssidmask[3] = ~mask[3]; | ||
96 | common->bssidmask[4] = ~mask[4]; | ||
97 | common->bssidmask[5] = ~mask[5]; | ||
98 | |||
99 | ath_hw_setbssidmask(common); | 66 | ath_hw_setbssidmask(common); |
100 | } | 67 | } |
101 | 68 | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 45fe9cac7971..93a8bda09c25 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -124,55 +124,11 @@ void ath9k_wmi_tasklet(unsigned long data) | |||
124 | { | 124 | { |
125 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 125 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
126 | struct ath_common *common = ath9k_hw_common(priv->ah); | 126 | struct ath_common *common = ath9k_hw_common(priv->ah); |
127 | struct wmi_cmd_hdr *hdr; | ||
128 | struct wmi_swba *swba_hdr; | ||
129 | enum wmi_event_id event; | ||
130 | struct sk_buff *skb; | ||
131 | void *wmi_event; | ||
132 | unsigned long flags; | ||
133 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
134 | __be32 txrate; | ||
135 | #endif | ||
136 | 127 | ||
137 | spin_lock_irqsave(&priv->wmi->wmi_lock, flags); | 128 | ath_print(common, ATH_DBG_WMI, "SWBA Event received\n"); |
138 | skb = priv->wmi->wmi_skb; | ||
139 | spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); | ||
140 | 129 | ||
141 | hdr = (struct wmi_cmd_hdr *) skb->data; | 130 | ath9k_htc_swba(priv, priv->wmi->beacon_pending); |
142 | event = be16_to_cpu(hdr->command_id); | ||
143 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | ||
144 | 131 | ||
145 | ath_print(common, ATH_DBG_WMI, | ||
146 | "WMI Event: 0x%x\n", event); | ||
147 | |||
148 | switch (event) { | ||
149 | case WMI_TGT_RDY_EVENTID: | ||
150 | break; | ||
151 | case WMI_SWBA_EVENTID: | ||
152 | swba_hdr = (struct wmi_swba *) wmi_event; | ||
153 | ath9k_htc_swba(priv, swba_hdr->beacon_pending); | ||
154 | break; | ||
155 | case WMI_FATAL_EVENTID: | ||
156 | break; | ||
157 | case WMI_TXTO_EVENTID: | ||
158 | break; | ||
159 | case WMI_BMISS_EVENTID: | ||
160 | break; | ||
161 | case WMI_WLAN_TXCOMP_EVENTID: | ||
162 | break; | ||
163 | case WMI_DELBA_EVENTID: | ||
164 | break; | ||
165 | case WMI_TXRATE_EVENTID: | ||
166 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
167 | txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; | ||
168 | priv->debug.txrate = be32_to_cpu(txrate); | ||
169 | #endif | ||
170 | break; | ||
171 | default: | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | kfree_skb(skb); | ||
176 | } | 132 | } |
177 | 133 | ||
178 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) | 134 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) |
@@ -191,6 +147,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
191 | struct wmi *wmi = (struct wmi *) priv; | 147 | struct wmi *wmi = (struct wmi *) priv; |
192 | struct wmi_cmd_hdr *hdr; | 148 | struct wmi_cmd_hdr *hdr; |
193 | u16 cmd_id; | 149 | u16 cmd_id; |
150 | void *wmi_event; | ||
151 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
152 | __be32 txrate; | ||
153 | #endif | ||
194 | 154 | ||
195 | if (unlikely(wmi->stopped)) | 155 | if (unlikely(wmi->stopped)) |
196 | goto free_skb; | 156 | goto free_skb; |
@@ -199,10 +159,22 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
199 | cmd_id = be16_to_cpu(hdr->command_id); | 159 | cmd_id = be16_to_cpu(hdr->command_id); |
200 | 160 | ||
201 | if (cmd_id & 0x1000) { | 161 | if (cmd_id & 0x1000) { |
202 | spin_lock(&wmi->wmi_lock); | 162 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); |
203 | wmi->wmi_skb = skb; | 163 | switch (cmd_id) { |
204 | spin_unlock(&wmi->wmi_lock); | 164 | case WMI_SWBA_EVENTID: |
205 | tasklet_schedule(&wmi->drv_priv->wmi_tasklet); | 165 | wmi->beacon_pending = *(u8 *)wmi_event; |
166 | tasklet_schedule(&wmi->drv_priv->wmi_tasklet); | ||
167 | break; | ||
168 | case WMI_TXRATE_EVENTID: | ||
169 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
170 | txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; | ||
171 | wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); | ||
172 | #endif | ||
173 | break; | ||
174 | default: | ||
175 | break; | ||
176 | } | ||
177 | kfree_skb(skb); | ||
206 | return; | 178 | return; |
207 | } | 179 | } |
208 | 180 | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index a0bf857625df..ac61074af8ac 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -31,10 +31,6 @@ struct wmi_cmd_hdr { | |||
31 | __be16 seq_no; | 31 | __be16 seq_no; |
32 | } __packed; | 32 | } __packed; |
33 | 33 | ||
34 | struct wmi_swba { | ||
35 | u8 beacon_pending; | ||
36 | } __packed; | ||
37 | |||
38 | enum wmi_cmd_id { | 34 | enum wmi_cmd_id { |
39 | WMI_ECHO_CMDID = 0x0001, | 35 | WMI_ECHO_CMDID = 0x0001, |
40 | WMI_ACCESS_MEMORY_CMDID, | 36 | WMI_ACCESS_MEMORY_CMDID, |
@@ -104,7 +100,7 @@ struct wmi { | |||
104 | u32 cmd_rsp_len; | 100 | u32 cmd_rsp_len; |
105 | bool stopped; | 101 | bool stopped; |
106 | 102 | ||
107 | struct sk_buff *wmi_skb; | 103 | u8 beacon_pending; |
108 | spinlock_t wmi_lock; | 104 | spinlock_t wmi_lock; |
109 | 105 | ||
110 | atomic_t mwrite_cnt; | 106 | atomic_t mwrite_cnt; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 457f07692ac7..85a7323a04ef 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -61,6 +61,8 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | |||
61 | struct ath_tx_status *ts, int txok); | 61 | struct ath_tx_status *ts, int txok); |
62 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | 62 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, |
63 | int nbad, int txok, bool update_rc); | 63 | int nbad, int txok, bool update_rc); |
64 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | ||
65 | int seqno); | ||
64 | 66 | ||
65 | enum { | 67 | enum { |
66 | MCS_HT20, | 68 | MCS_HT20, |
@@ -143,18 +145,23 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
143 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | 145 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; |
144 | struct ath_buf *bf; | 146 | struct ath_buf *bf; |
145 | struct list_head bf_head; | 147 | struct list_head bf_head; |
146 | INIT_LIST_HEAD(&bf_head); | 148 | struct ath_tx_status ts; |
147 | 149 | ||
148 | WARN_ON(!tid->paused); | 150 | INIT_LIST_HEAD(&bf_head); |
149 | 151 | ||
152 | memset(&ts, 0, sizeof(ts)); | ||
150 | spin_lock_bh(&txq->axq_lock); | 153 | spin_lock_bh(&txq->axq_lock); |
151 | tid->paused = false; | ||
152 | 154 | ||
153 | while (!list_empty(&tid->buf_q)) { | 155 | while (!list_empty(&tid->buf_q)) { |
154 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 156 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
155 | BUG_ON(bf_isretried(bf)); | ||
156 | list_move_tail(&bf->list, &bf_head); | 157 | list_move_tail(&bf->list, &bf_head); |
157 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); | 158 | |
159 | if (bf_isretried(bf)) { | ||
160 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | ||
161 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | ||
162 | } else { | ||
163 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); | ||
164 | } | ||
158 | } | 165 | } |
159 | 166 | ||
160 | spin_unlock_bh(&txq->axq_lock); | 167 | spin_unlock_bh(&txq->axq_lock); |
@@ -168,9 +175,9 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
168 | index = ATH_BA_INDEX(tid->seq_start, seqno); | 175 | index = ATH_BA_INDEX(tid->seq_start, seqno); |
169 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 176 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
170 | 177 | ||
171 | tid->tx_buf[cindex] = NULL; | 178 | __clear_bit(cindex, tid->tx_buf); |
172 | 179 | ||
173 | while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { | 180 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { |
174 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 181 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); |
175 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); | 182 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); |
176 | } | 183 | } |
@@ -186,9 +193,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
186 | 193 | ||
187 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); | 194 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); |
188 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 195 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
189 | 196 | __set_bit(cindex, tid->tx_buf); | |
190 | BUG_ON(tid->tx_buf[cindex] != NULL); | ||
191 | tid->tx_buf[cindex] = bf; | ||
192 | 197 | ||
193 | if (index >= ((tid->baw_tail - tid->baw_head) & | 198 | if (index >= ((tid->baw_tail - tid->baw_head) & |
194 | (ATH_TID_MAX_BUFS - 1))) { | 199 | (ATH_TID_MAX_BUFS - 1))) { |
@@ -431,7 +436,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
431 | list_move_tail(&bf->list, &bf_head); | 436 | list_move_tail(&bf->list, &bf_head); |
432 | } | 437 | } |
433 | 438 | ||
434 | if (!txpending) { | 439 | if (!txpending || (tid->state & AGGR_CLEANUP)) { |
435 | /* | 440 | /* |
436 | * complete the acked-ones/xretried ones; update | 441 | * complete the acked-ones/xretried ones; update |
437 | * block-ack window | 442 | * block-ack window |
@@ -510,15 +515,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
510 | } | 515 | } |
511 | 516 | ||
512 | if (tid->state & AGGR_CLEANUP) { | 517 | if (tid->state & AGGR_CLEANUP) { |
518 | ath_tx_flush_tid(sc, tid); | ||
519 | |||
513 | if (tid->baw_head == tid->baw_tail) { | 520 | if (tid->baw_head == tid->baw_tail) { |
514 | tid->state &= ~AGGR_ADDBA_COMPLETE; | 521 | tid->state &= ~AGGR_ADDBA_COMPLETE; |
515 | tid->state &= ~AGGR_CLEANUP; | 522 | tid->state &= ~AGGR_CLEANUP; |
516 | |||
517 | /* send buffered frames as singles */ | ||
518 | ath_tx_flush_tid(sc, tid); | ||
519 | } | 523 | } |
520 | rcu_read_unlock(); | ||
521 | return; | ||
522 | } | 524 | } |
523 | 525 | ||
524 | rcu_read_unlock(); | 526 | rcu_read_unlock(); |
@@ -785,17 +787,23 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
785 | status != ATH_AGGR_BAW_CLOSED); | 787 | status != ATH_AGGR_BAW_CLOSED); |
786 | } | 788 | } |
787 | 789 | ||
788 | void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 790 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
789 | u16 tid, u16 *ssn) | 791 | u16 tid, u16 *ssn) |
790 | { | 792 | { |
791 | struct ath_atx_tid *txtid; | 793 | struct ath_atx_tid *txtid; |
792 | struct ath_node *an; | 794 | struct ath_node *an; |
793 | 795 | ||
794 | an = (struct ath_node *)sta->drv_priv; | 796 | an = (struct ath_node *)sta->drv_priv; |
795 | txtid = ATH_AN_2_TID(an, tid); | 797 | txtid = ATH_AN_2_TID(an, tid); |
798 | |||
799 | if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE)) | ||
800 | return -EAGAIN; | ||
801 | |||
796 | txtid->state |= AGGR_ADDBA_PROGRESS; | 802 | txtid->state |= AGGR_ADDBA_PROGRESS; |
797 | txtid->paused = true; | 803 | txtid->paused = true; |
798 | *ssn = txtid->seq_start; | 804 | *ssn = txtid->seq_start; |
805 | |||
806 | return 0; | ||
799 | } | 807 | } |
800 | 808 | ||
801 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 809 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
@@ -803,12 +811,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
803 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 811 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
804 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | 812 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); |
805 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; | 813 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; |
806 | struct ath_tx_status ts; | ||
807 | struct ath_buf *bf; | ||
808 | struct list_head bf_head; | ||
809 | |||
810 | memset(&ts, 0, sizeof(ts)); | ||
811 | INIT_LIST_HEAD(&bf_head); | ||
812 | 814 | ||
813 | if (txtid->state & AGGR_CLEANUP) | 815 | if (txtid->state & AGGR_CLEANUP) |
814 | return; | 816 | return; |
@@ -818,31 +820,22 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
818 | return; | 820 | return; |
819 | } | 821 | } |
820 | 822 | ||
821 | /* drop all software retried frames and mark this TID */ | ||
822 | spin_lock_bh(&txq->axq_lock); | 823 | spin_lock_bh(&txq->axq_lock); |
823 | txtid->paused = true; | 824 | txtid->paused = true; |
824 | while (!list_empty(&txtid->buf_q)) { | ||
825 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | ||
826 | if (!bf_isretried(bf)) { | ||
827 | /* | ||
828 | * NB: it's based on the assumption that | ||
829 | * software retried frame will always stay | ||
830 | * at the head of software queue. | ||
831 | */ | ||
832 | break; | ||
833 | } | ||
834 | list_move_tail(&bf->list, &bf_head); | ||
835 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); | ||
836 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | ||
837 | } | ||
838 | spin_unlock_bh(&txq->axq_lock); | ||
839 | 825 | ||
840 | if (txtid->baw_head != txtid->baw_tail) { | 826 | /* |
827 | * If frames are still being transmitted for this TID, they will be | ||
828 | * cleaned up during tx completion. To prevent race conditions, this | ||
829 | * TID can only be reused after all in-progress subframes have been | ||
830 | * completed. | ||
831 | */ | ||
832 | if (txtid->baw_head != txtid->baw_tail) | ||
841 | txtid->state |= AGGR_CLEANUP; | 833 | txtid->state |= AGGR_CLEANUP; |
842 | } else { | 834 | else |
843 | txtid->state &= ~AGGR_ADDBA_COMPLETE; | 835 | txtid->state &= ~AGGR_ADDBA_COMPLETE; |
844 | ath_tx_flush_tid(sc, txtid); | 836 | spin_unlock_bh(&txq->axq_lock); |
845 | } | 837 | |
838 | ath_tx_flush_tid(sc, txtid); | ||
846 | } | 839 | } |
847 | 840 | ||
848 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 841 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
@@ -862,20 +855,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid | |||
862 | } | 855 | } |
863 | } | 856 | } |
864 | 857 | ||
865 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) | ||
866 | { | ||
867 | struct ath_atx_tid *txtid; | ||
868 | |||
869 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | ||
870 | return false; | ||
871 | |||
872 | txtid = ATH_AN_2_TID(an, tidno); | ||
873 | |||
874 | if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) | ||
875 | return true; | ||
876 | return false; | ||
877 | } | ||
878 | |||
879 | /********************/ | 858 | /********************/ |
880 | /* Queue Management */ | 859 | /* Queue Management */ |
881 | /********************/ | 860 | /********************/ |