diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-09-30 14:52:16 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-09-30 14:52:29 -0400 |
commit | 8e00f5fbb4ecbc3431fa686cba60cd76a62604af (patch) | |
tree | 78aa3bdef892dbd1afc8969fc528e529cfc266f7 /drivers/net | |
parent | 56fd49e399ce1d82200fad5b8924d4e35a587809 (diff) | |
parent | 0874073570d9184a169a4ae2abbe8dbcb71878e9 (diff) |
Merge branch 'master' of git://git.infradead.org/users/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/iwlwifi/iwl-pci.c
drivers/net/wireless/wl12xx/main.c
Diffstat (limited to 'drivers/net')
121 files changed, 4906 insertions, 3937 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 43ebc44fc82c..3b752d9fb3cd 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1249,7 +1249,8 @@ static int adm8211_hw_reset(struct ieee80211_hw *dev) | |||
1249 | return 0; | 1249 | return 0; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | static u64 adm8211_get_tsft(struct ieee80211_hw *dev) | 1252 | static u64 adm8211_get_tsft(struct ieee80211_hw *dev, |
1253 | struct ieee80211_vif *vif) | ||
1253 | { | 1254 | { |
1254 | struct adm8211_priv *priv = dev->priv; | 1255 | struct adm8211_priv *priv = dev->priv; |
1255 | u32 tsftl; | 1256 | u32 tsftl; |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 0560234ec3f6..bba4f6fcf7e2 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -602,7 +602,7 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
602 | 602 | ||
603 | 603 | ||
604 | static u64 | 604 | static u64 |
605 | ath5k_get_tsf(struct ieee80211_hw *hw) | 605 | ath5k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
606 | { | 606 | { |
607 | struct ath5k_hw *ah = hw->priv; | 607 | struct ath5k_hw *ah = hw->priv; |
608 | 608 | ||
@@ -611,7 +611,7 @@ ath5k_get_tsf(struct ieee80211_hw *hw) | |||
611 | 611 | ||
612 | 612 | ||
613 | static void | 613 | static void |
614 | ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 614 | ath5k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf) |
615 | { | 615 | { |
616 | struct ath5k_hw *ah = hw->priv; | 616 | struct ath5k_hw *ah = hw->priv; |
617 | 617 | ||
@@ -620,7 +620,7 @@ ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | |||
620 | 620 | ||
621 | 621 | ||
622 | static void | 622 | static void |
623 | ath5k_reset_tsf(struct ieee80211_hw *hw) | 623 | ath5k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
624 | { | 624 | { |
625 | struct ath5k_hw *ah = hw->priv; | 625 | struct ath5k_hw *ah = hw->priv; |
626 | 626 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index d969a11e3425..01240d63896e 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -273,7 +273,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
273 | immunityLevel, aniState->noiseFloor, | 273 | immunityLevel, aniState->noiseFloor, |
274 | aniState->rssiThrLow, aniState->rssiThrHigh); | 274 | aniState->rssiThrLow, aniState->rssiThrHigh); |
275 | 275 | ||
276 | aniState->ofdmNoiseImmunityLevel = immunityLevel; | 276 | if (aniState->update_ani) |
277 | aniState->ofdmNoiseImmunityLevel = immunityLevel; | ||
277 | 278 | ||
278 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | 279 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; |
279 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | 280 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; |
@@ -346,7 +347,8 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
346 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) | 347 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) |
347 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; | 348 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; |
348 | 349 | ||
349 | aniState->cckNoiseImmunityLevel = immunityLevel; | 350 | if (aniState->update_ani) |
351 | aniState->cckNoiseImmunityLevel = immunityLevel; | ||
350 | 352 | ||
351 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | 353 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; |
352 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | 354 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; |
@@ -593,6 +595,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
593 | aniState->ofdmNoiseImmunityLevel, | 595 | aniState->ofdmNoiseImmunityLevel, |
594 | aniState->cckNoiseImmunityLevel); | 596 | aniState->cckNoiseImmunityLevel); |
595 | 597 | ||
598 | aniState->update_ani = false; | ||
596 | ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); | 599 | ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); |
597 | ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); | 600 | ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); |
598 | } | 601 | } |
@@ -609,6 +612,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
609 | aniState->ofdmNoiseImmunityLevel, | 612 | aniState->ofdmNoiseImmunityLevel, |
610 | aniState->cckNoiseImmunityLevel); | 613 | aniState->cckNoiseImmunityLevel); |
611 | 614 | ||
615 | aniState->update_ani = true; | ||
612 | ath9k_hw_set_ofdm_nil(ah, | 616 | ath9k_hw_set_ofdm_nil(ah, |
613 | aniState->ofdmNoiseImmunityLevel); | 617 | aniState->ofdmNoiseImmunityLevel); |
614 | ath9k_hw_set_cck_nil(ah, | 618 | ath9k_hw_set_cck_nil(ah, |
@@ -892,6 +896,8 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
892 | ani->ofdmWeakSigDetectOff = | 896 | ani->ofdmWeakSigDetectOff = |
893 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 897 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
894 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; | 898 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
899 | ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; | ||
900 | ani->update_ani = false; | ||
895 | } | 901 | } |
896 | 902 | ||
897 | /* | 903 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index a547005572e7..83029d6c7b22 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -122,6 +122,7 @@ struct ar5416AniState { | |||
122 | u8 firstepLevel; | 122 | u8 firstepLevel; |
123 | u8 ofdmWeakSigDetectOff; | 123 | u8 ofdmWeakSigDetectOff; |
124 | u8 cckWeakSigThreshold; | 124 | u8 cckWeakSigThreshold; |
125 | bool update_ani; | ||
125 | u32 listenTime; | 126 | u32 listenTime; |
126 | int32_t rssiThrLow; | 127 | int32_t rssiThrLow; |
127 | int32_t rssiThrHigh; | 128 | int32_t rssiThrHigh; |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index fac2c6da6ca4..0a749c8fa634 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -704,8 +704,10 @@ static void ar5008_hw_override_ini(struct ath_hw *ah, | |||
704 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); | 704 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); |
705 | } | 705 | } |
706 | 706 | ||
707 | if (!AR_SREV_5416_20_OR_LATER(ah) || | 707 | REG_SET_BIT(ah, AR_PHY_CCK_DETECT, |
708 | AR_SREV_9280_20_OR_LATER(ah)) | 708 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); |
709 | |||
710 | if (AR_SREV_9280_20_OR_LATER(ah)) | ||
709 | return; | 711 | return; |
710 | /* | 712 | /* |
711 | * Disable BB clock gating | 713 | * Disable BB clock gating |
@@ -802,7 +804,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
802 | 804 | ||
803 | /* Write ADDAC shifts */ | 805 | /* Write ADDAC shifts */ |
804 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); | 806 | REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); |
805 | ah->eep_ops->set_addac(ah, chan); | 807 | if (ah->eep_ops->set_addac) |
808 | ah->eep_ops->set_addac(ah, chan); | ||
806 | 809 | ||
807 | if (AR_SREV_5416_22_OR_LATER(ah)) { | 810 | if (AR_SREV_5416_22_OR_LATER(ah)) { |
808 | REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); | 811 | REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); |
@@ -1007,24 +1010,6 @@ static void ar5008_restore_chainmask(struct ath_hw *ah) | |||
1007 | } | 1010 | } |
1008 | } | 1011 | } |
1009 | 1012 | ||
1010 | static void ar5008_set_diversity(struct ath_hw *ah, bool value) | ||
1011 | { | ||
1012 | u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
1013 | if (value) | ||
1014 | v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
1015 | else | ||
1016 | v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
1017 | REG_WRITE(ah, AR_PHY_CCK_DETECT, v); | ||
1018 | } | ||
1019 | |||
1020 | static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah, | ||
1021 | struct ath9k_channel *chan) | ||
1022 | { | ||
1023 | if (chan && IS_CHAN_5GHZ(chan)) | ||
1024 | return 0x1450; | ||
1025 | return 0x1458; | ||
1026 | } | ||
1027 | |||
1028 | static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah, | 1013 | static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah, |
1029 | struct ath9k_channel *chan) | 1014 | struct ath9k_channel *chan) |
1030 | { | 1015 | { |
@@ -1654,7 +1639,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1654 | priv_ops->rfbus_req = ar5008_hw_rfbus_req; | 1639 | priv_ops->rfbus_req = ar5008_hw_rfbus_req; |
1655 | priv_ops->rfbus_done = ar5008_hw_rfbus_done; | 1640 | priv_ops->rfbus_done = ar5008_hw_rfbus_done; |
1656 | priv_ops->restore_chainmask = ar5008_restore_chainmask; | 1641 | priv_ops->restore_chainmask = ar5008_restore_chainmask; |
1657 | priv_ops->set_diversity = ar5008_set_diversity; | ||
1658 | priv_ops->do_getnf = ar5008_hw_do_getnf; | 1642 | priv_ops->do_getnf = ar5008_hw_do_getnf; |
1659 | priv_ops->set_radar_params = ar5008_hw_set_radar_params; | 1643 | priv_ops->set_radar_params = ar5008_hw_set_radar_params; |
1660 | 1644 | ||
@@ -1664,9 +1648,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1664 | } else | 1648 | } else |
1665 | priv_ops->ani_control = ar5008_hw_ani_control_old; | 1649 | priv_ops->ani_control = ar5008_hw_ani_control_old; |
1666 | 1650 | ||
1667 | if (AR_SREV_9100(ah)) | 1651 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) |
1668 | priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; | ||
1669 | else if (AR_SREV_9160_10_OR_LATER(ah)) | ||
1670 | priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; | 1652 | priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; |
1671 | else | 1653 | else |
1672 | priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; | 1654 | priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 2d394af82171..e0ab0657cc3a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -869,6 +869,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
869 | ar9002_hw_pa_cal(ah, true); | 869 | ar9002_hw_pa_cal(ah, true); |
870 | 870 | ||
871 | /* Do NF Calibration after DC offset and other calibrations */ | 871 | /* Do NF Calibration after DC offset and other calibrations */ |
872 | ath9k_hw_loadnf(ah, chan); | ||
872 | ath9k_hw_start_nfcal(ah, true); | 873 | ath9k_hw_start_nfcal(ah, true); |
873 | 874 | ||
874 | if (ah->caldata) | 875 | if (ah->caldata) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index f2c6f2316a3b..08e9341f6368 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -1514,7 +1514,7 @@ static const u32 ar9300_2p2_mac_core[][2] = { | |||
1514 | {0x00008258, 0x00000000}, | 1514 | {0x00008258, 0x00000000}, |
1515 | {0x0000825c, 0x40000000}, | 1515 | {0x0000825c, 0x40000000}, |
1516 | {0x00008260, 0x00080922}, | 1516 | {0x00008260, 0x00080922}, |
1517 | {0x00008264, 0x9bc00010}, | 1517 | {0x00008264, 0x9d400010}, |
1518 | {0x00008268, 0xffffffff}, | 1518 | {0x00008268, 0xffffffff}, |
1519 | {0x0000826c, 0x0000ffff}, | 1519 | {0x0000826c, 0x0000ffff}, |
1520 | {0x00008270, 0x00000000}, | 1520 | {0x00008270, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 3319a676c0fb..e4b1a8300854 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -652,8 +652,9 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, | |||
652 | outlier_idx = max_idx; | 652 | outlier_idx = max_idx; |
653 | else | 653 | else |
654 | outlier_idx = min_idx; | 654 | outlier_idx = min_idx; |
655 | |||
656 | mp_coeff[outlier_idx] = mp_avg; | ||
655 | } | 657 | } |
656 | mp_coeff[outlier_idx] = mp_avg; | ||
657 | } | 658 | } |
658 | 659 | ||
659 | static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, | 660 | static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, |
@@ -884,6 +885,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
884 | if (txiqcal_done) | 885 | if (txiqcal_done) |
885 | ar9003_hw_tx_iq_cal_post_proc(ah); | 886 | ar9003_hw_tx_iq_cal_post_proc(ah); |
886 | 887 | ||
888 | ath9k_hw_loadnf(ah, chan); | ||
887 | ath9k_hw_start_nfcal(ah, true); | 889 | ath9k_hw_start_nfcal(ah, true); |
888 | 890 | ||
889 | /* Initialize list pointers */ | 891 | /* Initialize list pointers */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 4956d09cb589..7db6e8647a01 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -595,6 +595,9 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) | |||
595 | val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); | 595 | val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); |
596 | REG_WRITE(ah, AR_PCU_MISC_MODE2, | 596 | REG_WRITE(ah, AR_PCU_MISC_MODE2, |
597 | val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE); | 597 | val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE); |
598 | |||
599 | REG_SET_BIT(ah, AR_PHY_CCK_DETECT, | ||
600 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | ||
598 | } | 601 | } |
599 | 602 | ||
600 | static void ar9003_hw_prog_ini(struct ath_hw *ah, | 603 | static void ar9003_hw_prog_ini(struct ath_hw *ah, |
@@ -795,16 +798,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah) | |||
795 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); | 798 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); |
796 | } | 799 | } |
797 | 800 | ||
798 | static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) | ||
799 | { | ||
800 | u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
801 | if (value) | ||
802 | v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
803 | else | ||
804 | v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
805 | REG_WRITE(ah, AR_PHY_CCK_DETECT, v); | ||
806 | } | ||
807 | |||
808 | static bool ar9003_hw_ani_control(struct ath_hw *ah, | 801 | static bool ar9003_hw_ani_control(struct ath_hw *ah, |
809 | enum ath9k_ani_cmd cmd, int param) | 802 | enum ath9k_ani_cmd cmd, int param) |
810 | { | 803 | { |
@@ -1287,7 +1280,6 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1287 | priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; | 1280 | priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; |
1288 | priv_ops->rfbus_req = ar9003_hw_rfbus_req; | 1281 | priv_ops->rfbus_req = ar9003_hw_rfbus_req; |
1289 | priv_ops->rfbus_done = ar9003_hw_rfbus_done; | 1282 | priv_ops->rfbus_done = ar9003_hw_rfbus_done; |
1290 | priv_ops->set_diversity = ar9003_hw_set_diversity; | ||
1291 | priv_ops->ani_control = ar9003_hw_ani_control; | 1283 | priv_ops->ani_control = ar9003_hw_ani_control; |
1292 | priv_ops->do_getnf = ar9003_hw_do_getnf; | 1284 | priv_ops->do_getnf = ar9003_hw_do_getnf; |
1293 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; | 1285 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 179da2099270..a5329c98f9ea 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -876,6 +876,15 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | |||
876 | TX_SAMP_DBG(rssi) = ts->ts_rssi; | 876 | TX_SAMP_DBG(rssi) = ts->ts_rssi; |
877 | TX_SAMP_DBG(tid) = ts->tid; | 877 | TX_SAMP_DBG(tid) = ts->tid; |
878 | TX_SAMP_DBG(qid) = ts->qid; | 878 | TX_SAMP_DBG(qid) = ts->qid; |
879 | |||
880 | if (ts->ts_flags & ATH9K_TX_BA) { | ||
881 | TX_SAMP_DBG(ba_low) = ts->ba_low; | ||
882 | TX_SAMP_DBG(ba_high) = ts->ba_high; | ||
883 | } else { | ||
884 | TX_SAMP_DBG(ba_low) = 0; | ||
885 | TX_SAMP_DBG(ba_high) = 0; | ||
886 | } | ||
887 | |||
879 | sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; | 888 | sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; |
880 | spin_unlock(&sc->debug.samp_lock); | 889 | spin_unlock(&sc->debug.samp_lock); |
881 | 890 | ||
@@ -1516,14 +1525,15 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) | |||
1516 | len += snprintf(buf + len, size - len, "Tx status Dump :\n"); | 1525 | len += snprintf(buf + len, size - len, "Tx status Dump :\n"); |
1517 | len += snprintf(buf + len, size - len, | 1526 | len += snprintf(buf + len, size - len, |
1518 | "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb " | 1527 | "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb " |
1519 | "isok rts_fail data_fail rate tid qid tx_before(ms)\n"); | 1528 | "isok rts_fail data_fail rate tid qid " |
1529 | "ba_low ba_high tx_before(ms)\n"); | ||
1520 | for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { | 1530 | for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { |
1521 | for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { | 1531 | for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { |
1522 | if (!ATH_SAMP_DBG(ts[i].jiffies)) | 1532 | if (!ATH_SAMP_DBG(ts[i].jiffies)) |
1523 | continue; | 1533 | continue; |
1524 | len += snprintf(buf + len, size - len, "%4d \t" | 1534 | len += snprintf(buf + len, size - len, "%-14d" |
1525 | "%8d %4d %4d %4d %4d %4d %4d %4d %4d " | 1535 | "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d " |
1526 | "%4d %4d %2d %2d %d\n", | 1536 | "%-9d %-4d %-3d %-3d %08x %08x %-11d\n", |
1527 | sampidx, | 1537 | sampidx, |
1528 | ATH_SAMP_DBG(ts[i].rssi_ctl0), | 1538 | ATH_SAMP_DBG(ts[i].rssi_ctl0), |
1529 | ATH_SAMP_DBG(ts[i].rssi_ctl1), | 1539 | ATH_SAMP_DBG(ts[i].rssi_ctl1), |
@@ -1538,6 +1548,8 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) | |||
1538 | ATH_SAMP_DBG(ts[i].rateindex), | 1548 | ATH_SAMP_DBG(ts[i].rateindex), |
1539 | ATH_SAMP_DBG(ts[i].tid), | 1549 | ATH_SAMP_DBG(ts[i].tid), |
1540 | ATH_SAMP_DBG(ts[i].qid), | 1550 | ATH_SAMP_DBG(ts[i].qid), |
1551 | ATH_SAMP_DBG(ts[i].ba_low), | ||
1552 | ATH_SAMP_DBG(ts[i].ba_high), | ||
1541 | jiffies_to_msecs(jiffies - | 1553 | jiffies_to_msecs(jiffies - |
1542 | ATH_SAMP_DBG(ts[i].jiffies))); | 1554 | ATH_SAMP_DBG(ts[i].jiffies))); |
1543 | } | 1555 | } |
@@ -1550,8 +1562,8 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) | |||
1550 | for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { | 1562 | for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { |
1551 | if (!ATH_SAMP_DBG(rs[i].jiffies)) | 1563 | if (!ATH_SAMP_DBG(rs[i].jiffies)) |
1552 | continue; | 1564 | continue; |
1553 | len += snprintf(buf + len, size - len, "%4d \t" | 1565 | len += snprintf(buf + len, size - len, "%-14d" |
1554 | "%8d %4d %4d %4d %4d %4d %4d %s %4d %02x %d\n", | 1566 | "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n", |
1555 | sampidx, | 1567 | sampidx, |
1556 | ATH_SAMP_DBG(rs[i].rssi_ctl0), | 1568 | ATH_SAMP_DBG(rs[i].rssi_ctl0), |
1557 | ATH_SAMP_DBG(rs[i].rssi_ctl1), | 1569 | ATH_SAMP_DBG(rs[i].rssi_ctl1), |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 39f89bc9abcd..b93e88bd8c58 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -196,6 +196,8 @@ struct ath_dbg_bb_mac_samp { | |||
196 | u8 rateindex; | 196 | u8 rateindex; |
197 | u8 qid; | 197 | u8 qid; |
198 | u8 tid; | 198 | u8 tid; |
199 | u32 ba_low; | ||
200 | u32 ba_high; | ||
199 | } ts[ATH_DBG_MAX_SAMPLES]; | 201 | } ts[ATH_DBG_MAX_SAMPLES]; |
200 | struct { | 202 | struct { |
201 | u64 jiffies; | 203 | u64 jiffies; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index e61404dda8c5..e46f751ab508 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
456 | pPdGainBoundaries[i] = | 456 | pPdGainBoundaries[i] = |
457 | min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]); | 457 | min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]); |
458 | 458 | ||
459 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | 459 | minDelta = 0; |
460 | minDelta = pPdGainBoundaries[0] - 23; | ||
461 | pPdGainBoundaries[0] = 23; | ||
462 | } else { | ||
463 | minDelta = 0; | ||
464 | } | ||
465 | 460 | ||
466 | if (i == 0) { | 461 | if (i == 0) { |
467 | if (AR_SREV_9280_20_OR_LATER(ah)) | 462 | if (AR_SREV_9280_20_OR_LATER(ah)) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index ea658e794cbd..303560e49ac8 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -405,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
405 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); | 405 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); |
406 | 406 | ||
407 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | 407 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { |
408 | if (AR_SREV_5416_20_OR_LATER(ah) && | 408 | regChainOffset = i * 0x1000; |
409 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | ||
410 | (i != 0)) { | ||
411 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
412 | } else | ||
413 | regChainOffset = i * 0x1000; | ||
414 | 409 | ||
415 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | 410 | if (pEepData->baseEepHeader.txMask & (1 << i)) { |
416 | pRawDataset = pEepData->calPierData2G[i]; | 411 | pRawDataset = pEepData->calPierData2G[i]; |
@@ -423,19 +418,17 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
423 | 418 | ||
424 | ENABLE_REGWRITE_BUFFER(ah); | 419 | ENABLE_REGWRITE_BUFFER(ah); |
425 | 420 | ||
426 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | 421 | REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, |
427 | REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, | 422 | SM(pdGainOverlap_t2, |
428 | SM(pdGainOverlap_t2, | 423 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
429 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | 424 | | SM(gainBoundaries[0], |
430 | | SM(gainBoundaries[0], | 425 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
431 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | 426 | | SM(gainBoundaries[1], |
432 | | SM(gainBoundaries[1], | 427 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
433 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | 428 | | SM(gainBoundaries[2], |
434 | | SM(gainBoundaries[2], | 429 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
435 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | 430 | | SM(gainBoundaries[3], |
436 | | SM(gainBoundaries[3], | 431 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); |
437 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
438 | } | ||
439 | 432 | ||
440 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | 433 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; |
441 | for (j = 0; j < 32; j++) { | 434 | for (j = 0; j < 32; j++) { |
@@ -715,10 +708,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
715 | if (test) | 708 | if (test) |
716 | return; | 709 | return; |
717 | 710 | ||
718 | if (AR_SREV_9280_20_OR_LATER(ah)) { | 711 | for (i = 0; i < Ar5416RateSize; i++) |
719 | for (i = 0; i < Ar5416RateSize; i++) | 712 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; |
720 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; | ||
721 | } | ||
722 | 713 | ||
723 | ENABLE_REGWRITE_BUFFER(ah); | 714 | ENABLE_REGWRITE_BUFFER(ah); |
724 | 715 | ||
@@ -788,28 +779,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
788 | REGWRITE_BUFFER_FLUSH(ah); | 779 | REGWRITE_BUFFER_FLUSH(ah); |
789 | } | 780 | } |
790 | 781 | ||
791 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | ||
792 | struct ath9k_channel *chan) | ||
793 | { | ||
794 | struct modal_eep_4k_header *pModal; | ||
795 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
796 | u8 biaslevel; | ||
797 | |||
798 | if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) | ||
799 | return; | ||
800 | |||
801 | if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) | ||
802 | return; | ||
803 | |||
804 | pModal = &eep->modalHeader; | ||
805 | |||
806 | if (pModal->xpaBiasLvl != 0xff) { | ||
807 | biaslevel = pModal->xpaBiasLvl; | ||
808 | INI_RA(&ah->iniAddac, 7, 1) = | ||
809 | (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; | ||
810 | } | ||
811 | } | ||
812 | |||
813 | static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | 782 | static void ath9k_hw_4k_set_gain(struct ath_hw *ah, |
814 | struct modal_eep_4k_header *pModal, | 783 | struct modal_eep_4k_header *pModal, |
815 | struct ar5416_eeprom_4k *eep, | 784 | struct ar5416_eeprom_4k *eep, |
@@ -877,6 +846,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
877 | u8 txRxAttenLocal; | 846 | u8 txRxAttenLocal; |
878 | u8 ob[5], db1[5], db2[5]; | 847 | u8 ob[5], db1[5], db2[5]; |
879 | u8 ant_div_control1, ant_div_control2; | 848 | u8 ant_div_control1, ant_div_control2; |
849 | u8 bb_desired_scale; | ||
880 | u32 regVal; | 850 | u32 regVal; |
881 | 851 | ||
882 | pModal = &eep->modalHeader; | 852 | pModal = &eep->modalHeader; |
@@ -1096,30 +1066,29 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1096 | AR_PHY_SETTLING_SWITCH, | 1066 | AR_PHY_SETTLING_SWITCH, |
1097 | pModal->swSettleHt40); | 1067 | pModal->swSettleHt40); |
1098 | } | 1068 | } |
1099 | if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) { | 1069 | |
1100 | u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna & | 1070 | bb_desired_scale = (pModal->bb_scale_smrt_antenna & |
1101 | EEP_4K_BB_DESIRED_SCALE_MASK); | 1071 | EEP_4K_BB_DESIRED_SCALE_MASK); |
1102 | if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { | 1072 | if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { |
1103 | u32 pwrctrl, mask, clr; | 1073 | u32 pwrctrl, mask, clr; |
1104 | 1074 | ||
1105 | mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); | 1075 | mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); |
1106 | pwrctrl = mask * bb_desired_scale; | 1076 | pwrctrl = mask * bb_desired_scale; |
1107 | clr = mask * 0x1f; | 1077 | clr = mask * 0x1f; |
1108 | REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); | 1078 | REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); |
1109 | REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); | 1079 | REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); |
1110 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); | 1080 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); |
1111 | 1081 | ||
1112 | mask = BIT(0)|BIT(5)|BIT(15); | 1082 | mask = BIT(0)|BIT(5)|BIT(15); |
1113 | pwrctrl = mask * bb_desired_scale; | 1083 | pwrctrl = mask * bb_desired_scale; |
1114 | clr = mask * 0x1f; | 1084 | clr = mask * 0x1f; |
1115 | REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); | 1085 | REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); |
1116 | 1086 | ||
1117 | mask = BIT(0)|BIT(5); | 1087 | mask = BIT(0)|BIT(5); |
1118 | pwrctrl = mask * bb_desired_scale; | 1088 | pwrctrl = mask * bb_desired_scale; |
1119 | clr = mask * 0x1f; | 1089 | clr = mask * 0x1f; |
1120 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); | 1090 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); |
1121 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); | 1091 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); |
1122 | } | ||
1123 | } | 1092 | } |
1124 | } | 1093 | } |
1125 | 1094 | ||
@@ -1161,7 +1130,6 @@ const struct eeprom_ops eep_4k_ops = { | |||
1161 | .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, | 1130 | .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, |
1162 | .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, | 1131 | .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, |
1163 | .set_board_values = ath9k_hw_4k_set_board_values, | 1132 | .set_board_values = ath9k_hw_4k_set_board_values, |
1164 | .set_addac = ath9k_hw_4k_set_addac, | ||
1165 | .set_txpower = ath9k_hw_4k_set_txpower, | 1133 | .set_txpower = ath9k_hw_4k_set_txpower, |
1166 | .get_spur_channel = ath9k_hw_4k_get_spur_channel | 1134 | .get_spur_channel = ath9k_hw_4k_get_spur_channel |
1167 | }; | 1135 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 21f180db2381..6698b722b604 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -851,10 +851,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
851 | if (test) | 851 | if (test) |
852 | return; | 852 | return; |
853 | 853 | ||
854 | if (AR_SREV_9280_20_OR_LATER(ah)) { | 854 | for (i = 0; i < Ar5416RateSize; i++) |
855 | for (i = 0; i < Ar5416RateSize; i++) | 855 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; |
856 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
857 | } | ||
858 | 856 | ||
859 | ENABLE_REGWRITE_BUFFER(ah); | 857 | ENABLE_REGWRITE_BUFFER(ah); |
860 | 858 | ||
@@ -944,11 +942,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
944 | REGWRITE_BUFFER_FLUSH(ah); | 942 | REGWRITE_BUFFER_FLUSH(ah); |
945 | } | 943 | } |
946 | 944 | ||
947 | static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, | ||
948 | struct ath9k_channel *chan) | ||
949 | { | ||
950 | } | ||
951 | |||
952 | static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, | 945 | static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, |
953 | struct ath9k_channel *chan) | 946 | struct ath9k_channel *chan) |
954 | { | 947 | { |
@@ -1100,7 +1093,6 @@ const struct eeprom_ops eep_ar9287_ops = { | |||
1100 | .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, | 1093 | .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, |
1101 | .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, | 1094 | .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, |
1102 | .set_board_values = ath9k_hw_ar9287_set_board_values, | 1095 | .set_board_values = ath9k_hw_ar9287_set_board_values, |
1103 | .set_addac = ath9k_hw_ar9287_set_addac, | ||
1104 | .set_txpower = ath9k_hw_ar9287_set_txpower, | 1096 | .set_txpower = ath9k_hw_ar9287_set_txpower, |
1105 | .get_spur_channel = ath9k_hw_ar9287_get_spur_channel | 1097 | .get_spur_channel = ath9k_hw_ar9287_get_spur_channel |
1106 | }; | 1098 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index e7e84be8beed..eda681fc7ba6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -547,8 +547,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
547 | break; | 547 | break; |
548 | } | 548 | } |
549 | 549 | ||
550 | if (AR_SREV_5416_20_OR_LATER(ah) && | 550 | if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) |
551 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) | ||
552 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | 551 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; |
553 | else | 552 | else |
554 | regChainOffset = i * 0x1000; | 553 | regChainOffset = i * 0x1000; |
@@ -565,9 +564,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
565 | SM(pModal->iqCalQCh[i], | 564 | SM(pModal->iqCalQCh[i], |
566 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | 565 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); |
567 | 566 | ||
568 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) | 567 | ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, |
569 | ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, | 568 | regChainOffset, i); |
570 | regChainOffset, i); | ||
571 | } | 569 | } |
572 | 570 | ||
573 | if (AR_SREV_9280_20_OR_LATER(ah)) { | 571 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
@@ -893,8 +891,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
893 | xpdGainValues[2]); | 891 | xpdGainValues[2]); |
894 | 892 | ||
895 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | 893 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { |
896 | if (AR_SREV_5416_20_OR_LATER(ah) && | 894 | if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && |
897 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | ||
898 | (i != 0)) { | 895 | (i != 0)) { |
899 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | 896 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; |
900 | } else | 897 | } else |
@@ -935,27 +932,24 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
935 | 932 | ||
936 | ENABLE_REGWRITE_BUFFER(ah); | 933 | ENABLE_REGWRITE_BUFFER(ah); |
937 | 934 | ||
938 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | 935 | if (OLC_FOR_AR9280_20_LATER) { |
939 | if (OLC_FOR_AR9280_20_LATER) { | 936 | REG_WRITE(ah, |
940 | REG_WRITE(ah, | 937 | AR_PHY_TPCRG5 + regChainOffset, |
941 | AR_PHY_TPCRG5 + regChainOffset, | 938 | SM(0x6, |
942 | SM(0x6, | 939 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | |
943 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | 940 | SM_PD_GAIN(1) | SM_PD_GAIN(2) | |
944 | SM_PD_GAIN(1) | SM_PD_GAIN(2) | | 941 | SM_PD_GAIN(3) | SM_PD_GAIN(4)); |
945 | SM_PD_GAIN(3) | SM_PD_GAIN(4)); | 942 | } else { |
946 | } else { | 943 | REG_WRITE(ah, |
947 | REG_WRITE(ah, | 944 | AR_PHY_TPCRG5 + regChainOffset, |
948 | AR_PHY_TPCRG5 + regChainOffset, | 945 | SM(pdGainOverlap_t2, |
949 | SM(pdGainOverlap_t2, | 946 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| |
950 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| | 947 | SM_PDGAIN_B(0, 1) | |
951 | SM_PDGAIN_B(0, 1) | | 948 | SM_PDGAIN_B(1, 2) | |
952 | SM_PDGAIN_B(1, 2) | | 949 | SM_PDGAIN_B(2, 3) | |
953 | SM_PDGAIN_B(2, 3) | | 950 | SM_PDGAIN_B(3, 4)); |
954 | SM_PDGAIN_B(3, 4)); | ||
955 | } | ||
956 | } | 951 | } |
957 | 952 | ||
958 | |||
959 | ath9k_adjust_pdadc_values(ah, pwr_table_offset, | 953 | ath9k_adjust_pdadc_values(ah, pwr_table_offset, |
960 | diff, pdadcValues); | 954 | diff, pdadcValues); |
961 | 955 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 495fdf680a6c..17dbbd9d2f53 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1563,7 +1563,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1563 | mutex_unlock(&priv->mutex); | 1563 | mutex_unlock(&priv->mutex); |
1564 | } | 1564 | } |
1565 | 1565 | ||
1566 | static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) | 1566 | static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw, |
1567 | struct ieee80211_vif *vif) | ||
1567 | { | 1568 | { |
1568 | struct ath9k_htc_priv *priv = hw->priv; | 1569 | struct ath9k_htc_priv *priv = hw->priv; |
1569 | u64 tsf; | 1570 | u64 tsf; |
@@ -1577,7 +1578,8 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw) | |||
1577 | return tsf; | 1578 | return tsf; |
1578 | } | 1579 | } |
1579 | 1580 | ||
1580 | static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 1581 | static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, |
1582 | struct ieee80211_vif *vif, u64 tsf) | ||
1581 | { | 1583 | { |
1582 | struct ath9k_htc_priv *priv = hw->priv; | 1584 | struct ath9k_htc_priv *priv = hw->priv; |
1583 | 1585 | ||
@@ -1588,7 +1590,8 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf) | |||
1588 | mutex_unlock(&priv->mutex); | 1590 | mutex_unlock(&priv->mutex); |
1589 | } | 1591 | } |
1590 | 1592 | ||
1591 | static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) | 1593 | static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, |
1594 | struct ieee80211_vif *vif) | ||
1592 | { | 1595 | { |
1593 | struct ath9k_htc_priv *priv = hw->priv; | 1596 | struct ath9k_htc_priv *priv = hw->priv; |
1594 | 1597 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 41f4bf363d3d..e9782d164962 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -181,11 +181,6 @@ static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah) | |||
181 | return ath9k_hw_private_ops(ah)->restore_chainmask(ah); | 181 | return ath9k_hw_private_ops(ah)->restore_chainmask(ah); |
182 | } | 182 | } |
183 | 183 | ||
184 | static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value) | ||
185 | { | ||
186 | return ath9k_hw_private_ops(ah)->set_diversity(ah, value); | ||
187 | } | ||
188 | |||
189 | static inline bool ath9k_hw_ani_control(struct ath_hw *ah, | 184 | static inline bool ath9k_hw_ani_control(struct ath_hw *ah, |
190 | enum ath9k_ani_cmd cmd, int param) | 185 | enum ath9k_ani_cmd cmd, int param) |
191 | { | 186 | { |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index bf38e2fc8f78..24889f78a053 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -584,7 +584,6 @@ struct ath_hw_private_ops { | |||
584 | bool (*rfbus_req)(struct ath_hw *ah); | 584 | bool (*rfbus_req)(struct ath_hw *ah); |
585 | void (*rfbus_done)(struct ath_hw *ah); | 585 | void (*rfbus_done)(struct ath_hw *ah); |
586 | void (*restore_chainmask)(struct ath_hw *ah); | 586 | void (*restore_chainmask)(struct ath_hw *ah); |
587 | void (*set_diversity)(struct ath_hw *ah, bool value); | ||
588 | u32 (*compute_pll_control)(struct ath_hw *ah, | 587 | u32 (*compute_pll_control)(struct ath_hw *ah, |
589 | struct ath9k_channel *chan); | 588 | struct ath9k_channel *chan); |
590 | bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, | 589 | bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 9b34c4bab937..39514de044ef 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -506,7 +506,6 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
506 | sc->sc_flags |= SC_OP_RXAGGR; | 506 | sc->sc_flags |= SC_OP_RXAGGR; |
507 | } | 507 | } |
508 | 508 | ||
509 | ath9k_hw_set_diversity(sc->sc_ah, true); | ||
510 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); | 509 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); |
511 | 510 | ||
512 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | 511 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 786587ac40a7..22f23eafe8ba 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -584,7 +584,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
584 | else | 584 | else |
585 | rs->rs_keyix = ATH9K_RXKEYIX_INVALID; | 585 | rs->rs_keyix = ATH9K_RXKEYIX_INVALID; |
586 | 586 | ||
587 | rs->rs_rate = RXSTATUS_RATE(ah, (&ads)); | 587 | rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate); |
588 | rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; | 588 | rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; |
589 | 589 | ||
590 | rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; | 590 | rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index ac5a1d265d39..91c96546c0cd 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -17,10 +17,6 @@ | |||
17 | #ifndef MAC_H | 17 | #ifndef MAC_H |
18 | #define MAC_H | 18 | #define MAC_H |
19 | 19 | ||
20 | #define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \ | ||
21 | MS(ads->ds_rxstatus0, AR_RxRate) : \ | ||
22 | (ads->ds_rxstatus3 >> 2) & 0xFF) | ||
23 | |||
24 | #define set11nTries(_series, _index) \ | 20 | #define set11nTries(_series, _index) \ |
25 | (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) | 21 | (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) |
26 | 22 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a16f53994a7e..edaa7843bf4c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -133,7 +133,7 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
133 | ath_hw_cycle_counters_update(common); | 133 | ath_hw_cycle_counters_update(common); |
134 | spin_unlock(&common->cc_lock); | 134 | spin_unlock(&common->cc_lock); |
135 | 135 | ||
136 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); | 136 | ath9k_hw_setpower(sc->sc_ah, mode); |
137 | 137 | ||
138 | unlock: | 138 | unlock: |
139 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 139 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
@@ -2021,6 +2021,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
2021 | /* Stop ANI */ | 2021 | /* Stop ANI */ |
2022 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 2022 | sc->sc_flags &= ~SC_OP_ANI_RUN; |
2023 | del_timer_sync(&common->ani.timer); | 2023 | del_timer_sync(&common->ani.timer); |
2024 | memset(&sc->caldata, 0, sizeof(sc->caldata)); | ||
2024 | } | 2025 | } |
2025 | } | 2026 | } |
2026 | 2027 | ||
@@ -2142,7 +2143,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2142 | ath9k_ps_restore(sc); | 2143 | ath9k_ps_restore(sc); |
2143 | } | 2144 | } |
2144 | 2145 | ||
2145 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | 2146 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
2146 | { | 2147 | { |
2147 | struct ath_softc *sc = hw->priv; | 2148 | struct ath_softc *sc = hw->priv; |
2148 | u64 tsf; | 2149 | u64 tsf; |
@@ -2156,7 +2157,9 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | |||
2156 | return tsf; | 2157 | return tsf; |
2157 | } | 2158 | } |
2158 | 2159 | ||
2159 | static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 2160 | static void ath9k_set_tsf(struct ieee80211_hw *hw, |
2161 | struct ieee80211_vif *vif, | ||
2162 | u64 tsf) | ||
2160 | { | 2163 | { |
2161 | struct ath_softc *sc = hw->priv; | 2164 | struct ath_softc *sc = hw->priv; |
2162 | 2165 | ||
@@ -2167,7 +2170,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | |||
2167 | mutex_unlock(&sc->mutex); | 2170 | mutex_unlock(&sc->mutex); |
2168 | } | 2171 | } |
2169 | 2172 | ||
2170 | static void ath9k_reset_tsf(struct ieee80211_hw *hw) | 2173 | static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
2171 | { | 2174 | { |
2172 | struct ath_softc *sc = hw->priv; | 2175 | struct ath_softc *sc = hw->priv; |
2173 | 2176 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index bcc0b222ec18..49843500fe7c 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -205,14 +205,22 @@ static void ath_rx_remove_buffer(struct ath_softc *sc, | |||
205 | 205 | ||
206 | static void ath_rx_edma_cleanup(struct ath_softc *sc) | 206 | static void ath_rx_edma_cleanup(struct ath_softc *sc) |
207 | { | 207 | { |
208 | struct ath_hw *ah = sc->sc_ah; | ||
209 | struct ath_common *common = ath9k_hw_common(ah); | ||
208 | struct ath_buf *bf; | 210 | struct ath_buf *bf; |
209 | 211 | ||
210 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); | 212 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); |
211 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); | 213 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); |
212 | 214 | ||
213 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { | 215 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { |
214 | if (bf->bf_mpdu) | 216 | if (bf->bf_mpdu) { |
217 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | ||
218 | common->rx_bufsize, | ||
219 | DMA_BIDIRECTIONAL); | ||
215 | dev_kfree_skb_any(bf->bf_mpdu); | 220 | dev_kfree_skb_any(bf->bf_mpdu); |
221 | bf->bf_buf_addr = 0; | ||
222 | bf->bf_mpdu = NULL; | ||
223 | } | ||
216 | } | 224 | } |
217 | 225 | ||
218 | INIT_LIST_HEAD(&sc->rx.rxbuf); | 226 | INIT_LIST_HEAD(&sc->rx.rxbuf); |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 0846654b57ef..b76c49d9c503 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -803,10 +803,6 @@ | |||
803 | #define AR_SREV_5416(_ah) \ | 803 | #define AR_SREV_5416(_ah) \ |
804 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ | 804 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
805 | ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) | 805 | ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) |
806 | #define AR_SREV_5416_20_OR_LATER(_ah) \ | ||
807 | (((AR_SREV_5416(_ah)) && \ | ||
808 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \ | ||
809 | ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) | ||
810 | #define AR_SREV_5416_22_OR_LATER(_ah) \ | 806 | #define AR_SREV_5416_22_OR_LATER(_ah) \ |
811 | (((AR_SREV_5416(_ah)) && \ | 807 | (((AR_SREV_5416(_ah)) && \ |
812 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ | 808 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c6aefad3728..fa3dcfdf7174 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -262,6 +262,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | |||
262 | struct sk_buff *skb) | 262 | struct sk_buff *skb) |
263 | { | 263 | { |
264 | struct ath_frame_info *fi = get_frame_info(skb); | 264 | struct ath_frame_info *fi = get_frame_info(skb); |
265 | struct ath_buf *bf = fi->bf; | ||
265 | struct ieee80211_hdr *hdr; | 266 | struct ieee80211_hdr *hdr; |
266 | 267 | ||
267 | TX_STAT_INC(txq->axq_qnum, a_retries); | 268 | TX_STAT_INC(txq->axq_qnum, a_retries); |
@@ -270,6 +271,8 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | |||
270 | 271 | ||
271 | hdr = (struct ieee80211_hdr *)skb->data; | 272 | hdr = (struct ieee80211_hdr *)skb->data; |
272 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); | 273 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); |
274 | dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, | ||
275 | sizeof(*hdr), DMA_TO_DEVICE); | ||
273 | } | 276 | } |
274 | 277 | ||
275 | static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) | 278 | static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) |
@@ -1017,8 +1020,6 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1017 | while (bf) { | 1020 | while (bf) { |
1018 | struct sk_buff *skb = bf->bf_mpdu; | 1021 | struct sk_buff *skb = bf->bf_mpdu; |
1019 | struct ath_frame_info *fi = get_frame_info(skb); | 1022 | struct ath_frame_info *fi = get_frame_info(skb); |
1020 | struct ieee80211_hdr *hdr; | ||
1021 | int padpos, padsize; | ||
1022 | 1023 | ||
1023 | info.type = get_hw_packet_type(skb); | 1024 | info.type = get_hw_packet_type(skb); |
1024 | if (bf->bf_next) | 1025 | if (bf->bf_next) |
@@ -1026,20 +1027,8 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1026 | else | 1027 | else |
1027 | info.link = 0; | 1028 | info.link = 0; |
1028 | 1029 | ||
1029 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 1030 | info.buf_addr[0] = bf->bf_buf_addr; |
1030 | hdr = (struct ieee80211_hdr *)skb->data; | 1031 | info.buf_len[0] = skb->len; |
1031 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
1032 | padsize = padpos & 3; | ||
1033 | |||
1034 | info.buf_addr[0] = bf->bf_buf_addr; | ||
1035 | info.buf_len[0] = padpos + padsize; | ||
1036 | info.buf_addr[1] = info.buf_addr[0] + padpos; | ||
1037 | info.buf_len[1] = skb->len - padpos; | ||
1038 | } else { | ||
1039 | info.buf_addr[0] = bf->bf_buf_addr; | ||
1040 | info.buf_len[0] = skb->len; | ||
1041 | } | ||
1042 | |||
1043 | info.pkt_len = fi->framelen; | 1032 | info.pkt_len = fi->framelen; |
1044 | info.keyix = fi->keyix; | 1033 | info.keyix = fi->keyix; |
1045 | info.keytype = fi->keytype; | 1034 | info.keytype = fi->keytype; |
@@ -1892,17 +1881,16 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1892 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | 1881 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); |
1893 | } | 1882 | } |
1894 | 1883 | ||
1895 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { | 1884 | /* Add the padding after the header if this is not already done */ |
1896 | /* Add the padding after the header if this is not already done */ | 1885 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1897 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 1886 | padsize = padpos & 3; |
1898 | padsize = padpos & 3; | 1887 | if (padsize && skb->len > padpos) { |
1899 | if (padsize && skb->len > padpos) { | 1888 | if (skb_headroom(skb) < padsize) |
1900 | if (skb_headroom(skb) < padsize) | 1889 | return -ENOMEM; |
1901 | return -ENOMEM; | ||
1902 | 1890 | ||
1903 | skb_push(skb, padsize); | 1891 | skb_push(skb, padsize); |
1904 | memmove(skb->data, skb->data + padsize, padpos); | 1892 | memmove(skb->data, skb->data + padsize, padpos); |
1905 | } | 1893 | hdr = (struct ieee80211_hdr *) skb->data; |
1906 | } | 1894 | } |
1907 | 1895 | ||
1908 | if ((vif && vif->type != NL80211_IFTYPE_AP && | 1896 | if ((vif && vif->type != NL80211_IFTYPE_AP && |
@@ -1952,17 +1940,15 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1952 | /* Frame was ACKed */ | 1940 | /* Frame was ACKed */ |
1953 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 1941 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
1954 | 1942 | ||
1955 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { | 1943 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1956 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 1944 | padsize = padpos & 3; |
1957 | padsize = padpos & 3; | 1945 | if (padsize && skb->len>padpos+padsize) { |
1958 | if (padsize && skb->len>padpos+padsize) { | 1946 | /* |
1959 | /* | 1947 | * Remove MAC header padding before giving the frame back to |
1960 | * Remove MAC header padding before giving the frame back to | 1948 | * mac80211. |
1961 | * mac80211. | 1949 | */ |
1962 | */ | 1950 | memmove(skb->data + padsize, skb->data, padpos); |
1963 | memmove(skb->data + padsize, skb->data, padpos); | 1951 | skb_pull(skb, padsize); |
1964 | skb_pull(skb, padsize); | ||
1965 | } | ||
1966 | } | 1952 | } |
1967 | 1953 | ||
1968 | if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { | 1954 | if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index af351ecd87c4..8b780d6d470f 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -1078,7 +1078,8 @@ out: | |||
1078 | mutex_unlock(&ar->mutex); | 1078 | mutex_unlock(&ar->mutex); |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw) | 1081 | static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw, |
1082 | struct ieee80211_vif *vif) | ||
1082 | { | 1083 | { |
1083 | struct ar9170 *ar = hw->priv; | 1084 | struct ar9170 *ar = hw->priv; |
1084 | struct carl9170_tsf_rsp tsf; | 1085 | struct carl9170_tsf_rsp tsf; |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f8615cdf1075..447a2307c9d9 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -107,6 +107,40 @@ | |||
107 | #define B43_MMIO_RADIO_HWENABLED_LO 0x49A | 107 | #define B43_MMIO_RADIO_HWENABLED_LO 0x49A |
108 | #define B43_MMIO_GPIO_CONTROL 0x49C | 108 | #define B43_MMIO_GPIO_CONTROL 0x49C |
109 | #define B43_MMIO_GPIO_MASK 0x49E | 109 | #define B43_MMIO_GPIO_MASK 0x49E |
110 | #define B43_MMIO_TXE0_CTL 0x500 | ||
111 | #define B43_MMIO_TXE0_AUX 0x502 | ||
112 | #define B43_MMIO_TXE0_TS_LOC 0x504 | ||
113 | #define B43_MMIO_TXE0_TIME_OUT 0x506 | ||
114 | #define B43_MMIO_TXE0_WM_0 0x508 | ||
115 | #define B43_MMIO_TXE0_WM_1 0x50A | ||
116 | #define B43_MMIO_TXE0_PHYCTL 0x50C | ||
117 | #define B43_MMIO_TXE0_STATUS 0x50E | ||
118 | #define B43_MMIO_TXE0_MMPLCP0 0x510 | ||
119 | #define B43_MMIO_TXE0_MMPLCP1 0x512 | ||
120 | #define B43_MMIO_TXE0_PHYCTL1 0x514 | ||
121 | #define B43_MMIO_XMTFIFODEF 0x520 | ||
122 | #define B43_MMIO_XMTFIFO_FRAME_CNT 0x522 /* core rev>= 16 only */ | ||
123 | #define B43_MMIO_XMTFIFO_BYTE_CNT 0x524 /* core rev>= 16 only */ | ||
124 | #define B43_MMIO_XMTFIFO_HEAD 0x526 /* core rev>= 16 only */ | ||
125 | #define B43_MMIO_XMTFIFO_RD_PTR 0x528 /* core rev>= 16 only */ | ||
126 | #define B43_MMIO_XMTFIFO_WR_PTR 0x52A /* core rev>= 16 only */ | ||
127 | #define B43_MMIO_XMTFIFODEF1 0x52C /* core rev>= 16 only */ | ||
128 | #define B43_MMIO_XMTFIFOCMD 0x540 | ||
129 | #define B43_MMIO_XMTFIFOFLUSH 0x542 | ||
130 | #define B43_MMIO_XMTFIFOTHRESH 0x544 | ||
131 | #define B43_MMIO_XMTFIFORDY 0x546 | ||
132 | #define B43_MMIO_XMTFIFOPRIRDY 0x548 | ||
133 | #define B43_MMIO_XMTFIFORQPRI 0x54A | ||
134 | #define B43_MMIO_XMTTPLATETXPTR 0x54C | ||
135 | #define B43_MMIO_XMTTPLATEPTR 0x550 | ||
136 | #define B43_MMIO_SMPL_CLCT_STRPTR 0x552 /* core rev>= 22 only */ | ||
137 | #define B43_MMIO_SMPL_CLCT_STPPTR 0x554 /* core rev>= 22 only */ | ||
138 | #define B43_MMIO_SMPL_CLCT_CURPTR 0x556 /* core rev>= 22 only */ | ||
139 | #define B43_MMIO_XMTTPLATEDATALO 0x560 | ||
140 | #define B43_MMIO_XMTTPLATEDATAHI 0x562 | ||
141 | #define B43_MMIO_XMTSEL 0x568 | ||
142 | #define B43_MMIO_XMTTXCNT 0x56A | ||
143 | #define B43_MMIO_XMTTXSHMADDR 0x56C | ||
110 | #define B43_MMIO_TSF_CFP_START_LOW 0x604 | 144 | #define B43_MMIO_TSF_CFP_START_LOW 0x604 |
111 | #define B43_MMIO_TSF_CFP_START_HIGH 0x606 | 145 | #define B43_MMIO_TSF_CFP_START_HIGH 0x606 |
112 | #define B43_MMIO_TSF_CFP_PRETBTT 0x612 | 146 | #define B43_MMIO_TSF_CFP_PRETBTT 0x612 |
@@ -118,12 +152,16 @@ | |||
118 | #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ | 152 | #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ |
119 | #define B43_MMIO_RNG 0x65A | 153 | #define B43_MMIO_RNG 0x65A |
120 | #define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */ | 154 | #define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */ |
121 | #define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ | 155 | #define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ |
156 | #define B43_MMIO_IFSSTAT 0x690 | ||
157 | #define B43_MMIO_IFSMEDBUSYCTL 0x692 | ||
158 | #define B43_MMIO_IFTXDUR 0x694 | ||
122 | #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 | 159 | #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 |
123 | #define B43_MMIO_POWERUP_DELAY 0x6A8 | 160 | #define B43_MMIO_POWERUP_DELAY 0x6A8 |
124 | #define B43_MMIO_BTCOEX_CTL 0x6B4 /* Bluetooth Coexistence Control */ | 161 | #define B43_MMIO_BTCOEX_CTL 0x6B4 /* Bluetooth Coexistence Control */ |
125 | #define B43_MMIO_BTCOEX_STAT 0x6B6 /* Bluetooth Coexistence Status */ | 162 | #define B43_MMIO_BTCOEX_STAT 0x6B6 /* Bluetooth Coexistence Status */ |
126 | #define B43_MMIO_BTCOEX_TXCTL 0x6B8 /* Bluetooth Coexistence Transmit Control */ | 163 | #define B43_MMIO_BTCOEX_TXCTL 0x6B8 /* Bluetooth Coexistence Transmit Control */ |
164 | #define B43_MMIO_WEPCTL 0x7C0 | ||
127 | 165 | ||
128 | /* SPROM boardflags_lo values */ | 166 | /* SPROM boardflags_lo values */ |
129 | #define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ | 167 | #define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 56fa3a3648c4..43400fb62e1c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -729,52 +729,59 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) | |||
729 | for (i = 0; i < 5; i++) | 729 | for (i = 0; i < 5; i++) |
730 | b43_ram_write(dev, i * 4, buffer[i]); | 730 | b43_ram_write(dev, i * 4, buffer[i]); |
731 | 731 | ||
732 | b43_write16(dev, 0x0568, 0x0000); | 732 | b43_write16(dev, B43_MMIO_XMTSEL, 0x0000); |
733 | |||
733 | if (dev->dev->core_rev < 11) | 734 | if (dev->dev->core_rev < 11) |
734 | b43_write16(dev, 0x07C0, 0x0000); | 735 | b43_write16(dev, B43_MMIO_WEPCTL, 0x0000); |
735 | else | 736 | else |
736 | b43_write16(dev, 0x07C0, 0x0100); | 737 | b43_write16(dev, B43_MMIO_WEPCTL, 0x0100); |
738 | |||
737 | value = (ofdm ? 0x41 : 0x40); | 739 | value = (ofdm ? 0x41 : 0x40); |
738 | b43_write16(dev, 0x050C, value); | 740 | b43_write16(dev, B43_MMIO_TXE0_PHYCTL, value); |
739 | if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP)) | 741 | if (phy->type == B43_PHYTYPE_N || phy->type == B43_PHYTYPE_LP || |
740 | b43_write16(dev, 0x0514, 0x1A02); | 742 | phy->type == B43_PHYTYPE_LCN) |
741 | b43_write16(dev, 0x0508, 0x0000); | 743 | b43_write16(dev, B43_MMIO_TXE0_PHYCTL1, 0x1A02); |
742 | b43_write16(dev, 0x050A, 0x0000); | 744 | |
743 | b43_write16(dev, 0x054C, 0x0000); | 745 | b43_write16(dev, B43_MMIO_TXE0_WM_0, 0x0000); |
744 | b43_write16(dev, 0x056A, 0x0014); | 746 | b43_write16(dev, B43_MMIO_TXE0_WM_1, 0x0000); |
745 | b43_write16(dev, 0x0568, 0x0826); | 747 | |
746 | b43_write16(dev, 0x0500, 0x0000); | 748 | b43_write16(dev, B43_MMIO_XMTTPLATETXPTR, 0x0000); |
747 | if (!pa_on && (phy->type == B43_PHYTYPE_N)) { | 749 | b43_write16(dev, B43_MMIO_XMTTXCNT, 0x0014); |
748 | //SPEC TODO | 750 | b43_write16(dev, B43_MMIO_XMTSEL, 0x0826); |
749 | } | 751 | b43_write16(dev, B43_MMIO_TXE0_CTL, 0x0000); |
752 | |||
753 | if (!pa_on && phy->type == B43_PHYTYPE_N) | ||
754 | ; /*b43_nphy_pa_override(dev, false) */ | ||
750 | 755 | ||
751 | switch (phy->type) { | 756 | switch (phy->type) { |
752 | case B43_PHYTYPE_N: | 757 | case B43_PHYTYPE_N: |
753 | b43_write16(dev, 0x0502, 0x00D0); | 758 | case B43_PHYTYPE_LCN: |
759 | b43_write16(dev, B43_MMIO_TXE0_AUX, 0x00D0); | ||
754 | break; | 760 | break; |
755 | case B43_PHYTYPE_LP: | 761 | case B43_PHYTYPE_LP: |
756 | b43_write16(dev, 0x0502, 0x0050); | 762 | b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0050); |
757 | break; | 763 | break; |
758 | default: | 764 | default: |
759 | b43_write16(dev, 0x0502, 0x0030); | 765 | b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0030); |
760 | } | 766 | } |
767 | b43_read16(dev, B43_MMIO_TXE0_AUX); | ||
761 | 768 | ||
762 | if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) | 769 | if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) |
763 | b43_radio_write16(dev, 0x0051, 0x0017); | 770 | b43_radio_write16(dev, 0x0051, 0x0017); |
764 | for (i = 0x00; i < max_loop; i++) { | 771 | for (i = 0x00; i < max_loop; i++) { |
765 | value = b43_read16(dev, 0x050E); | 772 | value = b43_read16(dev, B43_MMIO_TXE0_STATUS); |
766 | if (value & 0x0080) | 773 | if (value & 0x0080) |
767 | break; | 774 | break; |
768 | udelay(10); | 775 | udelay(10); |
769 | } | 776 | } |
770 | for (i = 0x00; i < 0x0A; i++) { | 777 | for (i = 0x00; i < 0x0A; i++) { |
771 | value = b43_read16(dev, 0x050E); | 778 | value = b43_read16(dev, B43_MMIO_TXE0_STATUS); |
772 | if (value & 0x0400) | 779 | if (value & 0x0400) |
773 | break; | 780 | break; |
774 | udelay(10); | 781 | udelay(10); |
775 | } | 782 | } |
776 | for (i = 0x00; i < 0x19; i++) { | 783 | for (i = 0x00; i < 0x19; i++) { |
777 | value = b43_read16(dev, 0x0690); | 784 | value = b43_read16(dev, B43_MMIO_IFSSTAT); |
778 | if (!(value & 0x0100)) | 785 | if (!(value & 0x0100)) |
779 | break; | 786 | break; |
780 | udelay(10); | 787 | udelay(10); |
@@ -3599,7 +3606,7 @@ static int b43_op_get_stats(struct ieee80211_hw *hw, | |||
3599 | return 0; | 3606 | return 0; |
3600 | } | 3607 | } |
3601 | 3608 | ||
3602 | static u64 b43_op_get_tsf(struct ieee80211_hw *hw) | 3609 | static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
3603 | { | 3610 | { |
3604 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3611 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3605 | struct b43_wldev *dev; | 3612 | struct b43_wldev *dev; |
@@ -3618,7 +3625,8 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw) | |||
3618 | return tsf; | 3625 | return tsf; |
3619 | } | 3626 | } |
3620 | 3627 | ||
3621 | static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 3628 | static void b43_op_set_tsf(struct ieee80211_hw *hw, |
3629 | struct ieee80211_vif *vif, u64 tsf) | ||
3622 | { | 3630 | { |
3623 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3631 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3624 | struct b43_wldev *dev; | 3632 | struct b43_wldev *dev; |
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index d1dfeec7bc28..a13e28ef6246 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c | |||
@@ -20,6 +20,14 @@ | |||
20 | the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, | 20 | the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, |
21 | Boston, MA 02110-1301, USA. | 21 | Boston, MA 02110-1301, USA. |
22 | 22 | ||
23 | This file incorporates work covered by the following copyright and | ||
24 | permission notice: | ||
25 | |||
26 | Copyright (c) 2010 Broadcom Corporation | ||
27 | |||
28 | Permission to use, copy, modify, and/or distribute this software for any | ||
29 | purpose with or without fee is hereby granted, provided that the above | ||
30 | copyright notice and this permission notice appear in all copies. | ||
23 | */ | 31 | */ |
24 | 32 | ||
25 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
@@ -29,6 +37,56 @@ | |||
29 | #include "tables_phy_lcn.h" | 37 | #include "tables_phy_lcn.h" |
30 | #include "main.h" | 38 | #include "main.h" |
31 | 39 | ||
40 | struct lcn_tx_gains { | ||
41 | u16 gm_gain; | ||
42 | u16 pga_gain; | ||
43 | u16 pad_gain; | ||
44 | u16 dac_gain; | ||
45 | }; | ||
46 | |||
47 | struct lcn_tx_iir_filter { | ||
48 | u8 type; | ||
49 | u16 values[16]; | ||
50 | }; | ||
51 | |||
52 | enum lcn_sense_type { | ||
53 | B43_SENSE_TEMP, | ||
54 | B43_SENSE_VBAT, | ||
55 | }; | ||
56 | |||
57 | /* In theory it's PHY common function, move if needed */ | ||
58 | /* brcms_b_switch_macfreq */ | ||
59 | static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode) | ||
60 | { | ||
61 | if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) { | ||
62 | switch (spurmode) { | ||
63 | case 2: /* 126 Mhz */ | ||
64 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082); | ||
65 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
66 | break; | ||
67 | case 1: /* 123 Mhz */ | ||
68 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341); | ||
69 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
70 | break; | ||
71 | default: /* 120 Mhz */ | ||
72 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889); | ||
73 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
74 | break; | ||
75 | } | ||
76 | } else if (dev->phy.type == B43_PHYTYPE_LCN) { | ||
77 | switch (spurmode) { | ||
78 | case 1: /* 82 Mhz */ | ||
79 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0); | ||
80 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
81 | break; | ||
82 | default: /* 80 Mhz */ | ||
83 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD); | ||
84 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
32 | /************************************************** | 90 | /************************************************** |
33 | * Radio 2064. | 91 | * Radio 2064. |
34 | **************************************************/ | 92 | **************************************************/ |
@@ -152,6 +210,29 @@ static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev) | |||
152 | b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1); | 210 | b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1); |
153 | } | 211 | } |
154 | 212 | ||
213 | /* wlc_lcnphy_get_pa_gain */ | ||
214 | static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev) | ||
215 | { | ||
216 | return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8; | ||
217 | } | ||
218 | |||
219 | /* wlc_lcnphy_set_dac_gain */ | ||
220 | static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain) | ||
221 | { | ||
222 | u16 dac_ctrl; | ||
223 | |||
224 | dac_ctrl = b43_phy_read(dev, 0x439); | ||
225 | dac_ctrl = dac_ctrl & 0xc7f; | ||
226 | dac_ctrl = dac_ctrl | (dac_gain << 7); | ||
227 | b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl); | ||
228 | } | ||
229 | |||
230 | /* wlc_lcnphy_set_bbmult */ | ||
231 | static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0) | ||
232 | { | ||
233 | b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8); | ||
234 | } | ||
235 | |||
155 | /* wlc_lcnphy_clear_tx_power_offsets */ | 236 | /* wlc_lcnphy_clear_tx_power_offsets */ |
156 | static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev) | 237 | static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev) |
157 | { | 238 | { |
@@ -231,18 +312,40 @@ static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev) | |||
231 | 312 | ||
232 | b43_phy_write(dev, 0x7d6, 0x0902); | 313 | b43_phy_write(dev, 0x7d6, 0x0902); |
233 | 314 | ||
234 | /* TODO: more ops */ | 315 | b43_phy_maskset(dev, 0x429, ~0xf, 0x9); |
316 | b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4); | ||
235 | 317 | ||
236 | if (dev->phy.rev == 1) { | 318 | if (dev->phy.rev == 1) { |
237 | /* TODO: more ops */ | 319 | b43_phy_maskset(dev, 0x423, ~0xff, 0x46); |
320 | b43_phy_maskset(dev, 0x411, ~0xff, 1); | ||
321 | b43_phy_set(dev, 0x434, 0xff); /* FIXME: update to wl */ | ||
322 | |||
323 | /* TODO: wl operates on PHY 0x416, brcmsmac is outdated here */ | ||
324 | |||
325 | b43_phy_maskset(dev, 0x656, ~0xf, 2); | ||
326 | b43_phy_set(dev, 0x44d, 4); | ||
327 | |||
328 | b43_radio_set(dev, 0x0f7, 0x4); | ||
329 | b43_radio_mask(dev, 0x0f1, ~0x3); | ||
330 | b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90); | ||
331 | b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2); | ||
332 | b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0); | ||
333 | |||
334 | b43_radio_set(dev, 0x11f, 0x2); | ||
238 | 335 | ||
239 | b43_phy_lcn_clear_tx_power_offsets(dev); | 336 | b43_phy_lcn_clear_tx_power_offsets(dev); |
337 | |||
338 | /* TODO: something more? */ | ||
240 | } | 339 | } |
241 | } | 340 | } |
242 | 341 | ||
243 | /* wlc_lcnphy_vbat_temp_sense_setup */ | 342 | /* wlc_lcnphy_vbat_temp_sense_setup */ |
244 | static void b43_phy_lcn_sense_setup(struct b43_wldev *dev) | 343 | static void b43_phy_lcn_sense_setup(struct b43_wldev *dev, |
344 | enum lcn_sense_type sense_type) | ||
245 | { | 345 | { |
346 | u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain; | ||
347 | u16 auxpga_vmid; | ||
348 | u8 tx_pwr_idx; | ||
246 | u8 i; | 349 | u8 i; |
247 | 350 | ||
248 | u16 save_radio_regs[6][2] = { | 351 | u16 save_radio_regs[6][2] = { |
@@ -257,35 +360,312 @@ static void b43_phy_lcn_sense_setup(struct b43_wldev *dev) | |||
257 | }; | 360 | }; |
258 | u16 save_radio_4a4; | 361 | u16 save_radio_4a4; |
259 | 362 | ||
363 | msleep(1); | ||
364 | |||
365 | /* Save */ | ||
260 | for (i = 0; i < 6; i++) | 366 | for (i = 0; i < 6; i++) |
261 | save_radio_regs[i][1] = b43_radio_read(dev, | 367 | save_radio_regs[i][1] = b43_radio_read(dev, |
262 | save_radio_regs[i][0]); | 368 | save_radio_regs[i][0]); |
263 | for (i = 0; i < 14; i++) | 369 | for (i = 0; i < 14; i++) |
264 | save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]); | 370 | save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]); |
371 | b43_mac_suspend(dev); | ||
265 | save_radio_4a4 = b43_radio_read(dev, 0x4a4); | 372 | save_radio_4a4 = b43_radio_read(dev, 0x4a4); |
373 | /* wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); */ | ||
374 | tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx; | ||
375 | |||
376 | /* Setup */ | ||
377 | /* TODO: wlc_lcnphy_set_tx_pwr_by_index(pi, 127); */ | ||
378 | b43_radio_set(dev, 0x007, 0x1); | ||
379 | b43_radio_set(dev, 0x0ff, 0x10); | ||
380 | b43_radio_set(dev, 0x11f, 0x4); | ||
381 | |||
382 | b43_phy_mask(dev, 0x503, ~0x1); | ||
383 | b43_phy_mask(dev, 0x503, ~0x4); | ||
384 | b43_phy_mask(dev, 0x4a4, ~0x4000); | ||
385 | b43_phy_mask(dev, 0x4a4, (u16) ~0x8000); | ||
386 | b43_phy_mask(dev, 0x4d0, ~0x20); | ||
387 | b43_phy_set(dev, 0x4a5, 0xff); | ||
388 | b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000); | ||
389 | b43_phy_mask(dev, 0x4a5, ~0x700); | ||
390 | b43_phy_maskset(dev, 0x40d, ~0xff, 64); | ||
391 | b43_phy_maskset(dev, 0x40d, ~0x700, 0x600); | ||
392 | b43_phy_maskset(dev, 0x4a2, ~0xff, 64); | ||
393 | b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600); | ||
394 | b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20); | ||
395 | b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300); | ||
396 | b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000); | ||
397 | b43_phy_mask(dev, 0x4da, ~0x1000); | ||
398 | b43_phy_set(dev, 0x4da, 0x2000); | ||
399 | b43_phy_set(dev, 0x4a6, 0x8000); | ||
400 | |||
401 | b43_radio_write(dev, 0x025, 0xc); | ||
402 | b43_radio_set(dev, 0x005, 0x8); | ||
403 | b43_phy_set(dev, 0x938, 0x4); | ||
404 | b43_phy_set(dev, 0x939, 0x4); | ||
405 | b43_phy_set(dev, 0x4a4, 0x1000); | ||
406 | |||
407 | /* FIXME: don't hardcode */ | ||
408 | b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640); | ||
409 | |||
410 | switch (sense_type) { | ||
411 | case B43_SENSE_TEMP: | ||
412 | b43_phy_set(dev, 0x4d7, 0x8); | ||
413 | b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000); | ||
414 | auxpga_vmidcourse = 8; | ||
415 | auxpga_vmidfine = 0x4; | ||
416 | auxpga_gain = 2; | ||
417 | b43_radio_set(dev, 0x082, 0x20); | ||
418 | break; | ||
419 | case B43_SENSE_VBAT: | ||
420 | b43_phy_set(dev, 0x4d7, 0x8); | ||
421 | b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000); | ||
422 | auxpga_vmidcourse = 7; | ||
423 | auxpga_vmidfine = 0xa; | ||
424 | auxpga_gain = 2; | ||
425 | break; | ||
426 | } | ||
427 | auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine); | ||
428 | |||
429 | b43_phy_set(dev, 0x4d8, 0x1); | ||
430 | b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2); | ||
431 | b43_phy_set(dev, 0x4d8, 0x2); | ||
432 | b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12); | ||
433 | b43_phy_set(dev, 0x4d0, 0x20); | ||
434 | b43_radio_write(dev, 0x112, 0x6); | ||
266 | 435 | ||
267 | /* TODO: config sth */ | 436 | b43_dummy_transmission(dev, true, false); |
437 | /* Wait if not done */ | ||
438 | if (!(b43_phy_read(dev, 0x476) & 0x8000)) | ||
439 | udelay(10); | ||
268 | 440 | ||
441 | /* Restore */ | ||
269 | for (i = 0; i < 6; i++) | 442 | for (i = 0; i < 6; i++) |
270 | b43_radio_write(dev, save_radio_regs[i][0], | 443 | b43_radio_write(dev, save_radio_regs[i][0], |
271 | save_radio_regs[i][1]); | 444 | save_radio_regs[i][1]); |
272 | for (i = 0; i < 14; i++) | 445 | for (i = 0; i < 14; i++) |
273 | b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]); | 446 | b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]); |
447 | /* TODO: wlc_lcnphy_set_tx_pwr_by_index(tx_pwr_idx) */ | ||
274 | b43_radio_write(dev, 0x4a4, save_radio_4a4); | 448 | b43_radio_write(dev, 0x4a4, save_radio_4a4); |
449 | |||
450 | b43_mac_enable(dev); | ||
451 | |||
452 | msleep(1); | ||
453 | } | ||
454 | |||
455 | static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev, | ||
456 | u8 filter_type) | ||
457 | { | ||
458 | int i, j; | ||
459 | u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920, | ||
460 | 0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930, | ||
461 | 0x931, 0x932 }; | ||
462 | /* Table is from brcmsmac, values for type 25 were outdated, probably | ||
463 | * others need updating too */ | ||
464 | struct lcn_tx_iir_filter tx_iir_filters_cck[] = { | ||
465 | { 0, { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, | ||
466 | 1582, 64, 128, 64 } }, | ||
467 | { 1, { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, | ||
468 | 1863, 93, 167, 93 } }, | ||
469 | { 2, { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, | ||
470 | 778, 1582, 64, 128, 64 } }, | ||
471 | { 3, { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, | ||
472 | 754, 1760, 170, 340, 170 } }, | ||
473 | { 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, | ||
474 | 767, 1760, 256, 185, 256 } }, | ||
475 | { 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, | ||
476 | 767, 1760, 256, 273, 256 } }, | ||
477 | { 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, | ||
478 | 767, 1760, 256, 352, 256 } }, | ||
479 | { 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, | ||
480 | 767, 1760, 128, 233, 128 } }, | ||
481 | { 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, | ||
482 | 1760, 256, 1881, 256 } }, | ||
483 | { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, | ||
484 | 1760, 262, 1878, 262 } }, | ||
485 | /* brcmsmac version { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, | ||
486 | * 256, 471, 256, 765, 1760, 256, 1881, 256 } }, */ | ||
487 | { 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, | ||
488 | 1864, 128, 384, 288 } }, | ||
489 | { 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, | ||
490 | 613, 1864, 128, 384, 288 } }, | ||
491 | { 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, | ||
492 | 754, 1760, 170, 340, 170 } }, | ||
493 | }; | ||
494 | |||
495 | for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) { | ||
496 | if (tx_iir_filters_cck[i].type == filter_type) { | ||
497 | for (j = 0; j < 16; j++) | ||
498 | b43_phy_write(dev, phy_regs[j], | ||
499 | tx_iir_filters_cck[i].values[j]); | ||
500 | return true; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | return false; | ||
505 | } | ||
506 | |||
507 | static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev, | ||
508 | u8 filter_type) | ||
509 | { | ||
510 | int i, j; | ||
511 | u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902, | ||
512 | 0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c, | ||
513 | 0x90d, 0x90e }; | ||
514 | struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = { | ||
515 | { 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, | ||
516 | 0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } }, | ||
517 | { 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750, | ||
518 | 0xFE2B, 212, 0xFFCE, 212 } }, | ||
519 | { 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748, | ||
520 | 0xFEF2, 128, 0xFFE2, 128 } }, | ||
521 | }; | ||
522 | |||
523 | for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) { | ||
524 | if (tx_iir_filters_ofdm[i].type == filter_type) { | ||
525 | for (j = 0; j < 16; j++) | ||
526 | b43_phy_write(dev, phy_regs[j], | ||
527 | tx_iir_filters_ofdm[i].values[j]); | ||
528 | return true; | ||
529 | } | ||
530 | } | ||
531 | |||
532 | return false; | ||
533 | } | ||
534 | |||
535 | /* wlc_lcnphy_set_tx_gain_override */ | ||
536 | static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable) | ||
537 | { | ||
538 | b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7); | ||
539 | b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14); | ||
540 | b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6); | ||
541 | } | ||
542 | |||
543 | /* wlc_lcnphy_set_tx_gain */ | ||
544 | static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev, | ||
545 | struct lcn_tx_gains *target_gains) | ||
546 | { | ||
547 | u16 pa_gain = b43_phy_lcn_get_pa_gain(dev); | ||
548 | |||
549 | b43_phy_write(dev, 0x4b5, | ||
550 | (target_gains->gm_gain | (target_gains->pga_gain << 8))); | ||
551 | b43_phy_maskset(dev, 0x4fb, ~0x7fff, | ||
552 | (target_gains->pad_gain | (pa_gain << 8))); | ||
553 | b43_phy_write(dev, 0x4fc, | ||
554 | (target_gains->gm_gain | (target_gains->pga_gain << 8))); | ||
555 | b43_phy_maskset(dev, 0x4fd, ~0x7fff, | ||
556 | (target_gains->pad_gain | (pa_gain << 8))); | ||
557 | |||
558 | b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain); | ||
559 | b43_phy_lcn_set_tx_gain_override(dev, true); | ||
560 | } | ||
561 | |||
562 | /* wlc_lcnphy_tx_pwr_ctrl_init */ | ||
563 | static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev) | ||
564 | { | ||
565 | struct lcn_tx_gains tx_gains; | ||
566 | u8 bbmult; | ||
567 | |||
568 | b43_mac_suspend(dev); | ||
569 | |||
570 | if (!dev->phy.lcn->hw_pwr_ctl_capable) { | ||
571 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
572 | tx_gains.gm_gain = 4; | ||
573 | tx_gains.pga_gain = 12; | ||
574 | tx_gains.pad_gain = 12; | ||
575 | tx_gains.dac_gain = 0; | ||
576 | bbmult = 150; | ||
577 | } else { | ||
578 | tx_gains.gm_gain = 7; | ||
579 | tx_gains.pga_gain = 15; | ||
580 | tx_gains.pad_gain = 14; | ||
581 | tx_gains.dac_gain = 0; | ||
582 | bbmult = 150; | ||
583 | } | ||
584 | b43_phy_lcn_set_tx_gain(dev, &tx_gains); | ||
585 | b43_phy_lcn_set_bbmult(dev, bbmult); | ||
586 | b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP); | ||
587 | } else { | ||
588 | b43err(dev->wl, "TX power control not supported for this HW\n"); | ||
589 | } | ||
590 | |||
591 | b43_mac_enable(dev); | ||
592 | } | ||
593 | |||
594 | /* wlc_lcnphy_txrx_spur_avoidance_mode */ | ||
595 | static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev, | ||
596 | bool enable) | ||
597 | { | ||
598 | if (enable) { | ||
599 | b43_phy_write(dev, 0x942, 0x7); | ||
600 | b43_phy_write(dev, 0x93b, ((1 << 13) + 23)); | ||
601 | b43_phy_write(dev, 0x93c, ((1 << 13) + 1989)); | ||
602 | |||
603 | b43_phy_write(dev, 0x44a, 0x084); | ||
604 | b43_phy_write(dev, 0x44a, 0x080); | ||
605 | b43_phy_write(dev, 0x6d3, 0x2222); | ||
606 | b43_phy_write(dev, 0x6d3, 0x2220); | ||
607 | } else { | ||
608 | b43_phy_write(dev, 0x942, 0x0); | ||
609 | b43_phy_write(dev, 0x93b, ((0 << 13) + 23)); | ||
610 | b43_phy_write(dev, 0x93c, ((0 << 13) + 1989)); | ||
611 | } | ||
612 | b43_phy_switch_macfreq(dev, enable); | ||
275 | } | 613 | } |
276 | 614 | ||
277 | /************************************************** | 615 | /************************************************** |
278 | * Channel switching ops. | 616 | * Channel switching ops. |
279 | **************************************************/ | 617 | **************************************************/ |
280 | 618 | ||
619 | /* wlc_lcnphy_set_chanspec_tweaks */ | ||
620 | static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel) | ||
621 | { | ||
622 | struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc; | ||
623 | |||
624 | b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100); | ||
625 | |||
626 | if (channel == 1 || channel == 2 || channel == 3 || channel == 4 || | ||
627 | channel == 9 || channel == 10 || channel == 11 || channel == 12) { | ||
628 | bcma_chipco_pll_write(cc, 0x2, 0x03000c04); | ||
629 | bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0); | ||
630 | bcma_chipco_pll_write(cc, 0x4, 0x200005c0); | ||
631 | |||
632 | bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400); | ||
633 | |||
634 | b43_phy_write(dev, 0x942, 0); | ||
635 | |||
636 | b43_phy_lcn_txrx_spur_avoidance_mode(dev, false); | ||
637 | b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00); | ||
638 | b43_phy_write(dev, 0x425, 0x5907); | ||
639 | } else { | ||
640 | bcma_chipco_pll_write(cc, 0x2, 0x03140c04); | ||
641 | bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333); | ||
642 | bcma_chipco_pll_write(cc, 0x4, 0x202c2820); | ||
643 | |||
644 | bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400); | ||
645 | |||
646 | b43_phy_write(dev, 0x942, 0); | ||
647 | |||
648 | b43_phy_lcn_txrx_spur_avoidance_mode(dev, true); | ||
649 | b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00); | ||
650 | b43_phy_write(dev, 0x425, 0x590a); | ||
651 | } | ||
652 | |||
653 | b43_phy_set(dev, 0x44a, 0x44); | ||
654 | b43_phy_write(dev, 0x44a, 0x80); | ||
655 | } | ||
656 | |||
657 | /* wlc_phy_chanspec_set_lcnphy */ | ||
281 | static int b43_phy_lcn_set_channel(struct b43_wldev *dev, | 658 | static int b43_phy_lcn_set_channel(struct b43_wldev *dev, |
282 | struct ieee80211_channel *channel, | 659 | struct ieee80211_channel *channel, |
283 | enum nl80211_channel_type channel_type) | 660 | enum nl80211_channel_type channel_type) |
284 | { | 661 | { |
285 | /* TODO: PLL and PHY ops */ | 662 | static const u16 sfo_cfg[14][2] = { |
663 | {965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078}, | ||
664 | {975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067}, | ||
665 | {985, 1065}, {987, 1063}, {989, 1060}, {994, 1055}, | ||
666 | }; | ||
286 | 667 | ||
287 | b43_phy_set(dev, 0x44a, 0x44); | 668 | b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value); |
288 | b43_phy_write(dev, 0x44a, 0x80); | ||
289 | 669 | ||
290 | b43_phy_set(dev, 0x44a, 0x44); | 670 | b43_phy_set(dev, 0x44a, 0x44); |
291 | b43_phy_write(dev, 0x44a, 0x80); | 671 | b43_phy_write(dev, 0x44a, 0x80); |
@@ -295,7 +675,21 @@ static int b43_phy_lcn_set_channel(struct b43_wldev *dev, | |||
295 | 675 | ||
296 | b43_phy_lcn_afe_set_unset(dev); | 676 | b43_phy_lcn_afe_set_unset(dev); |
297 | 677 | ||
298 | /* TODO */ | 678 | b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]); |
679 | b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]); | ||
680 | |||
681 | if (channel->hw_value == 14) { | ||
682 | b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8); | ||
683 | b43_phy_lcn_load_tx_iir_cck_filter(dev, 3); | ||
684 | } else { | ||
685 | b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8); | ||
686 | /* brcmsmac uses filter_type 2, we follow wl with 25 */ | ||
687 | b43_phy_lcn_load_tx_iir_cck_filter(dev, 25); | ||
688 | } | ||
689 | /* brcmsmac uses filter_type 2, we follow wl with 0 */ | ||
690 | b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0); | ||
691 | |||
692 | b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3); | ||
299 | 693 | ||
300 | return 0; | 694 | return 0; |
301 | } | 695 | } |
@@ -336,6 +730,8 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev) | |||
336 | /* wlc_phy_init_lcnphy */ | 730 | /* wlc_phy_init_lcnphy */ |
337 | static int b43_phy_lcn_op_init(struct b43_wldev *dev) | 731 | static int b43_phy_lcn_op_init(struct b43_wldev *dev) |
338 | { | 732 | { |
733 | struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc; | ||
734 | |||
339 | b43_phy_set(dev, 0x44a, 0x80); | 735 | b43_phy_set(dev, 0x44a, 0x80); |
340 | b43_phy_mask(dev, 0x44a, 0x7f); | 736 | b43_phy_mask(dev, 0x44a, 0x7f); |
341 | b43_phy_set(dev, 0x6d1, 0x80); | 737 | b43_phy_set(dev, 0x6d1, 0x80); |
@@ -357,7 +753,21 @@ static int b43_phy_lcn_op_init(struct b43_wldev *dev) | |||
357 | else | 753 | else |
358 | B43_WARN_ON(1); | 754 | B43_WARN_ON(1); |
359 | 755 | ||
360 | b43_phy_lcn_sense_setup(dev); | 756 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
757 | b43_phy_lcn_tx_pwr_ctl_init(dev); | ||
758 | |||
759 | b43_switch_channel(dev, dev->phy.channel); | ||
760 | |||
761 | bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9); | ||
762 | bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd); | ||
763 | |||
764 | /* TODO */ | ||
765 | |||
766 | b43_phy_set(dev, 0x448, 0x4000); | ||
767 | udelay(100); | ||
768 | b43_phy_mask(dev, 0x448, ~0x4000); | ||
769 | |||
770 | /* TODO */ | ||
361 | 771 | ||
362 | return 0; | 772 | return 0; |
363 | } | 773 | } |
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h index 25f06e8d4531..6a7092e13fff 100644 --- a/drivers/net/wireless/b43/phy_lcn.h +++ b/drivers/net/wireless/b43/phy_lcn.h | |||
@@ -19,6 +19,9 @@ | |||
19 | 19 | ||
20 | 20 | ||
21 | struct b43_phy_lcn { | 21 | struct b43_phy_lcn { |
22 | bool hw_pwr_ctl; | ||
23 | bool hw_pwr_ctl_capable; | ||
24 | u8 tx_pwr_curr_idx; | ||
22 | }; | 25 | }; |
23 | 26 | ||
24 | 27 | ||
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c index 9d484e2f79bf..5176363cadf2 100644 --- a/drivers/net/wireless/b43/tables_phy_lcn.c +++ b/drivers/net/wireless/b43/tables_phy_lcn.c | |||
@@ -657,8 +657,25 @@ void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev, | |||
657 | } | 657 | } |
658 | } | 658 | } |
659 | 659 | ||
660 | /* wlc_lcnphy_load_rfpower */ | ||
661 | static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev) | ||
662 | { | ||
663 | u32 bbmult, rfgain; | ||
664 | u8 i; | ||
665 | |||
666 | for (i = 0; i < 128; i++) { | ||
667 | bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i)); | ||
668 | bbmult >>= 20; | ||
669 | rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i)); | ||
670 | |||
671 | /* TODO: calculate value for 0x240 + i table offset | ||
672 | * b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val); | ||
673 | */ | ||
674 | } | ||
675 | } | ||
676 | |||
660 | /* Not implemented in brcmsmac, noticed in wl in MMIO dump */ | 677 | /* Not implemented in brcmsmac, noticed in wl in MMIO dump */ |
661 | static void b43_phy_lcn_rewrite_tables(struct b43_wldev *dev) | 678 | static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev) |
662 | { | 679 | { |
663 | int i; | 680 | int i; |
664 | u32 tmp; | 681 | u32 tmp; |
@@ -685,7 +702,7 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev) | |||
685 | b43_phy_lcn_upload_static_tables(dev); | 702 | b43_phy_lcn_upload_static_tables(dev); |
686 | 703 | ||
687 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 704 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
688 | if (sprom->boardflags_lo & B43_BFL_EXTLNA) | 705 | if (sprom->boardflags_lo & B43_BFL_FEM) |
689 | b43_phy_lcn_load_tx_gain_tab(dev, | 706 | b43_phy_lcn_load_tx_gain_tab(dev, |
690 | b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0); | 707 | b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0); |
691 | else | 708 | else |
@@ -701,7 +718,7 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev) | |||
701 | else | 718 | else |
702 | b43err(dev->wl, "SW ctl table is unknown for this card\n"); | 719 | b43err(dev->wl, "SW ctl table is unknown for this card\n"); |
703 | 720 | ||
704 | /* TODO: various tables ops here */ | 721 | b43_phy_lcn_load_rfpower(dev); |
705 | b43_phy_lcn_rewrite_tables(dev); | 722 | b43_phy_lcn_rewrite_rfpower_table(dev); |
706 | b43_phy_lcn_clean_papd_comp_table(dev); | 723 | b43_phy_lcn_clean_papd_comp_table(dev); |
707 | } | 724 | } |
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 35cd2537e7fd..8928d47432df 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c | |||
@@ -937,7 +937,7 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv) | |||
937 | &priv->contexts[IWL_RXON_CTX_BSS]); | 937 | &priv->contexts[IWL_RXON_CTX_BSS]); |
938 | #endif | 938 | #endif |
939 | 939 | ||
940 | wake_up_interruptible(&priv->wait_command_queue); | 940 | wake_up(&priv->wait_command_queue); |
941 | 941 | ||
942 | /* Keep the restart process from trying to send host | 942 | /* Keep the restart process from trying to send host |
943 | * commands by clearing the INIT status bit */ | 943 | * commands by clearing the INIT status bit */ |
@@ -1746,7 +1746,7 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, bool external) | |||
1746 | 1746 | ||
1747 | /* Set the FW error flag -- cleared on iwl_down */ | 1747 | /* Set the FW error flag -- cleared on iwl_down */ |
1748 | set_bit(STATUS_FW_ERROR, &priv->status); | 1748 | set_bit(STATUS_FW_ERROR, &priv->status); |
1749 | wake_up_interruptible(&priv->wait_command_queue); | 1749 | wake_up(&priv->wait_command_queue); |
1750 | /* | 1750 | /* |
1751 | * Keep the restart process from trying to send host | 1751 | * Keep the restart process from trying to send host |
1752 | * commands by clearing the INIT status bit | 1752 | * commands by clearing the INIT status bit |
@@ -2220,7 +2220,8 @@ out: | |||
2220 | } | 2220 | } |
2221 | EXPORT_SYMBOL(iwl_legacy_mac_config); | 2221 | EXPORT_SYMBOL(iwl_legacy_mac_config); |
2222 | 2222 | ||
2223 | void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw) | 2223 | void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw, |
2224 | struct ieee80211_vif *vif) | ||
2224 | { | 2225 | { |
2225 | struct iwl_priv *priv = hw->priv; | 2226 | struct iwl_priv *priv = hw->priv; |
2226 | unsigned long flags; | 2227 | unsigned long flags; |
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h index 84da79376ef8..b2df01c8f8f5 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.h +++ b/drivers/net/wireless/iwlegacy/iwl-core.h | |||
@@ -620,7 +620,8 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | |||
620 | 620 | ||
621 | /* mac80211 handlers */ | 621 | /* mac80211 handlers */ |
622 | int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed); | 622 | int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed); |
623 | void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw); | 623 | void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw, |
624 | struct ieee80211_vif *vif); | ||
624 | void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, | 625 | void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, |
625 | struct ieee80211_vif *vif, | 626 | struct ieee80211_vif *vif, |
626 | struct ieee80211_bss_conf *bss_conf, | 627 | struct ieee80211_bss_conf *bss_conf, |
diff --git a/drivers/net/wireless/iwlegacy/iwl-hcmd.c b/drivers/net/wireless/iwlegacy/iwl-hcmd.c index 62b4b09122cb..ce1fc9feb61f 100644 --- a/drivers/net/wireless/iwlegacy/iwl-hcmd.c +++ b/drivers/net/wireless/iwlegacy/iwl-hcmd.c | |||
@@ -167,7 +167,7 @@ int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
167 | goto out; | 167 | goto out; |
168 | } | 168 | } |
169 | 169 | ||
170 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | 170 | ret = wait_event_timeout(priv->wait_command_queue, |
171 | !test_bit(STATUS_HCMD_ACTIVE, &priv->status), | 171 | !test_bit(STATUS_HCMD_ACTIVE, &priv->status), |
172 | HOST_COMPLETE_TIMEOUT); | 172 | HOST_COMPLETE_TIMEOUT); |
173 | if (!ret) { | 173 | if (!ret) { |
diff --git a/drivers/net/wireless/iwlegacy/iwl-tx.c b/drivers/net/wireless/iwlegacy/iwl-tx.c index 4fff995c6f3e..ef9e268bf8a0 100644 --- a/drivers/net/wireless/iwlegacy/iwl-tx.c +++ b/drivers/net/wireless/iwlegacy/iwl-tx.c | |||
@@ -625,6 +625,8 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
625 | cmd = txq->cmd[cmd_index]; | 625 | cmd = txq->cmd[cmd_index]; |
626 | meta = &txq->meta[cmd_index]; | 626 | meta = &txq->meta[cmd_index]; |
627 | 627 | ||
628 | txq->time_stamp = jiffies; | ||
629 | |||
628 | pci_unmap_single(priv->pci_dev, | 630 | pci_unmap_single(priv->pci_dev, |
629 | dma_unmap_addr(meta, mapping), | 631 | dma_unmap_addr(meta, mapping), |
630 | dma_unmap_len(meta, len), | 632 | dma_unmap_len(meta, len), |
@@ -645,7 +647,7 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
645 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 647 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
646 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", | 648 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", |
647 | iwl_legacy_get_cmd_string(cmd->hdr.cmd)); | 649 | iwl_legacy_get_cmd_string(cmd->hdr.cmd)); |
648 | wake_up_interruptible(&priv->wait_command_queue); | 650 | wake_up(&priv->wait_command_queue); |
649 | } | 651 | } |
650 | 652 | ||
651 | /* Mark as unmapped */ | 653 | /* Mark as unmapped */ |
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c index 015739d204f2..b282d869a546 100644 --- a/drivers/net/wireless/iwlegacy/iwl3945-base.c +++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c | |||
@@ -840,7 +840,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, | |||
840 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | 840 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, |
841 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | 841 | test_bit(STATUS_RF_KILL_HW, &priv->status)); |
842 | else | 842 | else |
843 | wake_up_interruptible(&priv->wait_command_queue); | 843 | wake_up(&priv->wait_command_queue); |
844 | } | 844 | } |
845 | 845 | ||
846 | /** | 846 | /** |
@@ -2268,7 +2268,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2268 | iwl3945_reg_txpower_periodic(priv); | 2268 | iwl3945_reg_txpower_periodic(priv); |
2269 | 2269 | ||
2270 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 2270 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
2271 | wake_up_interruptible(&priv->wait_command_queue); | 2271 | wake_up(&priv->wait_command_queue); |
2272 | 2272 | ||
2273 | return; | 2273 | return; |
2274 | 2274 | ||
@@ -2299,7 +2299,7 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2299 | iwl_legacy_clear_driver_stations(priv); | 2299 | iwl_legacy_clear_driver_stations(priv); |
2300 | 2300 | ||
2301 | /* Unblock any waiting calls */ | 2301 | /* Unblock any waiting calls */ |
2302 | wake_up_interruptible_all(&priv->wait_command_queue); | 2302 | wake_up_all(&priv->wait_command_queue); |
2303 | 2303 | ||
2304 | /* Wipe out the EXIT_PENDING status bit if we are not actually | 2304 | /* Wipe out the EXIT_PENDING status bit if we are not actually |
2305 | * exiting the module */ | 2305 | * exiting the module */ |
@@ -2852,7 +2852,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
2852 | 2852 | ||
2853 | /* Wait for START_ALIVE from ucode. Otherwise callbacks from | 2853 | /* Wait for START_ALIVE from ucode. Otherwise callbacks from |
2854 | * mac80211 will not be run successfully. */ | 2854 | * mac80211 will not be run successfully. */ |
2855 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | 2855 | ret = wait_event_timeout(priv->wait_command_queue, |
2856 | test_bit(STATUS_READY, &priv->status), | 2856 | test_bit(STATUS_READY, &priv->status), |
2857 | UCODE_READY_TIMEOUT); | 2857 | UCODE_READY_TIMEOUT); |
2858 | if (!ret) { | 2858 | if (!ret) { |
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index 6bc5575c8dff..d2fba9eae153 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c | |||
@@ -575,7 +575,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, | |||
575 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | 575 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, |
576 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | 576 | test_bit(STATUS_RF_KILL_HW, &priv->status)); |
577 | else | 577 | else |
578 | wake_up_interruptible(&priv->wait_command_queue); | 578 | wake_up(&priv->wait_command_queue); |
579 | } | 579 | } |
580 | 580 | ||
581 | /** | 581 | /** |
@@ -925,7 +925,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) | |||
925 | handled |= CSR_INT_BIT_FH_TX; | 925 | handled |= CSR_INT_BIT_FH_TX; |
926 | /* Wake up uCode load routine, now that load is complete */ | 926 | /* Wake up uCode load routine, now that load is complete */ |
927 | priv->ucode_write_complete = 1; | 927 | priv->ucode_write_complete = 1; |
928 | wake_up_interruptible(&priv->wait_command_queue); | 928 | wake_up(&priv->wait_command_queue); |
929 | } | 929 | } |
930 | 930 | ||
931 | if (inta & ~handled) { | 931 | if (inta & ~handled) { |
@@ -1794,7 +1794,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv) | |||
1794 | iwl4965_rf_kill_ct_config(priv); | 1794 | iwl4965_rf_kill_ct_config(priv); |
1795 | 1795 | ||
1796 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 1796 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
1797 | wake_up_interruptible(&priv->wait_command_queue); | 1797 | wake_up(&priv->wait_command_queue); |
1798 | 1798 | ||
1799 | iwl_legacy_power_update_mode(priv, true); | 1799 | iwl_legacy_power_update_mode(priv, true); |
1800 | IWL_DEBUG_INFO(priv, "Updated power mode\n"); | 1800 | IWL_DEBUG_INFO(priv, "Updated power mode\n"); |
@@ -1827,7 +1827,7 @@ static void __iwl4965_down(struct iwl_priv *priv) | |||
1827 | iwl_legacy_clear_driver_stations(priv); | 1827 | iwl_legacy_clear_driver_stations(priv); |
1828 | 1828 | ||
1829 | /* Unblock any waiting calls */ | 1829 | /* Unblock any waiting calls */ |
1830 | wake_up_interruptible_all(&priv->wait_command_queue); | 1830 | wake_up_all(&priv->wait_command_queue); |
1831 | 1831 | ||
1832 | /* Wipe out the EXIT_PENDING status bit if we are not actually | 1832 | /* Wipe out the EXIT_PENDING status bit if we are not actually |
1833 | * exiting the module */ | 1833 | * exiting the module */ |
@@ -2265,7 +2265,7 @@ int iwl4965_mac_start(struct ieee80211_hw *hw) | |||
2265 | 2265 | ||
2266 | /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from | 2266 | /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from |
2267 | * mac80211 will not be run successfully. */ | 2267 | * mac80211 will not be run successfully. */ |
2268 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | 2268 | ret = wait_event_timeout(priv->wait_command_queue, |
2269 | test_bit(STATUS_READY, &priv->status), | 2269 | test_bit(STATUS_READY, &priv->status), |
2270 | UCODE_READY_TIMEOUT); | 2270 | UCODE_READY_TIMEOUT); |
2271 | if (!ret) { | 2271 | if (!ret) { |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 48ab9142af38..8fa59cdb3b49 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -3,18 +3,19 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o | |||
3 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o | 3 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o |
4 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o | 4 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o |
5 | iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o | 5 | iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o |
6 | iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o | 6 | iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o |
7 | 7 | ||
8 | iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o | 8 | iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o |
9 | iwlagn-objs += iwl-rx.o iwl-sta.o | 9 | iwlagn-objs += iwl-rx.o iwl-sta.o |
10 | iwlagn-objs += iwl-scan.o iwl-led.o | 10 | iwlagn-objs += iwl-scan.o iwl-led.o |
11 | iwlagn-objs += iwl-agn-rxon.o | 11 | iwlagn-objs += iwl-agn-rxon.o |
12 | iwlagn-objs += iwl-5000.o | 12 | iwlagn-objs += iwl-5000.o |
13 | iwlagn-objs += iwl-6000.o | 13 | iwlagn-objs += iwl-6000.o |
14 | iwlagn-objs += iwl-1000.o | 14 | iwlagn-objs += iwl-1000.o |
15 | iwlagn-objs += iwl-2000.o | 15 | iwlagn-objs += iwl-2000.o |
16 | iwlagn-objs += iwl-pci.o | 16 | iwlagn-objs += iwl-pci.o |
17 | iwlagn-objs += iwl-trans.o iwl-trans-rx-pcie.o iwl-trans-tx-pcie.o | 17 | iwlagn-objs += iwl-trans.o |
18 | iwlagn-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | ||
18 | 19 | ||
19 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 20 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
20 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 21 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 4766c3a1a2f6..887f9ac434c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "iwl-helpers.h" | 44 | #include "iwl-helpers.h" |
45 | #include "iwl-agn-hw.h" | 45 | #include "iwl-agn-hw.h" |
46 | #include "iwl-shared.h" | 46 | #include "iwl-shared.h" |
47 | #include "iwl-pci.h" | 47 | #include "iwl-cfg.h" |
48 | 48 | ||
49 | /* Highest firmware API version supported */ | 49 | /* Highest firmware API version supported */ |
50 | #define IWL1000_UCODE_API_MAX 6 | 50 | #define IWL1000_UCODE_API_MAX 6 |
@@ -161,8 +161,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
161 | if (priv->cfg->need_dc_calib) | 161 | if (priv->cfg->need_dc_calib) |
162 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); | 162 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); |
163 | 163 | ||
164 | hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
165 | |||
166 | return 0; | 164 | return 0; |
167 | } | 165 | } |
168 | 166 | ||
@@ -191,7 +189,6 @@ static struct iwl_base_params iwl1000_base_params = { | |||
191 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 189 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
192 | .shadow_ram_support = false, | 190 | .shadow_ram_support = false, |
193 | .led_compensation = 51, | 191 | .led_compensation = 51, |
194 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
195 | .support_ct_kill_exit = true, | 192 | .support_ct_kill_exit = true, |
196 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 193 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
197 | .chain_noise_scale = 1000, | 194 | .chain_noise_scale = 1000, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 913f2a228527..db889581c0e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include "iwl-agn-hw.h" | 45 | #include "iwl-agn-hw.h" |
46 | #include "iwl-6000-hw.h" | 46 | #include "iwl-6000-hw.h" |
47 | #include "iwl-shared.h" | 47 | #include "iwl-shared.h" |
48 | #include "iwl-pci.h" | 48 | #include "iwl-cfg.h" |
49 | 49 | ||
50 | /* Highest firmware API version supported */ | 50 | /* Highest firmware API version supported */ |
51 | #define IWL2030_UCODE_API_MAX 6 | 51 | #define IWL2030_UCODE_API_MAX 6 |
@@ -75,7 +75,7 @@ | |||
75 | #define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode" | 75 | #define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode" |
76 | 76 | ||
77 | #define IWL135_FW_PRE "iwlwifi-135-" | 77 | #define IWL135_FW_PRE "iwlwifi-135-" |
78 | #define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode" | 78 | #define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode" |
79 | 79 | ||
80 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | 80 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) |
81 | { | 81 | { |
@@ -159,8 +159,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |||
159 | if (priv->cfg->need_temp_offset_calib) | 159 | if (priv->cfg->need_temp_offset_calib) |
160 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); | 160 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); |
161 | 161 | ||
162 | hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
163 | |||
164 | return 0; | 162 | return 0; |
165 | } | 163 | } |
166 | 164 | ||
@@ -211,7 +209,6 @@ static struct iwl_base_params iwl2000_base_params = { | |||
211 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | 209 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, |
212 | .shadow_ram_support = true, | 210 | .shadow_ram_support = true, |
213 | .led_compensation = 51, | 211 | .led_compensation = 51, |
214 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
215 | .adv_thermal_throttle = true, | 212 | .adv_thermal_throttle = true, |
216 | .support_ct_kill_exit = true, | 213 | .support_ct_kill_exit = true, |
217 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 214 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -231,7 +228,6 @@ static struct iwl_base_params iwl2030_base_params = { | |||
231 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | 228 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, |
232 | .shadow_ram_support = true, | 229 | .shadow_ram_support = true, |
233 | .led_compensation = 57, | 230 | .led_compensation = 57, |
234 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
235 | .adv_thermal_throttle = true, | 231 | .adv_thermal_throttle = true, |
236 | .support_ct_kill_exit = true, | 232 | .support_ct_kill_exit = true, |
237 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 233 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -268,6 +264,7 @@ static struct iwl_bt_params iwl2030_bt_params = { | |||
268 | .base_params = &iwl2000_base_params, \ | 264 | .base_params = &iwl2000_base_params, \ |
269 | .need_dc_calib = true, \ | 265 | .need_dc_calib = true, \ |
270 | .need_temp_offset_calib = true, \ | 266 | .need_temp_offset_calib = true, \ |
267 | .temp_offset_v2 = true, \ | ||
271 | .led_mode = IWL_LED_RF_STATE, \ | 268 | .led_mode = IWL_LED_RF_STATE, \ |
272 | .iq_invert = true \ | 269 | .iq_invert = true \ |
273 | 270 | ||
@@ -300,6 +297,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = { | |||
300 | .bt_params = &iwl2030_bt_params, \ | 297 | .bt_params = &iwl2030_bt_params, \ |
301 | .need_dc_calib = true, \ | 298 | .need_dc_calib = true, \ |
302 | .need_temp_offset_calib = true, \ | 299 | .need_temp_offset_calib = true, \ |
300 | .temp_offset_v2 = true, \ | ||
303 | .led_mode = IWL_LED_RF_STATE, \ | 301 | .led_mode = IWL_LED_RF_STATE, \ |
304 | .adv_pm = true, \ | 302 | .adv_pm = true, \ |
305 | .iq_invert = true \ | 303 | .iq_invert = true \ |
@@ -326,6 +324,7 @@ struct iwl_cfg iwl2030_2bg_cfg = { | |||
326 | .base_params = &iwl2000_base_params, \ | 324 | .base_params = &iwl2000_base_params, \ |
327 | .need_dc_calib = true, \ | 325 | .need_dc_calib = true, \ |
328 | .need_temp_offset_calib = true, \ | 326 | .need_temp_offset_calib = true, \ |
327 | .temp_offset_v2 = true, \ | ||
329 | .led_mode = IWL_LED_RF_STATE, \ | 328 | .led_mode = IWL_LED_RF_STATE, \ |
330 | .adv_pm = true, \ | 329 | .adv_pm = true, \ |
331 | .rx_with_siso_diversity = true, \ | 330 | .rx_with_siso_diversity = true, \ |
@@ -354,6 +353,7 @@ struct iwl_cfg iwl105_bgn_cfg = { | |||
354 | .bt_params = &iwl2030_bt_params, \ | 353 | .bt_params = &iwl2030_bt_params, \ |
355 | .need_dc_calib = true, \ | 354 | .need_dc_calib = true, \ |
356 | .need_temp_offset_calib = true, \ | 355 | .need_temp_offset_calib = true, \ |
356 | .temp_offset_v2 = true, \ | ||
357 | .led_mode = IWL_LED_RF_STATE, \ | 357 | .led_mode = IWL_LED_RF_STATE, \ |
358 | .adv_pm = true, \ | 358 | .adv_pm = true, \ |
359 | .rx_with_siso_diversity = true, \ | 359 | .rx_with_siso_diversity = true, \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index f9630a3c79fe..c0135988e777 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h | |||
@@ -74,8 +74,8 @@ | |||
74 | static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | 74 | static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) |
75 | { | 75 | { |
76 | u16 temperature, voltage; | 76 | u16 temperature, voltage; |
77 | __le16 *temp_calib = | 77 | __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv, |
78 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE); | 78 | EEPROM_KELVIN_TEMPERATURE); |
79 | 79 | ||
80 | temperature = le16_to_cpu(temp_calib[0]); | 80 | temperature = le16_to_cpu(temp_calib[0]); |
81 | voltage = le16_to_cpu(temp_calib[1]); | 81 | voltage = le16_to_cpu(temp_calib[1]); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7cb4d69e0c37..290701620f03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #include "iwl-5000-hw.h" | 47 | #include "iwl-5000-hw.h" |
48 | #include "iwl-trans.h" | 48 | #include "iwl-trans.h" |
49 | #include "iwl-shared.h" | 49 | #include "iwl-shared.h" |
50 | #include "iwl-pci.h" | 50 | #include "iwl-cfg.h" |
51 | 51 | ||
52 | /* Highest firmware API version supported */ | 52 | /* Highest firmware API version supported */ |
53 | #define IWL5000_UCODE_API_MAX 5 | 53 | #define IWL5000_UCODE_API_MAX 5 |
@@ -184,8 +184,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
184 | BIT(IWL_CALIB_TX_IQ_PERD) | | 184 | BIT(IWL_CALIB_TX_IQ_PERD) | |
185 | BIT(IWL_CALIB_BASE_BAND); | 185 | BIT(IWL_CALIB_BASE_BAND); |
186 | 186 | ||
187 | hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
188 | |||
189 | return 0; | 187 | return 0; |
190 | } | 188 | } |
191 | 189 | ||
@@ -223,8 +221,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
223 | if (priv->cfg->need_dc_calib) | 221 | if (priv->cfg->need_dc_calib) |
224 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); | 222 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); |
225 | 223 | ||
226 | hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
227 | |||
228 | return 0; | 224 | return 0; |
229 | } | 225 | } |
230 | 226 | ||
@@ -353,7 +349,6 @@ static struct iwl_base_params iwl5000_base_params = { | |||
353 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | 349 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
354 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 350 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
355 | .led_compensation = 51, | 351 | .led_compensation = 51, |
356 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
357 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 352 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
358 | .chain_noise_scale = 1000, | 353 | .chain_noise_scale = 1000, |
359 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | 354 | .wd_timeout = IWL_LONG_WD_TIMEOUT, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 2a98e65ca84c..37837f7b6990 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include "iwl-6000-hw.h" | 46 | #include "iwl-6000-hw.h" |
47 | #include "iwl-trans.h" | 47 | #include "iwl-trans.h" |
48 | #include "iwl-shared.h" | 48 | #include "iwl-shared.h" |
49 | #include "iwl-pci.h" | 49 | #include "iwl-cfg.h" |
50 | 50 | ||
51 | /* Highest firmware API version supported */ | 51 | /* Highest firmware API version supported */ |
52 | #define IWL6000_UCODE_API_MAX 4 | 52 | #define IWL6000_UCODE_API_MAX 4 |
@@ -180,8 +180,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
180 | if (priv->cfg->need_temp_offset_calib) | 180 | if (priv->cfg->need_temp_offset_calib) |
181 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); | 181 | hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); |
182 | 182 | ||
183 | hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
184 | |||
185 | return 0; | 183 | return 0; |
186 | } | 184 | } |
187 | 185 | ||
@@ -305,7 +303,6 @@ static struct iwl_base_params iwl6000_base_params = { | |||
305 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 303 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
306 | .shadow_ram_support = true, | 304 | .shadow_ram_support = true, |
307 | .led_compensation = 51, | 305 | .led_compensation = 51, |
308 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
309 | .adv_thermal_throttle = true, | 306 | .adv_thermal_throttle = true, |
310 | .support_ct_kill_exit = true, | 307 | .support_ct_kill_exit = true, |
311 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 308 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -323,7 +320,6 @@ static struct iwl_base_params iwl6050_base_params = { | |||
323 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | 320 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
324 | .shadow_ram_support = true, | 321 | .shadow_ram_support = true, |
325 | .led_compensation = 51, | 322 | .led_compensation = 51, |
326 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
327 | .adv_thermal_throttle = true, | 323 | .adv_thermal_throttle = true, |
328 | .support_ct_kill_exit = true, | 324 | .support_ct_kill_exit = true, |
329 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 325 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -340,7 +336,6 @@ static struct iwl_base_params iwl6000_g2_base_params = { | |||
340 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 336 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
341 | .shadow_ram_support = true, | 337 | .shadow_ram_support = true, |
342 | .led_compensation = 57, | 338 | .led_compensation = 57, |
343 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
344 | .adv_thermal_throttle = true, | 339 | .adv_thermal_throttle = true, |
345 | .support_ct_kill_exit = true, | 340 | .support_ct_kill_exit = true, |
346 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 341 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index b725f6970dee..03bac48558b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -766,12 +766,9 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | |||
766 | u8 first_chain; | 766 | u8 first_chain; |
767 | u16 i = 0; | 767 | u16 i = 0; |
768 | 768 | ||
769 | average_sig[0] = data->chain_signal_a / | 769 | average_sig[0] = data->chain_signal_a / IWL_CAL_NUM_BEACONS; |
770 | priv->cfg->base_params->chain_noise_num_beacons; | 770 | average_sig[1] = data->chain_signal_b / IWL_CAL_NUM_BEACONS; |
771 | average_sig[1] = data->chain_signal_b / | 771 | average_sig[2] = data->chain_signal_c / IWL_CAL_NUM_BEACONS; |
772 | priv->cfg->base_params->chain_noise_num_beacons; | ||
773 | average_sig[2] = data->chain_signal_c / | ||
774 | priv->cfg->base_params->chain_noise_num_beacons; | ||
775 | 772 | ||
776 | if (average_sig[0] >= average_sig[1]) { | 773 | if (average_sig[0] >= average_sig[1]) { |
777 | max_average_sig = average_sig[0]; | 774 | max_average_sig = average_sig[0]; |
@@ -1038,8 +1035,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1038 | /* If this is the "chain_noise_num_beacons", determine: | 1035 | /* If this is the "chain_noise_num_beacons", determine: |
1039 | * 1) Disconnected antennas (using signal strengths) | 1036 | * 1) Disconnected antennas (using signal strengths) |
1040 | * 2) Differential gain (using silence noise) to balance receivers */ | 1037 | * 2) Differential gain (using silence noise) to balance receivers */ |
1041 | if (data->beacon_count != | 1038 | if (data->beacon_count != IWL_CAL_NUM_BEACONS) |
1042 | priv->cfg->base_params->chain_noise_num_beacons) | ||
1043 | return; | 1039 | return; |
1044 | 1040 | ||
1045 | /* Analyze signal for disconnected antenna */ | 1041 | /* Analyze signal for disconnected antenna */ |
@@ -1055,12 +1051,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1055 | iwl_find_disconn_antenna(priv, average_sig, data); | 1051 | iwl_find_disconn_antenna(priv, average_sig, data); |
1056 | 1052 | ||
1057 | /* Analyze noise for rx balance */ | 1053 | /* Analyze noise for rx balance */ |
1058 | average_noise[0] = data->chain_noise_a / | 1054 | average_noise[0] = data->chain_noise_a / IWL_CAL_NUM_BEACONS; |
1059 | priv->cfg->base_params->chain_noise_num_beacons; | 1055 | average_noise[1] = data->chain_noise_b / IWL_CAL_NUM_BEACONS; |
1060 | average_noise[1] = data->chain_noise_b / | 1056 | average_noise[2] = data->chain_noise_c / IWL_CAL_NUM_BEACONS; |
1061 | priv->cfg->base_params->chain_noise_num_beacons; | ||
1062 | average_noise[2] = data->chain_noise_c / | ||
1063 | priv->cfg->base_params->chain_noise_num_beacons; | ||
1064 | 1057 | ||
1065 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 1058 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
1066 | if (!(data->disconn_array[i]) && | 1059 | if (!(data->disconn_array[i]) && |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c deleted file mode 100644 index c62ddc2a31bd..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ /dev/null | |||
@@ -1,299 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | |||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/slab.h> | ||
67 | #include <linux/init.h> | ||
68 | |||
69 | #include <net/mac80211.h> | ||
70 | |||
71 | #include "iwl-commands.h" | ||
72 | #include "iwl-dev.h" | ||
73 | #include "iwl-core.h" | ||
74 | #include "iwl-debug.h" | ||
75 | #include "iwl-agn.h" | ||
76 | #include "iwl-io.h" | ||
77 | |||
78 | /****************************************************************************** | ||
79 | * | ||
80 | * EEPROM related functions | ||
81 | * | ||
82 | ******************************************************************************/ | ||
83 | |||
84 | int iwl_eeprom_check_version(struct iwl_priv *priv) | ||
85 | { | ||
86 | u16 eeprom_ver; | ||
87 | u16 calib_ver; | ||
88 | |||
89 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
90 | calib_ver = iwlagn_eeprom_calib_version(priv); | ||
91 | |||
92 | if (eeprom_ver < priv->cfg->eeprom_ver || | ||
93 | calib_ver < priv->cfg->eeprom_calib_ver) | ||
94 | goto err; | ||
95 | |||
96 | IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
97 | eeprom_ver, calib_ver); | ||
98 | |||
99 | return 0; | ||
100 | err: | ||
101 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x " | ||
102 | "CALIB=0x%x < 0x%x\n", | ||
103 | eeprom_ver, priv->cfg->eeprom_ver, | ||
104 | calib_ver, priv->cfg->eeprom_calib_ver); | ||
105 | return -EINVAL; | ||
106 | |||
107 | } | ||
108 | |||
109 | int iwl_eeprom_check_sku(struct iwl_priv *priv) | ||
110 | { | ||
111 | u16 radio_cfg; | ||
112 | |||
113 | if (!priv->cfg->sku) { | ||
114 | /* not using sku overwrite */ | ||
115 | priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); | ||
116 | if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
117 | !priv->cfg->ht_params) { | ||
118 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | } | ||
122 | if (!priv->cfg->sku) { | ||
123 | IWL_ERR(priv, "Invalid device sku\n"); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku); | ||
128 | |||
129 | if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) { | ||
130 | /* not using .cfg overwrite */ | ||
131 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
132 | priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); | ||
133 | priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); | ||
134 | if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) { | ||
135 | IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n", | ||
136 | priv->cfg->valid_tx_ant, | ||
137 | priv->cfg->valid_rx_ant); | ||
138 | return -EINVAL; | ||
139 | } | ||
140 | IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n", | ||
141 | priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant); | ||
142 | } | ||
143 | /* | ||
144 | * for some special cases, | ||
145 | * EEPROM did not reflect the correct antenna setting | ||
146 | * so overwrite the valid tx/rx antenna from .cfg | ||
147 | */ | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) | ||
152 | { | ||
153 | const u8 *addr = iwl_eeprom_query_addr(priv, | ||
154 | EEPROM_MAC_ADDRESS); | ||
155 | memcpy(mac, addr, ETH_ALEN); | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | ||
160 | * find the highest tx power from all chains for the channel | ||
161 | */ | ||
162 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | ||
163 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
164 | int element, s8 *max_txpower_in_half_dbm) | ||
165 | { | ||
166 | s8 max_txpower_avg = 0; /* (dBm) */ | ||
167 | |||
168 | /* Take the highest tx power from any valid chains */ | ||
169 | if ((priv->cfg->valid_tx_ant & ANT_A) && | ||
170 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | ||
171 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | ||
172 | if ((priv->cfg->valid_tx_ant & ANT_B) && | ||
173 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | ||
174 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | ||
175 | if ((priv->cfg->valid_tx_ant & ANT_C) && | ||
176 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | ||
177 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | ||
178 | if (((priv->cfg->valid_tx_ant == ANT_AB) | | ||
179 | (priv->cfg->valid_tx_ant == ANT_BC) | | ||
180 | (priv->cfg->valid_tx_ant == ANT_AC)) && | ||
181 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | ||
182 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | ||
183 | if ((priv->cfg->valid_tx_ant == ANT_ABC) && | ||
184 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | ||
185 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | ||
186 | |||
187 | /* | ||
188 | * max. tx power in EEPROM is in 1/2 dBm format | ||
189 | * convert from 1/2 dBm to dBm (round-up convert) | ||
190 | * but we also do not want to loss 1/2 dBm resolution which | ||
191 | * will impact performance | ||
192 | */ | ||
193 | *max_txpower_in_half_dbm = max_txpower_avg; | ||
194 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
195 | } | ||
196 | |||
197 | static void | ||
198 | iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, | ||
199 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
200 | s8 max_txpower_avg) | ||
201 | { | ||
202 | int ch_idx; | ||
203 | bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ; | ||
204 | enum ieee80211_band band; | ||
205 | |||
206 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
207 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
208 | |||
209 | for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) { | ||
210 | struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx]; | ||
211 | |||
212 | /* update matching channel or from common data only */ | ||
213 | if (txp->channel != 0 && ch_info->channel != txp->channel) | ||
214 | continue; | ||
215 | |||
216 | /* update matching band only */ | ||
217 | if (band != ch_info->band) | ||
218 | continue; | ||
219 | |||
220 | if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) { | ||
221 | ch_info->max_power_avg = max_txpower_avg; | ||
222 | ch_info->curr_txpow = max_txpower_avg; | ||
223 | ch_info->scan_power = max_txpower_avg; | ||
224 | } | ||
225 | |||
226 | if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg) | ||
227 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
232 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
233 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
234 | |||
235 | #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ | ||
236 | ? # x " " : "") | ||
237 | |||
238 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | ||
239 | { | ||
240 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
241 | int idx, entries; | ||
242 | __le16 *txp_len; | ||
243 | s8 max_txp_avg, max_txp_avg_halfdbm; | ||
244 | |||
245 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
246 | |||
247 | /* the length is in 16-bit words, but we want entries */ | ||
248 | txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); | ||
249 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
250 | |||
251 | txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS); | ||
252 | |||
253 | for (idx = 0; idx < entries; idx++) { | ||
254 | txp = &txp_array[idx]; | ||
255 | /* skip invalid entries */ | ||
256 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
257 | continue; | ||
258 | |||
259 | IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
260 | (txp->channel && (txp->flags & | ||
261 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
262 | "Common " : (txp->channel) ? | ||
263 | "Channel" : "Common", | ||
264 | (txp->channel), | ||
265 | TXP_CHECK_AND_PRINT(VALID), | ||
266 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
267 | TXP_CHECK_AND_PRINT(OFDM), | ||
268 | TXP_CHECK_AND_PRINT(40MHZ), | ||
269 | TXP_CHECK_AND_PRINT(HT_AP), | ||
270 | TXP_CHECK_AND_PRINT(RES1), | ||
271 | TXP_CHECK_AND_PRINT(RES2), | ||
272 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
273 | txp->flags); | ||
274 | IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x " | ||
275 | "chain_B: 0X%02x chain_C: 0X%02x\n", | ||
276 | txp->chain_a_max, txp->chain_b_max, | ||
277 | txp->chain_c_max); | ||
278 | IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x " | ||
279 | "MIMO3: 0x%02x High 20_on_40: 0x%02x " | ||
280 | "Low 20_on_40: 0x%02x\n", | ||
281 | txp->mimo2_max, txp->mimo3_max, | ||
282 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
283 | (txp->delta_20_in_40 & 0x0f)); | ||
284 | |||
285 | max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, | ||
286 | &max_txp_avg_halfdbm); | ||
287 | |||
288 | /* | ||
289 | * Update the user limit values values to the highest | ||
290 | * power supported by any channel | ||
291 | */ | ||
292 | if (max_txp_avg > priv->tx_power_user_lmt) | ||
293 | priv->tx_power_user_lmt = max_txp_avg; | ||
294 | if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) | ||
295 | priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; | ||
296 | |||
297 | iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); | ||
298 | } | ||
299 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 13018872f776..d30714be515b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -96,11 +96,7 @@ void iwlagn_temperature(struct iwl_priv *priv) | |||
96 | 96 | ||
97 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) | 97 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) |
98 | { | 98 | { |
99 | struct iwl_eeprom_calib_hdr { | 99 | struct iwl_eeprom_calib_hdr *hdr; |
100 | u8 version; | ||
101 | u8 pa_type; | ||
102 | u16 voltage; | ||
103 | } *hdr; | ||
104 | 100 | ||
105 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 101 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, |
106 | EEPROM_CALIB_ALL); | 102 | EEPROM_CALIB_ALL); |
@@ -194,433 +190,6 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | |||
194 | return -1; | 190 | return -1; |
195 | } | 191 | } |
196 | 192 | ||
197 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | ||
198 | struct ieee80211_vif *vif, | ||
199 | enum ieee80211_band band, | ||
200 | struct iwl_scan_channel *scan_ch) | ||
201 | { | ||
202 | const struct ieee80211_supported_band *sband; | ||
203 | u16 passive_dwell = 0; | ||
204 | u16 active_dwell = 0; | ||
205 | int added = 0; | ||
206 | u16 channel = 0; | ||
207 | |||
208 | sband = iwl_get_hw_mode(priv, band); | ||
209 | if (!sband) { | ||
210 | IWL_ERR(priv, "invalid band\n"); | ||
211 | return added; | ||
212 | } | ||
213 | |||
214 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
215 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); | ||
216 | |||
217 | if (passive_dwell <= active_dwell) | ||
218 | passive_dwell = active_dwell + 1; | ||
219 | |||
220 | channel = iwl_get_single_channel_number(priv, band); | ||
221 | if (channel) { | ||
222 | scan_ch->channel = cpu_to_le16(channel); | ||
223 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
224 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
225 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
226 | /* Set txpower levels to defaults */ | ||
227 | scan_ch->dsp_atten = 110; | ||
228 | if (band == IEEE80211_BAND_5GHZ) | ||
229 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
230 | else | ||
231 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
232 | added++; | ||
233 | } else | ||
234 | IWL_ERR(priv, "no valid channel found\n"); | ||
235 | return added; | ||
236 | } | ||
237 | |||
238 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | ||
239 | struct ieee80211_vif *vif, | ||
240 | enum ieee80211_band band, | ||
241 | u8 is_active, u8 n_probes, | ||
242 | struct iwl_scan_channel *scan_ch) | ||
243 | { | ||
244 | struct ieee80211_channel *chan; | ||
245 | const struct ieee80211_supported_band *sband; | ||
246 | const struct iwl_channel_info *ch_info; | ||
247 | u16 passive_dwell = 0; | ||
248 | u16 active_dwell = 0; | ||
249 | int added, i; | ||
250 | u16 channel; | ||
251 | |||
252 | sband = iwl_get_hw_mode(priv, band); | ||
253 | if (!sband) | ||
254 | return 0; | ||
255 | |||
256 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); | ||
257 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); | ||
258 | |||
259 | if (passive_dwell <= active_dwell) | ||
260 | passive_dwell = active_dwell + 1; | ||
261 | |||
262 | for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { | ||
263 | chan = priv->scan_request->channels[i]; | ||
264 | |||
265 | if (chan->band != band) | ||
266 | continue; | ||
267 | |||
268 | channel = chan->hw_value; | ||
269 | scan_ch->channel = cpu_to_le16(channel); | ||
270 | |||
271 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
272 | if (!is_channel_valid(ch_info)) { | ||
273 | IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", | ||
274 | channel); | ||
275 | continue; | ||
276 | } | ||
277 | |||
278 | if (!is_active || is_channel_passive(ch_info) || | ||
279 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
280 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
281 | else | ||
282 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | ||
283 | |||
284 | if (n_probes) | ||
285 | scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); | ||
286 | |||
287 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
288 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
289 | |||
290 | /* Set txpower levels to defaults */ | ||
291 | scan_ch->dsp_atten = 110; | ||
292 | |||
293 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
294 | * power level: | ||
295 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
296 | */ | ||
297 | if (band == IEEE80211_BAND_5GHZ) | ||
298 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
299 | else | ||
300 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
301 | |||
302 | IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", | ||
303 | channel, le32_to_cpu(scan_ch->type), | ||
304 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
305 | "ACTIVE" : "PASSIVE", | ||
306 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
307 | active_dwell : passive_dwell); | ||
308 | |||
309 | scan_ch++; | ||
310 | added++; | ||
311 | } | ||
312 | |||
313 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); | ||
314 | return added; | ||
315 | } | ||
316 | |||
317 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||
318 | { | ||
319 | struct iwl_host_cmd cmd = { | ||
320 | .id = REPLY_SCAN_CMD, | ||
321 | .len = { sizeof(struct iwl_scan_cmd), }, | ||
322 | .flags = CMD_SYNC, | ||
323 | }; | ||
324 | struct iwl_scan_cmd *scan; | ||
325 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
326 | u32 rate_flags = 0; | ||
327 | u16 cmd_len; | ||
328 | u16 rx_chain = 0; | ||
329 | enum ieee80211_band band; | ||
330 | u8 n_probes = 0; | ||
331 | u8 rx_ant = hw_params(priv).valid_rx_ant; | ||
332 | u8 rate; | ||
333 | bool is_active = false; | ||
334 | int chan_mod; | ||
335 | u8 active_chains; | ||
336 | u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; | ||
337 | int ret; | ||
338 | |||
339 | lockdep_assert_held(&priv->shrd->mutex); | ||
340 | |||
341 | if (vif) | ||
342 | ctx = iwl_rxon_ctx_from_vif(vif); | ||
343 | |||
344 | if (!priv->scan_cmd) { | ||
345 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | ||
346 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
347 | if (!priv->scan_cmd) { | ||
348 | IWL_DEBUG_SCAN(priv, | ||
349 | "fail to allocate memory for scan\n"); | ||
350 | return -ENOMEM; | ||
351 | } | ||
352 | } | ||
353 | scan = priv->scan_cmd; | ||
354 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | ||
355 | |||
356 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | ||
357 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | ||
358 | |||
359 | if (priv->scan_type != IWL_SCAN_ROC && | ||
360 | iwl_is_any_associated(priv)) { | ||
361 | u16 interval = 0; | ||
362 | u32 extra; | ||
363 | u32 suspend_time = 100; | ||
364 | u32 scan_suspend_time = 100; | ||
365 | |||
366 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | ||
367 | switch (priv->scan_type) { | ||
368 | case IWL_SCAN_ROC: | ||
369 | WARN_ON(1); | ||
370 | break; | ||
371 | case IWL_SCAN_RADIO_RESET: | ||
372 | interval = 0; | ||
373 | break; | ||
374 | case IWL_SCAN_NORMAL: | ||
375 | interval = vif->bss_conf.beacon_int; | ||
376 | break; | ||
377 | } | ||
378 | |||
379 | scan->suspend_time = 0; | ||
380 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
381 | if (!interval) | ||
382 | interval = suspend_time; | ||
383 | |||
384 | extra = (suspend_time / interval) << 22; | ||
385 | scan_suspend_time = (extra | | ||
386 | ((suspend_time % interval) * 1024)); | ||
387 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | ||
388 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | ||
389 | scan_suspend_time, interval); | ||
390 | } else if (priv->scan_type == IWL_SCAN_ROC) { | ||
391 | scan->suspend_time = 0; | ||
392 | scan->max_out_time = 0; | ||
393 | scan->quiet_time = 0; | ||
394 | scan->quiet_plcp_th = 0; | ||
395 | } | ||
396 | |||
397 | switch (priv->scan_type) { | ||
398 | case IWL_SCAN_RADIO_RESET: | ||
399 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
400 | break; | ||
401 | case IWL_SCAN_NORMAL: | ||
402 | if (priv->scan_request->n_ssids) { | ||
403 | int i, p = 0; | ||
404 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | ||
405 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | ||
406 | /* always does wildcard anyway */ | ||
407 | if (!priv->scan_request->ssids[i].ssid_len) | ||
408 | continue; | ||
409 | scan->direct_scan[p].id = WLAN_EID_SSID; | ||
410 | scan->direct_scan[p].len = | ||
411 | priv->scan_request->ssids[i].ssid_len; | ||
412 | memcpy(scan->direct_scan[p].ssid, | ||
413 | priv->scan_request->ssids[i].ssid, | ||
414 | priv->scan_request->ssids[i].ssid_len); | ||
415 | n_probes++; | ||
416 | p++; | ||
417 | } | ||
418 | is_active = true; | ||
419 | } else | ||
420 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); | ||
421 | break; | ||
422 | case IWL_SCAN_ROC: | ||
423 | IWL_DEBUG_SCAN(priv, "Start ROC scan.\n"); | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | ||
428 | scan->tx_cmd.sta_id = ctx->bcast_sta_id; | ||
429 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
430 | |||
431 | switch (priv->scan_band) { | ||
432 | case IEEE80211_BAND_2GHZ: | ||
433 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | ||
434 | chan_mod = le32_to_cpu( | ||
435 | priv->contexts[IWL_RXON_CTX_BSS].active.flags & | ||
436 | RXON_FLG_CHANNEL_MODE_MSK) | ||
437 | >> RXON_FLG_CHANNEL_MODE_POS; | ||
438 | if (chan_mod == CHANNEL_MODE_PURE_40) { | ||
439 | rate = IWL_RATE_6M_PLCP; | ||
440 | } else { | ||
441 | rate = IWL_RATE_1M_PLCP; | ||
442 | rate_flags = RATE_MCS_CCK_MSK; | ||
443 | } | ||
444 | /* | ||
445 | * Internal scans are passive, so we can indiscriminately set | ||
446 | * the BT ignore flag on 2.4 GHz since it applies to TX only. | ||
447 | */ | ||
448 | if (priv->cfg->bt_params && | ||
449 | priv->cfg->bt_params->advanced_bt_coexist) | ||
450 | scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; | ||
451 | break; | ||
452 | case IEEE80211_BAND_5GHZ: | ||
453 | rate = IWL_RATE_6M_PLCP; | ||
454 | break; | ||
455 | default: | ||
456 | IWL_WARN(priv, "Invalid scan band\n"); | ||
457 | return -EIO; | ||
458 | } | ||
459 | |||
460 | /* | ||
461 | * If active scanning is requested but a certain channel is | ||
462 | * marked passive, we can do active scanning if we detect | ||
463 | * transmissions. | ||
464 | * | ||
465 | * There is an issue with some firmware versions that triggers | ||
466 | * a sysassert on a "good CRC threshold" of zero (== disabled), | ||
467 | * on a radar channel even though this means that we should NOT | ||
468 | * send probes. | ||
469 | * | ||
470 | * The "good CRC threshold" is the number of frames that we | ||
471 | * need to receive during our dwell time on a channel before | ||
472 | * sending out probes -- setting this to a huge value will | ||
473 | * mean we never reach it, but at the same time work around | ||
474 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | ||
475 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | ||
476 | * | ||
477 | * This was fixed in later versions along with some other | ||
478 | * scan changes, and the threshold behaves as a flag in those | ||
479 | * versions. | ||
480 | */ | ||
481 | if (priv->new_scan_threshold_behaviour) | ||
482 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
483 | IWL_GOOD_CRC_TH_DISABLED; | ||
484 | else | ||
485 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
486 | IWL_GOOD_CRC_TH_NEVER; | ||
487 | |||
488 | band = priv->scan_band; | ||
489 | |||
490 | if (priv->cfg->scan_rx_antennas[band]) | ||
491 | rx_ant = priv->cfg->scan_rx_antennas[band]; | ||
492 | |||
493 | if (band == IEEE80211_BAND_2GHZ && | ||
494 | priv->cfg->bt_params && | ||
495 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
496 | /* transmit 2.4 GHz probes only on first antenna */ | ||
497 | scan_tx_antennas = first_antenna(scan_tx_antennas); | ||
498 | } | ||
499 | |||
500 | priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band], | ||
501 | scan_tx_antennas); | ||
502 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | ||
503 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | ||
504 | |||
505 | /* In power save mode use one chain, otherwise use all chains */ | ||
506 | if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { | ||
507 | /* rx_ant has been set to all valid chains previously */ | ||
508 | active_chains = rx_ant & | ||
509 | ((u8)(priv->chain_noise_data.active_chains)); | ||
510 | if (!active_chains) | ||
511 | active_chains = rx_ant; | ||
512 | |||
513 | IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", | ||
514 | priv->chain_noise_data.active_chains); | ||
515 | |||
516 | rx_ant = first_antenna(active_chains); | ||
517 | } | ||
518 | if (priv->cfg->bt_params && | ||
519 | priv->cfg->bt_params->advanced_bt_coexist && | ||
520 | priv->bt_full_concurrent) { | ||
521 | /* operated as 1x1 in full concurrency mode */ | ||
522 | rx_ant = first_antenna(rx_ant); | ||
523 | } | ||
524 | |||
525 | /* MIMO is not used here, but value is required */ | ||
526 | rx_chain |= | ||
527 | hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | ||
528 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | ||
529 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | ||
530 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | ||
531 | scan->rx_chain = cpu_to_le16(rx_chain); | ||
532 | switch (priv->scan_type) { | ||
533 | case IWL_SCAN_NORMAL: | ||
534 | cmd_len = iwl_fill_probe_req(priv, | ||
535 | (struct ieee80211_mgmt *)scan->data, | ||
536 | vif->addr, | ||
537 | priv->scan_request->ie, | ||
538 | priv->scan_request->ie_len, | ||
539 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
540 | break; | ||
541 | case IWL_SCAN_RADIO_RESET: | ||
542 | case IWL_SCAN_ROC: | ||
543 | /* use bcast addr, will not be transmitted but must be valid */ | ||
544 | cmd_len = iwl_fill_probe_req(priv, | ||
545 | (struct ieee80211_mgmt *)scan->data, | ||
546 | iwl_bcast_addr, NULL, 0, | ||
547 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
548 | break; | ||
549 | default: | ||
550 | BUG(); | ||
551 | } | ||
552 | scan->tx_cmd.len = cpu_to_le16(cmd_len); | ||
553 | |||
554 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | ||
555 | RXON_FILTER_BCON_AWARE_MSK); | ||
556 | |||
557 | switch (priv->scan_type) { | ||
558 | case IWL_SCAN_RADIO_RESET: | ||
559 | scan->channel_count = | ||
560 | iwl_get_single_channel_for_scan(priv, vif, band, | ||
561 | (void *)&scan->data[cmd_len]); | ||
562 | break; | ||
563 | case IWL_SCAN_NORMAL: | ||
564 | scan->channel_count = | ||
565 | iwl_get_channels_for_scan(priv, vif, band, | ||
566 | is_active, n_probes, | ||
567 | (void *)&scan->data[cmd_len]); | ||
568 | break; | ||
569 | case IWL_SCAN_ROC: { | ||
570 | struct iwl_scan_channel *scan_ch; | ||
571 | |||
572 | scan->channel_count = 1; | ||
573 | |||
574 | scan_ch = (void *)&scan->data[cmd_len]; | ||
575 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
576 | scan_ch->channel = | ||
577 | cpu_to_le16(priv->hw_roc_channel->hw_value); | ||
578 | scan_ch->active_dwell = | ||
579 | scan_ch->passive_dwell = | ||
580 | cpu_to_le16(priv->hw_roc_duration); | ||
581 | |||
582 | /* Set txpower levels to defaults */ | ||
583 | scan_ch->dsp_atten = 110; | ||
584 | |||
585 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
586 | * power level: | ||
587 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
588 | */ | ||
589 | if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) | ||
590 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
591 | else | ||
592 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
593 | } | ||
594 | break; | ||
595 | } | ||
596 | |||
597 | if (scan->channel_count == 0) { | ||
598 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | ||
599 | return -EIO; | ||
600 | } | ||
601 | |||
602 | cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + | ||
603 | scan->channel_count * sizeof(struct iwl_scan_channel); | ||
604 | cmd.data[0] = scan; | ||
605 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
606 | scan->len = cpu_to_le16(cmd.len[0]); | ||
607 | |||
608 | /* set scan bit here for PAN params */ | ||
609 | set_bit(STATUS_SCAN_HW, &priv->shrd->status); | ||
610 | |||
611 | ret = iwlagn_set_pan_params(priv); | ||
612 | if (ret) | ||
613 | return ret; | ||
614 | |||
615 | ret = iwl_trans_send_cmd(trans(priv), &cmd); | ||
616 | if (ret) { | ||
617 | clear_bit(STATUS_SCAN_HW, &priv->shrd->status); | ||
618 | iwlagn_set_pan_params(priv); | ||
619 | } | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | 193 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, |
625 | struct ieee80211_vif *vif, bool add) | 194 | struct ieee80211_vif *vif, bool add) |
626 | { | 195 | { |
@@ -1136,8 +705,9 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv, | |||
1136 | } | 705 | } |
1137 | } | 706 | } |
1138 | 707 | ||
1139 | void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, | 708 | int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, |
1140 | struct iwl_rx_mem_buffer *rxb) | 709 | struct iwl_rx_mem_buffer *rxb, |
710 | struct iwl_device_cmd *cmd) | ||
1141 | { | 711 | { |
1142 | unsigned long flags; | 712 | unsigned long flags; |
1143 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 713 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -1146,7 +716,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, | |||
1146 | 716 | ||
1147 | if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) { | 717 | if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) { |
1148 | /* bt coex disabled */ | 718 | /* bt coex disabled */ |
1149 | return; | 719 | return 0; |
1150 | } | 720 | } |
1151 | 721 | ||
1152 | IWL_DEBUG_COEX(priv, "BT Coex notification:\n"); | 722 | IWL_DEBUG_COEX(priv, "BT Coex notification:\n"); |
@@ -1188,6 +758,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, | |||
1188 | spin_lock_irqsave(&priv->shrd->lock, flags); | 758 | spin_lock_irqsave(&priv->shrd->lock, flags); |
1189 | priv->bt_ci_compliance = coex->bt_ci_compliance; | 759 | priv->bt_ci_compliance = coex->bt_ci_compliance; |
1190 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 760 | spin_unlock_irqrestore(&priv->shrd->lock, flags); |
761 | return 0; | ||
1191 | } | 762 | } |
1192 | 763 | ||
1193 | void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) | 764 | void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index ffee15ba06a8..c14f8d6fd7d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -346,7 +346,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv, | |||
346 | { | 346 | { |
347 | struct iwl_station_priv *sta_priv = | 347 | struct iwl_station_priv *sta_priv = |
348 | container_of(lq_sta, struct iwl_station_priv, lq_sta); | 348 | container_of(lq_sta, struct iwl_station_priv, lq_sta); |
349 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | 349 | struct iwl_rxon_context *ctx = sta_priv->ctx; |
350 | 350 | ||
351 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ | 351 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ |
352 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | 352 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ |
@@ -710,7 +710,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
710 | static bool rs_use_green(struct ieee80211_sta *sta) | 710 | static bool rs_use_green(struct ieee80211_sta *sta) |
711 | { | 711 | { |
712 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 712 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
713 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | 713 | struct iwl_rxon_context *ctx = sta_priv->ctx; |
714 | 714 | ||
715 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && | 715 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && |
716 | !(ctx->ht.non_gf_sta_present); | 716 | !(ctx->ht.non_gf_sta_present); |
@@ -917,7 +917,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
917 | struct iwl_scale_tbl_info tbl_type; | 917 | struct iwl_scale_tbl_info tbl_type; |
918 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; | 918 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
919 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 919 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
920 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | 920 | struct iwl_rxon_context *ctx = sta_priv->ctx; |
921 | 921 | ||
922 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 922 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
923 | 923 | ||
@@ -1283,7 +1283,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1283 | s32 rate; | 1283 | s32 rate; |
1284 | s8 is_green = lq_sta->is_green; | 1284 | s8 is_green = lq_sta->is_green; |
1285 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 1285 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
1286 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | 1286 | struct iwl_rxon_context *ctx = sta_priv->ctx; |
1287 | 1287 | ||
1288 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1288 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1289 | return -1; | 1289 | return -1; |
@@ -1339,7 +1339,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, | |||
1339 | s32 rate; | 1339 | s32 rate; |
1340 | s8 is_green = lq_sta->is_green; | 1340 | s8 is_green = lq_sta->is_green; |
1341 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 1341 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
1342 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | 1342 | struct iwl_rxon_context *ctx = sta_priv->ctx; |
1343 | 1343 | ||
1344 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1344 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1345 | return -1; | 1345 | return -1; |
@@ -1396,7 +1396,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, | |||
1396 | u8 is_green = lq_sta->is_green; | 1396 | u8 is_green = lq_sta->is_green; |
1397 | s32 rate; | 1397 | s32 rate; |
1398 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 1398 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
1399 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | 1399 | struct iwl_rxon_context *ctx = sta_priv->ctx; |
1400 | 1400 | ||
1401 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1401 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1402 | return -1; | 1402 | return -1; |
@@ -2263,7 +2263,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2263 | u8 tid = IWL_MAX_TID_COUNT; | 2263 | u8 tid = IWL_MAX_TID_COUNT; |
2264 | struct iwl_tid_data *tid_data; | 2264 | struct iwl_tid_data *tid_data; |
2265 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 2265 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
2266 | struct iwl_rxon_context *ctx = sta_priv->common.ctx; | 2266 | struct iwl_rxon_context *ctx = sta_priv->ctx; |
2267 | 2267 | ||
2268 | IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); | 2268 | IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); |
2269 | 2269 | ||
@@ -2706,7 +2706,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2706 | return; | 2706 | return; |
2707 | 2707 | ||
2708 | sta_priv = (void *)sta->drv_priv; | 2708 | sta_priv = (void *)sta->drv_priv; |
2709 | ctx = sta_priv->common.ctx; | 2709 | ctx = sta_priv->ctx; |
2710 | 2710 | ||
2711 | i = lq_sta->last_txrate_idx; | 2711 | i = lq_sta->last_txrate_idx; |
2712 | 2712 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 00e6fc59e459..ca632f9b1cc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -370,7 +370,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
370 | slot1 = IWL_MIN_SLOT_TIME; | 370 | slot1 = IWL_MIN_SLOT_TIME; |
371 | } else if (!ctx_pan->vif->bss_conf.idle && | 371 | } else if (!ctx_pan->vif->bss_conf.idle && |
372 | !ctx_pan->vif->bss_conf.assoc) { | 372 | !ctx_pan->vif->bss_conf.assoc) { |
373 | slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME; | 373 | slot1 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; |
374 | slot0 = IWL_MIN_SLOT_TIME; | 374 | slot0 = IWL_MIN_SLOT_TIME; |
375 | } | 375 | } |
376 | } else if (ctx_pan->vif) { | 376 | } else if (ctx_pan->vif) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 92ba8cd0ecd5..c27180a73351 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c | |||
@@ -114,9 +114,6 @@ static bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | |||
114 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | 114 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
115 | bool within_margin = false; | 115 | bool within_margin = false; |
116 | 116 | ||
117 | if (priv->cfg->base_params->temperature_kelvin) | ||
118 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
119 | |||
120 | if (!priv->thermal_throttle.advanced_tt) | 117 | if (!priv->thermal_throttle.advanced_tt) |
121 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | 118 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= |
122 | CT_KILL_THRESHOLD_LEGACY) ? true : false; | 119 | CT_KILL_THRESHOLD_LEGACY) ? true : false; |
@@ -209,7 +206,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | |||
209 | { | 206 | { |
210 | if (stop) { | 207 | if (stop) { |
211 | IWL_DEBUG_TEMP(priv, "Stop all queues\n"); | 208 | IWL_DEBUG_TEMP(priv, "Stop all queues\n"); |
212 | if (priv->shrd->mac80211_registered) | 209 | if (priv->mac80211_registered) |
213 | ieee80211_stop_queues(priv->hw); | 210 | ieee80211_stop_queues(priv->hw); |
214 | IWL_DEBUG_TEMP(priv, | 211 | IWL_DEBUG_TEMP(priv, |
215 | "Schedule 5 seconds CT_KILL Timer\n"); | 212 | "Schedule 5 seconds CT_KILL Timer\n"); |
@@ -217,7 +214,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | |||
217 | jiffies + CT_KILL_EXIT_DURATION * HZ); | 214 | jiffies + CT_KILL_EXIT_DURATION * HZ); |
218 | } else { | 215 | } else { |
219 | IWL_DEBUG_TEMP(priv, "Wake all queues\n"); | 216 | IWL_DEBUG_TEMP(priv, "Wake all queues\n"); |
220 | if (priv->shrd->mac80211_registered) | 217 | if (priv->mac80211_registered) |
221 | ieee80211_wake_queues(priv->hw); | 218 | ieee80211_wake_queues(priv->hw); |
222 | } | 219 | } |
223 | } | 220 | } |
@@ -591,9 +588,6 @@ static void iwl_bg_tt_work(struct work_struct *work) | |||
591 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) | 588 | if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) |
592 | return; | 589 | return; |
593 | 590 | ||
594 | if (priv->cfg->base_params->temperature_kelvin) | ||
595 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
596 | |||
597 | if (!priv->thermal_throttle.advanced_tt) | 591 | if (!priv->thermal_throttle.advanced_tt) |
598 | iwl_legacy_tt_handler(priv, temp, false); | 592 | iwl_legacy_tt_handler(priv, temp, false); |
599 | else | 593 | else |
@@ -641,11 +635,13 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
641 | 635 | ||
642 | if (priv->cfg->base_params->adv_thermal_throttle) { | 636 | if (priv->cfg->base_params->adv_thermal_throttle) { |
643 | IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n"); | 637 | IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n"); |
644 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | 638 | tt->restriction = kcalloc(IWL_TI_STATE_MAX, |
645 | IWL_TI_STATE_MAX, GFP_KERNEL); | 639 | sizeof(struct iwl_tt_restriction), |
646 | tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * | 640 | GFP_KERNEL); |
647 | IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), | 641 | tt->transaction = kcalloc(IWL_TI_STATE_MAX * |
648 | GFP_KERNEL); | 642 | (IWL_TI_STATE_MAX - 1), |
643 | sizeof(struct iwl_tt_trans), | ||
644 | GFP_KERNEL); | ||
649 | if (!tt->restriction || !tt->transaction) { | 645 | if (!tt->restriction || !tt->transaction) { |
650 | IWL_ERR(priv, "Fallback to Legacy Throttling\n"); | 646 | IWL_ERR(priv, "Fallback to Legacy Throttling\n"); |
651 | priv->thermal_throttle.advanced_tt = false; | 647 | priv->thermal_throttle.advanced_tt = false; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index ba5c514c4a43..0e5d6498be21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -313,6 +313,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
313 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | 313 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); |
314 | } | 314 | } |
315 | 315 | ||
316 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
317 | is_agg = true; | ||
318 | |||
316 | /* irqs already disabled/saved above when locking priv->shrd->lock */ | 319 | /* irqs already disabled/saved above when locking priv->shrd->lock */ |
317 | spin_lock(&priv->shrd->sta_lock); | 320 | spin_lock(&priv->shrd->sta_lock); |
318 | 321 | ||
@@ -322,10 +325,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
322 | goto drop_unlock_sta; | 325 | goto drop_unlock_sta; |
323 | 326 | ||
324 | memset(dev_cmd, 0, sizeof(*dev_cmd)); | 327 | memset(dev_cmd, 0, sizeof(*dev_cmd)); |
325 | tx_cmd = &dev_cmd->cmd.tx; | 328 | tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; |
326 | |||
327 | /* Copy MAC header from skb into command buffer */ | ||
328 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
329 | 329 | ||
330 | /* Total # bytes to be transmitted */ | 330 | /* Total # bytes to be transmitted */ |
331 | len = (u16)skb->len; | 331 | len = (u16)skb->len; |
@@ -342,6 +342,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
342 | 342 | ||
343 | iwl_update_stats(priv, true, fc, len); | 343 | iwl_update_stats(priv, true, fc, len); |
344 | 344 | ||
345 | memset(&info->status, 0, sizeof(info->status)); | ||
346 | |||
345 | info->driver_data[0] = ctx; | 347 | info->driver_data[0] = ctx; |
346 | info->driver_data[1] = dev_cmd; | 348 | info->driver_data[1] = dev_cmd; |
347 | 349 | ||
@@ -580,6 +582,9 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | |||
580 | IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); | 582 | IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); |
581 | } | 583 | } |
582 | 584 | ||
585 | if (tx_resp->frame_count == 1) | ||
586 | return; | ||
587 | |||
583 | /* Construct bit-map of pending frames within Tx window */ | 588 | /* Construct bit-map of pending frames within Tx window */ |
584 | for (i = 0; i < tx_resp->frame_count; i++) { | 589 | for (i = 0; i < tx_resp->frame_count; i++) { |
585 | u16 fstatus = le16_to_cpu(frame_status[i].status); | 590 | u16 fstatus = le16_to_cpu(frame_status[i].status); |
@@ -736,7 +741,8 @@ static void iwl_check_abort_status(struct iwl_priv *priv, | |||
736 | } | 741 | } |
737 | } | 742 | } |
738 | 743 | ||
739 | void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 744 | int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
745 | struct iwl_device_cmd *cmd) | ||
740 | { | 746 | { |
741 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 747 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
742 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 748 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
@@ -824,6 +830,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
824 | 830 | ||
825 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 831 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
826 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); | 832 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); |
833 | return 0; | ||
827 | } | 834 | } |
828 | 835 | ||
829 | /** | 836 | /** |
@@ -832,8 +839,9 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
832 | * Handles block-acknowledge notification from device, which reports success | 839 | * Handles block-acknowledge notification from device, which reports success |
833 | * of frames sent via aggregation. | 840 | * of frames sent via aggregation. |
834 | */ | 841 | */ |
835 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | 842 | int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, |
836 | struct iwl_rx_mem_buffer *rxb) | 843 | struct iwl_rx_mem_buffer *rxb, |
844 | struct iwl_device_cmd *cmd) | ||
837 | { | 845 | { |
838 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 846 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
839 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | 847 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; |
@@ -857,7 +865,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
857 | if (scd_flow >= hw_params(priv).max_txq_num) { | 865 | if (scd_flow >= hw_params(priv).max_txq_num) { |
858 | IWL_ERR(priv, | 866 | IWL_ERR(priv, |
859 | "BUG_ON scd_flow is bigger than number of queues\n"); | 867 | "BUG_ON scd_flow is bigger than number of queues\n"); |
860 | return; | 868 | return 0; |
861 | } | 869 | } |
862 | 870 | ||
863 | sta_id = ba_resp->sta_id; | 871 | sta_id = ba_resp->sta_id; |
@@ -877,14 +885,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
877 | "BA scd_flow %d does not match txq_id %d\n", | 885 | "BA scd_flow %d does not match txq_id %d\n", |
878 | scd_flow, agg->txq_id); | 886 | scd_flow, agg->txq_id); |
879 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); | 887 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); |
880 | return; | 888 | return 0; |
881 | } | 889 | } |
882 | 890 | ||
883 | if (unlikely(!agg->wait_for_ba)) { | 891 | if (unlikely(!agg->wait_for_ba)) { |
884 | if (unlikely(ba_resp->bitmap)) | 892 | if (unlikely(ba_resp->bitmap)) |
885 | IWL_ERR(priv, "Received BA when not expected\n"); | 893 | IWL_ERR(priv, "Received BA when not expected\n"); |
886 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); | 894 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); |
887 | return; | 895 | return 0; |
888 | } | 896 | } |
889 | 897 | ||
890 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | 898 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " |
@@ -901,7 +909,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
901 | ba_resp->scd_ssn); | 909 | ba_resp->scd_ssn); |
902 | 910 | ||
903 | /* Mark that the expected block-ack response arrived */ | 911 | /* Mark that the expected block-ack response arrived */ |
904 | agg->wait_for_ba = 0; | 912 | agg->wait_for_ba = false; |
905 | 913 | ||
906 | /* Sanity check values reported by uCode */ | 914 | /* Sanity check values reported by uCode */ |
907 | if (ba_resp->txed_2_done > ba_resp->txed) { | 915 | if (ba_resp->txed_2_done > ba_resp->txed) { |
@@ -935,7 +943,10 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
935 | else | 943 | else |
936 | WARN_ON_ONCE(1); | 944 | WARN_ON_ONCE(1); |
937 | 945 | ||
938 | if (freed == 0) { | 946 | info = IEEE80211_SKB_CB(skb); |
947 | kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); | ||
948 | |||
949 | if (freed == 1) { | ||
939 | /* this is the first skb we deliver in this batch */ | 950 | /* this is the first skb we deliver in this batch */ |
940 | /* put the rate scaling data there */ | 951 | /* put the rate scaling data there */ |
941 | info = IEEE80211_SKB_CB(skb); | 952 | info = IEEE80211_SKB_CB(skb); |
@@ -948,11 +959,9 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
948 | info); | 959 | info); |
949 | } | 960 | } |
950 | 961 | ||
951 | info = IEEE80211_SKB_CB(skb); | ||
952 | kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); | ||
953 | |||
954 | ieee80211_tx_status_irqsafe(priv->hw, skb); | 962 | ieee80211_tx_status_irqsafe(priv->hw, skb); |
955 | } | 963 | } |
956 | 964 | ||
957 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); | 965 | spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); |
966 | return 0; | ||
958 | } | 967 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index a7b891453869..b4e1e7c4c314 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -114,13 +114,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, | |||
114 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | 114 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); |
115 | 115 | ||
116 | IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name); | 116 | IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name); |
117 | ret = wait_event_interruptible_timeout(priv->shrd->wait_command_queue, | 117 | ret = wait_event_timeout(priv->shrd->wait_command_queue, |
118 | priv->ucode_write_complete, 5 * HZ); | 118 | priv->ucode_write_complete, 5 * HZ); |
119 | if (ret == -ERESTARTSYS) { | ||
120 | IWL_ERR(priv, "Could not load the %s uCode section due " | ||
121 | "to interrupt\n", name); | ||
122 | return ret; | ||
123 | } | ||
124 | if (!ret) { | 119 | if (!ret) { |
125 | IWL_ERR(priv, "Could not load the %s uCode section\n", | 120 | IWL_ERR(priv, "Could not load the %s uCode section\n", |
126 | name); | 121 | name); |
@@ -164,7 +159,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) | |||
164 | { | 159 | { |
165 | struct iwl_calib_temperature_offset_cmd cmd; | 160 | struct iwl_calib_temperature_offset_cmd cmd; |
166 | __le16 *offset_calib = | 161 | __le16 *offset_calib = |
167 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE); | 162 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); |
168 | 163 | ||
169 | memset(&cmd, 0, sizeof(cmd)); | 164 | memset(&cmd, 0, sizeof(cmd)); |
170 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 165 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); |
@@ -178,6 +173,42 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) | |||
178 | (u8 *)&cmd, sizeof(cmd)); | 173 | (u8 *)&cmd, sizeof(cmd)); |
179 | } | 174 | } |
180 | 175 | ||
176 | static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) | ||
177 | { | ||
178 | struct iwl_calib_temperature_offset_v2_cmd cmd; | ||
179 | __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, | ||
180 | EEPROM_KELVIN_TEMPERATURE); | ||
181 | __le16 *offset_calib_low = | ||
182 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); | ||
183 | struct iwl_eeprom_calib_hdr *hdr; | ||
184 | |||
185 | memset(&cmd, 0, sizeof(cmd)); | ||
186 | iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | ||
187 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
188 | EEPROM_CALIB_ALL); | ||
189 | memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, | ||
190 | sizeof(*offset_calib_high)); | ||
191 | memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, | ||
192 | sizeof(*offset_calib_low)); | ||
193 | if (!(cmd.radio_sensor_offset_low)) { | ||
194 | IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); | ||
195 | cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; | ||
196 | cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; | ||
197 | } | ||
198 | memcpy(&cmd.burntVoltageRef, &hdr->voltage, | ||
199 | sizeof(hdr->voltage)); | ||
200 | |||
201 | IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", | ||
202 | le16_to_cpu(cmd.radio_sensor_offset_high)); | ||
203 | IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n", | ||
204 | le16_to_cpu(cmd.radio_sensor_offset_low)); | ||
205 | IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", | ||
206 | le16_to_cpu(cmd.burntVoltageRef)); | ||
207 | |||
208 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], | ||
209 | (u8 *)&cmd, sizeof(cmd)); | ||
210 | } | ||
211 | |||
181 | static int iwlagn_send_calib_cfg(struct iwl_priv *priv) | 212 | static int iwlagn_send_calib_cfg(struct iwl_priv *priv) |
182 | { | 213 | { |
183 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | 214 | struct iwl_calib_cfg_cmd calib_cfg_cmd; |
@@ -197,8 +228,9 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) | |||
197 | return iwl_trans_send_cmd(trans(priv), &cmd); | 228 | return iwl_trans_send_cmd(trans(priv), &cmd); |
198 | } | 229 | } |
199 | 230 | ||
200 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | 231 | int iwlagn_rx_calib_result(struct iwl_priv *priv, |
201 | struct iwl_rx_mem_buffer *rxb) | 232 | struct iwl_rx_mem_buffer *rxb, |
233 | struct iwl_device_cmd *cmd) | ||
202 | { | 234 | { |
203 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 235 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
204 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | 236 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; |
@@ -231,9 +263,10 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv, | |||
231 | default: | 263 | default: |
232 | IWL_ERR(priv, "Unknown calibration notification %d\n", | 264 | IWL_ERR(priv, "Unknown calibration notification %d\n", |
233 | hdr->op_code); | 265 | hdr->op_code); |
234 | return; | 266 | return -1; |
235 | } | 267 | } |
236 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | 268 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); |
269 | return 0; | ||
237 | } | 270 | } |
238 | 271 | ||
239 | int iwlagn_init_alive_start(struct iwl_priv *priv) | 272 | int iwlagn_init_alive_start(struct iwl_priv *priv) |
@@ -263,8 +296,12 @@ int iwlagn_init_alive_start(struct iwl_priv *priv) | |||
263 | * temperature offset calibration is only needed for runtime ucode, | 296 | * temperature offset calibration is only needed for runtime ucode, |
264 | * so prepare the value now. | 297 | * so prepare the value now. |
265 | */ | 298 | */ |
266 | if (priv->cfg->need_temp_offset_calib) | 299 | if (priv->cfg->need_temp_offset_calib) { |
267 | return iwlagn_set_temperature_offset_calib(priv); | 300 | if (priv->cfg->temp_offset_v2) |
301 | return iwlagn_set_temperature_offset_calib_v2(priv); | ||
302 | else | ||
303 | return iwlagn_set_temperature_offset_calib(priv); | ||
304 | } | ||
268 | 305 | ||
269 | return 0; | 306 | return 0; |
270 | } | 307 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6057e18f688c..baaf48616cc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -453,122 +453,6 @@ static void iwl_bg_tx_flush(struct work_struct *work) | |||
453 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); | 453 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); |
454 | } | 454 | } |
455 | 455 | ||
456 | /***************************************************************************** | ||
457 | * | ||
458 | * sysfs attributes | ||
459 | * | ||
460 | *****************************************************************************/ | ||
461 | |||
462 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
463 | |||
464 | /* | ||
465 | * The following adds a new attribute to the sysfs representation | ||
466 | * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) | ||
467 | * used for controlling the debug level. | ||
468 | * | ||
469 | * See the level definitions in iwl for details. | ||
470 | * | ||
471 | * The debug_level being managed using sysfs below is a per device debug | ||
472 | * level that is used instead of the global debug level if it (the per | ||
473 | * device debug level) is set. | ||
474 | */ | ||
475 | static ssize_t show_debug_level(struct device *d, | ||
476 | struct device_attribute *attr, char *buf) | ||
477 | { | ||
478 | struct iwl_shared *shrd = dev_get_drvdata(d); | ||
479 | return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd)); | ||
480 | } | ||
481 | static ssize_t store_debug_level(struct device *d, | ||
482 | struct device_attribute *attr, | ||
483 | const char *buf, size_t count) | ||
484 | { | ||
485 | struct iwl_shared *shrd = dev_get_drvdata(d); | ||
486 | struct iwl_priv *priv = shrd->priv; | ||
487 | unsigned long val; | ||
488 | int ret; | ||
489 | |||
490 | ret = strict_strtoul(buf, 0, &val); | ||
491 | if (ret) | ||
492 | IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); | ||
493 | else { | ||
494 | shrd->dbg_level_dev = val; | ||
495 | if (iwl_alloc_traffic_mem(priv)) | ||
496 | IWL_ERR(shrd->priv, | ||
497 | "Not enough memory to generate traffic log\n"); | ||
498 | } | ||
499 | return strnlen(buf, count); | ||
500 | } | ||
501 | |||
502 | static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, | ||
503 | show_debug_level, store_debug_level); | ||
504 | |||
505 | |||
506 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
507 | |||
508 | |||
509 | static ssize_t show_temperature(struct device *d, | ||
510 | struct device_attribute *attr, char *buf) | ||
511 | { | ||
512 | struct iwl_shared *shrd = dev_get_drvdata(d); | ||
513 | struct iwl_priv *priv = shrd->priv; | ||
514 | |||
515 | if (!iwl_is_alive(priv->shrd)) | ||
516 | return -EAGAIN; | ||
517 | |||
518 | return sprintf(buf, "%d\n", priv->temperature); | ||
519 | } | ||
520 | |||
521 | static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); | ||
522 | |||
523 | static ssize_t show_tx_power(struct device *d, | ||
524 | struct device_attribute *attr, char *buf) | ||
525 | { | ||
526 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
527 | |||
528 | if (!iwl_is_ready_rf(priv->shrd)) | ||
529 | return sprintf(buf, "off\n"); | ||
530 | else | ||
531 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | ||
532 | } | ||
533 | |||
534 | static ssize_t store_tx_power(struct device *d, | ||
535 | struct device_attribute *attr, | ||
536 | const char *buf, size_t count) | ||
537 | { | ||
538 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
539 | unsigned long val; | ||
540 | int ret; | ||
541 | |||
542 | ret = strict_strtoul(buf, 10, &val); | ||
543 | if (ret) | ||
544 | IWL_INFO(priv, "%s is not in decimal form.\n", buf); | ||
545 | else { | ||
546 | ret = iwl_set_tx_power(priv, val, false); | ||
547 | if (ret) | ||
548 | IWL_ERR(priv, "failed setting tx power (0x%d).\n", | ||
549 | ret); | ||
550 | else | ||
551 | ret = count; | ||
552 | } | ||
553 | return ret; | ||
554 | } | ||
555 | |||
556 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | ||
557 | |||
558 | static struct attribute *iwl_sysfs_entries[] = { | ||
559 | &dev_attr_temperature.attr, | ||
560 | &dev_attr_tx_power.attr, | ||
561 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
562 | &dev_attr_debug_level.attr, | ||
563 | #endif | ||
564 | NULL | ||
565 | }; | ||
566 | |||
567 | static struct attribute_group iwl_attribute_group = { | ||
568 | .name = NULL, /* put in device directory */ | ||
569 | .attrs = iwl_sysfs_entries, | ||
570 | }; | ||
571 | |||
572 | /****************************************************************************** | 456 | /****************************************************************************** |
573 | * | 457 | * |
574 | * uCode download functions | 458 | * uCode download functions |
@@ -1259,13 +1143,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1259 | if (err) | 1143 | if (err) |
1260 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | 1144 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); |
1261 | 1145 | ||
1262 | err = sysfs_create_group(&(priv->bus->dev->kobj), | ||
1263 | &iwl_attribute_group); | ||
1264 | if (err) { | ||
1265 | IWL_ERR(priv, "failed to create sysfs device attributes\n"); | ||
1266 | goto out_unbind; | ||
1267 | } | ||
1268 | |||
1269 | /* We have our copies now, allow OS release its copies */ | 1146 | /* We have our copies now, allow OS release its copies */ |
1270 | release_firmware(ucode_raw); | 1147 | release_firmware(ucode_raw); |
1271 | complete(&priv->firmware_loading_complete); | 1148 | complete(&priv->firmware_loading_complete); |
@@ -1519,9 +1396,11 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1519 | if (!exit_pending) | 1396 | if (!exit_pending) |
1520 | clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); | 1397 | clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); |
1521 | 1398 | ||
1522 | if (priv->shrd->mac80211_registered) | 1399 | if (priv->mac80211_registered) |
1523 | ieee80211_stop_queues(priv->hw); | 1400 | ieee80211_stop_queues(priv->hw); |
1524 | 1401 | ||
1402 | iwl_trans_stop_device(trans(priv)); | ||
1403 | |||
1525 | /* Clear out all status bits but a few that are stable across reset */ | 1404 | /* Clear out all status bits but a few that are stable across reset */ |
1526 | priv->shrd->status &= | 1405 | priv->shrd->status &= |
1527 | test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) << | 1406 | test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) << |
@@ -1533,8 +1412,6 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1533 | test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) << | 1412 | test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) << |
1534 | STATUS_EXIT_PENDING; | 1413 | STATUS_EXIT_PENDING; |
1535 | 1414 | ||
1536 | iwl_trans_stop_device(trans(priv)); | ||
1537 | |||
1538 | dev_kfree_skb(priv->beacon_skb); | 1415 | dev_kfree_skb(priv->beacon_skb); |
1539 | priv->beacon_skb = NULL; | 1416 | priv->beacon_skb = NULL; |
1540 | } | 1417 | } |
@@ -1868,7 +1745,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
1868 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | 1745 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); |
1869 | return ret; | 1746 | return ret; |
1870 | } | 1747 | } |
1871 | priv->shrd->mac80211_registered = 1; | 1748 | priv->mac80211_registered = 1; |
1872 | 1749 | ||
1873 | return 0; | 1750 | return 0; |
1874 | } | 1751 | } |
@@ -1924,7 +1801,7 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) | |||
1924 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1801 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1925 | } | 1802 | } |
1926 | 1803 | ||
1927 | #ifdef CONFIG_PM | 1804 | #ifdef CONFIG_PM_SLEEP |
1928 | static int iwlagn_send_patterns(struct iwl_priv *priv, | 1805 | static int iwlagn_send_patterns(struct iwl_priv *priv, |
1929 | struct cfg80211_wowlan *wowlan) | 1806 | struct cfg80211_wowlan *wowlan) |
1930 | { | 1807 | { |
@@ -1999,7 +1876,7 @@ struct wowlan_key_data { | |||
1999 | bool error, use_rsc_tsc, use_tkip; | 1876 | bool error, use_rsc_tsc, use_tkip; |
2000 | }; | 1877 | }; |
2001 | 1878 | ||
2002 | #ifdef CONFIG_PM | 1879 | #ifdef CONFIG_PM_SLEEP |
2003 | static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) | 1880 | static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) |
2004 | { | 1881 | { |
2005 | int i; | 1882 | int i; |
@@ -2636,7 +2513,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
2636 | mutex_lock(&priv->shrd->mutex); | 2513 | mutex_lock(&priv->shrd->mutex); |
2637 | IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", | 2514 | IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", |
2638 | sta->addr); | 2515 | sta->addr); |
2639 | sta_priv->common.sta_id = IWL_INVALID_STATION; | 2516 | sta_priv->sta_id = IWL_INVALID_STATION; |
2640 | 2517 | ||
2641 | atomic_set(&sta_priv->pending_frames, 0); | 2518 | atomic_set(&sta_priv->pending_frames, 0); |
2642 | if (vif->type == NL80211_IFTYPE_AP) | 2519 | if (vif->type == NL80211_IFTYPE_AP) |
@@ -2652,7 +2529,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
2652 | return ret; | 2529 | return ret; |
2653 | } | 2530 | } |
2654 | 2531 | ||
2655 | sta_priv->common.sta_id = sta_id; | 2532 | sta_priv->sta_id = sta_id; |
2656 | 2533 | ||
2657 | /* Initialize rate scaling */ | 2534 | /* Initialize rate scaling */ |
2658 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | 2535 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", |
@@ -2893,15 +2770,6 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
2893 | 2770 | ||
2894 | mutex_lock(&priv->shrd->mutex); | 2771 | mutex_lock(&priv->shrd->mutex); |
2895 | 2772 | ||
2896 | /* | ||
2897 | * TODO: Remove this hack! Firmware needs to be updated | ||
2898 | * to allow longer off-channel periods in scanning for | ||
2899 | * this use case, based on a flag (and we'll need an API | ||
2900 | * flag in the firmware when it has that). | ||
2901 | */ | ||
2902 | if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80) | ||
2903 | duration = 80; | ||
2904 | |||
2905 | if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { | 2773 | if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { |
2906 | err = -EBUSY; | 2774 | err = -EBUSY; |
2907 | goto out; | 2775 | goto out; |
@@ -2910,6 +2778,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
2910 | priv->hw_roc_channel = channel; | 2778 | priv->hw_roc_channel = channel; |
2911 | priv->hw_roc_chantype = channel_type; | 2779 | priv->hw_roc_chantype = channel_type; |
2912 | priv->hw_roc_duration = duration; | 2780 | priv->hw_roc_duration = duration; |
2781 | priv->hw_roc_start_notified = false; | ||
2913 | cancel_delayed_work(&priv->hw_roc_disable_work); | 2782 | cancel_delayed_work(&priv->hw_roc_disable_work); |
2914 | 2783 | ||
2915 | if (!ctx->is_active) { | 2784 | if (!ctx->is_active) { |
@@ -3208,7 +3077,7 @@ struct ieee80211_ops iwlagn_hw_ops = { | |||
3208 | .tx = iwlagn_mac_tx, | 3077 | .tx = iwlagn_mac_tx, |
3209 | .start = iwlagn_mac_start, | 3078 | .start = iwlagn_mac_start, |
3210 | .stop = iwlagn_mac_stop, | 3079 | .stop = iwlagn_mac_stop, |
3211 | #ifdef CONFIG_PM | 3080 | #ifdef CONFIG_PM_SLEEP |
3212 | .suspend = iwlagn_mac_suspend, | 3081 | .suspend = iwlagn_mac_suspend, |
3213 | .resume = iwlagn_mac_resume, | 3082 | .resume = iwlagn_mac_resume, |
3214 | #endif | 3083 | #endif |
@@ -3314,10 +3183,9 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | |||
3314 | priv = hw->priv; | 3183 | priv = hw->priv; |
3315 | priv->bus = bus; | 3184 | priv->bus = bus; |
3316 | priv->shrd = &priv->_shrd; | 3185 | priv->shrd = &priv->_shrd; |
3186 | bus->shrd = priv->shrd; | ||
3317 | priv->shrd->bus = bus; | 3187 | priv->shrd->bus = bus; |
3318 | priv->shrd->priv = priv; | 3188 | priv->shrd->priv = priv; |
3319 | priv->shrd->hw = hw; | ||
3320 | bus_set_drv_data(priv->bus, priv->shrd); | ||
3321 | 3189 | ||
3322 | priv->shrd->trans = trans_ops->alloc(priv->shrd); | 3190 | priv->shrd->trans = trans_ops->alloc(priv->shrd); |
3323 | if (priv->shrd->trans == NULL) { | 3191 | if (priv->shrd->trans == NULL) { |
@@ -3480,8 +3348,6 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
3480 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); | 3348 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); |
3481 | 3349 | ||
3482 | iwl_dbgfs_unregister(priv); | 3350 | iwl_dbgfs_unregister(priv); |
3483 | sysfs_remove_group(&priv->bus->dev->kobj, | ||
3484 | &iwl_attribute_group); | ||
3485 | 3351 | ||
3486 | /* ieee80211_unregister_hw call wil cause iwl_mac_stop to | 3352 | /* ieee80211_unregister_hw call wil cause iwl_mac_stop to |
3487 | * to be called and iwl_down since we are removing the device | 3353 | * to be called and iwl_down since we are removing the device |
@@ -3492,9 +3358,9 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
3492 | iwl_testmode_cleanup(priv); | 3358 | iwl_testmode_cleanup(priv); |
3493 | iwl_leds_exit(priv); | 3359 | iwl_leds_exit(priv); |
3494 | 3360 | ||
3495 | if (priv->shrd->mac80211_registered) { | 3361 | if (priv->mac80211_registered) { |
3496 | ieee80211_unregister_hw(priv->hw); | 3362 | ieee80211_unregister_hw(priv->hw); |
3497 | priv->shrd->mac80211_registered = 0; | 3363 | priv->mac80211_registered = 0; |
3498 | } | 3364 | } |
3499 | 3365 | ||
3500 | iwl_tt_exit(priv); | 3366 | iwl_tt_exit(priv); |
@@ -3518,8 +3384,6 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
3518 | 3384 | ||
3519 | iwl_trans_free(trans(priv)); | 3385 | iwl_trans_free(trans(priv)); |
3520 | 3386 | ||
3521 | bus_set_drv_data(priv->bus, NULL); | ||
3522 | |||
3523 | iwl_uninit_drv(priv); | 3387 | iwl_uninit_drv(priv); |
3524 | 3388 | ||
3525 | dev_kfree_skb(priv->beacon_skb); | 3389 | dev_kfree_skb(priv->beacon_skb); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 4bc1f4669e5a..2a297d1e6bc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -88,8 +88,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
88 | u32 changes); | 88 | u32 changes); |
89 | 89 | ||
90 | /* uCode */ | 90 | /* uCode */ |
91 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | 91 | int iwlagn_rx_calib_result(struct iwl_priv *priv, |
92 | struct iwl_rx_mem_buffer *rxb); | 92 | struct iwl_rx_mem_buffer *rxb, |
93 | struct iwl_device_cmd *cmd); | ||
93 | int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | 94 | int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); |
94 | void iwlagn_send_prio_tbl(struct iwl_priv *priv); | 95 | void iwlagn_send_prio_tbl(struct iwl_priv *priv); |
95 | int iwlagn_run_init_ucode(struct iwl_priv *priv); | 96 | int iwlagn_run_init_ucode(struct iwl_priv *priv); |
@@ -116,9 +117,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
116 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 117 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); |
117 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | 118 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, |
118 | struct ieee80211_sta *sta, u16 tid); | 119 | struct ieee80211_sta *sta, u16 tid); |
119 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | 120 | int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, |
120 | struct iwl_rx_mem_buffer *rxb); | 121 | struct iwl_rx_mem_buffer *rxb, |
121 | void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 122 | struct iwl_device_cmd *cmd); |
123 | int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, | ||
124 | struct iwl_device_cmd *cmd); | ||
122 | 125 | ||
123 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | 126 | static inline u32 iwl_tx_status_to_mac80211(u32 status) |
124 | { | 127 | { |
@@ -146,7 +149,6 @@ static inline bool iwl_is_tx_success(u32 status) | |||
146 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); | 149 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); |
147 | 150 | ||
148 | /* scan */ | 151 | /* scan */ |
149 | int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
150 | void iwlagn_post_scan(struct iwl_priv *priv); | 152 | void iwlagn_post_scan(struct iwl_priv *priv); |
151 | void iwlagn_disable_roc(struct iwl_priv *priv); | 153 | void iwlagn_disable_roc(struct iwl_priv *priv); |
152 | 154 | ||
@@ -156,8 +158,9 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
156 | 158 | ||
157 | /* bt coex */ | 159 | /* bt coex */ |
158 | void iwlagn_send_advance_bt_config(struct iwl_priv *priv); | 160 | void iwlagn_send_advance_bt_config(struct iwl_priv *priv); |
159 | void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, | 161 | int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, |
160 | struct iwl_rx_mem_buffer *rxb); | 162 | struct iwl_rx_mem_buffer *rxb, |
163 | struct iwl_device_cmd *cmd); | ||
161 | void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv); | 164 | void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv); |
162 | void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); | 165 | void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); |
163 | void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); | 166 | void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 83aed46673e1..08b97594e305 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h | |||
@@ -63,19 +63,65 @@ | |||
63 | #ifndef __iwl_bus_h__ | 63 | #ifndef __iwl_bus_h__ |
64 | #define __iwl_bus_h__ | 64 | #define __iwl_bus_h__ |
65 | 65 | ||
66 | /*This file includes the declaration that are exported from the bus layer */ | ||
67 | |||
68 | #include <linux/types.h> | 66 | #include <linux/types.h> |
69 | #include <linux/spinlock.h> | 67 | #include <linux/spinlock.h> |
70 | 68 | ||
69 | /** | ||
70 | * DOC: Bus layer - role and goal | ||
71 | * | ||
72 | * iwl-bus.h defines the API to the bus layer of the iwlwifi driver. | ||
73 | * The bus layer is responsible for doing very basic bus operations that are | ||
74 | * listed in the iwl_bus_ops structure. | ||
75 | * The bus layer registers to the bus driver, advertises the supported HW and | ||
76 | * gets notifications about enumeration, suspend, resume. | ||
77 | * For the moment, the bus layer is not a linux kernel module as itself, and | ||
78 | * the module_init function of the driver must call the bus specific | ||
79 | * registration functions. These functions are listed at the end of this file. | ||
80 | * For the moment, there is only one implementation of this interface: PCI-e. | ||
81 | * This implementation is iwl-pci.c | ||
82 | */ | ||
83 | |||
84 | /** | ||
85 | * DOC: encapsulation and type safety | ||
86 | * | ||
87 | * The iwl_bus describes the data that is shared amongst all the bus layer | ||
88 | * implementations. This data is visible to other layers. Data in the bus | ||
89 | * specific area is not visible outside the bus specific implementation. | ||
90 | * iwl_bus holds a pointer to iwl_shared which holds pointer to all the other | ||
91 | * layers of the driver (iwl_priv, iwl_trans). In fact, this is the way to go | ||
92 | * when the transport layer needs to call a function of another layer. | ||
93 | * | ||
94 | * In order to achieve encapsulation, iwl_priv cannot be dereferenced from the | ||
95 | * bus layer. Type safety is still kept since functions that gets iwl_priv gets | ||
96 | * a typed pointer (as opposed to void *). | ||
97 | */ | ||
98 | |||
99 | /** | ||
100 | * DOC: probe flow | ||
101 | * | ||
102 | * The module_init calls the bus specific registration function. The | ||
103 | * registration to the bus layer will trigger an enumeration of the bus which | ||
104 | * will call the bus specific probe function. | ||
105 | * The first thing this function must do is to allocate the memory needed by | ||
106 | * iwl_bus + the bus_specific data. | ||
107 | * Once the bus specific probe function has configured the hardware, it | ||
108 | * chooses the appropriate transport layer and calls iwl_probe that will run | ||
109 | * the bus independent probe flow. | ||
110 | * | ||
111 | * Note: The bus specific code must set the following data in iwl_bus before it | ||
112 | * calls iwl_probe: | ||
113 | * * bus->dev | ||
114 | * * bus->irq | ||
115 | * * bus->ops | ||
116 | */ | ||
117 | |||
71 | struct iwl_shared; | 118 | struct iwl_shared; |
72 | struct iwl_bus; | 119 | struct iwl_bus; |
73 | 120 | ||
74 | /** | 121 | /** |
75 | * struct iwl_bus_ops - bus specific operations | 122 | * struct iwl_bus_ops - bus specific operations |
76 | * @get_pm_support: must returns true if the bus can go to sleep | 123 | * @get_pm_support: must returns true if the bus can go to sleep |
77 | * @apm_config: will be called during the config of the APM configuration | 124 | * @apm_config: will be called during the config of the APM |
78 | * @set_drv_data: set the shared data pointer to the bus layer | ||
79 | * @get_hw_id: prints the hw_id in the provided buffer | 125 | * @get_hw_id: prints the hw_id in the provided buffer |
80 | * @write8: write a byte to register at offset ofs | 126 | * @write8: write a byte to register at offset ofs |
81 | * @write32: write a dword to register at offset ofs | 127 | * @write32: write a dword to register at offset ofs |
@@ -84,7 +130,6 @@ struct iwl_bus; | |||
84 | struct iwl_bus_ops { | 130 | struct iwl_bus_ops { |
85 | bool (*get_pm_support)(struct iwl_bus *bus); | 131 | bool (*get_pm_support)(struct iwl_bus *bus); |
86 | void (*apm_config)(struct iwl_bus *bus); | 132 | void (*apm_config)(struct iwl_bus *bus); |
87 | void (*set_drv_data)(struct iwl_bus *bus, struct iwl_shared *shrd); | ||
88 | void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); | 133 | void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); |
89 | void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); | 134 | void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); |
90 | void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); | 135 | void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); |
@@ -93,14 +138,18 @@ struct iwl_bus_ops { | |||
93 | 138 | ||
94 | /** | 139 | /** |
95 | * struct iwl_bus - bus common data | 140 | * struct iwl_bus - bus common data |
96 | * @dev - pointer to struct device * that represent the device | 141 | * |
142 | * This data is common to all bus layer implementations. | ||
143 | * | ||
144 | * @dev - pointer to struct device * that represents the device | ||
97 | * @ops - pointer to iwl_bus_ops | 145 | * @ops - pointer to iwl_bus_ops |
98 | * @shrd - pointer to iwl_shared which holds shared data from the upper layer | 146 | * @shrd - pointer to iwl_shared which holds shared data from the upper layer |
147 | * NB: for the time being this needs to be set by the upper layer since | ||
148 | * it allocates the shared data | ||
99 | * @irq - the irq number for the device | 149 | * @irq - the irq number for the device |
100 | * @reg_lock - protect hw register access | 150 | * @reg_lock - protect hw register access |
101 | */ | 151 | */ |
102 | struct iwl_bus { | 152 | struct iwl_bus { |
103 | /* Common data to all buses */ | ||
104 | struct device *dev; | 153 | struct device *dev; |
105 | const struct iwl_bus_ops *ops; | 154 | const struct iwl_bus_ops *ops; |
106 | struct iwl_shared *shrd; | 155 | struct iwl_shared *shrd; |
@@ -123,12 +172,6 @@ static inline void bus_apm_config(struct iwl_bus *bus) | |||
123 | bus->ops->apm_config(bus); | 172 | bus->ops->apm_config(bus); |
124 | } | 173 | } |
125 | 174 | ||
126 | static inline void bus_set_drv_data(struct iwl_bus *bus, | ||
127 | struct iwl_shared *shrd) | ||
128 | { | ||
129 | bus->ops->set_drv_data(bus, shrd); | ||
130 | } | ||
131 | |||
132 | static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) | 175 | static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) |
133 | { | 176 | { |
134 | bus->ops->get_hw_id(bus, buf, buf_len); | 177 | bus->ops->get_hw_id(bus, buf, buf_len); |
@@ -149,6 +192,9 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) | |||
149 | return bus->ops->read32(bus, ofs); | 192 | return bus->ops->read32(bus, ofs); |
150 | } | 193 | } |
151 | 194 | ||
195 | /***************************************************** | ||
196 | * Bus layer registration functions | ||
197 | ******************************************************/ | ||
152 | int __must_check iwl_pci_register_driver(void); | 198 | int __must_check iwl_pci_register_driver(void); |
153 | void iwl_pci_unregister_driver(void); | 199 | void iwl_pci_unregister_driver(void); |
154 | 200 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h index c0aea9e092cb..d4f317cfe8b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.h +++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h | |||
@@ -64,11 +64,10 @@ | |||
64 | #define __iwl_pci_h__ | 64 | #define __iwl_pci_h__ |
65 | 65 | ||
66 | 66 | ||
67 | /* This file includes the declaration that are internal to the PCI | 67 | /* |
68 | * implementation of the bus layer | 68 | * This file declares the config structures for all devices. |
69 | */ | 69 | */ |
70 | 70 | ||
71 | /* configuration for the _agn devices */ | ||
72 | extern struct iwl_cfg iwl5300_agn_cfg; | 71 | extern struct iwl_cfg iwl5300_agn_cfg; |
73 | extern struct iwl_cfg iwl5100_agn_cfg; | 72 | extern struct iwl_cfg iwl5100_agn_cfg; |
74 | extern struct iwl_cfg iwl5350_agn_cfg; | 73 | extern struct iwl_cfg iwl5350_agn_cfg; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 82bfef4730d5..64593aa03ad6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -3263,6 +3263,14 @@ struct iwl_calib_temperature_offset_cmd { | |||
3263 | __le16 reserved; | 3263 | __le16 reserved; |
3264 | } __packed; | 3264 | } __packed; |
3265 | 3265 | ||
3266 | struct iwl_calib_temperature_offset_v2_cmd { | ||
3267 | struct iwl_calib_hdr hdr; | ||
3268 | __le16 radio_sensor_offset_high; | ||
3269 | __le16 radio_sensor_offset_low; | ||
3270 | __le16 burntVoltageRef; | ||
3271 | __le16 reserved; | ||
3272 | } __packed; | ||
3273 | |||
3266 | /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */ | 3274 | /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */ |
3267 | struct iwl_calib_chain_noise_reset_cmd { | 3275 | struct iwl_calib_chain_noise_reset_cmd { |
3268 | struct iwl_calib_hdr hdr; | 3276 | struct iwl_calib_hdr hdr; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9270f990b2dd..fc400bb2bdff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -125,12 +125,12 @@ int iwl_init_geos(struct iwl_priv *priv) | |||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
127 | 127 | ||
128 | channels = kzalloc(sizeof(struct ieee80211_channel) * | 128 | channels = kcalloc(priv->channel_count, |
129 | priv->channel_count, GFP_KERNEL); | 129 | sizeof(struct ieee80211_channel), GFP_KERNEL); |
130 | if (!channels) | 130 | if (!channels) |
131 | return -ENOMEM; | 131 | return -ENOMEM; |
132 | 132 | ||
133 | rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY), | 133 | rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), |
134 | GFP_KERNEL); | 134 | GFP_KERNEL); |
135 | if (!rates) { | 135 | if (!rates) { |
136 | kfree(channels); | 136 | kfree(channels); |
@@ -817,7 +817,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | |||
817 | } | 817 | } |
818 | 818 | ||
819 | #ifdef CONFIG_IWLWIFI_DEBUG | 819 | #ifdef CONFIG_IWLWIFI_DEBUG |
820 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid) | 820 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, |
821 | enum iwl_rxon_context_id ctxid) | ||
821 | { | 822 | { |
822 | struct iwl_rxon_context *ctx = &priv->contexts[ctxid]; | 823 | struct iwl_rxon_context *ctx = &priv->contexts[ctxid]; |
823 | struct iwl_rxon_cmd *rxon = &ctx->staging; | 824 | struct iwl_rxon_cmd *rxon = &ctx->staging; |
@@ -868,7 +869,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
868 | * commands by clearing the ready bit */ | 869 | * commands by clearing the ready bit */ |
869 | clear_bit(STATUS_READY, &priv->shrd->status); | 870 | clear_bit(STATUS_READY, &priv->shrd->status); |
870 | 871 | ||
871 | wake_up_interruptible(&priv->shrd->wait_command_queue); | 872 | wake_up(&priv->shrd->wait_command_queue); |
872 | 873 | ||
873 | if (!ondemand) { | 874 | if (!ondemand) { |
874 | /* | 875 | /* |
@@ -1327,7 +1328,13 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
1327 | 1328 | ||
1328 | mutex_lock(&priv->shrd->mutex); | 1329 | mutex_lock(&priv->shrd->mutex); |
1329 | 1330 | ||
1330 | WARN_ON(ctx->vif != vif); | 1331 | if (WARN_ON(ctx->vif != vif)) { |
1332 | struct iwl_rxon_context *tmp; | ||
1333 | IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif); | ||
1334 | for_each_context(priv, tmp) | ||
1335 | IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n", | ||
1336 | tmp->ctxid, tmp, tmp->vif); | ||
1337 | } | ||
1331 | ctx->vif = NULL; | 1338 | ctx->vif = NULL; |
1332 | 1339 | ||
1333 | iwl_teardown_interface(priv, vif, false); | 1340 | iwl_teardown_interface(priv, vif, false); |
@@ -1802,13 +1809,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) | |||
1802 | return 0; | 1809 | return 0; |
1803 | 1810 | ||
1804 | quot = (usec / interval) & | 1811 | quot = (usec / interval) & |
1805 | (iwl_beacon_time_mask_high(priv, | 1812 | (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >> |
1806 | hw_params(priv).beacon_time_tsf_bits) >> | 1813 | IWLAGN_EXT_BEACON_TIME_POS); |
1807 | hw_params(priv).beacon_time_tsf_bits); | ||
1808 | rem = (usec % interval) & iwl_beacon_time_mask_low(priv, | 1814 | rem = (usec % interval) & iwl_beacon_time_mask_low(priv, |
1809 | hw_params(priv).beacon_time_tsf_bits); | 1815 | IWLAGN_EXT_BEACON_TIME_POS); |
1810 | 1816 | ||
1811 | return (quot << hw_params(priv).beacon_time_tsf_bits) + rem; | 1817 | return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem; |
1812 | } | 1818 | } |
1813 | 1819 | ||
1814 | /* base is usually what we get from ucode with each received frame, | 1820 | /* base is usually what we get from ucode with each received frame, |
@@ -1818,22 +1824,22 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | |||
1818 | u32 addon, u32 beacon_interval) | 1824 | u32 addon, u32 beacon_interval) |
1819 | { | 1825 | { |
1820 | u32 base_low = base & iwl_beacon_time_mask_low(priv, | 1826 | u32 base_low = base & iwl_beacon_time_mask_low(priv, |
1821 | hw_params(priv).beacon_time_tsf_bits); | 1827 | IWLAGN_EXT_BEACON_TIME_POS); |
1822 | u32 addon_low = addon & iwl_beacon_time_mask_low(priv, | 1828 | u32 addon_low = addon & iwl_beacon_time_mask_low(priv, |
1823 | hw_params(priv).beacon_time_tsf_bits); | 1829 | IWLAGN_EXT_BEACON_TIME_POS); |
1824 | u32 interval = beacon_interval * TIME_UNIT; | 1830 | u32 interval = beacon_interval * TIME_UNIT; |
1825 | u32 res = (base & iwl_beacon_time_mask_high(priv, | 1831 | u32 res = (base & iwl_beacon_time_mask_high(priv, |
1826 | hw_params(priv).beacon_time_tsf_bits)) + | 1832 | IWLAGN_EXT_BEACON_TIME_POS)) + |
1827 | (addon & iwl_beacon_time_mask_high(priv, | 1833 | (addon & iwl_beacon_time_mask_high(priv, |
1828 | hw_params(priv).beacon_time_tsf_bits)); | 1834 | IWLAGN_EXT_BEACON_TIME_POS)); |
1829 | 1835 | ||
1830 | if (base_low > addon_low) | 1836 | if (base_low > addon_low) |
1831 | res += base_low - addon_low; | 1837 | res += base_low - addon_low; |
1832 | else if (base_low < addon_low) { | 1838 | else if (base_low < addon_low) { |
1833 | res += interval + base_low - addon_low; | 1839 | res += interval + base_low - addon_low; |
1834 | res += (1 << hw_params(priv).beacon_time_tsf_bits); | 1840 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); |
1835 | } else | 1841 | } else |
1836 | res += (1 << hw_params(priv).beacon_time_tsf_bits); | 1842 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); |
1837 | 1843 | ||
1838 | return cpu_to_le32(res); | 1844 | return cpu_to_le32(res); |
1839 | } | 1845 | } |
@@ -1876,3 +1882,22 @@ void iwl_nic_config(struct iwl_priv *priv) | |||
1876 | priv->cfg->lib->nic_config(priv); | 1882 | priv->cfg->lib->nic_config(priv); |
1877 | 1883 | ||
1878 | } | 1884 | } |
1885 | |||
1886 | void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
1887 | { | ||
1888 | struct ieee80211_tx_info *info; | ||
1889 | |||
1890 | info = IEEE80211_SKB_CB(skb); | ||
1891 | kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); | ||
1892 | dev_kfree_skb_any(skb); | ||
1893 | } | ||
1894 | |||
1895 | void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac) | ||
1896 | { | ||
1897 | ieee80211_stop_queue(priv->hw, ac); | ||
1898 | } | ||
1899 | |||
1900 | void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac) | ||
1901 | { | ||
1902 | ieee80211_wake_queue(priv->hw, ac); | ||
1903 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 56b554c43fde..e55ffad83950 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -108,7 +108,6 @@ struct iwl_lib_ops { | |||
108 | * radio tuning when there is a high receiving plcp error rate | 108 | * radio tuning when there is a high receiving plcp error rate |
109 | * @chain_noise_scale: default chain noise scale used for gain computation | 109 | * @chain_noise_scale: default chain noise scale used for gain computation |
110 | * @wd_timeout: TX queues watchdog timeout | 110 | * @wd_timeout: TX queues watchdog timeout |
111 | * @temperature_kelvin: temperature report by uCode in kelvin | ||
112 | * @max_event_log_size: size of event log buffer size for ucode event logging | 111 | * @max_event_log_size: size of event log buffer size for ucode event logging |
113 | * @shadow_reg_enable: HW shadhow register bit | 112 | * @shadow_reg_enable: HW shadhow register bit |
114 | * @no_idle_support: do not support idle mode | 113 | * @no_idle_support: do not support idle mode |
@@ -124,14 +123,12 @@ struct iwl_base_params { | |||
124 | const u16 max_ll_items; | 123 | const u16 max_ll_items; |
125 | const bool shadow_ram_support; | 124 | const bool shadow_ram_support; |
126 | u16 led_compensation; | 125 | u16 led_compensation; |
127 | int chain_noise_num_beacons; | ||
128 | bool adv_thermal_throttle; | 126 | bool adv_thermal_throttle; |
129 | bool support_ct_kill_exit; | 127 | bool support_ct_kill_exit; |
130 | const bool support_wimax_coexist; | 128 | const bool support_wimax_coexist; |
131 | u8 plcp_delta_threshold; | 129 | u8 plcp_delta_threshold; |
132 | s32 chain_noise_scale; | 130 | s32 chain_noise_scale; |
133 | unsigned int wd_timeout; | 131 | unsigned int wd_timeout; |
134 | bool temperature_kelvin; | ||
135 | u32 max_event_log_size; | 132 | u32 max_event_log_size; |
136 | const bool shadow_reg_enable; | 133 | const bool shadow_reg_enable; |
137 | const bool no_idle_support; | 134 | const bool no_idle_support; |
@@ -194,6 +191,7 @@ struct iwl_ht_params { | |||
194 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity | 191 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity |
195 | * @internal_wimax_coex: internal wifi/wimax combo device | 192 | * @internal_wimax_coex: internal wifi/wimax combo device |
196 | * @iq_invert: I/Q inversion | 193 | * @iq_invert: I/Q inversion |
194 | * @temp_offset_v2: support v2 of temperature offset calibration | ||
197 | * | 195 | * |
198 | * We enable the driver to be backward compatible wrt API version. The | 196 | * We enable the driver to be backward compatible wrt API version. The |
199 | * driver specifies which APIs it supports (with @ucode_api_max being the | 197 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -231,6 +229,7 @@ struct iwl_cfg { | |||
231 | const bool rx_with_siso_diversity; | 229 | const bool rx_with_siso_diversity; |
232 | const bool internal_wimax_coex; | 230 | const bool internal_wimax_coex; |
233 | const bool iq_invert; | 231 | const bool iq_invert; |
232 | const bool temp_offset_v2; | ||
234 | }; | 233 | }; |
235 | 234 | ||
236 | /*************************** | 235 | /*************************** |
@@ -319,7 +318,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); | |||
319 | ******************************************************************************/ | 318 | ******************************************************************************/ |
320 | void iwl_init_scan_params(struct iwl_priv *priv); | 319 | void iwl_init_scan_params(struct iwl_priv *priv); |
321 | int iwl_scan_cancel(struct iwl_priv *priv); | 320 | int iwl_scan_cancel(struct iwl_priv *priv); |
322 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | 321 | void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); |
323 | void iwl_force_scan_end(struct iwl_priv *priv); | 322 | void iwl_force_scan_end(struct iwl_priv *priv); |
324 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, | 323 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, |
325 | struct ieee80211_vif *vif, | 324 | struct ieee80211_vif *vif, |
@@ -329,12 +328,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); | |||
329 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 328 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
330 | const u8 *ta, const u8 *ie, int ie_len, int left); | 329 | const u8 *ta, const u8 *ie, int ie_len, int left); |
331 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 330 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
332 | u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | ||
333 | enum ieee80211_band band, | ||
334 | u8 n_probes); | ||
335 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | ||
336 | enum ieee80211_band band, | ||
337 | struct ieee80211_vif *vif); | ||
338 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); | 331 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); |
339 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); | 332 | void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); |
340 | int __must_check iwl_scan_initiate(struct iwl_priv *priv, | 333 | int __must_check iwl_scan_initiate(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d0c63cfee15c..6d49dfbee964 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -64,6 +64,14 @@ | |||
64 | goto err; \ | 64 | goto err; \ |
65 | } while (0) | 65 | } while (0) |
66 | 66 | ||
67 | #define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ | ||
68 | struct dentry *__tmp; \ | ||
69 | __tmp = debugfs_create_u32(#name, mode, \ | ||
70 | parent, ptr); \ | ||
71 | if (IS_ERR(__tmp) || !__tmp) \ | ||
72 | goto err; \ | ||
73 | } while (0) | ||
74 | |||
67 | /* file operation */ | 75 | /* file operation */ |
68 | #define DEBUGFS_READ_FUNC(name) \ | 76 | #define DEBUGFS_READ_FUNC(name) \ |
69 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | 77 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ |
@@ -707,6 +715,20 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, | |||
707 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 715 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
708 | } | 716 | } |
709 | 717 | ||
718 | static ssize_t iwl_dbgfs_temperature_read(struct file *file, | ||
719 | char __user *user_buf, | ||
720 | size_t count, loff_t *ppos) | ||
721 | { | ||
722 | struct iwl_priv *priv = file->private_data; | ||
723 | char buf[8]; | ||
724 | int pos = 0; | ||
725 | const size_t bufsz = sizeof(buf); | ||
726 | |||
727 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", priv->temperature); | ||
728 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
729 | } | ||
730 | |||
731 | |||
710 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | 732 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, |
711 | const char __user *user_buf, | 733 | const char __user *user_buf, |
712 | size_t count, loff_t *ppos) | 734 | size_t count, loff_t *ppos) |
@@ -801,6 +823,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers); | |||
801 | DEBUGFS_READ_FILE_OPS(qos); | 823 | DEBUGFS_READ_FILE_OPS(qos); |
802 | DEBUGFS_READ_FILE_OPS(thermal_throttling); | 824 | DEBUGFS_READ_FILE_OPS(thermal_throttling); |
803 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | 825 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); |
826 | DEBUGFS_READ_FILE_OPS(temperature); | ||
804 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); | 827 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); |
805 | DEBUGFS_READ_FILE_OPS(current_sleep_command); | 828 | DEBUGFS_READ_FILE_OPS(current_sleep_command); |
806 | 829 | ||
@@ -2229,8 +2252,8 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | |||
2229 | 2252 | ||
2230 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, | 2253 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, |
2231 | char __user *user_buf, | 2254 | char __user *user_buf, |
2232 | size_t count, loff_t *ppos) { | 2255 | size_t count, loff_t *ppos) |
2233 | 2256 | { | |
2234 | struct iwl_priv *priv = file->private_data; | 2257 | struct iwl_priv *priv = file->private_data; |
2235 | int i, pos = 0; | 2258 | int i, pos = 0; |
2236 | char buf[300]; | 2259 | char buf[300]; |
@@ -2309,8 +2332,8 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, | |||
2309 | 2332 | ||
2310 | static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, | 2333 | static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, |
2311 | const char __user *user_buf, | 2334 | const char __user *user_buf, |
2312 | size_t count, loff_t *ppos) { | 2335 | size_t count, loff_t *ppos) |
2313 | 2336 | { | |
2314 | struct iwl_priv *priv = file->private_data; | 2337 | struct iwl_priv *priv = file->private_data; |
2315 | char buf[8]; | 2338 | char buf[8]; |
2316 | int buf_size; | 2339 | int buf_size; |
@@ -2445,6 +2468,52 @@ DEBUGFS_READ_FILE_OPS(bt_traffic); | |||
2445 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); | 2468 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); |
2446 | DEBUGFS_READ_FILE_OPS(reply_tx_error); | 2469 | DEBUGFS_READ_FILE_OPS(reply_tx_error); |
2447 | 2470 | ||
2471 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2472 | static ssize_t iwl_dbgfs_debug_level_read(struct file *file, | ||
2473 | char __user *user_buf, | ||
2474 | size_t count, loff_t *ppos) | ||
2475 | { | ||
2476 | struct iwl_priv *priv = file->private_data; | ||
2477 | struct iwl_shared *shrd = priv->shrd; | ||
2478 | char buf[11]; | ||
2479 | int len; | ||
2480 | |||
2481 | len = scnprintf(buf, sizeof(buf), "0x%.8x", | ||
2482 | iwl_get_debug_level(shrd)); | ||
2483 | |||
2484 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
2485 | } | ||
2486 | |||
2487 | static ssize_t iwl_dbgfs_debug_level_write(struct file *file, | ||
2488 | const char __user *user_buf, | ||
2489 | size_t count, loff_t *ppos) | ||
2490 | { | ||
2491 | struct iwl_priv *priv = file->private_data; | ||
2492 | struct iwl_shared *shrd = priv->shrd; | ||
2493 | char buf[11]; | ||
2494 | unsigned long val; | ||
2495 | int ret; | ||
2496 | |||
2497 | if (count > sizeof(buf)) | ||
2498 | return -EINVAL; | ||
2499 | |||
2500 | memset(buf, 0, sizeof(buf)); | ||
2501 | if (copy_from_user(buf, user_buf, count)) | ||
2502 | return -EFAULT; | ||
2503 | |||
2504 | ret = strict_strtoul(buf, 0, &val); | ||
2505 | if (ret) | ||
2506 | return ret; | ||
2507 | |||
2508 | shrd->dbg_level_dev = val; | ||
2509 | if (iwl_alloc_traffic_mem(priv)) | ||
2510 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | ||
2511 | |||
2512 | return count; | ||
2513 | } | ||
2514 | DEBUGFS_READ_WRITE_FILE_OPS(debug_level); | ||
2515 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
2516 | |||
2448 | /* | 2517 | /* |
2449 | * Create the debugfs files and directories | 2518 | * Create the debugfs files and directories |
2450 | * | 2519 | * |
@@ -2482,6 +2551,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2482 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); | 2551 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); |
2483 | DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); | 2552 | DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); |
2484 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); | 2553 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); |
2554 | DEBUGFS_ADD_FILE(temperature, dir_data, S_IRUSR); | ||
2555 | |||
2485 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); | 2556 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); |
2486 | DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); | 2557 | DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); |
2487 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); | 2558 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); |
@@ -2496,7 +2567,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2496 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 2567 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
2497 | DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); | 2568 | DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); |
2498 | DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); | 2569 | DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); |
2499 | |||
2500 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 2570 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
2501 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 2571 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
2502 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 2572 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); |
@@ -2507,6 +2577,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2507 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); | 2577 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); |
2508 | if (iwl_advanced_bt_coexist(priv)) | 2578 | if (iwl_advanced_bt_coexist(priv)) |
2509 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); | 2579 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); |
2580 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2581 | DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR); | ||
2582 | #endif | ||
2583 | |||
2510 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | 2584 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, |
2511 | &priv->disable_sens_cal); | 2585 | &priv->disable_sens_cal); |
2512 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 2586 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, |
@@ -2534,6 +2608,3 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
2534 | debugfs_remove_recursive(priv->debugfs_dir); | 2608 | debugfs_remove_recursive(priv->debugfs_dir); |
2535 | priv->debugfs_dir = NULL; | 2609 | priv->debugfs_dir = NULL; |
2536 | } | 2610 | } |
2537 | |||
2538 | |||
2539 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8438a33e17ee..257aa9a407ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -202,11 +202,6 @@ struct iwl_station_entry { | |||
202 | struct iwl_link_quality_cmd *lq; | 202 | struct iwl_link_quality_cmd *lq; |
203 | }; | 203 | }; |
204 | 204 | ||
205 | struct iwl_station_priv_common { | ||
206 | struct iwl_rxon_context *ctx; | ||
207 | u8 sta_id; | ||
208 | }; | ||
209 | |||
210 | /* | 205 | /* |
211 | * iwl_station_priv: Driver's private station information | 206 | * iwl_station_priv: Driver's private station information |
212 | * | 207 | * |
@@ -215,12 +210,13 @@ struct iwl_station_priv_common { | |||
215 | * space. | 210 | * space. |
216 | */ | 211 | */ |
217 | struct iwl_station_priv { | 212 | struct iwl_station_priv { |
218 | struct iwl_station_priv_common common; | 213 | struct iwl_rxon_context *ctx; |
219 | struct iwl_lq_sta lq_sta; | 214 | struct iwl_lq_sta lq_sta; |
220 | atomic_t pending_frames; | 215 | atomic_t pending_frames; |
221 | bool client; | 216 | bool client; |
222 | bool asleep; | 217 | bool asleep; |
223 | u8 max_agg_bufsize; | 218 | u8 max_agg_bufsize; |
219 | u8 sta_id; | ||
224 | }; | 220 | }; |
225 | 221 | ||
226 | /** | 222 | /** |
@@ -845,8 +841,9 @@ struct iwl_priv { | |||
845 | 841 | ||
846 | void (*pre_rx_handler)(struct iwl_priv *priv, | 842 | void (*pre_rx_handler)(struct iwl_priv *priv, |
847 | struct iwl_rx_mem_buffer *rxb); | 843 | struct iwl_rx_mem_buffer *rxb); |
848 | void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, | 844 | int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, |
849 | struct iwl_rx_mem_buffer *rxb); | 845 | struct iwl_rx_mem_buffer *rxb, |
846 | struct iwl_device_cmd *cmd); | ||
850 | 847 | ||
851 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 848 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
852 | 849 | ||
@@ -880,7 +877,7 @@ struct iwl_priv { | |||
880 | u8 channel_count; /* # of channels */ | 877 | u8 channel_count; /* # of channels */ |
881 | 878 | ||
882 | /* thermal calibration */ | 879 | /* thermal calibration */ |
883 | s32 temperature; /* degrees Kelvin */ | 880 | s32 temperature; /* Celsius */ |
884 | s32 last_temperature; | 881 | s32 last_temperature; |
885 | 882 | ||
886 | /* init calibration results */ | 883 | /* init calibration results */ |
@@ -958,6 +955,8 @@ struct iwl_priv { | |||
958 | struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; | 955 | struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; |
959 | unsigned long ucode_key_table; | 956 | unsigned long ucode_key_table; |
960 | 957 | ||
958 | u8 mac80211_registered; | ||
959 | |||
961 | /* Indication if ieee80211_ops->open has been called */ | 960 | /* Indication if ieee80211_ops->open has been called */ |
962 | u8 is_open; | 961 | u8 is_open; |
963 | 962 | ||
@@ -1031,7 +1030,7 @@ struct iwl_priv { | |||
1031 | struct delayed_work hw_roc_disable_work; | 1030 | struct delayed_work hw_roc_disable_work; |
1032 | enum nl80211_channel_type hw_roc_chantype; | 1031 | enum nl80211_channel_type hw_roc_chantype; |
1033 | int hw_roc_duration; | 1032 | int hw_roc_duration; |
1034 | bool hw_roc_setup; | 1033 | bool hw_roc_setup, hw_roc_start_notified; |
1035 | 1034 | ||
1036 | /* bt coex */ | 1035 | /* bt coex */ |
1037 | u8 bt_enable_flag; | 1036 | u8 bt_enable_flag; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 80ee65be9cd1..a4e43bd4a547 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -72,6 +72,7 @@ | |||
72 | #include "iwl-dev.h" | 72 | #include "iwl-dev.h" |
73 | #include "iwl-core.h" | 73 | #include "iwl-core.h" |
74 | #include "iwl-debug.h" | 74 | #include "iwl-debug.h" |
75 | #include "iwl-agn.h" | ||
75 | #include "iwl-eeprom.h" | 76 | #include "iwl-eeprom.h" |
76 | #include "iwl-io.h" | 77 | #include "iwl-io.h" |
77 | 78 | ||
@@ -138,7 +139,7 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ | |||
138 | 139 | ||
139 | /****************************************************************************** | 140 | /****************************************************************************** |
140 | * | 141 | * |
141 | * EEPROM related functions | 142 | * generic NVM functions |
142 | * | 143 | * |
143 | ******************************************************************************/ | 144 | ******************************************************************************/ |
144 | 145 | ||
@@ -214,6 +215,93 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv) | |||
214 | return ret; | 215 | return ret; |
215 | } | 216 | } |
216 | 217 | ||
218 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | ||
219 | { | ||
220 | if (!priv->eeprom) | ||
221 | return 0; | ||
222 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | ||
223 | } | ||
224 | |||
225 | int iwl_eeprom_check_version(struct iwl_priv *priv) | ||
226 | { | ||
227 | u16 eeprom_ver; | ||
228 | u16 calib_ver; | ||
229 | |||
230 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
231 | calib_ver = iwlagn_eeprom_calib_version(priv); | ||
232 | |||
233 | if (eeprom_ver < priv->cfg->eeprom_ver || | ||
234 | calib_ver < priv->cfg->eeprom_calib_ver) | ||
235 | goto err; | ||
236 | |||
237 | IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||
238 | eeprom_ver, calib_ver); | ||
239 | |||
240 | return 0; | ||
241 | err: | ||
242 | IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x " | ||
243 | "CALIB=0x%x < 0x%x\n", | ||
244 | eeprom_ver, priv->cfg->eeprom_ver, | ||
245 | calib_ver, priv->cfg->eeprom_calib_ver); | ||
246 | return -EINVAL; | ||
247 | |||
248 | } | ||
249 | |||
250 | int iwl_eeprom_check_sku(struct iwl_priv *priv) | ||
251 | { | ||
252 | u16 radio_cfg; | ||
253 | |||
254 | if (!priv->cfg->sku) { | ||
255 | /* not using sku overwrite */ | ||
256 | priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); | ||
257 | if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE && | ||
258 | !priv->cfg->ht_params) { | ||
259 | IWL_ERR(priv, "Invalid 11n configuration\n"); | ||
260 | return -EINVAL; | ||
261 | } | ||
262 | } | ||
263 | if (!priv->cfg->sku) { | ||
264 | IWL_ERR(priv, "Invalid device sku\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku); | ||
269 | |||
270 | if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) { | ||
271 | /* not using .cfg overwrite */ | ||
272 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
273 | priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); | ||
274 | priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); | ||
275 | if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) { | ||
276 | IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n", | ||
277 | priv->cfg->valid_tx_ant, | ||
278 | priv->cfg->valid_rx_ant); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n", | ||
282 | priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant); | ||
283 | } | ||
284 | /* | ||
285 | * for some special cases, | ||
286 | * EEPROM did not reflect the correct antenna setting | ||
287 | * so overwrite the valid tx/rx antenna from .cfg | ||
288 | */ | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) | ||
293 | { | ||
294 | const u8 *addr = iwl_eeprom_query_addr(priv, | ||
295 | EEPROM_MAC_ADDRESS); | ||
296 | memcpy(mac, addr, ETH_ALEN); | ||
297 | } | ||
298 | |||
299 | /****************************************************************************** | ||
300 | * | ||
301 | * OTP related functions | ||
302 | * | ||
303 | ******************************************************************************/ | ||
304 | |||
217 | static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) | 305 | static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) |
218 | { | 306 | { |
219 | iwl_read32(bus(priv), CSR_OTP_GP_REG); | 307 | iwl_read32(bus(priv), CSR_OTP_GP_REG); |
@@ -407,11 +495,152 @@ static int iwl_find_otp_image(struct iwl_priv *priv, | |||
407 | return -EINVAL; | 495 | return -EINVAL; |
408 | } | 496 | } |
409 | 497 | ||
410 | u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) | 498 | /****************************************************************************** |
499 | * | ||
500 | * Tx Power related functions | ||
501 | * | ||
502 | ******************************************************************************/ | ||
503 | /** | ||
504 | * iwl_get_max_txpower_avg - get the highest tx power from all chains. | ||
505 | * find the highest tx power from all chains for the channel | ||
506 | */ | ||
507 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | ||
508 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | ||
509 | int element, s8 *max_txpower_in_half_dbm) | ||
411 | { | 510 | { |
412 | if (!priv->eeprom) | 511 | s8 max_txpower_avg = 0; /* (dBm) */ |
413 | return 0; | 512 | |
414 | return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); | 513 | /* Take the highest tx power from any valid chains */ |
514 | if ((priv->cfg->valid_tx_ant & ANT_A) && | ||
515 | (enhanced_txpower[element].chain_a_max > max_txpower_avg)) | ||
516 | max_txpower_avg = enhanced_txpower[element].chain_a_max; | ||
517 | if ((priv->cfg->valid_tx_ant & ANT_B) && | ||
518 | (enhanced_txpower[element].chain_b_max > max_txpower_avg)) | ||
519 | max_txpower_avg = enhanced_txpower[element].chain_b_max; | ||
520 | if ((priv->cfg->valid_tx_ant & ANT_C) && | ||
521 | (enhanced_txpower[element].chain_c_max > max_txpower_avg)) | ||
522 | max_txpower_avg = enhanced_txpower[element].chain_c_max; | ||
523 | if (((priv->cfg->valid_tx_ant == ANT_AB) | | ||
524 | (priv->cfg->valid_tx_ant == ANT_BC) | | ||
525 | (priv->cfg->valid_tx_ant == ANT_AC)) && | ||
526 | (enhanced_txpower[element].mimo2_max > max_txpower_avg)) | ||
527 | max_txpower_avg = enhanced_txpower[element].mimo2_max; | ||
528 | if ((priv->cfg->valid_tx_ant == ANT_ABC) && | ||
529 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | ||
530 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | ||
531 | |||
532 | /* | ||
533 | * max. tx power in EEPROM is in 1/2 dBm format | ||
534 | * convert from 1/2 dBm to dBm (round-up convert) | ||
535 | * but we also do not want to loss 1/2 dBm resolution which | ||
536 | * will impact performance | ||
537 | */ | ||
538 | *max_txpower_in_half_dbm = max_txpower_avg; | ||
539 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
540 | } | ||
541 | |||
542 | static void | ||
543 | iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, | ||
544 | struct iwl_eeprom_enhanced_txpwr *txp, | ||
545 | s8 max_txpower_avg) | ||
546 | { | ||
547 | int ch_idx; | ||
548 | bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ; | ||
549 | enum ieee80211_band band; | ||
550 | |||
551 | band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||
552 | IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||
553 | |||
554 | for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) { | ||
555 | struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx]; | ||
556 | |||
557 | /* update matching channel or from common data only */ | ||
558 | if (txp->channel != 0 && ch_info->channel != txp->channel) | ||
559 | continue; | ||
560 | |||
561 | /* update matching band only */ | ||
562 | if (band != ch_info->band) | ||
563 | continue; | ||
564 | |||
565 | if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) { | ||
566 | ch_info->max_power_avg = max_txpower_avg; | ||
567 | ch_info->curr_txpow = max_txpower_avg; | ||
568 | ch_info->scan_power = max_txpower_avg; | ||
569 | } | ||
570 | |||
571 | if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg) | ||
572 | ch_info->ht40_max_power_avg = max_txpower_avg; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | #define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||
577 | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||
578 | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||
579 | |||
580 | #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ | ||
581 | ? # x " " : "") | ||
582 | |||
583 | void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) | ||
584 | { | ||
585 | struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||
586 | int idx, entries; | ||
587 | __le16 *txp_len; | ||
588 | s8 max_txp_avg, max_txp_avg_halfdbm; | ||
589 | |||
590 | BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||
591 | |||
592 | /* the length is in 16-bit words, but we want entries */ | ||
593 | txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); | ||
594 | entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||
595 | |||
596 | txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS); | ||
597 | |||
598 | for (idx = 0; idx < entries; idx++) { | ||
599 | txp = &txp_array[idx]; | ||
600 | /* skip invalid entries */ | ||
601 | if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||
602 | continue; | ||
603 | |||
604 | IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||
605 | (txp->channel && (txp->flags & | ||
606 | IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||
607 | "Common " : (txp->channel) ? | ||
608 | "Channel" : "Common", | ||
609 | (txp->channel), | ||
610 | TXP_CHECK_AND_PRINT(VALID), | ||
611 | TXP_CHECK_AND_PRINT(BAND_52G), | ||
612 | TXP_CHECK_AND_PRINT(OFDM), | ||
613 | TXP_CHECK_AND_PRINT(40MHZ), | ||
614 | TXP_CHECK_AND_PRINT(HT_AP), | ||
615 | TXP_CHECK_AND_PRINT(RES1), | ||
616 | TXP_CHECK_AND_PRINT(RES2), | ||
617 | TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||
618 | txp->flags); | ||
619 | IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x " | ||
620 | "chain_B: 0X%02x chain_C: 0X%02x\n", | ||
621 | txp->chain_a_max, txp->chain_b_max, | ||
622 | txp->chain_c_max); | ||
623 | IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x " | ||
624 | "MIMO3: 0x%02x High 20_on_40: 0x%02x " | ||
625 | "Low 20_on_40: 0x%02x\n", | ||
626 | txp->mimo2_max, txp->mimo3_max, | ||
627 | ((txp->delta_20_in_40 & 0xf0) >> 4), | ||
628 | (txp->delta_20_in_40 & 0x0f)); | ||
629 | |||
630 | max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, | ||
631 | &max_txp_avg_halfdbm); | ||
632 | |||
633 | /* | ||
634 | * Update the user limit values values to the highest | ||
635 | * power supported by any channel | ||
636 | */ | ||
637 | if (max_txp_avg > priv->tx_power_user_lmt) | ||
638 | priv->tx_power_user_lmt = max_txp_avg; | ||
639 | if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) | ||
640 | priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; | ||
641 | |||
642 | iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); | ||
643 | } | ||
415 | } | 644 | } |
416 | 645 | ||
417 | /** | 646 | /** |
@@ -670,8 +899,9 @@ int iwl_init_channel_map(struct iwl_priv *priv) | |||
670 | IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n", | 899 | IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n", |
671 | priv->channel_count); | 900 | priv->channel_count); |
672 | 901 | ||
673 | priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * | 902 | priv->channel_info = kcalloc(priv->channel_count, |
674 | priv->channel_count, GFP_KERNEL); | 903 | sizeof(struct iwl_channel_info), |
904 | GFP_KERNEL); | ||
675 | if (!priv->channel_info) { | 905 | if (!priv->channel_info) { |
676 | IWL_ERR(priv, "Could not allocate channel_info\n"); | 906 | IWL_ERR(priv, "Could not allocate channel_info\n"); |
677 | priv->channel_count = 0; | 907 | priv->channel_count = 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index e2b5e0ea5d9c..c94747e7299e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -163,11 +163,19 @@ struct iwl_eeprom_enhanced_txpwr { | |||
163 | } __packed; | 163 | } __packed; |
164 | 164 | ||
165 | /* calibration */ | 165 | /* calibration */ |
166 | struct iwl_eeprom_calib_hdr { | ||
167 | u8 version; | ||
168 | u8 pa_type; | ||
169 | __le16 voltage; | ||
170 | } __packed; | ||
171 | |||
166 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | 172 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) |
167 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) | 173 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) |
168 | 174 | ||
169 | /* temperature */ | 175 | /* temperature */ |
170 | #define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) | 176 | #define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) |
177 | #define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL) | ||
178 | |||
171 | 179 | ||
172 | /* agn links */ | 180 | /* agn links */ |
173 | #define EEPROM_LINK_HOST (2*0x64) | 181 | #define EEPROM_LINK_HOST (2*0x64) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 7dffed186f0a..f149165e8010 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -104,7 +104,6 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | |||
104 | .len = { sizeof(struct iwl_led_cmd), }, | 104 | .len = { sizeof(struct iwl_led_cmd), }, |
105 | .data = { led_cmd, }, | 105 | .data = { led_cmd, }, |
106 | .flags = CMD_ASYNC, | 106 | .flags = CMD_ASYNC, |
107 | .callback = NULL, | ||
108 | }; | 107 | }; |
109 | u32 reg; | 108 | u32 reg; |
110 | 109 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 78a3f8dfe680..1d7bb7423f94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c | |||
@@ -68,7 +68,7 @@ | |||
68 | #include "iwl-shared.h" | 68 | #include "iwl-shared.h" |
69 | #include "iwl-trans.h" | 69 | #include "iwl-trans.h" |
70 | #include "iwl-csr.h" | 70 | #include "iwl-csr.h" |
71 | #include "iwl-pci.h" | 71 | #include "iwl-cfg.h" |
72 | 72 | ||
73 | /* PCI registers */ | 73 | /* PCI registers */ |
74 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | 74 | #define PCI_CFG_RETRY_TIMEOUT 0x041 |
@@ -134,12 +134,6 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | static void iwl_pci_set_drv_data(struct iwl_bus *bus, struct iwl_shared *shrd) | ||
138 | { | ||
139 | bus->shrd = shrd; | ||
140 | pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), shrd); | ||
141 | } | ||
142 | |||
143 | static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], | 137 | static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], |
144 | int buf_len) | 138 | int buf_len) |
145 | { | 139 | { |
@@ -168,7 +162,6 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) | |||
168 | static const struct iwl_bus_ops bus_ops_pci = { | 162 | static const struct iwl_bus_ops bus_ops_pci = { |
169 | .get_pm_support = iwl_pci_is_pm_supported, | 163 | .get_pm_support = iwl_pci_is_pm_supported, |
170 | .apm_config = iwl_pci_apm_config, | 164 | .apm_config = iwl_pci_apm_config, |
171 | .set_drv_data = iwl_pci_set_drv_data, | ||
172 | .get_hw_id = iwl_pci_get_hw_id, | 165 | .get_hw_id = iwl_pci_get_hw_id, |
173 | .write8 = iwl_pci_write8, | 166 | .write8 = iwl_pci_write8, |
174 | .write32 = iwl_pci_write32, | 167 | .write32 = iwl_pci_write32, |
@@ -260,6 +253,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
260 | {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, | 253 | {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, |
261 | {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, | 254 | {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, |
262 | {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)}, | 255 | {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)}, |
256 | {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)}, | ||
263 | 257 | ||
264 | /* 6x30 Series */ | 258 | /* 6x30 Series */ |
265 | {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, | 259 | {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, |
@@ -392,6 +386,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
392 | pci_bus = IWL_BUS_GET_PCI_BUS(bus); | 386 | pci_bus = IWL_BUS_GET_PCI_BUS(bus); |
393 | pci_bus->pci_dev = pdev; | 387 | pci_bus->pci_dev = pdev; |
394 | 388 | ||
389 | pci_set_drvdata(pdev, bus); | ||
390 | |||
395 | /* W/A - seems to solve weird behavior. We need to remove this if we | 391 | /* W/A - seems to solve weird behavior. We need to remove this if we |
396 | * don't want to stay in L1 all the time. This wastes a lot of power */ | 392 | * don't want to stay in L1 all the time. This wastes a lot of power */ |
397 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | 393 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | |
@@ -485,17 +481,18 @@ out_no_pci: | |||
485 | 481 | ||
486 | static void __devexit iwl_pci_remove(struct pci_dev *pdev) | 482 | static void __devexit iwl_pci_remove(struct pci_dev *pdev) |
487 | { | 483 | { |
488 | struct iwl_shared *shrd = pci_get_drvdata(pdev); | 484 | struct iwl_bus *bus = pci_get_drvdata(pdev); |
489 | struct iwl_bus *bus = shrd->bus; | ||
490 | struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus); | 485 | struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus); |
486 | struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); | ||
487 | struct iwl_shared *shrd = bus->shrd; | ||
491 | 488 | ||
492 | iwl_remove(shrd->priv); | 489 | iwl_remove(shrd->priv); |
493 | 490 | ||
494 | pci_disable_msi(pci_bus->pci_dev); | 491 | pci_disable_msi(pci_dev); |
495 | pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); | 492 | pci_iounmap(pci_dev, pci_bus->hw_base); |
496 | pci_release_regions(pci_bus->pci_dev); | 493 | pci_release_regions(pci_dev); |
497 | pci_disable_device(pci_bus->pci_dev); | 494 | pci_disable_device(pci_dev); |
498 | pci_set_drvdata(pci_bus->pci_dev, NULL); | 495 | pci_set_drvdata(pci_dev, NULL); |
499 | 496 | ||
500 | kfree(bus); | 497 | kfree(bus); |
501 | } | 498 | } |
@@ -505,7 +502,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
505 | static int iwl_pci_suspend(struct device *device) | 502 | static int iwl_pci_suspend(struct device *device) |
506 | { | 503 | { |
507 | struct pci_dev *pdev = to_pci_dev(device); | 504 | struct pci_dev *pdev = to_pci_dev(device); |
508 | struct iwl_shared *shrd = pci_get_drvdata(pdev); | 505 | struct iwl_bus *bus = pci_get_drvdata(pdev); |
506 | struct iwl_shared *shrd = bus->shrd; | ||
509 | 507 | ||
510 | /* Before you put code here, think about WoWLAN. You cannot check here | 508 | /* Before you put code here, think about WoWLAN. You cannot check here |
511 | * whether WoWLAN is enabled or not, and your code will run even if | 509 | * whether WoWLAN is enabled or not, and your code will run even if |
@@ -518,7 +516,8 @@ static int iwl_pci_suspend(struct device *device) | |||
518 | static int iwl_pci_resume(struct device *device) | 516 | static int iwl_pci_resume(struct device *device) |
519 | { | 517 | { |
520 | struct pci_dev *pdev = to_pci_dev(device); | 518 | struct pci_dev *pdev = to_pci_dev(device); |
521 | struct iwl_shared *shrd = pci_get_drvdata(pdev); | 519 | struct iwl_bus *bus = pci_get_drvdata(pdev); |
520 | struct iwl_shared *shrd = bus->shrd; | ||
522 | 521 | ||
523 | /* Before you put code here, think about WoWLAN. You cannot check here | 522 | /* Before you put code here, think about WoWLAN. You cannot check here |
524 | * whether WoWLAN is enabled or not, and your code will run even if | 523 | * whether WoWLAN is enabled or not, and your code will run even if |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index c7e6a746c3ea..bcd7f64683aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -130,8 +130,9 @@ const char *get_cmd_string(u8 cmd) | |||
130 | * | 130 | * |
131 | ******************************************************************************/ | 131 | ******************************************************************************/ |
132 | 132 | ||
133 | static void iwl_rx_reply_error(struct iwl_priv *priv, | 133 | static int iwl_rx_reply_error(struct iwl_priv *priv, |
134 | struct iwl_rx_mem_buffer *rxb) | 134 | struct iwl_rx_mem_buffer *rxb, |
135 | struct iwl_device_cmd *cmd) | ||
135 | { | 136 | { |
136 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 137 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
137 | 138 | ||
@@ -142,9 +143,11 @@ static void iwl_rx_reply_error(struct iwl_priv *priv, | |||
142 | pkt->u.err_resp.cmd_id, | 143 | pkt->u.err_resp.cmd_id, |
143 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), | 144 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), |
144 | le32_to_cpu(pkt->u.err_resp.error_info)); | 145 | le32_to_cpu(pkt->u.err_resp.error_info)); |
146 | return 0; | ||
145 | } | 147 | } |
146 | 148 | ||
147 | static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 149 | static int iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
150 | struct iwl_device_cmd *cmd) | ||
148 | { | 151 | { |
149 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 152 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
150 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | 153 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); |
@@ -156,7 +159,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
156 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; | 159 | struct iwl_rxon_cmd *rxon = (void *)&ctx->active; |
157 | 160 | ||
158 | if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) | 161 | if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) |
159 | return; | 162 | return 0; |
160 | 163 | ||
161 | if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { | 164 | if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { |
162 | rxon->channel = csa->channel; | 165 | rxon->channel = csa->channel; |
@@ -169,11 +172,13 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
169 | le16_to_cpu(csa->channel)); | 172 | le16_to_cpu(csa->channel)); |
170 | iwl_chswitch_done(priv, false); | 173 | iwl_chswitch_done(priv, false); |
171 | } | 174 | } |
175 | return 0; | ||
172 | } | 176 | } |
173 | 177 | ||
174 | 178 | ||
175 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 179 | static int iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
176 | struct iwl_rx_mem_buffer *rxb) | 180 | struct iwl_rx_mem_buffer *rxb, |
181 | struct iwl_device_cmd *cmd) | ||
177 | { | 182 | { |
178 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 183 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
179 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); | 184 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); |
@@ -181,15 +186,17 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | |||
181 | if (!report->state) { | 186 | if (!report->state) { |
182 | IWL_DEBUG_11H(priv, | 187 | IWL_DEBUG_11H(priv, |
183 | "Spectrum Measure Notification: Start\n"); | 188 | "Spectrum Measure Notification: Start\n"); |
184 | return; | 189 | return 0; |
185 | } | 190 | } |
186 | 191 | ||
187 | memcpy(&priv->measure_report, report, sizeof(*report)); | 192 | memcpy(&priv->measure_report, report, sizeof(*report)); |
188 | priv->measurement_status |= MEASUREMENT_READY; | 193 | priv->measurement_status |= MEASUREMENT_READY; |
194 | return 0; | ||
189 | } | 195 | } |
190 | 196 | ||
191 | static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | 197 | static int iwl_rx_pm_sleep_notif(struct iwl_priv *priv, |
192 | struct iwl_rx_mem_buffer *rxb) | 198 | struct iwl_rx_mem_buffer *rxb, |
199 | struct iwl_device_cmd *cmd) | ||
193 | { | 200 | { |
194 | #ifdef CONFIG_IWLWIFI_DEBUG | 201 | #ifdef CONFIG_IWLWIFI_DEBUG |
195 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 202 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -197,10 +204,12 @@ static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | |||
197 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", | 204 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", |
198 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | 205 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); |
199 | #endif | 206 | #endif |
207 | return 0; | ||
200 | } | 208 | } |
201 | 209 | ||
202 | static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | 210 | static int iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, |
203 | struct iwl_rx_mem_buffer *rxb) | 211 | struct iwl_rx_mem_buffer *rxb, |
212 | struct iwl_device_cmd *cmd) | ||
204 | { | 213 | { |
205 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 214 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
206 | u32 __maybe_unused len = | 215 | u32 __maybe_unused len = |
@@ -209,10 +218,12 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | |||
209 | "notification for %s:\n", len, | 218 | "notification for %s:\n", len, |
210 | get_cmd_string(pkt->hdr.cmd)); | 219 | get_cmd_string(pkt->hdr.cmd)); |
211 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); | 220 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); |
221 | return 0; | ||
212 | } | 222 | } |
213 | 223 | ||
214 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 224 | static int iwl_rx_beacon_notif(struct iwl_priv *priv, |
215 | struct iwl_rx_mem_buffer *rxb) | 225 | struct iwl_rx_mem_buffer *rxb, |
226 | struct iwl_device_cmd *cmd) | ||
216 | { | 227 | { |
217 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 228 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
218 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; | 229 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; |
@@ -233,6 +244,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
233 | 244 | ||
234 | if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) | 245 | if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) |
235 | queue_work(priv->shrd->workqueue, &priv->beacon_update); | 246 | queue_work(priv->shrd->workqueue, &priv->beacon_update); |
247 | return 0; | ||
236 | } | 248 | } |
237 | 249 | ||
238 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | 250 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ |
@@ -475,8 +487,9 @@ iwl_accumulative_statistics(struct iwl_priv *priv, | |||
475 | } | 487 | } |
476 | #endif | 488 | #endif |
477 | 489 | ||
478 | static void iwl_rx_statistics(struct iwl_priv *priv, | 490 | static int iwl_rx_statistics(struct iwl_priv *priv, |
479 | struct iwl_rx_mem_buffer *rxb) | 491 | struct iwl_rx_mem_buffer *rxb, |
492 | struct iwl_device_cmd *cmd) | ||
480 | { | 493 | { |
481 | unsigned long stamp = jiffies; | 494 | unsigned long stamp = jiffies; |
482 | const int reg_recalib_period = 60; | 495 | const int reg_recalib_period = 60; |
@@ -530,7 +543,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv, | |||
530 | WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", | 543 | WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", |
531 | len, sizeof(struct iwl_bt_notif_statistics), | 544 | len, sizeof(struct iwl_bt_notif_statistics), |
532 | sizeof(struct iwl_notif_statistics)); | 545 | sizeof(struct iwl_notif_statistics)); |
533 | return; | 546 | return 0; |
534 | } | 547 | } |
535 | 548 | ||
536 | change = common->temperature != priv->statistics.common.temperature || | 549 | change = common->temperature != priv->statistics.common.temperature || |
@@ -573,10 +586,12 @@ static void iwl_rx_statistics(struct iwl_priv *priv, | |||
573 | } | 586 | } |
574 | if (priv->cfg->lib->temperature && change) | 587 | if (priv->cfg->lib->temperature && change) |
575 | priv->cfg->lib->temperature(priv); | 588 | priv->cfg->lib->temperature(priv); |
589 | return 0; | ||
576 | } | 590 | } |
577 | 591 | ||
578 | static void iwl_rx_reply_statistics(struct iwl_priv *priv, | 592 | static int iwl_rx_reply_statistics(struct iwl_priv *priv, |
579 | struct iwl_rx_mem_buffer *rxb) | 593 | struct iwl_rx_mem_buffer *rxb, |
594 | struct iwl_device_cmd *cmd) | ||
580 | { | 595 | { |
581 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 596 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
582 | 597 | ||
@@ -591,13 +606,15 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv, | |||
591 | #endif | 606 | #endif |
592 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | 607 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); |
593 | } | 608 | } |
594 | iwl_rx_statistics(priv, rxb); | 609 | iwl_rx_statistics(priv, rxb, cmd); |
610 | return 0; | ||
595 | } | 611 | } |
596 | 612 | ||
597 | /* Handle notification from uCode that card's power state is changing | 613 | /* Handle notification from uCode that card's power state is changing |
598 | * due to software, hardware, or critical temperature RFKILL */ | 614 | * due to software, hardware, or critical temperature RFKILL */ |
599 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, | 615 | static int iwl_rx_card_state_notif(struct iwl_priv *priv, |
600 | struct iwl_rx_mem_buffer *rxb) | 616 | struct iwl_rx_mem_buffer *rxb, |
617 | struct iwl_device_cmd *cmd) | ||
601 | { | 618 | { |
602 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 619 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
603 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 620 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
@@ -644,11 +661,13 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, | |||
644 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | 661 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, |
645 | test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); | 662 | test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); |
646 | else | 663 | else |
647 | wake_up_interruptible(&priv->shrd->wait_command_queue); | 664 | wake_up(&priv->shrd->wait_command_queue); |
665 | return 0; | ||
648 | } | 666 | } |
649 | 667 | ||
650 | static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 668 | static int iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
651 | struct iwl_rx_mem_buffer *rxb) | 669 | struct iwl_rx_mem_buffer *rxb, |
670 | struct iwl_device_cmd *cmd) | ||
652 | 671 | ||
653 | { | 672 | { |
654 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 673 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -666,18 +685,21 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
666 | if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) | 685 | if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) |
667 | iwl_init_sensitivity(priv); | 686 | iwl_init_sensitivity(priv); |
668 | } | 687 | } |
688 | return 0; | ||
669 | } | 689 | } |
670 | 690 | ||
671 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | 691 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). |
672 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | 692 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ |
673 | static void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | 693 | static int iwl_rx_reply_rx_phy(struct iwl_priv *priv, |
674 | struct iwl_rx_mem_buffer *rxb) | 694 | struct iwl_rx_mem_buffer *rxb, |
695 | struct iwl_device_cmd *cmd) | ||
675 | { | 696 | { |
676 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 697 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
677 | 698 | ||
678 | priv->last_phy_res_valid = true; | 699 | priv->last_phy_res_valid = true; |
679 | memcpy(&priv->last_phy_res, pkt->u.raw, | 700 | memcpy(&priv->last_phy_res, pkt->u.raw, |
680 | sizeof(struct iwl_rx_phy_res)); | 701 | sizeof(struct iwl_rx_phy_res)); |
702 | return 0; | ||
681 | } | 703 | } |
682 | 704 | ||
683 | /* | 705 | /* |
@@ -892,8 +914,9 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
892 | 914 | ||
893 | /* Called for REPLY_RX (legacy ABG frames), or | 915 | /* Called for REPLY_RX (legacy ABG frames), or |
894 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | 916 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ |
895 | static void iwl_rx_reply_rx(struct iwl_priv *priv, | 917 | static int iwl_rx_reply_rx(struct iwl_priv *priv, |
896 | struct iwl_rx_mem_buffer *rxb) | 918 | struct iwl_rx_mem_buffer *rxb, |
919 | struct iwl_device_cmd *cmd) | ||
897 | { | 920 | { |
898 | struct ieee80211_hdr *header; | 921 | struct ieee80211_hdr *header; |
899 | struct ieee80211_rx_status rx_status; | 922 | struct ieee80211_rx_status rx_status; |
@@ -926,7 +949,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
926 | } else { | 949 | } else { |
927 | if (!priv->last_phy_res_valid) { | 950 | if (!priv->last_phy_res_valid) { |
928 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | 951 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); |
929 | return; | 952 | return 0; |
930 | } | 953 | } |
931 | phy_res = &priv->last_phy_res; | 954 | phy_res = &priv->last_phy_res; |
932 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; | 955 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; |
@@ -940,14 +963,14 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
940 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | 963 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { |
941 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | 964 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", |
942 | phy_res->cfg_phy_cnt); | 965 | phy_res->cfg_phy_cnt); |
943 | return; | 966 | return 0; |
944 | } | 967 | } |
945 | 968 | ||
946 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | 969 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || |
947 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | 970 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { |
948 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | 971 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", |
949 | le32_to_cpu(rx_pkt_status)); | 972 | le32_to_cpu(rx_pkt_status)); |
950 | return; | 973 | return 0; |
951 | } | 974 | } |
952 | 975 | ||
953 | /* This will be used in several places later */ | 976 | /* This will be used in several places later */ |
@@ -1008,6 +1031,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1008 | 1031 | ||
1009 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | 1032 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, |
1010 | rxb, &rx_status); | 1033 | rxb, &rx_status); |
1034 | return 0; | ||
1011 | } | 1035 | } |
1012 | 1036 | ||
1013 | /** | 1037 | /** |
@@ -1018,7 +1042,8 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1018 | */ | 1042 | */ |
1019 | void iwl_setup_rx_handlers(struct iwl_priv *priv) | 1043 | void iwl_setup_rx_handlers(struct iwl_priv *priv) |
1020 | { | 1044 | { |
1021 | void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 1045 | int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
1046 | struct iwl_device_cmd *cmd); | ||
1022 | 1047 | ||
1023 | handlers = priv->rx_handlers; | 1048 | handlers = priv->rx_handlers; |
1024 | 1049 | ||
@@ -1028,6 +1053,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1028 | handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 1053 | handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
1029 | handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; | 1054 | handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; |
1030 | handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; | 1055 | handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; |
1056 | handlers[REPLY_ADD_STA] = iwl_add_sta_callback; | ||
1031 | 1057 | ||
1032 | /* | 1058 | /* |
1033 | * The same handler is used for both the REPLY to a discrete | 1059 | * The same handler is used for both the REPLY to a discrete |
@@ -1065,9 +1091,11 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1065 | 1091 | ||
1066 | } | 1092 | } |
1067 | 1093 | ||
1068 | void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1094 | int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
1095 | struct iwl_device_cmd *cmd) | ||
1069 | { | 1096 | { |
1070 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1097 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1098 | int err = 0; | ||
1071 | 1099 | ||
1072 | /* | 1100 | /* |
1073 | * Do the notification wait before RX handlers so | 1101 | * Do the notification wait before RX handlers so |
@@ -1102,11 +1130,12 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1102 | * rx_handlers table. See iwl_setup_rx_handlers() */ | 1130 | * rx_handlers table. See iwl_setup_rx_handlers() */ |
1103 | if (priv->rx_handlers[pkt->hdr.cmd]) { | 1131 | if (priv->rx_handlers[pkt->hdr.cmd]) { |
1104 | priv->rx_handlers_stats[pkt->hdr.cmd]++; | 1132 | priv->rx_handlers_stats[pkt->hdr.cmd]++; |
1105 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | 1133 | err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); |
1106 | } else { | 1134 | } else { |
1107 | /* No handling needed */ | 1135 | /* No handling needed */ |
1108 | IWL_DEBUG_RX(priv, | 1136 | IWL_DEBUG_RX(priv, |
1109 | "No handler needed for %s, 0x%02x\n", | 1137 | "No handler needed for %s, 0x%02x\n", |
1110 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 1138 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); |
1111 | } | 1139 | } |
1140 | return err; | ||
1112 | } | 1141 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index fc5af3475392..c5c95d5319b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -114,6 +114,65 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | |||
114 | priv->scan_request = NULL; | 114 | priv->scan_request = NULL; |
115 | } | 115 | } |
116 | 116 | ||
117 | static void iwl_process_scan_complete(struct iwl_priv *priv) | ||
118 | { | ||
119 | bool aborted; | ||
120 | |||
121 | lockdep_assert_held(&priv->shrd->mutex); | ||
122 | |||
123 | if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status)) | ||
124 | return; | ||
125 | |||
126 | IWL_DEBUG_SCAN(priv, "Completed scan.\n"); | ||
127 | |||
128 | cancel_delayed_work(&priv->scan_check); | ||
129 | |||
130 | aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); | ||
131 | if (aborted) | ||
132 | IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); | ||
133 | |||
134 | if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { | ||
135 | IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); | ||
136 | goto out_settings; | ||
137 | } | ||
138 | |||
139 | if (priv->scan_type == IWL_SCAN_ROC) { | ||
140 | ieee80211_remain_on_channel_expired(priv->hw); | ||
141 | priv->hw_roc_channel = NULL; | ||
142 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); | ||
143 | } | ||
144 | |||
145 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | ||
146 | int err; | ||
147 | |||
148 | /* Check if mac80211 requested scan during our internal scan */ | ||
149 | if (priv->scan_request == NULL) | ||
150 | goto out_complete; | ||
151 | |||
152 | /* If so request a new scan */ | ||
153 | err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL, | ||
154 | priv->scan_request->channels[0]->band); | ||
155 | if (err) { | ||
156 | IWL_DEBUG_SCAN(priv, | ||
157 | "failed to initiate pending scan: %d\n", err); | ||
158 | aborted = true; | ||
159 | goto out_complete; | ||
160 | } | ||
161 | |||
162 | return; | ||
163 | } | ||
164 | |||
165 | out_complete: | ||
166 | iwl_complete_scan(priv, aborted); | ||
167 | |||
168 | out_settings: | ||
169 | /* Can we still talk to firmware ? */ | ||
170 | if (!iwl_is_ready_rf(priv->shrd)) | ||
171 | return; | ||
172 | |||
173 | iwlagn_post_scan(priv); | ||
174 | } | ||
175 | |||
117 | void iwl_force_scan_end(struct iwl_priv *priv) | 176 | void iwl_force_scan_end(struct iwl_priv *priv) |
118 | { | 177 | { |
119 | lockdep_assert_held(&priv->shrd->mutex); | 178 | lockdep_assert_held(&priv->shrd->mutex); |
@@ -127,6 +186,7 @@ void iwl_force_scan_end(struct iwl_priv *priv) | |||
127 | clear_bit(STATUS_SCANNING, &priv->shrd->status); | 186 | clear_bit(STATUS_SCANNING, &priv->shrd->status); |
128 | clear_bit(STATUS_SCAN_HW, &priv->shrd->status); | 187 | clear_bit(STATUS_SCAN_HW, &priv->shrd->status); |
129 | clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); | 188 | clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); |
189 | clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status); | ||
130 | iwl_complete_scan(priv, true); | 190 | iwl_complete_scan(priv, true); |
131 | } | 191 | } |
132 | 192 | ||
@@ -169,7 +229,7 @@ int iwl_scan_cancel(struct iwl_priv *priv) | |||
169 | * @ms: amount of time to wait (in milliseconds) for scan to abort | 229 | * @ms: amount of time to wait (in milliseconds) for scan to abort |
170 | * | 230 | * |
171 | */ | 231 | */ |
172 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) | 232 | void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) |
173 | { | 233 | { |
174 | unsigned long timeout = jiffies + msecs_to_jiffies(ms); | 234 | unsigned long timeout = jiffies + msecs_to_jiffies(ms); |
175 | 235 | ||
@@ -181,16 +241,30 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) | |||
181 | 241 | ||
182 | while (time_before_eq(jiffies, timeout)) { | 242 | while (time_before_eq(jiffies, timeout)) { |
183 | if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status)) | 243 | if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status)) |
184 | break; | 244 | goto finished; |
185 | msleep(20); | 245 | msleep(20); |
186 | } | 246 | } |
187 | 247 | ||
188 | return test_bit(STATUS_SCAN_HW, &priv->shrd->status); | 248 | return; |
249 | |||
250 | finished: | ||
251 | /* | ||
252 | * Now STATUS_SCAN_HW is clear. This means that the | ||
253 | * device finished, but the background work is going | ||
254 | * to execute at best as soon as we release the mutex. | ||
255 | * Since we need to be able to issue a new scan right | ||
256 | * after this function returns, run the complete here. | ||
257 | * The STATUS_SCAN_COMPLETE bit will then be cleared | ||
258 | * and prevent the background work from "completing" | ||
259 | * a possible new scan. | ||
260 | */ | ||
261 | iwl_process_scan_complete(priv); | ||
189 | } | 262 | } |
190 | 263 | ||
191 | /* Service response to REPLY_SCAN_CMD (0x80) */ | 264 | /* Service response to REPLY_SCAN_CMD (0x80) */ |
192 | static void iwl_rx_reply_scan(struct iwl_priv *priv, | 265 | static int iwl_rx_reply_scan(struct iwl_priv *priv, |
193 | struct iwl_rx_mem_buffer *rxb) | 266 | struct iwl_rx_mem_buffer *rxb, |
267 | struct iwl_device_cmd *cmd) | ||
194 | { | 268 | { |
195 | #ifdef CONFIG_IWLWIFI_DEBUG | 269 | #ifdef CONFIG_IWLWIFI_DEBUG |
196 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 270 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -199,11 +273,13 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, | |||
199 | 273 | ||
200 | IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status); | 274 | IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status); |
201 | #endif | 275 | #endif |
276 | return 0; | ||
202 | } | 277 | } |
203 | 278 | ||
204 | /* Service SCAN_START_NOTIFICATION (0x82) */ | 279 | /* Service SCAN_START_NOTIFICATION (0x82) */ |
205 | static void iwl_rx_scan_start_notif(struct iwl_priv *priv, | 280 | static int iwl_rx_scan_start_notif(struct iwl_priv *priv, |
206 | struct iwl_rx_mem_buffer *rxb) | 281 | struct iwl_rx_mem_buffer *rxb, |
282 | struct iwl_device_cmd *cmd) | ||
207 | { | 283 | { |
208 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 284 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
209 | struct iwl_scanstart_notification *notif = | 285 | struct iwl_scanstart_notification *notif = |
@@ -218,13 +294,19 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, | |||
218 | le32_to_cpu(notif->tsf_low), | 294 | le32_to_cpu(notif->tsf_low), |
219 | notif->status, notif->beacon_timer); | 295 | notif->status, notif->beacon_timer); |
220 | 296 | ||
221 | if (priv->scan_type == IWL_SCAN_ROC) | 297 | if (priv->scan_type == IWL_SCAN_ROC && |
298 | !priv->hw_roc_start_notified) { | ||
222 | ieee80211_ready_on_channel(priv->hw); | 299 | ieee80211_ready_on_channel(priv->hw); |
300 | priv->hw_roc_start_notified = true; | ||
301 | } | ||
302 | |||
303 | return 0; | ||
223 | } | 304 | } |
224 | 305 | ||
225 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ | 306 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ |
226 | static void iwl_rx_scan_results_notif(struct iwl_priv *priv, | 307 | static int iwl_rx_scan_results_notif(struct iwl_priv *priv, |
227 | struct iwl_rx_mem_buffer *rxb) | 308 | struct iwl_rx_mem_buffer *rxb, |
309 | struct iwl_device_cmd *cmd) | ||
228 | { | 310 | { |
229 | #ifdef CONFIG_IWLWIFI_DEBUG | 311 | #ifdef CONFIG_IWLWIFI_DEBUG |
230 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 312 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
@@ -233,20 +315,24 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, | |||
233 | 315 | ||
234 | IWL_DEBUG_SCAN(priv, "Scan ch.res: " | 316 | IWL_DEBUG_SCAN(priv, "Scan ch.res: " |
235 | "%d [802.11%s] " | 317 | "%d [802.11%s] " |
318 | "probe status: %u:%u " | ||
236 | "(TSF: 0x%08X:%08X) - %d " | 319 | "(TSF: 0x%08X:%08X) - %d " |
237 | "elapsed=%lu usec\n", | 320 | "elapsed=%lu usec\n", |
238 | notif->channel, | 321 | notif->channel, |
239 | notif->band ? "bg" : "a", | 322 | notif->band ? "bg" : "a", |
323 | notif->probe_status, notif->num_probe_not_sent, | ||
240 | le32_to_cpu(notif->tsf_high), | 324 | le32_to_cpu(notif->tsf_high), |
241 | le32_to_cpu(notif->tsf_low), | 325 | le32_to_cpu(notif->tsf_low), |
242 | le32_to_cpu(notif->statistics[0]), | 326 | le32_to_cpu(notif->statistics[0]), |
243 | le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); | 327 | le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); |
244 | #endif | 328 | #endif |
329 | return 0; | ||
245 | } | 330 | } |
246 | 331 | ||
247 | /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ | 332 | /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ |
248 | static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | 333 | static int iwl_rx_scan_complete_notif(struct iwl_priv *priv, |
249 | struct iwl_rx_mem_buffer *rxb) | 334 | struct iwl_rx_mem_buffer *rxb, |
335 | struct iwl_device_cmd *cmd) | ||
250 | { | 336 | { |
251 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 337 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
252 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; | 338 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; |
@@ -256,13 +342,20 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
256 | scan_notif->tsf_low, | 342 | scan_notif->tsf_low, |
257 | scan_notif->tsf_high, scan_notif->status); | 343 | scan_notif->tsf_high, scan_notif->status); |
258 | 344 | ||
259 | /* The HW is no longer scanning */ | ||
260 | clear_bit(STATUS_SCAN_HW, &priv->shrd->status); | ||
261 | |||
262 | IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", | 345 | IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", |
263 | (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", | 346 | (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", |
264 | jiffies_to_msecs(jiffies - priv->scan_start)); | 347 | jiffies_to_msecs(jiffies - priv->scan_start)); |
265 | 348 | ||
349 | /* | ||
350 | * When aborting, we run the scan completed background work inline | ||
351 | * and the background work must then do nothing. The SCAN_COMPLETE | ||
352 | * bit helps implement that logic and thus needs to be set before | ||
353 | * queueing the work. Also, since the scan abort waits for SCAN_HW | ||
354 | * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW | ||
355 | * to avoid a race there. | ||
356 | */ | ||
357 | set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status); | ||
358 | clear_bit(STATUS_SCAN_HW, &priv->shrd->status); | ||
266 | queue_work(priv->shrd->workqueue, &priv->scan_completed); | 359 | queue_work(priv->shrd->workqueue, &priv->scan_completed); |
267 | 360 | ||
268 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && | 361 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && |
@@ -286,6 +379,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
286 | queue_work(priv->shrd->workqueue, | 379 | queue_work(priv->shrd->workqueue, |
287 | &priv->bt_traffic_change_work); | 380 | &priv->bt_traffic_change_work); |
288 | } | 381 | } |
382 | return 0; | ||
289 | } | 383 | } |
290 | 384 | ||
291 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | 385 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) |
@@ -299,9 +393,8 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | |||
299 | iwl_rx_scan_complete_notif; | 393 | iwl_rx_scan_complete_notif; |
300 | } | 394 | } |
301 | 395 | ||
302 | inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | 396 | static u16 iwl_get_active_dwell_time(struct iwl_priv *priv, |
303 | enum ieee80211_band band, | 397 | enum ieee80211_band band, u8 n_probes) |
304 | u8 n_probes) | ||
305 | { | 398 | { |
306 | if (band == IEEE80211_BAND_5GHZ) | 399 | if (band == IEEE80211_BAND_5GHZ) |
307 | return IWL_ACTIVE_DWELL_TIME_52 + | 400 | return IWL_ACTIVE_DWELL_TIME_52 + |
@@ -311,35 +404,481 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | |||
311 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); | 404 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); |
312 | } | 405 | } |
313 | 406 | ||
314 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 407 | static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) |
315 | enum ieee80211_band band, | ||
316 | struct ieee80211_vif *vif) | ||
317 | { | 408 | { |
318 | struct iwl_rxon_context *ctx; | 409 | struct iwl_rxon_context *ctx; |
410 | |||
411 | /* | ||
412 | * If we're associated, we clamp the dwell time 98% | ||
413 | * of the smallest beacon interval (minus 2 * channel | ||
414 | * tune time) | ||
415 | */ | ||
416 | for_each_context(priv, ctx) { | ||
417 | u16 value; | ||
418 | |||
419 | if (!iwl_is_associated_ctx(ctx)) | ||
420 | continue; | ||
421 | value = ctx->beacon_int; | ||
422 | if (!value) | ||
423 | value = IWL_PASSIVE_DWELL_BASE; | ||
424 | value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | ||
425 | dwell_time = min(value, dwell_time); | ||
426 | } | ||
427 | |||
428 | return dwell_time; | ||
429 | } | ||
430 | |||
431 | static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | ||
432 | enum ieee80211_band band) | ||
433 | { | ||
319 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? | 434 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? |
320 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : | 435 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : |
321 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; | 436 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; |
322 | 437 | ||
323 | if (iwl_is_any_associated(priv)) { | 438 | return iwl_limit_dwell(priv, passive); |
439 | } | ||
440 | |||
441 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | ||
442 | struct ieee80211_vif *vif, | ||
443 | enum ieee80211_band band, | ||
444 | struct iwl_scan_channel *scan_ch) | ||
445 | { | ||
446 | const struct ieee80211_supported_band *sband; | ||
447 | u16 passive_dwell = 0; | ||
448 | u16 active_dwell = 0; | ||
449 | int added = 0; | ||
450 | u16 channel = 0; | ||
451 | |||
452 | sband = iwl_get_hw_mode(priv, band); | ||
453 | if (!sband) { | ||
454 | IWL_ERR(priv, "invalid band\n"); | ||
455 | return added; | ||
456 | } | ||
457 | |||
458 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
459 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
460 | |||
461 | if (passive_dwell <= active_dwell) | ||
462 | passive_dwell = active_dwell + 1; | ||
463 | |||
464 | channel = iwl_get_single_channel_number(priv, band); | ||
465 | if (channel) { | ||
466 | scan_ch->channel = cpu_to_le16(channel); | ||
467 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
468 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
469 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
470 | /* Set txpower levels to defaults */ | ||
471 | scan_ch->dsp_atten = 110; | ||
472 | if (band == IEEE80211_BAND_5GHZ) | ||
473 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
474 | else | ||
475 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
476 | added++; | ||
477 | } else | ||
478 | IWL_ERR(priv, "no valid channel found\n"); | ||
479 | return added; | ||
480 | } | ||
481 | |||
482 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | ||
483 | struct ieee80211_vif *vif, | ||
484 | enum ieee80211_band band, | ||
485 | u8 is_active, u8 n_probes, | ||
486 | struct iwl_scan_channel *scan_ch) | ||
487 | { | ||
488 | struct ieee80211_channel *chan; | ||
489 | const struct ieee80211_supported_band *sband; | ||
490 | const struct iwl_channel_info *ch_info; | ||
491 | u16 passive_dwell = 0; | ||
492 | u16 active_dwell = 0; | ||
493 | int added, i; | ||
494 | u16 channel; | ||
495 | |||
496 | sband = iwl_get_hw_mode(priv, band); | ||
497 | if (!sband) | ||
498 | return 0; | ||
499 | |||
500 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); | ||
501 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
502 | |||
503 | if (passive_dwell <= active_dwell) | ||
504 | passive_dwell = active_dwell + 1; | ||
505 | |||
506 | for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { | ||
507 | chan = priv->scan_request->channels[i]; | ||
508 | |||
509 | if (chan->band != band) | ||
510 | continue; | ||
511 | |||
512 | channel = chan->hw_value; | ||
513 | scan_ch->channel = cpu_to_le16(channel); | ||
514 | |||
515 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
516 | if (!is_channel_valid(ch_info)) { | ||
517 | IWL_DEBUG_SCAN(priv, | ||
518 | "Channel %d is INVALID for this band.\n", | ||
519 | channel); | ||
520 | continue; | ||
521 | } | ||
522 | |||
523 | if (!is_active || is_channel_passive(ch_info) || | ||
524 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
525 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
526 | else | ||
527 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | ||
528 | |||
529 | if (n_probes) | ||
530 | scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); | ||
531 | |||
532 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
533 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
534 | |||
535 | /* Set txpower levels to defaults */ | ||
536 | scan_ch->dsp_atten = 110; | ||
537 | |||
538 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
539 | * power level: | ||
540 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
541 | */ | ||
542 | if (band == IEEE80211_BAND_5GHZ) | ||
543 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
544 | else | ||
545 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
546 | |||
547 | IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", | ||
548 | channel, le32_to_cpu(scan_ch->type), | ||
549 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
550 | "ACTIVE" : "PASSIVE", | ||
551 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
552 | active_dwell : passive_dwell); | ||
553 | |||
554 | scan_ch++; | ||
555 | added++; | ||
556 | } | ||
557 | |||
558 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); | ||
559 | return added; | ||
560 | } | ||
561 | |||
562 | static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||
563 | { | ||
564 | struct iwl_host_cmd cmd = { | ||
565 | .id = REPLY_SCAN_CMD, | ||
566 | .len = { sizeof(struct iwl_scan_cmd), }, | ||
567 | .flags = CMD_SYNC, | ||
568 | }; | ||
569 | struct iwl_scan_cmd *scan; | ||
570 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
571 | u32 rate_flags = 0; | ||
572 | u16 cmd_len; | ||
573 | u16 rx_chain = 0; | ||
574 | enum ieee80211_band band; | ||
575 | u8 n_probes = 0; | ||
576 | u8 rx_ant = hw_params(priv).valid_rx_ant; | ||
577 | u8 rate; | ||
578 | bool is_active = false; | ||
579 | int chan_mod; | ||
580 | u8 active_chains; | ||
581 | u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; | ||
582 | int ret; | ||
583 | |||
584 | lockdep_assert_held(&priv->shrd->mutex); | ||
585 | |||
586 | if (vif) | ||
587 | ctx = iwl_rxon_ctx_from_vif(vif); | ||
588 | |||
589 | if (!priv->scan_cmd) { | ||
590 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | ||
591 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
592 | if (!priv->scan_cmd) { | ||
593 | IWL_DEBUG_SCAN(priv, | ||
594 | "fail to allocate memory for scan\n"); | ||
595 | return -ENOMEM; | ||
596 | } | ||
597 | } | ||
598 | scan = priv->scan_cmd; | ||
599 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | ||
600 | |||
601 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | ||
602 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | ||
603 | |||
604 | if (priv->scan_type != IWL_SCAN_ROC && | ||
605 | iwl_is_any_associated(priv)) { | ||
606 | u16 interval = 0; | ||
607 | u32 extra; | ||
608 | u32 suspend_time = 100; | ||
609 | u32 scan_suspend_time = 100; | ||
610 | |||
611 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | ||
612 | switch (priv->scan_type) { | ||
613 | case IWL_SCAN_ROC: | ||
614 | WARN_ON(1); | ||
615 | break; | ||
616 | case IWL_SCAN_RADIO_RESET: | ||
617 | interval = 0; | ||
618 | break; | ||
619 | case IWL_SCAN_NORMAL: | ||
620 | interval = vif->bss_conf.beacon_int; | ||
621 | break; | ||
622 | } | ||
623 | |||
624 | scan->suspend_time = 0; | ||
625 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
626 | if (!interval) | ||
627 | interval = suspend_time; | ||
628 | |||
629 | extra = (suspend_time / interval) << 22; | ||
630 | scan_suspend_time = (extra | | ||
631 | ((suspend_time % interval) * 1024)); | ||
632 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | ||
633 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | ||
634 | scan_suspend_time, interval); | ||
635 | } else if (priv->scan_type == IWL_SCAN_ROC) { | ||
636 | scan->suspend_time = 0; | ||
637 | scan->max_out_time = 0; | ||
638 | scan->quiet_time = 0; | ||
639 | scan->quiet_plcp_th = 0; | ||
640 | } | ||
641 | |||
642 | switch (priv->scan_type) { | ||
643 | case IWL_SCAN_RADIO_RESET: | ||
644 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
645 | break; | ||
646 | case IWL_SCAN_NORMAL: | ||
647 | if (priv->scan_request->n_ssids) { | ||
648 | int i, p = 0; | ||
649 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | ||
650 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | ||
651 | /* always does wildcard anyway */ | ||
652 | if (!priv->scan_request->ssids[i].ssid_len) | ||
653 | continue; | ||
654 | scan->direct_scan[p].id = WLAN_EID_SSID; | ||
655 | scan->direct_scan[p].len = | ||
656 | priv->scan_request->ssids[i].ssid_len; | ||
657 | memcpy(scan->direct_scan[p].ssid, | ||
658 | priv->scan_request->ssids[i].ssid, | ||
659 | priv->scan_request->ssids[i].ssid_len); | ||
660 | n_probes++; | ||
661 | p++; | ||
662 | } | ||
663 | is_active = true; | ||
664 | } else | ||
665 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); | ||
666 | break; | ||
667 | case IWL_SCAN_ROC: | ||
668 | IWL_DEBUG_SCAN(priv, "Start ROC scan.\n"); | ||
669 | break; | ||
670 | } | ||
671 | |||
672 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | ||
673 | scan->tx_cmd.sta_id = ctx->bcast_sta_id; | ||
674 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
675 | |||
676 | switch (priv->scan_band) { | ||
677 | case IEEE80211_BAND_2GHZ: | ||
678 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | ||
679 | chan_mod = le32_to_cpu( | ||
680 | priv->contexts[IWL_RXON_CTX_BSS].active.flags & | ||
681 | RXON_FLG_CHANNEL_MODE_MSK) | ||
682 | >> RXON_FLG_CHANNEL_MODE_POS; | ||
683 | if (chan_mod == CHANNEL_MODE_PURE_40) { | ||
684 | rate = IWL_RATE_6M_PLCP; | ||
685 | } else { | ||
686 | rate = IWL_RATE_1M_PLCP; | ||
687 | rate_flags = RATE_MCS_CCK_MSK; | ||
688 | } | ||
324 | /* | 689 | /* |
325 | * If we're associated, we clamp the maximum passive | 690 | * Internal scans are passive, so we can indiscriminately set |
326 | * dwell time to be 98% of the smallest beacon interval | 691 | * the BT ignore flag on 2.4 GHz since it applies to TX only. |
327 | * (minus 2 * channel tune time) | ||
328 | */ | 692 | */ |
329 | for_each_context(priv, ctx) { | 693 | if (priv->cfg->bt_params && |
330 | u16 value; | 694 | priv->cfg->bt_params->advanced_bt_coexist) |
331 | 695 | scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; | |
332 | if (!iwl_is_associated_ctx(ctx)) | 696 | break; |
333 | continue; | 697 | case IEEE80211_BAND_5GHZ: |
334 | value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0; | 698 | rate = IWL_RATE_6M_PLCP; |
335 | if ((value > IWL_PASSIVE_DWELL_BASE) || !value) | 699 | break; |
336 | value = IWL_PASSIVE_DWELL_BASE; | 700 | default: |
337 | value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | 701 | IWL_WARN(priv, "Invalid scan band\n"); |
338 | passive = min(value, passive); | 702 | return -EIO; |
703 | } | ||
704 | |||
705 | /* | ||
706 | * If active scanning is requested but a certain channel is | ||
707 | * marked passive, we can do active scanning if we detect | ||
708 | * transmissions. | ||
709 | * | ||
710 | * There is an issue with some firmware versions that triggers | ||
711 | * a sysassert on a "good CRC threshold" of zero (== disabled), | ||
712 | * on a radar channel even though this means that we should NOT | ||
713 | * send probes. | ||
714 | * | ||
715 | * The "good CRC threshold" is the number of frames that we | ||
716 | * need to receive during our dwell time on a channel before | ||
717 | * sending out probes -- setting this to a huge value will | ||
718 | * mean we never reach it, but at the same time work around | ||
719 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | ||
720 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | ||
721 | * | ||
722 | * This was fixed in later versions along with some other | ||
723 | * scan changes, and the threshold behaves as a flag in those | ||
724 | * versions. | ||
725 | */ | ||
726 | if (priv->new_scan_threshold_behaviour) | ||
727 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
728 | IWL_GOOD_CRC_TH_DISABLED; | ||
729 | else | ||
730 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
731 | IWL_GOOD_CRC_TH_NEVER; | ||
732 | |||
733 | band = priv->scan_band; | ||
734 | |||
735 | if (priv->cfg->scan_rx_antennas[band]) | ||
736 | rx_ant = priv->cfg->scan_rx_antennas[band]; | ||
737 | |||
738 | if (band == IEEE80211_BAND_2GHZ && | ||
739 | priv->cfg->bt_params && | ||
740 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
741 | /* transmit 2.4 GHz probes only on first antenna */ | ||
742 | scan_tx_antennas = first_antenna(scan_tx_antennas); | ||
743 | } | ||
744 | |||
745 | priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, | ||
746 | priv->scan_tx_ant[band], | ||
747 | scan_tx_antennas); | ||
748 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | ||
749 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | ||
750 | |||
751 | /* In power save mode use one chain, otherwise use all chains */ | ||
752 | if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { | ||
753 | /* rx_ant has been set to all valid chains previously */ | ||
754 | active_chains = rx_ant & | ||
755 | ((u8)(priv->chain_noise_data.active_chains)); | ||
756 | if (!active_chains) | ||
757 | active_chains = rx_ant; | ||
758 | |||
759 | IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", | ||
760 | priv->chain_noise_data.active_chains); | ||
761 | |||
762 | rx_ant = first_antenna(active_chains); | ||
763 | } | ||
764 | if (priv->cfg->bt_params && | ||
765 | priv->cfg->bt_params->advanced_bt_coexist && | ||
766 | priv->bt_full_concurrent) { | ||
767 | /* operated as 1x1 in full concurrency mode */ | ||
768 | rx_ant = first_antenna(rx_ant); | ||
769 | } | ||
770 | |||
771 | /* MIMO is not used here, but value is required */ | ||
772 | rx_chain |= | ||
773 | hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | ||
774 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | ||
775 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | ||
776 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | ||
777 | scan->rx_chain = cpu_to_le16(rx_chain); | ||
778 | switch (priv->scan_type) { | ||
779 | case IWL_SCAN_NORMAL: | ||
780 | cmd_len = iwl_fill_probe_req(priv, | ||
781 | (struct ieee80211_mgmt *)scan->data, | ||
782 | vif->addr, | ||
783 | priv->scan_request->ie, | ||
784 | priv->scan_request->ie_len, | ||
785 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
786 | break; | ||
787 | case IWL_SCAN_RADIO_RESET: | ||
788 | case IWL_SCAN_ROC: | ||
789 | /* use bcast addr, will not be transmitted but must be valid */ | ||
790 | cmd_len = iwl_fill_probe_req(priv, | ||
791 | (struct ieee80211_mgmt *)scan->data, | ||
792 | iwl_bcast_addr, NULL, 0, | ||
793 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
794 | break; | ||
795 | default: | ||
796 | BUG(); | ||
797 | } | ||
798 | scan->tx_cmd.len = cpu_to_le16(cmd_len); | ||
799 | |||
800 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | ||
801 | RXON_FILTER_BCON_AWARE_MSK); | ||
802 | |||
803 | switch (priv->scan_type) { | ||
804 | case IWL_SCAN_RADIO_RESET: | ||
805 | scan->channel_count = | ||
806 | iwl_get_single_channel_for_scan(priv, vif, band, | ||
807 | (void *)&scan->data[cmd_len]); | ||
808 | break; | ||
809 | case IWL_SCAN_NORMAL: | ||
810 | scan->channel_count = | ||
811 | iwl_get_channels_for_scan(priv, vif, band, | ||
812 | is_active, n_probes, | ||
813 | (void *)&scan->data[cmd_len]); | ||
814 | break; | ||
815 | case IWL_SCAN_ROC: { | ||
816 | struct iwl_scan_channel *scan_ch; | ||
817 | int n_chan, i; | ||
818 | u16 dwell; | ||
819 | |||
820 | dwell = iwl_limit_dwell(priv, priv->hw_roc_duration); | ||
821 | n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell); | ||
822 | |||
823 | scan->channel_count = n_chan; | ||
824 | |||
825 | scan_ch = (void *)&scan->data[cmd_len]; | ||
826 | |||
827 | for (i = 0; i < n_chan; i++) { | ||
828 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
829 | scan_ch->channel = | ||
830 | cpu_to_le16(priv->hw_roc_channel->hw_value); | ||
831 | |||
832 | if (i == n_chan - 1) | ||
833 | dwell = priv->hw_roc_duration - i * dwell; | ||
834 | |||
835 | scan_ch->active_dwell = | ||
836 | scan_ch->passive_dwell = cpu_to_le16(dwell); | ||
837 | |||
838 | /* Set txpower levels to defaults */ | ||
839 | scan_ch->dsp_atten = 110; | ||
840 | |||
841 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
842 | * power level: | ||
843 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
844 | */ | ||
845 | if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ) | ||
846 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
847 | else | ||
848 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
849 | |||
850 | scan_ch++; | ||
851 | } | ||
339 | } | 852 | } |
853 | |||
854 | break; | ||
855 | } | ||
856 | |||
857 | if (scan->channel_count == 0) { | ||
858 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | ||
859 | return -EIO; | ||
860 | } | ||
861 | |||
862 | cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + | ||
863 | scan->channel_count * sizeof(struct iwl_scan_channel); | ||
864 | cmd.data[0] = scan; | ||
865 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
866 | scan->len = cpu_to_le16(cmd.len[0]); | ||
867 | |||
868 | /* set scan bit here for PAN params */ | ||
869 | set_bit(STATUS_SCAN_HW, &priv->shrd->status); | ||
870 | |||
871 | ret = iwlagn_set_pan_params(priv); | ||
872 | if (ret) | ||
873 | return ret; | ||
874 | |||
875 | ret = iwl_trans_send_cmd(trans(priv), &cmd); | ||
876 | if (ret) { | ||
877 | clear_bit(STATUS_SCAN_HW, &priv->shrd->status); | ||
878 | iwlagn_set_pan_params(priv); | ||
340 | } | 879 | } |
341 | 880 | ||
342 | return passive; | 881 | return ret; |
343 | } | 882 | } |
344 | 883 | ||
345 | void iwl_init_scan_params(struct iwl_priv *priv) | 884 | void iwl_init_scan_params(struct iwl_priv *priv) |
@@ -415,31 +954,33 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
415 | 954 | ||
416 | mutex_lock(&priv->shrd->mutex); | 955 | mutex_lock(&priv->shrd->mutex); |
417 | 956 | ||
418 | if (test_bit(STATUS_SCANNING, &priv->shrd->status) && | ||
419 | priv->scan_type != IWL_SCAN_NORMAL) { | ||
420 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
421 | ret = -EAGAIN; | ||
422 | goto out_unlock; | ||
423 | } | ||
424 | |||
425 | /* mac80211 will only ask for one band at a time */ | ||
426 | priv->scan_request = req; | ||
427 | priv->scan_vif = vif; | ||
428 | |||
429 | /* | 957 | /* |
430 | * If an internal scan is in progress, just set | 958 | * If an internal scan is in progress, just set |
431 | * up the scan_request as per above. | 959 | * up the scan_request as per above. |
432 | */ | 960 | */ |
433 | if (priv->scan_type != IWL_SCAN_NORMAL) { | 961 | if (priv->scan_type != IWL_SCAN_NORMAL) { |
434 | IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); | 962 | IWL_DEBUG_SCAN(priv, |
963 | "SCAN request during internal scan - defer\n"); | ||
964 | priv->scan_request = req; | ||
965 | priv->scan_vif = vif; | ||
435 | ret = 0; | 966 | ret = 0; |
436 | } else | 967 | } else { |
968 | priv->scan_request = req; | ||
969 | priv->scan_vif = vif; | ||
970 | /* | ||
971 | * mac80211 will only ask for one band at a time | ||
972 | * so using channels[0] here is ok | ||
973 | */ | ||
437 | ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL, | 974 | ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL, |
438 | req->channels[0]->band); | 975 | req->channels[0]->band); |
976 | if (ret) { | ||
977 | priv->scan_request = NULL; | ||
978 | priv->scan_vif = NULL; | ||
979 | } | ||
980 | } | ||
439 | 981 | ||
440 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 982 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
441 | 983 | ||
442 | out_unlock: | ||
443 | mutex_unlock(&priv->shrd->mutex); | 984 | mutex_unlock(&priv->shrd->mutex); |
444 | 985 | ||
445 | return ret; | 986 | return ret; |
@@ -557,61 +1098,10 @@ static void iwl_bg_abort_scan(struct work_struct *work) | |||
557 | static void iwl_bg_scan_completed(struct work_struct *work) | 1098 | static void iwl_bg_scan_completed(struct work_struct *work) |
558 | { | 1099 | { |
559 | struct iwl_priv *priv = | 1100 | struct iwl_priv *priv = |
560 | container_of(work, struct iwl_priv, scan_completed); | 1101 | container_of(work, struct iwl_priv, scan_completed); |
561 | bool aborted; | ||
562 | |||
563 | IWL_DEBUG_SCAN(priv, "Completed scan.\n"); | ||
564 | |||
565 | cancel_delayed_work(&priv->scan_check); | ||
566 | 1102 | ||
567 | mutex_lock(&priv->shrd->mutex); | 1103 | mutex_lock(&priv->shrd->mutex); |
568 | 1104 | iwl_process_scan_complete(priv); | |
569 | aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); | ||
570 | if (aborted) | ||
571 | IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); | ||
572 | |||
573 | if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { | ||
574 | IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); | ||
575 | goto out_settings; | ||
576 | } | ||
577 | |||
578 | if (priv->scan_type == IWL_SCAN_ROC) { | ||
579 | ieee80211_remain_on_channel_expired(priv->hw); | ||
580 | priv->hw_roc_channel = NULL; | ||
581 | schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); | ||
582 | } | ||
583 | |||
584 | if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | ||
585 | int err; | ||
586 | |||
587 | /* Check if mac80211 requested scan during our internal scan */ | ||
588 | if (priv->scan_request == NULL) | ||
589 | goto out_complete; | ||
590 | |||
591 | /* If so request a new scan */ | ||
592 | err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL, | ||
593 | priv->scan_request->channels[0]->band); | ||
594 | if (err) { | ||
595 | IWL_DEBUG_SCAN(priv, | ||
596 | "failed to initiate pending scan: %d\n", err); | ||
597 | aborted = true; | ||
598 | goto out_complete; | ||
599 | } | ||
600 | |||
601 | goto out; | ||
602 | } | ||
603 | |||
604 | out_complete: | ||
605 | iwl_complete_scan(priv, aborted); | ||
606 | |||
607 | out_settings: | ||
608 | /* Can we still talk to firmware ? */ | ||
609 | if (!iwl_is_ready_rf(priv->shrd)) | ||
610 | goto out; | ||
611 | |||
612 | iwlagn_post_scan(priv); | ||
613 | |||
614 | out: | ||
615 | mutex_unlock(&priv->shrd->mutex); | 1105 | mutex_unlock(&priv->shrd->mutex); |
616 | } | 1106 | } |
617 | 1107 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index d987bee5e6ce..8747bbdf8983 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -72,8 +72,27 @@ | |||
72 | 72 | ||
73 | #include "iwl-commands.h" | 73 | #include "iwl-commands.h" |
74 | 74 | ||
75 | /*This files includes all the types / functions that are exported by the | 75 | /** |
76 | * upper layer to the bus and transport layer */ | 76 | * DOC: shared area - role and goal |
77 | * | ||
78 | * The shared area contains all the data exported by the upper layer to the | ||
79 | * other layers. Since the bus and transport layer shouldn't dereference | ||
80 | * iwl_priv, all the data needed by the upper layer and the transport / bus | ||
81 | * layer must be here. | ||
82 | * The shared area also holds pointer to all the other layers. This allows a | ||
83 | * layer to call a function from another layer. | ||
84 | * | ||
85 | * NOTE: All the layers hold a pointer to the shared area which must be shrd. | ||
86 | * A few macros assume that (_m)->shrd points to the shared area no matter | ||
87 | * what _m is. | ||
88 | * | ||
89 | * gets notifications about enumeration, suspend, resume. | ||
90 | * For the moment, the bus layer is not a linux kernel module as itself, and | ||
91 | * the module_init function of the driver must call the bus specific | ||
92 | * registration functions. These functions are listed at the end of this file. | ||
93 | * For the moment, there is only one implementation of this interface: PCI-e. | ||
94 | * This implementation is iwl-pci.c | ||
95 | */ | ||
77 | 96 | ||
78 | struct iwl_cfg; | 97 | struct iwl_cfg; |
79 | struct iwl_bus; | 98 | struct iwl_bus; |
@@ -90,6 +109,9 @@ extern struct iwl_mod_params iwlagn_mod_params; | |||
90 | 109 | ||
91 | /** | 110 | /** |
92 | * struct iwl_mod_params | 111 | * struct iwl_mod_params |
112 | * | ||
113 | * Holds the module parameters | ||
114 | * | ||
93 | * @sw_crypto: using hardware encryption, default = 0 | 115 | * @sw_crypto: using hardware encryption, default = 0 |
94 | * @num_of_queues: number of tx queue, HW dependent | 116 | * @num_of_queues: number of tx queue, HW dependent |
95 | * @disable_11n: 11n capabilities enabled, default = 0 | 117 | * @disable_11n: 11n capabilities enabled, default = 0 |
@@ -134,20 +156,24 @@ struct iwl_mod_params { | |||
134 | 156 | ||
135 | /** | 157 | /** |
136 | * struct iwl_hw_params | 158 | * struct iwl_hw_params |
159 | * | ||
160 | * Holds the module parameters | ||
161 | * | ||
137 | * @max_txq_num: Max # Tx queues supported | 162 | * @max_txq_num: Max # Tx queues supported |
138 | * @num_ampdu_queues: num of ampdu queues | 163 | * @num_ampdu_queues: num of ampdu queues |
139 | * @tx/rx_chains_num: Number of TX/RX chains | 164 | * @tx_chains_num: Number of TX chains |
140 | * @valid_tx/rx_ant: usable antennas | 165 | * @rx_chains_num: Number of RX chains |
141 | * @max_stations: | 166 | * @valid_tx_ant: usable antennas for TX |
142 | * @ht40_channel: is 40MHz width possible in band 2.4 | 167 | * @valid_rx_ant: usable antennas for RX |
143 | * @beacon_time_tsf_bits: number of valid tsf bits for beacon time | 168 | * @max_stations: the maximal number of stations |
144 | * @sku: | 169 | * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX) |
170 | * @sku: sku read from EEPROM | ||
145 | * @rx_page_order: Rx buffer page order | 171 | * @rx_page_order: Rx buffer page order |
146 | * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR | 172 | * @max_inst_size: for ucode use |
147 | * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) | 173 | * @max_data_size: for ucode use |
148 | * @sw_crypto: 0 for hw, 1 for sw | 174 | * @ct_kill_threshold: temperature threshold - in hw dependent unit |
149 | * @max_xxx_size: for ucode uses | 175 | * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit |
150 | * @ct_kill_threshold: temperature threshold | 176 | * relevant for 1000, 6000 and up |
151 | * @wd_timeout: TX queues watchdog timeout | 177 | * @wd_timeout: TX queues watchdog timeout |
152 | * @calib_init_cfg: setup initial calibrations for the hw | 178 | * @calib_init_cfg: setup initial calibrations for the hw |
153 | * @calib_rt_cfg: setup runtime calibrations for the hw | 179 | * @calib_rt_cfg: setup runtime calibrations for the hw |
@@ -163,14 +189,12 @@ struct iwl_hw_params { | |||
163 | u8 max_stations; | 189 | u8 max_stations; |
164 | u8 ht40_channel; | 190 | u8 ht40_channel; |
165 | bool shadow_reg_enable; | 191 | bool shadow_reg_enable; |
166 | u16 beacon_time_tsf_bits; | ||
167 | u16 sku; | 192 | u16 sku; |
168 | u32 rx_page_order; | 193 | u32 rx_page_order; |
169 | u32 max_inst_size; | 194 | u32 max_inst_size; |
170 | u32 max_data_size; | 195 | u32 max_data_size; |
171 | u32 ct_kill_threshold; /* value in hw-dependent units */ | 196 | u32 ct_kill_threshold; |
172 | u32 ct_kill_exit_threshold; /* value in hw-dependent units */ | 197 | u32 ct_kill_exit_threshold; |
173 | /* for 1000, 6000 series and up */ | ||
174 | unsigned int wd_timeout; | 198 | unsigned int wd_timeout; |
175 | 199 | ||
176 | u32 calib_init_cfg; | 200 | u32 calib_init_cfg; |
@@ -179,28 +203,59 @@ struct iwl_hw_params { | |||
179 | }; | 203 | }; |
180 | 204 | ||
181 | /** | 205 | /** |
182 | * struct iwl_ht_agg - aggregation status while waiting for block-ack | 206 | * enum iwl_agg_state |
183 | * @txq_id: Tx queue used for Tx attempt | ||
184 | * @wait_for_ba: Expect block-ack before next Tx reply | ||
185 | * @rate_n_flags: Rate at which Tx was attempted | ||
186 | * | 207 | * |
187 | * If REPLY_TX indicates that aggregation was attempted, driver must wait | 208 | * The state machine of the BA agreement establishment / tear down. |
188 | * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info | 209 | * These states relate to a specific RA / TID. |
189 | * until block ack arrives. | 210 | * |
211 | * @IWL_AGG_OFF: aggregation is not used | ||
212 | * @IWL_AGG_ON: aggregation session is up | ||
213 | * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the | ||
214 | * HW queue to be empty from packets for this RA /TID. | ||
215 | * @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the | ||
216 | * HW queue to be empty from packets for this RA /TID. | ||
217 | */ | ||
218 | enum iwl_agg_state { | ||
219 | IWL_AGG_OFF = 0, | ||
220 | IWL_AGG_ON, | ||
221 | IWL_EMPTYING_HW_QUEUE_ADDBA, | ||
222 | IWL_EMPTYING_HW_QUEUE_DELBA, | ||
223 | }; | ||
224 | |||
225 | /** | ||
226 | * struct iwl_ht_agg - aggregation state machine | ||
227 | |||
228 | * This structs holds the states for the BA agreement establishment and tear | ||
229 | * down. It also holds the state during the BA session itself. This struct is | ||
230 | * duplicated for each RA / TID. | ||
231 | |||
232 | * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the | ||
233 | * Tx response (REPLY_TX), and the block ack notification | ||
234 | * (REPLY_COMPRESSED_BA). | ||
235 | * @state: state of the BA agreement establishment / tear down. | ||
236 | * @txq_id: Tx queue used by the BA session - used by the transport layer. | ||
237 | * Needed by the upper layer for debugfs only. | ||
238 | * @wait_for_ba: Expect block-ack before next Tx reply | ||
190 | */ | 239 | */ |
191 | struct iwl_ht_agg { | 240 | struct iwl_ht_agg { |
192 | u16 txq_id; | ||
193 | u16 wait_for_ba; | ||
194 | u32 rate_n_flags; | 241 | u32 rate_n_flags; |
195 | #define IWL_AGG_OFF 0 | 242 | enum iwl_agg_state state; |
196 | #define IWL_AGG_ON 1 | 243 | u16 txq_id; |
197 | #define IWL_EMPTYING_HW_QUEUE_ADDBA 2 | 244 | bool wait_for_ba; |
198 | #define IWL_EMPTYING_HW_QUEUE_DELBA 3 | ||
199 | u8 state; | ||
200 | }; | 245 | }; |
201 | 246 | ||
247 | /** | ||
248 | * struct iwl_tid_data - one for each RA / TID | ||
249 | |||
250 | * This structs holds the states for each RA / TID. | ||
251 | |||
252 | * @seq_number: the next WiFi sequence number to use | ||
253 | * @tfds_in_queue: number of packets sent to the HW queues. | ||
254 | * Exported for debugfs only | ||
255 | * @agg: aggregation state machine | ||
256 | */ | ||
202 | struct iwl_tid_data { | 257 | struct iwl_tid_data { |
203 | u16 seq_number; /* agn only */ | 258 | u16 seq_number; |
204 | u16 tfds_in_queue; | 259 | u16 tfds_in_queue; |
205 | struct iwl_ht_agg agg; | 260 | struct iwl_ht_agg agg; |
206 | }; | 261 | }; |
@@ -246,12 +301,6 @@ struct iwl_shared { | |||
246 | spinlock_t sta_lock; | 301 | spinlock_t sta_lock; |
247 | struct mutex mutex; | 302 | struct mutex mutex; |
248 | 303 | ||
249 | /*these 2 shouldn't really be here, but they are needed for | ||
250 | * iwl_queue_stop, which is called from the upper layer too | ||
251 | */ | ||
252 | u8 mac80211_registered; | ||
253 | struct ieee80211_hw *hw; | ||
254 | |||
255 | struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; | 304 | struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; |
256 | 305 | ||
257 | wait_queue_head_t wait_command_queue; | 306 | wait_queue_head_t wait_command_queue; |
@@ -371,16 +420,14 @@ enum iwl_rxon_context_id { | |||
371 | NUM_IWL_RXON_CTX | 420 | NUM_IWL_RXON_CTX |
372 | }; | 421 | }; |
373 | 422 | ||
374 | #ifdef CONFIG_PM | ||
375 | int iwl_suspend(struct iwl_priv *priv); | ||
376 | int iwl_resume(struct iwl_priv *priv); | ||
377 | #endif /* !CONFIG_PM */ | ||
378 | |||
379 | int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | 423 | int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, |
380 | struct iwl_cfg *cfg); | 424 | struct iwl_cfg *cfg); |
381 | void __devexit iwl_remove(struct iwl_priv * priv); | 425 | void __devexit iwl_remove(struct iwl_priv * priv); |
426 | struct iwl_device_cmd; | ||
427 | int __must_check iwl_rx_dispatch(struct iwl_priv *priv, | ||
428 | struct iwl_rx_mem_buffer *rxb, | ||
429 | struct iwl_device_cmd *cmd); | ||
382 | 430 | ||
383 | void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | ||
384 | int iwlagn_hw_valid_rtc_data_addr(u32 addr); | 431 | int iwlagn_hw_valid_rtc_data_addr(u32 addr); |
385 | void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, | 432 | void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, |
386 | enum iwl_rxon_context_id ctx, | 433 | enum iwl_rxon_context_id ctx, |
@@ -390,20 +437,26 @@ void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, | |||
390 | u8 sta_id, u8 tid); | 437 | u8 sta_id, u8 tid); |
391 | void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state); | 438 | void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state); |
392 | void iwl_nic_config(struct iwl_priv *priv); | 439 | void iwl_nic_config(struct iwl_priv *priv); |
440 | void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb); | ||
393 | void iwl_apm_stop(struct iwl_priv *priv); | 441 | void iwl_apm_stop(struct iwl_priv *priv); |
394 | int iwl_apm_init(struct iwl_priv *priv); | 442 | int iwl_apm_init(struct iwl_priv *priv); |
395 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); | 443 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); |
396 | const char *get_cmd_string(u8 cmd); | 444 | const char *get_cmd_string(u8 cmd); |
397 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); | 445 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); |
398 | 446 | ||
447 | void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac); | ||
448 | void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac); | ||
449 | |||
399 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 450 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
400 | void iwl_reset_traffic_log(struct iwl_priv *priv); | 451 | void iwl_reset_traffic_log(struct iwl_priv *priv); |
401 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 452 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
402 | 453 | ||
403 | #ifdef CONFIG_IWLWIFI_DEBUG | 454 | #ifdef CONFIG_IWLWIFI_DEBUG |
404 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid); | 455 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, |
456 | enum iwl_rxon_context_id ctxid); | ||
405 | #else | 457 | #else |
406 | static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid) | 458 | static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, |
459 | enum iwl_rxon_context_id ctxid) | ||
407 | { | 460 | { |
408 | } | 461 | } |
409 | #endif | 462 | #endif |
@@ -436,6 +489,7 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid) | |||
436 | #define STATUS_FW_ERROR 17 | 489 | #define STATUS_FW_ERROR 17 |
437 | #define STATUS_DEVICE_ENABLED 18 | 490 | #define STATUS_DEVICE_ENABLED 18 |
438 | #define STATUS_CHANNEL_SWITCH_PENDING 19 | 491 | #define STATUS_CHANNEL_SWITCH_PENDING 19 |
492 | #define STATUS_SCAN_COMPLETE 20 | ||
439 | 493 | ||
440 | static inline int iwl_is_ready(struct iwl_shared *shrd) | 494 | static inline int iwl_is_ready(struct iwl_shared *shrd) |
441 | { | 495 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index e24135e7d37d..580a4d702ff3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -59,8 +59,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | |||
59 | 59 | ||
60 | static int iwl_process_add_sta_resp(struct iwl_priv *priv, | 60 | static int iwl_process_add_sta_resp(struct iwl_priv *priv, |
61 | struct iwl_addsta_cmd *addsta, | 61 | struct iwl_addsta_cmd *addsta, |
62 | struct iwl_rx_packet *pkt, | 62 | struct iwl_rx_packet *pkt) |
63 | bool sync) | ||
64 | { | 63 | { |
65 | u8 sta_id = addsta->sta.sta_id; | 64 | u8 sta_id = addsta->sta.sta_id; |
66 | unsigned long flags; | 65 | unsigned long flags; |
@@ -123,15 +122,14 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
123 | return ret; | 122 | return ret; |
124 | } | 123 | } |
125 | 124 | ||
126 | static void iwl_add_sta_callback(struct iwl_shared *shrd, | 125 | int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, |
127 | struct iwl_device_cmd *cmd, | 126 | struct iwl_device_cmd *cmd) |
128 | struct iwl_rx_packet *pkt) | ||
129 | { | 127 | { |
128 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
130 | struct iwl_addsta_cmd *addsta = | 129 | struct iwl_addsta_cmd *addsta = |
131 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | 130 | (struct iwl_addsta_cmd *) cmd->payload; |
132 | |||
133 | iwl_process_add_sta_resp(shrd->priv, addsta, pkt, false); | ||
134 | 131 | ||
132 | return iwl_process_add_sta_resp(priv, addsta, pkt); | ||
135 | } | 133 | } |
136 | 134 | ||
137 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | 135 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) |
@@ -147,7 +145,6 @@ static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
147 | int iwl_send_add_sta(struct iwl_priv *priv, | 145 | int iwl_send_add_sta(struct iwl_priv *priv, |
148 | struct iwl_addsta_cmd *sta, u8 flags) | 146 | struct iwl_addsta_cmd *sta, u8 flags) |
149 | { | 147 | { |
150 | struct iwl_rx_packet *pkt = NULL; | ||
151 | int ret = 0; | 148 | int ret = 0; |
152 | u8 data[sizeof(*sta)]; | 149 | u8 data[sizeof(*sta)]; |
153 | struct iwl_host_cmd cmd = { | 150 | struct iwl_host_cmd cmd = { |
@@ -160,9 +157,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
160 | IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", | 157 | IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", |
161 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); | 158 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); |
162 | 159 | ||
163 | if (flags & CMD_ASYNC) | 160 | if (!(flags & CMD_ASYNC)) { |
164 | cmd.callback = iwl_add_sta_callback; | ||
165 | else { | ||
166 | cmd.flags |= CMD_WANT_SKB; | 161 | cmd.flags |= CMD_WANT_SKB; |
167 | might_sleep(); | 162 | might_sleep(); |
168 | } | 163 | } |
@@ -172,14 +167,16 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
172 | 167 | ||
173 | if (ret || (flags & CMD_ASYNC)) | 168 | if (ret || (flags & CMD_ASYNC)) |
174 | return ret; | 169 | return ret; |
170 | /*else the command was successfully sent in SYNC mode, need to free | ||
171 | * the reply page */ | ||
175 | 172 | ||
176 | if (ret == 0) { | ||
177 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | ||
178 | ret = iwl_process_add_sta_resp(priv, sta, pkt, true); | ||
179 | } | ||
180 | iwl_free_pages(priv->shrd, cmd.reply_page); | 173 | iwl_free_pages(priv->shrd, cmd.reply_page); |
181 | 174 | ||
182 | return ret; | 175 | if (cmd.handler_status) |
176 | IWL_ERR(priv, "%s - error in the CMD response %d", __func__, | ||
177 | cmd.handler_status); | ||
178 | |||
179 | return cmd.handler_status; | ||
183 | } | 180 | } |
184 | 181 | ||
185 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | 182 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, |
@@ -305,7 +302,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
305 | station->ctxid = ctx->ctxid; | 302 | station->ctxid = ctx->ctxid; |
306 | 303 | ||
307 | if (sta) { | 304 | if (sta) { |
308 | struct iwl_station_priv_common *sta_priv; | 305 | struct iwl_station_priv *sta_priv; |
309 | 306 | ||
310 | sta_priv = (void *)sta->drv_priv; | 307 | sta_priv = (void *)sta->drv_priv; |
311 | sta_priv->ctx = ctx; | 308 | sta_priv->ctx = ctx; |
@@ -821,7 +818,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, | |||
821 | struct ieee80211_sta *sta) | 818 | struct ieee80211_sta *sta) |
822 | { | 819 | { |
823 | struct iwl_priv *priv = hw->priv; | 820 | struct iwl_priv *priv = hw->priv; |
824 | struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv; | 821 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
825 | int ret; | 822 | int ret; |
826 | 823 | ||
827 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", | 824 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", |
@@ -829,7 +826,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, | |||
829 | mutex_lock(&priv->shrd->mutex); | 826 | mutex_lock(&priv->shrd->mutex); |
830 | IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", | 827 | IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", |
831 | sta->addr); | 828 | sta->addr); |
832 | ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); | 829 | ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr); |
833 | if (ret) | 830 | if (ret) |
834 | IWL_ERR(priv, "Error removing station %pM\n", | 831 | IWL_ERR(priv, "Error removing station %pM\n", |
835 | sta->addr); | 832 | sta->addr); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 9641eb6b1d0a..1bca0dabde8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -61,6 +61,9 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
61 | int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | 61 | int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, |
62 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); | 62 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); |
63 | void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | 63 | void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |
64 | int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, | ||
65 | struct iwl_device_cmd *cmd); | ||
66 | |||
64 | 67 | ||
65 | /** | 68 | /** |
66 | * iwl_clear_driver_stations - clear knowledge of all stations from driver | 69 | * iwl_clear_driver_stations - clear knowledge of all stations from driver |
@@ -102,7 +105,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) | |||
102 | if (WARN_ON(!sta)) | 105 | if (WARN_ON(!sta)) |
103 | return IWL_INVALID_STATION; | 106 | return IWL_INVALID_STATION; |
104 | 107 | ||
105 | return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; | 108 | return ((struct iwl_station_priv *)sta->drv_priv)->sta_id; |
106 | } | 109 | } |
107 | 110 | ||
108 | /** | 111 | /** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 8047e955a27b..2b6756e8b8f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | |||
@@ -118,16 +118,6 @@ struct iwl_dma_ptr { | |||
118 | struct iwl_cmd_meta { | 118 | struct iwl_cmd_meta { |
119 | /* only for SYNC commands, iff the reply skb is wanted */ | 119 | /* only for SYNC commands, iff the reply skb is wanted */ |
120 | struct iwl_host_cmd *source; | 120 | struct iwl_host_cmd *source; |
121 | /* | ||
122 | * only for ASYNC commands | ||
123 | * (which is somewhat stupid -- look at iwl-sta.c for instance | ||
124 | * which duplicates a bunch of code because the callback isn't | ||
125 | * invoked for SYNC commands, if it were and its result passed | ||
126 | * through it would be simpler...) | ||
127 | */ | ||
128 | void (*callback)(struct iwl_shared *shrd, | ||
129 | struct iwl_device_cmd *cmd, | ||
130 | struct iwl_rx_packet *pkt); | ||
131 | 121 | ||
132 | u32 flags; | 122 | u32 flags; |
133 | 123 | ||
@@ -285,10 +275,8 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, | |||
285 | dma_addr_t addr, u16 len, u8 reset); | 275 | dma_addr_t addr, u16 len, u8 reset); |
286 | int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); | 276 | int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); |
287 | int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | 277 | int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
288 | int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, | ||
289 | u32 flags, u16 len, const void *data); | ||
290 | void iwl_tx_cmd_complete(struct iwl_trans *trans, | 278 | void iwl_tx_cmd_complete(struct iwl_trans *trans, |
291 | struct iwl_rx_mem_buffer *rxb); | 279 | struct iwl_rx_mem_buffer *rxb, int handler_status); |
292 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | 280 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, |
293 | struct iwl_tx_queue *txq, | 281 | struct iwl_tx_queue *txq, |
294 | u16 byte_cnt); | 282 | u16 byte_cnt); |
@@ -307,7 +295,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | |||
307 | enum iwl_rxon_context_id ctx, | 295 | enum iwl_rxon_context_id ctx, |
308 | int sta_id, int tid, int frame_limit); | 296 | int sta_id, int tid, int frame_limit); |
309 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | 297 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, |
310 | int index); | 298 | int index, enum dma_data_direction dma_dir); |
311 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | 299 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, |
312 | struct sk_buff_head *skbs); | 300 | struct sk_buff_head *skbs); |
313 | int iwl_queue_space(const struct iwl_queue *q); | 301 | int iwl_queue_space(const struct iwl_queue *q); |
@@ -375,12 +363,9 @@ static inline void iwl_wake_queue(struct iwl_trans *trans, | |||
375 | struct iwl_trans_pcie *trans_pcie = | 363 | struct iwl_trans_pcie *trans_pcie = |
376 | IWL_TRANS_GET_PCIE_TRANS(trans); | 364 | IWL_TRANS_GET_PCIE_TRANS(trans); |
377 | 365 | ||
378 | if (unlikely(!trans->shrd->mac80211_registered)) | ||
379 | return; | ||
380 | |||
381 | if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) | 366 | if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) |
382 | if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) | 367 | if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) |
383 | ieee80211_wake_queue(trans->shrd->hw, ac); | 368 | iwl_wake_sw_queue(priv(trans), ac); |
384 | } | 369 | } |
385 | 370 | ||
386 | static inline void iwl_stop_queue(struct iwl_trans *trans, | 371 | static inline void iwl_stop_queue(struct iwl_trans *trans, |
@@ -392,12 +377,9 @@ static inline void iwl_stop_queue(struct iwl_trans *trans, | |||
392 | struct iwl_trans_pcie *trans_pcie = | 377 | struct iwl_trans_pcie *trans_pcie = |
393 | IWL_TRANS_GET_PCIE_TRANS(trans); | 378 | IWL_TRANS_GET_PCIE_TRANS(trans); |
394 | 379 | ||
395 | if (unlikely(!trans->shrd->mac80211_registered)) | ||
396 | return; | ||
397 | |||
398 | if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) | 380 | if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) |
399 | if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) | 381 | if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) |
400 | ieee80211_stop_queue(trans->shrd->hw, ac); | 382 | iwl_stop_sw_queue(priv(trans), ac); |
401 | } | 383 | } |
402 | 384 | ||
403 | #ifdef ieee80211_stop_queue | 385 | #ifdef ieee80211_stop_queue |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 126e5a4cc401..b4eff556cd0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include "iwl-core.h" | 34 | #include "iwl-core.h" |
35 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
36 | #include "iwl-helpers.h" | 36 | #include "iwl-helpers.h" |
37 | #include "iwl-trans-int-pcie.h" | 37 | #include "iwl-trans-pcie-int.h" |
38 | 38 | ||
39 | /****************************************************************************** | 39 | /****************************************************************************** |
40 | * | 40 | * |
@@ -372,12 +372,15 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
372 | struct iwl_trans_pcie *trans_pcie = | 372 | struct iwl_trans_pcie *trans_pcie = |
373 | IWL_TRANS_GET_PCIE_TRANS(trans); | 373 | IWL_TRANS_GET_PCIE_TRANS(trans); |
374 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 374 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
375 | struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; | ||
376 | struct iwl_device_cmd *cmd; | ||
375 | u32 r, i; | 377 | u32 r, i; |
376 | int reclaim; | 378 | int reclaim; |
377 | unsigned long flags; | 379 | unsigned long flags; |
378 | u8 fill_rx = 0; | 380 | u8 fill_rx = 0; |
379 | u32 count = 8; | 381 | u32 count = 8; |
380 | int total_empty; | 382 | int total_empty; |
383 | int index, cmd_index; | ||
381 | 384 | ||
382 | /* uCode's read index (stored in shared DRAM) indicates the last Rx | 385 | /* uCode's read index (stored in shared DRAM) indicates the last Rx |
383 | * buffer that the driver may process (last buffer filled by ucode). */ | 386 | * buffer that the driver may process (last buffer filled by ucode). */ |
@@ -397,7 +400,8 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
397 | fill_rx = 1; | 400 | fill_rx = 1; |
398 | 401 | ||
399 | while (i != r) { | 402 | while (i != r) { |
400 | int len; | 403 | int len, err; |
404 | u16 sequence; | ||
401 | 405 | ||
402 | rxb = rxq->queue[i]; | 406 | rxb = rxq->queue[i]; |
403 | 407 | ||
@@ -437,7 +441,27 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
437 | (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && | 441 | (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && |
438 | (pkt->hdr.cmd != REPLY_TX); | 442 | (pkt->hdr.cmd != REPLY_TX); |
439 | 443 | ||
440 | iwl_rx_dispatch(priv(trans), rxb); | 444 | sequence = le16_to_cpu(pkt->hdr.sequence); |
445 | index = SEQ_TO_INDEX(sequence); | ||
446 | cmd_index = get_cmd_index(&txq->q, index); | ||
447 | |||
448 | if (reclaim) | ||
449 | cmd = txq->cmd[cmd_index]; | ||
450 | else | ||
451 | cmd = NULL; | ||
452 | |||
453 | /* warn if this is cmd response / notification and the uCode | ||
454 | * didn't set the SEQ_RX_FRAME for a frame that is | ||
455 | * uCode-originated | ||
456 | * If you saw this code after the second half of 2012, then | ||
457 | * please remove it | ||
458 | */ | ||
459 | WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false && | ||
460 | (!(pkt->hdr.sequence & SEQ_RX_FRAME)), | ||
461 | "reclaim is false, SEQ_RX_FRAME unset: %s\n", | ||
462 | get_cmd_string(pkt->hdr.cmd)); | ||
463 | |||
464 | err = iwl_rx_dispatch(priv(trans), rxb, cmd); | ||
441 | 465 | ||
442 | /* | 466 | /* |
443 | * XXX: After here, we should always check rxb->page | 467 | * XXX: After here, we should always check rxb->page |
@@ -452,7 +476,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
452 | * iwl_trans_send_cmd() | 476 | * iwl_trans_send_cmd() |
453 | * as we reclaim the driver command queue */ | 477 | * as we reclaim the driver command queue */ |
454 | if (rxb->page) | 478 | if (rxb->page) |
455 | iwl_tx_cmd_complete(trans, rxb); | 479 | iwl_tx_cmd_complete(trans, rxb, err); |
456 | else | 480 | else |
457 | IWL_WARN(trans, "Claim null rxb?\n"); | 481 | IWL_WARN(trans, "Claim null rxb?\n"); |
458 | } | 482 | } |
@@ -645,7 +669,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) | |||
645 | */ | 669 | */ |
646 | clear_bit(STATUS_READY, &trans->shrd->status); | 670 | clear_bit(STATUS_READY, &trans->shrd->status); |
647 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); | 671 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); |
648 | wake_up_interruptible(&priv->shrd->wait_command_queue); | 672 | wake_up(&priv->shrd->wait_command_queue); |
649 | IWL_ERR(trans, "RF is used by WiMAX\n"); | 673 | IWL_ERR(trans, "RF is used by WiMAX\n"); |
650 | return; | 674 | return; |
651 | } | 675 | } |
@@ -1086,7 +1110,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
1086 | handled |= CSR_INT_BIT_FH_TX; | 1110 | handled |= CSR_INT_BIT_FH_TX; |
1087 | /* Wake up uCode load routine, now that load is complete */ | 1111 | /* Wake up uCode load routine, now that load is complete */ |
1088 | priv(trans)->ucode_write_complete = 1; | 1112 | priv(trans)->ucode_write_complete = 1; |
1089 | wake_up_interruptible(&trans->shrd->wait_command_queue); | 1113 | wake_up(&trans->shrd->wait_command_queue); |
1090 | } | 1114 | } |
1091 | 1115 | ||
1092 | if (inta & ~handled) { | 1116 | if (inta & ~handled) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index f6d823f012db..ee7059dcbbcb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "iwl-io.h" | 38 | #include "iwl-io.h" |
39 | #include "iwl-agn-hw.h" | 39 | #include "iwl-agn-hw.h" |
40 | #include "iwl-helpers.h" | 40 | #include "iwl-helpers.h" |
41 | #include "iwl-trans-int-pcie.h" | 41 | #include "iwl-trans-pcie-int.h" |
42 | 42 | ||
43 | #define IWL_TX_CRC_SIZE 4 | 43 | #define IWL_TX_CRC_SIZE 4 |
44 | #define IWL_TX_DELIMITER_SIZE 4 | 44 | #define IWL_TX_DELIMITER_SIZE 4 |
@@ -59,13 +59,15 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | |||
59 | u8 sta_id = 0; | 59 | u8 sta_id = 0; |
60 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | 60 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; |
61 | __le16 bc_ent; | 61 | __le16 bc_ent; |
62 | struct iwl_tx_cmd *tx_cmd = | ||
63 | (struct iwl_tx_cmd *) txq->cmd[txq->q.write_ptr]->payload; | ||
62 | 64 | ||
63 | scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; | 65 | scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; |
64 | 66 | ||
65 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | 67 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); |
66 | 68 | ||
67 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | 69 | sta_id = tx_cmd->sta_id; |
68 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | 70 | sec_ctl = tx_cmd->sec_ctl; |
69 | 71 | ||
70 | switch (sec_ctl & TX_CMD_SEC_MSK) { | 72 | switch (sec_ctl & TX_CMD_SEC_MSK) { |
71 | case TX_CMD_SEC_CCM: | 73 | case TX_CMD_SEC_CCM: |
@@ -207,17 +209,17 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, | |||
207 | * @trans - transport private data | 209 | * @trans - transport private data |
208 | * @txq - tx queue | 210 | * @txq - tx queue |
209 | * @index - the index of the TFD to be freed | 211 | * @index - the index of the TFD to be freed |
212 | *@dma_dir - the direction of the DMA mapping | ||
210 | * | 213 | * |
211 | * Does NOT advance any TFD circular buffer read/write indexes | 214 | * Does NOT advance any TFD circular buffer read/write indexes |
212 | * Does NOT free the TFD itself (which is within circular buffer) | 215 | * Does NOT free the TFD itself (which is within circular buffer) |
213 | */ | 216 | */ |
214 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | 217 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, |
215 | int index) | 218 | int index, enum dma_data_direction dma_dir) |
216 | { | 219 | { |
217 | struct iwl_tfd *tfd_tmp = txq->tfds; | 220 | struct iwl_tfd *tfd_tmp = txq->tfds; |
218 | 221 | ||
219 | iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], | 222 | iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir); |
220 | DMA_TO_DEVICE); | ||
221 | 223 | ||
222 | /* free SKB */ | 224 | /* free SKB */ |
223 | if (txq->skbs) { | 225 | if (txq->skbs) { |
@@ -225,9 +227,12 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | |||
225 | 227 | ||
226 | skb = txq->skbs[index]; | 228 | skb = txq->skbs[index]; |
227 | 229 | ||
228 | /* can be called from irqs-disabled context */ | 230 | /* Can be called from irqs-disabled context |
231 | * If skb is not NULL, it means that the whole queue is being | ||
232 | * freed and that the queue is not empty - free the skb | ||
233 | */ | ||
229 | if (skb) { | 234 | if (skb) { |
230 | dev_kfree_skb_any(skb); | 235 | iwl_free_skb(priv(trans), skb); |
231 | txq->skbs[index] = NULL; | 236 | txq->skbs[index] = NULL; |
232 | } | 237 | } |
233 | } | 238 | } |
@@ -350,11 +355,13 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, | |||
350 | int read_ptr = txq->q.read_ptr; | 355 | int read_ptr = txq->q.read_ptr; |
351 | u8 sta_id = 0; | 356 | u8 sta_id = 0; |
352 | __le16 bc_ent; | 357 | __le16 bc_ent; |
358 | struct iwl_tx_cmd *tx_cmd = | ||
359 | (struct iwl_tx_cmd *) txq->cmd[txq->q.read_ptr]->payload; | ||
353 | 360 | ||
354 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | 361 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); |
355 | 362 | ||
356 | if (txq_id != trans->shrd->cmd_queue) | 363 | if (txq_id != trans->shrd->cmd_queue) |
357 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | 364 | sta_id = tx_cmd->sta_id; |
358 | 365 | ||
359 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | 366 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); |
360 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | 367 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; |
@@ -759,8 +766,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
759 | memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ | 766 | memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ |
760 | if (cmd->flags & CMD_WANT_SKB) | 767 | if (cmd->flags & CMD_WANT_SKB) |
761 | out_meta->source = cmd; | 768 | out_meta->source = cmd; |
762 | if (cmd->flags & CMD_ASYNC) | ||
763 | out_meta->callback = cmd->callback; | ||
764 | 769 | ||
765 | /* set up the header */ | 770 | /* set up the header */ |
766 | 771 | ||
@@ -772,7 +777,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
772 | 777 | ||
773 | /* and copy the data that needs to be copied */ | 778 | /* and copy the data that needs to be copied */ |
774 | 779 | ||
775 | cmd_dest = &out_cmd->cmd.payload[0]; | 780 | cmd_dest = out_cmd->payload; |
776 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 781 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
777 | if (!cmd->len[i]) | 782 | if (!cmd->len[i]) |
778 | continue; | 783 | continue; |
@@ -891,12 +896,15 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, | |||
891 | /** | 896 | /** |
892 | * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them | 897 | * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them |
893 | * @rxb: Rx buffer to reclaim | 898 | * @rxb: Rx buffer to reclaim |
899 | * @handler_status: return value of the handler of the command | ||
900 | * (put in setup_rx_handlers) | ||
894 | * | 901 | * |
895 | * If an Rx buffer has an async callback associated with it the callback | 902 | * If an Rx buffer has an async callback associated with it the callback |
896 | * will be executed. The attached skb (if present) will only be freed | 903 | * will be executed. The attached skb (if present) will only be freed |
897 | * if the callback returns 1 | 904 | * if the callback returns 1 |
898 | */ | 905 | */ |
899 | void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) | 906 | void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, |
907 | int handler_status) | ||
900 | { | 908 | { |
901 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 909 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
902 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 910 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
@@ -933,9 +941,9 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) | |||
933 | /* Input error checking is done when commands are added to queue. */ | 941 | /* Input error checking is done when commands are added to queue. */ |
934 | if (meta->flags & CMD_WANT_SKB) { | 942 | if (meta->flags & CMD_WANT_SKB) { |
935 | meta->source->reply_page = (unsigned long)rxb_addr(rxb); | 943 | meta->source->reply_page = (unsigned long)rxb_addr(rxb); |
944 | meta->source->handler_status = handler_status; | ||
936 | rxb->page = NULL; | 945 | rxb->page = NULL; |
937 | } else if (meta->callback) | 946 | } |
938 | meta->callback(trans->shrd, cmd, pkt); | ||
939 | 947 | ||
940 | spin_lock_irqsave(&trans->hcmd_lock, flags); | 948 | spin_lock_irqsave(&trans->hcmd_lock, flags); |
941 | 949 | ||
@@ -945,7 +953,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) | |||
945 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); | 953 | clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); |
946 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", | 954 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", |
947 | get_cmd_string(cmd->hdr.cmd)); | 955 | get_cmd_string(cmd->hdr.cmd)); |
948 | wake_up_interruptible(&trans->shrd->wait_command_queue); | 956 | wake_up(&trans->shrd->wait_command_queue); |
949 | } | 957 | } |
950 | 958 | ||
951 | meta->flags = 0; | 959 | meta->flags = 0; |
@@ -955,30 +963,6 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) | |||
955 | 963 | ||
956 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) | 964 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) |
957 | 965 | ||
958 | static void iwl_generic_cmd_callback(struct iwl_shared *shrd, | ||
959 | struct iwl_device_cmd *cmd, | ||
960 | struct iwl_rx_packet *pkt) | ||
961 | { | ||
962 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
963 | IWL_ERR(shrd->trans, "Bad return from %s (0x%08X)\n", | ||
964 | get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); | ||
965 | return; | ||
966 | } | ||
967 | |||
968 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
969 | switch (cmd->hdr.cmd) { | ||
970 | case REPLY_TX_LINK_QUALITY_CMD: | ||
971 | case SENSITIVITY_CMD: | ||
972 | IWL_DEBUG_HC_DUMP(shrd->trans, "back from %s (0x%08X)\n", | ||
973 | get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); | ||
974 | break; | ||
975 | default: | ||
976 | IWL_DEBUG_HC(shrd->trans, "back from %s (0x%08X)\n", | ||
977 | get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); | ||
978 | } | ||
979 | #endif | ||
980 | } | ||
981 | |||
982 | static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | 966 | static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) |
983 | { | 967 | { |
984 | int ret; | 968 | int ret; |
@@ -987,9 +971,6 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
987 | if (WARN_ON(cmd->flags & CMD_WANT_SKB)) | 971 | if (WARN_ON(cmd->flags & CMD_WANT_SKB)) |
988 | return -EINVAL; | 972 | return -EINVAL; |
989 | 973 | ||
990 | /* Assign a generic callback if one is not provided */ | ||
991 | if (!cmd->callback) | ||
992 | cmd->callback = iwl_generic_cmd_callback; | ||
993 | 974 | ||
994 | if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) | 975 | if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) |
995 | return -EBUSY; | 976 | return -EBUSY; |
@@ -1011,10 +992,6 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
1011 | 992 | ||
1012 | lockdep_assert_held(&trans->shrd->mutex); | 993 | lockdep_assert_held(&trans->shrd->mutex); |
1013 | 994 | ||
1014 | /* A synchronous command can not have a callback set. */ | ||
1015 | if (WARN_ON(cmd->callback)) | ||
1016 | return -EINVAL; | ||
1017 | |||
1018 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 995 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
1019 | get_cmd_string(cmd->id)); | 996 | get_cmd_string(cmd->id)); |
1020 | 997 | ||
@@ -1031,7 +1008,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
1031 | return ret; | 1008 | return ret; |
1032 | } | 1009 | } |
1033 | 1010 | ||
1034 | ret = wait_event_interruptible_timeout(trans->shrd->wait_command_queue, | 1011 | ret = wait_event_timeout(trans->shrd->wait_command_queue, |
1035 | !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), | 1012 | !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), |
1036 | HOST_COMPLETE_TIMEOUT); | 1013 | HOST_COMPLETE_TIMEOUT); |
1037 | if (!ret) { | 1014 | if (!ret) { |
@@ -1098,19 +1075,6 @@ int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
1098 | return iwl_send_cmd_sync(trans, cmd); | 1075 | return iwl_send_cmd_sync(trans, cmd); |
1099 | } | 1076 | } |
1100 | 1077 | ||
1101 | int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, | ||
1102 | u16 len, const void *data) | ||
1103 | { | ||
1104 | struct iwl_host_cmd cmd = { | ||
1105 | .id = id, | ||
1106 | .len = { len, }, | ||
1107 | .data = { data, }, | ||
1108 | .flags = flags, | ||
1109 | }; | ||
1110 | |||
1111 | return iwl_trans_pcie_send_cmd(trans, &cmd); | ||
1112 | } | ||
1113 | |||
1114 | /* Frees buffers until index _not_ inclusive */ | 1078 | /* Frees buffers until index _not_ inclusive */ |
1115 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | 1079 | int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, |
1116 | struct sk_buff_head *skbs) | 1080 | struct sk_buff_head *skbs) |
@@ -1121,6 +1085,10 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | |||
1121 | int last_to_free; | 1085 | int last_to_free; |
1122 | int freed = 0; | 1086 | int freed = 0; |
1123 | 1087 | ||
1088 | /* This function is not meant to release cmd queue*/ | ||
1089 | if (WARN_ON(txq_id == trans->shrd->cmd_queue)) | ||
1090 | return 0; | ||
1091 | |||
1124 | /*Since we free until index _not_ inclusive, the one before index is | 1092 | /*Since we free until index _not_ inclusive, the one before index is |
1125 | * the last we will free. This one must be used */ | 1093 | * the last we will free. This one must be used */ |
1126 | last_to_free = iwl_queue_dec_wrap(index, q->n_bd); | 1094 | last_to_free = iwl_queue_dec_wrap(index, q->n_bd); |
@@ -1153,7 +1121,7 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, | |||
1153 | 1121 | ||
1154 | iwlagn_txq_inval_byte_cnt_tbl(trans, txq); | 1122 | iwlagn_txq_inval_byte_cnt_tbl(trans, txq); |
1155 | 1123 | ||
1156 | iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr); | 1124 | iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr, DMA_TO_DEVICE); |
1157 | freed++; | 1125 | freed++; |
1158 | } | 1126 | } |
1159 | return freed; | 1127 | return freed; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c new file mode 100644 index 000000000000..416e9920e4d9 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | |||
@@ -0,0 +1,1989 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #include <linux/interrupt.h> | ||
64 | #include <linux/debugfs.h> | ||
65 | #include <linux/bitops.h> | ||
66 | #include <linux/gfp.h> | ||
67 | |||
68 | #include "iwl-trans.h" | ||
69 | #include "iwl-trans-pcie-int.h" | ||
70 | #include "iwl-csr.h" | ||
71 | #include "iwl-prph.h" | ||
72 | #include "iwl-shared.h" | ||
73 | #include "iwl-eeprom.h" | ||
74 | #include "iwl-agn-hw.h" | ||
75 | |||
76 | static int iwl_trans_rx_alloc(struct iwl_trans *trans) | ||
77 | { | ||
78 | struct iwl_trans_pcie *trans_pcie = | ||
79 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
80 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
81 | struct device *dev = bus(trans)->dev; | ||
82 | |||
83 | memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); | ||
84 | |||
85 | spin_lock_init(&rxq->lock); | ||
86 | |||
87 | if (WARN_ON(rxq->bd || rxq->rb_stts)) | ||
88 | return -EINVAL; | ||
89 | |||
90 | /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ | ||
91 | rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
92 | &rxq->bd_dma, GFP_KERNEL); | ||
93 | if (!rxq->bd) | ||
94 | goto err_bd; | ||
95 | memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE); | ||
96 | |||
97 | /*Allocate the driver's pointer to receive buffer status */ | ||
98 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts), | ||
99 | &rxq->rb_stts_dma, GFP_KERNEL); | ||
100 | if (!rxq->rb_stts) | ||
101 | goto err_rb_stts; | ||
102 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); | ||
103 | |||
104 | return 0; | ||
105 | |||
106 | err_rb_stts: | ||
107 | dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
108 | rxq->bd, rxq->bd_dma); | ||
109 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | ||
110 | rxq->bd = NULL; | ||
111 | err_bd: | ||
112 | return -ENOMEM; | ||
113 | } | ||
114 | |||
115 | static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) | ||
116 | { | ||
117 | struct iwl_trans_pcie *trans_pcie = | ||
118 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
119 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
120 | int i; | ||
121 | |||
122 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
123 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
124 | /* In the reset function, these buffers may have been allocated | ||
125 | * to an SKB, so we need to unmap and free potential storage */ | ||
126 | if (rxq->pool[i].page != NULL) { | ||
127 | dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, | ||
128 | PAGE_SIZE << hw_params(trans).rx_page_order, | ||
129 | DMA_FROM_DEVICE); | ||
130 | __free_pages(rxq->pool[i].page, | ||
131 | hw_params(trans).rx_page_order); | ||
132 | rxq->pool[i].page = NULL; | ||
133 | } | ||
134 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | ||
139 | struct iwl_rx_queue *rxq) | ||
140 | { | ||
141 | u32 rb_size; | ||
142 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
143 | u32 rb_timeout = RX_RB_TIMEOUT; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
144 | |||
145 | if (iwlagn_mod_params.amsdu_size_8K) | ||
146 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
147 | else | ||
148 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
149 | |||
150 | /* Stop Rx DMA */ | ||
151 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
152 | |||
153 | /* Reset driver's Rx queue write index */ | ||
154 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
155 | |||
156 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
157 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
158 | (u32)(rxq->bd_dma >> 8)); | ||
159 | |||
160 | /* Tell device where in DRAM to update its Rx status */ | ||
161 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
162 | rxq->rb_stts_dma >> 4); | ||
163 | |||
164 | /* Enable Rx DMA | ||
165 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
166 | * the credit mechanism in 5000 HW RX FIFO | ||
167 | * Direct rx interrupts to hosts | ||
168 | * Rx buffer size 4 or 8k | ||
169 | * RB timeout 0x10 | ||
170 | * 256 RBDs | ||
171 | */ | ||
172 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
173 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
174 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
175 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
176 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
177 | rb_size| | ||
178 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
179 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
180 | |||
181 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
182 | iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
183 | } | ||
184 | |||
185 | static int iwl_rx_init(struct iwl_trans *trans) | ||
186 | { | ||
187 | struct iwl_trans_pcie *trans_pcie = | ||
188 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
189 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
190 | |||
191 | int i, err; | ||
192 | unsigned long flags; | ||
193 | |||
194 | if (!rxq->bd) { | ||
195 | err = iwl_trans_rx_alloc(trans); | ||
196 | if (err) | ||
197 | return err; | ||
198 | } | ||
199 | |||
200 | spin_lock_irqsave(&rxq->lock, flags); | ||
201 | INIT_LIST_HEAD(&rxq->rx_free); | ||
202 | INIT_LIST_HEAD(&rxq->rx_used); | ||
203 | |||
204 | iwl_trans_rxq_free_rx_bufs(trans); | ||
205 | |||
206 | for (i = 0; i < RX_QUEUE_SIZE; i++) | ||
207 | rxq->queue[i] = NULL; | ||
208 | |||
209 | /* Set us so that we have processed and used all buffers, but have | ||
210 | * not restocked the Rx queue with fresh buffers */ | ||
211 | rxq->read = rxq->write = 0; | ||
212 | rxq->write_actual = 0; | ||
213 | rxq->free_count = 0; | ||
214 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
215 | |||
216 | iwlagn_rx_replenish(trans); | ||
217 | |||
218 | iwl_trans_rx_hw_init(trans, rxq); | ||
219 | |||
220 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
221 | rxq->need_update = 1; | ||
222 | iwl_rx_queue_update_write_ptr(trans, rxq); | ||
223 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) | ||
229 | { | ||
230 | struct iwl_trans_pcie *trans_pcie = | ||
231 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
232 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
233 | |||
234 | unsigned long flags; | ||
235 | |||
236 | /*if rxq->bd is NULL, it means that nothing has been allocated, | ||
237 | * exit now */ | ||
238 | if (!rxq->bd) { | ||
239 | IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); | ||
240 | return; | ||
241 | } | ||
242 | |||
243 | spin_lock_irqsave(&rxq->lock, flags); | ||
244 | iwl_trans_rxq_free_rx_bufs(trans); | ||
245 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
246 | |||
247 | dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
248 | rxq->bd, rxq->bd_dma); | ||
249 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | ||
250 | rxq->bd = NULL; | ||
251 | |||
252 | if (rxq->rb_stts) | ||
253 | dma_free_coherent(bus(trans)->dev, | ||
254 | sizeof(struct iwl_rb_status), | ||
255 | rxq->rb_stts, rxq->rb_stts_dma); | ||
256 | else | ||
257 | IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); | ||
258 | memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); | ||
259 | rxq->rb_stts = NULL; | ||
260 | } | ||
261 | |||
262 | static int iwl_trans_rx_stop(struct iwl_trans *trans) | ||
263 | { | ||
264 | |||
265 | /* stop Rx DMA */ | ||
266 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
267 | return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG, | ||
268 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
269 | } | ||
270 | |||
271 | static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, | ||
272 | struct iwl_dma_ptr *ptr, size_t size) | ||
273 | { | ||
274 | if (WARN_ON(ptr->addr)) | ||
275 | return -EINVAL; | ||
276 | |||
277 | ptr->addr = dma_alloc_coherent(bus(trans)->dev, size, | ||
278 | &ptr->dma, GFP_KERNEL); | ||
279 | if (!ptr->addr) | ||
280 | return -ENOMEM; | ||
281 | ptr->size = size; | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, | ||
286 | struct iwl_dma_ptr *ptr) | ||
287 | { | ||
288 | if (unlikely(!ptr->addr)) | ||
289 | return; | ||
290 | |||
291 | dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma); | ||
292 | memset(ptr, 0, sizeof(*ptr)); | ||
293 | } | ||
294 | |||
295 | static int iwl_trans_txq_alloc(struct iwl_trans *trans, | ||
296 | struct iwl_tx_queue *txq, int slots_num, | ||
297 | u32 txq_id) | ||
298 | { | ||
299 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; | ||
300 | int i; | ||
301 | |||
302 | if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) | ||
303 | return -EINVAL; | ||
304 | |||
305 | txq->q.n_window = slots_num; | ||
306 | |||
307 | txq->meta = kcalloc(slots_num, sizeof(txq->meta[0]), GFP_KERNEL); | ||
308 | txq->cmd = kcalloc(slots_num, sizeof(txq->cmd[0]), GFP_KERNEL); | ||
309 | |||
310 | if (!txq->meta || !txq->cmd) | ||
311 | goto error; | ||
312 | |||
313 | if (txq_id == trans->shrd->cmd_queue) | ||
314 | for (i = 0; i < slots_num; i++) { | ||
315 | txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), | ||
316 | GFP_KERNEL); | ||
317 | if (!txq->cmd[i]) | ||
318 | goto error; | ||
319 | } | ||
320 | |||
321 | /* Alloc driver data array and TFD circular buffer */ | ||
322 | /* Driver private data, only for Tx (not command) queues, | ||
323 | * not shared with device. */ | ||
324 | if (txq_id != trans->shrd->cmd_queue) { | ||
325 | txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->skbs[0]), | ||
326 | GFP_KERNEL); | ||
327 | if (!txq->skbs) { | ||
328 | IWL_ERR(trans, "kmalloc for auxiliary BD " | ||
329 | "structures failed\n"); | ||
330 | goto error; | ||
331 | } | ||
332 | } else { | ||
333 | txq->skbs = NULL; | ||
334 | } | ||
335 | |||
336 | /* Circular buffer of transmit frame descriptors (TFDs), | ||
337 | * shared with device */ | ||
338 | txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz, | ||
339 | &txq->q.dma_addr, GFP_KERNEL); | ||
340 | if (!txq->tfds) { | ||
341 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); | ||
342 | goto error; | ||
343 | } | ||
344 | txq->q.id = txq_id; | ||
345 | |||
346 | return 0; | ||
347 | error: | ||
348 | kfree(txq->skbs); | ||
349 | txq->skbs = NULL; | ||
350 | /* since txq->cmd has been zeroed, | ||
351 | * all non allocated cmd[i] will be NULL */ | ||
352 | if (txq->cmd && txq_id == trans->shrd->cmd_queue) | ||
353 | for (i = 0; i < slots_num; i++) | ||
354 | kfree(txq->cmd[i]); | ||
355 | kfree(txq->meta); | ||
356 | kfree(txq->cmd); | ||
357 | txq->meta = NULL; | ||
358 | txq->cmd = NULL; | ||
359 | |||
360 | return -ENOMEM; | ||
361 | |||
362 | } | ||
363 | |||
364 | static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, | ||
365 | int slots_num, u32 txq_id) | ||
366 | { | ||
367 | int ret; | ||
368 | |||
369 | txq->need_update = 0; | ||
370 | memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num); | ||
371 | |||
372 | /* | ||
373 | * For the default queues 0-3, set up the swq_id | ||
374 | * already -- all others need to get one later | ||
375 | * (if they need one at all). | ||
376 | */ | ||
377 | if (txq_id < 4) | ||
378 | iwl_set_swq_id(txq, txq_id, txq_id); | ||
379 | |||
380 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | ||
381 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ | ||
382 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | ||
383 | |||
384 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
385 | ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, | ||
386 | txq_id); | ||
387 | if (ret) | ||
388 | return ret; | ||
389 | |||
390 | /* | ||
391 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
392 | * given Tx queue, and enable the DMA channel used for that queue. | ||
393 | * Circular buffer (TFD queue in DRAM) physical base address */ | ||
394 | iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id), | ||
395 | txq->q.dma_addr >> 8); | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | /** | ||
401 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | ||
402 | */ | ||
403 | static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) | ||
404 | { | ||
405 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
406 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | ||
407 | struct iwl_queue *q = &txq->q; | ||
408 | enum dma_data_direction dma_dir; | ||
409 | |||
410 | if (!q->n_bd) | ||
411 | return; | ||
412 | |||
413 | /* In the command queue, all the TBs are mapped as BIDI | ||
414 | * so unmap them as such. | ||
415 | */ | ||
416 | if (txq_id == trans->shrd->cmd_queue) | ||
417 | dma_dir = DMA_BIDIRECTIONAL; | ||
418 | else | ||
419 | dma_dir = DMA_TO_DEVICE; | ||
420 | |||
421 | while (q->write_ptr != q->read_ptr) { | ||
422 | /* The read_ptr needs to bound by q->n_window */ | ||
423 | iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr), | ||
424 | dma_dir); | ||
425 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * iwl_tx_queue_free - Deallocate DMA queue. | ||
431 | * @txq: Transmit queue to deallocate. | ||
432 | * | ||
433 | * Empty queue by removing and destroying all BD's. | ||
434 | * Free all buffers. | ||
435 | * 0-fill, but do not free "txq" descriptor structure. | ||
436 | */ | ||
437 | static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) | ||
438 | { | ||
439 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
440 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | ||
441 | struct device *dev = bus(trans)->dev; | ||
442 | int i; | ||
443 | if (WARN_ON(!txq)) | ||
444 | return; | ||
445 | |||
446 | iwl_tx_queue_unmap(trans, txq_id); | ||
447 | |||
448 | /* De-alloc array of command/tx buffers */ | ||
449 | |||
450 | if (txq_id == trans->shrd->cmd_queue) | ||
451 | for (i = 0; i < txq->q.n_window; i++) | ||
452 | kfree(txq->cmd[i]); | ||
453 | |||
454 | /* De-alloc circular buffer of TFDs */ | ||
455 | if (txq->q.n_bd) { | ||
456 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * | ||
457 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | ||
458 | memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); | ||
459 | } | ||
460 | |||
461 | /* De-alloc array of per-TFD driver data */ | ||
462 | kfree(txq->skbs); | ||
463 | txq->skbs = NULL; | ||
464 | |||
465 | /* deallocate arrays */ | ||
466 | kfree(txq->cmd); | ||
467 | kfree(txq->meta); | ||
468 | txq->cmd = NULL; | ||
469 | txq->meta = NULL; | ||
470 | |||
471 | /* 0-fill queue descriptor structure */ | ||
472 | memset(txq, 0, sizeof(*txq)); | ||
473 | } | ||
474 | |||
475 | /** | ||
476 | * iwl_trans_tx_free - Free TXQ Context | ||
477 | * | ||
478 | * Destroy all TX DMA queues and structures | ||
479 | */ | ||
480 | static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) | ||
481 | { | ||
482 | int txq_id; | ||
483 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
484 | |||
485 | /* Tx queues */ | ||
486 | if (trans_pcie->txq) { | ||
487 | for (txq_id = 0; | ||
488 | txq_id < hw_params(trans).max_txq_num; txq_id++) | ||
489 | iwl_tx_queue_free(trans, txq_id); | ||
490 | } | ||
491 | |||
492 | kfree(trans_pcie->txq); | ||
493 | trans_pcie->txq = NULL; | ||
494 | |||
495 | iwlagn_free_dma_ptr(trans, &trans_pcie->kw); | ||
496 | |||
497 | iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * iwl_trans_tx_alloc - allocate TX context | ||
502 | * Allocate all Tx DMA structures and initialize them | ||
503 | * | ||
504 | * @param priv | ||
505 | * @return error code | ||
506 | */ | ||
507 | static int iwl_trans_tx_alloc(struct iwl_trans *trans) | ||
508 | { | ||
509 | int ret; | ||
510 | int txq_id, slots_num; | ||
511 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
512 | |||
513 | u16 scd_bc_tbls_size = hw_params(trans).max_txq_num * | ||
514 | sizeof(struct iwlagn_scd_bc_tbl); | ||
515 | |||
516 | /*It is not allowed to alloc twice, so warn when this happens. | ||
517 | * We cannot rely on the previous allocation, so free and fail */ | ||
518 | if (WARN_ON(trans_pcie->txq)) { | ||
519 | ret = -EINVAL; | ||
520 | goto error; | ||
521 | } | ||
522 | |||
523 | ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, | ||
524 | scd_bc_tbls_size); | ||
525 | if (ret) { | ||
526 | IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); | ||
527 | goto error; | ||
528 | } | ||
529 | |||
530 | /* Alloc keep-warm buffer */ | ||
531 | ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); | ||
532 | if (ret) { | ||
533 | IWL_ERR(trans, "Keep Warm allocation failed\n"); | ||
534 | goto error; | ||
535 | } | ||
536 | |||
537 | trans_pcie->txq = kcalloc(hw_params(trans).max_txq_num, | ||
538 | sizeof(struct iwl_tx_queue), GFP_KERNEL); | ||
539 | if (!trans_pcie->txq) { | ||
540 | IWL_ERR(trans, "Not enough memory for txq\n"); | ||
541 | ret = ENOMEM; | ||
542 | goto error; | ||
543 | } | ||
544 | |||
545 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | ||
546 | for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { | ||
547 | slots_num = (txq_id == trans->shrd->cmd_queue) ? | ||
548 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
549 | ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], | ||
550 | slots_num, txq_id); | ||
551 | if (ret) { | ||
552 | IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); | ||
553 | goto error; | ||
554 | } | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | |||
559 | error: | ||
560 | iwl_trans_pcie_tx_free(trans); | ||
561 | |||
562 | return ret; | ||
563 | } | ||
564 | static int iwl_tx_init(struct iwl_trans *trans) | ||
565 | { | ||
566 | int ret; | ||
567 | int txq_id, slots_num; | ||
568 | unsigned long flags; | ||
569 | bool alloc = false; | ||
570 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
571 | |||
572 | if (!trans_pcie->txq) { | ||
573 | ret = iwl_trans_tx_alloc(trans); | ||
574 | if (ret) | ||
575 | goto error; | ||
576 | alloc = true; | ||
577 | } | ||
578 | |||
579 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
580 | |||
581 | /* Turn off all Tx DMA fifos */ | ||
582 | iwl_write_prph(bus(trans), SCD_TXFACT, 0); | ||
583 | |||
584 | /* Tell NIC where to find the "keep warm" buffer */ | ||
585 | iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG, | ||
586 | trans_pcie->kw.dma >> 4); | ||
587 | |||
588 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
589 | |||
590 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | ||
591 | for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { | ||
592 | slots_num = (txq_id == trans->shrd->cmd_queue) ? | ||
593 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
594 | ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], | ||
595 | slots_num, txq_id); | ||
596 | if (ret) { | ||
597 | IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); | ||
598 | goto error; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | return 0; | ||
603 | error: | ||
604 | /*Upon error, free only if we allocated something */ | ||
605 | if (alloc) | ||
606 | iwl_trans_pcie_tx_free(trans); | ||
607 | return ret; | ||
608 | } | ||
609 | |||
610 | static void iwl_set_pwr_vmain(struct iwl_trans *trans) | ||
611 | { | ||
612 | /* | ||
613 | * (for documentation purposes) | ||
614 | * to set power to V_AUX, do: | ||
615 | |||
616 | if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) | ||
617 | iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, | ||
618 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, | ||
619 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
620 | */ | ||
621 | |||
622 | iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, | ||
623 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, | ||
624 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
625 | } | ||
626 | |||
627 | static int iwl_nic_init(struct iwl_trans *trans) | ||
628 | { | ||
629 | unsigned long flags; | ||
630 | |||
631 | /* nic_init */ | ||
632 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
633 | iwl_apm_init(priv(trans)); | ||
634 | |||
635 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
636 | iwl_write8(bus(trans), CSR_INT_COALESCING, | ||
637 | IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
638 | |||
639 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
640 | |||
641 | iwl_set_pwr_vmain(trans); | ||
642 | |||
643 | iwl_nic_config(priv(trans)); | ||
644 | |||
645 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
646 | iwl_rx_init(trans); | ||
647 | |||
648 | /* Allocate or reset and init all Tx and Command queues */ | ||
649 | if (iwl_tx_init(trans)) | ||
650 | return -ENOMEM; | ||
651 | |||
652 | if (hw_params(trans).shadow_reg_enable) { | ||
653 | /* enable shadow regs in HW */ | ||
654 | iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, | ||
655 | 0x800FFFFF); | ||
656 | } | ||
657 | |||
658 | set_bit(STATUS_INIT, &trans->shrd->status); | ||
659 | |||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | #define HW_READY_TIMEOUT (50) | ||
664 | |||
665 | /* Note: returns poll_bit return value, which is >= 0 if success */ | ||
666 | static int iwl_set_hw_ready(struct iwl_trans *trans) | ||
667 | { | ||
668 | int ret; | ||
669 | |||
670 | iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
671 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); | ||
672 | |||
673 | /* See if we got it */ | ||
674 | ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
675 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | ||
676 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | ||
677 | HW_READY_TIMEOUT); | ||
678 | |||
679 | IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); | ||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | /* Note: returns standard 0/-ERROR code */ | ||
684 | static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) | ||
685 | { | ||
686 | int ret; | ||
687 | |||
688 | IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); | ||
689 | |||
690 | ret = iwl_set_hw_ready(trans); | ||
691 | if (ret >= 0) | ||
692 | return 0; | ||
693 | |||
694 | /* If HW is not ready, prepare the conditions to check again */ | ||
695 | iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
696 | CSR_HW_IF_CONFIG_REG_PREPARE); | ||
697 | |||
698 | ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
699 | ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, | ||
700 | CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); | ||
701 | |||
702 | if (ret < 0) | ||
703 | return ret; | ||
704 | |||
705 | /* HW should be ready by now, check again. */ | ||
706 | ret = iwl_set_hw_ready(trans); | ||
707 | if (ret >= 0) | ||
708 | return 0; | ||
709 | return ret; | ||
710 | } | ||
711 | |||
712 | #define IWL_AC_UNSET -1 | ||
713 | |||
714 | struct queue_to_fifo_ac { | ||
715 | s8 fifo, ac; | ||
716 | }; | ||
717 | |||
718 | static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { | ||
719 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
720 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
721 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
722 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
723 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
724 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
725 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
726 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
727 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
728 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
729 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
730 | }; | ||
731 | |||
732 | static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { | ||
733 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
734 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
735 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
736 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
737 | { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, | ||
738 | { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, | ||
739 | { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, | ||
740 | { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, | ||
741 | { IWL_TX_FIFO_BE_IPAN, 2, }, | ||
742 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
743 | { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, | ||
744 | }; | ||
745 | |||
746 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
747 | IWL_TX_FIFO_VO, | ||
748 | IWL_TX_FIFO_VI, | ||
749 | IWL_TX_FIFO_BE, | ||
750 | IWL_TX_FIFO_BK, | ||
751 | }; | ||
752 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
753 | 0, 1, 2, 3, | ||
754 | }; | ||
755 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
756 | IWL_TX_FIFO_VO_IPAN, | ||
757 | IWL_TX_FIFO_VI_IPAN, | ||
758 | IWL_TX_FIFO_BE_IPAN, | ||
759 | IWL_TX_FIFO_BK_IPAN, | ||
760 | }; | ||
761 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
762 | 7, 6, 5, 4, | ||
763 | }; | ||
764 | |||
765 | static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | ||
766 | { | ||
767 | int ret; | ||
768 | struct iwl_trans_pcie *trans_pcie = | ||
769 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
770 | |||
771 | trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; | ||
772 | trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; | ||
773 | trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; | ||
774 | |||
775 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo; | ||
776 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo; | ||
777 | |||
778 | trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; | ||
779 | trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; | ||
780 | |||
781 | if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && | ||
782 | iwl_trans_pcie_prepare_card_hw(trans)) { | ||
783 | IWL_WARN(trans, "Exit HW not ready\n"); | ||
784 | return -EIO; | ||
785 | } | ||
786 | |||
787 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
788 | if (iwl_read32(bus(trans), CSR_GP_CNTRL) & | ||
789 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | ||
790 | clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
791 | else | ||
792 | set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
793 | |||
794 | if (iwl_is_rfkill(trans->shrd)) { | ||
795 | iwl_set_hw_rfkill_state(priv(trans), true); | ||
796 | iwl_enable_interrupts(trans); | ||
797 | return -ERFKILL; | ||
798 | } | ||
799 | |||
800 | iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); | ||
801 | |||
802 | ret = iwl_nic_init(trans); | ||
803 | if (ret) { | ||
804 | IWL_ERR(trans, "Unable to init nic\n"); | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | /* make sure rfkill handshake bits are cleared */ | ||
809 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
810 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, | ||
811 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
812 | |||
813 | /* clear (again), then enable host interrupts */ | ||
814 | iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); | ||
815 | iwl_enable_interrupts(trans); | ||
816 | |||
817 | /* really make sure rfkill handshake bits are cleared */ | ||
818 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
819 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
826 | * must be called under priv->shrd->lock and mac access | ||
827 | */ | ||
828 | static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) | ||
829 | { | ||
830 | iwl_write_prph(bus(trans), SCD_TXFACT, mask); | ||
831 | } | ||
832 | |||
833 | static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) | ||
834 | { | ||
835 | const struct queue_to_fifo_ac *queue_to_fifo; | ||
836 | struct iwl_trans_pcie *trans_pcie = | ||
837 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
838 | u32 a; | ||
839 | unsigned long flags; | ||
840 | int i, chan; | ||
841 | u32 reg_val; | ||
842 | |||
843 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
844 | |||
845 | trans_pcie->scd_base_addr = | ||
846 | iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR); | ||
847 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | ||
848 | /* reset conext data memory */ | ||
849 | for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; | ||
850 | a += 4) | ||
851 | iwl_write_targ_mem(bus(trans), a, 0); | ||
852 | /* reset tx status memory */ | ||
853 | for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; | ||
854 | a += 4) | ||
855 | iwl_write_targ_mem(bus(trans), a, 0); | ||
856 | for (; a < trans_pcie->scd_base_addr + | ||
857 | SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); | ||
858 | a += 4) | ||
859 | iwl_write_targ_mem(bus(trans), a, 0); | ||
860 | |||
861 | iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR, | ||
862 | trans_pcie->scd_bc_tbls.dma >> 10); | ||
863 | |||
864 | /* Enable DMA channel */ | ||
865 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | ||
866 | iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
867 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
868 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
869 | |||
870 | /* Update FH chicken bits */ | ||
871 | reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG); | ||
872 | iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG, | ||
873 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
874 | |||
875 | iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, | ||
876 | SCD_QUEUECHAIN_SEL_ALL(trans)); | ||
877 | iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); | ||
878 | |||
879 | /* initiate the queues */ | ||
880 | for (i = 0; i < hw_params(trans).max_txq_num; i++) { | ||
881 | iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); | ||
882 | iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
883 | iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + | ||
884 | SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
885 | iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + | ||
886 | SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
887 | sizeof(u32), | ||
888 | ((SCD_WIN_SIZE << | ||
889 | SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
890 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
891 | ((SCD_FRAME_LIMIT << | ||
892 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
893 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
894 | } | ||
895 | |||
896 | iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK, | ||
897 | IWL_MASK(0, hw_params(trans).max_txq_num)); | ||
898 | |||
899 | /* Activate all Tx DMA/FIFO channels */ | ||
900 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); | ||
901 | |||
902 | /* map queues to FIFOs */ | ||
903 | if (trans->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS)) | ||
904 | queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; | ||
905 | else | ||
906 | queue_to_fifo = iwlagn_default_queue_to_tx_fifo; | ||
907 | |||
908 | iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0); | ||
909 | |||
910 | /* make sure all queue are not stopped */ | ||
911 | memset(&trans_pcie->queue_stopped[0], 0, | ||
912 | sizeof(trans_pcie->queue_stopped)); | ||
913 | for (i = 0; i < 4; i++) | ||
914 | atomic_set(&trans_pcie->queue_stop_count[i], 0); | ||
915 | |||
916 | /* reset to 0 to enable all the queue first */ | ||
917 | trans_pcie->txq_ctx_active_msk = 0; | ||
918 | |||
919 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) < | ||
920 | IWLAGN_FIRST_AMPDU_QUEUE); | ||
921 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) < | ||
922 | IWLAGN_FIRST_AMPDU_QUEUE); | ||
923 | |||
924 | for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) { | ||
925 | int fifo = queue_to_fifo[i].fifo; | ||
926 | int ac = queue_to_fifo[i].ac; | ||
927 | |||
928 | iwl_txq_ctx_activate(trans_pcie, i); | ||
929 | |||
930 | if (fifo == IWL_TX_FIFO_UNUSED) | ||
931 | continue; | ||
932 | |||
933 | if (ac != IWL_AC_UNSET) | ||
934 | iwl_set_swq_id(&trans_pcie->txq[i], ac, i); | ||
935 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], | ||
936 | fifo, 0); | ||
937 | } | ||
938 | |||
939 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
940 | |||
941 | /* Enable L1-Active */ | ||
942 | iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG, | ||
943 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
944 | } | ||
945 | |||
946 | /** | ||
947 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | ||
948 | */ | ||
949 | static int iwl_trans_tx_stop(struct iwl_trans *trans) | ||
950 | { | ||
951 | int ch, txq_id; | ||
952 | unsigned long flags; | ||
953 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
954 | |||
955 | /* Turn off all Tx DMA fifos */ | ||
956 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
957 | |||
958 | iwl_trans_txq_set_sched(trans, 0); | ||
959 | |||
960 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
961 | for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { | ||
962 | iwl_write_direct32(bus(trans), | ||
963 | FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
964 | if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG, | ||
965 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
966 | 1000)) | ||
967 | IWL_ERR(trans, "Failing on timeout while stopping" | ||
968 | " DMA channel %d [0x%08x]", ch, | ||
969 | iwl_read_direct32(bus(trans), | ||
970 | FH_TSSR_TX_STATUS_REG)); | ||
971 | } | ||
972 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
973 | |||
974 | if (!trans_pcie->txq) { | ||
975 | IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | /* Unmap DMA from host system and free skb's */ | ||
980 | for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) | ||
981 | iwl_tx_queue_unmap(trans, txq_id); | ||
982 | |||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) | ||
987 | { | ||
988 | unsigned long flags; | ||
989 | struct iwl_trans_pcie *trans_pcie = | ||
990 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
991 | |||
992 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
993 | iwl_disable_interrupts(trans); | ||
994 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
995 | |||
996 | /* wait to make sure we flush pending tasklet*/ | ||
997 | synchronize_irq(bus(trans)->irq); | ||
998 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
999 | } | ||
1000 | |||
1001 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | ||
1002 | { | ||
1003 | /* stop and reset the on-board processor */ | ||
1004 | iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
1005 | |||
1006 | /* tell the device to stop sending interrupts */ | ||
1007 | iwl_trans_pcie_disable_sync_irq(trans); | ||
1008 | |||
1009 | /* device going down, Stop using ICT table */ | ||
1010 | iwl_disable_ict(trans); | ||
1011 | |||
1012 | /* | ||
1013 | * If a HW restart happens during firmware loading, | ||
1014 | * then the firmware loading might call this function | ||
1015 | * and later it might be called again due to the | ||
1016 | * restart. So don't process again if the device is | ||
1017 | * already dead. | ||
1018 | */ | ||
1019 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { | ||
1020 | iwl_trans_tx_stop(trans); | ||
1021 | iwl_trans_rx_stop(trans); | ||
1022 | |||
1023 | /* Power-down device's busmaster DMA clocks */ | ||
1024 | iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, | ||
1025 | APMG_CLK_VAL_DMA_CLK_RQT); | ||
1026 | udelay(5); | ||
1027 | } | ||
1028 | |||
1029 | /* Make sure (redundant) we've released our request to stay awake */ | ||
1030 | iwl_clear_bit(bus(trans), CSR_GP_CNTRL, | ||
1031 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
1032 | |||
1033 | /* Stop the device, and put it in low power state */ | ||
1034 | iwl_apm_stop(priv(trans)); | ||
1035 | } | ||
1036 | |||
1037 | static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | ||
1038 | struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, | ||
1039 | u8 sta_id) | ||
1040 | { | ||
1041 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1042 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1043 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1044 | struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; | ||
1045 | struct iwl_cmd_meta *out_meta; | ||
1046 | struct iwl_tx_queue *txq; | ||
1047 | struct iwl_queue *q; | ||
1048 | |||
1049 | dma_addr_t phys_addr = 0; | ||
1050 | dma_addr_t txcmd_phys; | ||
1051 | dma_addr_t scratch_phys; | ||
1052 | u16 len, firstlen, secondlen; | ||
1053 | u16 seq_number = 0; | ||
1054 | u8 wait_write_ptr = 0; | ||
1055 | u8 txq_id; | ||
1056 | u8 tid = 0; | ||
1057 | bool is_agg = false; | ||
1058 | __le16 fc = hdr->frame_control; | ||
1059 | u8 hdr_len = ieee80211_hdrlen(fc); | ||
1060 | |||
1061 | /* | ||
1062 | * Send this frame after DTIM -- there's a special queue | ||
1063 | * reserved for this for contexts that support AP mode. | ||
1064 | */ | ||
1065 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
1066 | txq_id = trans_pcie->mcast_queue[ctx]; | ||
1067 | |||
1068 | /* | ||
1069 | * The microcode will clear the more data | ||
1070 | * bit in the last frame it transmits. | ||
1071 | */ | ||
1072 | hdr->frame_control |= | ||
1073 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1074 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
1075 | txq_id = IWL_AUX_QUEUE; | ||
1076 | else | ||
1077 | txq_id = | ||
1078 | trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)]; | ||
1079 | |||
1080 | if (ieee80211_is_data_qos(fc)) { | ||
1081 | u8 *qc = NULL; | ||
1082 | struct iwl_tid_data *tid_data; | ||
1083 | qc = ieee80211_get_qos_ctl(hdr); | ||
1084 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
1085 | tid_data = &trans->shrd->tid_data[sta_id][tid]; | ||
1086 | |||
1087 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | ||
1088 | return -1; | ||
1089 | |||
1090 | seq_number = tid_data->seq_number; | ||
1091 | seq_number &= IEEE80211_SCTL_SEQ; | ||
1092 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
1093 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
1094 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
1095 | seq_number += 0x10; | ||
1096 | /* aggregation is on for this <sta,tid> */ | ||
1097 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1098 | WARN_ON(tid_data->agg.state != IWL_AGG_ON); | ||
1099 | txq_id = tid_data->agg.txq_id; | ||
1100 | is_agg = true; | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | /* Copy MAC header from skb into command buffer */ | ||
1105 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
1106 | |||
1107 | txq = &trans_pcie->txq[txq_id]; | ||
1108 | q = &txq->q; | ||
1109 | |||
1110 | /* Set up driver data for this TFD */ | ||
1111 | txq->skbs[q->write_ptr] = skb; | ||
1112 | txq->cmd[q->write_ptr] = dev_cmd; | ||
1113 | |||
1114 | dev_cmd->hdr.cmd = REPLY_TX; | ||
1115 | dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
1116 | INDEX_TO_SEQ(q->write_ptr))); | ||
1117 | |||
1118 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
1119 | out_meta = &txq->meta[q->write_ptr]; | ||
1120 | |||
1121 | /* | ||
1122 | * Use the first empty entry in this queue's command buffer array | ||
1123 | * to contain the Tx command and MAC header concatenated together | ||
1124 | * (payload data will be in another buffer). | ||
1125 | * Size of this varies, due to varying MAC header length. | ||
1126 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
1127 | * of the MAC header (device reads on dword boundaries). | ||
1128 | * We'll tell device about this padding later. | ||
1129 | */ | ||
1130 | len = sizeof(struct iwl_tx_cmd) + | ||
1131 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
1132 | firstlen = (len + 3) & ~3; | ||
1133 | |||
1134 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
1135 | if (firstlen != len) | ||
1136 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
1137 | |||
1138 | /* Physical address of this Tx command's header (not MAC header!), | ||
1139 | * within command buffer array. */ | ||
1140 | txcmd_phys = dma_map_single(bus(trans)->dev, | ||
1141 | &dev_cmd->hdr, firstlen, | ||
1142 | DMA_BIDIRECTIONAL); | ||
1143 | if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) | ||
1144 | return -1; | ||
1145 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
1146 | dma_unmap_len_set(out_meta, len, firstlen); | ||
1147 | |||
1148 | if (!ieee80211_has_morefrags(fc)) { | ||
1149 | txq->need_update = 1; | ||
1150 | } else { | ||
1151 | wait_write_ptr = 1; | ||
1152 | txq->need_update = 0; | ||
1153 | } | ||
1154 | |||
1155 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
1156 | * if any (802.11 null frames have no payload). */ | ||
1157 | secondlen = skb->len - hdr_len; | ||
1158 | if (secondlen > 0) { | ||
1159 | phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, | ||
1160 | secondlen, DMA_TO_DEVICE); | ||
1161 | if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { | ||
1162 | dma_unmap_single(bus(trans)->dev, | ||
1163 | dma_unmap_addr(out_meta, mapping), | ||
1164 | dma_unmap_len(out_meta, len), | ||
1165 | DMA_BIDIRECTIONAL); | ||
1166 | return -1; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | /* Attach buffers to TFD */ | ||
1171 | iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1); | ||
1172 | if (secondlen > 0) | ||
1173 | iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, | ||
1174 | secondlen, 0); | ||
1175 | |||
1176 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
1177 | offsetof(struct iwl_tx_cmd, scratch); | ||
1178 | |||
1179 | /* take back ownership of DMA buffer to enable update */ | ||
1180 | dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, | ||
1181 | DMA_BIDIRECTIONAL); | ||
1182 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1183 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1184 | |||
1185 | IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", | ||
1186 | le16_to_cpu(dev_cmd->hdr.sequence)); | ||
1187 | IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | ||
1188 | iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
1189 | iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
1190 | |||
1191 | /* Set up entry for this TFD in Tx byte-count array */ | ||
1192 | if (is_agg) | ||
1193 | iwl_trans_txq_update_byte_cnt_tbl(trans, txq, | ||
1194 | le16_to_cpu(tx_cmd->len)); | ||
1195 | |||
1196 | dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, | ||
1197 | DMA_BIDIRECTIONAL); | ||
1198 | |||
1199 | trace_iwlwifi_dev_tx(priv(trans), | ||
1200 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
1201 | sizeof(struct iwl_tfd), | ||
1202 | &dev_cmd->hdr, firstlen, | ||
1203 | skb->data + hdr_len, secondlen); | ||
1204 | |||
1205 | /* Tell device the write index *just past* this latest filled TFD */ | ||
1206 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
1207 | iwl_txq_update_write_ptr(trans, txq); | ||
1208 | |||
1209 | if (ieee80211_is_data_qos(fc)) { | ||
1210 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue++; | ||
1211 | if (!ieee80211_has_morefrags(fc)) | ||
1212 | trans->shrd->tid_data[sta_id][tid].seq_number = | ||
1213 | seq_number; | ||
1214 | } | ||
1215 | |||
1216 | /* | ||
1217 | * At this point the frame is "transmitted" successfully | ||
1218 | * and we will get a TX status notification eventually, | ||
1219 | * regardless of the value of ret. "ret" only indicates | ||
1220 | * whether or not we should update the write pointer. | ||
1221 | */ | ||
1222 | if (iwl_queue_space(q) < q->high_mark) { | ||
1223 | if (wait_write_ptr) { | ||
1224 | txq->need_update = 1; | ||
1225 | iwl_txq_update_write_ptr(trans, txq); | ||
1226 | } else { | ||
1227 | iwl_stop_queue(trans, txq); | ||
1228 | } | ||
1229 | } | ||
1230 | return 0; | ||
1231 | } | ||
1232 | |||
1233 | static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) | ||
1234 | { | ||
1235 | /* Remove all resets to allow NIC to operate */ | ||
1236 | iwl_write32(bus(trans), CSR_RESET, 0); | ||
1237 | } | ||
1238 | |||
1239 | static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) | ||
1240 | { | ||
1241 | struct iwl_trans_pcie *trans_pcie = | ||
1242 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1243 | int err; | ||
1244 | |||
1245 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | ||
1246 | |||
1247 | tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) | ||
1248 | iwl_irq_tasklet, (unsigned long)trans); | ||
1249 | |||
1250 | iwl_alloc_isr_ict(trans); | ||
1251 | |||
1252 | err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, | ||
1253 | DRV_NAME, trans); | ||
1254 | if (err) { | ||
1255 | IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); | ||
1256 | iwl_free_isr_ict(trans); | ||
1257 | return err; | ||
1258 | } | ||
1259 | |||
1260 | INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); | ||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1264 | static int iwlagn_txq_check_empty(struct iwl_trans *trans, | ||
1265 | int sta_id, u8 tid, int txq_id) | ||
1266 | { | ||
1267 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1268 | struct iwl_queue *q = &trans_pcie->txq[txq_id].q; | ||
1269 | struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid]; | ||
1270 | |||
1271 | lockdep_assert_held(&trans->shrd->sta_lock); | ||
1272 | |||
1273 | switch (trans->shrd->tid_data[sta_id][tid].agg.state) { | ||
1274 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1275 | /* We are reclaiming the last packet of the */ | ||
1276 | /* aggregated HW queue */ | ||
1277 | if ((txq_id == tid_data->agg.txq_id) && | ||
1278 | (q->read_ptr == q->write_ptr)) { | ||
1279 | IWL_DEBUG_HT(trans, | ||
1280 | "HW queue empty: continue DELBA flow\n"); | ||
1281 | iwl_trans_pcie_txq_agg_disable(trans, txq_id); | ||
1282 | tid_data->agg.state = IWL_AGG_OFF; | ||
1283 | iwl_stop_tx_ba_trans_ready(priv(trans), | ||
1284 | NUM_IWL_RXON_CTX, | ||
1285 | sta_id, tid); | ||
1286 | iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); | ||
1287 | } | ||
1288 | break; | ||
1289 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1290 | /* We are reclaiming the last packet of the queue */ | ||
1291 | if (tid_data->tfds_in_queue == 0) { | ||
1292 | IWL_DEBUG_HT(trans, | ||
1293 | "HW queue empty: continue ADDBA flow\n"); | ||
1294 | tid_data->agg.state = IWL_AGG_ON; | ||
1295 | iwl_start_tx_ba_trans_ready(priv(trans), | ||
1296 | NUM_IWL_RXON_CTX, | ||
1297 | sta_id, tid); | ||
1298 | } | ||
1299 | break; | ||
1300 | default: | ||
1301 | break; | ||
1302 | } | ||
1303 | |||
1304 | return 0; | ||
1305 | } | ||
1306 | |||
1307 | static void iwl_free_tfds_in_queue(struct iwl_trans *trans, | ||
1308 | int sta_id, int tid, int freed) | ||
1309 | { | ||
1310 | lockdep_assert_held(&trans->shrd->sta_lock); | ||
1311 | |||
1312 | if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed) | ||
1313 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed; | ||
1314 | else { | ||
1315 | IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n", | ||
1316 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue, | ||
1317 | freed); | ||
1318 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0; | ||
1319 | } | ||
1320 | } | ||
1321 | |||
1322 | static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, | ||
1323 | int txq_id, int ssn, u32 status, | ||
1324 | struct sk_buff_head *skbs) | ||
1325 | { | ||
1326 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1327 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | ||
1328 | enum iwl_agg_state agg_state; | ||
1329 | /* n_bd is usually 256 => n_bd - 1 = 0xff */ | ||
1330 | int tfd_num = ssn & (txq->q.n_bd - 1); | ||
1331 | int freed = 0; | ||
1332 | bool cond; | ||
1333 | |||
1334 | txq->time_stamp = jiffies; | ||
1335 | |||
1336 | if (txq->sched_retry) { | ||
1337 | agg_state = | ||
1338 | trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state; | ||
1339 | cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); | ||
1340 | } else { | ||
1341 | cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); | ||
1342 | } | ||
1343 | |||
1344 | if (txq->q.read_ptr != tfd_num) { | ||
1345 | IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim " | ||
1346 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
1347 | ssn , tfd_num, txq_id, txq->swq_id); | ||
1348 | freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); | ||
1349 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) | ||
1350 | iwl_wake_queue(trans, txq); | ||
1351 | } | ||
1352 | |||
1353 | iwl_free_tfds_in_queue(trans, sta_id, tid, freed); | ||
1354 | iwlagn_txq_check_empty(trans, sta_id, tid, txq_id); | ||
1355 | } | ||
1356 | |||
1357 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | ||
1358 | { | ||
1359 | iwl_trans_pcie_tx_free(trans); | ||
1360 | iwl_trans_pcie_rx_free(trans); | ||
1361 | free_irq(bus(trans)->irq, trans); | ||
1362 | iwl_free_isr_ict(trans); | ||
1363 | trans->shrd->trans = NULL; | ||
1364 | kfree(trans); | ||
1365 | } | ||
1366 | |||
1367 | #ifdef CONFIG_PM_SLEEP | ||
1368 | static int iwl_trans_pcie_suspend(struct iwl_trans *trans) | ||
1369 | { | ||
1370 | /* | ||
1371 | * This function is called when system goes into suspend state | ||
1372 | * mac80211 will call iwl_mac_stop() from the mac80211 suspend function | ||
1373 | * first but since iwl_mac_stop() has no knowledge of who the caller is, | ||
1374 | * it will not call apm_ops.stop() to stop the DMA operation. | ||
1375 | * Calling apm_ops.stop here to make sure we stop the DMA. | ||
1376 | * | ||
1377 | * But of course ... if we have configured WoWLAN then we did other | ||
1378 | * things already :-) | ||
1379 | */ | ||
1380 | if (!trans->shrd->wowlan) | ||
1381 | iwl_apm_stop(priv(trans)); | ||
1382 | |||
1383 | return 0; | ||
1384 | } | ||
1385 | |||
1386 | static int iwl_trans_pcie_resume(struct iwl_trans *trans) | ||
1387 | { | ||
1388 | bool hw_rfkill = false; | ||
1389 | |||
1390 | iwl_enable_interrupts(trans); | ||
1391 | |||
1392 | if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & | ||
1393 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | ||
1394 | hw_rfkill = true; | ||
1395 | |||
1396 | if (hw_rfkill) | ||
1397 | set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
1398 | else | ||
1399 | clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
1400 | |||
1401 | iwl_set_hw_rfkill_state(priv(trans), hw_rfkill); | ||
1402 | |||
1403 | return 0; | ||
1404 | } | ||
1405 | #endif /* CONFIG_PM_SLEEP */ | ||
1406 | |||
1407 | static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, | ||
1408 | enum iwl_rxon_context_id ctx) | ||
1409 | { | ||
1410 | u8 ac, txq_id; | ||
1411 | struct iwl_trans_pcie *trans_pcie = | ||
1412 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1413 | |||
1414 | for (ac = 0; ac < AC_NUM; ac++) { | ||
1415 | txq_id = trans_pcie->ac_to_queue[ctx][ac]; | ||
1416 | IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n", | ||
1417 | ac, | ||
1418 | (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0) | ||
1419 | ? "stopped" : "awake"); | ||
1420 | iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); | ||
1421 | } | ||
1422 | } | ||
1423 | |||
1424 | const struct iwl_trans_ops trans_ops_pcie; | ||
1425 | |||
1426 | static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) | ||
1427 | { | ||
1428 | struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + | ||
1429 | sizeof(struct iwl_trans_pcie), | ||
1430 | GFP_KERNEL); | ||
1431 | if (iwl_trans) { | ||
1432 | struct iwl_trans_pcie *trans_pcie = | ||
1433 | IWL_TRANS_GET_PCIE_TRANS(iwl_trans); | ||
1434 | iwl_trans->ops = &trans_ops_pcie; | ||
1435 | iwl_trans->shrd = shrd; | ||
1436 | trans_pcie->trans = iwl_trans; | ||
1437 | spin_lock_init(&iwl_trans->hcmd_lock); | ||
1438 | } | ||
1439 | |||
1440 | return iwl_trans; | ||
1441 | } | ||
1442 | |||
1443 | static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id) | ||
1444 | { | ||
1445 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1446 | |||
1447 | iwl_stop_queue(trans, &trans_pcie->txq[txq_id]); | ||
1448 | } | ||
1449 | |||
1450 | #define IWL_FLUSH_WAIT_MS 2000 | ||
1451 | |||
1452 | static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) | ||
1453 | { | ||
1454 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1455 | struct iwl_tx_queue *txq; | ||
1456 | struct iwl_queue *q; | ||
1457 | int cnt; | ||
1458 | unsigned long now = jiffies; | ||
1459 | int ret = 0; | ||
1460 | |||
1461 | /* waiting for all the tx frames complete might take a while */ | ||
1462 | for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { | ||
1463 | if (cnt == trans->shrd->cmd_queue) | ||
1464 | continue; | ||
1465 | txq = &trans_pcie->txq[cnt]; | ||
1466 | q = &txq->q; | ||
1467 | while (q->read_ptr != q->write_ptr && !time_after(jiffies, | ||
1468 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) | ||
1469 | msleep(1); | ||
1470 | |||
1471 | if (q->read_ptr != q->write_ptr) { | ||
1472 | IWL_ERR(trans, "fail to flush all tx fifo queues\n"); | ||
1473 | ret = -ETIMEDOUT; | ||
1474 | break; | ||
1475 | } | ||
1476 | } | ||
1477 | return ret; | ||
1478 | } | ||
1479 | |||
1480 | /* | ||
1481 | * On every watchdog tick we check (latest) time stamp. If it does not | ||
1482 | * change during timeout period and queue is not empty we reset firmware. | ||
1483 | */ | ||
1484 | static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) | ||
1485 | { | ||
1486 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1487 | struct iwl_tx_queue *txq = &trans_pcie->txq[cnt]; | ||
1488 | struct iwl_queue *q = &txq->q; | ||
1489 | unsigned long timeout; | ||
1490 | |||
1491 | if (q->read_ptr == q->write_ptr) { | ||
1492 | txq->time_stamp = jiffies; | ||
1493 | return 0; | ||
1494 | } | ||
1495 | |||
1496 | timeout = txq->time_stamp + | ||
1497 | msecs_to_jiffies(hw_params(trans).wd_timeout); | ||
1498 | |||
1499 | if (time_after(jiffies, timeout)) { | ||
1500 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id, | ||
1501 | hw_params(trans).wd_timeout); | ||
1502 | IWL_ERR(trans, "Current read_ptr %d write_ptr %d\n", | ||
1503 | q->read_ptr, q->write_ptr); | ||
1504 | return 1; | ||
1505 | } | ||
1506 | |||
1507 | return 0; | ||
1508 | } | ||
1509 | |||
1510 | static const char *get_fh_string(int cmd) | ||
1511 | { | ||
1512 | switch (cmd) { | ||
1513 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | ||
1514 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | ||
1515 | IWL_CMD(FH_RSCSR_CHNL0_WPTR); | ||
1516 | IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); | ||
1517 | IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); | ||
1518 | IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); | ||
1519 | IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); | ||
1520 | IWL_CMD(FH_TSSR_TX_STATUS_REG); | ||
1521 | IWL_CMD(FH_TSSR_TX_ERROR_REG); | ||
1522 | default: | ||
1523 | return "UNKNOWN"; | ||
1524 | } | ||
1525 | } | ||
1526 | |||
1527 | int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) | ||
1528 | { | ||
1529 | int i; | ||
1530 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1531 | int pos = 0; | ||
1532 | size_t bufsz = 0; | ||
1533 | #endif | ||
1534 | static const u32 fh_tbl[] = { | ||
1535 | FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
1536 | FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
1537 | FH_RSCSR_CHNL0_WPTR, | ||
1538 | FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
1539 | FH_MEM_RSSR_SHARED_CTRL_REG, | ||
1540 | FH_MEM_RSSR_RX_STATUS_REG, | ||
1541 | FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, | ||
1542 | FH_TSSR_TX_STATUS_REG, | ||
1543 | FH_TSSR_TX_ERROR_REG | ||
1544 | }; | ||
1545 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1546 | if (display) { | ||
1547 | bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; | ||
1548 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1549 | if (!*buf) | ||
1550 | return -ENOMEM; | ||
1551 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1552 | "FH register values:\n"); | ||
1553 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
1554 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1555 | " %34s: 0X%08x\n", | ||
1556 | get_fh_string(fh_tbl[i]), | ||
1557 | iwl_read_direct32(bus(trans), fh_tbl[i])); | ||
1558 | } | ||
1559 | return pos; | ||
1560 | } | ||
1561 | #endif | ||
1562 | IWL_ERR(trans, "FH register values:\n"); | ||
1563 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
1564 | IWL_ERR(trans, " %34s: 0X%08x\n", | ||
1565 | get_fh_string(fh_tbl[i]), | ||
1566 | iwl_read_direct32(bus(trans), fh_tbl[i])); | ||
1567 | } | ||
1568 | return 0; | ||
1569 | } | ||
1570 | |||
1571 | static const char *get_csr_string(int cmd) | ||
1572 | { | ||
1573 | switch (cmd) { | ||
1574 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | ||
1575 | IWL_CMD(CSR_INT_COALESCING); | ||
1576 | IWL_CMD(CSR_INT); | ||
1577 | IWL_CMD(CSR_INT_MASK); | ||
1578 | IWL_CMD(CSR_FH_INT_STATUS); | ||
1579 | IWL_CMD(CSR_GPIO_IN); | ||
1580 | IWL_CMD(CSR_RESET); | ||
1581 | IWL_CMD(CSR_GP_CNTRL); | ||
1582 | IWL_CMD(CSR_HW_REV); | ||
1583 | IWL_CMD(CSR_EEPROM_REG); | ||
1584 | IWL_CMD(CSR_EEPROM_GP); | ||
1585 | IWL_CMD(CSR_OTP_GP_REG); | ||
1586 | IWL_CMD(CSR_GIO_REG); | ||
1587 | IWL_CMD(CSR_GP_UCODE_REG); | ||
1588 | IWL_CMD(CSR_GP_DRIVER_REG); | ||
1589 | IWL_CMD(CSR_UCODE_DRV_GP1); | ||
1590 | IWL_CMD(CSR_UCODE_DRV_GP2); | ||
1591 | IWL_CMD(CSR_LED_REG); | ||
1592 | IWL_CMD(CSR_DRAM_INT_TBL_REG); | ||
1593 | IWL_CMD(CSR_GIO_CHICKEN_BITS); | ||
1594 | IWL_CMD(CSR_ANA_PLL_CFG); | ||
1595 | IWL_CMD(CSR_HW_REV_WA_REG); | ||
1596 | IWL_CMD(CSR_DBG_HPET_MEM_REG); | ||
1597 | default: | ||
1598 | return "UNKNOWN"; | ||
1599 | } | ||
1600 | } | ||
1601 | |||
1602 | void iwl_dump_csr(struct iwl_trans *trans) | ||
1603 | { | ||
1604 | int i; | ||
1605 | static const u32 csr_tbl[] = { | ||
1606 | CSR_HW_IF_CONFIG_REG, | ||
1607 | CSR_INT_COALESCING, | ||
1608 | CSR_INT, | ||
1609 | CSR_INT_MASK, | ||
1610 | CSR_FH_INT_STATUS, | ||
1611 | CSR_GPIO_IN, | ||
1612 | CSR_RESET, | ||
1613 | CSR_GP_CNTRL, | ||
1614 | CSR_HW_REV, | ||
1615 | CSR_EEPROM_REG, | ||
1616 | CSR_EEPROM_GP, | ||
1617 | CSR_OTP_GP_REG, | ||
1618 | CSR_GIO_REG, | ||
1619 | CSR_GP_UCODE_REG, | ||
1620 | CSR_GP_DRIVER_REG, | ||
1621 | CSR_UCODE_DRV_GP1, | ||
1622 | CSR_UCODE_DRV_GP2, | ||
1623 | CSR_LED_REG, | ||
1624 | CSR_DRAM_INT_TBL_REG, | ||
1625 | CSR_GIO_CHICKEN_BITS, | ||
1626 | CSR_ANA_PLL_CFG, | ||
1627 | CSR_HW_REV_WA_REG, | ||
1628 | CSR_DBG_HPET_MEM_REG | ||
1629 | }; | ||
1630 | IWL_ERR(trans, "CSR values:\n"); | ||
1631 | IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is " | ||
1632 | "CSR_INT_PERIODIC_REG)\n"); | ||
1633 | for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { | ||
1634 | IWL_ERR(trans, " %25s: 0X%08x\n", | ||
1635 | get_csr_string(csr_tbl[i]), | ||
1636 | iwl_read32(bus(trans), csr_tbl[i])); | ||
1637 | } | ||
1638 | } | ||
1639 | |||
1640 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1641 | /* create and remove of files */ | ||
1642 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | ||
1643 | if (!debugfs_create_file(#name, mode, parent, trans, \ | ||
1644 | &iwl_dbgfs_##name##_ops)) \ | ||
1645 | return -ENOMEM; \ | ||
1646 | } while (0) | ||
1647 | |||
1648 | /* file operation */ | ||
1649 | #define DEBUGFS_READ_FUNC(name) \ | ||
1650 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | ||
1651 | char __user *user_buf, \ | ||
1652 | size_t count, loff_t *ppos); | ||
1653 | |||
1654 | #define DEBUGFS_WRITE_FUNC(name) \ | ||
1655 | static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ | ||
1656 | const char __user *user_buf, \ | ||
1657 | size_t count, loff_t *ppos); | ||
1658 | |||
1659 | |||
1660 | static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) | ||
1661 | { | ||
1662 | file->private_data = inode->i_private; | ||
1663 | return 0; | ||
1664 | } | ||
1665 | |||
1666 | #define DEBUGFS_READ_FILE_OPS(name) \ | ||
1667 | DEBUGFS_READ_FUNC(name); \ | ||
1668 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1669 | .read = iwl_dbgfs_##name##_read, \ | ||
1670 | .open = iwl_dbgfs_open_file_generic, \ | ||
1671 | .llseek = generic_file_llseek, \ | ||
1672 | }; | ||
1673 | |||
1674 | #define DEBUGFS_WRITE_FILE_OPS(name) \ | ||
1675 | DEBUGFS_WRITE_FUNC(name); \ | ||
1676 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1677 | .write = iwl_dbgfs_##name##_write, \ | ||
1678 | .open = iwl_dbgfs_open_file_generic, \ | ||
1679 | .llseek = generic_file_llseek, \ | ||
1680 | }; | ||
1681 | |||
1682 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ | ||
1683 | DEBUGFS_READ_FUNC(name); \ | ||
1684 | DEBUGFS_WRITE_FUNC(name); \ | ||
1685 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1686 | .write = iwl_dbgfs_##name##_write, \ | ||
1687 | .read = iwl_dbgfs_##name##_read, \ | ||
1688 | .open = iwl_dbgfs_open_file_generic, \ | ||
1689 | .llseek = generic_file_llseek, \ | ||
1690 | }; | ||
1691 | |||
1692 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | ||
1693 | char __user *user_buf, | ||
1694 | size_t count, loff_t *ppos) | ||
1695 | { | ||
1696 | struct iwl_trans *trans = file->private_data; | ||
1697 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1698 | struct iwl_tx_queue *txq; | ||
1699 | struct iwl_queue *q; | ||
1700 | char *buf; | ||
1701 | int pos = 0; | ||
1702 | int cnt; | ||
1703 | int ret; | ||
1704 | const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; | ||
1705 | |||
1706 | if (!trans_pcie->txq) { | ||
1707 | IWL_ERR(trans, "txq not ready\n"); | ||
1708 | return -EAGAIN; | ||
1709 | } | ||
1710 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1711 | if (!buf) | ||
1712 | return -ENOMEM; | ||
1713 | |||
1714 | for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { | ||
1715 | txq = &trans_pcie->txq[cnt]; | ||
1716 | q = &txq->q; | ||
1717 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1718 | "hwq %.2d: read=%u write=%u stop=%d" | ||
1719 | " swq_id=%#.2x (ac %d/hwq %d)\n", | ||
1720 | cnt, q->read_ptr, q->write_ptr, | ||
1721 | !!test_bit(cnt, trans_pcie->queue_stopped), | ||
1722 | txq->swq_id, txq->swq_id & 3, | ||
1723 | (txq->swq_id >> 2) & 0x1f); | ||
1724 | if (cnt >= 4) | ||
1725 | continue; | ||
1726 | /* for the ACs, display the stop count too */ | ||
1727 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1728 | " stop-count: %d\n", | ||
1729 | atomic_read(&trans_pcie->queue_stop_count[cnt])); | ||
1730 | } | ||
1731 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1732 | kfree(buf); | ||
1733 | return ret; | ||
1734 | } | ||
1735 | |||
1736 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | ||
1737 | char __user *user_buf, | ||
1738 | size_t count, loff_t *ppos) { | ||
1739 | struct iwl_trans *trans = file->private_data; | ||
1740 | struct iwl_trans_pcie *trans_pcie = | ||
1741 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1742 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
1743 | char buf[256]; | ||
1744 | int pos = 0; | ||
1745 | const size_t bufsz = sizeof(buf); | ||
1746 | |||
1747 | pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", | ||
1748 | rxq->read); | ||
1749 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | ||
1750 | rxq->write); | ||
1751 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | ||
1752 | rxq->free_count); | ||
1753 | if (rxq->rb_stts) { | ||
1754 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | ||
1755 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); | ||
1756 | } else { | ||
1757 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1758 | "closed_rb_num: Not Allocated\n"); | ||
1759 | } | ||
1760 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1761 | } | ||
1762 | |||
1763 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | ||
1764 | char __user *user_buf, | ||
1765 | size_t count, loff_t *ppos) | ||
1766 | { | ||
1767 | struct iwl_trans *trans = file->private_data; | ||
1768 | char *buf; | ||
1769 | int pos = 0; | ||
1770 | ssize_t ret = -ENOMEM; | ||
1771 | |||
1772 | ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true); | ||
1773 | if (buf) { | ||
1774 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1775 | kfree(buf); | ||
1776 | } | ||
1777 | return ret; | ||
1778 | } | ||
1779 | |||
1780 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | ||
1781 | const char __user *user_buf, | ||
1782 | size_t count, loff_t *ppos) | ||
1783 | { | ||
1784 | struct iwl_trans *trans = file->private_data; | ||
1785 | u32 event_log_flag; | ||
1786 | char buf[8]; | ||
1787 | int buf_size; | ||
1788 | |||
1789 | memset(buf, 0, sizeof(buf)); | ||
1790 | buf_size = min(count, sizeof(buf) - 1); | ||
1791 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1792 | return -EFAULT; | ||
1793 | if (sscanf(buf, "%d", &event_log_flag) != 1) | ||
1794 | return -EFAULT; | ||
1795 | if (event_log_flag == 1) | ||
1796 | iwl_dump_nic_event_log(trans, true, NULL, false); | ||
1797 | |||
1798 | return count; | ||
1799 | } | ||
1800 | |||
1801 | static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | ||
1802 | char __user *user_buf, | ||
1803 | size_t count, loff_t *ppos) { | ||
1804 | |||
1805 | struct iwl_trans *trans = file->private_data; | ||
1806 | struct iwl_trans_pcie *trans_pcie = | ||
1807 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1808 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | ||
1809 | |||
1810 | int pos = 0; | ||
1811 | char *buf; | ||
1812 | int bufsz = 24 * 64; /* 24 items * 64 char per item */ | ||
1813 | ssize_t ret; | ||
1814 | |||
1815 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1816 | if (!buf) { | ||
1817 | IWL_ERR(trans, "Can not allocate Buffer\n"); | ||
1818 | return -ENOMEM; | ||
1819 | } | ||
1820 | |||
1821 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1822 | "Interrupt Statistics Report:\n"); | ||
1823 | |||
1824 | pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", | ||
1825 | isr_stats->hw); | ||
1826 | pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", | ||
1827 | isr_stats->sw); | ||
1828 | if (isr_stats->sw || isr_stats->hw) { | ||
1829 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1830 | "\tLast Restarting Code: 0x%X\n", | ||
1831 | isr_stats->err_code); | ||
1832 | } | ||
1833 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1834 | pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", | ||
1835 | isr_stats->sch); | ||
1836 | pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", | ||
1837 | isr_stats->alive); | ||
1838 | #endif | ||
1839 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1840 | "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill); | ||
1841 | |||
1842 | pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", | ||
1843 | isr_stats->ctkill); | ||
1844 | |||
1845 | pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", | ||
1846 | isr_stats->wakeup); | ||
1847 | |||
1848 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1849 | "Rx command responses:\t\t %u\n", isr_stats->rx); | ||
1850 | |||
1851 | pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", | ||
1852 | isr_stats->tx); | ||
1853 | |||
1854 | pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", | ||
1855 | isr_stats->unhandled); | ||
1856 | |||
1857 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1858 | kfree(buf); | ||
1859 | return ret; | ||
1860 | } | ||
1861 | |||
1862 | static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | ||
1863 | const char __user *user_buf, | ||
1864 | size_t count, loff_t *ppos) | ||
1865 | { | ||
1866 | struct iwl_trans *trans = file->private_data; | ||
1867 | struct iwl_trans_pcie *trans_pcie = | ||
1868 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1869 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | ||
1870 | |||
1871 | char buf[8]; | ||
1872 | int buf_size; | ||
1873 | u32 reset_flag; | ||
1874 | |||
1875 | memset(buf, 0, sizeof(buf)); | ||
1876 | buf_size = min(count, sizeof(buf) - 1); | ||
1877 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1878 | return -EFAULT; | ||
1879 | if (sscanf(buf, "%x", &reset_flag) != 1) | ||
1880 | return -EFAULT; | ||
1881 | if (reset_flag == 0) | ||
1882 | memset(isr_stats, 0, sizeof(*isr_stats)); | ||
1883 | |||
1884 | return count; | ||
1885 | } | ||
1886 | |||
1887 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | ||
1888 | const char __user *user_buf, | ||
1889 | size_t count, loff_t *ppos) | ||
1890 | { | ||
1891 | struct iwl_trans *trans = file->private_data; | ||
1892 | char buf[8]; | ||
1893 | int buf_size; | ||
1894 | int csr; | ||
1895 | |||
1896 | memset(buf, 0, sizeof(buf)); | ||
1897 | buf_size = min(count, sizeof(buf) - 1); | ||
1898 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1899 | return -EFAULT; | ||
1900 | if (sscanf(buf, "%d", &csr) != 1) | ||
1901 | return -EFAULT; | ||
1902 | |||
1903 | iwl_dump_csr(trans); | ||
1904 | |||
1905 | return count; | ||
1906 | } | ||
1907 | |||
1908 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | ||
1909 | char __user *user_buf, | ||
1910 | size_t count, loff_t *ppos) | ||
1911 | { | ||
1912 | struct iwl_trans *trans = file->private_data; | ||
1913 | char *buf; | ||
1914 | int pos = 0; | ||
1915 | ssize_t ret = -EFAULT; | ||
1916 | |||
1917 | ret = pos = iwl_dump_fh(trans, &buf, true); | ||
1918 | if (buf) { | ||
1919 | ret = simple_read_from_buffer(user_buf, | ||
1920 | count, ppos, buf, pos); | ||
1921 | kfree(buf); | ||
1922 | } | ||
1923 | |||
1924 | return ret; | ||
1925 | } | ||
1926 | |||
1927 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | ||
1928 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | ||
1929 | DEBUGFS_READ_FILE_OPS(fh_reg); | ||
1930 | DEBUGFS_READ_FILE_OPS(rx_queue); | ||
1931 | DEBUGFS_READ_FILE_OPS(tx_queue); | ||
1932 | DEBUGFS_WRITE_FILE_OPS(csr); | ||
1933 | |||
1934 | /* | ||
1935 | * Create the debugfs files and directories | ||
1936 | * | ||
1937 | */ | ||
1938 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
1939 | struct dentry *dir) | ||
1940 | { | ||
1941 | DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); | ||
1942 | DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); | ||
1943 | DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); | ||
1944 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); | ||
1945 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); | ||
1946 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); | ||
1947 | return 0; | ||
1948 | } | ||
1949 | #else | ||
1950 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
1951 | struct dentry *dir) | ||
1952 | { return 0; } | ||
1953 | |||
1954 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ | ||
1955 | |||
1956 | const struct iwl_trans_ops trans_ops_pcie = { | ||
1957 | .alloc = iwl_trans_pcie_alloc, | ||
1958 | .request_irq = iwl_trans_pcie_request_irq, | ||
1959 | .start_device = iwl_trans_pcie_start_device, | ||
1960 | .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, | ||
1961 | .stop_device = iwl_trans_pcie_stop_device, | ||
1962 | |||
1963 | .tx_start = iwl_trans_pcie_tx_start, | ||
1964 | .wake_any_queue = iwl_trans_pcie_wake_any_queue, | ||
1965 | |||
1966 | .send_cmd = iwl_trans_pcie_send_cmd, | ||
1967 | |||
1968 | .tx = iwl_trans_pcie_tx, | ||
1969 | .reclaim = iwl_trans_pcie_reclaim, | ||
1970 | |||
1971 | .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, | ||
1972 | .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, | ||
1973 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, | ||
1974 | |||
1975 | .kick_nic = iwl_trans_pcie_kick_nic, | ||
1976 | |||
1977 | .free = iwl_trans_pcie_free, | ||
1978 | .stop_queue = iwl_trans_pcie_stop_queue, | ||
1979 | |||
1980 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | ||
1981 | |||
1982 | .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, | ||
1983 | .check_stuck_queue = iwl_trans_pcie_check_stuck_queue, | ||
1984 | |||
1985 | #ifdef CONFIG_PM_SLEEP | ||
1986 | .suspend = iwl_trans_pcie_suspend, | ||
1987 | .resume = iwl_trans_pcie_resume, | ||
1988 | #endif | ||
1989 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index b2e89077c684..1b20c4fb791b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -60,1928 +60,18 @@ | |||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #include <linux/interrupt.h> | ||
64 | #include <linux/debugfs.h> | ||
65 | #include <linux/bitops.h> | ||
66 | #include <linux/gfp.h> | ||
67 | 63 | ||
68 | #include "iwl-trans.h" | 64 | #include "iwl-trans.h" |
69 | #include "iwl-trans-int-pcie.h" | ||
70 | #include "iwl-csr.h" | ||
71 | #include "iwl-prph.h" | ||
72 | #include "iwl-shared.h" | ||
73 | #include "iwl-eeprom.h" | ||
74 | #include "iwl-agn-hw.h" | ||
75 | 65 | ||
76 | static int iwl_trans_rx_alloc(struct iwl_trans *trans) | 66 | int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, |
67 | u32 flags, u16 len, const void *data) | ||
77 | { | 68 | { |
78 | struct iwl_trans_pcie *trans_pcie = | 69 | struct iwl_host_cmd cmd = { |
79 | IWL_TRANS_GET_PCIE_TRANS(trans); | 70 | .id = id, |
80 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 71 | .len = { len, }, |
81 | struct device *dev = bus(trans)->dev; | 72 | .data = { data, }, |
82 | 73 | .flags = flags, | |
83 | memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); | ||
84 | |||
85 | spin_lock_init(&rxq->lock); | ||
86 | INIT_LIST_HEAD(&rxq->rx_free); | ||
87 | INIT_LIST_HEAD(&rxq->rx_used); | ||
88 | |||
89 | if (WARN_ON(rxq->bd || rxq->rb_stts)) | ||
90 | return -EINVAL; | ||
91 | |||
92 | /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ | ||
93 | rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
94 | &rxq->bd_dma, GFP_KERNEL); | ||
95 | if (!rxq->bd) | ||
96 | goto err_bd; | ||
97 | memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE); | ||
98 | |||
99 | /*Allocate the driver's pointer to receive buffer status */ | ||
100 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts), | ||
101 | &rxq->rb_stts_dma, GFP_KERNEL); | ||
102 | if (!rxq->rb_stts) | ||
103 | goto err_rb_stts; | ||
104 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); | ||
105 | |||
106 | return 0; | ||
107 | |||
108 | err_rb_stts: | ||
109 | dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
110 | rxq->bd, rxq->bd_dma); | ||
111 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | ||
112 | rxq->bd = NULL; | ||
113 | err_bd: | ||
114 | return -ENOMEM; | ||
115 | } | ||
116 | |||
117 | static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) | ||
118 | { | ||
119 | struct iwl_trans_pcie *trans_pcie = | ||
120 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
121 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
122 | int i; | ||
123 | |||
124 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
125 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
126 | /* In the reset function, these buffers may have been allocated | ||
127 | * to an SKB, so we need to unmap and free potential storage */ | ||
128 | if (rxq->pool[i].page != NULL) { | ||
129 | dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, | ||
130 | PAGE_SIZE << hw_params(trans).rx_page_order, | ||
131 | DMA_FROM_DEVICE); | ||
132 | __free_pages(rxq->pool[i].page, | ||
133 | hw_params(trans).rx_page_order); | ||
134 | rxq->pool[i].page = NULL; | ||
135 | } | ||
136 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | ||
141 | struct iwl_rx_queue *rxq) | ||
142 | { | ||
143 | u32 rb_size; | ||
144 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
145 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
146 | |||
147 | rb_timeout = RX_RB_TIMEOUT; | ||
148 | |||
149 | if (iwlagn_mod_params.amsdu_size_8K) | ||
150 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
151 | else | ||
152 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
153 | |||
154 | /* Stop Rx DMA */ | ||
155 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
156 | |||
157 | /* Reset driver's Rx queue write index */ | ||
158 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
159 | |||
160 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
161 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
162 | (u32)(rxq->bd_dma >> 8)); | ||
163 | |||
164 | /* Tell device where in DRAM to update its Rx status */ | ||
165 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
166 | rxq->rb_stts_dma >> 4); | ||
167 | |||
168 | /* Enable Rx DMA | ||
169 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
170 | * the credit mechanism in 5000 HW RX FIFO | ||
171 | * Direct rx interrupts to hosts | ||
172 | * Rx buffer size 4 or 8k | ||
173 | * RB timeout 0x10 | ||
174 | * 256 RBDs | ||
175 | */ | ||
176 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
177 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
178 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
179 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
180 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
181 | rb_size| | ||
182 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
183 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
184 | |||
185 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
186 | iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
187 | } | ||
188 | |||
189 | static int iwl_rx_init(struct iwl_trans *trans) | ||
190 | { | ||
191 | struct iwl_trans_pcie *trans_pcie = | ||
192 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
193 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
194 | |||
195 | int i, err; | ||
196 | unsigned long flags; | ||
197 | |||
198 | if (!rxq->bd) { | ||
199 | err = iwl_trans_rx_alloc(trans); | ||
200 | if (err) | ||
201 | return err; | ||
202 | } | ||
203 | |||
204 | spin_lock_irqsave(&rxq->lock, flags); | ||
205 | INIT_LIST_HEAD(&rxq->rx_free); | ||
206 | INIT_LIST_HEAD(&rxq->rx_used); | ||
207 | |||
208 | iwl_trans_rxq_free_rx_bufs(trans); | ||
209 | |||
210 | for (i = 0; i < RX_QUEUE_SIZE; i++) | ||
211 | rxq->queue[i] = NULL; | ||
212 | |||
213 | /* Set us so that we have processed and used all buffers, but have | ||
214 | * not restocked the Rx queue with fresh buffers */ | ||
215 | rxq->read = rxq->write = 0; | ||
216 | rxq->write_actual = 0; | ||
217 | rxq->free_count = 0; | ||
218 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
219 | |||
220 | iwlagn_rx_replenish(trans); | ||
221 | |||
222 | iwl_trans_rx_hw_init(trans, rxq); | ||
223 | |||
224 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
225 | rxq->need_update = 1; | ||
226 | iwl_rx_queue_update_write_ptr(trans, rxq); | ||
227 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) | ||
233 | { | ||
234 | struct iwl_trans_pcie *trans_pcie = | ||
235 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
236 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
237 | |||
238 | unsigned long flags; | ||
239 | |||
240 | /*if rxq->bd is NULL, it means that nothing has been allocated, | ||
241 | * exit now */ | ||
242 | if (!rxq->bd) { | ||
243 | IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); | ||
244 | return; | ||
245 | } | ||
246 | |||
247 | spin_lock_irqsave(&rxq->lock, flags); | ||
248 | iwl_trans_rxq_free_rx_bufs(trans); | ||
249 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
250 | |||
251 | dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
252 | rxq->bd, rxq->bd_dma); | ||
253 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | ||
254 | rxq->bd = NULL; | ||
255 | |||
256 | if (rxq->rb_stts) | ||
257 | dma_free_coherent(bus(trans)->dev, | ||
258 | sizeof(struct iwl_rb_status), | ||
259 | rxq->rb_stts, rxq->rb_stts_dma); | ||
260 | else | ||
261 | IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); | ||
262 | memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); | ||
263 | rxq->rb_stts = NULL; | ||
264 | } | ||
265 | |||
266 | static int iwl_trans_rx_stop(struct iwl_trans *trans) | ||
267 | { | ||
268 | |||
269 | /* stop Rx DMA */ | ||
270 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
271 | return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG, | ||
272 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
273 | } | ||
274 | |||
275 | static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, | ||
276 | struct iwl_dma_ptr *ptr, size_t size) | ||
277 | { | ||
278 | if (WARN_ON(ptr->addr)) | ||
279 | return -EINVAL; | ||
280 | |||
281 | ptr->addr = dma_alloc_coherent(bus(trans)->dev, size, | ||
282 | &ptr->dma, GFP_KERNEL); | ||
283 | if (!ptr->addr) | ||
284 | return -ENOMEM; | ||
285 | ptr->size = size; | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, | ||
290 | struct iwl_dma_ptr *ptr) | ||
291 | { | ||
292 | if (unlikely(!ptr->addr)) | ||
293 | return; | ||
294 | |||
295 | dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma); | ||
296 | memset(ptr, 0, sizeof(*ptr)); | ||
297 | } | ||
298 | |||
299 | static int iwl_trans_txq_alloc(struct iwl_trans *trans, | ||
300 | struct iwl_tx_queue *txq, int slots_num, | ||
301 | u32 txq_id) | ||
302 | { | ||
303 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; | ||
304 | int i; | ||
305 | |||
306 | if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) | ||
307 | return -EINVAL; | ||
308 | |||
309 | txq->q.n_window = slots_num; | ||
310 | |||
311 | txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num, | ||
312 | GFP_KERNEL); | ||
313 | txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num, | ||
314 | GFP_KERNEL); | ||
315 | |||
316 | if (!txq->meta || !txq->cmd) | ||
317 | goto error; | ||
318 | |||
319 | if (txq_id == trans->shrd->cmd_queue) | ||
320 | for (i = 0; i < slots_num; i++) { | ||
321 | txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), | ||
322 | GFP_KERNEL); | ||
323 | if (!txq->cmd[i]) | ||
324 | goto error; | ||
325 | } | ||
326 | |||
327 | /* Alloc driver data array and TFD circular buffer */ | ||
328 | /* Driver private data, only for Tx (not command) queues, | ||
329 | * not shared with device. */ | ||
330 | if (txq_id != trans->shrd->cmd_queue) { | ||
331 | txq->skbs = kzalloc(sizeof(txq->skbs[0]) * | ||
332 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); | ||
333 | if (!txq->skbs) { | ||
334 | IWL_ERR(trans, "kmalloc for auxiliary BD " | ||
335 | "structures failed\n"); | ||
336 | goto error; | ||
337 | } | ||
338 | } else { | ||
339 | txq->skbs = NULL; | ||
340 | } | ||
341 | |||
342 | /* Circular buffer of transmit frame descriptors (TFDs), | ||
343 | * shared with device */ | ||
344 | txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz, | ||
345 | &txq->q.dma_addr, GFP_KERNEL); | ||
346 | if (!txq->tfds) { | ||
347 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); | ||
348 | goto error; | ||
349 | } | ||
350 | txq->q.id = txq_id; | ||
351 | |||
352 | return 0; | ||
353 | error: | ||
354 | kfree(txq->skbs); | ||
355 | txq->skbs = NULL; | ||
356 | /* since txq->cmd has been zeroed, | ||
357 | * all non allocated cmd[i] will be NULL */ | ||
358 | if (txq->cmd && txq_id == trans->shrd->cmd_queue) | ||
359 | for (i = 0; i < slots_num; i++) | ||
360 | kfree(txq->cmd[i]); | ||
361 | kfree(txq->meta); | ||
362 | kfree(txq->cmd); | ||
363 | txq->meta = NULL; | ||
364 | txq->cmd = NULL; | ||
365 | |||
366 | return -ENOMEM; | ||
367 | |||
368 | } | ||
369 | |||
370 | static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, | ||
371 | int slots_num, u32 txq_id) | ||
372 | { | ||
373 | int ret; | ||
374 | |||
375 | txq->need_update = 0; | ||
376 | memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num); | ||
377 | |||
378 | /* | ||
379 | * For the default queues 0-3, set up the swq_id | ||
380 | * already -- all others need to get one later | ||
381 | * (if they need one at all). | ||
382 | */ | ||
383 | if (txq_id < 4) | ||
384 | iwl_set_swq_id(txq, txq_id, txq_id); | ||
385 | |||
386 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | ||
387 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ | ||
388 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | ||
389 | |||
390 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
391 | ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, | ||
392 | txq_id); | ||
393 | if (ret) | ||
394 | return ret; | ||
395 | |||
396 | /* | ||
397 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
398 | * given Tx queue, and enable the DMA channel used for that queue. | ||
399 | * Circular buffer (TFD queue in DRAM) physical base address */ | ||
400 | iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id), | ||
401 | txq->q.dma_addr >> 8); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | ||
408 | */ | ||
409 | static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) | ||
410 | { | ||
411 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
412 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | ||
413 | struct iwl_queue *q = &txq->q; | ||
414 | |||
415 | if (!q->n_bd) | ||
416 | return; | ||
417 | |||
418 | while (q->write_ptr != q->read_ptr) { | ||
419 | /* The read_ptr needs to bound by q->n_window */ | ||
420 | iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr)); | ||
421 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | ||
422 | } | ||
423 | } | ||
424 | |||
425 | /** | ||
426 | * iwl_tx_queue_free - Deallocate DMA queue. | ||
427 | * @txq: Transmit queue to deallocate. | ||
428 | * | ||
429 | * Empty queue by removing and destroying all BD's. | ||
430 | * Free all buffers. | ||
431 | * 0-fill, but do not free "txq" descriptor structure. | ||
432 | */ | ||
433 | static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) | ||
434 | { | ||
435 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
436 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | ||
437 | struct device *dev = bus(trans)->dev; | ||
438 | int i; | ||
439 | if (WARN_ON(!txq)) | ||
440 | return; | ||
441 | |||
442 | iwl_tx_queue_unmap(trans, txq_id); | ||
443 | |||
444 | /* De-alloc array of command/tx buffers */ | ||
445 | |||
446 | if (txq_id == trans->shrd->cmd_queue) | ||
447 | for (i = 0; i < txq->q.n_window; i++) | ||
448 | kfree(txq->cmd[i]); | ||
449 | |||
450 | /* De-alloc circular buffer of TFDs */ | ||
451 | if (txq->q.n_bd) { | ||
452 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * | ||
453 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | ||
454 | memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); | ||
455 | } | ||
456 | |||
457 | /* De-alloc array of per-TFD driver data */ | ||
458 | kfree(txq->skbs); | ||
459 | txq->skbs = NULL; | ||
460 | |||
461 | /* deallocate arrays */ | ||
462 | kfree(txq->cmd); | ||
463 | kfree(txq->meta); | ||
464 | txq->cmd = NULL; | ||
465 | txq->meta = NULL; | ||
466 | |||
467 | /* 0-fill queue descriptor structure */ | ||
468 | memset(txq, 0, sizeof(*txq)); | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * iwl_trans_tx_free - Free TXQ Context | ||
473 | * | ||
474 | * Destroy all TX DMA queues and structures | ||
475 | */ | ||
476 | static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) | ||
477 | { | ||
478 | int txq_id; | ||
479 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
480 | |||
481 | /* Tx queues */ | ||
482 | if (trans_pcie->txq) { | ||
483 | for (txq_id = 0; | ||
484 | txq_id < hw_params(trans).max_txq_num; txq_id++) | ||
485 | iwl_tx_queue_free(trans, txq_id); | ||
486 | } | ||
487 | |||
488 | kfree(trans_pcie->txq); | ||
489 | trans_pcie->txq = NULL; | ||
490 | |||
491 | iwlagn_free_dma_ptr(trans, &trans_pcie->kw); | ||
492 | |||
493 | iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * iwl_trans_tx_alloc - allocate TX context | ||
498 | * Allocate all Tx DMA structures and initialize them | ||
499 | * | ||
500 | * @param priv | ||
501 | * @return error code | ||
502 | */ | ||
503 | static int iwl_trans_tx_alloc(struct iwl_trans *trans) | ||
504 | { | ||
505 | int ret; | ||
506 | int txq_id, slots_num; | ||
507 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
508 | |||
509 | u16 scd_bc_tbls_size = hw_params(trans).max_txq_num * | ||
510 | sizeof(struct iwlagn_scd_bc_tbl); | ||
511 | |||
512 | /*It is not allowed to alloc twice, so warn when this happens. | ||
513 | * We cannot rely on the previous allocation, so free and fail */ | ||
514 | if (WARN_ON(trans_pcie->txq)) { | ||
515 | ret = -EINVAL; | ||
516 | goto error; | ||
517 | } | ||
518 | |||
519 | ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, | ||
520 | scd_bc_tbls_size); | ||
521 | if (ret) { | ||
522 | IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); | ||
523 | goto error; | ||
524 | } | ||
525 | |||
526 | /* Alloc keep-warm buffer */ | ||
527 | ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); | ||
528 | if (ret) { | ||
529 | IWL_ERR(trans, "Keep Warm allocation failed\n"); | ||
530 | goto error; | ||
531 | } | ||
532 | |||
533 | trans_pcie->txq = kzalloc(sizeof(struct iwl_tx_queue) * | ||
534 | hw_params(trans).max_txq_num, GFP_KERNEL); | ||
535 | if (!trans_pcie->txq) { | ||
536 | IWL_ERR(trans, "Not enough memory for txq\n"); | ||
537 | ret = ENOMEM; | ||
538 | goto error; | ||
539 | } | ||
540 | |||
541 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | ||
542 | for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { | ||
543 | slots_num = (txq_id == trans->shrd->cmd_queue) ? | ||
544 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
545 | ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], | ||
546 | slots_num, txq_id); | ||
547 | if (ret) { | ||
548 | IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); | ||
549 | goto error; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | return 0; | ||
554 | |||
555 | error: | ||
556 | iwl_trans_pcie_tx_free(trans); | ||
557 | |||
558 | return ret; | ||
559 | } | ||
560 | static int iwl_tx_init(struct iwl_trans *trans) | ||
561 | { | ||
562 | int ret; | ||
563 | int txq_id, slots_num; | ||
564 | unsigned long flags; | ||
565 | bool alloc = false; | ||
566 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
567 | |||
568 | if (!trans_pcie->txq) { | ||
569 | ret = iwl_trans_tx_alloc(trans); | ||
570 | if (ret) | ||
571 | goto error; | ||
572 | alloc = true; | ||
573 | } | ||
574 | |||
575 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
576 | |||
577 | /* Turn off all Tx DMA fifos */ | ||
578 | iwl_write_prph(bus(trans), SCD_TXFACT, 0); | ||
579 | |||
580 | /* Tell NIC where to find the "keep warm" buffer */ | ||
581 | iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG, | ||
582 | trans_pcie->kw.dma >> 4); | ||
583 | |||
584 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
585 | |||
586 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | ||
587 | for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { | ||
588 | slots_num = (txq_id == trans->shrd->cmd_queue) ? | ||
589 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
590 | ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], | ||
591 | slots_num, txq_id); | ||
592 | if (ret) { | ||
593 | IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); | ||
594 | goto error; | ||
595 | } | ||
596 | } | ||
597 | |||
598 | return 0; | ||
599 | error: | ||
600 | /*Upon error, free only if we allocated something */ | ||
601 | if (alloc) | ||
602 | iwl_trans_pcie_tx_free(trans); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | static void iwl_set_pwr_vmain(struct iwl_trans *trans) | ||
607 | { | ||
608 | /* | ||
609 | * (for documentation purposes) | ||
610 | * to set power to V_AUX, do: | ||
611 | |||
612 | if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) | ||
613 | iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, | ||
614 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, | ||
615 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
616 | */ | ||
617 | |||
618 | iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, | ||
619 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, | ||
620 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
621 | } | ||
622 | |||
623 | static int iwl_nic_init(struct iwl_trans *trans) | ||
624 | { | ||
625 | unsigned long flags; | ||
626 | |||
627 | /* nic_init */ | ||
628 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
629 | iwl_apm_init(priv(trans)); | ||
630 | |||
631 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
632 | iwl_write8(bus(trans), CSR_INT_COALESCING, | ||
633 | IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
634 | |||
635 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
636 | |||
637 | iwl_set_pwr_vmain(trans); | ||
638 | |||
639 | iwl_nic_config(priv(trans)); | ||
640 | |||
641 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
642 | iwl_rx_init(trans); | ||
643 | |||
644 | /* Allocate or reset and init all Tx and Command queues */ | ||
645 | if (iwl_tx_init(trans)) | ||
646 | return -ENOMEM; | ||
647 | |||
648 | if (hw_params(trans).shadow_reg_enable) { | ||
649 | /* enable shadow regs in HW */ | ||
650 | iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, | ||
651 | 0x800FFFFF); | ||
652 | } | ||
653 | |||
654 | set_bit(STATUS_INIT, &trans->shrd->status); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | #define HW_READY_TIMEOUT (50) | ||
660 | |||
661 | /* Note: returns poll_bit return value, which is >= 0 if success */ | ||
662 | static int iwl_set_hw_ready(struct iwl_trans *trans) | ||
663 | { | ||
664 | int ret; | ||
665 | |||
666 | iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
667 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); | ||
668 | |||
669 | /* See if we got it */ | ||
670 | ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
671 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | ||
672 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | ||
673 | HW_READY_TIMEOUT); | ||
674 | |||
675 | IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); | ||
676 | return ret; | ||
677 | } | ||
678 | |||
679 | /* Note: returns standard 0/-ERROR code */ | ||
680 | static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) | ||
681 | { | ||
682 | int ret; | ||
683 | |||
684 | IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); | ||
685 | |||
686 | ret = iwl_set_hw_ready(trans); | ||
687 | if (ret >= 0) | ||
688 | return 0; | ||
689 | |||
690 | /* If HW is not ready, prepare the conditions to check again */ | ||
691 | iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
692 | CSR_HW_IF_CONFIG_REG_PREPARE); | ||
693 | |||
694 | ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | ||
695 | ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, | ||
696 | CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); | ||
697 | |||
698 | if (ret < 0) | ||
699 | return ret; | ||
700 | |||
701 | /* HW should be ready by now, check again. */ | ||
702 | ret = iwl_set_hw_ready(trans); | ||
703 | if (ret >= 0) | ||
704 | return 0; | ||
705 | return ret; | ||
706 | } | ||
707 | |||
708 | #define IWL_AC_UNSET -1 | ||
709 | |||
710 | struct queue_to_fifo_ac { | ||
711 | s8 fifo, ac; | ||
712 | }; | ||
713 | |||
714 | static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { | ||
715 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
716 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
717 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
718 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
719 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
720 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
721 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
722 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
723 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
724 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
725 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
726 | }; | ||
727 | |||
728 | static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { | ||
729 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
730 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
731 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
732 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
733 | { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, | ||
734 | { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, | ||
735 | { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, | ||
736 | { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, | ||
737 | { IWL_TX_FIFO_BE_IPAN, 2, }, | ||
738 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
739 | { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, | ||
740 | }; | ||
741 | |||
742 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
743 | IWL_TX_FIFO_VO, | ||
744 | IWL_TX_FIFO_VI, | ||
745 | IWL_TX_FIFO_BE, | ||
746 | IWL_TX_FIFO_BK, | ||
747 | }; | ||
748 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
749 | 0, 1, 2, 3, | ||
750 | }; | ||
751 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
752 | IWL_TX_FIFO_VO_IPAN, | ||
753 | IWL_TX_FIFO_VI_IPAN, | ||
754 | IWL_TX_FIFO_BE_IPAN, | ||
755 | IWL_TX_FIFO_BK_IPAN, | ||
756 | }; | ||
757 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
758 | 7, 6, 5, 4, | ||
759 | }; | ||
760 | |||
761 | static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | ||
762 | { | ||
763 | int ret; | ||
764 | struct iwl_trans_pcie *trans_pcie = | ||
765 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
766 | |||
767 | trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; | ||
768 | trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; | ||
769 | trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; | ||
770 | |||
771 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo; | ||
772 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo; | ||
773 | |||
774 | trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; | ||
775 | trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; | ||
776 | |||
777 | if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && | ||
778 | iwl_trans_pcie_prepare_card_hw(trans)) { | ||
779 | IWL_WARN(trans, "Exit HW not ready\n"); | ||
780 | return -EIO; | ||
781 | } | ||
782 | |||
783 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
784 | if (iwl_read32(bus(trans), CSR_GP_CNTRL) & | ||
785 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | ||
786 | clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
787 | else | ||
788 | set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
789 | |||
790 | if (iwl_is_rfkill(trans->shrd)) { | ||
791 | iwl_set_hw_rfkill_state(priv(trans), true); | ||
792 | iwl_enable_interrupts(trans); | ||
793 | return -ERFKILL; | ||
794 | } | ||
795 | |||
796 | iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); | ||
797 | |||
798 | ret = iwl_nic_init(trans); | ||
799 | if (ret) { | ||
800 | IWL_ERR(trans, "Unable to init nic\n"); | ||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | /* make sure rfkill handshake bits are cleared */ | ||
805 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
806 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, | ||
807 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
808 | |||
809 | /* clear (again), then enable host interrupts */ | ||
810 | iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); | ||
811 | iwl_enable_interrupts(trans); | ||
812 | |||
813 | /* really make sure rfkill handshake bits are cleared */ | ||
814 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
815 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
816 | |||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | /* | ||
821 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
822 | * must be called under priv->shrd->lock and mac access | ||
823 | */ | ||
824 | static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) | ||
825 | { | ||
826 | iwl_write_prph(bus(trans), SCD_TXFACT, mask); | ||
827 | } | ||
828 | |||
829 | static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) | ||
830 | { | ||
831 | const struct queue_to_fifo_ac *queue_to_fifo; | ||
832 | struct iwl_trans_pcie *trans_pcie = | ||
833 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
834 | u32 a; | ||
835 | unsigned long flags; | ||
836 | int i, chan; | ||
837 | u32 reg_val; | ||
838 | |||
839 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
840 | |||
841 | trans_pcie->scd_base_addr = | ||
842 | iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR); | ||
843 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | ||
844 | /* reset conext data memory */ | ||
845 | for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; | ||
846 | a += 4) | ||
847 | iwl_write_targ_mem(bus(trans), a, 0); | ||
848 | /* reset tx status memory */ | ||
849 | for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; | ||
850 | a += 4) | ||
851 | iwl_write_targ_mem(bus(trans), a, 0); | ||
852 | for (; a < trans_pcie->scd_base_addr + | ||
853 | SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); | ||
854 | a += 4) | ||
855 | iwl_write_targ_mem(bus(trans), a, 0); | ||
856 | |||
857 | iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR, | ||
858 | trans_pcie->scd_bc_tbls.dma >> 10); | ||
859 | |||
860 | /* Enable DMA channel */ | ||
861 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | ||
862 | iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
863 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
864 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
865 | |||
866 | /* Update FH chicken bits */ | ||
867 | reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG); | ||
868 | iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG, | ||
869 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
870 | |||
871 | iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, | ||
872 | SCD_QUEUECHAIN_SEL_ALL(trans)); | ||
873 | iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); | ||
874 | |||
875 | /* initiate the queues */ | ||
876 | for (i = 0; i < hw_params(trans).max_txq_num; i++) { | ||
877 | iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); | ||
878 | iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
879 | iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + | ||
880 | SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
881 | iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + | ||
882 | SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
883 | sizeof(u32), | ||
884 | ((SCD_WIN_SIZE << | ||
885 | SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
886 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
887 | ((SCD_FRAME_LIMIT << | ||
888 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
889 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
890 | } | ||
891 | |||
892 | iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK, | ||
893 | IWL_MASK(0, hw_params(trans).max_txq_num)); | ||
894 | |||
895 | /* Activate all Tx DMA/FIFO channels */ | ||
896 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); | ||
897 | |||
898 | /* map queues to FIFOs */ | ||
899 | if (trans->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS)) | ||
900 | queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; | ||
901 | else | ||
902 | queue_to_fifo = iwlagn_default_queue_to_tx_fifo; | ||
903 | |||
904 | iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0); | ||
905 | |||
906 | /* make sure all queue are not stopped */ | ||
907 | memset(&trans_pcie->queue_stopped[0], 0, | ||
908 | sizeof(trans_pcie->queue_stopped)); | ||
909 | for (i = 0; i < 4; i++) | ||
910 | atomic_set(&trans_pcie->queue_stop_count[i], 0); | ||
911 | |||
912 | /* reset to 0 to enable all the queue first */ | ||
913 | trans_pcie->txq_ctx_active_msk = 0; | ||
914 | |||
915 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) < | ||
916 | IWLAGN_FIRST_AMPDU_QUEUE); | ||
917 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) < | ||
918 | IWLAGN_FIRST_AMPDU_QUEUE); | ||
919 | |||
920 | for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) { | ||
921 | int fifo = queue_to_fifo[i].fifo; | ||
922 | int ac = queue_to_fifo[i].ac; | ||
923 | |||
924 | iwl_txq_ctx_activate(trans_pcie, i); | ||
925 | |||
926 | if (fifo == IWL_TX_FIFO_UNUSED) | ||
927 | continue; | ||
928 | |||
929 | if (ac != IWL_AC_UNSET) | ||
930 | iwl_set_swq_id(&trans_pcie->txq[i], ac, i); | ||
931 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], | ||
932 | fifo, 0); | ||
933 | } | ||
934 | |||
935 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
936 | |||
937 | /* Enable L1-Active */ | ||
938 | iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG, | ||
939 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
940 | } | ||
941 | |||
942 | /** | ||
943 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | ||
944 | */ | ||
945 | static int iwl_trans_tx_stop(struct iwl_trans *trans) | ||
946 | { | ||
947 | int ch, txq_id; | ||
948 | unsigned long flags; | ||
949 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
950 | |||
951 | /* Turn off all Tx DMA fifos */ | ||
952 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
953 | |||
954 | iwl_trans_txq_set_sched(trans, 0); | ||
955 | |||
956 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
957 | for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { | ||
958 | iwl_write_direct32(bus(trans), | ||
959 | FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
960 | if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG, | ||
961 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
962 | 1000)) | ||
963 | IWL_ERR(trans, "Failing on timeout while stopping" | ||
964 | " DMA channel %d [0x%08x]", ch, | ||
965 | iwl_read_direct32(bus(trans), | ||
966 | FH_TSSR_TX_STATUS_REG)); | ||
967 | } | ||
968 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
969 | |||
970 | if (!trans_pcie->txq) { | ||
971 | IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | /* Unmap DMA from host system and free skb's */ | ||
976 | for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) | ||
977 | iwl_tx_queue_unmap(trans, txq_id); | ||
978 | |||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) | ||
983 | { | ||
984 | unsigned long flags; | ||
985 | struct iwl_trans_pcie *trans_pcie = | ||
986 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
987 | |||
988 | spin_lock_irqsave(&trans->shrd->lock, flags); | ||
989 | iwl_disable_interrupts(trans); | ||
990 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | ||
991 | |||
992 | /* wait to make sure we flush pending tasklet*/ | ||
993 | synchronize_irq(bus(trans)->irq); | ||
994 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
995 | } | ||
996 | |||
997 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | ||
998 | { | ||
999 | /* stop and reset the on-board processor */ | ||
1000 | iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
1001 | |||
1002 | /* tell the device to stop sending interrupts */ | ||
1003 | iwl_trans_pcie_disable_sync_irq(trans); | ||
1004 | |||
1005 | /* device going down, Stop using ICT table */ | ||
1006 | iwl_disable_ict(trans); | ||
1007 | |||
1008 | /* | ||
1009 | * If a HW restart happens during firmware loading, | ||
1010 | * then the firmware loading might call this function | ||
1011 | * and later it might be called again due to the | ||
1012 | * restart. So don't process again if the device is | ||
1013 | * already dead. | ||
1014 | */ | ||
1015 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { | ||
1016 | iwl_trans_tx_stop(trans); | ||
1017 | iwl_trans_rx_stop(trans); | ||
1018 | |||
1019 | /* Power-down device's busmaster DMA clocks */ | ||
1020 | iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, | ||
1021 | APMG_CLK_VAL_DMA_CLK_RQT); | ||
1022 | udelay(5); | ||
1023 | } | ||
1024 | |||
1025 | /* Make sure (redundant) we've released our request to stay awake */ | ||
1026 | iwl_clear_bit(bus(trans), CSR_GP_CNTRL, | ||
1027 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
1028 | |||
1029 | /* Stop the device, and put it in low power state */ | ||
1030 | iwl_apm_stop(priv(trans)); | ||
1031 | } | ||
1032 | |||
1033 | static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | ||
1034 | struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) | ||
1035 | { | ||
1036 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1037 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1038 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1039 | struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; | ||
1040 | struct iwl_cmd_meta *out_meta; | ||
1041 | struct iwl_tx_queue *txq; | ||
1042 | struct iwl_queue *q; | ||
1043 | |||
1044 | dma_addr_t phys_addr = 0; | ||
1045 | dma_addr_t txcmd_phys; | ||
1046 | dma_addr_t scratch_phys; | ||
1047 | u16 len, firstlen, secondlen; | ||
1048 | u16 seq_number = 0; | ||
1049 | u8 wait_write_ptr = 0; | ||
1050 | u8 txq_id; | ||
1051 | u8 tid = 0; | ||
1052 | bool is_agg = false; | ||
1053 | __le16 fc = hdr->frame_control; | ||
1054 | u8 hdr_len = ieee80211_hdrlen(fc); | ||
1055 | |||
1056 | /* | ||
1057 | * Send this frame after DTIM -- there's a special queue | ||
1058 | * reserved for this for contexts that support AP mode. | ||
1059 | */ | ||
1060 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
1061 | txq_id = trans_pcie->mcast_queue[ctx]; | ||
1062 | |||
1063 | /* | ||
1064 | * The microcode will clear the more data | ||
1065 | * bit in the last frame it transmits. | ||
1066 | */ | ||
1067 | hdr->frame_control |= | ||
1068 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1069 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
1070 | txq_id = IWL_AUX_QUEUE; | ||
1071 | else | ||
1072 | txq_id = | ||
1073 | trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)]; | ||
1074 | |||
1075 | if (ieee80211_is_data_qos(fc)) { | ||
1076 | u8 *qc = NULL; | ||
1077 | struct iwl_tid_data *tid_data; | ||
1078 | qc = ieee80211_get_qos_ctl(hdr); | ||
1079 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
1080 | tid_data = &trans->shrd->tid_data[sta_id][tid]; | ||
1081 | |||
1082 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | ||
1083 | return -1; | ||
1084 | |||
1085 | seq_number = tid_data->seq_number; | ||
1086 | seq_number &= IEEE80211_SCTL_SEQ; | ||
1087 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
1088 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
1089 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
1090 | seq_number += 0x10; | ||
1091 | /* aggregation is on for this <sta,tid> */ | ||
1092 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
1093 | tid_data->agg.state == IWL_AGG_ON) { | ||
1094 | txq_id = tid_data->agg.txq_id; | ||
1095 | is_agg = true; | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | txq = &trans_pcie->txq[txq_id]; | ||
1100 | q = &txq->q; | ||
1101 | |||
1102 | /* Set up driver data for this TFD */ | ||
1103 | txq->skbs[q->write_ptr] = skb; | ||
1104 | txq->cmd[q->write_ptr] = dev_cmd; | ||
1105 | |||
1106 | dev_cmd->hdr.cmd = REPLY_TX; | ||
1107 | dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
1108 | INDEX_TO_SEQ(q->write_ptr))); | ||
1109 | |||
1110 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
1111 | out_meta = &txq->meta[q->write_ptr]; | ||
1112 | |||
1113 | /* | ||
1114 | * Use the first empty entry in this queue's command buffer array | ||
1115 | * to contain the Tx command and MAC header concatenated together | ||
1116 | * (payload data will be in another buffer). | ||
1117 | * Size of this varies, due to varying MAC header length. | ||
1118 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
1119 | * of the MAC header (device reads on dword boundaries). | ||
1120 | * We'll tell device about this padding later. | ||
1121 | */ | ||
1122 | len = sizeof(struct iwl_tx_cmd) + | ||
1123 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
1124 | firstlen = (len + 3) & ~3; | ||
1125 | |||
1126 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
1127 | if (firstlen != len) | ||
1128 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
1129 | |||
1130 | /* Physical address of this Tx command's header (not MAC header!), | ||
1131 | * within command buffer array. */ | ||
1132 | txcmd_phys = dma_map_single(bus(trans)->dev, | ||
1133 | &dev_cmd->hdr, firstlen, | ||
1134 | DMA_BIDIRECTIONAL); | ||
1135 | if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) | ||
1136 | return -1; | ||
1137 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
1138 | dma_unmap_len_set(out_meta, len, firstlen); | ||
1139 | |||
1140 | if (!ieee80211_has_morefrags(fc)) { | ||
1141 | txq->need_update = 1; | ||
1142 | } else { | ||
1143 | wait_write_ptr = 1; | ||
1144 | txq->need_update = 0; | ||
1145 | } | ||
1146 | |||
1147 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
1148 | * if any (802.11 null frames have no payload). */ | ||
1149 | secondlen = skb->len - hdr_len; | ||
1150 | if (secondlen > 0) { | ||
1151 | phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, | ||
1152 | secondlen, DMA_TO_DEVICE); | ||
1153 | if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { | ||
1154 | dma_unmap_single(bus(trans)->dev, | ||
1155 | dma_unmap_addr(out_meta, mapping), | ||
1156 | dma_unmap_len(out_meta, len), | ||
1157 | DMA_BIDIRECTIONAL); | ||
1158 | return -1; | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | /* Attach buffers to TFD */ | ||
1163 | iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1); | ||
1164 | if (secondlen > 0) | ||
1165 | iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, | ||
1166 | secondlen, 0); | ||
1167 | |||
1168 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
1169 | offsetof(struct iwl_tx_cmd, scratch); | ||
1170 | |||
1171 | /* take back ownership of DMA buffer to enable update */ | ||
1172 | dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, | ||
1173 | DMA_BIDIRECTIONAL); | ||
1174 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1175 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1176 | |||
1177 | IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", | ||
1178 | le16_to_cpu(dev_cmd->hdr.sequence)); | ||
1179 | IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | ||
1180 | iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
1181 | iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
1182 | |||
1183 | /* Set up entry for this TFD in Tx byte-count array */ | ||
1184 | if (is_agg) | ||
1185 | iwl_trans_txq_update_byte_cnt_tbl(trans, txq, | ||
1186 | le16_to_cpu(tx_cmd->len)); | ||
1187 | |||
1188 | dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, | ||
1189 | DMA_BIDIRECTIONAL); | ||
1190 | |||
1191 | trace_iwlwifi_dev_tx(priv(trans), | ||
1192 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
1193 | sizeof(struct iwl_tfd), | ||
1194 | &dev_cmd->hdr, firstlen, | ||
1195 | skb->data + hdr_len, secondlen); | ||
1196 | |||
1197 | /* Tell device the write index *just past* this latest filled TFD */ | ||
1198 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
1199 | iwl_txq_update_write_ptr(trans, txq); | ||
1200 | |||
1201 | if (ieee80211_is_data_qos(fc)) { | ||
1202 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue++; | ||
1203 | if (!ieee80211_has_morefrags(fc)) | ||
1204 | trans->shrd->tid_data[sta_id][tid].seq_number = | ||
1205 | seq_number; | ||
1206 | } | ||
1207 | |||
1208 | /* | ||
1209 | * At this point the frame is "transmitted" successfully | ||
1210 | * and we will get a TX status notification eventually, | ||
1211 | * regardless of the value of ret. "ret" only indicates | ||
1212 | * whether or not we should update the write pointer. | ||
1213 | */ | ||
1214 | if (iwl_queue_space(q) < q->high_mark) { | ||
1215 | if (wait_write_ptr) { | ||
1216 | txq->need_update = 1; | ||
1217 | iwl_txq_update_write_ptr(trans, txq); | ||
1218 | } else { | ||
1219 | iwl_stop_queue(trans, txq); | ||
1220 | } | ||
1221 | } | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) | ||
1226 | { | ||
1227 | /* Remove all resets to allow NIC to operate */ | ||
1228 | iwl_write32(bus(trans), CSR_RESET, 0); | ||
1229 | } | ||
1230 | |||
1231 | static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) | ||
1232 | { | ||
1233 | struct iwl_trans_pcie *trans_pcie = | ||
1234 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1235 | int err; | ||
1236 | |||
1237 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | ||
1238 | |||
1239 | tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) | ||
1240 | iwl_irq_tasklet, (unsigned long)trans); | ||
1241 | |||
1242 | iwl_alloc_isr_ict(trans); | ||
1243 | |||
1244 | err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, | ||
1245 | DRV_NAME, trans); | ||
1246 | if (err) { | ||
1247 | IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); | ||
1248 | iwl_free_isr_ict(trans); | ||
1249 | return err; | ||
1250 | } | ||
1251 | |||
1252 | INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); | ||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | static int iwlagn_txq_check_empty(struct iwl_trans *trans, | ||
1257 | int sta_id, u8 tid, int txq_id) | ||
1258 | { | ||
1259 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1260 | struct iwl_queue *q = &trans_pcie->txq[txq_id].q; | ||
1261 | struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid]; | ||
1262 | |||
1263 | lockdep_assert_held(&trans->shrd->sta_lock); | ||
1264 | |||
1265 | switch (trans->shrd->tid_data[sta_id][tid].agg.state) { | ||
1266 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1267 | /* We are reclaiming the last packet of the */ | ||
1268 | /* aggregated HW queue */ | ||
1269 | if ((txq_id == tid_data->agg.txq_id) && | ||
1270 | (q->read_ptr == q->write_ptr)) { | ||
1271 | IWL_DEBUG_HT(trans, | ||
1272 | "HW queue empty: continue DELBA flow\n"); | ||
1273 | iwl_trans_pcie_txq_agg_disable(trans, txq_id); | ||
1274 | tid_data->agg.state = IWL_AGG_OFF; | ||
1275 | iwl_stop_tx_ba_trans_ready(priv(trans), | ||
1276 | NUM_IWL_RXON_CTX, | ||
1277 | sta_id, tid); | ||
1278 | iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); | ||
1279 | } | ||
1280 | break; | ||
1281 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1282 | /* We are reclaiming the last packet of the queue */ | ||
1283 | if (tid_data->tfds_in_queue == 0) { | ||
1284 | IWL_DEBUG_HT(trans, | ||
1285 | "HW queue empty: continue ADDBA flow\n"); | ||
1286 | tid_data->agg.state = IWL_AGG_ON; | ||
1287 | iwl_start_tx_ba_trans_ready(priv(trans), | ||
1288 | NUM_IWL_RXON_CTX, | ||
1289 | sta_id, tid); | ||
1290 | } | ||
1291 | break; | ||
1292 | } | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | static void iwl_free_tfds_in_queue(struct iwl_trans *trans, | ||
1298 | int sta_id, int tid, int freed) | ||
1299 | { | ||
1300 | lockdep_assert_held(&trans->shrd->sta_lock); | ||
1301 | |||
1302 | if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed) | ||
1303 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed; | ||
1304 | else { | ||
1305 | IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n", | ||
1306 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue, | ||
1307 | freed); | ||
1308 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0; | ||
1309 | } | ||
1310 | } | ||
1311 | |||
1312 | static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, | ||
1313 | int txq_id, int ssn, u32 status, | ||
1314 | struct sk_buff_head *skbs) | ||
1315 | { | ||
1316 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1317 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | ||
1318 | /* n_bd is usually 256 => n_bd - 1 = 0xff */ | ||
1319 | int tfd_num = ssn & (txq->q.n_bd - 1); | ||
1320 | int freed = 0; | ||
1321 | u8 agg_state; | ||
1322 | bool cond; | ||
1323 | |||
1324 | txq->time_stamp = jiffies; | ||
1325 | |||
1326 | if (txq->sched_retry) { | ||
1327 | agg_state = | ||
1328 | trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state; | ||
1329 | cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); | ||
1330 | } else { | ||
1331 | cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); | ||
1332 | } | ||
1333 | |||
1334 | if (txq->q.read_ptr != tfd_num) { | ||
1335 | IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim " | ||
1336 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
1337 | ssn , tfd_num, txq_id, txq->swq_id); | ||
1338 | freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); | ||
1339 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) | ||
1340 | iwl_wake_queue(trans, txq); | ||
1341 | } | ||
1342 | |||
1343 | iwl_free_tfds_in_queue(trans, sta_id, tid, freed); | ||
1344 | iwlagn_txq_check_empty(trans, sta_id, tid, txq_id); | ||
1345 | } | ||
1346 | |||
1347 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | ||
1348 | { | ||
1349 | iwl_trans_pcie_tx_free(trans); | ||
1350 | iwl_trans_pcie_rx_free(trans); | ||
1351 | free_irq(bus(trans)->irq, trans); | ||
1352 | iwl_free_isr_ict(trans); | ||
1353 | trans->shrd->trans = NULL; | ||
1354 | kfree(trans); | ||
1355 | } | ||
1356 | |||
1357 | #ifdef CONFIG_PM | ||
1358 | |||
1359 | static int iwl_trans_pcie_suspend(struct iwl_trans *trans) | ||
1360 | { | ||
1361 | /* | ||
1362 | * This function is called when system goes into suspend state | ||
1363 | * mac80211 will call iwl_mac_stop() from the mac80211 suspend function | ||
1364 | * first but since iwl_mac_stop() has no knowledge of who the caller is, | ||
1365 | * it will not call apm_ops.stop() to stop the DMA operation. | ||
1366 | * Calling apm_ops.stop here to make sure we stop the DMA. | ||
1367 | * | ||
1368 | * But of course ... if we have configured WoWLAN then we did other | ||
1369 | * things already :-) | ||
1370 | */ | ||
1371 | if (!trans->shrd->wowlan) | ||
1372 | iwl_apm_stop(priv(trans)); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | static int iwl_trans_pcie_resume(struct iwl_trans *trans) | ||
1378 | { | ||
1379 | bool hw_rfkill = false; | ||
1380 | |||
1381 | iwl_enable_interrupts(trans); | ||
1382 | |||
1383 | if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & | ||
1384 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | ||
1385 | hw_rfkill = true; | ||
1386 | |||
1387 | if (hw_rfkill) | ||
1388 | set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
1389 | else | ||
1390 | clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
1391 | |||
1392 | iwl_set_hw_rfkill_state(priv(trans), hw_rfkill); | ||
1393 | |||
1394 | return 0; | ||
1395 | } | ||
1396 | #else /* CONFIG_PM */ | ||
1397 | static int iwl_trans_pcie_suspend(struct iwl_trans *trans) | ||
1398 | { return 0; } | ||
1399 | |||
1400 | static int iwl_trans_pcie_resume(struct iwl_trans *trans) | ||
1401 | { return 0; } | ||
1402 | |||
1403 | #endif /* CONFIG_PM */ | ||
1404 | |||
1405 | static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, | ||
1406 | u8 ctx) | ||
1407 | { | ||
1408 | u8 ac, txq_id; | ||
1409 | struct iwl_trans_pcie *trans_pcie = | ||
1410 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1411 | |||
1412 | for (ac = 0; ac < AC_NUM; ac++) { | ||
1413 | txq_id = trans_pcie->ac_to_queue[ctx][ac]; | ||
1414 | IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n", | ||
1415 | ac, | ||
1416 | (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0) | ||
1417 | ? "stopped" : "awake"); | ||
1418 | iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | const struct iwl_trans_ops trans_ops_pcie; | ||
1423 | |||
1424 | static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) | ||
1425 | { | ||
1426 | struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + | ||
1427 | sizeof(struct iwl_trans_pcie), | ||
1428 | GFP_KERNEL); | ||
1429 | if (iwl_trans) { | ||
1430 | struct iwl_trans_pcie *trans_pcie = | ||
1431 | IWL_TRANS_GET_PCIE_TRANS(iwl_trans); | ||
1432 | iwl_trans->ops = &trans_ops_pcie; | ||
1433 | iwl_trans->shrd = shrd; | ||
1434 | trans_pcie->trans = iwl_trans; | ||
1435 | spin_lock_init(&iwl_trans->hcmd_lock); | ||
1436 | } | ||
1437 | |||
1438 | return iwl_trans; | ||
1439 | } | ||
1440 | |||
1441 | static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id) | ||
1442 | { | ||
1443 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1444 | |||
1445 | iwl_stop_queue(trans, &trans_pcie->txq[txq_id]); | ||
1446 | } | ||
1447 | |||
1448 | #define IWL_FLUSH_WAIT_MS 2000 | ||
1449 | |||
1450 | static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) | ||
1451 | { | ||
1452 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1453 | struct iwl_tx_queue *txq; | ||
1454 | struct iwl_queue *q; | ||
1455 | int cnt; | ||
1456 | unsigned long now = jiffies; | ||
1457 | int ret = 0; | ||
1458 | |||
1459 | /* waiting for all the tx frames complete might take a while */ | ||
1460 | for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { | ||
1461 | if (cnt == trans->shrd->cmd_queue) | ||
1462 | continue; | ||
1463 | txq = &trans_pcie->txq[cnt]; | ||
1464 | q = &txq->q; | ||
1465 | while (q->read_ptr != q->write_ptr && !time_after(jiffies, | ||
1466 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) | ||
1467 | msleep(1); | ||
1468 | |||
1469 | if (q->read_ptr != q->write_ptr) { | ||
1470 | IWL_ERR(trans, "fail to flush all tx fifo queues\n"); | ||
1471 | ret = -ETIMEDOUT; | ||
1472 | break; | ||
1473 | } | ||
1474 | } | ||
1475 | return ret; | ||
1476 | } | ||
1477 | |||
1478 | /* | ||
1479 | * On every watchdog tick we check (latest) time stamp. If it does not | ||
1480 | * change during timeout period and queue is not empty we reset firmware. | ||
1481 | */ | ||
1482 | static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) | ||
1483 | { | ||
1484 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1485 | struct iwl_tx_queue *txq = &trans_pcie->txq[cnt]; | ||
1486 | struct iwl_queue *q = &txq->q; | ||
1487 | unsigned long timeout; | ||
1488 | |||
1489 | if (q->read_ptr == q->write_ptr) { | ||
1490 | txq->time_stamp = jiffies; | ||
1491 | return 0; | ||
1492 | } | ||
1493 | |||
1494 | timeout = txq->time_stamp + | ||
1495 | msecs_to_jiffies(hw_params(trans).wd_timeout); | ||
1496 | |||
1497 | if (time_after(jiffies, timeout)) { | ||
1498 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id, | ||
1499 | hw_params(trans).wd_timeout); | ||
1500 | IWL_ERR(trans, "Current read_ptr %d write_ptr %d\n", | ||
1501 | q->read_ptr, q->write_ptr); | ||
1502 | return 1; | ||
1503 | } | ||
1504 | |||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | static const char *get_fh_string(int cmd) | ||
1509 | { | ||
1510 | switch (cmd) { | ||
1511 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | ||
1512 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | ||
1513 | IWL_CMD(FH_RSCSR_CHNL0_WPTR); | ||
1514 | IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); | ||
1515 | IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); | ||
1516 | IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); | ||
1517 | IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); | ||
1518 | IWL_CMD(FH_TSSR_TX_STATUS_REG); | ||
1519 | IWL_CMD(FH_TSSR_TX_ERROR_REG); | ||
1520 | default: | ||
1521 | return "UNKNOWN"; | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1525 | int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) | ||
1526 | { | ||
1527 | int i; | ||
1528 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1529 | int pos = 0; | ||
1530 | size_t bufsz = 0; | ||
1531 | #endif | ||
1532 | static const u32 fh_tbl[] = { | ||
1533 | FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
1534 | FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
1535 | FH_RSCSR_CHNL0_WPTR, | ||
1536 | FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
1537 | FH_MEM_RSSR_SHARED_CTRL_REG, | ||
1538 | FH_MEM_RSSR_RX_STATUS_REG, | ||
1539 | FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, | ||
1540 | FH_TSSR_TX_STATUS_REG, | ||
1541 | FH_TSSR_TX_ERROR_REG | ||
1542 | }; | ||
1543 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1544 | if (display) { | ||
1545 | bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; | ||
1546 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1547 | if (!*buf) | ||
1548 | return -ENOMEM; | ||
1549 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1550 | "FH register values:\n"); | ||
1551 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
1552 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1553 | " %34s: 0X%08x\n", | ||
1554 | get_fh_string(fh_tbl[i]), | ||
1555 | iwl_read_direct32(bus(trans), fh_tbl[i])); | ||
1556 | } | ||
1557 | return pos; | ||
1558 | } | ||
1559 | #endif | ||
1560 | IWL_ERR(trans, "FH register values:\n"); | ||
1561 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
1562 | IWL_ERR(trans, " %34s: 0X%08x\n", | ||
1563 | get_fh_string(fh_tbl[i]), | ||
1564 | iwl_read_direct32(bus(trans), fh_tbl[i])); | ||
1565 | } | ||
1566 | return 0; | ||
1567 | } | ||
1568 | |||
1569 | static const char *get_csr_string(int cmd) | ||
1570 | { | ||
1571 | switch (cmd) { | ||
1572 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | ||
1573 | IWL_CMD(CSR_INT_COALESCING); | ||
1574 | IWL_CMD(CSR_INT); | ||
1575 | IWL_CMD(CSR_INT_MASK); | ||
1576 | IWL_CMD(CSR_FH_INT_STATUS); | ||
1577 | IWL_CMD(CSR_GPIO_IN); | ||
1578 | IWL_CMD(CSR_RESET); | ||
1579 | IWL_CMD(CSR_GP_CNTRL); | ||
1580 | IWL_CMD(CSR_HW_REV); | ||
1581 | IWL_CMD(CSR_EEPROM_REG); | ||
1582 | IWL_CMD(CSR_EEPROM_GP); | ||
1583 | IWL_CMD(CSR_OTP_GP_REG); | ||
1584 | IWL_CMD(CSR_GIO_REG); | ||
1585 | IWL_CMD(CSR_GP_UCODE_REG); | ||
1586 | IWL_CMD(CSR_GP_DRIVER_REG); | ||
1587 | IWL_CMD(CSR_UCODE_DRV_GP1); | ||
1588 | IWL_CMD(CSR_UCODE_DRV_GP2); | ||
1589 | IWL_CMD(CSR_LED_REG); | ||
1590 | IWL_CMD(CSR_DRAM_INT_TBL_REG); | ||
1591 | IWL_CMD(CSR_GIO_CHICKEN_BITS); | ||
1592 | IWL_CMD(CSR_ANA_PLL_CFG); | ||
1593 | IWL_CMD(CSR_HW_REV_WA_REG); | ||
1594 | IWL_CMD(CSR_DBG_HPET_MEM_REG); | ||
1595 | default: | ||
1596 | return "UNKNOWN"; | ||
1597 | } | ||
1598 | } | ||
1599 | |||
1600 | void iwl_dump_csr(struct iwl_trans *trans) | ||
1601 | { | ||
1602 | int i; | ||
1603 | static const u32 csr_tbl[] = { | ||
1604 | CSR_HW_IF_CONFIG_REG, | ||
1605 | CSR_INT_COALESCING, | ||
1606 | CSR_INT, | ||
1607 | CSR_INT_MASK, | ||
1608 | CSR_FH_INT_STATUS, | ||
1609 | CSR_GPIO_IN, | ||
1610 | CSR_RESET, | ||
1611 | CSR_GP_CNTRL, | ||
1612 | CSR_HW_REV, | ||
1613 | CSR_EEPROM_REG, | ||
1614 | CSR_EEPROM_GP, | ||
1615 | CSR_OTP_GP_REG, | ||
1616 | CSR_GIO_REG, | ||
1617 | CSR_GP_UCODE_REG, | ||
1618 | CSR_GP_DRIVER_REG, | ||
1619 | CSR_UCODE_DRV_GP1, | ||
1620 | CSR_UCODE_DRV_GP2, | ||
1621 | CSR_LED_REG, | ||
1622 | CSR_DRAM_INT_TBL_REG, | ||
1623 | CSR_GIO_CHICKEN_BITS, | ||
1624 | CSR_ANA_PLL_CFG, | ||
1625 | CSR_HW_REV_WA_REG, | ||
1626 | CSR_DBG_HPET_MEM_REG | ||
1627 | }; | 74 | }; |
1628 | IWL_ERR(trans, "CSR values:\n"); | ||
1629 | IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is " | ||
1630 | "CSR_INT_PERIODIC_REG)\n"); | ||
1631 | for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { | ||
1632 | IWL_ERR(trans, " %25s: 0X%08x\n", | ||
1633 | get_csr_string(csr_tbl[i]), | ||
1634 | iwl_read32(bus(trans), csr_tbl[i])); | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1638 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1639 | /* create and remove of files */ | ||
1640 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | ||
1641 | if (!debugfs_create_file(#name, mode, parent, trans, \ | ||
1642 | &iwl_dbgfs_##name##_ops)) \ | ||
1643 | return -ENOMEM; \ | ||
1644 | } while (0) | ||
1645 | |||
1646 | /* file operation */ | ||
1647 | #define DEBUGFS_READ_FUNC(name) \ | ||
1648 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | ||
1649 | char __user *user_buf, \ | ||
1650 | size_t count, loff_t *ppos); | ||
1651 | |||
1652 | #define DEBUGFS_WRITE_FUNC(name) \ | ||
1653 | static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ | ||
1654 | const char __user *user_buf, \ | ||
1655 | size_t count, loff_t *ppos); | ||
1656 | |||
1657 | |||
1658 | static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) | ||
1659 | { | ||
1660 | file->private_data = inode->i_private; | ||
1661 | return 0; | ||
1662 | } | ||
1663 | |||
1664 | #define DEBUGFS_READ_FILE_OPS(name) \ | ||
1665 | DEBUGFS_READ_FUNC(name); \ | ||
1666 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1667 | .read = iwl_dbgfs_##name##_read, \ | ||
1668 | .open = iwl_dbgfs_open_file_generic, \ | ||
1669 | .llseek = generic_file_llseek, \ | ||
1670 | }; | ||
1671 | 75 | ||
1672 | #define DEBUGFS_WRITE_FILE_OPS(name) \ | 76 | return iwl_trans_send_cmd(trans, &cmd); |
1673 | DEBUGFS_WRITE_FUNC(name); \ | ||
1674 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1675 | .write = iwl_dbgfs_##name##_write, \ | ||
1676 | .open = iwl_dbgfs_open_file_generic, \ | ||
1677 | .llseek = generic_file_llseek, \ | ||
1678 | }; | ||
1679 | |||
1680 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ | ||
1681 | DEBUGFS_READ_FUNC(name); \ | ||
1682 | DEBUGFS_WRITE_FUNC(name); \ | ||
1683 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1684 | .write = iwl_dbgfs_##name##_write, \ | ||
1685 | .read = iwl_dbgfs_##name##_read, \ | ||
1686 | .open = iwl_dbgfs_open_file_generic, \ | ||
1687 | .llseek = generic_file_llseek, \ | ||
1688 | }; | ||
1689 | |||
1690 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | ||
1691 | char __user *user_buf, | ||
1692 | size_t count, loff_t *ppos) | ||
1693 | { | ||
1694 | struct iwl_trans *trans = file->private_data; | ||
1695 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1696 | struct iwl_tx_queue *txq; | ||
1697 | struct iwl_queue *q; | ||
1698 | char *buf; | ||
1699 | int pos = 0; | ||
1700 | int cnt; | ||
1701 | int ret; | ||
1702 | const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; | ||
1703 | |||
1704 | if (!trans_pcie->txq) { | ||
1705 | IWL_ERR(trans, "txq not ready\n"); | ||
1706 | return -EAGAIN; | ||
1707 | } | ||
1708 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1709 | if (!buf) | ||
1710 | return -ENOMEM; | ||
1711 | |||
1712 | for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { | ||
1713 | txq = &trans_pcie->txq[cnt]; | ||
1714 | q = &txq->q; | ||
1715 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1716 | "hwq %.2d: read=%u write=%u stop=%d" | ||
1717 | " swq_id=%#.2x (ac %d/hwq %d)\n", | ||
1718 | cnt, q->read_ptr, q->write_ptr, | ||
1719 | !!test_bit(cnt, trans_pcie->queue_stopped), | ||
1720 | txq->swq_id, txq->swq_id & 3, | ||
1721 | (txq->swq_id >> 2) & 0x1f); | ||
1722 | if (cnt >= 4) | ||
1723 | continue; | ||
1724 | /* for the ACs, display the stop count too */ | ||
1725 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1726 | " stop-count: %d\n", | ||
1727 | atomic_read(&trans_pcie->queue_stop_count[cnt])); | ||
1728 | } | ||
1729 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1730 | kfree(buf); | ||
1731 | return ret; | ||
1732 | } | 77 | } |
1733 | |||
1734 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | ||
1735 | char __user *user_buf, | ||
1736 | size_t count, loff_t *ppos) { | ||
1737 | struct iwl_trans *trans = file->private_data; | ||
1738 | struct iwl_trans_pcie *trans_pcie = | ||
1739 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1740 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | ||
1741 | char buf[256]; | ||
1742 | int pos = 0; | ||
1743 | const size_t bufsz = sizeof(buf); | ||
1744 | |||
1745 | pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", | ||
1746 | rxq->read); | ||
1747 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | ||
1748 | rxq->write); | ||
1749 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | ||
1750 | rxq->free_count); | ||
1751 | if (rxq->rb_stts) { | ||
1752 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | ||
1753 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); | ||
1754 | } else { | ||
1755 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1756 | "closed_rb_num: Not Allocated\n"); | ||
1757 | } | ||
1758 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1759 | } | ||
1760 | |||
1761 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | ||
1762 | char __user *user_buf, | ||
1763 | size_t count, loff_t *ppos) | ||
1764 | { | ||
1765 | struct iwl_trans *trans = file->private_data; | ||
1766 | char *buf; | ||
1767 | int pos = 0; | ||
1768 | ssize_t ret = -ENOMEM; | ||
1769 | |||
1770 | ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true); | ||
1771 | if (buf) { | ||
1772 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1773 | kfree(buf); | ||
1774 | } | ||
1775 | return ret; | ||
1776 | } | ||
1777 | |||
1778 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | ||
1779 | const char __user *user_buf, | ||
1780 | size_t count, loff_t *ppos) | ||
1781 | { | ||
1782 | struct iwl_trans *trans = file->private_data; | ||
1783 | u32 event_log_flag; | ||
1784 | char buf[8]; | ||
1785 | int buf_size; | ||
1786 | |||
1787 | memset(buf, 0, sizeof(buf)); | ||
1788 | buf_size = min(count, sizeof(buf) - 1); | ||
1789 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1790 | return -EFAULT; | ||
1791 | if (sscanf(buf, "%d", &event_log_flag) != 1) | ||
1792 | return -EFAULT; | ||
1793 | if (event_log_flag == 1) | ||
1794 | iwl_dump_nic_event_log(trans, true, NULL, false); | ||
1795 | |||
1796 | return count; | ||
1797 | } | ||
1798 | |||
1799 | static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | ||
1800 | char __user *user_buf, | ||
1801 | size_t count, loff_t *ppos) { | ||
1802 | |||
1803 | struct iwl_trans *trans = file->private_data; | ||
1804 | struct iwl_trans_pcie *trans_pcie = | ||
1805 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1806 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | ||
1807 | |||
1808 | int pos = 0; | ||
1809 | char *buf; | ||
1810 | int bufsz = 24 * 64; /* 24 items * 64 char per item */ | ||
1811 | ssize_t ret; | ||
1812 | |||
1813 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1814 | if (!buf) { | ||
1815 | IWL_ERR(trans, "Can not allocate Buffer\n"); | ||
1816 | return -ENOMEM; | ||
1817 | } | ||
1818 | |||
1819 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1820 | "Interrupt Statistics Report:\n"); | ||
1821 | |||
1822 | pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", | ||
1823 | isr_stats->hw); | ||
1824 | pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", | ||
1825 | isr_stats->sw); | ||
1826 | if (isr_stats->sw || isr_stats->hw) { | ||
1827 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1828 | "\tLast Restarting Code: 0x%X\n", | ||
1829 | isr_stats->err_code); | ||
1830 | } | ||
1831 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1832 | pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", | ||
1833 | isr_stats->sch); | ||
1834 | pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", | ||
1835 | isr_stats->alive); | ||
1836 | #endif | ||
1837 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1838 | "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill); | ||
1839 | |||
1840 | pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", | ||
1841 | isr_stats->ctkill); | ||
1842 | |||
1843 | pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", | ||
1844 | isr_stats->wakeup); | ||
1845 | |||
1846 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1847 | "Rx command responses:\t\t %u\n", isr_stats->rx); | ||
1848 | |||
1849 | pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", | ||
1850 | isr_stats->tx); | ||
1851 | |||
1852 | pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", | ||
1853 | isr_stats->unhandled); | ||
1854 | |||
1855 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1856 | kfree(buf); | ||
1857 | return ret; | ||
1858 | } | ||
1859 | |||
1860 | static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | ||
1861 | const char __user *user_buf, | ||
1862 | size_t count, loff_t *ppos) | ||
1863 | { | ||
1864 | struct iwl_trans *trans = file->private_data; | ||
1865 | struct iwl_trans_pcie *trans_pcie = | ||
1866 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1867 | struct isr_statistics *isr_stats = &trans_pcie->isr_stats; | ||
1868 | |||
1869 | char buf[8]; | ||
1870 | int buf_size; | ||
1871 | u32 reset_flag; | ||
1872 | |||
1873 | memset(buf, 0, sizeof(buf)); | ||
1874 | buf_size = min(count, sizeof(buf) - 1); | ||
1875 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1876 | return -EFAULT; | ||
1877 | if (sscanf(buf, "%x", &reset_flag) != 1) | ||
1878 | return -EFAULT; | ||
1879 | if (reset_flag == 0) | ||
1880 | memset(isr_stats, 0, sizeof(*isr_stats)); | ||
1881 | |||
1882 | return count; | ||
1883 | } | ||
1884 | |||
1885 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | ||
1886 | const char __user *user_buf, | ||
1887 | size_t count, loff_t *ppos) | ||
1888 | { | ||
1889 | struct iwl_trans *trans = file->private_data; | ||
1890 | char buf[8]; | ||
1891 | int buf_size; | ||
1892 | int csr; | ||
1893 | |||
1894 | memset(buf, 0, sizeof(buf)); | ||
1895 | buf_size = min(count, sizeof(buf) - 1); | ||
1896 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1897 | return -EFAULT; | ||
1898 | if (sscanf(buf, "%d", &csr) != 1) | ||
1899 | return -EFAULT; | ||
1900 | |||
1901 | iwl_dump_csr(trans); | ||
1902 | |||
1903 | return count; | ||
1904 | } | ||
1905 | |||
1906 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | ||
1907 | char __user *user_buf, | ||
1908 | size_t count, loff_t *ppos) | ||
1909 | { | ||
1910 | struct iwl_trans *trans = file->private_data; | ||
1911 | char *buf; | ||
1912 | int pos = 0; | ||
1913 | ssize_t ret = -EFAULT; | ||
1914 | |||
1915 | ret = pos = iwl_dump_fh(trans, &buf, true); | ||
1916 | if (buf) { | ||
1917 | ret = simple_read_from_buffer(user_buf, | ||
1918 | count, ppos, buf, pos); | ||
1919 | kfree(buf); | ||
1920 | } | ||
1921 | |||
1922 | return ret; | ||
1923 | } | ||
1924 | |||
1925 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | ||
1926 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | ||
1927 | DEBUGFS_READ_FILE_OPS(fh_reg); | ||
1928 | DEBUGFS_READ_FILE_OPS(rx_queue); | ||
1929 | DEBUGFS_READ_FILE_OPS(tx_queue); | ||
1930 | DEBUGFS_WRITE_FILE_OPS(csr); | ||
1931 | |||
1932 | /* | ||
1933 | * Create the debugfs files and directories | ||
1934 | * | ||
1935 | */ | ||
1936 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
1937 | struct dentry *dir) | ||
1938 | { | ||
1939 | DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); | ||
1940 | DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); | ||
1941 | DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); | ||
1942 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); | ||
1943 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); | ||
1944 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); | ||
1945 | return 0; | ||
1946 | } | ||
1947 | #else | ||
1948 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
1949 | struct dentry *dir) | ||
1950 | { return 0; } | ||
1951 | |||
1952 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ | ||
1953 | |||
1954 | const struct iwl_trans_ops trans_ops_pcie = { | ||
1955 | .alloc = iwl_trans_pcie_alloc, | ||
1956 | .request_irq = iwl_trans_pcie_request_irq, | ||
1957 | .start_device = iwl_trans_pcie_start_device, | ||
1958 | .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, | ||
1959 | .stop_device = iwl_trans_pcie_stop_device, | ||
1960 | |||
1961 | .tx_start = iwl_trans_pcie_tx_start, | ||
1962 | .wake_any_queue = iwl_trans_pcie_wake_any_queue, | ||
1963 | |||
1964 | .send_cmd = iwl_trans_pcie_send_cmd, | ||
1965 | .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, | ||
1966 | |||
1967 | .tx = iwl_trans_pcie_tx, | ||
1968 | .reclaim = iwl_trans_pcie_reclaim, | ||
1969 | |||
1970 | .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, | ||
1971 | .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, | ||
1972 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, | ||
1973 | |||
1974 | .kick_nic = iwl_trans_pcie_kick_nic, | ||
1975 | |||
1976 | .free = iwl_trans_pcie_free, | ||
1977 | .stop_queue = iwl_trans_pcie_stop_queue, | ||
1978 | |||
1979 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | ||
1980 | |||
1981 | .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, | ||
1982 | .check_stuck_queue = iwl_trans_pcie_check_stuck_queue, | ||
1983 | |||
1984 | .suspend = iwl_trans_pcie_suspend, | ||
1985 | .resume = iwl_trans_pcie_resume, | ||
1986 | }; | ||
1987 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 71a6fb05356a..c5923125c3f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -97,15 +97,7 @@ enum { | |||
97 | */ | 97 | */ |
98 | struct iwl_device_cmd { | 98 | struct iwl_device_cmd { |
99 | struct iwl_cmd_header hdr; /* uCode API */ | 99 | struct iwl_cmd_header hdr; /* uCode API */ |
100 | union { | 100 | u8 payload[DEF_CMD_PAYLOAD_SIZE]; |
101 | u32 flags; | ||
102 | u8 val8; | ||
103 | u16 val16; | ||
104 | u32 val32; | ||
105 | struct iwl_tx_cmd tx; | ||
106 | struct iwl6000_channel_switch_cmd chswitch; | ||
107 | u8 payload[DEF_CMD_PAYLOAD_SIZE]; | ||
108 | } __packed cmd; | ||
109 | } __packed; | 101 | } __packed; |
110 | 102 | ||
111 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) | 103 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) |
@@ -120,6 +112,8 @@ enum iwl_hcmd_dataflag { | |||
120 | * struct iwl_host_cmd - Host command to the uCode | 112 | * struct iwl_host_cmd - Host command to the uCode |
121 | * @data: array of chunks that composes the data of the host command | 113 | * @data: array of chunks that composes the data of the host command |
122 | * @reply_page: pointer to the page that holds the response to the host command | 114 | * @reply_page: pointer to the page that holds the response to the host command |
115 | * @handler_status: return value of the handler of the command | ||
116 | * (put in setup_rx_handlers) - valid for SYNC mode only | ||
123 | * @callback: | 117 | * @callback: |
124 | * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC | 118 | * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC |
125 | * @len: array of the lenths of the chunks in data | 119 | * @len: array of the lenths of the chunks in data |
@@ -129,9 +123,8 @@ enum iwl_hcmd_dataflag { | |||
129 | struct iwl_host_cmd { | 123 | struct iwl_host_cmd { |
130 | const void *data[IWL_MAX_CMD_TFDS]; | 124 | const void *data[IWL_MAX_CMD_TFDS]; |
131 | unsigned long reply_page; | 125 | unsigned long reply_page; |
132 | void (*callback)(struct iwl_shared *shrd, | 126 | int handler_status; |
133 | struct iwl_device_cmd *cmd, | 127 | |
134 | struct iwl_rx_packet *pkt); | ||
135 | u32 flags; | 128 | u32 flags; |
136 | u16 len[IWL_MAX_CMD_TFDS]; | 129 | u16 len[IWL_MAX_CMD_TFDS]; |
137 | u8 dataflags[IWL_MAX_CMD_TFDS]; | 130 | u8 dataflags[IWL_MAX_CMD_TFDS]; |
@@ -151,7 +144,6 @@ struct iwl_host_cmd { | |||
151 | * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* | 144 | * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* |
152 | * @stop_device:stops the whole device (embedded CPU put to reset) | 145 | * @stop_device:stops the whole device (embedded CPU put to reset) |
153 | * @send_cmd:send a host command | 146 | * @send_cmd:send a host command |
154 | * @send_cmd_pdu:send a host command: flags can be CMD_* | ||
155 | * @tx: send an skb | 147 | * @tx: send an skb |
156 | * @reclaim: free packet until ssn. Returns a list of freed packets. | 148 | * @reclaim: free packet until ssn. Returns a list of freed packets. |
157 | * @tx_agg_alloc: allocate resources for a TX BA session | 149 | * @tx_agg_alloc: allocate resources for a TX BA session |
@@ -178,14 +170,14 @@ struct iwl_trans_ops { | |||
178 | void (*stop_device)(struct iwl_trans *trans); | 170 | void (*stop_device)(struct iwl_trans *trans); |
179 | void (*tx_start)(struct iwl_trans *trans); | 171 | void (*tx_start)(struct iwl_trans *trans); |
180 | 172 | ||
181 | void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx); | 173 | void (*wake_any_queue)(struct iwl_trans *trans, |
174 | enum iwl_rxon_context_id ctx); | ||
182 | 175 | ||
183 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | 176 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
184 | 177 | ||
185 | int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, | ||
186 | const void *data); | ||
187 | int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, | 178 | int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, |
188 | struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); | 179 | struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, |
180 | u8 sta_id); | ||
189 | void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid, | 181 | void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid, |
190 | int txq_id, int ssn, u32 status, | 182 | int txq_id, int ssn, u32 status, |
191 | struct sk_buff_head *skbs); | 183 | struct sk_buff_head *skbs); |
@@ -209,9 +201,10 @@ struct iwl_trans_ops { | |||
209 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 201 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
210 | int (*check_stuck_queue)(struct iwl_trans *trans, int q); | 202 | int (*check_stuck_queue)(struct iwl_trans *trans, int q); |
211 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); | 203 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); |
212 | 204 | #ifdef CONFIG_PM_SLEEP | |
213 | int (*suspend)(struct iwl_trans *trans); | 205 | int (*suspend)(struct iwl_trans *trans); |
214 | int (*resume)(struct iwl_trans *trans); | 206 | int (*resume)(struct iwl_trans *trans); |
207 | #endif | ||
215 | }; | 208 | }; |
216 | 209 | ||
217 | /** | 210 | /** |
@@ -255,7 +248,8 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans) | |||
255 | trans->ops->tx_start(trans); | 248 | trans->ops->tx_start(trans); |
256 | } | 249 | } |
257 | 250 | ||
258 | static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx) | 251 | static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, |
252 | enum iwl_rxon_context_id ctx) | ||
259 | { | 253 | { |
260 | trans->ops->wake_any_queue(trans, ctx); | 254 | trans->ops->wake_any_queue(trans, ctx); |
261 | } | 255 | } |
@@ -267,14 +261,12 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
267 | return trans->ops->send_cmd(trans, cmd); | 261 | return trans->ops->send_cmd(trans, cmd); |
268 | } | 262 | } |
269 | 263 | ||
270 | static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, | 264 | int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, |
271 | u32 flags, u16 len, const void *data) | 265 | u32 flags, u16 len, const void *data); |
272 | { | ||
273 | return trans->ops->send_cmd_pdu(trans, id, flags, len, data); | ||
274 | } | ||
275 | 266 | ||
276 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 267 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
277 | struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) | 268 | struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, |
269 | u8 sta_id) | ||
278 | { | 270 | { |
279 | return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); | 271 | return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); |
280 | } | 272 | } |
@@ -339,6 +331,7 @@ static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | |||
339 | return trans->ops->dbgfs_register(trans, dir); | 331 | return trans->ops->dbgfs_register(trans, dir); |
340 | } | 332 | } |
341 | 333 | ||
334 | #ifdef CONFIG_PM_SLEEP | ||
342 | static inline int iwl_trans_suspend(struct iwl_trans *trans) | 335 | static inline int iwl_trans_suspend(struct iwl_trans *trans) |
343 | { | 336 | { |
344 | return trans->ops->suspend(trans); | 337 | return trans->ops->suspend(trans); |
@@ -348,6 +341,7 @@ static inline int iwl_trans_resume(struct iwl_trans *trans) | |||
348 | { | 341 | { |
349 | return trans->ops->resume(trans); | 342 | return trans->ops->resume(trans); |
350 | } | 343 | } |
344 | #endif | ||
351 | 345 | ||
352 | /***************************************************** | 346 | /***************************************************** |
353 | * Transport layers implementations | 347 | * Transport layers implementations |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 85b3169c40d7..610bfcee3cf6 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -695,7 +695,7 @@ static void lbs_scan_worker(struct work_struct *work) | |||
695 | tlv = scan_cmd->tlvbuffer; | 695 | tlv = scan_cmd->tlvbuffer; |
696 | 696 | ||
697 | /* add SSID TLV */ | 697 | /* add SSID TLV */ |
698 | if (priv->scan_req->n_ssids) | 698 | if (priv->scan_req->n_ssids && priv->scan_req->ssids[0].ssid_len > 0) |
699 | tlv += lbs_add_ssid_tlv(tlv, | 699 | tlv += lbs_add_ssid_tlv(tlv, |
700 | priv->scan_req->ssids[0].ssid, | 700 | priv->scan_req->ssids[0].ssid, |
701 | priv->scan_req->ssids[0].ssid_len); | 701 | priv->scan_req->ssids[0].ssid_len); |
@@ -736,7 +736,6 @@ static void lbs_scan_worker(struct work_struct *work) | |||
736 | cfg80211_scan_done(priv->scan_req, false); | 736 | cfg80211_scan_done(priv->scan_req, false); |
737 | 737 | ||
738 | priv->scan_req = NULL; | 738 | priv->scan_req = NULL; |
739 | priv->last_scan = jiffies; | ||
740 | } | 739 | } |
741 | 740 | ||
742 | /* Restart network */ | 741 | /* Restart network */ |
@@ -1302,24 +1301,26 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1302 | lbs_deb_enter(LBS_DEB_CFG80211); | 1301 | lbs_deb_enter(LBS_DEB_CFG80211); |
1303 | 1302 | ||
1304 | if (!sme->bssid) { | 1303 | if (!sme->bssid) { |
1305 | /* Run a scan if one isn't in-progress already and if the last | 1304 | struct cfg80211_scan_request *creq; |
1306 | * scan was done more than 2 seconds ago. | ||
1307 | */ | ||
1308 | if (priv->scan_req == NULL && | ||
1309 | time_after(jiffies, priv->last_scan + (2 * HZ))) { | ||
1310 | struct cfg80211_scan_request *creq; | ||
1311 | 1305 | ||
1312 | creq = _new_connect_scan_req(wiphy, sme); | 1306 | /* |
1313 | if (!creq) { | 1307 | * Scan for the requested network after waiting for existing |
1314 | ret = -EINVAL; | 1308 | * scans to finish. |
1315 | goto done; | 1309 | */ |
1316 | } | 1310 | lbs_deb_assoc("assoc: waiting for existing scans\n"); |
1311 | wait_event_interruptible_timeout(priv->scan_q, | ||
1312 | (priv->scan_req == NULL), | ||
1313 | (15 * HZ)); | ||
1317 | 1314 | ||
1318 | lbs_deb_assoc("assoc: scanning for compatible AP\n"); | 1315 | creq = _new_connect_scan_req(wiphy, sme); |
1319 | _internal_start_scan(priv, true, creq); | 1316 | if (!creq) { |
1317 | ret = -EINVAL; | ||
1318 | goto done; | ||
1320 | } | 1319 | } |
1321 | 1320 | ||
1322 | /* Wait for any in-progress scan to complete */ | 1321 | lbs_deb_assoc("assoc: scanning for compatible AP\n"); |
1322 | _internal_start_scan(priv, true, creq); | ||
1323 | |||
1323 | lbs_deb_assoc("assoc: waiting for scan to complete\n"); | 1324 | lbs_deb_assoc("assoc: waiting for scan to complete\n"); |
1324 | wait_event_interruptible_timeout(priv->scan_q, | 1325 | wait_event_interruptible_timeout(priv->scan_q, |
1325 | (priv->scan_req == NULL), | 1326 | (priv->scan_req == NULL), |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index b9ff0dc53e8d..fb3e40bf5902 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -179,7 +179,6 @@ struct lbs_private { | |||
179 | wait_queue_head_t scan_q; | 179 | wait_queue_head_t scan_q; |
180 | /* Whether the scan was initiated internally and not by cfg80211 */ | 180 | /* Whether the scan was initiated internally and not by cfg80211 */ |
181 | bool internal_scan; | 181 | bool internal_scan; |
182 | unsigned long last_scan; | ||
183 | }; | 182 | }; |
184 | 183 | ||
185 | extern struct cmd_confirm_sleep confirm_sleep; | 184 | extern struct cmd_confirm_sleep confirm_sleep; |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6fd53e4e3fe6..0ddcdca63cf7 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -768,6 +768,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
768 | struct mwifiex_bss_info bss_info; | 768 | struct mwifiex_bss_info bss_info; |
769 | int ie_len; | 769 | int ie_len; |
770 | u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; | 770 | u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; |
771 | enum ieee80211_band band; | ||
771 | 772 | ||
772 | if (mwifiex_get_bss_info(priv, &bss_info)) | 773 | if (mwifiex_get_bss_info(priv, &bss_info)) |
773 | return -1; | 774 | return -1; |
@@ -780,9 +781,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
780 | bss_info.ssid.ssid_len); | 781 | bss_info.ssid.ssid_len); |
781 | ie_len = ie_buf[1] + sizeof(struct ieee_types_header); | 782 | ie_len = ie_buf[1] + sizeof(struct ieee_types_header); |
782 | 783 | ||
784 | band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | ||
783 | chan = __ieee80211_get_channel(priv->wdev->wiphy, | 785 | chan = __ieee80211_get_channel(priv->wdev->wiphy, |
784 | ieee80211_channel_to_frequency(bss_info.bss_chan, | 786 | ieee80211_channel_to_frequency(bss_info.bss_chan, |
785 | priv->curr_bss_params.band)); | 787 | band)); |
786 | 788 | ||
787 | cfg80211_inform_bss(priv->wdev->wiphy, chan, | 789 | cfg80211_inform_bss(priv->wdev->wiphy, chan, |
788 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, | 790 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, |
@@ -1219,6 +1221,9 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, | |||
1219 | /* We are using custom domains */ | 1221 | /* We are using custom domains */ |
1220 | wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | 1222 | wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
1221 | 1223 | ||
1224 | /* Reserve space for bss band information */ | ||
1225 | wdev->wiphy->bss_priv_size = sizeof(u8); | ||
1226 | |||
1222 | wdev->wiphy->reg_notifier = mwifiex_reg_notifier; | 1227 | wdev->wiphy->reg_notifier = mwifiex_reg_notifier; |
1223 | 1228 | ||
1224 | /* Set struct mwifiex_private pointer in wiphy_priv */ | 1229 | /* Set struct mwifiex_private pointer in wiphy_priv */ |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index b5352afb8714..d12e25d0c880 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -90,6 +90,9 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, | |||
90 | cmd_node->data_buf = NULL; | 90 | cmd_node->data_buf = NULL; |
91 | cmd_node->wait_q_enabled = false; | 91 | cmd_node->wait_q_enabled = false; |
92 | 92 | ||
93 | if (cmd_node->cmd_skb) | ||
94 | skb_trim(cmd_node->cmd_skb, 0); | ||
95 | |||
93 | if (cmd_node->resp_skb) { | 96 | if (cmd_node->resp_skb) { |
94 | dev_kfree_skb_any(cmd_node->resp_skb); | 97 | dev_kfree_skb_any(cmd_node->resp_skb); |
95 | cmd_node->resp_skb = NULL; | 98 | cmd_node->resp_skb = NULL; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index e6b6c0cfb63e..1e801328a558 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -958,7 +958,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *, | |||
958 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | 958 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, |
959 | u8 *bssid, s32 rssi, u8 *ie_buf, | 959 | u8 *bssid, s32 rssi, u8 *ie_buf, |
960 | size_t ie_len, u16 beacon_period, | 960 | size_t ie_len, u16 beacon_period, |
961 | u16 cap_info_bitmap, | 961 | u16 cap_info_bitmap, u8 band, |
962 | struct mwifiex_bssdescriptor *bss_desc); | 962 | struct mwifiex_bssdescriptor *bss_desc); |
963 | int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | 963 | int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, |
964 | struct mwifiex_bssdescriptor *bss_entry, | 964 | struct mwifiex_bssdescriptor *bss_entry, |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 8d8588db1cd9..ca3761965e85 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -532,7 +532,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | |||
532 | 532 | ||
533 | sband = priv->wdev->wiphy->bands[band]; | 533 | sband = priv->wdev->wiphy->bands[band]; |
534 | 534 | ||
535 | for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) { | 535 | for (i = 0; (i < sband->n_channels) ; i++) { |
536 | ch = &sband->channels[i]; | 536 | ch = &sband->channels[i]; |
537 | if (ch->flags & IEEE80211_CHAN_DISABLED) | 537 | if (ch->flags & IEEE80211_CHAN_DISABLED) |
538 | continue; | 538 | continue; |
@@ -563,6 +563,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | |||
563 | scan_chan_list[chan_idx].chan_scan_mode_bitmap | 563 | scan_chan_list[chan_idx].chan_scan_mode_bitmap |
564 | |= MWIFIEX_DISABLE_CHAN_FILT; | 564 | |= MWIFIEX_DISABLE_CHAN_FILT; |
565 | } | 565 | } |
566 | chan_idx++; | ||
566 | } | 567 | } |
567 | 568 | ||
568 | } | 569 | } |
@@ -1463,9 +1464,9 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv, | |||
1463 | } | 1464 | } |
1464 | 1465 | ||
1465 | static int | 1466 | static int |
1466 | mwifiex_update_curr_bss_params(struct mwifiex_private *priv, | 1467 | mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, |
1467 | u8 *bssid, s32 rssi, const u8 *ie_buf, | 1468 | s32 rssi, const u8 *ie_buf, size_t ie_len, |
1468 | size_t ie_len, u16 beacon_period, u16 cap_info_bitmap) | 1469 | u16 beacon_period, u16 cap_info_bitmap, u8 band) |
1469 | { | 1470 | { |
1470 | struct mwifiex_bssdescriptor *bss_desc = NULL; | 1471 | struct mwifiex_bssdescriptor *bss_desc = NULL; |
1471 | int ret; | 1472 | int ret; |
@@ -1488,7 +1489,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, | |||
1488 | 1489 | ||
1489 | ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie, | 1490 | ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie, |
1490 | ie_len, beacon_period, | 1491 | ie_len, beacon_period, |
1491 | cap_info_bitmap, bss_desc); | 1492 | cap_info_bitmap, band, bss_desc); |
1492 | if (ret) | 1493 | if (ret) |
1493 | goto done; | 1494 | goto done; |
1494 | 1495 | ||
@@ -1532,6 +1533,11 @@ done: | |||
1532 | return 0; | 1533 | return 0; |
1533 | } | 1534 | } |
1534 | 1535 | ||
1536 | static void mwifiex_free_bss_priv(struct cfg80211_bss *bss) | ||
1537 | { | ||
1538 | kfree(bss->priv); | ||
1539 | } | ||
1540 | |||
1535 | /* | 1541 | /* |
1536 | * This function handles the command response of scan. | 1542 | * This function handles the command response of scan. |
1537 | * | 1543 | * |
@@ -1570,6 +1576,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1570 | struct chan_band_param_set *chan_band; | 1576 | struct chan_band_param_set *chan_band; |
1571 | u8 is_bgscan_resp; | 1577 | u8 is_bgscan_resp; |
1572 | unsigned long flags; | 1578 | unsigned long flags; |
1579 | struct cfg80211_bss *bss; | ||
1573 | 1580 | ||
1574 | is_bgscan_resp = (le16_to_cpu(resp->command) | 1581 | is_bgscan_resp = (le16_to_cpu(resp->command) |
1575 | == HostCmd_CMD_802_11_BG_SCAN_QUERY); | 1582 | == HostCmd_CMD_802_11_BG_SCAN_QUERY); |
@@ -1751,10 +1758,12 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1751 | chan = ieee80211_get_channel(priv->wdev->wiphy, freq); | 1758 | chan = ieee80211_get_channel(priv->wdev->wiphy, freq); |
1752 | 1759 | ||
1753 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | 1760 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { |
1754 | cfg80211_inform_bss(priv->wdev->wiphy, chan, | 1761 | bss = cfg80211_inform_bss(priv->wdev->wiphy, |
1755 | bssid, network_tsf, cap_info_bitmap, | 1762 | chan, bssid, network_tsf, |
1756 | beacon_period, ie_buf, ie_len, rssi, | 1763 | cap_info_bitmap, beacon_period, |
1757 | GFP_KERNEL); | 1764 | ie_buf, ie_len, rssi, GFP_KERNEL); |
1765 | *(u8 *)bss->priv = band; | ||
1766 | bss->free_priv = mwifiex_free_bss_priv; | ||
1758 | 1767 | ||
1759 | if (priv->media_connected && !memcmp(bssid, | 1768 | if (priv->media_connected && !memcmp(bssid, |
1760 | priv->curr_bss_params.bss_descriptor | 1769 | priv->curr_bss_params.bss_descriptor |
@@ -1762,7 +1771,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1762 | mwifiex_update_curr_bss_params(priv, | 1771 | mwifiex_update_curr_bss_params(priv, |
1763 | bssid, rssi, ie_buf, | 1772 | bssid, rssi, ie_buf, |
1764 | ie_len, beacon_period, | 1773 | ie_len, beacon_period, |
1765 | cap_info_bitmap); | 1774 | cap_info_bitmap, band); |
1766 | } | 1775 | } |
1767 | } else { | 1776 | } else { |
1768 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | 1777 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index eb569fa9adba..a9dfeb1b4ace 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -148,7 +148,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
148 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | 148 | int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, |
149 | u8 *bssid, s32 rssi, u8 *ie_buf, | 149 | u8 *bssid, s32 rssi, u8 *ie_buf, |
150 | size_t ie_len, u16 beacon_period, | 150 | size_t ie_len, u16 beacon_period, |
151 | u16 cap_info_bitmap, | 151 | u16 cap_info_bitmap, u8 band, |
152 | struct mwifiex_bssdescriptor *bss_desc) | 152 | struct mwifiex_bssdescriptor *bss_desc) |
153 | { | 153 | { |
154 | int ret; | 154 | int ret; |
@@ -159,6 +159,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
159 | bss_desc->beacon_buf_size = ie_len; | 159 | bss_desc->beacon_buf_size = ie_len; |
160 | bss_desc->beacon_period = beacon_period; | 160 | bss_desc->beacon_period = beacon_period; |
161 | bss_desc->cap_info_bitmap = cap_info_bitmap; | 161 | bss_desc->cap_info_bitmap = cap_info_bitmap; |
162 | bss_desc->bss_band = band; | ||
162 | if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { | 163 | if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { |
163 | dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); | 164 | dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); |
164 | bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; | 165 | bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; |
@@ -203,6 +204,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
203 | beacon_ie = kmemdup(bss->information_elements, | 204 | beacon_ie = kmemdup(bss->information_elements, |
204 | bss->len_beacon_ies, GFP_KERNEL); | 205 | bss->len_beacon_ies, GFP_KERNEL); |
205 | if (!beacon_ie) { | 206 | if (!beacon_ie) { |
207 | kfree(bss_desc); | ||
206 | dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); | 208 | dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); |
207 | return -ENOMEM; | 209 | return -ENOMEM; |
208 | } | 210 | } |
@@ -210,7 +212,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
210 | ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal, | 212 | ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal, |
211 | beacon_ie, bss->len_beacon_ies, | 213 | beacon_ie, bss->len_beacon_ies, |
212 | bss->beacon_interval, | 214 | bss->beacon_interval, |
213 | bss->capability, bss_desc); | 215 | bss->capability, |
216 | *(u8 *)bss->priv, bss_desc); | ||
214 | if (ret) | 217 | if (ret) |
215 | goto done; | 218 | goto done; |
216 | } | 219 | } |
@@ -652,6 +655,7 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) | |||
652 | u16 curr_chan = 0; | 655 | u16 curr_chan = 0; |
653 | struct cfg80211_bss *bss = NULL; | 656 | struct cfg80211_bss *bss = NULL; |
654 | struct ieee80211_channel *chan; | 657 | struct ieee80211_channel *chan; |
658 | enum ieee80211_band band; | ||
655 | 659 | ||
656 | memset(&bss_info, 0, sizeof(bss_info)); | 660 | memset(&bss_info, 0, sizeof(bss_info)); |
657 | 661 | ||
@@ -688,9 +692,9 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) | |||
688 | goto done; | 692 | goto done; |
689 | } | 693 | } |
690 | 694 | ||
695 | band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | ||
691 | chan = __ieee80211_get_channel(priv->wdev->wiphy, | 696 | chan = __ieee80211_get_channel(priv->wdev->wiphy, |
692 | ieee80211_channel_to_frequency(channel, | 697 | ieee80211_channel_to_frequency(channel, band)); |
693 | priv->curr_bss_params.band)); | ||
694 | 698 | ||
695 | /* Find the BSS we want using available scan results */ | 699 | /* Find the BSS we want using available scan results */ |
696 | bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid, | 700 | bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid, |
@@ -867,10 +871,10 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, | |||
867 | ret = mwifiex_rate_ioctl_cfg(priv, rate); | 871 | ret = mwifiex_rate_ioctl_cfg(priv, rate); |
868 | 872 | ||
869 | if (!ret) { | 873 | if (!ret) { |
870 | if (rate && rate->is_rate_auto) | 874 | if (rate->is_rate_auto) |
871 | rate->rate = mwifiex_index_to_data_rate(priv->tx_rate, | 875 | rate->rate = mwifiex_index_to_data_rate(priv->tx_rate, |
872 | priv->tx_htinfo); | 876 | priv->tx_htinfo); |
873 | else if (rate) | 877 | else |
874 | rate->rate = priv->data_rate; | 878 | rate->rate = priv->data_rate; |
875 | } else { | 879 | } else { |
876 | ret = -1; | 880 | ret = -1; |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index daa32fc9398b..7e9272b8f01d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1239,7 +1239,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, | |||
1239 | * call, we must decrease the higher 32bits with 1 to get | 1239 | * call, we must decrease the higher 32bits with 1 to get |
1240 | * to correct value. | 1240 | * to correct value. |
1241 | */ | 1241 | */ |
1242 | tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw); | 1242 | tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL); |
1243 | rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME); | 1243 | rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME); |
1244 | rx_high = upper_32_bits(tsf); | 1244 | rx_high = upper_32_bits(tsf); |
1245 | 1245 | ||
@@ -1673,7 +1673,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1673 | return 0; | 1673 | return 0; |
1674 | } | 1674 | } |
1675 | 1675 | ||
1676 | static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) | 1676 | static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw, |
1677 | struct ieee80211_vif *vif) | ||
1677 | { | 1678 | { |
1678 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1679 | struct rt2x00_dev *rt2x00dev = hw->priv; |
1679 | u64 tsf; | 1680 | u64 tsf; |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index b46c3b8866fa..dcc0e1fcca77 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1966,7 +1966,8 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1966 | /* | 1966 | /* |
1967 | * IEEE80211 stack callback functions. | 1967 | * IEEE80211 stack callback functions. |
1968 | */ | 1968 | */ |
1969 | static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) | 1969 | static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw, |
1970 | struct ieee80211_vif *vif) | ||
1970 | { | 1971 | { |
1971 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1972 | struct rt2x00_dev *rt2x00dev = hw->priv; |
1972 | u64 tsf; | 1973 | u64 tsf; |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 31c98509f7e6..9688dd0a7ebd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -4466,7 +4466,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
4466 | } | 4466 | } |
4467 | EXPORT_SYMBOL_GPL(rt2800_conf_tx); | 4467 | EXPORT_SYMBOL_GPL(rt2800_conf_tx); |
4468 | 4468 | ||
4469 | u64 rt2800_get_tsf(struct ieee80211_hw *hw) | 4469 | u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
4470 | { | 4470 | { |
4471 | struct rt2x00_dev *rt2x00dev = hw->priv; | 4471 | struct rt2x00_dev *rt2x00dev = hw->priv; |
4472 | u64 tsf; | 4472 | u64 tsf; |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 7a2511f6785c..6de128e9c612 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -199,7 +199,7 @@ void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, | |||
199 | int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value); | 199 | int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value); |
200 | int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | 200 | int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, |
201 | const struct ieee80211_tx_queue_params *params); | 201 | const struct ieee80211_tx_queue_params *params); |
202 | u64 rt2800_get_tsf(struct ieee80211_hw *hw); | 202 | u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
203 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 203 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
204 | enum ieee80211_ampdu_mlme_action action, | 204 | enum ieee80211_ampdu_mlme_action action, |
205 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | 205 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 058ef4b19d1d..6b6a8e2dcddc 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2940,7 +2940,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
2940 | return 0; | 2940 | return 0; |
2941 | } | 2941 | } |
2942 | 2942 | ||
2943 | static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) | 2943 | static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
2944 | { | 2944 | { |
2945 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2945 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2946 | u64 tsf; | 2946 | u64 tsf; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 0baeb894f093..6f51e39f5595 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2279,7 +2279,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
2279 | return 0; | 2279 | return 0; |
2280 | } | 2280 | } |
2281 | 2281 | ||
2282 | static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) | 2282 | static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
2283 | { | 2283 | { |
2284 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2284 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2285 | u64 tsf; | 2285 | u64 tsf; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 66b29dc07cc3..0082015ff664 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
@@ -669,7 +669,8 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
669 | rtl8180_free_tx_ring(dev, i); | 669 | rtl8180_free_tx_ring(dev, i); |
670 | } | 670 | } |
671 | 671 | ||
672 | static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) | 672 | static u64 rtl8180_get_tsf(struct ieee80211_hw *dev, |
673 | struct ieee80211_vif *vif) | ||
673 | { | 674 | { |
674 | struct rtl8180_priv *priv = dev->priv; | 675 | struct rtl8180_priv *priv = dev->priv; |
675 | 676 | ||
@@ -701,7 +702,7 @@ static void rtl8180_beacon_work(struct work_struct *work) | |||
701 | * TODO: make hardware update beacon timestamp | 702 | * TODO: make hardware update beacon timestamp |
702 | */ | 703 | */ |
703 | mgmt = (struct ieee80211_mgmt *)skb->data; | 704 | mgmt = (struct ieee80211_mgmt *)skb->data; |
704 | mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev)); | 705 | mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev, vif)); |
705 | 706 | ||
706 | /* TODO: use actual beacon queue */ | 707 | /* TODO: use actual beacon queue */ |
707 | skb_set_queue_mapping(skb, 0); | 708 | skb_set_queue_mapping(skb, 0); |
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 1e0be14d10d4..f5afa155ce91 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c | |||
@@ -1277,7 +1277,7 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, | |||
1277 | return 0; | 1277 | return 0; |
1278 | } | 1278 | } |
1279 | 1279 | ||
1280 | static u64 rtl8187_get_tsf(struct ieee80211_hw *dev) | 1280 | static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) |
1281 | { | 1281 | { |
1282 | struct rtl8187_priv *priv = dev->priv; | 1282 | struct rtl8187_priv *priv = dev->priv; |
1283 | 1283 | ||
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 04c4e9eb6ee6..21e40f62a8d7 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -775,7 +775,7 @@ out: | |||
775 | mutex_unlock(&rtlpriv->locks.conf_mutex); | 775 | mutex_unlock(&rtlpriv->locks.conf_mutex); |
776 | } | 776 | } |
777 | 777 | ||
778 | static u64 rtl_op_get_tsf(struct ieee80211_hw *hw) | 778 | static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
779 | { | 779 | { |
780 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 780 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
781 | u64 tsf; | 781 | u64 tsf; |
@@ -784,7 +784,8 @@ static u64 rtl_op_get_tsf(struct ieee80211_hw *hw) | |||
784 | return tsf; | 784 | return tsf; |
785 | } | 785 | } |
786 | 786 | ||
787 | static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 787 | static void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
788 | u64 tsf) | ||
788 | { | 789 | { |
789 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 790 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
790 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 791 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
@@ -794,7 +795,8 @@ static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) | |||
794 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss)); | 795 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss)); |
795 | } | 796 | } |
796 | 797 | ||
797 | static void rtl_op_reset_tsf(struct ieee80211_hw *hw) | 798 | static void rtl_op_reset_tsf(struct ieee80211_hw *hw, |
799 | struct ieee80211_vif *vif) | ||
798 | { | 800 | { |
799 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 801 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
800 | u8 tmp = 0; | 802 | u8 tmp = 0; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 4c34c4c1ae56..b7ecb9e44aa9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
@@ -133,6 +133,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) | |||
133 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; | 133 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; |
134 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; | 134 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; |
135 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; | 135 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; |
136 | if (!rtlpriv->psc.inactiveps) | ||
137 | pr_info("rtl8192ce: Power Save off (module option)\n"); | ||
138 | if (!rtlpriv->psc.fwctrl_lps) | ||
139 | pr_info("rtl8192ce: FW Power Save off (module option)\n"); | ||
136 | rtlpriv->psc.reg_fwctrl_lps = 3; | 140 | rtlpriv->psc.reg_fwctrl_lps = 3; |
137 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; | 141 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; |
138 | /* for ASPM, you can close aspm through | 142 | /* for ASPM, you can close aspm through |
@@ -356,10 +360,10 @@ module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444); | |||
356 | module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444); | 360 | module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444); |
357 | module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444); | 361 | module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444); |
358 | module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444); | 362 | module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444); |
359 | MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); | 363 | MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); |
360 | MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); | 364 | MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); |
361 | MODULE_PARM_DESC(fwlps, "using linked fw control power save " | 365 | MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); |
362 | "(default 1 is open)\n"); | 366 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
363 | 367 | ||
364 | static struct pci_driver rtl92ce_driver = { | 368 | static struct pci_driver rtl92ce_driver = { |
365 | .name = KBUILD_MODNAME, | 369 | .name = KBUILD_MODNAME, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index 81ae64234f80..c8977a50ca36 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h | |||
@@ -537,12 +537,6 @@ do { \ | |||
537 | memset(__pdesc, 0, _size); \ | 537 | memset(__pdesc, 0, _size); \ |
538 | } while (0); | 538 | } while (0); |
539 | 539 | ||
540 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ | ||
541 | (_pdesc->rxmcs == DESC92_RATE1M || \ | ||
542 | _pdesc->rxmcs == DESC92_RATE2M || \ | ||
543 | _pdesc->rxmcs == DESC92_RATE5_5M || \ | ||
544 | _pdesc->rxmcs == DESC92_RATE11M) | ||
545 | |||
546 | struct rx_fwinfo_92c { | 540 | struct rx_fwinfo_92c { |
547 | u8 gain_trsw[4]; | 541 | u8 gain_trsw[4]; |
548 | u8 pwdb_all; | 542 | u8 pwdb_all; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h index 35529f701fc0..626d88e88e26 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h | |||
@@ -87,12 +87,6 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter); | |||
87 | 87 | ||
88 | u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw); | 88 | u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw); |
89 | 89 | ||
90 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ | ||
91 | (GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||\ | ||
92 | GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||\ | ||
93 | GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ | ||
94 | GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE11M) | ||
95 | |||
96 | struct rx_fwinfo_92c { | 90 | struct rx_fwinfo_92c { |
97 | u8 gain_trsw[4]; | 91 | u8 gain_trsw[4]; |
98 | u8 pwdb_all; | 92 | u8 pwdb_all; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index f6419b7ed2f4..c681597c7f20 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
@@ -150,6 +150,10 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
150 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; | 150 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; |
151 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; | 151 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; |
152 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; | 152 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; |
153 | if (!rtlpriv->psc.inactiveps) | ||
154 | pr_info("rtl8192ce: Power Save off (module option)\n"); | ||
155 | if (!rtlpriv->psc.fwctrl_lps) | ||
156 | pr_info("rtl8192ce: FW Power Save off (module option)\n"); | ||
153 | rtlpriv->psc.reg_fwctrl_lps = 3; | 157 | rtlpriv->psc.reg_fwctrl_lps = 3; |
154 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; | 158 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; |
155 | /* for ASPM, you can close aspm through | 159 | /* for ASPM, you can close aspm through |
@@ -376,10 +380,10 @@ module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444); | |||
376 | module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444); | 380 | module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444); |
377 | module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444); | 381 | module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444); |
378 | module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444); | 382 | module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444); |
379 | MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); | 383 | MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); |
380 | MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); | 384 | MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); |
381 | MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1" | 385 | MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); |
382 | " is open)\n"); | 386 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
383 | 387 | ||
384 | static struct pci_driver rtl92de_driver = { | 388 | static struct pci_driver rtl92de_driver = { |
385 | .name = KBUILD_MODNAME, | 389 | .name = KBUILD_MODNAME, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h index 6c2236868c9a..4d55d0b6816d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h | |||
@@ -537,12 +537,6 @@ do { \ | |||
537 | memset((void *)__pdesc, 0, _size); \ | 537 | memset((void *)__pdesc, 0, _size); \ |
538 | } while (0); | 538 | } while (0); |
539 | 539 | ||
540 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ | ||
541 | (_pdesc->rxmcs == DESC92_RATE1M || \ | ||
542 | _pdesc->rxmcs == DESC92_RATE2M || \ | ||
543 | _pdesc->rxmcs == DESC92_RATE5_5M || \ | ||
544 | _pdesc->rxmcs == DESC92_RATE11M) | ||
545 | |||
546 | /* For 92D early mode */ | 540 | /* For 92D early mode */ |
547 | #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ | 541 | #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ |
548 | SET_BITS_OFFSET_LE(__paddr, 0, 3, __value) | 542 | SET_BITS_OFFSET_LE(__paddr, 0, 3, __value) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 68204ea175dd..c6c044816d39 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h | |||
@@ -459,7 +459,7 @@ do { \ | |||
459 | #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ | 459 | #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ |
460 | SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) | 460 | SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) |
461 | 461 | ||
462 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ | 462 | #define SE_RX_HAL_IS_CCK_RATE(_pdesc)\ |
463 | (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \ | 463 | (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \ |
464 | GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \ | 464 | GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \ |
465 | GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ | 465 | GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 0055a1c845a2..24bd331a5484 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -164,6 +164,10 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) | |||
164 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; | 164 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; |
165 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; | 165 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; |
166 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; | 166 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; |
167 | if (!rtlpriv->psc.inactiveps) | ||
168 | pr_info("rtl8192ce: Power Save off (module option)\n"); | ||
169 | if (!rtlpriv->psc.fwctrl_lps) | ||
170 | pr_info("rtl8192ce: FW Power Save off (module option)\n"); | ||
167 | rtlpriv->psc.reg_fwctrl_lps = 3; | 171 | rtlpriv->psc.reg_fwctrl_lps = 3; |
168 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; | 172 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; |
169 | /* for ASPM, you can close aspm through | 173 | /* for ASPM, you can close aspm through |
@@ -378,6 +382,7 @@ MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids); | |||
378 | 382 | ||
379 | MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); | 383 | MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); |
380 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); | 384 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); |
385 | MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); | ||
381 | MODULE_LICENSE("GPL"); | 386 | MODULE_LICENSE("GPL"); |
382 | MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless"); | 387 | MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless"); |
383 | MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin"); | 388 | MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin"); |
@@ -386,11 +391,10 @@ module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444); | |||
386 | module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444); | 391 | module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444); |
387 | module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444); | 392 | module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444); |
388 | module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444); | 393 | module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444); |
389 | MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); | 394 | MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); |
390 | MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); | 395 | MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); |
391 | MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is " | 396 | MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); |
392 | "open)\n"); | 397 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
393 | |||
394 | 398 | ||
395 | static struct pci_driver rtl92se_driver = { | 399 | static struct pci_driver rtl92se_driver = { |
396 | .name = KBUILD_MODNAME, | 400 | .name = KBUILD_MODNAME, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index d9aeae7f8bdb..ba137da082b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
@@ -126,7 +126,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
126 | bool in_powersavemode = false; | 126 | bool in_powersavemode = false; |
127 | bool is_cck_rate; | 127 | bool is_cck_rate; |
128 | 128 | ||
129 | is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); | 129 | is_cck_rate = SE_RX_HAL_IS_CCK_RATE(pdesc); |
130 | pstats->packet_matchbssid = packet_match_bssid; | 130 | pstats->packet_matchbssid = packet_match_bssid; |
131 | pstats->packet_toself = packet_toself; | 131 | pstats->packet_toself = packet_toself; |
132 | pstats->is_cck = is_cck_rate; | 132 | pstats->is_cck = is_cck_rate; |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 8b1cef0ffde6..4bf3cf457ef0 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -863,6 +863,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
863 | u8 tid = 0; | 863 | u8 tid = 0; |
864 | u16 seq_number = 0; | 864 | u16 seq_number = 0; |
865 | 865 | ||
866 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); | ||
866 | if (ieee80211_is_auth(fc)) { | 867 | if (ieee80211_is_auth(fc)) { |
867 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); | 868 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n")); |
868 | rtl_ips_nic_on(hw); | 869 | rtl_ips_nic_on(hw); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 8a9091968f31..615f6b4463e6 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -165,6 +165,12 @@ enum hardware_type { | |||
165 | #define IS_HARDWARE_TYPE_8723U(rtlhal) \ | 165 | #define IS_HARDWARE_TYPE_8723U(rtlhal) \ |
166 | (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) | 166 | (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) |
167 | 167 | ||
168 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ | ||
169 | (_pdesc->rxmcs == DESC92_RATE1M || \ | ||
170 | _pdesc->rxmcs == DESC92_RATE2M || \ | ||
171 | _pdesc->rxmcs == DESC92_RATE5_5M || \ | ||
172 | _pdesc->rxmcs == DESC92_RATE11M) | ||
173 | |||
168 | enum scan_operation_backup_opt { | 174 | enum scan_operation_backup_opt { |
169 | SCAN_OPT_BACKUP = 0, | 175 | SCAN_OPT_BACKUP = 0, |
170 | SCAN_OPT_RESTORE, | 176 | SCAN_OPT_RESTORE, |
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 07bcb1548d8b..3fe388b87c2e 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
@@ -19,16 +19,6 @@ config WL12XX | |||
19 | If you choose to build a module, it will be called wl12xx. Say N if | 19 | If you choose to build a module, it will be called wl12xx. Say N if |
20 | unsure. | 20 | unsure. |
21 | 21 | ||
22 | config WL12XX_HT | ||
23 | bool "TI wl12xx 802.11 HT support (EXPERIMENTAL)" | ||
24 | depends on WL12XX && EXPERIMENTAL | ||
25 | default n | ||
26 | ---help--- | ||
27 | This will enable 802.11 HT support in the wl12xx module. | ||
28 | |||
29 | That configuration is temporary due to the code incomplete and | ||
30 | still in testing process. | ||
31 | |||
32 | config WL12XX_SPI | 22 | config WL12XX_SPI |
33 | tristate "TI wl12xx SPI support" | 23 | tristate "TI wl12xx SPI support" |
34 | depends on WL12XX && SPI_MASTER | 24 | depends on WL12XX && SPI_MASTER |
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 521c0414e52e..621b3483ca2c 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -1,16 +1,16 @@ | |||
1 | wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ | 1 | wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ |
2 | boot.o init.o debugfs.o scan.o | 2 | boot.o init.o debugfs.o scan.o |
3 | 3 | ||
4 | wl12xx_spi-objs = spi.o | 4 | wl12xx_spi-objs = spi.o |
5 | wl12xx_sdio-objs = sdio.o | 5 | wl12xx_sdio-objs = sdio.o |
6 | wl12xx_sdio_test-objs = sdio_test.o | 6 | wl12xx_sdio_test-objs = sdio_test.o |
7 | 7 | ||
8 | wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o | 8 | wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o |
9 | obj-$(CONFIG_WL12XX) += wl12xx.o | 9 | obj-$(CONFIG_WL12XX) += wl12xx.o |
10 | obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o | 10 | obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o |
11 | obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o | 11 | obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o |
12 | 12 | ||
13 | obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o | 13 | obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o |
14 | 14 | ||
15 | # small builtin driver bit | 15 | # small builtin driver bit |
16 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o | 16 | obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o |
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index f2838ae07da5..399849eeb247 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -1687,3 +1687,43 @@ out: | |||
1687 | kfree(acx); | 1687 | kfree(acx); |
1688 | return ret; | 1688 | return ret; |
1689 | } | 1689 | } |
1690 | |||
1691 | int wl12xx_acx_config_hangover(struct wl1271 *wl) | ||
1692 | { | ||
1693 | struct wl12xx_acx_config_hangover *acx; | ||
1694 | struct conf_hangover_settings *conf = &wl->conf.hangover; | ||
1695 | int ret; | ||
1696 | |||
1697 | wl1271_debug(DEBUG_ACX, "acx config hangover"); | ||
1698 | |||
1699 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1700 | if (!acx) { | ||
1701 | ret = -ENOMEM; | ||
1702 | goto out; | ||
1703 | } | ||
1704 | |||
1705 | acx->recover_time = cpu_to_le32(conf->recover_time); | ||
1706 | acx->hangover_period = conf->hangover_period; | ||
1707 | acx->dynamic_mode = conf->dynamic_mode; | ||
1708 | acx->early_termination_mode = conf->early_termination_mode; | ||
1709 | acx->max_period = conf->max_period; | ||
1710 | acx->min_period = conf->min_period; | ||
1711 | acx->increase_delta = conf->increase_delta; | ||
1712 | acx->decrease_delta = conf->decrease_delta; | ||
1713 | acx->quiet_time = conf->quiet_time; | ||
1714 | acx->increase_time = conf->increase_time; | ||
1715 | acx->window_size = acx->window_size; | ||
1716 | |||
1717 | ret = wl1271_cmd_configure(wl, ACX_CONFIG_HANGOVER, acx, | ||
1718 | sizeof(*acx)); | ||
1719 | |||
1720 | if (ret < 0) { | ||
1721 | wl1271_warning("acx config hangover failed: %d", ret); | ||
1722 | goto out; | ||
1723 | } | ||
1724 | |||
1725 | out: | ||
1726 | kfree(acx); | ||
1727 | return ret; | ||
1728 | |||
1729 | } | ||
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 758c596f62f6..556ee4e282d5 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -1144,6 +1144,23 @@ struct wl12xx_acx_set_rate_mgmt_params { | |||
1144 | u8 padding2[2]; | 1144 | u8 padding2[2]; |
1145 | } __packed; | 1145 | } __packed; |
1146 | 1146 | ||
1147 | struct wl12xx_acx_config_hangover { | ||
1148 | struct acx_header header; | ||
1149 | |||
1150 | __le32 recover_time; | ||
1151 | u8 hangover_period; | ||
1152 | u8 dynamic_mode; | ||
1153 | u8 early_termination_mode; | ||
1154 | u8 max_period; | ||
1155 | u8 min_period; | ||
1156 | u8 increase_delta; | ||
1157 | u8 decrease_delta; | ||
1158 | u8 quiet_time; | ||
1159 | u8 increase_time; | ||
1160 | u8 window_size; | ||
1161 | u8 padding[2]; | ||
1162 | } __packed; | ||
1163 | |||
1147 | enum { | 1164 | enum { |
1148 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 1165 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
1149 | ACX_MEM_CFG = 0x0003, | 1166 | ACX_MEM_CFG = 0x0003, |
@@ -1281,5 +1298,6 @@ int wl1271_acx_config_ps(struct wl1271 *wl); | |||
1281 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | 1298 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); |
1282 | int wl1271_acx_fm_coex(struct wl1271 *wl); | 1299 | int wl1271_acx_fm_coex(struct wl1271 *wl); |
1283 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); | 1300 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); |
1301 | int wl12xx_acx_config_hangover(struct wl1271 *wl); | ||
1284 | 1302 | ||
1285 | #endif /* __WL1271_ACX_H__ */ | 1303 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 817bc183bc83..287fe95ecb40 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -661,12 +661,9 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) | |||
661 | 661 | ||
662 | wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); | 662 | wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); |
663 | 663 | ||
664 | /* | 664 | /* trying to use hidden SSID with an old hostapd version */ |
665 | * We currently do not support hidden SSID. The real SSID | 665 | if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) { |
666 | * should be fetched from mac80211 first. | 666 | wl1271_error("got a null SSID from beacon/bss"); |
667 | */ | ||
668 | if (wl->ssid_len == 0) { | ||
669 | wl1271_warning("Hidden SSID currently not supported for AP"); | ||
670 | ret = -EINVAL; | 667 | ret = -EINVAL; |
671 | goto out; | 668 | goto out; |
672 | } | 669 | } |
@@ -695,9 +692,18 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) | |||
695 | cmd->ap.dtim_interval = bss_conf->dtim_period; | 692 | cmd->ap.dtim_interval = bss_conf->dtim_period; |
696 | cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; | 693 | cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; |
697 | cmd->channel = wl->channel; | 694 | cmd->channel = wl->channel; |
698 | cmd->ap.ssid_len = wl->ssid_len; | 695 | |
699 | cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; | 696 | if (!bss_conf->hidden_ssid) { |
700 | memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); | 697 | /* take the SSID from the beacon for backward compatibility */ |
698 | cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; | ||
699 | cmd->ap.ssid_len = wl->ssid_len; | ||
700 | memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); | ||
701 | } else { | ||
702 | cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN; | ||
703 | cmd->ap.ssid_len = bss_conf->ssid_len; | ||
704 | memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); | ||
705 | } | ||
706 | |||
701 | cmd->ap.local_rates = cpu_to_le32(0xffffffff); | 707 | cmd->ap.local_rates = cpu_to_le32(0xffffffff); |
702 | 708 | ||
703 | switch (wl->band) { | 709 | switch (wl->band) { |
@@ -895,7 +901,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
895 | struct acx_header *acx = buf; | 901 | struct acx_header *acx = buf; |
896 | int ret; | 902 | int ret; |
897 | 903 | ||
898 | wl1271_debug(DEBUG_CMD, "cmd configure"); | 904 | wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id); |
899 | 905 | ||
900 | acx->id = cpu_to_le16(id); | 906 | acx->id = cpu_to_le16(id); |
901 | 907 | ||
@@ -1106,6 +1112,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, | |||
1106 | { | 1112 | { |
1107 | struct sk_buff *skb; | 1113 | struct sk_buff *skb; |
1108 | int ret; | 1114 | int ret; |
1115 | u32 rate; | ||
1109 | 1116 | ||
1110 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, | 1117 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
1111 | ie, ie_len); | 1118 | ie, ie_len); |
@@ -1116,14 +1123,13 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, | |||
1116 | 1123 | ||
1117 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); | 1124 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); |
1118 | 1125 | ||
1126 | rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); | ||
1119 | if (band == IEEE80211_BAND_2GHZ) | 1127 | if (band == IEEE80211_BAND_2GHZ) |
1120 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 1128 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
1121 | skb->data, skb->len, 0, | 1129 | skb->data, skb->len, 0, rate); |
1122 | wl->conf.tx.basic_rate); | ||
1123 | else | 1130 | else |
1124 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 1131 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
1125 | skb->data, skb->len, 0, | 1132 | skb->data, skb->len, 0, rate); |
1126 | wl->conf.tx.basic_rate_5); | ||
1127 | 1133 | ||
1128 | out: | 1134 | out: |
1129 | dev_kfree_skb(skb); | 1135 | dev_kfree_skb(skb); |
@@ -1134,6 +1140,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | |||
1134 | struct sk_buff *skb) | 1140 | struct sk_buff *skb) |
1135 | { | 1141 | { |
1136 | int ret; | 1142 | int ret; |
1143 | u32 rate; | ||
1137 | 1144 | ||
1138 | if (!skb) | 1145 | if (!skb) |
1139 | skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); | 1146 | skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); |
@@ -1142,14 +1149,13 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | |||
1142 | 1149 | ||
1143 | wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); | 1150 | wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); |
1144 | 1151 | ||
1152 | rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]); | ||
1145 | if (wl->band == IEEE80211_BAND_2GHZ) | 1153 | if (wl->band == IEEE80211_BAND_2GHZ) |
1146 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 1154 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
1147 | skb->data, skb->len, 0, | 1155 | skb->data, skb->len, 0, rate); |
1148 | wl->conf.tx.basic_rate); | ||
1149 | else | 1156 | else |
1150 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 1157 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
1151 | skb->data, skb->len, 0, | 1158 | skb->data, skb->len, 0, rate); |
1152 | wl->conf.tx.basic_rate_5); | ||
1153 | 1159 | ||
1154 | if (ret < 0) | 1160 | if (ret < 0) |
1155 | wl1271_error("Unable to set ap probe request template."); | 1161 | wl1271_error("Unable to set ap probe request template."); |
@@ -1413,7 +1419,7 @@ out: | |||
1413 | int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) | 1419 | int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) |
1414 | { | 1420 | { |
1415 | struct wl12xx_cmd_add_peer *cmd; | 1421 | struct wl12xx_cmd_add_peer *cmd; |
1416 | int ret; | 1422 | int i, ret; |
1417 | u32 sta_rates; | 1423 | u32 sta_rates; |
1418 | 1424 | ||
1419 | wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid); | 1425 | wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid); |
@@ -1424,23 +1430,29 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) | |||
1424 | goto out; | 1430 | goto out; |
1425 | } | 1431 | } |
1426 | 1432 | ||
1427 | /* currently we don't support UAPSD */ | ||
1428 | cmd->sp_len = 0; | ||
1429 | |||
1430 | memcpy(cmd->addr, sta->addr, ETH_ALEN); | 1433 | memcpy(cmd->addr, sta->addr, ETH_ALEN); |
1431 | cmd->bss_index = WL1271_AP_BSS_INDEX; | 1434 | cmd->bss_index = WL1271_AP_BSS_INDEX; |
1432 | cmd->aid = sta->aid; | 1435 | cmd->aid = sta->aid; |
1433 | cmd->hlid = hlid; | 1436 | cmd->hlid = hlid; |
1437 | cmd->sp_len = sta->max_sp; | ||
1434 | cmd->wmm = sta->wme ? 1 : 0; | 1438 | cmd->wmm = sta->wme ? 1 : 0; |
1435 | 1439 | ||
1440 | for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) | ||
1441 | if (sta->wme && (sta->uapsd_queues & BIT(i))) | ||
1442 | cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER; | ||
1443 | else | ||
1444 | cmd->psd_type[i] = WL1271_PSD_LEGACY; | ||
1445 | |||
1436 | sta_rates = sta->supp_rates[wl->band]; | 1446 | sta_rates = sta->supp_rates[wl->band]; |
1437 | if (sta->ht_cap.ht_supported) | 1447 | if (sta->ht_cap.ht_supported) |
1438 | sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; | 1448 | sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; |
1439 | 1449 | ||
1440 | cmd->supported_rates = | 1450 | cmd->supported_rates = |
1441 | cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates)); | 1451 | cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, |
1452 | wl->band)); | ||
1442 | 1453 | ||
1443 | wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates); | 1454 | wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x", |
1455 | cmd->supported_rates, sta->uapsd_queues); | ||
1444 | 1456 | ||
1445 | ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0); | 1457 | ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0); |
1446 | if (ret < 0) { | 1458 | if (ret < 0) { |
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 22c2f373dd04..8e4d11ec0c55 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h | |||
@@ -591,6 +591,13 @@ enum wl12xx_ssid_type { | |||
591 | WL12XX_SSID_TYPE_ANY = 2, | 591 | WL12XX_SSID_TYPE_ANY = 2, |
592 | }; | 592 | }; |
593 | 593 | ||
594 | enum wl1271_psd_type { | ||
595 | WL1271_PSD_LEGACY = 0, | ||
596 | WL1271_PSD_UPSD_TRIGGER = 1, | ||
597 | WL1271_PSD_LEGACY_PSPOLL = 2, | ||
598 | WL1271_PSD_SAPSD = 3 | ||
599 | }; | ||
600 | |||
594 | struct wl12xx_cmd_add_peer { | 601 | struct wl12xx_cmd_add_peer { |
595 | struct wl1271_cmd_header header; | 602 | struct wl1271_cmd_header header; |
596 | 603 | ||
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 82f205c43342..6a6805c3cc74 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h | |||
@@ -454,12 +454,10 @@ struct conf_rx_settings { | |||
454 | #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ | 454 | #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ |
455 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) | 455 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) |
456 | 456 | ||
457 | /* | 457 | /* default rates for working as IBSS (11b and OFDM) */ |
458 | * Default rates for working as IBSS. use 11b rates | ||
459 | */ | ||
460 | #define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \ | 458 | #define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \ |
461 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ | 459 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ |
462 | CONF_HW_BIT_RATE_11MBPS); | 460 | CONF_HW_BIT_RATE_11MBPS | CONF_TX_OFDM_RATES); |
463 | 461 | ||
464 | struct conf_tx_rate_class { | 462 | struct conf_tx_rate_class { |
465 | 463 | ||
@@ -916,14 +914,6 @@ struct conf_conn_settings { | |||
916 | u8 psm_entry_nullfunc_retries; | 914 | u8 psm_entry_nullfunc_retries; |
917 | 915 | ||
918 | /* | 916 | /* |
919 | * Specifies the time to linger in active mode after successfully | ||
920 | * transmitting the PSM entry null-func frame. | ||
921 | * | ||
922 | * Range 0 - 255 TU's | ||
923 | */ | ||
924 | u8 psm_entry_hangover_period; | ||
925 | |||
926 | /* | ||
927 | * | 917 | * |
928 | * Specifies the interval of the connection keep-alive null-func | 918 | * Specifies the interval of the connection keep-alive null-func |
929 | * frame in ms. | 919 | * frame in ms. |
@@ -1236,6 +1226,20 @@ struct conf_rate_policy_settings { | |||
1236 | u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; | 1226 | u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; |
1237 | }; | 1227 | }; |
1238 | 1228 | ||
1229 | struct conf_hangover_settings { | ||
1230 | u32 recover_time; | ||
1231 | u8 hangover_period; | ||
1232 | u8 dynamic_mode; | ||
1233 | u8 early_termination_mode; | ||
1234 | u8 max_period; | ||
1235 | u8 min_period; | ||
1236 | u8 increase_delta; | ||
1237 | u8 decrease_delta; | ||
1238 | u8 quiet_time; | ||
1239 | u8 increase_time; | ||
1240 | u8 window_size; | ||
1241 | }; | ||
1242 | |||
1239 | struct conf_drv_settings { | 1243 | struct conf_drv_settings { |
1240 | struct conf_sg_settings sg; | 1244 | struct conf_sg_settings sg; |
1241 | struct conf_rx_settings rx; | 1245 | struct conf_rx_settings rx; |
@@ -1254,6 +1258,7 @@ struct conf_drv_settings { | |||
1254 | struct conf_rx_streaming_settings rx_streaming; | 1258 | struct conf_rx_streaming_settings rx_streaming; |
1255 | struct conf_fwlog fwlog; | 1259 | struct conf_fwlog fwlog; |
1256 | struct conf_rate_policy_settings rate; | 1260 | struct conf_rate_policy_settings rate; |
1261 | struct conf_hangover_settings hangover; | ||
1257 | u8 hci_io_ds; | 1262 | u8 hci_io_ds; |
1258 | }; | 1263 | }; |
1259 | 1264 | ||
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index d59354f53702..3999fd528302 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -265,18 +265,10 @@ static ssize_t gpio_power_write(struct file *file, | |||
265 | size_t count, loff_t *ppos) | 265 | size_t count, loff_t *ppos) |
266 | { | 266 | { |
267 | struct wl1271 *wl = file->private_data; | 267 | struct wl1271 *wl = file->private_data; |
268 | char buf[10]; | ||
269 | size_t len; | ||
270 | unsigned long value; | 268 | unsigned long value; |
271 | int ret; | 269 | int ret; |
272 | 270 | ||
273 | len = min(count, sizeof(buf) - 1); | 271 | ret = kstrtoul_from_user(user_buf, count, 10, &value); |
274 | if (copy_from_user(buf, user_buf, len)) { | ||
275 | return -EFAULT; | ||
276 | } | ||
277 | buf[len] = '\0'; | ||
278 | |||
279 | ret = kstrtoul(buf, 0, &value); | ||
280 | if (ret < 0) { | 272 | if (ret < 0) { |
281 | wl1271_warning("illegal value in gpio_power"); | 273 | wl1271_warning("illegal value in gpio_power"); |
282 | return -EINVAL; | 274 | return -EINVAL; |
@@ -427,17 +419,10 @@ static ssize_t dtim_interval_write(struct file *file, | |||
427 | size_t count, loff_t *ppos) | 419 | size_t count, loff_t *ppos) |
428 | { | 420 | { |
429 | struct wl1271 *wl = file->private_data; | 421 | struct wl1271 *wl = file->private_data; |
430 | char buf[10]; | ||
431 | size_t len; | ||
432 | unsigned long value; | 422 | unsigned long value; |
433 | int ret; | 423 | int ret; |
434 | 424 | ||
435 | len = min(count, sizeof(buf) - 1); | 425 | ret = kstrtoul_from_user(user_buf, count, 10, &value); |
436 | if (copy_from_user(buf, user_buf, len)) | ||
437 | return -EFAULT; | ||
438 | buf[len] = '\0'; | ||
439 | |||
440 | ret = kstrtoul(buf, 0, &value); | ||
441 | if (ret < 0) { | 426 | if (ret < 0) { |
442 | wl1271_warning("illegal value for dtim_interval"); | 427 | wl1271_warning("illegal value for dtim_interval"); |
443 | return -EINVAL; | 428 | return -EINVAL; |
@@ -492,17 +477,10 @@ static ssize_t beacon_interval_write(struct file *file, | |||
492 | size_t count, loff_t *ppos) | 477 | size_t count, loff_t *ppos) |
493 | { | 478 | { |
494 | struct wl1271 *wl = file->private_data; | 479 | struct wl1271 *wl = file->private_data; |
495 | char buf[10]; | ||
496 | size_t len; | ||
497 | unsigned long value; | 480 | unsigned long value; |
498 | int ret; | 481 | int ret; |
499 | 482 | ||
500 | len = min(count, sizeof(buf) - 1); | 483 | ret = kstrtoul_from_user(user_buf, count, 10, &value); |
501 | if (copy_from_user(buf, user_buf, len)) | ||
502 | return -EFAULT; | ||
503 | buf[len] = '\0'; | ||
504 | |||
505 | ret = kstrtoul(buf, 0, &value); | ||
506 | if (ret < 0) { | 484 | if (ret < 0) { |
507 | wl1271_warning("illegal value for beacon_interval"); | 485 | wl1271_warning("illegal value for beacon_interval"); |
508 | return -EINVAL; | 486 | return -EINVAL; |
@@ -542,17 +520,10 @@ static ssize_t rx_streaming_interval_write(struct file *file, | |||
542 | size_t count, loff_t *ppos) | 520 | size_t count, loff_t *ppos) |
543 | { | 521 | { |
544 | struct wl1271 *wl = file->private_data; | 522 | struct wl1271 *wl = file->private_data; |
545 | char buf[10]; | ||
546 | size_t len; | ||
547 | unsigned long value; | 523 | unsigned long value; |
548 | int ret; | 524 | int ret; |
549 | 525 | ||
550 | len = min(count, sizeof(buf) - 1); | 526 | ret = kstrtoul_from_user(user_buf, count, 10, &value); |
551 | if (copy_from_user(buf, user_buf, len)) | ||
552 | return -EFAULT; | ||
553 | buf[len] = '\0'; | ||
554 | |||
555 | ret = kstrtoul(buf, 0, &value); | ||
556 | if (ret < 0) { | 527 | if (ret < 0) { |
557 | wl1271_warning("illegal value in rx_streaming_interval!"); | 528 | wl1271_warning("illegal value in rx_streaming_interval!"); |
558 | return -EINVAL; | 529 | return -EINVAL; |
@@ -601,17 +572,10 @@ static ssize_t rx_streaming_always_write(struct file *file, | |||
601 | size_t count, loff_t *ppos) | 572 | size_t count, loff_t *ppos) |
602 | { | 573 | { |
603 | struct wl1271 *wl = file->private_data; | 574 | struct wl1271 *wl = file->private_data; |
604 | char buf[10]; | ||
605 | size_t len; | ||
606 | unsigned long value; | 575 | unsigned long value; |
607 | int ret; | 576 | int ret; |
608 | 577 | ||
609 | len = min(count, sizeof(buf) - 1); | 578 | ret = kstrtoul_from_user(user_buf, count, 10, &value); |
610 | if (copy_from_user(buf, user_buf, len)) | ||
611 | return -EFAULT; | ||
612 | buf[len] = '\0'; | ||
613 | |||
614 | ret = kstrtoul(buf, 0, &value); | ||
615 | if (ret < 0) { | 579 | if (ret < 0) { |
616 | wl1271_warning("illegal value in rx_streaming_write!"); | 580 | wl1271_warning("illegal value in rx_streaming_write!"); |
617 | return -EINVAL; | 581 | return -EINVAL; |
@@ -655,6 +619,47 @@ static const struct file_operations rx_streaming_always_ops = { | |||
655 | .llseek = default_llseek, | 619 | .llseek = default_llseek, |
656 | }; | 620 | }; |
657 | 621 | ||
622 | static ssize_t beacon_filtering_write(struct file *file, | ||
623 | const char __user *user_buf, | ||
624 | size_t count, loff_t *ppos) | ||
625 | { | ||
626 | struct wl1271 *wl = file->private_data; | ||
627 | char buf[10]; | ||
628 | size_t len; | ||
629 | unsigned long value; | ||
630 | int ret; | ||
631 | |||
632 | len = min(count, sizeof(buf) - 1); | ||
633 | if (copy_from_user(buf, user_buf, len)) | ||
634 | return -EFAULT; | ||
635 | buf[len] = '\0'; | ||
636 | |||
637 | ret = kstrtoul(buf, 0, &value); | ||
638 | if (ret < 0) { | ||
639 | wl1271_warning("illegal value for beacon_filtering!"); | ||
640 | return -EINVAL; | ||
641 | } | ||
642 | |||
643 | mutex_lock(&wl->mutex); | ||
644 | |||
645 | ret = wl1271_ps_elp_wakeup(wl); | ||
646 | if (ret < 0) | ||
647 | goto out; | ||
648 | |||
649 | ret = wl1271_acx_beacon_filter_opt(wl, !!value); | ||
650 | |||
651 | wl1271_ps_elp_sleep(wl); | ||
652 | out: | ||
653 | mutex_unlock(&wl->mutex); | ||
654 | return count; | ||
655 | } | ||
656 | |||
657 | static const struct file_operations beacon_filtering_ops = { | ||
658 | .write = beacon_filtering_write, | ||
659 | .open = wl1271_open_file_generic, | ||
660 | .llseek = default_llseek, | ||
661 | }; | ||
662 | |||
658 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 663 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
659 | struct dentry *rootdir) | 664 | struct dentry *rootdir) |
660 | { | 665 | { |
@@ -767,6 +772,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
767 | DEBUGFS_ADD(driver_state, rootdir); | 772 | DEBUGFS_ADD(driver_state, rootdir); |
768 | DEBUGFS_ADD(dtim_interval, rootdir); | 773 | DEBUGFS_ADD(dtim_interval, rootdir); |
769 | DEBUGFS_ADD(beacon_interval, rootdir); | 774 | DEBUGFS_ADD(beacon_interval, rootdir); |
775 | DEBUGFS_ADD(beacon_filtering, rootdir); | ||
770 | 776 | ||
771 | streaming = debugfs_create_dir("rx_streaming", rootdir); | 777 | streaming = debugfs_create_dir("rx_streaming", rootdir); |
772 | if (!streaming || IS_ERR(streaming)) | 778 | if (!streaming || IS_ERR(streaming)) |
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 0bd7b020a420..e66db69f8d17 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -171,19 +171,26 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl, | |||
171 | wl->last_rssi_event = event; | 171 | wl->last_rssi_event = event; |
172 | } | 172 | } |
173 | 173 | ||
174 | static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed) | 174 | static void wl1271_stop_ba_event(struct wl1271 *wl) |
175 | { | 175 | { |
176 | /* Convert the value to bool */ | 176 | if (wl->bss_type != BSS_TYPE_AP_BSS) { |
177 | wl->ba_allowed = !!ba_allowed; | 177 | if (!wl->ba_rx_bitmap) |
178 | 178 | return; | |
179 | /* | 179 | ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, |
180 | * Return in case: | 180 | wl->bssid); |
181 | * there are not BA open or the event indication is to allowed BA | 181 | } else { |
182 | */ | 182 | int i; |
183 | if ((!wl->ba_rx_bitmap) || (wl->ba_allowed)) | 183 | struct wl1271_link *lnk; |
184 | return; | 184 | for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) { |
185 | lnk = &wl->links[i]; | ||
186 | if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap) | ||
187 | continue; | ||
185 | 188 | ||
186 | ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid); | 189 | ieee80211_stop_rx_ba_session(wl->vif, |
190 | lnk->ba_bitmap, | ||
191 | lnk->addr); | ||
192 | } | ||
193 | } | ||
187 | } | 194 | } |
188 | 195 | ||
189 | static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, | 196 | static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, |
@@ -283,12 +290,14 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
283 | wl1271_event_rssi_trigger(wl, mbox); | 290 | wl1271_event_rssi_trigger(wl, mbox); |
284 | } | 291 | } |
285 | 292 | ||
286 | if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) { | 293 | if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) { |
287 | wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " | 294 | wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " |
288 | "ba_allowed = 0x%x", mbox->rx_ba_allowed); | 295 | "ba_allowed = 0x%x", mbox->rx_ba_allowed); |
289 | 296 | ||
290 | if (wl->vif) | 297 | wl->ba_allowed = !!mbox->rx_ba_allowed; |
291 | wl1271_stop_ba_event(wl, mbox->rx_ba_allowed); | 298 | |
299 | if (wl->vif && !wl->ba_allowed) | ||
300 | wl1271_stop_ba_event(wl); | ||
292 | } | 301 | } |
293 | 302 | ||
294 | if ((vector & DUMMY_PACKET_EVENT_ID)) { | 303 | if ((vector & DUMMY_PACKET_EVENT_ID)) { |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index b13bebea95e0..04db64c94e9a 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -103,6 +103,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl) | |||
103 | { | 103 | { |
104 | struct wl12xx_disconn_template *tmpl; | 104 | struct wl12xx_disconn_template *tmpl; |
105 | int ret; | 105 | int ret; |
106 | u32 rate; | ||
106 | 107 | ||
107 | tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); | 108 | tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); |
108 | if (!tmpl) { | 109 | if (!tmpl) { |
@@ -113,9 +114,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl) | |||
113 | tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 114 | tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
114 | IEEE80211_STYPE_DEAUTH); | 115 | IEEE80211_STYPE_DEAUTH); |
115 | 116 | ||
117 | rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
116 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, | 118 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, |
117 | tmpl, sizeof(*tmpl), 0, | 119 | tmpl, sizeof(*tmpl), 0, rate); |
118 | wl1271_tx_min_rate_get(wl)); | ||
119 | 120 | ||
120 | out: | 121 | out: |
121 | kfree(tmpl); | 122 | kfree(tmpl); |
@@ -126,6 +127,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl) | |||
126 | { | 127 | { |
127 | struct ieee80211_hdr_3addr *nullfunc; | 128 | struct ieee80211_hdr_3addr *nullfunc; |
128 | int ret; | 129 | int ret; |
130 | u32 rate; | ||
129 | 131 | ||
130 | nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL); | 132 | nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL); |
131 | if (!nullfunc) { | 133 | if (!nullfunc) { |
@@ -142,9 +144,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl) | |||
142 | memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN); | 144 | memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN); |
143 | memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN); | 145 | memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN); |
144 | 146 | ||
147 | rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
145 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, | 148 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, |
146 | sizeof(*nullfunc), 0, | 149 | sizeof(*nullfunc), 0, rate); |
147 | wl1271_tx_min_rate_get(wl)); | ||
148 | 150 | ||
149 | out: | 151 | out: |
150 | kfree(nullfunc); | 152 | kfree(nullfunc); |
@@ -155,6 +157,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) | |||
155 | { | 157 | { |
156 | struct ieee80211_qos_hdr *qosnull; | 158 | struct ieee80211_qos_hdr *qosnull; |
157 | int ret; | 159 | int ret; |
160 | u32 rate; | ||
158 | 161 | ||
159 | qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL); | 162 | qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL); |
160 | if (!qosnull) { | 163 | if (!qosnull) { |
@@ -171,9 +174,9 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) | |||
171 | memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN); | 174 | memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN); |
172 | memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN); | 175 | memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN); |
173 | 176 | ||
177 | rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
174 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, | 178 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, |
175 | sizeof(*qosnull), 0, | 179 | sizeof(*qosnull), 0, rate); |
176 | wl1271_tx_min_rate_get(wl)); | ||
177 | 180 | ||
178 | out: | 181 | out: |
179 | kfree(qosnull); | 182 | kfree(qosnull); |
@@ -498,7 +501,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl) | |||
498 | return ret; | 501 | return ret; |
499 | 502 | ||
500 | /* use the min basic rate for AP broadcast/multicast */ | 503 | /* use the min basic rate for AP broadcast/multicast */ |
501 | rc.enabled_rates = wl1271_tx_min_rate_get(wl); | 504 | rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); |
502 | rc.short_retry_limit = 10; | 505 | rc.short_retry_limit = 10; |
503 | rc.long_retry_limit = 10; | 506 | rc.long_retry_limit = 10; |
504 | rc.aflags = 0; | 507 | rc.aflags = 0; |
@@ -707,6 +710,11 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
707 | if (ret < 0) | 710 | if (ret < 0) |
708 | goto out_free_memmap; | 711 | goto out_free_memmap; |
709 | 712 | ||
713 | /* configure hangover */ | ||
714 | ret = wl12xx_acx_config_hangover(wl); | ||
715 | if (ret < 0) | ||
716 | goto out_free_memmap; | ||
717 | |||
710 | return 0; | 718 | return 0; |
711 | 719 | ||
712 | out_free_memmap: | 720 | out_free_memmap: |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index bde84027ab7f..7d409b0f3357 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -239,7 +239,6 @@ static struct conf_drv_settings default_conf = { | |||
239 | .psm_entry_retries = 8, | 239 | .psm_entry_retries = 8, |
240 | .psm_exit_retries = 16, | 240 | .psm_exit_retries = 16, |
241 | .psm_entry_nullfunc_retries = 3, | 241 | .psm_entry_nullfunc_retries = 3, |
242 | .psm_entry_hangover_period = 1, | ||
243 | .keep_alive_interval = 55000, | 242 | .keep_alive_interval = 55000, |
244 | .max_listen_interval = 20, | 243 | .max_listen_interval = 20, |
245 | }, | 244 | }, |
@@ -267,8 +266,8 @@ static struct conf_drv_settings default_conf = { | |||
267 | }, | 266 | }, |
268 | .sched_scan = { | 267 | .sched_scan = { |
269 | /* sched_scan requires dwell times in TU instead of TU/1000 */ | 268 | /* sched_scan requires dwell times in TU instead of TU/1000 */ |
270 | .min_dwell_time_active = 8, | 269 | .min_dwell_time_active = 30, |
271 | .max_dwell_time_active = 30, | 270 | .max_dwell_time_active = 60, |
272 | .dwell_time_passive = 100, | 271 | .dwell_time_passive = 100, |
273 | .dwell_time_dfs = 150, | 272 | .dwell_time_dfs = 150, |
274 | .num_probe_reqs = 2, | 273 | .num_probe_reqs = 2, |
@@ -359,9 +358,23 @@ static struct conf_drv_settings default_conf = { | |||
359 | 0x00, 0x00, 0x00, | 358 | 0x00, 0x00, 0x00, |
360 | }, | 359 | }, |
361 | }, | 360 | }, |
361 | .hangover = { | ||
362 | .recover_time = 0, | ||
363 | .hangover_period = 20, | ||
364 | .dynamic_mode = 1, | ||
365 | .early_termination_mode = 1, | ||
366 | .max_period = 20, | ||
367 | .min_period = 1, | ||
368 | .increase_delta = 1, | ||
369 | .decrease_delta = 2, | ||
370 | .quiet_time = 4, | ||
371 | .increase_time = 1, | ||
372 | .window_size = 16, | ||
373 | }, | ||
362 | }; | 374 | }; |
363 | 375 | ||
364 | static char *fwlog_param; | 376 | static char *fwlog_param; |
377 | static bool bug_on_recovery; | ||
365 | 378 | ||
366 | static void __wl1271_op_remove_interface(struct wl1271 *wl, | 379 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
367 | bool reset_tx_queues); | 380 | bool reset_tx_queues); |
@@ -757,13 +770,14 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
757 | 770 | ||
758 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) | 771 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) |
759 | { | 772 | { |
760 | bool fw_ps; | 773 | bool fw_ps, single_sta; |
761 | 774 | ||
762 | /* only regulate station links */ | 775 | /* only regulate station links */ |
763 | if (hlid < WL1271_AP_STA_HLID_START) | 776 | if (hlid < WL1271_AP_STA_HLID_START) |
764 | return; | 777 | return; |
765 | 778 | ||
766 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 779 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
780 | single_sta = (wl->active_sta_count == 1); | ||
767 | 781 | ||
768 | /* | 782 | /* |
769 | * Wake up from high level PS if the STA is asleep with too little | 783 | * Wake up from high level PS if the STA is asleep with too little |
@@ -772,8 +786,12 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) | |||
772 | if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) | 786 | if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) |
773 | wl1271_ps_link_end(wl, hlid); | 787 | wl1271_ps_link_end(wl, hlid); |
774 | 788 | ||
775 | /* Start high-level PS if the STA is asleep with enough blocks in FW */ | 789 | /* |
776 | else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 790 | * Start high-level PS if the STA is asleep with enough blocks in FW. |
791 | * Make an exception if this is the only connected station. In this | ||
792 | * case FW-memory congestion is not a problem. | ||
793 | */ | ||
794 | else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | ||
777 | wl1271_ps_link_start(wl, hlid, true); | 795 | wl1271_ps_link_start(wl, hlid, true); |
778 | } | 796 | } |
779 | 797 | ||
@@ -1213,6 +1231,8 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1213 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", | 1231 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
1214 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | 1232 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); |
1215 | 1233 | ||
1234 | BUG_ON(bug_on_recovery); | ||
1235 | |||
1216 | /* | 1236 | /* |
1217 | * Advance security sequence number to overcome potential progress | 1237 | * Advance security sequence number to overcome potential progress |
1218 | * in the firmware during recovery. This doens't hurt if the network is | 1238 | * in the firmware during recovery. This doens't hurt if the network is |
@@ -1222,9 +1242,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1222 | test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) | 1242 | test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) |
1223 | wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; | 1243 | wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; |
1224 | 1244 | ||
1225 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1226 | ieee80211_connection_loss(wl->vif); | ||
1227 | |||
1228 | /* Prevent spurious TX during FW restart */ | 1245 | /* Prevent spurious TX during FW restart */ |
1229 | ieee80211_stop_queues(wl->hw); | 1246 | ieee80211_stop_queues(wl->hw); |
1230 | 1247 | ||
@@ -1528,7 +1545,13 @@ out: | |||
1528 | int wl1271_tx_dummy_packet(struct wl1271 *wl) | 1545 | int wl1271_tx_dummy_packet(struct wl1271 *wl) |
1529 | { | 1546 | { |
1530 | unsigned long flags; | 1547 | unsigned long flags; |
1531 | int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet)); | 1548 | int q; |
1549 | |||
1550 | /* no need to queue a new dummy packet if one is already pending */ | ||
1551 | if (test_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) | ||
1552 | return 0; | ||
1553 | |||
1554 | q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet)); | ||
1532 | 1555 | ||
1533 | spin_lock_irqsave(&wl->wl_lock, flags); | 1556 | spin_lock_irqsave(&wl->wl_lock, flags); |
1534 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); | 1557 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); |
@@ -1802,10 +1825,16 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl) | |||
1802 | { | 1825 | { |
1803 | switch (wl->bss_type) { | 1826 | switch (wl->bss_type) { |
1804 | case BSS_TYPE_AP_BSS: | 1827 | case BSS_TYPE_AP_BSS: |
1805 | return WL1271_ROLE_AP; | 1828 | if (wl->p2p) |
1829 | return WL1271_ROLE_P2P_GO; | ||
1830 | else | ||
1831 | return WL1271_ROLE_AP; | ||
1806 | 1832 | ||
1807 | case BSS_TYPE_STA_BSS: | 1833 | case BSS_TYPE_STA_BSS: |
1808 | return WL1271_ROLE_STA; | 1834 | if (wl->p2p) |
1835 | return WL1271_ROLE_P2P_CL; | ||
1836 | else | ||
1837 | return WL1271_ROLE_STA; | ||
1809 | 1838 | ||
1810 | case BSS_TYPE_IBSS: | 1839 | case BSS_TYPE_IBSS: |
1811 | return WL1271_ROLE_IBSS; | 1840 | return WL1271_ROLE_IBSS; |
@@ -1827,7 +1856,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1827 | bool booted = false; | 1856 | bool booted = false; |
1828 | 1857 | ||
1829 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1858 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
1830 | vif->type, vif->addr); | 1859 | ieee80211_vif_type_p2p(vif), vif->addr); |
1831 | 1860 | ||
1832 | mutex_lock(&wl->mutex); | 1861 | mutex_lock(&wl->mutex); |
1833 | if (wl->vif) { | 1862 | if (wl->vif) { |
@@ -1847,7 +1876,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1847 | goto out; | 1876 | goto out; |
1848 | } | 1877 | } |
1849 | 1878 | ||
1850 | switch (vif->type) { | 1879 | switch (ieee80211_vif_type_p2p(vif)) { |
1880 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1881 | wl->p2p = 1; | ||
1882 | /* fall-through */ | ||
1851 | case NL80211_IFTYPE_STATION: | 1883 | case NL80211_IFTYPE_STATION: |
1852 | wl->bss_type = BSS_TYPE_STA_BSS; | 1884 | wl->bss_type = BSS_TYPE_STA_BSS; |
1853 | wl->set_bss_type = BSS_TYPE_STA_BSS; | 1885 | wl->set_bss_type = BSS_TYPE_STA_BSS; |
@@ -1856,6 +1888,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1856 | wl->bss_type = BSS_TYPE_IBSS; | 1888 | wl->bss_type = BSS_TYPE_IBSS; |
1857 | wl->set_bss_type = BSS_TYPE_STA_BSS; | 1889 | wl->set_bss_type = BSS_TYPE_STA_BSS; |
1858 | break; | 1890 | break; |
1891 | case NL80211_IFTYPE_P2P_GO: | ||
1892 | wl->p2p = 1; | ||
1893 | /* fall-through */ | ||
1859 | case NL80211_IFTYPE_AP: | 1894 | case NL80211_IFTYPE_AP: |
1860 | wl->bss_type = BSS_TYPE_AP_BSS; | 1895 | wl->bss_type = BSS_TYPE_AP_BSS; |
1861 | break; | 1896 | break; |
@@ -2051,6 +2086,7 @@ deinit: | |||
2051 | wl->ssid_len = 0; | 2086 | wl->ssid_len = 0; |
2052 | wl->bss_type = MAX_BSS_TYPE; | 2087 | wl->bss_type = MAX_BSS_TYPE; |
2053 | wl->set_bss_type = MAX_BSS_TYPE; | 2088 | wl->set_bss_type = MAX_BSS_TYPE; |
2089 | wl->p2p = 0; | ||
2054 | wl->band = IEEE80211_BAND_2GHZ; | 2090 | wl->band = IEEE80211_BAND_2GHZ; |
2055 | 2091 | ||
2056 | wl->rx_counter = 0; | 2092 | wl->rx_counter = 0; |
@@ -2063,6 +2099,8 @@ deinit: | |||
2063 | wl->time_offset = 0; | 2099 | wl->time_offset = 0; |
2064 | wl->session_counter = 0; | 2100 | wl->session_counter = 0; |
2065 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2101 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
2102 | wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; | ||
2103 | wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; | ||
2066 | wl->vif = NULL; | 2104 | wl->vif = NULL; |
2067 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | 2105 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; |
2068 | wl1271_free_ap_keys(wl); | 2106 | wl1271_free_ap_keys(wl); |
@@ -2075,6 +2113,7 @@ deinit: | |||
2075 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); | 2113 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); |
2076 | memset(wl->links_map, 0, sizeof(wl->links_map)); | 2114 | memset(wl->links_map, 0, sizeof(wl->links_map)); |
2077 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); | 2115 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); |
2116 | wl->active_sta_count = 0; | ||
2078 | 2117 | ||
2079 | /* The system link is always allocated */ | 2118 | /* The system link is always allocated */ |
2080 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); | 2119 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); |
@@ -2200,14 +2239,8 @@ out: | |||
2200 | 2239 | ||
2201 | static void wl1271_set_band_rate(struct wl1271 *wl) | 2240 | static void wl1271_set_band_rate(struct wl1271 *wl) |
2202 | { | 2241 | { |
2203 | if (wl->band == IEEE80211_BAND_2GHZ) { | 2242 | wl->basic_rate_set = wl->bitrate_masks[wl->band]; |
2204 | wl->basic_rate_set = wl->conf.tx.basic_rate; | 2243 | wl->rate_set = wl->basic_rate_set; |
2205 | wl->rate_set = wl->conf.tx.basic_rate; | ||
2206 | } else { | ||
2207 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | ||
2208 | wl->rate_set = wl->conf.tx.basic_rate_5; | ||
2209 | } | ||
2210 | |||
2211 | } | 2244 | } |
2212 | 2245 | ||
2213 | static bool wl12xx_is_roc(struct wl1271 *wl) | 2246 | static bool wl12xx_is_roc(struct wl1271 *wl) |
@@ -2236,7 +2269,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) | |||
2236 | if (ret < 0) | 2269 | if (ret < 0) |
2237 | goto out; | 2270 | goto out; |
2238 | } | 2271 | } |
2239 | wl->rate_set = wl1271_tx_min_rate_get(wl); | 2272 | wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); |
2240 | ret = wl1271_acx_sta_rate_policies(wl); | 2273 | ret = wl1271_acx_sta_rate_policies(wl); |
2241 | if (ret < 0) | 2274 | if (ret < 0) |
2242 | goto out; | 2275 | goto out; |
@@ -2318,6 +2351,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2318 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && | 2351 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && |
2319 | ((wl->band != conf->channel->band) || | 2352 | ((wl->band != conf->channel->band) || |
2320 | (wl->channel != channel))) { | 2353 | (wl->channel != channel))) { |
2354 | /* send all pending packets */ | ||
2355 | wl1271_tx_work_locked(wl); | ||
2321 | wl->band = conf->channel->band; | 2356 | wl->band = conf->channel->band; |
2322 | wl->channel = channel; | 2357 | wl->channel = channel; |
2323 | 2358 | ||
@@ -2331,7 +2366,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2331 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 2366 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
2332 | wl1271_set_band_rate(wl); | 2367 | wl1271_set_band_rate(wl); |
2333 | 2368 | ||
2334 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 2369 | wl->basic_rate = |
2370 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
2335 | ret = wl1271_acx_sta_rate_policies(wl); | 2371 | ret = wl1271_acx_sta_rate_policies(wl); |
2336 | if (ret < 0) | 2372 | if (ret < 0) |
2337 | wl1271_warning("rate policy for channel " | 2373 | wl1271_warning("rate policy for channel " |
@@ -3032,6 +3068,93 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | |||
3032 | return 0; | 3068 | return 0; |
3033 | } | 3069 | } |
3034 | 3070 | ||
3071 | static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset) | ||
3072 | { | ||
3073 | int len; | ||
3074 | const u8 *next, *end = skb->data + skb->len; | ||
3075 | u8 *ie = (u8 *)cfg80211_find_ie(eid, skb->data + ieoffset, | ||
3076 | skb->len - ieoffset); | ||
3077 | if (!ie) | ||
3078 | return; | ||
3079 | len = ie[1] + 2; | ||
3080 | next = ie + len; | ||
3081 | memmove(ie, next, end - next); | ||
3082 | skb_trim(skb, skb->len - len); | ||
3083 | } | ||
3084 | |||
3085 | static void wl12xx_remove_vendor_ie(struct sk_buff *skb, | ||
3086 | unsigned int oui, u8 oui_type, | ||
3087 | int ieoffset) | ||
3088 | { | ||
3089 | int len; | ||
3090 | const u8 *next, *end = skb->data + skb->len; | ||
3091 | u8 *ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type, | ||
3092 | skb->data + ieoffset, | ||
3093 | skb->len - ieoffset); | ||
3094 | if (!ie) | ||
3095 | return; | ||
3096 | len = ie[1] + 2; | ||
3097 | next = ie + len; | ||
3098 | memmove(ie, next, end - next); | ||
3099 | skb_trim(skb, skb->len - len); | ||
3100 | } | ||
3101 | |||
3102 | static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, | ||
3103 | u8 *probe_rsp_data, | ||
3104 | size_t probe_rsp_len, | ||
3105 | u32 rates) | ||
3106 | { | ||
3107 | struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; | ||
3108 | u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE]; | ||
3109 | int ssid_ie_offset, ie_offset, templ_len; | ||
3110 | const u8 *ptr; | ||
3111 | |||
3112 | /* no need to change probe response if the SSID is set correctly */ | ||
3113 | if (wl->ssid_len > 0) | ||
3114 | return wl1271_cmd_template_set(wl, | ||
3115 | CMD_TEMPL_AP_PROBE_RESPONSE, | ||
3116 | probe_rsp_data, | ||
3117 | probe_rsp_len, 0, | ||
3118 | rates); | ||
3119 | |||
3120 | if (probe_rsp_len + bss_conf->ssid_len > WL1271_CMD_TEMPL_MAX_SIZE) { | ||
3121 | wl1271_error("probe_rsp template too big"); | ||
3122 | return -EINVAL; | ||
3123 | } | ||
3124 | |||
3125 | /* start searching from IE offset */ | ||
3126 | ie_offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | ||
3127 | |||
3128 | ptr = cfg80211_find_ie(WLAN_EID_SSID, probe_rsp_data + ie_offset, | ||
3129 | probe_rsp_len - ie_offset); | ||
3130 | if (!ptr) { | ||
3131 | wl1271_error("No SSID in beacon!"); | ||
3132 | return -EINVAL; | ||
3133 | } | ||
3134 | |||
3135 | ssid_ie_offset = ptr - probe_rsp_data; | ||
3136 | ptr += (ptr[1] + 2); | ||
3137 | |||
3138 | memcpy(probe_rsp_templ, probe_rsp_data, ssid_ie_offset); | ||
3139 | |||
3140 | /* insert SSID from bss_conf */ | ||
3141 | probe_rsp_templ[ssid_ie_offset] = WLAN_EID_SSID; | ||
3142 | probe_rsp_templ[ssid_ie_offset + 1] = bss_conf->ssid_len; | ||
3143 | memcpy(probe_rsp_templ + ssid_ie_offset + 2, | ||
3144 | bss_conf->ssid, bss_conf->ssid_len); | ||
3145 | templ_len = ssid_ie_offset + 2 + bss_conf->ssid_len; | ||
3146 | |||
3147 | memcpy(probe_rsp_templ + ssid_ie_offset + 2 + bss_conf->ssid_len, | ||
3148 | ptr, probe_rsp_len - (ptr - probe_rsp_data)); | ||
3149 | templ_len += probe_rsp_len - (ptr - probe_rsp_data); | ||
3150 | |||
3151 | return wl1271_cmd_template_set(wl, | ||
3152 | CMD_TEMPL_AP_PROBE_RESPONSE, | ||
3153 | probe_rsp_templ, | ||
3154 | templ_len, 0, | ||
3155 | rates); | ||
3156 | } | ||
3157 | |||
3035 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, | 3158 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, |
3036 | struct ieee80211_bss_conf *bss_conf, | 3159 | struct ieee80211_bss_conf *bss_conf, |
3037 | u32 changed) | 3160 | u32 changed) |
@@ -3088,6 +3211,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3088 | 3211 | ||
3089 | if ((changed & BSS_CHANGED_BEACON)) { | 3212 | if ((changed & BSS_CHANGED_BEACON)) { |
3090 | struct ieee80211_hdr *hdr; | 3213 | struct ieee80211_hdr *hdr; |
3214 | u32 min_rate; | ||
3091 | int ieoffset = offsetof(struct ieee80211_mgmt, | 3215 | int ieoffset = offsetof(struct ieee80211_mgmt, |
3092 | u.beacon.variable); | 3216 | u.beacon.variable); |
3093 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); | 3217 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); |
@@ -3103,28 +3227,46 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3103 | dev_kfree_skb(beacon); | 3227 | dev_kfree_skb(beacon); |
3104 | goto out; | 3228 | goto out; |
3105 | } | 3229 | } |
3230 | min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
3106 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : | 3231 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : |
3107 | CMD_TEMPL_BEACON; | 3232 | CMD_TEMPL_BEACON; |
3108 | ret = wl1271_cmd_template_set(wl, tmpl_id, | 3233 | ret = wl1271_cmd_template_set(wl, tmpl_id, |
3109 | beacon->data, | 3234 | beacon->data, |
3110 | beacon->len, 0, | 3235 | beacon->len, 0, |
3111 | wl1271_tx_min_rate_get(wl)); | 3236 | min_rate); |
3112 | if (ret < 0) { | 3237 | if (ret < 0) { |
3113 | dev_kfree_skb(beacon); | 3238 | dev_kfree_skb(beacon); |
3114 | goto out; | 3239 | goto out; |
3115 | } | 3240 | } |
3116 | 3241 | ||
3242 | /* remove TIM ie from probe response */ | ||
3243 | wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); | ||
3244 | |||
3245 | /* | ||
3246 | * remove p2p ie from probe response. | ||
3247 | * the fw reponds to probe requests that don't include | ||
3248 | * the p2p ie. probe requests with p2p ie will be passed, | ||
3249 | * and will be responded by the supplicant (the spec | ||
3250 | * forbids including the p2p ie when responding to probe | ||
3251 | * requests that didn't include it). | ||
3252 | */ | ||
3253 | wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, | ||
3254 | WLAN_OUI_TYPE_WFA_P2P, ieoffset); | ||
3255 | |||
3117 | hdr = (struct ieee80211_hdr *) beacon->data; | 3256 | hdr = (struct ieee80211_hdr *) beacon->data; |
3118 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 3257 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
3119 | IEEE80211_STYPE_PROBE_RESP); | 3258 | IEEE80211_STYPE_PROBE_RESP); |
3120 | 3259 | if (is_ap) | |
3121 | tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE : | 3260 | ret = wl1271_ap_set_probe_resp_tmpl(wl, |
3122 | CMD_TEMPL_PROBE_RESPONSE; | 3261 | beacon->data, |
3123 | ret = wl1271_cmd_template_set(wl, | 3262 | beacon->len, |
3124 | tmpl_id, | 3263 | min_rate); |
3125 | beacon->data, | 3264 | else |
3126 | beacon->len, 0, | 3265 | ret = wl1271_cmd_template_set(wl, |
3127 | wl1271_tx_min_rate_get(wl)); | 3266 | CMD_TEMPL_PROBE_RESPONSE, |
3267 | beacon->data, | ||
3268 | beacon->len, 0, | ||
3269 | min_rate); | ||
3128 | dev_kfree_skb(beacon); | 3270 | dev_kfree_skb(beacon); |
3129 | if (ret < 0) | 3271 | if (ret < 0) |
3130 | goto out; | 3272 | goto out; |
@@ -3145,8 +3287,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
3145 | if ((changed & BSS_CHANGED_BASIC_RATES)) { | 3287 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
3146 | u32 rates = bss_conf->basic_rates; | 3288 | u32 rates = bss_conf->basic_rates; |
3147 | 3289 | ||
3148 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); | 3290 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, |
3149 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 3291 | wl->band); |
3292 | wl->basic_rate = wl1271_tx_min_rate_get(wl, | ||
3293 | wl->basic_rate_set); | ||
3150 | 3294 | ||
3151 | ret = wl1271_init_ap_rates(wl); | 3295 | ret = wl1271_init_ap_rates(wl); |
3152 | if (ret < 0) { | 3296 | if (ret < 0) { |
@@ -3328,12 +3472,15 @@ sta_not_found: | |||
3328 | * to use with control frames. | 3472 | * to use with control frames. |
3329 | */ | 3473 | */ |
3330 | rates = bss_conf->basic_rates; | 3474 | rates = bss_conf->basic_rates; |
3331 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | 3475 | wl->basic_rate_set = |
3332 | rates); | 3476 | wl1271_tx_enabled_rates_get(wl, rates, |
3333 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 3477 | wl->band); |
3478 | wl->basic_rate = | ||
3479 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
3334 | if (sta_rate_set) | 3480 | if (sta_rate_set) |
3335 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, | 3481 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, |
3336 | sta_rate_set); | 3482 | sta_rate_set, |
3483 | wl->band); | ||
3337 | ret = wl1271_acx_sta_rate_policies(wl); | 3484 | ret = wl1271_acx_sta_rate_policies(wl); |
3338 | if (ret < 0) | 3485 | if (ret < 0) |
3339 | goto out; | 3486 | goto out; |
@@ -3380,7 +3527,8 @@ sta_not_found: | |||
3380 | 3527 | ||
3381 | /* revert back to minimum rates for the current band */ | 3528 | /* revert back to minimum rates for the current band */ |
3382 | wl1271_set_band_rate(wl); | 3529 | wl1271_set_band_rate(wl); |
3383 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 3530 | wl->basic_rate = |
3531 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
3384 | ret = wl1271_acx_sta_rate_policies(wl); | 3532 | ret = wl1271_acx_sta_rate_policies(wl); |
3385 | if (ret < 0) | 3533 | if (ret < 0) |
3386 | goto out; | 3534 | goto out; |
@@ -3431,11 +3579,13 @@ sta_not_found: | |||
3431 | 3579 | ||
3432 | if (bss_conf->ibss_joined) { | 3580 | if (bss_conf->ibss_joined) { |
3433 | u32 rates = bss_conf->basic_rates; | 3581 | u32 rates = bss_conf->basic_rates; |
3434 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | 3582 | wl->basic_rate_set = |
3435 | rates); | 3583 | wl1271_tx_enabled_rates_get(wl, rates, |
3436 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 3584 | wl->band); |
3585 | wl->basic_rate = | ||
3586 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | ||
3437 | 3587 | ||
3438 | /* by default, use 11b rates */ | 3588 | /* by default, use 11b + OFDM rates */ |
3439 | wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; | 3589 | wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; |
3440 | ret = wl1271_acx_sta_rate_policies(wl); | 3590 | ret = wl1271_acx_sta_rate_policies(wl); |
3441 | if (ret < 0) | 3591 | if (ret < 0) |
@@ -3665,7 +3815,8 @@ out: | |||
3665 | return ret; | 3815 | return ret; |
3666 | } | 3816 | } |
3667 | 3817 | ||
3668 | static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw) | 3818 | static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, |
3819 | struct ieee80211_vif *vif) | ||
3669 | { | 3820 | { |
3670 | 3821 | ||
3671 | struct wl1271 *wl = hw->priv; | 3822 | struct wl1271 *wl = hw->priv; |
@@ -3729,14 +3880,18 @@ static int wl1271_allocate_sta(struct wl1271 *wl, | |||
3729 | wl_sta->hlid = WL1271_AP_STA_HLID_START + id; | 3880 | wl_sta->hlid = WL1271_AP_STA_HLID_START + id; |
3730 | *hlid = wl_sta->hlid; | 3881 | *hlid = wl_sta->hlid; |
3731 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); | 3882 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); |
3883 | wl->active_sta_count++; | ||
3732 | return 0; | 3884 | return 0; |
3733 | } | 3885 | } |
3734 | 3886 | ||
3735 | static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | 3887 | void wl1271_free_sta(struct wl1271 *wl, u8 hlid) |
3736 | { | 3888 | { |
3737 | int id = hlid - WL1271_AP_STA_HLID_START; | 3889 | int id = hlid - WL1271_AP_STA_HLID_START; |
3738 | 3890 | ||
3739 | if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) | 3891 | if (hlid < WL1271_AP_STA_HLID_START) |
3892 | return; | ||
3893 | |||
3894 | if (!test_bit(id, wl->ap_hlid_map)) | ||
3740 | return; | 3895 | return; |
3741 | 3896 | ||
3742 | clear_bit(id, wl->ap_hlid_map); | 3897 | clear_bit(id, wl->ap_hlid_map); |
@@ -3745,6 +3900,7 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | |||
3745 | wl1271_tx_reset_link_queues(wl, hlid); | 3900 | wl1271_tx_reset_link_queues(wl, hlid); |
3746 | __clear_bit(hlid, &wl->ap_ps_map); | 3901 | __clear_bit(hlid, &wl->ap_ps_map); |
3747 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 3902 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
3903 | wl->active_sta_count--; | ||
3748 | } | 3904 | } |
3749 | 3905 | ||
3750 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | 3906 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, |
@@ -3950,6 +4106,29 @@ out: | |||
3950 | return ret; | 4106 | return ret; |
3951 | } | 4107 | } |
3952 | 4108 | ||
4109 | static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, | ||
4110 | struct ieee80211_vif *vif, | ||
4111 | const struct cfg80211_bitrate_mask *mask) | ||
4112 | { | ||
4113 | struct wl1271 *wl = hw->priv; | ||
4114 | int i; | ||
4115 | |||
4116 | wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x", | ||
4117 | mask->control[NL80211_BAND_2GHZ].legacy, | ||
4118 | mask->control[NL80211_BAND_5GHZ].legacy); | ||
4119 | |||
4120 | mutex_lock(&wl->mutex); | ||
4121 | |||
4122 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
4123 | wl->bitrate_masks[i] = | ||
4124 | wl1271_tx_enabled_rates_get(wl, | ||
4125 | mask->control[i].legacy, | ||
4126 | i); | ||
4127 | mutex_unlock(&wl->mutex); | ||
4128 | |||
4129 | return 0; | ||
4130 | } | ||
4131 | |||
3953 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | 4132 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) |
3954 | { | 4133 | { |
3955 | struct wl1271 *wl = hw->priv; | 4134 | struct wl1271 *wl = hw->priv; |
@@ -4066,7 +4245,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { | |||
4066 | /* 11n STA capabilities */ | 4245 | /* 11n STA capabilities */ |
4067 | #define HW_RX_HIGHEST_RATE 72 | 4246 | #define HW_RX_HIGHEST_RATE 72 |
4068 | 4247 | ||
4069 | #ifdef CONFIG_WL12XX_HT | ||
4070 | #define WL12XX_HT_CAP { \ | 4248 | #define WL12XX_HT_CAP { \ |
4071 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ | 4249 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ |
4072 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ | 4250 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ |
@@ -4079,11 +4257,6 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { | |||
4079 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | 4257 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ |
4080 | }, \ | 4258 | }, \ |
4081 | } | 4259 | } |
4082 | #else | ||
4083 | #define WL12XX_HT_CAP { \ | ||
4084 | .ht_supported = false, \ | ||
4085 | } | ||
4086 | #endif | ||
4087 | 4260 | ||
4088 | /* can't be const, mac80211 writes to this */ | 4261 | /* can't be const, mac80211 writes to this */ |
4089 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 4262 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
@@ -4231,6 +4404,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
4231 | .sta_remove = wl1271_op_sta_remove, | 4404 | .sta_remove = wl1271_op_sta_remove, |
4232 | .ampdu_action = wl1271_op_ampdu_action, | 4405 | .ampdu_action = wl1271_op_ampdu_action, |
4233 | .tx_frames_pending = wl1271_tx_frames_pending, | 4406 | .tx_frames_pending = wl1271_tx_frames_pending, |
4407 | .set_bitrate_mask = wl12xx_set_bitrate_mask, | ||
4234 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 4408 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
4235 | }; | 4409 | }; |
4236 | 4410 | ||
@@ -4483,15 +4657,19 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4483 | IEEE80211_HW_SUPPORTS_CQM_RSSI | | 4657 | IEEE80211_HW_SUPPORTS_CQM_RSSI | |
4484 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 4658 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
4485 | IEEE80211_HW_SPECTRUM_MGMT | | 4659 | IEEE80211_HW_SPECTRUM_MGMT | |
4486 | IEEE80211_HW_AP_LINK_PS; | 4660 | IEEE80211_HW_AP_LINK_PS | |
4661 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
4662 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW; | ||
4487 | 4663 | ||
4488 | wl->hw->wiphy->cipher_suites = cipher_suites; | 4664 | wl->hw->wiphy->cipher_suites = cipher_suites; |
4489 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 4665 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
4490 | 4666 | ||
4491 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 4667 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
4492 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); | 4668 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | |
4669 | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); | ||
4493 | wl->hw->wiphy->max_scan_ssids = 1; | 4670 | wl->hw->wiphy->max_scan_ssids = 1; |
4494 | wl->hw->wiphy->max_sched_scan_ssids = 8; | 4671 | wl->hw->wiphy->max_sched_scan_ssids = 16; |
4672 | wl->hw->wiphy->max_match_sets = 16; | ||
4495 | /* | 4673 | /* |
4496 | * Maximum length of elements in scanning probe request templates | 4674 | * Maximum length of elements in scanning probe request templates |
4497 | * should be the maximum length possible for a template, without | 4675 | * should be the maximum length possible for a template, without |
@@ -4500,6 +4678,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4500 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - | 4678 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - |
4501 | sizeof(struct ieee80211_header); | 4679 | sizeof(struct ieee80211_header); |
4502 | 4680 | ||
4681 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | ||
4682 | |||
4503 | /* make sure all our channels fit in the scanned_ch bitmask */ | 4683 | /* make sure all our channels fit in the scanned_ch bitmask */ |
4504 | BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + | 4684 | BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + |
4505 | ARRAY_SIZE(wl1271_channels_5ghz) > | 4685 | ARRAY_SIZE(wl1271_channels_5ghz) > |
@@ -4543,6 +4723,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4543 | int i, j, ret; | 4723 | int i, j, ret; |
4544 | unsigned int order; | 4724 | unsigned int order; |
4545 | 4725 | ||
4726 | BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS); | ||
4727 | |||
4546 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 4728 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
4547 | if (!hw) { | 4729 | if (!hw) { |
4548 | wl1271_error("could not alloc ieee80211_hw"); | 4730 | wl1271_error("could not alloc ieee80211_hw"); |
@@ -4625,6 +4807,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4625 | wl->session_counter = 0; | 4807 | wl->session_counter = 0; |
4626 | wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; | 4808 | wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; |
4627 | wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; | 4809 | wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; |
4810 | wl->active_sta_count = 0; | ||
4628 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, | 4811 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, |
4629 | (unsigned long) wl); | 4812 | (unsigned long) wl); |
4630 | wl->fwlog_size = 0; | 4813 | wl->fwlog_size = 0; |
@@ -4644,6 +4827,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4644 | 4827 | ||
4645 | /* Apply default driver configuration. */ | 4828 | /* Apply default driver configuration. */ |
4646 | wl1271_conf_init(wl); | 4829 | wl1271_conf_init(wl); |
4830 | wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; | ||
4831 | wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; | ||
4647 | 4832 | ||
4648 | order = get_order(WL1271_AGGR_BUFFER_SIZE); | 4833 | order = get_order(WL1271_AGGR_BUFFER_SIZE); |
4649 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); | 4834 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); |
@@ -4776,6 +4961,9 @@ module_param_named(fwlog, fwlog_param, charp, 0); | |||
4776 | MODULE_PARM_DESC(keymap, | 4961 | MODULE_PARM_DESC(keymap, |
4777 | "FW logger options: continuous, ondemand, dbgpins or disable"); | 4962 | "FW logger options: continuous, ondemand, dbgpins or disable"); |
4778 | 4963 | ||
4964 | module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR); | ||
4965 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); | ||
4966 | |||
4779 | MODULE_LICENSE("GPL"); | 4967 | MODULE_LICENSE("GPL"); |
4780 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 4968 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
4781 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 4969 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 4b720b1b9f65..c15ebf2efd40 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -199,15 +199,19 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) | |||
199 | unsigned long flags; | 199 | unsigned long flags; |
200 | int filtered[NUM_TX_QUEUES]; | 200 | int filtered[NUM_TX_QUEUES]; |
201 | 201 | ||
202 | /* filter all frames currently the low level queus for this hlid */ | 202 | /* filter all frames currently in the low level queues for this hlid */ |
203 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 203 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
204 | filtered[i] = 0; | 204 | filtered[i] = 0; |
205 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { | 205 | while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { |
206 | filtered[i]++; | ||
207 | |||
208 | if (WARN_ON(wl12xx_is_dummy_packet(wl, skb))) | ||
209 | continue; | ||
210 | |||
206 | info = IEEE80211_SKB_CB(skb); | 211 | info = IEEE80211_SKB_CB(skb); |
207 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 212 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
208 | info->status.rates[0].idx = -1; | 213 | info->status.rates[0].idx = -1; |
209 | ieee80211_tx_status_ni(wl->hw, skb); | 214 | ieee80211_tx_status_ni(wl->hw, skb); |
210 | filtered[i]++; | ||
211 | } | 215 | } |
212 | } | 216 | } |
213 | 217 | ||
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 78d8410da1f4..dee4cfe9ccc1 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -66,11 +66,9 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
66 | 66 | ||
67 | status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band); | 67 | status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band); |
68 | 68 | ||
69 | #ifdef CONFIG_WL12XX_HT | ||
70 | /* 11n support */ | 69 | /* 11n support */ |
71 | if (desc->rate <= CONF_HW_RXTX_RATE_MCS0) | 70 | if (desc->rate <= CONF_HW_RXTX_RATE_MCS0) |
72 | status->flag |= RX_FLAG_HT; | 71 | status->flag |= RX_FLAG_HT; |
73 | #endif | ||
74 | 72 | ||
75 | status->signal = desc->rssi; | 73 | status->signal = desc->rssi; |
76 | 74 | ||
@@ -107,6 +105,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
107 | u8 beacon = 0; | 105 | u8 beacon = 0; |
108 | u8 is_data = 0; | 106 | u8 is_data = 0; |
109 | u8 reserved = unaligned ? NET_IP_ALIGN : 0; | 107 | u8 reserved = unaligned ? NET_IP_ALIGN : 0; |
108 | u16 seq_num; | ||
110 | 109 | ||
111 | /* | 110 | /* |
112 | * In PLT mode we seem to get frames and mac80211 warns about them, | 111 | * In PLT mode we seem to get frames and mac80211 warns about them, |
@@ -169,9 +168,11 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
169 | 168 | ||
170 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); | 169 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
171 | 170 | ||
172 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, | 171 | seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; |
172 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb, | ||
173 | skb->len - desc->pad_len, | 173 | skb->len - desc->pad_len, |
174 | beacon ? "beacon" : ""); | 174 | beacon ? "beacon" : "", |
175 | seq_num); | ||
175 | 176 | ||
176 | skb_trim(skb, skb->len - desc->pad_len); | 177 | skb_trim(skb, skb->len - desc->pad_len); |
177 | 178 | ||
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index af4ad2353f59..128ccb79318c 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "scan.h" | 28 | #include "scan.h" |
29 | #include "acx.h" | 29 | #include "acx.h" |
30 | #include "ps.h" | 30 | #include "ps.h" |
31 | #include "tx.h" | ||
31 | 32 | ||
32 | void wl1271_scan_complete_work(struct work_struct *work) | 33 | void wl1271_scan_complete_work(struct work_struct *work) |
33 | { | 34 | { |
@@ -65,8 +66,9 @@ void wl1271_scan_complete_work(struct work_struct *work) | |||
65 | /* return to ROC if needed */ | 66 | /* return to ROC if needed */ |
66 | is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); | 67 | is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); |
67 | is_ibss = (wl->bss_type == BSS_TYPE_IBSS); | 68 | is_ibss = (wl->bss_type == BSS_TYPE_IBSS); |
68 | if ((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || | 69 | if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || |
69 | (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) { | 70 | (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && |
71 | !test_bit(wl->dev_role_id, wl->roc_map)) { | ||
70 | /* restore remain on channel */ | 72 | /* restore remain on channel */ |
71 | wl12xx_cmd_role_start_dev(wl); | 73 | wl12xx_cmd_role_start_dev(wl); |
72 | wl12xx_roc(wl, wl->dev_role_id); | 74 | wl12xx_roc(wl, wl->dev_role_id); |
@@ -98,14 +100,18 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, | |||
98 | for (i = 0, j = 0; | 100 | for (i = 0, j = 0; |
99 | i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS; | 101 | i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS; |
100 | i++) { | 102 | i++) { |
101 | |||
102 | flags = req->channels[i]->flags; | 103 | flags = req->channels[i]->flags; |
103 | 104 | ||
104 | if (!test_bit(i, wl->scan.scanned_ch) && | 105 | if (!test_bit(i, wl->scan.scanned_ch) && |
105 | !(flags & IEEE80211_CHAN_DISABLED) && | 106 | !(flags & IEEE80211_CHAN_DISABLED) && |
106 | ((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) && | 107 | (req->channels[i]->band == band) && |
107 | (req->channels[i]->band == band)) { | 108 | /* |
108 | 109 | * In passive scans, we scan all remaining | |
110 | * channels, even if not marked as such. | ||
111 | * In active scans, we only scan channels not | ||
112 | * marked as passive. | ||
113 | */ | ||
114 | (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) { | ||
109 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | 115 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", |
110 | req->channels[i]->band, | 116 | req->channels[i]->band, |
111 | req->channels[i]->center_freq); | 117 | req->channels[i]->center_freq); |
@@ -157,6 +163,10 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | |||
157 | int ret; | 163 | int ret; |
158 | u16 scan_options = 0; | 164 | u16 scan_options = 0; |
159 | 165 | ||
166 | /* skip active scans if we don't have SSIDs */ | ||
167 | if (!passive && wl->scan.req->n_ssids == 0) | ||
168 | return WL1271_NOTHING_TO_SCAN; | ||
169 | |||
160 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 170 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
161 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); | 171 | trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); |
162 | if (!cmd || !trigger) { | 172 | if (!cmd || !trigger) { |
@@ -164,11 +174,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, | |||
164 | goto out; | 174 | goto out; |
165 | } | 175 | } |
166 | 176 | ||
167 | /* We always use high priority scans */ | 177 | if (passive) |
168 | scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH; | ||
169 | |||
170 | /* No SSIDs means that we have a forced passive scan */ | ||
171 | if (passive || wl->scan.req->n_ssids == 0) | ||
172 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | 178 | scan_options |= WL1271_SCAN_OPT_PASSIVE; |
173 | 179 | ||
174 | if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { | 180 | if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { |
@@ -238,14 +244,17 @@ out: | |||
238 | void wl1271_scan_stm(struct wl1271 *wl) | 244 | void wl1271_scan_stm(struct wl1271 *wl) |
239 | { | 245 | { |
240 | int ret = 0; | 246 | int ret = 0; |
247 | enum ieee80211_band band; | ||
248 | u32 rate; | ||
241 | 249 | ||
242 | switch (wl->scan.state) { | 250 | switch (wl->scan.state) { |
243 | case WL1271_SCAN_STATE_IDLE: | 251 | case WL1271_SCAN_STATE_IDLE: |
244 | break; | 252 | break; |
245 | 253 | ||
246 | case WL1271_SCAN_STATE_2GHZ_ACTIVE: | 254 | case WL1271_SCAN_STATE_2GHZ_ACTIVE: |
247 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false, | 255 | band = IEEE80211_BAND_2GHZ; |
248 | wl->conf.tx.basic_rate); | 256 | rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); |
257 | ret = wl1271_scan_send(wl, band, false, rate); | ||
249 | if (ret == WL1271_NOTHING_TO_SCAN) { | 258 | if (ret == WL1271_NOTHING_TO_SCAN) { |
250 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; | 259 | wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; |
251 | wl1271_scan_stm(wl); | 260 | wl1271_scan_stm(wl); |
@@ -254,8 +263,9 @@ void wl1271_scan_stm(struct wl1271 *wl) | |||
254 | break; | 263 | break; |
255 | 264 | ||
256 | case WL1271_SCAN_STATE_2GHZ_PASSIVE: | 265 | case WL1271_SCAN_STATE_2GHZ_PASSIVE: |
257 | ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, | 266 | band = IEEE80211_BAND_2GHZ; |
258 | wl->conf.tx.basic_rate); | 267 | rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); |
268 | ret = wl1271_scan_send(wl, band, true, rate); | ||
259 | if (ret == WL1271_NOTHING_TO_SCAN) { | 269 | if (ret == WL1271_NOTHING_TO_SCAN) { |
260 | if (wl->enable_11a) | 270 | if (wl->enable_11a) |
261 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; | 271 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; |
@@ -267,8 +277,9 @@ void wl1271_scan_stm(struct wl1271 *wl) | |||
267 | break; | 277 | break; |
268 | 278 | ||
269 | case WL1271_SCAN_STATE_5GHZ_ACTIVE: | 279 | case WL1271_SCAN_STATE_5GHZ_ACTIVE: |
270 | ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false, | 280 | band = IEEE80211_BAND_5GHZ; |
271 | wl->conf.tx.basic_rate_5); | 281 | rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); |
282 | ret = wl1271_scan_send(wl, band, false, rate); | ||
272 | if (ret == WL1271_NOTHING_TO_SCAN) { | 283 | if (ret == WL1271_NOTHING_TO_SCAN) { |
273 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; | 284 | wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; |
274 | wl1271_scan_stm(wl); | 285 | wl1271_scan_stm(wl); |
@@ -277,8 +288,9 @@ void wl1271_scan_stm(struct wl1271 *wl) | |||
277 | break; | 288 | break; |
278 | 289 | ||
279 | case WL1271_SCAN_STATE_5GHZ_PASSIVE: | 290 | case WL1271_SCAN_STATE_5GHZ_PASSIVE: |
280 | ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true, | 291 | band = IEEE80211_BAND_5GHZ; |
281 | wl->conf.tx.basic_rate_5); | 292 | rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); |
293 | ret = wl1271_scan_send(wl, band, true, rate); | ||
282 | if (ret == WL1271_NOTHING_TO_SCAN) { | 294 | if (ret == WL1271_NOTHING_TO_SCAN) { |
283 | wl->scan.state = WL1271_SCAN_STATE_DONE; | 295 | wl->scan.state = WL1271_SCAN_STATE_DONE; |
284 | wl1271_scan_stm(wl); | 296 | wl1271_scan_stm(wl); |
@@ -473,34 +485,86 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl, | |||
473 | cfg->passive[2] || cfg->active[2]; | 485 | cfg->passive[2] || cfg->active[2]; |
474 | } | 486 | } |
475 | 487 | ||
476 | /* Returns 0 if no wildcard is used, 1 if wildcard is used or a | 488 | /* Returns the scan type to be used or a negative value on error */ |
477 | * negative value on error */ | ||
478 | static int | 489 | static int |
479 | wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, | 490 | wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, |
480 | struct cfg80211_sched_scan_request *req) | 491 | struct cfg80211_sched_scan_request *req) |
481 | { | 492 | { |
482 | struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL; | 493 | struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL; |
483 | struct cfg80211_ssid *ssid = req->ssids; | 494 | struct cfg80211_match_set *sets = req->match_sets; |
484 | int ret, wildcard = 0; | 495 | struct cfg80211_ssid *ssids = req->ssids; |
496 | int ret = 0, type, i, j, n_match_ssids = 0; | ||
485 | 497 | ||
486 | wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list"); | 498 | wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list"); |
487 | 499 | ||
500 | /* count the match sets that contain SSIDs */ | ||
501 | for (i = 0; i < req->n_match_sets; i++) | ||
502 | if (sets[i].ssid.ssid_len > 0) | ||
503 | n_match_ssids++; | ||
504 | |||
505 | /* No filter, no ssids or only bcast ssid */ | ||
506 | if (!n_match_ssids && | ||
507 | (!req->n_ssids || | ||
508 | (req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) { | ||
509 | type = SCAN_SSID_FILTER_ANY; | ||
510 | goto out; | ||
511 | } | ||
512 | |||
488 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 513 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
489 | if (!cmd) | 514 | if (!cmd) { |
490 | return -ENOMEM; | 515 | ret = -ENOMEM; |
516 | goto out; | ||
517 | } | ||
518 | |||
519 | if (!n_match_ssids) { | ||
520 | /* No filter, with ssids */ | ||
521 | type = SCAN_SSID_FILTER_DISABLED; | ||
522 | |||
523 | for (i = 0; i < req->n_ssids; i++) { | ||
524 | cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ? | ||
525 | SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC; | ||
526 | cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len; | ||
527 | memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid, | ||
528 | ssids[i].ssid_len); | ||
529 | cmd->n_ssids++; | ||
530 | } | ||
531 | } else { | ||
532 | type = SCAN_SSID_FILTER_LIST; | ||
533 | |||
534 | /* Add all SSIDs from the filters */ | ||
535 | for (i = 0; i < req->n_match_sets; i++) { | ||
536 | /* ignore sets without SSIDs */ | ||
537 | if (!sets[i].ssid.ssid_len) | ||
538 | continue; | ||
491 | 539 | ||
492 | while ((cmd->n_ssids < req->n_ssids) && ssid) { | ||
493 | if (ssid->ssid_len == 0) { | ||
494 | wildcard = 1; | ||
495 | cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC; | 540 | cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC; |
496 | } else { | 541 | cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len; |
497 | cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN; | 542 | memcpy(cmd->ssids[cmd->n_ssids].ssid, |
543 | sets[i].ssid.ssid, sets[i].ssid.ssid_len); | ||
544 | cmd->n_ssids++; | ||
545 | } | ||
546 | if ((req->n_ssids > 1) || | ||
547 | (req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) { | ||
548 | /* | ||
549 | * Mark all the SSIDs passed in the SSID list as HIDDEN, | ||
550 | * so they're used in probe requests. | ||
551 | */ | ||
552 | for (i = 0; i < req->n_ssids; i++) { | ||
553 | for (j = 0; j < cmd->n_ssids; j++) | ||
554 | if (!memcmp(req->ssids[i].ssid, | ||
555 | cmd->ssids[j].ssid, | ||
556 | req->ssids[i].ssid_len)) { | ||
557 | cmd->ssids[j].type = | ||
558 | SCAN_SSID_TYPE_HIDDEN; | ||
559 | break; | ||
560 | } | ||
561 | /* Fail if SSID isn't present in the filters */ | ||
562 | if (j == req->n_ssids) { | ||
563 | ret = -EINVAL; | ||
564 | goto out_free; | ||
565 | } | ||
566 | } | ||
498 | } | 567 | } |
499 | cmd->ssids[cmd->n_ssids].len = ssid->ssid_len; | ||
500 | memcpy(cmd->ssids[cmd->n_ssids].ssid, ssid->ssid, | ||
501 | ssid->ssid_len); | ||
502 | ssid++; | ||
503 | cmd->n_ssids++; | ||
504 | } | 568 | } |
505 | 569 | ||
506 | wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd)); | 570 | wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd)); |
@@ -509,13 +573,15 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, | |||
509 | sizeof(*cmd), 0); | 573 | sizeof(*cmd), 0); |
510 | if (ret < 0) { | 574 | if (ret < 0) { |
511 | wl1271_error("cmd sched scan ssid list failed"); | 575 | wl1271_error("cmd sched scan ssid list failed"); |
512 | goto out; | 576 | goto out_free; |
513 | } | 577 | } |
514 | 578 | ||
515 | ret = wildcard; | 579 | out_free: |
516 | out: | ||
517 | kfree(cmd); | 580 | kfree(cmd); |
518 | return ret; | 581 | out: |
582 | if (ret < 0) | ||
583 | return ret; | ||
584 | return type; | ||
519 | } | 585 | } |
520 | 586 | ||
521 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | 587 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, |
@@ -550,21 +616,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, | |||
550 | cfg->intervals[i] = cpu_to_le32(req->interval); | 616 | cfg->intervals[i] = cpu_to_le32(req->interval); |
551 | 617 | ||
552 | cfg->ssid_len = 0; | 618 | cfg->ssid_len = 0; |
553 | if (req->n_ssids == 0) { | 619 | ret = wl12xx_scan_sched_scan_ssid_list(wl, req); |
554 | wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_ANY"); | 620 | if (ret < 0) |
555 | cfg->filter_type = SCAN_SSID_FILTER_ANY; | 621 | goto out; |
556 | } else { | 622 | |
557 | ret = wl12xx_scan_sched_scan_ssid_list(wl, req); | 623 | cfg->filter_type = ret; |
558 | if (ret < 0) | 624 | |
559 | goto out; | 625 | wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type); |
560 | if (ret) { | ||
561 | wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_DISABLED"); | ||
562 | cfg->filter_type = SCAN_SSID_FILTER_DISABLED; | ||
563 | } else { | ||
564 | wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_LIST"); | ||
565 | cfg->filter_type = SCAN_SSID_FILTER_LIST; | ||
566 | } | ||
567 | } | ||
568 | 626 | ||
569 | if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) { | 627 | if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) { |
570 | wl1271_error("scan channel list is empty"); | 628 | wl1271_error("scan channel list is empty"); |
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c index c3610492852e..f25d5d9212e7 100644 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ b/drivers/net/wireless/wl12xx/sdio_test.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/mmc/sdio_func.h> | 30 | #include <linux/mmc/sdio_func.h> |
31 | #include <linux/mmc/sdio_ids.h> | 31 | #include <linux/mmc/sdio_ids.h> |
32 | #include <linux/mmc/card.h> | 32 | #include <linux/mmc/card.h> |
33 | #include <linux/mmc/host.h> | ||
33 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
34 | #include <linux/wl12xx.h> | 35 | #include <linux/wl12xx.h> |
35 | #include <linux/kthread.h> | 36 | #include <linux/kthread.h> |
@@ -142,14 +143,23 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) | |||
142 | ret = pm_runtime_get_sync(&func->dev); | 143 | ret = pm_runtime_get_sync(&func->dev); |
143 | if (ret < 0) | 144 | if (ret < 0) |
144 | goto out; | 145 | goto out; |
146 | |||
147 | /* Runtime PM might be disabled, power up the card manually */ | ||
148 | ret = mmc_power_restore_host(func->card->host); | ||
149 | if (ret < 0) | ||
150 | goto out; | ||
151 | |||
145 | sdio_claim_host(func); | 152 | sdio_claim_host(func); |
146 | sdio_enable_func(func); | 153 | sdio_enable_func(func); |
147 | sdio_release_host(func); | ||
148 | } else { | 154 | } else { |
149 | sdio_claim_host(func); | ||
150 | sdio_disable_func(func); | 155 | sdio_disable_func(func); |
151 | sdio_release_host(func); | 156 | sdio_release_host(func); |
152 | 157 | ||
158 | /* Runtime PM might be disabled, power off the card manually */ | ||
159 | ret = mmc_power_save_host(func->card->host); | ||
160 | if (ret < 0) | ||
161 | goto out; | ||
162 | |||
153 | /* Power down the card */ | 163 | /* Power down the card */ |
154 | ret = pm_runtime_put_sync(&func->dev); | 164 | ret = pm_runtime_put_sync(&func->dev); |
155 | } | 165 | } |
@@ -433,7 +443,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
433 | 443 | ||
434 | sdio_set_drvdata(func, wl_test); | 444 | sdio_set_drvdata(func, wl_test); |
435 | 445 | ||
436 | |||
437 | /* power up the device */ | 446 | /* power up the device */ |
438 | ret = wl1271_chip_wakeup(wl); | 447 | ret = wl1271_chip_wakeup(wl); |
439 | if (ret) { | 448 | if (ret) { |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 08227e69616b..bad9e29d49b0 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "reg.h" | 30 | #include "reg.h" |
31 | #include "ps.h" | 31 | #include "ps.h" |
32 | #include "tx.h" | 32 | #include "tx.h" |
33 | #include "event.h" | ||
33 | 34 | ||
34 | static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) | 35 | static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) |
35 | { | 36 | { |
@@ -80,8 +81,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, | |||
80 | struct ieee80211_hdr *hdr; | 81 | struct ieee80211_hdr *hdr; |
81 | int ret; | 82 | int ret; |
82 | 83 | ||
83 | hdr = (struct ieee80211_hdr *)(skb->data + | 84 | hdr = (struct ieee80211_hdr *)skb->data; |
84 | sizeof(struct wl1271_tx_hw_descr)); | ||
85 | 85 | ||
86 | /* | 86 | /* |
87 | * stop bssid-based filtering before transmitting authentication | 87 | * stop bssid-based filtering before transmitting authentication |
@@ -125,25 +125,31 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, | |||
125 | 125 | ||
126 | static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) | 126 | static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) |
127 | { | 127 | { |
128 | bool fw_ps; | 128 | bool fw_ps, single_sta; |
129 | u8 tx_pkts; | 129 | u8 tx_pkts; |
130 | 130 | ||
131 | /* only regulate station links */ | 131 | /* only regulate station links */ |
132 | if (hlid < WL1271_AP_STA_HLID_START) | 132 | if (hlid < WL1271_AP_STA_HLID_START) |
133 | return; | 133 | return; |
134 | 134 | ||
135 | if (WARN_ON(!wl1271_is_active_sta(wl, hlid))) | ||
136 | return; | ||
137 | |||
135 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 138 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
136 | tx_pkts = wl->links[hlid].allocated_pkts; | 139 | tx_pkts = wl->links[hlid].allocated_pkts; |
140 | single_sta = (wl->active_sta_count == 1); | ||
137 | 141 | ||
138 | /* | 142 | /* |
139 | * if in FW PS and there is enough data in FW we can put the link | 143 | * if in FW PS and there is enough data in FW we can put the link |
140 | * into high-level PS and clean out its TX queues. | 144 | * into high-level PS and clean out its TX queues. |
145 | * Make an exception if this is the only connected station. In this | ||
146 | * case FW-memory congestion is not a problem. | ||
141 | */ | 147 | */ |
142 | if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 148 | if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) |
143 | wl1271_ps_link_start(wl, hlid, true); | 149 | wl1271_ps_link_start(wl, hlid, true); |
144 | } | 150 | } |
145 | 151 | ||
146 | static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) | 152 | bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) |
147 | { | 153 | { |
148 | return wl->dummy_packet == skb; | 154 | return wl->dummy_packet == skb; |
149 | } | 155 | } |
@@ -174,14 +180,20 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) | |||
174 | 180 | ||
175 | static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) | 181 | static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) |
176 | { | 182 | { |
183 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
184 | |||
177 | if (wl12xx_is_dummy_packet(wl, skb)) | 185 | if (wl12xx_is_dummy_packet(wl, skb)) |
178 | return wl->system_hlid; | 186 | return wl->system_hlid; |
179 | 187 | ||
180 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 188 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
181 | return wl12xx_tx_get_hlid_ap(wl, skb); | 189 | return wl12xx_tx_get_hlid_ap(wl, skb); |
182 | 190 | ||
183 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | 191 | wl1271_tx_update_filters(wl, skb); |
184 | test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) | 192 | |
193 | if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | ||
194 | test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) && | ||
195 | !ieee80211_is_auth(hdr->frame_control) && | ||
196 | !ieee80211_is_assoc_req(hdr->frame_control)) | ||
185 | return wl->sta_hlid; | 197 | return wl->sta_hlid; |
186 | else | 198 | else |
187 | return wl->dev_hlid; | 199 | return wl->dev_hlid; |
@@ -416,8 +428,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
416 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | 428 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
417 | wl1271_tx_ap_update_inconnection_sta(wl, skb); | 429 | wl1271_tx_ap_update_inconnection_sta(wl, skb); |
418 | wl1271_tx_regulate_link(wl, hlid); | 430 | wl1271_tx_regulate_link(wl, hlid); |
419 | } else { | ||
420 | wl1271_tx_update_filters(wl, skb); | ||
421 | } | 431 | } |
422 | 432 | ||
423 | /* | 433 | /* |
@@ -440,20 +450,20 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
440 | return total_len; | 450 | return total_len; |
441 | } | 451 | } |
442 | 452 | ||
443 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | 453 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, |
454 | enum ieee80211_band rate_band) | ||
444 | { | 455 | { |
445 | struct ieee80211_supported_band *band; | 456 | struct ieee80211_supported_band *band; |
446 | u32 enabled_rates = 0; | 457 | u32 enabled_rates = 0; |
447 | int bit; | 458 | int bit; |
448 | 459 | ||
449 | band = wl->hw->wiphy->bands[wl->band]; | 460 | band = wl->hw->wiphy->bands[rate_band]; |
450 | for (bit = 0; bit < band->n_bitrates; bit++) { | 461 | for (bit = 0; bit < band->n_bitrates; bit++) { |
451 | if (rate_set & 0x1) | 462 | if (rate_set & 0x1) |
452 | enabled_rates |= band->bitrates[bit].hw_value; | 463 | enabled_rates |= band->bitrates[bit].hw_value; |
453 | rate_set >>= 1; | 464 | rate_set >>= 1; |
454 | } | 465 | } |
455 | 466 | ||
456 | #ifdef CONFIG_WL12XX_HT | ||
457 | /* MCS rates indication are on bits 16 - 23 */ | 467 | /* MCS rates indication are on bits 16 - 23 */ |
458 | rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates; | 468 | rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates; |
459 | 469 | ||
@@ -462,7 +472,6 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | |||
462 | enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit); | 472 | enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit); |
463 | rate_set >>= 1; | 473 | rate_set >>= 1; |
464 | } | 474 | } |
465 | #endif | ||
466 | 475 | ||
467 | return enabled_rates; | 476 | return enabled_rates; |
468 | } | 477 | } |
@@ -886,6 +895,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
886 | /* TX failure */ | 895 | /* TX failure */ |
887 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | 896 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
888 | for (i = 0; i < AP_MAX_LINKS; i++) { | 897 | for (i = 0; i < AP_MAX_LINKS; i++) { |
898 | wl1271_free_sta(wl, i); | ||
889 | wl1271_tx_reset_link_queues(wl, i); | 899 | wl1271_tx_reset_link_queues(wl, i); |
890 | wl->links[i].allocated_pkts = 0; | 900 | wl->links[i].allocated_pkts = 0; |
891 | wl->links[i].prev_freed_pkts = 0; | 901 | wl->links[i].prev_freed_pkts = 0; |
@@ -905,10 +915,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) | |||
905 | ieee80211_tx_status_ni(wl->hw, skb); | 915 | ieee80211_tx_status_ni(wl->hw, skb); |
906 | } | 916 | } |
907 | } | 917 | } |
908 | wl->tx_queue_count[i] = 0; | ||
909 | } | 918 | } |
919 | |||
920 | wl->ba_rx_bitmap = 0; | ||
910 | } | 921 | } |
911 | 922 | ||
923 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
924 | wl->tx_queue_count[i] = 0; | ||
925 | |||
912 | wl->stopped_queues_map = 0; | 926 | wl->stopped_queues_map = 0; |
913 | 927 | ||
914 | /* | 928 | /* |
@@ -976,20 +990,10 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
976 | wl1271_warning("Unable to flush all TX buffers, timed out."); | 990 | wl1271_warning("Unable to flush all TX buffers, timed out."); |
977 | } | 991 | } |
978 | 992 | ||
979 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl) | 993 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) |
980 | { | 994 | { |
981 | int i; | 995 | if (WARN_ON(!rate_set)) |
982 | u32 rate = 0; | 996 | return 0; |
983 | |||
984 | if (!wl->basic_rate_set) { | ||
985 | WARN_ON(1); | ||
986 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
987 | } | ||
988 | |||
989 | for (i = 0; !rate; i++) { | ||
990 | if ((wl->basic_rate_set >> i) & 0x1) | ||
991 | rate = 1 << i; | ||
992 | } | ||
993 | 997 | ||
994 | return rate; | 998 | return BIT(__ffs(rate_set)); |
995 | } | 999 | } |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 6519be4b2c38..dc4f09adf088 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -209,10 +209,15 @@ void wl1271_tx_complete(struct wl1271 *wl); | |||
209 | void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); | 209 | void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); |
210 | void wl1271_tx_flush(struct wl1271 *wl); | 210 | void wl1271_tx_flush(struct wl1271 *wl); |
211 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 211 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
212 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | 212 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, |
213 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl); | 213 | enum ieee80211_band rate_band); |
214 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); | ||
214 | u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); | 215 | u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); |
215 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); | 216 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); |
216 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl); | 217 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl); |
218 | bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); | ||
219 | |||
220 | /* from main.c */ | ||
221 | void wl1271_free_sta(struct wl1271 *wl, u8 hlid); | ||
217 | 222 | ||
218 | #endif | 223 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index fb2753c46300..997f53245011 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -138,7 +138,7 @@ extern u32 wl12xx_debug_level; | |||
138 | #define WL1271_DEFAULT_DTIM_PERIOD 1 | 138 | #define WL1271_DEFAULT_DTIM_PERIOD 1 |
139 | 139 | ||
140 | #define WL12XX_MAX_ROLES 4 | 140 | #define WL12XX_MAX_ROLES 4 |
141 | #define WL12XX_MAX_LINKS 8 | 141 | #define WL12XX_MAX_LINKS 12 |
142 | #define WL12XX_INVALID_ROLE_ID 0xff | 142 | #define WL12XX_INVALID_ROLE_ID 0xff |
143 | #define WL12XX_INVALID_LINK_ID 0xff | 143 | #define WL12XX_INVALID_LINK_ID 0xff |
144 | 144 | ||
@@ -234,14 +234,14 @@ struct wl1271_stats { | |||
234 | #define NUM_TX_QUEUES 4 | 234 | #define NUM_TX_QUEUES 4 |
235 | #define NUM_RX_PKT_DESC 8 | 235 | #define NUM_RX_PKT_DESC 8 |
236 | 236 | ||
237 | #define AP_MAX_STATIONS 5 | 237 | #define AP_MAX_STATIONS 8 |
238 | 238 | ||
239 | /* Broadcast and Global links + system link + links to stations */ | 239 | /* Broadcast and Global links + system link + links to stations */ |
240 | /* | 240 | /* |
241 | * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all | 241 | * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all |
242 | * the places that use this. | 242 | * the places that use this. |
243 | */ | 243 | */ |
244 | #define AP_MAX_LINKS (AP_MAX_STATIONS + 3) | 244 | #define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START) |
245 | 245 | ||
246 | /* FW status registers */ | 246 | /* FW status registers */ |
247 | struct wl12xx_fw_status { | 247 | struct wl12xx_fw_status { |
@@ -279,7 +279,7 @@ struct wl12xx_fw_status { | |||
279 | 279 | ||
280 | /* Cumulative counter of released Voice memory blocks */ | 280 | /* Cumulative counter of released Voice memory blocks */ |
281 | u8 tx_voice_released_blks; | 281 | u8 tx_voice_released_blks; |
282 | u8 padding_1[7]; | 282 | u8 padding_1[3]; |
283 | __le32 log_start_addr; | 283 | __le32 log_start_addr; |
284 | } __packed; | 284 | } __packed; |
285 | 285 | ||
@@ -402,6 +402,7 @@ struct wl1271 { | |||
402 | u8 mac_addr[ETH_ALEN]; | 402 | u8 mac_addr[ETH_ALEN]; |
403 | u8 bss_type; | 403 | u8 bss_type; |
404 | u8 set_bss_type; | 404 | u8 set_bss_type; |
405 | u8 p2p; /* we are using p2p role */ | ||
405 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | 406 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; |
406 | u8 ssid_len; | 407 | u8 ssid_len; |
407 | int channel; | 408 | int channel; |
@@ -525,6 +526,7 @@ struct wl1271 { | |||
525 | u32 basic_rate_set; | 526 | u32 basic_rate_set; |
526 | u32 basic_rate; | 527 | u32 basic_rate; |
527 | u32 rate_set; | 528 | u32 rate_set; |
529 | u32 bitrate_masks[IEEE80211_NUM_BANDS]; | ||
528 | 530 | ||
529 | /* The current band */ | 531 | /* The current band */ |
530 | enum ieee80211_band band; | 532 | enum ieee80211_band band; |
@@ -626,6 +628,9 @@ struct wl1271 { | |||
626 | 628 | ||
627 | /* number of currently active RX BA sessions */ | 629 | /* number of currently active RX BA sessions */ |
628 | int ba_rx_session_count; | 630 | int ba_rx_session_count; |
631 | |||
632 | /* AP-mode - number of currently connected stations */ | ||
633 | int active_sta_count; | ||
629 | }; | 634 | }; |
630 | 635 | ||
631 | struct wl1271_station { | 636 | struct wl1271_station { |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 6bc7c92fbff7..98fbf54f6004 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -1781,7 +1781,7 @@ static int wl3501_get_encode(struct net_device *dev, | |||
1781 | keys, len_keys); | 1781 | keys, len_keys); |
1782 | if (rc) | 1782 | if (rc) |
1783 | goto out; | 1783 | goto out; |
1784 | tocopy = min_t(u8, len_keys, wrqu->encoding.length); | 1784 | tocopy = min_t(u16, len_keys, wrqu->encoding.length); |
1785 | tocopy = min_t(u8, tocopy, 100); | 1785 | tocopy = min_t(u8, tocopy, 100); |
1786 | wrqu->encoding.length = tocopy; | 1786 | wrqu->encoding.length = tocopy; |
1787 | memcpy(extra, keys, tocopy); | 1787 | memcpy(extra, keys, tocopy); |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index cabfae1e70b1..0a70149df3fc 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -1332,7 +1332,7 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1332 | } | 1332 | } |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | static u64 zd_op_get_tsf(struct ieee80211_hw *hw) | 1335 | static u64 zd_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
1336 | { | 1336 | { |
1337 | struct zd_mac *mac = zd_hw_mac(hw); | 1337 | struct zd_mac *mac = zd_hw_mac(hw); |
1338 | return zd_chip_get_tsf(&mac->chip); | 1338 | return zd_chip_get_tsf(&mac->chip); |