diff options
186 files changed, 8572 insertions, 4414 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 5faf685ee6c2..65ca7eae6276 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3426,7 +3426,7 @@ M: Wey-Yi Guy <wey-yi.w.guy@intel.com> | |||
3426 | M: Intel Linux Wireless <ilw@linux.intel.com> | 3426 | M: Intel Linux Wireless <ilw@linux.intel.com> |
3427 | L: linux-wireless@vger.kernel.org | 3427 | L: linux-wireless@vger.kernel.org |
3428 | W: http://intellinuxwireless.org | 3428 | W: http://intellinuxwireless.org |
3429 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git | 3429 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git |
3430 | S: Supported | 3430 | S: Supported |
3431 | F: drivers/net/wireless/iwlwifi/ | 3431 | F: drivers/net/wireless/iwlwifi/ |
3432 | 3432 | ||
@@ -4528,7 +4528,7 @@ L: linux-wireless@vger.kernel.org | |||
4528 | S: Maintained | 4528 | S: Maintained |
4529 | F: net/nfc/ | 4529 | F: net/nfc/ |
4530 | F: include/linux/nfc.h | 4530 | F: include/linux/nfc.h |
4531 | F: include/net/nfc.h | 4531 | F: include/net/nfc/ |
4532 | F: drivers/nfc/ | 4532 | F: drivers/nfc/ |
4533 | 4533 | ||
4534 | NFS, SUNRPC, AND LOCKD CLIENTS | 4534 | NFS, SUNRPC, AND LOCKD CLIENTS |
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 4bc10aa57bd4..2968d809d49f 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -18,20 +18,40 @@ static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) | |||
18 | return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | 18 | return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); |
19 | } | 19 | } |
20 | 20 | ||
21 | static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, | 21 | void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) |
22 | u32 offset, u32 mask, u32 set) | ||
23 | { | 22 | { |
24 | u32 value; | 23 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); |
24 | bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | ||
25 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); | ||
26 | } | ||
27 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); | ||
25 | 28 | ||
26 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); | 29 | void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, |
30 | u32 set) | ||
31 | { | ||
32 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | ||
33 | bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | ||
34 | bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set); | ||
35 | } | ||
36 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); | ||
37 | |||
38 | void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, | ||
39 | u32 offset, u32 mask, u32 set) | ||
40 | { | ||
27 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); | 41 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); |
28 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); | 42 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); |
29 | value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); | 43 | bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set); |
30 | value &= mask; | 44 | } |
31 | value |= set; | 45 | EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); |
32 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value); | 46 | |
33 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); | 47 | void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, |
48 | u32 set) | ||
49 | { | ||
50 | bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset); | ||
51 | bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR); | ||
52 | bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set); | ||
34 | } | 53 | } |
54 | EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); | ||
35 | 55 | ||
36 | static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) | 56 | static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) |
37 | { | 57 | { |
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); |
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 2acff4307ca4..5af959274d4e 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
@@ -27,4 +27,15 @@ config NFC_PN533 | |||
27 | Say Y here to compile support for PN533 devices into the | 27 | Say Y here to compile support for PN533 devices into the |
28 | kernel or say M to compile it as module (pn533). | 28 | kernel or say M to compile it as module (pn533). |
29 | 29 | ||
30 | config NFC_WILINK | ||
31 | tristate "Texas Instruments NFC WiLink driver" | ||
32 | depends on TI_ST && NFC_NCI | ||
33 | help | ||
34 | This enables the NFC driver for Texas Instrument's BT/FM/GPS/NFC | ||
35 | combo devices. This makes use of shared transport line discipline | ||
36 | core driver to communicate with the NFC core of the combo chip. | ||
37 | |||
38 | Say Y here to compile support for Texas Instrument's NFC WiLink driver | ||
39 | into the kernel or say M to compile it as module. | ||
40 | |||
30 | endmenu | 41 | endmenu |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 8ef446d2c1bd..ab99e8572f02 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
@@ -4,5 +4,6 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_PN544_NFC) += pn544.o | 5 | obj-$(CONFIG_PN544_NFC) += pn544.o |
6 | obj-$(CONFIG_NFC_PN533) += pn533.o | 6 | obj-$(CONFIG_NFC_PN533) += pn533.o |
7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o | ||
7 | 8 | ||
8 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG | 9 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG |
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c new file mode 100644 index 000000000000..5b0f1ff80361 --- /dev/null +++ b/drivers/nfc/nfcwilink.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * Texas Instrument's NFC Driver For Shared Transport. | ||
3 | * | ||
4 | * NFC Driver acts as interface between NCI core and | ||
5 | * TI Shared Transport Layer. | ||
6 | * | ||
7 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
8 | * | ||
9 | * Written by Ilan Elias <ilane@ti.com> | ||
10 | * | ||
11 | * Acknowledgements: | ||
12 | * This file is based on btwilink.c, which was written | ||
13 | * by Raja Mani and Pavan Savoy. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License version 2 as | ||
17 | * published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
27 | * | ||
28 | */ | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/nfc.h> | ||
31 | #include <net/nfc/nci.h> | ||
32 | #include <net/nfc/nci_core.h> | ||
33 | #include <linux/ti_wilink_st.h> | ||
34 | |||
35 | #define NFCWILINK_CHNL 12 | ||
36 | #define NFCWILINK_OPCODE 7 | ||
37 | #define NFCWILINK_MAX_FRAME_SIZE 300 | ||
38 | #define NFCWILINK_HDR_LEN 4 | ||
39 | #define NFCWILINK_OFFSET_LEN_IN_HDR 1 | ||
40 | #define NFCWILINK_LEN_SIZE 2 | ||
41 | #define NFCWILINK_REGISTER_TIMEOUT 8000 /* 8 sec */ | ||
42 | |||
43 | struct nfcwilink_hdr { | ||
44 | u8 chnl; | ||
45 | u8 opcode; | ||
46 | u16 len; | ||
47 | } __packed; | ||
48 | |||
49 | struct nfcwilink { | ||
50 | struct platform_device *pdev; | ||
51 | struct nci_dev *ndev; | ||
52 | unsigned long flags; | ||
53 | |||
54 | char st_register_cb_status; | ||
55 | long (*st_write) (struct sk_buff *); | ||
56 | struct completion st_register_completed; | ||
57 | }; | ||
58 | |||
59 | /* NFCWILINK driver flags */ | ||
60 | enum { | ||
61 | NFCWILINK_RUNNING, | ||
62 | }; | ||
63 | |||
64 | /* Called by ST when registration is complete */ | ||
65 | static void nfcwilink_register_complete(void *priv_data, char data) | ||
66 | { | ||
67 | struct nfcwilink *drv = priv_data; | ||
68 | |||
69 | nfc_dev_dbg(&drv->pdev->dev, "register_complete entry"); | ||
70 | |||
71 | /* store ST registration status */ | ||
72 | drv->st_register_cb_status = data; | ||
73 | |||
74 | /* complete the wait in nfc_st_open() */ | ||
75 | complete(&drv->st_register_completed); | ||
76 | } | ||
77 | |||
78 | /* Called by ST when receive data is available */ | ||
79 | static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) | ||
80 | { | ||
81 | struct nfcwilink *drv = priv_data; | ||
82 | int rc; | ||
83 | |||
84 | nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len); | ||
85 | |||
86 | if (!skb) | ||
87 | return -EFAULT; | ||
88 | |||
89 | if (!drv) { | ||
90 | kfree_skb(skb); | ||
91 | return -EFAULT; | ||
92 | } | ||
93 | |||
94 | /* strip the ST header | ||
95 | (apart for the chnl byte, which is not received in the hdr) */ | ||
96 | skb_pull(skb, (NFCWILINK_HDR_LEN-1)); | ||
97 | |||
98 | skb->dev = (void *) drv->ndev; | ||
99 | |||
100 | /* Forward skb to NCI core layer */ | ||
101 | rc = nci_recv_frame(skb); | ||
102 | if (rc < 0) { | ||
103 | nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc); | ||
104 | return rc; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /* protocol structure registered with ST */ | ||
111 | static struct st_proto_s nfcwilink_proto = { | ||
112 | .chnl_id = NFCWILINK_CHNL, | ||
113 | .max_frame_size = NFCWILINK_MAX_FRAME_SIZE, | ||
114 | .hdr_len = (NFCWILINK_HDR_LEN-1), /* not including chnl byte */ | ||
115 | .offset_len_in_hdr = NFCWILINK_OFFSET_LEN_IN_HDR, | ||
116 | .len_size = NFCWILINK_LEN_SIZE, | ||
117 | .reserve = 0, | ||
118 | .recv = nfcwilink_receive, | ||
119 | .reg_complete_cb = nfcwilink_register_complete, | ||
120 | .write = NULL, | ||
121 | }; | ||
122 | |||
123 | static int nfcwilink_open(struct nci_dev *ndev) | ||
124 | { | ||
125 | struct nfcwilink *drv = nci_get_drvdata(ndev); | ||
126 | unsigned long comp_ret; | ||
127 | int rc; | ||
128 | |||
129 | nfc_dev_dbg(&drv->pdev->dev, "open entry"); | ||
130 | |||
131 | if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) { | ||
132 | rc = -EBUSY; | ||
133 | goto exit; | ||
134 | } | ||
135 | |||
136 | nfcwilink_proto.priv_data = drv; | ||
137 | |||
138 | init_completion(&drv->st_register_completed); | ||
139 | drv->st_register_cb_status = -EINPROGRESS; | ||
140 | |||
141 | rc = st_register(&nfcwilink_proto); | ||
142 | if (rc < 0) { | ||
143 | if (rc == -EINPROGRESS) { | ||
144 | comp_ret = wait_for_completion_timeout( | ||
145 | &drv->st_register_completed, | ||
146 | msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT)); | ||
147 | |||
148 | nfc_dev_dbg(&drv->pdev->dev, | ||
149 | "wait_for_completion_timeout returned %ld", | ||
150 | comp_ret); | ||
151 | |||
152 | if (comp_ret == 0) { | ||
153 | /* timeout */ | ||
154 | rc = -ETIMEDOUT; | ||
155 | goto clear_exit; | ||
156 | } else if (drv->st_register_cb_status != 0) { | ||
157 | rc = drv->st_register_cb_status; | ||
158 | nfc_dev_err(&drv->pdev->dev, | ||
159 | "st_register_cb failed %d", rc); | ||
160 | goto clear_exit; | ||
161 | } | ||
162 | } else { | ||
163 | nfc_dev_err(&drv->pdev->dev, | ||
164 | "st_register failed %d", rc); | ||
165 | goto clear_exit; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /* st_register MUST fill the write callback */ | ||
170 | BUG_ON(nfcwilink_proto.write == NULL); | ||
171 | drv->st_write = nfcwilink_proto.write; | ||
172 | |||
173 | goto exit; | ||
174 | |||
175 | clear_exit: | ||
176 | clear_bit(NFCWILINK_RUNNING, &drv->flags); | ||
177 | |||
178 | exit: | ||
179 | return rc; | ||
180 | } | ||
181 | |||
182 | static int nfcwilink_close(struct nci_dev *ndev) | ||
183 | { | ||
184 | struct nfcwilink *drv = nci_get_drvdata(ndev); | ||
185 | int rc; | ||
186 | |||
187 | nfc_dev_dbg(&drv->pdev->dev, "close entry"); | ||
188 | |||
189 | if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags)) | ||
190 | return 0; | ||
191 | |||
192 | rc = st_unregister(&nfcwilink_proto); | ||
193 | if (rc) | ||
194 | nfc_dev_err(&drv->pdev->dev, "st_unregister failed %d", rc); | ||
195 | |||
196 | drv->st_write = NULL; | ||
197 | |||
198 | return rc; | ||
199 | } | ||
200 | |||
201 | static int nfcwilink_send(struct sk_buff *skb) | ||
202 | { | ||
203 | struct nci_dev *ndev = (struct nci_dev *)skb->dev; | ||
204 | struct nfcwilink *drv = nci_get_drvdata(ndev); | ||
205 | struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000}; | ||
206 | long len; | ||
207 | |||
208 | nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len); | ||
209 | |||
210 | if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) | ||
211 | return -EBUSY; | ||
212 | |||
213 | /* add the ST hdr to the start of the buffer */ | ||
214 | hdr.len = skb->len; | ||
215 | memcpy(skb_push(skb, NFCWILINK_HDR_LEN), &hdr, NFCWILINK_HDR_LEN); | ||
216 | |||
217 | /* Insert skb to shared transport layer's transmit queue. | ||
218 | * Freeing skb memory is taken care in shared transport layer, | ||
219 | * so don't free skb memory here. | ||
220 | */ | ||
221 | len = drv->st_write(skb); | ||
222 | if (len < 0) { | ||
223 | kfree_skb(skb); | ||
224 | nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len); | ||
225 | return -EFAULT; | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static struct nci_ops nfcwilink_ops = { | ||
232 | .open = nfcwilink_open, | ||
233 | .close = nfcwilink_close, | ||
234 | .send = nfcwilink_send, | ||
235 | }; | ||
236 | |||
237 | static int nfcwilink_probe(struct platform_device *pdev) | ||
238 | { | ||
239 | static struct nfcwilink *drv; | ||
240 | int rc; | ||
241 | u32 protocols; | ||
242 | |||
243 | nfc_dev_dbg(&pdev->dev, "probe entry"); | ||
244 | |||
245 | drv = kzalloc(sizeof(struct nfcwilink), GFP_KERNEL); | ||
246 | if (!drv) { | ||
247 | rc = -ENOMEM; | ||
248 | goto exit; | ||
249 | } | ||
250 | |||
251 | drv->pdev = pdev; | ||
252 | |||
253 | protocols = NFC_PROTO_JEWEL_MASK | ||
254 | | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK | ||
255 | | NFC_PROTO_ISO14443_MASK | ||
256 | | NFC_PROTO_NFC_DEP_MASK; | ||
257 | |||
258 | drv->ndev = nci_allocate_device(&nfcwilink_ops, | ||
259 | protocols, | ||
260 | NFCWILINK_HDR_LEN, | ||
261 | 0); | ||
262 | if (!drv->ndev) { | ||
263 | nfc_dev_err(&pdev->dev, "nci_allocate_device failed"); | ||
264 | rc = -ENOMEM; | ||
265 | goto free_exit; | ||
266 | } | ||
267 | |||
268 | nci_set_parent_dev(drv->ndev, &pdev->dev); | ||
269 | nci_set_drvdata(drv->ndev, drv); | ||
270 | |||
271 | rc = nci_register_device(drv->ndev); | ||
272 | if (rc < 0) { | ||
273 | nfc_dev_err(&pdev->dev, "nci_register_device failed %d", rc); | ||
274 | goto free_dev_exit; | ||
275 | } | ||
276 | |||
277 | dev_set_drvdata(&pdev->dev, drv); | ||
278 | |||
279 | goto exit; | ||
280 | |||
281 | free_dev_exit: | ||
282 | nci_free_device(drv->ndev); | ||
283 | |||
284 | free_exit: | ||
285 | kfree(drv); | ||
286 | |||
287 | exit: | ||
288 | return rc; | ||
289 | } | ||
290 | |||
291 | static int nfcwilink_remove(struct platform_device *pdev) | ||
292 | { | ||
293 | struct nfcwilink *drv = dev_get_drvdata(&pdev->dev); | ||
294 | struct nci_dev *ndev; | ||
295 | |||
296 | nfc_dev_dbg(&pdev->dev, "remove entry"); | ||
297 | |||
298 | if (!drv) | ||
299 | return -EFAULT; | ||
300 | |||
301 | ndev = drv->ndev; | ||
302 | |||
303 | nci_unregister_device(ndev); | ||
304 | nci_free_device(ndev); | ||
305 | |||
306 | kfree(drv); | ||
307 | |||
308 | dev_set_drvdata(&pdev->dev, NULL); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static struct platform_driver nfcwilink_driver = { | ||
314 | .probe = nfcwilink_probe, | ||
315 | .remove = nfcwilink_remove, | ||
316 | .driver = { | ||
317 | .name = "nfcwilink", | ||
318 | .owner = THIS_MODULE, | ||
319 | }, | ||
320 | }; | ||
321 | |||
322 | /* ------- Module Init/Exit interfaces ------ */ | ||
323 | static int __init nfcwilink_init(void) | ||
324 | { | ||
325 | printk(KERN_INFO "NFC Driver for TI WiLink"); | ||
326 | |||
327 | return platform_driver_register(&nfcwilink_driver); | ||
328 | } | ||
329 | |||
330 | static void __exit nfcwilink_exit(void) | ||
331 | { | ||
332 | platform_driver_unregister(&nfcwilink_driver); | ||
333 | } | ||
334 | |||
335 | module_init(nfcwilink_init); | ||
336 | module_exit(nfcwilink_exit); | ||
337 | |||
338 | /* ------ Module Info ------ */ | ||
339 | |||
340 | MODULE_AUTHOR("Ilan Elias <ilane@ti.com>"); | ||
341 | MODULE_DESCRIPTION("NFC Driver for TI Shared Transport"); | ||
342 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index f81a93e5b59d..7bcb1febef0d 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
29 | #include <linux/nfc.h> | 29 | #include <linux/nfc.h> |
30 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
31 | #include <net/nfc.h> | 31 | #include <net/nfc/nfc.h> |
32 | 32 | ||
33 | #define VERSION "0.1" | 33 | #define VERSION "0.1" |
34 | 34 | ||
@@ -1432,6 +1432,8 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | |||
1432 | } | 1432 | } |
1433 | 1433 | ||
1434 | struct nfc_ops pn533_nfc_ops = { | 1434 | struct nfc_ops pn533_nfc_ops = { |
1435 | .dev_up = NULL, | ||
1436 | .dev_down = NULL, | ||
1435 | .start_poll = pn533_start_poll, | 1437 | .start_poll = pn533_start_poll, |
1436 | .stop_poll = pn533_stop_poll, | 1438 | .stop_poll = pn533_stop_poll, |
1437 | .activate_target = pn533_activate_target, | 1439 | .activate_target = pn533_activate_target, |
diff --git a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c index d6de44e430d3..315dd91800b6 100644 --- a/drivers/staging/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/staging/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -133,7 +133,8 @@ static int brcms_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | |||
133 | bool set); | 133 | bool set); |
134 | static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw); | 134 | static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw); |
135 | static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw); | 135 | static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw); |
136 | static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf); | 136 | static void brcms_ops_set_tsf(struct ieee80211_hw *hw, |
137 | struct ieee80211_vif *vif, u64 tsf); | ||
137 | static int brcms_ops_get_stats(struct ieee80211_hw *hw, | 138 | static int brcms_ops_get_stats(struct ieee80211_hw *hw, |
138 | struct ieee80211_low_level_stats *stats); | 139 | struct ieee80211_low_level_stats *stats); |
139 | static void brcms_ops_sta_notify(struct ieee80211_hw *hw, | 140 | static void brcms_ops_sta_notify(struct ieee80211_hw *hw, |
@@ -142,7 +143,8 @@ static void brcms_ops_sta_notify(struct ieee80211_hw *hw, | |||
142 | struct ieee80211_sta *sta); | 143 | struct ieee80211_sta *sta); |
143 | static int brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, | 144 | static int brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, |
144 | const struct ieee80211_tx_queue_params *params); | 145 | const struct ieee80211_tx_queue_params *params); |
145 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw); | 146 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, |
147 | struct ieee80211_vif *vif); | ||
146 | static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 148 | static int brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
147 | struct ieee80211_sta *sta); | 149 | struct ieee80211_sta *sta); |
148 | static int brcms_ops_sta_remove(struct ieee80211_hw *hw, | 150 | static int brcms_ops_sta_remove(struct ieee80211_hw *hw, |
@@ -516,7 +518,8 @@ static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) | |||
516 | return; | 518 | return; |
517 | } | 519 | } |
518 | 520 | ||
519 | static void brcms_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 521 | static void brcms_ops_set_tsf(struct ieee80211_hw *hw, |
522 | struct ieee80211_vif *vif, u64 tsf) | ||
520 | { | 523 | { |
521 | wiphy_err(hw->wiphy, "%s: Enter\n", __func__); | 524 | wiphy_err(hw->wiphy, "%s: Enter\n", __func__); |
522 | return; | 525 | return; |
@@ -565,7 +568,8 @@ brcms_ops_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
565 | return 0; | 568 | return 0; |
566 | } | 569 | } |
567 | 570 | ||
568 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw) | 571 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, |
572 | struct ieee80211_vif *vif) | ||
569 | { | 573 | { |
570 | wiphy_err(hw->wiphy, "%s: Enter\n", __func__); | 574 | wiphy_err(hw->wiphy, "%s: Enter\n", __func__); |
571 | return 0; | 575 | return 0; |
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index 3724e1e67ec2..a2e8bd452ed9 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c | |||
@@ -277,7 +277,7 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed) | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | static u64 wbsoft_get_tsf(struct ieee80211_hw *dev) | 280 | static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) |
281 | { | 281 | { |
282 | printk("wbsoft_get_tsf called\n"); | 282 | printk("wbsoft_get_tsf called\n"); |
283 | return 0; | 283 | return 0; |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index a7ae33d06f24..1526d965ed06 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -378,4 +378,13 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value); | |||
378 | /* PMU support */ | 378 | /* PMU support */ |
379 | extern void bcma_pmu_init(struct bcma_drv_cc *cc); | 379 | extern void bcma_pmu_init(struct bcma_drv_cc *cc); |
380 | 380 | ||
381 | extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, | ||
382 | u32 value); | ||
383 | extern void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, | ||
384 | u32 mask, u32 set); | ||
385 | extern void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, | ||
386 | u32 offset, u32 mask, u32 set); | ||
387 | extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, | ||
388 | u32 offset, u32 mask, u32 set); | ||
389 | |||
381 | #endif /* LINUX_BCMA_DRIVER_CC_H_ */ | 390 | #endif /* LINUX_BCMA_DRIVER_CC_H_ */ |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 72f3933938c0..b5e0a5c344fd 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -777,6 +777,13 @@ struct ieee80211_mmie { | |||
777 | u8 mic[8]; | 777 | u8 mic[8]; |
778 | } __attribute__ ((packed)); | 778 | } __attribute__ ((packed)); |
779 | 779 | ||
780 | struct ieee80211_vendor_ie { | ||
781 | u8 element_id; | ||
782 | u8 len; | ||
783 | u8 oui[3]; | ||
784 | u8 oui_type; | ||
785 | } __packed; | ||
786 | |||
780 | /* Control frames */ | 787 | /* Control frames */ |
781 | struct ieee80211_rts { | 788 | struct ieee80211_rts { |
782 | __le16 frame_control; | 789 | __le16 frame_control; |
@@ -1470,6 +1477,9 @@ enum ieee80211_sa_query_action { | |||
1470 | 1477 | ||
1471 | #define WLAN_PMKID_LEN 16 | 1478 | #define WLAN_PMKID_LEN 16 |
1472 | 1479 | ||
1480 | #define WLAN_OUI_WFA 0x506f9a | ||
1481 | #define WLAN_OUI_TYPE_WFA_P2P 9 | ||
1482 | |||
1473 | /* | 1483 | /* |
1474 | * WMM/802.11e Tspec Element | 1484 | * WMM/802.11e Tspec Element |
1475 | */ | 1485 | */ |
diff --git a/include/linux/nfc.h b/include/linux/nfc.h index c525e0b5876b..36cb955b05cc 100644 --- a/include/linux/nfc.h +++ b/include/linux/nfc.h | |||
@@ -39,6 +39,10 @@ | |||
39 | * | 39 | * |
40 | * @NFC_CMD_GET_DEVICE: request information about a device (requires | 40 | * @NFC_CMD_GET_DEVICE: request information about a device (requires |
41 | * %NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices | 41 | * %NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices |
42 | * @NFC_CMD_DEV_UP: turn on the nfc device | ||
43 | * (requires %NFC_ATTR_DEVICE_INDEX) | ||
44 | * @NFC_CMD_DEV_DOWN: turn off the nfc device | ||
45 | * (requires %NFC_ATTR_DEVICE_INDEX) | ||
42 | * @NFC_CMD_START_POLL: start polling for targets using the given protocols | 46 | * @NFC_CMD_START_POLL: start polling for targets using the given protocols |
43 | * (requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS) | 47 | * (requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS) |
44 | * @NFC_CMD_STOP_POLL: stop polling for targets (requires | 48 | * @NFC_CMD_STOP_POLL: stop polling for targets (requires |
@@ -56,6 +60,8 @@ | |||
56 | enum nfc_commands { | 60 | enum nfc_commands { |
57 | NFC_CMD_UNSPEC, | 61 | NFC_CMD_UNSPEC, |
58 | NFC_CMD_GET_DEVICE, | 62 | NFC_CMD_GET_DEVICE, |
63 | NFC_CMD_DEV_UP, | ||
64 | NFC_CMD_DEV_DOWN, | ||
59 | NFC_CMD_START_POLL, | 65 | NFC_CMD_START_POLL, |
60 | NFC_CMD_STOP_POLL, | 66 | NFC_CMD_STOP_POLL, |
61 | NFC_CMD_GET_TARGET, | 67 | NFC_CMD_GET_TARGET, |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f17307590e61..c73582fb9d20 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -238,6 +238,8 @@ | |||
238 | * | 238 | * |
239 | * @NL80211_CMD_GET_SCAN: get scan results | 239 | * @NL80211_CMD_GET_SCAN: get scan results |
240 | * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters | 240 | * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters |
241 | * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the | ||
242 | * probe requests at CCK rate or not. | ||
241 | * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to | 243 | * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to |
242 | * NL80211_CMD_GET_SCAN and on the "scan" multicast group) | 244 | * NL80211_CMD_GET_SCAN and on the "scan" multicast group) |
243 | * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, | 245 | * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, |
@@ -432,6 +434,8 @@ | |||
432 | * specified using %NL80211_ATTR_DURATION. When called, this operation | 434 | * specified using %NL80211_ATTR_DURATION. When called, this operation |
433 | * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the | 435 | * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the |
434 | * TX status event pertaining to the TX request. | 436 | * TX status event pertaining to the TX request. |
437 | * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the | ||
438 | * management frames at CCK rate or not in 2GHz band. | ||
435 | * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this | 439 | * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this |
436 | * command may be used with the corresponding cookie to cancel the wait | 440 | * command may be used with the corresponding cookie to cancel the wait |
437 | * time if it is known that it is no longer necessary. | 441 | * time if it is known that it is no longer necessary. |
@@ -499,6 +503,9 @@ | |||
499 | * this command may also be sent by the driver as an MLME event to | 503 | * this command may also be sent by the driver as an MLME event to |
500 | * inform userspace of the new replay counter. | 504 | * inform userspace of the new replay counter. |
501 | * | 505 | * |
506 | * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace | ||
507 | * of PMKSA caching dandidates. | ||
508 | * | ||
502 | * @NL80211_CMD_MAX: highest used command number | 509 | * @NL80211_CMD_MAX: highest used command number |
503 | * @__NL80211_CMD_AFTER_LAST: internal use | 510 | * @__NL80211_CMD_AFTER_LAST: internal use |
504 | */ | 511 | */ |
@@ -623,6 +630,8 @@ enum nl80211_commands { | |||
623 | 630 | ||
624 | NL80211_CMD_SET_REKEY_OFFLOAD, | 631 | NL80211_CMD_SET_REKEY_OFFLOAD, |
625 | 632 | ||
633 | NL80211_CMD_PMKSA_CANDIDATE, | ||
634 | |||
626 | /* add new commands above here */ | 635 | /* add new commands above here */ |
627 | 636 | ||
628 | /* used to define NL80211_CMD_MAX below */ | 637 | /* used to define NL80211_CMD_MAX below */ |
@@ -1070,6 +1079,16 @@ enum nl80211_commands { | |||
1070 | * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of | 1079 | * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of |
1071 | * roaming to another AP in the same ESS if the signal lever is low. | 1080 | * roaming to another AP in the same ESS if the signal lever is low. |
1072 | * | 1081 | * |
1082 | * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching | ||
1083 | * candidate information, see &enum nl80211_pmksa_candidate_attr. | ||
1084 | * | ||
1085 | * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not | ||
1086 | * for management frames transmission. In order to avoid p2p probe/action | ||
1087 | * frames are being transmitted at CCK rate in 2GHz band, the user space | ||
1088 | * applications use this attribute. | ||
1089 | * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and | ||
1090 | * %NL80211_CMD_FRAME commands. | ||
1091 | * | ||
1073 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1092 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1074 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1093 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1075 | */ | 1094 | */ |
@@ -1288,6 +1307,10 @@ enum nl80211_attrs { | |||
1288 | NL80211_ATTR_SCHED_SCAN_MATCH, | 1307 | NL80211_ATTR_SCHED_SCAN_MATCH, |
1289 | NL80211_ATTR_MAX_MATCH_SETS, | 1308 | NL80211_ATTR_MAX_MATCH_SETS, |
1290 | 1309 | ||
1310 | NL80211_ATTR_PMKSA_CANDIDATE, | ||
1311 | |||
1312 | NL80211_ATTR_TX_NO_CCK_RATE, | ||
1313 | |||
1291 | /* add attributes here, update the policy in nl80211.c */ | 1314 | /* add attributes here, update the policy in nl80211.c */ |
1292 | 1315 | ||
1293 | __NL80211_ATTR_AFTER_LAST, | 1316 | __NL80211_ATTR_AFTER_LAST, |
@@ -2558,4 +2581,27 @@ enum nl80211_sta_wme_attr { | |||
2558 | NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 | 2581 | NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 |
2559 | }; | 2582 | }; |
2560 | 2583 | ||
2584 | /** | ||
2585 | * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates | ||
2586 | * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes | ||
2587 | * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher | ||
2588 | * priority) | ||
2589 | * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets) | ||
2590 | * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag) | ||
2591 | * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes | ||
2592 | * (internal) | ||
2593 | * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute | ||
2594 | * (internal) | ||
2595 | */ | ||
2596 | enum nl80211_pmksa_candidate_attr { | ||
2597 | __NL80211_PMKSA_CANDIDATE_INVALID, | ||
2598 | NL80211_PMKSA_CANDIDATE_INDEX, | ||
2599 | NL80211_PMKSA_CANDIDATE_BSSID, | ||
2600 | NL80211_PMKSA_CANDIDATE_PREAUTH, | ||
2601 | |||
2602 | /* keep last */ | ||
2603 | NUM_NL80211_PMKSA_CANDIDATE, | ||
2604 | MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1 | ||
2605 | }; | ||
2606 | |||
2561 | #endif /* __LINUX_NL80211_H */ | 2607 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index be30aabe7b88..aaf79af72432 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -716,6 +716,16 @@ struct hci_rp_read_bd_addr { | |||
716 | bdaddr_t bdaddr; | 716 | bdaddr_t bdaddr; |
717 | } __packed; | 717 | } __packed; |
718 | 718 | ||
719 | #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c | ||
720 | struct hci_cp_write_page_scan_activity { | ||
721 | __le16 interval; | ||
722 | __le16 window; | ||
723 | } __packed; | ||
724 | |||
725 | #define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47 | ||
726 | #define PAGE_SCAN_TYPE_STANDARD 0x00 | ||
727 | #define PAGE_SCAN_TYPE_INTERLACED 0x01 | ||
728 | |||
719 | #define HCI_OP_LE_SET_EVENT_MASK 0x2001 | 729 | #define HCI_OP_LE_SET_EVENT_MASK 0x2001 |
720 | struct hci_cp_le_set_event_mask { | 730 | struct hci_cp_le_set_event_mask { |
721 | __u8 mask[8]; | 731 | __u8 mask[8]; |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 8f441b8b2963..5b924423cf20 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -195,8 +195,6 @@ struct hci_dev { | |||
195 | 195 | ||
196 | __u16 init_last_cmd; | 196 | __u16 init_last_cmd; |
197 | 197 | ||
198 | struct crypto_blkcipher *tfm; | ||
199 | |||
200 | struct inquiry_cache inq_cache; | 198 | struct inquiry_cache inq_cache; |
201 | struct hci_conn_hash conn_hash; | 199 | struct hci_conn_hash conn_hash; |
202 | struct list_head blacklist; | 200 | struct list_head blacklist; |
@@ -348,6 +346,7 @@ enum { | |||
348 | HCI_CONN_RSWITCH_PEND, | 346 | HCI_CONN_RSWITCH_PEND, |
349 | HCI_CONN_MODE_CHANGE_PEND, | 347 | HCI_CONN_MODE_CHANGE_PEND, |
350 | HCI_CONN_SCO_SETUP_PEND, | 348 | HCI_CONN_SCO_SETUP_PEND, |
349 | HCI_CONN_LE_SMP_PEND, | ||
351 | }; | 350 | }; |
352 | 351 | ||
353 | static inline void hci_conn_hash_init(struct hci_dev *hdev) | 352 | static inline void hci_conn_hash_init(struct hci_dev *hdev) |
@@ -395,6 +394,22 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) | |||
395 | } | 394 | } |
396 | } | 395 | } |
397 | 396 | ||
397 | static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) | ||
398 | { | ||
399 | struct hci_conn_hash *h = &hdev->conn_hash; | ||
400 | switch (type) { | ||
401 | case ACL_LINK: | ||
402 | return h->acl_num; | ||
403 | case LE_LINK: | ||
404 | return h->le_num; | ||
405 | case SCO_LINK: | ||
406 | case ESCO_LINK: | ||
407 | return h->sco_num; | ||
408 | default: | ||
409 | return 0; | ||
410 | } | ||
411 | } | ||
412 | |||
398 | static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, | 413 | static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, |
399 | __u16 handle) | 414 | __u16 handle) |
400 | { | 415 | { |
@@ -475,7 +490,7 @@ static inline void hci_conn_put(struct hci_conn *conn) | |||
475 | { | 490 | { |
476 | if (atomic_dec_and_test(&conn->refcnt)) { | 491 | if (atomic_dec_and_test(&conn->refcnt)) { |
477 | unsigned long timeo; | 492 | unsigned long timeo; |
478 | if (conn->type == ACL_LINK) { | 493 | if (conn->type == ACL_LINK || conn->type == LE_LINK) { |
479 | del_timer(&conn->idle_timer); | 494 | del_timer(&conn->idle_timer); |
480 | if (conn->state == BT_CONNECTED) { | 495 | if (conn->state == BT_CONNECTED) { |
481 | timeo = msecs_to_jiffies(conn->disc_timeout); | 496 | timeo = msecs_to_jiffies(conn->disc_timeout); |
@@ -838,7 +853,7 @@ int mgmt_powered(u16 index, u8 powered); | |||
838 | int mgmt_discoverable(u16 index, u8 discoverable); | 853 | int mgmt_discoverable(u16 index, u8 discoverable); |
839 | int mgmt_connectable(u16 index, u8 connectable); | 854 | int mgmt_connectable(u16 index, u8 connectable); |
840 | int mgmt_new_key(u16 index, struct link_key *key, u8 persistent); | 855 | int mgmt_new_key(u16 index, struct link_key *key, u8 persistent); |
841 | int mgmt_connected(u16 index, bdaddr_t *bdaddr); | 856 | int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type); |
842 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); | 857 | int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); |
843 | int mgmt_disconnect_failed(u16 index); | 858 | int mgmt_disconnect_failed(u16 index); |
844 | int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); | 859 | int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); |
@@ -858,6 +873,8 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, | |||
858 | u8 *eir); | 873 | u8 *eir); |
859 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); | 874 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); |
860 | int mgmt_discovering(u16 index, u8 discovering); | 875 | int mgmt_discovering(u16 index, u8 discovering); |
876 | int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr); | ||
877 | int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr); | ||
861 | 878 | ||
862 | /* HCI info for socket */ | 879 | /* HCI info for socket */ |
863 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | 880 | #define hci_pi(sk) ((struct hci_pinfo *) sk) |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 4f34ad25e75c..7f878b9d5642 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -409,14 +409,8 @@ struct l2cap_conn { | |||
409 | 409 | ||
410 | __u8 disc_reason; | 410 | __u8 disc_reason; |
411 | 411 | ||
412 | __u8 preq[7]; /* SMP Pairing Request */ | ||
413 | __u8 prsp[7]; /* SMP Pairing Response */ | ||
414 | __u8 prnd[16]; /* SMP Pairing Random */ | ||
415 | __u8 pcnf[16]; /* SMP Pairing Confirm */ | ||
416 | __u8 tk[16]; /* SMP Temporary Key */ | ||
417 | __u8 smp_key_size; | ||
418 | |||
419 | struct timer_list security_timer; | 412 | struct timer_list security_timer; |
413 | struct smp_chan *smp_chan; | ||
420 | 414 | ||
421 | struct list_head chan_l; | 415 | struct list_head chan_l; |
422 | rwlock_t chan_lock; | 416 | rwlock_t chan_lock; |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 5428fd32ccec..d66da0f94f95 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -211,6 +211,11 @@ struct mgmt_cp_unblock_device { | |||
211 | bdaddr_t bdaddr; | 211 | bdaddr_t bdaddr; |
212 | } __packed; | 212 | } __packed; |
213 | 213 | ||
214 | #define MGMT_OP_SET_FAST_CONNECTABLE 0x001F | ||
215 | struct mgmt_cp_set_fast_connectable { | ||
216 | __u8 enable; | ||
217 | } __packed; | ||
218 | |||
214 | #define MGMT_EV_CMD_COMPLETE 0x0001 | 219 | #define MGMT_EV_CMD_COMPLETE 0x0001 |
215 | struct mgmt_ev_cmd_complete { | 220 | struct mgmt_ev_cmd_complete { |
216 | __le16 opcode; | 221 | __le16 opcode; |
@@ -249,6 +254,7 @@ struct mgmt_ev_new_key { | |||
249 | #define MGMT_EV_CONNECTED 0x000B | 254 | #define MGMT_EV_CONNECTED 0x000B |
250 | struct mgmt_ev_connected { | 255 | struct mgmt_ev_connected { |
251 | bdaddr_t bdaddr; | 256 | bdaddr_t bdaddr; |
257 | __u8 link_type; | ||
252 | } __packed; | 258 | } __packed; |
253 | 259 | ||
254 | #define MGMT_EV_DISCONNECTED 0x000C | 260 | #define MGMT_EV_DISCONNECTED 0x000C |
@@ -301,3 +307,13 @@ struct mgmt_ev_remote_name { | |||
301 | } __packed; | 307 | } __packed; |
302 | 308 | ||
303 | #define MGMT_EV_DISCOVERING 0x0014 | 309 | #define MGMT_EV_DISCOVERING 0x0014 |
310 | |||
311 | #define MGMT_EV_DEVICE_BLOCKED 0x0015 | ||
312 | struct mgmt_ev_device_blocked { | ||
313 | bdaddr_t bdaddr; | ||
314 | } __packed; | ||
315 | |||
316 | #define MGMT_EV_DEVICE_UNBLOCKED 0x0016 | ||
317 | struct mgmt_ev_device_unblocked { | ||
318 | bdaddr_t bdaddr; | ||
319 | } __packed; | ||
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index 46c457612300..15b97d549441 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h | |||
@@ -115,9 +115,26 @@ struct smp_cmd_security_req { | |||
115 | #define SMP_MIN_ENC_KEY_SIZE 7 | 115 | #define SMP_MIN_ENC_KEY_SIZE 7 |
116 | #define SMP_MAX_ENC_KEY_SIZE 16 | 116 | #define SMP_MAX_ENC_KEY_SIZE 16 |
117 | 117 | ||
118 | struct smp_chan { | ||
119 | struct l2cap_conn *conn; | ||
120 | u8 preq[7]; /* SMP Pairing Request */ | ||
121 | u8 prsp[7]; /* SMP Pairing Response */ | ||
122 | u8 prnd[16]; /* SMP Pairing Random (local) */ | ||
123 | u8 rrnd[16]; /* SMP Pairing Random (remote) */ | ||
124 | u8 pcnf[16]; /* SMP Pairing Confirm */ | ||
125 | u8 tk[16]; /* SMP Temporary Key */ | ||
126 | u8 smp_key_size; | ||
127 | struct crypto_blkcipher *tfm; | ||
128 | struct work_struct confirm; | ||
129 | struct work_struct random; | ||
130 | |||
131 | }; | ||
132 | |||
118 | /* SMP Commands */ | 133 | /* SMP Commands */ |
119 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level); | 134 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level); |
120 | int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); | 135 | int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); |
121 | int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); | 136 | int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); |
122 | 137 | ||
138 | void smp_chan_destroy(struct l2cap_conn *conn); | ||
139 | |||
123 | #endif /* __SMP_H */ | 140 | #endif /* __SMP_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f4b19b223941..31d823a3092b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -860,6 +860,7 @@ struct cfg80211_ssid { | |||
860 | * @wiphy: the wiphy this was for | 860 | * @wiphy: the wiphy this was for |
861 | * @dev: the interface | 861 | * @dev: the interface |
862 | * @aborted: (internal) scan request was notified as aborted | 862 | * @aborted: (internal) scan request was notified as aborted |
863 | * @no_cck: used to send probe requests at non CCK rate in 2GHz band | ||
863 | */ | 864 | */ |
864 | struct cfg80211_scan_request { | 865 | struct cfg80211_scan_request { |
865 | struct cfg80211_ssid *ssids; | 866 | struct cfg80211_ssid *ssids; |
@@ -874,6 +875,7 @@ struct cfg80211_scan_request { | |||
874 | struct wiphy *wiphy; | 875 | struct wiphy *wiphy; |
875 | struct net_device *dev; | 876 | struct net_device *dev; |
876 | bool aborted; | 877 | bool aborted; |
878 | bool no_cck; | ||
877 | 879 | ||
878 | /* keep last */ | 880 | /* keep last */ |
879 | struct ieee80211_channel *channels[0]; | 881 | struct ieee80211_channel *channels[0]; |
@@ -1484,7 +1486,7 @@ struct cfg80211_ops { | |||
1484 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, | 1486 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, |
1485 | struct bss_parameters *params); | 1487 | struct bss_parameters *params); |
1486 | 1488 | ||
1487 | int (*set_txq_params)(struct wiphy *wiphy, | 1489 | int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev, |
1488 | struct ieee80211_txq_params *params); | 1490 | struct ieee80211_txq_params *params); |
1489 | 1491 | ||
1490 | int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, | 1492 | int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, |
@@ -1560,7 +1562,8 @@ struct cfg80211_ops { | |||
1560 | struct ieee80211_channel *chan, bool offchan, | 1562 | struct ieee80211_channel *chan, bool offchan, |
1561 | enum nl80211_channel_type channel_type, | 1563 | enum nl80211_channel_type channel_type, |
1562 | bool channel_type_valid, unsigned int wait, | 1564 | bool channel_type_valid, unsigned int wait, |
1563 | const u8 *buf, size_t len, u64 *cookie); | 1565 | const u8 *buf, size_t len, bool no_cck, |
1566 | u64 *cookie); | ||
1564 | int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, | 1567 | int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, |
1565 | struct net_device *dev, | 1568 | struct net_device *dev, |
1566 | u64 cookie); | 1569 | u64 cookie); |
@@ -2462,6 +2465,24 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb); | |||
2462 | const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); | 2465 | const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); |
2463 | 2466 | ||
2464 | /** | 2467 | /** |
2468 | * cfg80211_find_vendor_ie - find vendor specific information element in data | ||
2469 | * | ||
2470 | * @oui: vendor OUI | ||
2471 | * @oui_type: vendor-specific OUI type | ||
2472 | * @ies: data consisting of IEs | ||
2473 | * @len: length of data | ||
2474 | * | ||
2475 | * This function will return %NULL if the vendor specific element ID | ||
2476 | * could not be found or if the element is invalid (claims to be | ||
2477 | * longer than the given data), or a pointer to the first byte | ||
2478 | * of the requested element, that is the byte containing the | ||
2479 | * element ID. There are no checks on the element length | ||
2480 | * other than having to fit into the given data. | ||
2481 | */ | ||
2482 | const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, | ||
2483 | const u8 *ies, int len); | ||
2484 | |||
2485 | /** | ||
2465 | * DOC: Regulatory enforcement infrastructure | 2486 | * DOC: Regulatory enforcement infrastructure |
2466 | * | 2487 | * |
2467 | * TODO | 2488 | * TODO |
@@ -3121,6 +3142,17 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev, | |||
3121 | void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, | 3142 | void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, |
3122 | const u8 *replay_ctr, gfp_t gfp); | 3143 | const u8 *replay_ctr, gfp_t gfp); |
3123 | 3144 | ||
3145 | /** | ||
3146 | * cfg80211_pmksa_candidate_notify - notify about PMKSA caching candidate | ||
3147 | * @dev: network device | ||
3148 | * @index: candidate index (the smaller the index, the higher the priority) | ||
3149 | * @bssid: BSSID of AP | ||
3150 | * @preauth: Whether AP advertises support for RSN pre-authentication | ||
3151 | * @gfp: allocation flags | ||
3152 | */ | ||
3153 | void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | ||
3154 | const u8 *bssid, bool preauth, gfp_t gfp); | ||
3155 | |||
3124 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ | 3156 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ |
3125 | 3157 | ||
3126 | /* wiphy_printk helpers, similar to dev_printk */ | 3158 | /* wiphy_printk helpers, similar to dev_printk */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9edba09547e4..1e83afae3c64 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -171,7 +171,7 @@ enum ieee80211_bss_change { | |||
171 | BSS_CHANGED_ERP_CTS_PROT = 1<<1, | 171 | BSS_CHANGED_ERP_CTS_PROT = 1<<1, |
172 | BSS_CHANGED_ERP_PREAMBLE = 1<<2, | 172 | BSS_CHANGED_ERP_PREAMBLE = 1<<2, |
173 | BSS_CHANGED_ERP_SLOT = 1<<3, | 173 | BSS_CHANGED_ERP_SLOT = 1<<3, |
174 | BSS_CHANGED_HT = 1<<4, | 174 | BSS_CHANGED_HT = 1<<4, |
175 | BSS_CHANGED_BASIC_RATES = 1<<5, | 175 | BSS_CHANGED_BASIC_RATES = 1<<5, |
176 | BSS_CHANGED_BEACON_INT = 1<<6, | 176 | BSS_CHANGED_BEACON_INT = 1<<6, |
177 | BSS_CHANGED_BSSID = 1<<7, | 177 | BSS_CHANGED_BSSID = 1<<7, |
@@ -363,6 +363,9 @@ struct ieee80211_bss_conf { | |||
363 | * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP | 363 | * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP |
364 | * testing. It will be sent out with incorrect Michael MIC key to allow | 364 | * testing. It will be sent out with incorrect Michael MIC key to allow |
365 | * TKIP countermeasures to be tested. | 365 | * TKIP countermeasures to be tested. |
366 | * @IEEE80211_TX_CTL_NO_CCK_RATE: This frame will be sent at non CCK rate. | ||
367 | * This flag is actually used for management frame especially for P2P | ||
368 | * frames not being sent at CCK rate in 2GHz band. | ||
366 | * | 369 | * |
367 | * Note: If you have to add new flags to the enumeration, then don't | 370 | * Note: If you have to add new flags to the enumeration, then don't |
368 | * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. | 371 | * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. |
@@ -393,6 +396,7 @@ enum mac80211_tx_control_flags { | |||
393 | IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), | 396 | IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), |
394 | IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25), | 397 | IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25), |
395 | IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26), | 398 | IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26), |
399 | IEEE80211_TX_CTL_NO_CCK_RATE = BIT(27), | ||
396 | }; | 400 | }; |
397 | 401 | ||
398 | #define IEEE80211_TX_CTL_STBC_SHIFT 23 | 402 | #define IEEE80211_TX_CTL_STBC_SHIFT 23 |
@@ -2000,9 +2004,10 @@ struct ieee80211_ops { | |||
2000 | enum sta_notify_cmd, struct ieee80211_sta *sta); | 2004 | enum sta_notify_cmd, struct ieee80211_sta *sta); |
2001 | int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, | 2005 | int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, |
2002 | const struct ieee80211_tx_queue_params *params); | 2006 | const struct ieee80211_tx_queue_params *params); |
2003 | u64 (*get_tsf)(struct ieee80211_hw *hw); | 2007 | u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
2004 | void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf); | 2008 | void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2005 | void (*reset_tsf)(struct ieee80211_hw *hw); | 2009 | u64 tsf); |
2010 | void (*reset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | ||
2006 | int (*tx_last_beacon)(struct ieee80211_hw *hw); | 2011 | int (*tx_last_beacon)(struct ieee80211_hw *hw); |
2007 | int (*ampdu_action)(struct ieee80211_hw *hw, | 2012 | int (*ampdu_action)(struct ieee80211_hw *hw, |
2008 | struct ieee80211_vif *vif, | 2013 | struct ieee80211_vif *vif, |
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h new file mode 100644 index 000000000000..39b85bc0804f --- /dev/null +++ b/include/net/nfc/nci.h | |||
@@ -0,0 +1,313 @@ | |||
1 | /* | ||
2 | * The NFC Controller Interface is the communication protocol between an | ||
3 | * NFC Controller (NFCC) and a Device Host (DH). | ||
4 | * | ||
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
6 | * | ||
7 | * Written by Ilan Elias <ilane@ti.com> | ||
8 | * | ||
9 | * Acknowledgements: | ||
10 | * This file is based on hci.h, which was written | ||
11 | * by Maxim Krasnyansky. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 | ||
15 | * as published by the Free Software Foundation | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #ifndef __NCI_H | ||
29 | #define __NCI_H | ||
30 | |||
31 | /* NCI constants */ | ||
32 | #define NCI_MAX_NUM_MAPPING_CONFIGS 10 | ||
33 | #define NCI_MAX_NUM_RF_CONFIGS 10 | ||
34 | #define NCI_MAX_NUM_CONN 10 | ||
35 | |||
36 | /* NCI Status Codes */ | ||
37 | #define NCI_STATUS_OK 0x00 | ||
38 | #define NCI_STATUS_REJECTED 0x01 | ||
39 | #define NCI_STATUS_MESSAGE_CORRUPTED 0x02 | ||
40 | #define NCI_STATUS_BUFFER_FULL 0x03 | ||
41 | #define NCI_STATUS_FAILED 0x04 | ||
42 | #define NCI_STATUS_NOT_INITIALIZED 0x05 | ||
43 | #define NCI_STATUS_SYNTAX_ERROR 0x06 | ||
44 | #define NCI_STATUS_SEMANTIC_ERROR 0x07 | ||
45 | #define NCI_STATUS_UNKNOWN_GID 0x08 | ||
46 | #define NCI_STATUS_UNKNOWN_OID 0x09 | ||
47 | #define NCI_STATUS_INVALID_PARAM 0x0a | ||
48 | #define NCI_STATUS_MESSAGE_SIZE_EXCEEDED 0x0b | ||
49 | /* Discovery Specific Status Codes */ | ||
50 | #define NCI_STATUS_DISCOVERY_ALREADY_STARTED 0xa0 | ||
51 | #define NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED 0xa1 | ||
52 | /* RF Interface Specific Status Codes */ | ||
53 | #define NCI_STATUS_RF_TRANSMISSION_ERROR 0xb0 | ||
54 | #define NCI_STATUS_RF_PROTOCOL_ERROR 0xb1 | ||
55 | #define NCI_STATUS_RF_TIMEOUT_ERROR 0xb2 | ||
56 | #define NCI_STATUS_RF_LINK_LOSS_ERROR 0xb3 | ||
57 | /* NFCEE Interface Specific Status Codes */ | ||
58 | #define NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED 0xc0 | ||
59 | #define NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED 0xc1 | ||
60 | #define NCI_STATUS_NFCEE_TRANSMISSION_ERROR 0xc2 | ||
61 | #define NCI_STATUS_NFCEE_PROTOCOL_ERROR 0xc3 | ||
62 | #define NCI_STATUS_NFCEE_TIMEOUT_ERROR 0xc4 | ||
63 | |||
64 | /* NCI RF Technology and Mode */ | ||
65 | #define NCI_NFC_A_PASSIVE_POLL_MODE 0x00 | ||
66 | #define NCI_NFC_B_PASSIVE_POLL_MODE 0x01 | ||
67 | #define NCI_NFC_F_PASSIVE_POLL_MODE 0x02 | ||
68 | #define NCI_NFC_A_ACTIVE_POLL_MODE 0x03 | ||
69 | #define NCI_NFC_F_ACTIVE_POLL_MODE 0x05 | ||
70 | #define NCI_NFC_A_PASSIVE_LISTEN_MODE 0x80 | ||
71 | #define NCI_NFC_B_PASSIVE_LISTEN_MODE 0x81 | ||
72 | #define NCI_NFC_F_PASSIVE_LISTEN_MODE 0x82 | ||
73 | #define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83 | ||
74 | #define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85 | ||
75 | |||
76 | /* NCI RF Protocols */ | ||
77 | #define NCI_RF_PROTOCOL_UNKNOWN 0x00 | ||
78 | #define NCI_RF_PROTOCOL_T1T 0x01 | ||
79 | #define NCI_RF_PROTOCOL_T2T 0x02 | ||
80 | #define NCI_RF_PROTOCOL_T3T 0x03 | ||
81 | #define NCI_RF_PROTOCOL_ISO_DEP 0x04 | ||
82 | #define NCI_RF_PROTOCOL_NFC_DEP 0x05 | ||
83 | |||
84 | /* NCI RF Interfaces */ | ||
85 | #define NCI_RF_INTERFACE_RFU 0x00 | ||
86 | #define NCI_RF_INTERFACE_FRAME 0x01 | ||
87 | #define NCI_RF_INTERFACE_ISO_DEP 0x02 | ||
88 | #define NCI_RF_INTERFACE_NFC_DEP 0x03 | ||
89 | |||
90 | /* NCI RF_DISCOVER_MAP_CMD modes */ | ||
91 | #define NCI_DISC_MAP_MODE_POLL 0x01 | ||
92 | #define NCI_DISC_MAP_MODE_LISTEN 0x02 | ||
93 | #define NCI_DISC_MAP_MODE_BOTH 0x03 | ||
94 | |||
95 | /* NCI Discovery Types */ | ||
96 | #define NCI_DISCOVERY_TYPE_POLL_A_PASSIVE 0x00 | ||
97 | #define NCI_DISCOVERY_TYPE_POLL_B_PASSIVE 0x01 | ||
98 | #define NCI_DISCOVERY_TYPE_POLL_F_PASSIVE 0x02 | ||
99 | #define NCI_DISCOVERY_TYPE_POLL_A_ACTIVE 0x03 | ||
100 | #define NCI_DISCOVERY_TYPE_POLL_F_ACTIVE 0x05 | ||
101 | #define NCI_DISCOVERY_TYPE_WAKEUP_A_PASSIVE 0x06 | ||
102 | #define NCI_DISCOVERY_TYPE_WAKEUP_B_PASSIVE 0x07 | ||
103 | #define NCI_DISCOVERY_TYPE_WAKEUP_A_ACTIVE 0x09 | ||
104 | #define NCI_DISCOVERY_TYPE_LISTEN_A_PASSIVE 0x80 | ||
105 | #define NCI_DISCOVERY_TYPE_LISTEN_B_PASSIVE 0x81 | ||
106 | #define NCI_DISCOVERY_TYPE_LISTEN_F_PASSIVE 0x82 | ||
107 | #define NCI_DISCOVERY_TYPE_LISTEN_A_ACTIVE 0x83 | ||
108 | #define NCI_DISCOVERY_TYPE_LISTEN_F_ACTIVE 0x85 | ||
109 | |||
110 | /* NCI Deactivation Type */ | ||
111 | #define NCI_DEACTIVATE_TYPE_IDLE_MODE 0x00 | ||
112 | #define NCI_DEACTIVATE_TYPE_SLEEP_MODE 0x01 | ||
113 | #define NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE 0x02 | ||
114 | #define NCI_DEACTIVATE_TYPE_RF_LINK_LOSS 0x03 | ||
115 | #define NCI_DEACTIVATE_TYPE_DISCOVERY_ERROR 0x04 | ||
116 | |||
117 | /* Message Type (MT) */ | ||
118 | #define NCI_MT_DATA_PKT 0x00 | ||
119 | #define NCI_MT_CMD_PKT 0x01 | ||
120 | #define NCI_MT_RSP_PKT 0x02 | ||
121 | #define NCI_MT_NTF_PKT 0x03 | ||
122 | |||
123 | #define nci_mt(hdr) (((hdr)[0]>>5)&0x07) | ||
124 | #define nci_mt_set(hdr, mt) ((hdr)[0] |= (__u8)(((mt)&0x07)<<5)) | ||
125 | |||
126 | /* Packet Boundary Flag (PBF) */ | ||
127 | #define NCI_PBF_LAST 0x00 | ||
128 | #define NCI_PBF_CONT 0x01 | ||
129 | |||
130 | #define nci_pbf(hdr) (__u8)(((hdr)[0]>>4)&0x01) | ||
131 | #define nci_pbf_set(hdr, pbf) ((hdr)[0] |= (__u8)(((pbf)&0x01)<<4)) | ||
132 | |||
133 | /* Control Opcode manipulation */ | ||
134 | #define nci_opcode_pack(gid, oid) (__u16)((((__u16)((gid)&0x0f))<<8)|\ | ||
135 | ((__u16)((oid)&0x3f))) | ||
136 | #define nci_opcode(hdr) nci_opcode_pack(hdr[0], hdr[1]) | ||
137 | #define nci_opcode_gid(op) (__u8)(((op)&0x0f00)>>8) | ||
138 | #define nci_opcode_oid(op) (__u8)((op)&0x003f) | ||
139 | |||
140 | /* Payload Length */ | ||
141 | #define nci_plen(hdr) (__u8)((hdr)[2]) | ||
142 | |||
143 | /* Connection ID */ | ||
144 | #define nci_conn_id(hdr) (__u8)(((hdr)[0])&0x0f) | ||
145 | |||
146 | /* GID values */ | ||
147 | #define NCI_GID_CORE 0x0 | ||
148 | #define NCI_GID_RF_MGMT 0x1 | ||
149 | #define NCI_GID_NFCEE_MGMT 0x2 | ||
150 | #define NCI_GID_PROPRIETARY 0xf | ||
151 | |||
152 | /* ---- NCI Packet structures ---- */ | ||
153 | #define NCI_CTRL_HDR_SIZE 3 | ||
154 | #define NCI_DATA_HDR_SIZE 3 | ||
155 | |||
156 | struct nci_ctrl_hdr { | ||
157 | __u8 gid; /* MT & PBF & GID */ | ||
158 | __u8 oid; | ||
159 | __u8 plen; | ||
160 | } __packed; | ||
161 | |||
162 | struct nci_data_hdr { | ||
163 | __u8 conn_id; /* MT & PBF & ConnID */ | ||
164 | __u8 rfu; | ||
165 | __u8 plen; | ||
166 | } __packed; | ||
167 | |||
168 | /* ------------------------ */ | ||
169 | /* ----- NCI Commands ---- */ | ||
170 | /* ------------------------ */ | ||
171 | #define NCI_OP_CORE_RESET_CMD nci_opcode_pack(NCI_GID_CORE, 0x00) | ||
172 | |||
173 | #define NCI_OP_CORE_INIT_CMD nci_opcode_pack(NCI_GID_CORE, 0x01) | ||
174 | |||
175 | #define NCI_OP_CORE_SET_CONFIG_CMD nci_opcode_pack(NCI_GID_CORE, 0x02) | ||
176 | |||
177 | #define NCI_OP_CORE_CONN_CREATE_CMD nci_opcode_pack(NCI_GID_CORE, 0x04) | ||
178 | struct nci_core_conn_create_cmd { | ||
179 | __u8 target_handle; | ||
180 | __u8 num_target_specific_params; | ||
181 | } __packed; | ||
182 | |||
183 | #define NCI_OP_CORE_CONN_CLOSE_CMD nci_opcode_pack(NCI_GID_CORE, 0x06) | ||
184 | |||
185 | #define NCI_OP_RF_DISCOVER_MAP_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x00) | ||
186 | struct disc_map_config { | ||
187 | __u8 rf_protocol; | ||
188 | __u8 mode; | ||
189 | __u8 rf_interface_type; | ||
190 | } __packed; | ||
191 | |||
192 | struct nci_rf_disc_map_cmd { | ||
193 | __u8 num_mapping_configs; | ||
194 | struct disc_map_config mapping_configs | ||
195 | [NCI_MAX_NUM_MAPPING_CONFIGS]; | ||
196 | } __packed; | ||
197 | |||
198 | #define NCI_OP_RF_DISCOVER_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x03) | ||
199 | struct disc_config { | ||
200 | __u8 type; | ||
201 | __u8 frequency; | ||
202 | } __packed; | ||
203 | |||
204 | struct nci_rf_disc_cmd { | ||
205 | __u8 num_disc_configs; | ||
206 | struct disc_config disc_configs[NCI_MAX_NUM_RF_CONFIGS]; | ||
207 | } __packed; | ||
208 | |||
209 | #define NCI_OP_RF_DEACTIVATE_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x06) | ||
210 | struct nci_rf_deactivate_cmd { | ||
211 | __u8 type; | ||
212 | } __packed; | ||
213 | |||
214 | /* ----------------------- */ | ||
215 | /* ---- NCI Responses ---- */ | ||
216 | /* ----------------------- */ | ||
217 | #define NCI_OP_CORE_RESET_RSP nci_opcode_pack(NCI_GID_CORE, 0x00) | ||
218 | struct nci_core_reset_rsp { | ||
219 | __u8 status; | ||
220 | __u8 nci_ver; | ||
221 | } __packed; | ||
222 | |||
223 | #define NCI_OP_CORE_INIT_RSP nci_opcode_pack(NCI_GID_CORE, 0x01) | ||
224 | struct nci_core_init_rsp_1 { | ||
225 | __u8 status; | ||
226 | __le32 nfcc_features; | ||
227 | __u8 num_supported_rf_interfaces; | ||
228 | __u8 supported_rf_interfaces[0]; /* variable size array */ | ||
229 | /* continuted in nci_core_init_rsp_2 */ | ||
230 | } __packed; | ||
231 | |||
232 | struct nci_core_init_rsp_2 { | ||
233 | __u8 max_logical_connections; | ||
234 | __le16 max_routing_table_size; | ||
235 | __u8 max_control_packet_payload_length; | ||
236 | __le16 rf_sending_buffer_size; | ||
237 | __le16 rf_receiving_buffer_size; | ||
238 | __le16 manufacturer_id; | ||
239 | } __packed; | ||
240 | |||
241 | #define NCI_OP_CORE_SET_CONFIG_RSP nci_opcode_pack(NCI_GID_CORE, 0x02) | ||
242 | |||
243 | #define NCI_OP_CORE_CONN_CREATE_RSP nci_opcode_pack(NCI_GID_CORE, 0x04) | ||
244 | struct nci_core_conn_create_rsp { | ||
245 | __u8 status; | ||
246 | __u8 max_pkt_payload_size; | ||
247 | __u8 initial_num_credits; | ||
248 | __u8 conn_id; | ||
249 | } __packed; | ||
250 | |||
251 | #define NCI_OP_CORE_CONN_CLOSE_RSP nci_opcode_pack(NCI_GID_CORE, 0x06) | ||
252 | |||
253 | #define NCI_OP_RF_DISCOVER_MAP_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x00) | ||
254 | |||
255 | #define NCI_OP_RF_DISCOVER_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x03) | ||
256 | |||
257 | #define NCI_OP_RF_DEACTIVATE_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x06) | ||
258 | |||
259 | /* --------------------------- */ | ||
260 | /* ---- NCI Notifications ---- */ | ||
261 | /* --------------------------- */ | ||
262 | #define NCI_OP_CORE_CONN_CREDITS_NTF nci_opcode_pack(NCI_GID_CORE, 0x07) | ||
263 | struct conn_credit_entry { | ||
264 | __u8 conn_id; | ||
265 | __u8 credits; | ||
266 | } __packed; | ||
267 | |||
268 | struct nci_core_conn_credit_ntf { | ||
269 | __u8 num_entries; | ||
270 | struct conn_credit_entry conn_entries[NCI_MAX_NUM_CONN]; | ||
271 | } __packed; | ||
272 | |||
273 | #define NCI_OP_RF_FIELD_INFO_NTF nci_opcode_pack(NCI_GID_CORE, 0x08) | ||
274 | struct nci_rf_field_info_ntf { | ||
275 | __u8 rf_field_status; | ||
276 | } __packed; | ||
277 | |||
278 | #define NCI_OP_RF_ACTIVATE_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x05) | ||
279 | struct rf_tech_specific_params_nfca_poll { | ||
280 | __u16 sens_res; | ||
281 | __u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */ | ||
282 | __u8 nfcid1[10]; | ||
283 | __u8 sel_res_len; /* 0 or 1 Bytes */ | ||
284 | __u8 sel_res; | ||
285 | } __packed; | ||
286 | |||
287 | struct activation_params_nfca_poll_iso_dep { | ||
288 | __u8 rats_res_len; | ||
289 | __u8 rats_res[20]; | ||
290 | }; | ||
291 | |||
292 | struct nci_rf_activate_ntf { | ||
293 | __u8 target_handle; | ||
294 | __u8 rf_protocol; | ||
295 | __u8 rf_tech_and_mode; | ||
296 | __u8 rf_tech_specific_params_len; | ||
297 | |||
298 | union { | ||
299 | struct rf_tech_specific_params_nfca_poll nfca_poll; | ||
300 | } rf_tech_specific_params; | ||
301 | |||
302 | __u8 rf_interface_type; | ||
303 | __u8 activation_params_len; | ||
304 | |||
305 | union { | ||
306 | struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep; | ||
307 | } activation_params; | ||
308 | |||
309 | } __packed; | ||
310 | |||
311 | #define NCI_OP_RF_DEACTIVATE_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x06) | ||
312 | |||
313 | #endif /* __NCI_H */ | ||
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h new file mode 100644 index 000000000000..b8b4bbd7e0fc --- /dev/null +++ b/include/net/nfc/nci_core.h | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * The NFC Controller Interface is the communication protocol between an | ||
3 | * NFC Controller (NFCC) and a Device Host (DH). | ||
4 | * | ||
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
6 | * | ||
7 | * Written by Ilan Elias <ilane@ti.com> | ||
8 | * | ||
9 | * Acknowledgements: | ||
10 | * This file is based on hci_core.h, which was written | ||
11 | * by Maxim Krasnyansky. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 | ||
15 | * as published by the Free Software Foundation | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #ifndef __NCI_CORE_H | ||
29 | #define __NCI_CORE_H | ||
30 | |||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/skbuff.h> | ||
33 | |||
34 | #include <net/nfc/nfc.h> | ||
35 | #include <net/nfc/nci.h> | ||
36 | |||
37 | /* NCI device state */ | ||
38 | enum { | ||
39 | NCI_INIT, | ||
40 | NCI_UP, | ||
41 | NCI_DISCOVERY, | ||
42 | NCI_POLL_ACTIVE, | ||
43 | NCI_DATA_EXCHANGE, | ||
44 | }; | ||
45 | |||
46 | /* NCI timeouts */ | ||
47 | #define NCI_RESET_TIMEOUT 5000 | ||
48 | #define NCI_INIT_TIMEOUT 5000 | ||
49 | #define NCI_RF_DISC_TIMEOUT 5000 | ||
50 | #define NCI_RF_DEACTIVATE_TIMEOUT 5000 | ||
51 | #define NCI_CMD_TIMEOUT 5000 | ||
52 | |||
53 | struct nci_dev; | ||
54 | |||
55 | struct nci_ops { | ||
56 | int (*open)(struct nci_dev *ndev); | ||
57 | int (*close)(struct nci_dev *ndev); | ||
58 | int (*send)(struct sk_buff *skb); | ||
59 | }; | ||
60 | |||
61 | #define NCI_MAX_SUPPORTED_RF_INTERFACES 4 | ||
62 | |||
63 | /* NCI Core structures */ | ||
64 | struct nci_dev { | ||
65 | struct nfc_dev *nfc_dev; | ||
66 | struct nci_ops *ops; | ||
67 | |||
68 | int tx_headroom; | ||
69 | int tx_tailroom; | ||
70 | |||
71 | unsigned long flags; | ||
72 | |||
73 | atomic_t cmd_cnt; | ||
74 | atomic_t credits_cnt; | ||
75 | |||
76 | struct timer_list cmd_timer; | ||
77 | |||
78 | struct workqueue_struct *cmd_wq; | ||
79 | struct work_struct cmd_work; | ||
80 | |||
81 | struct workqueue_struct *rx_wq; | ||
82 | struct work_struct rx_work; | ||
83 | |||
84 | struct workqueue_struct *tx_wq; | ||
85 | struct work_struct tx_work; | ||
86 | |||
87 | struct sk_buff_head cmd_q; | ||
88 | struct sk_buff_head rx_q; | ||
89 | struct sk_buff_head tx_q; | ||
90 | |||
91 | struct mutex req_lock; | ||
92 | struct completion req_completion; | ||
93 | __u32 req_status; | ||
94 | __u32 req_result; | ||
95 | |||
96 | void *driver_data; | ||
97 | |||
98 | __u32 poll_prots; | ||
99 | __u32 target_available_prots; | ||
100 | __u32 target_active_prot; | ||
101 | |||
102 | /* received during NCI_OP_CORE_RESET_RSP */ | ||
103 | __u8 nci_ver; | ||
104 | |||
105 | /* received during NCI_OP_CORE_INIT_RSP */ | ||
106 | __u32 nfcc_features; | ||
107 | __u8 num_supported_rf_interfaces; | ||
108 | __u8 supported_rf_interfaces | ||
109 | [NCI_MAX_SUPPORTED_RF_INTERFACES]; | ||
110 | __u8 max_logical_connections; | ||
111 | __u16 max_routing_table_size; | ||
112 | __u8 max_control_packet_payload_length; | ||
113 | __u16 rf_sending_buffer_size; | ||
114 | __u16 rf_receiving_buffer_size; | ||
115 | __u16 manufacturer_id; | ||
116 | |||
117 | /* received during NCI_OP_CORE_CONN_CREATE_RSP for static conn 0 */ | ||
118 | __u8 max_pkt_payload_size; | ||
119 | __u8 initial_num_credits; | ||
120 | __u8 conn_id; | ||
121 | |||
122 | /* stored during nci_data_exchange */ | ||
123 | data_exchange_cb_t data_exchange_cb; | ||
124 | void *data_exchange_cb_context; | ||
125 | struct sk_buff *rx_data_reassembly; | ||
126 | }; | ||
127 | |||
128 | /* ----- NCI Devices ----- */ | ||
129 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, | ||
130 | __u32 supported_protocols, | ||
131 | int tx_headroom, | ||
132 | int tx_tailroom); | ||
133 | void nci_free_device(struct nci_dev *ndev); | ||
134 | int nci_register_device(struct nci_dev *ndev); | ||
135 | void nci_unregister_device(struct nci_dev *ndev); | ||
136 | int nci_recv_frame(struct sk_buff *skb); | ||
137 | |||
138 | static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev, | ||
139 | unsigned int len, | ||
140 | gfp_t how) | ||
141 | { | ||
142 | struct sk_buff *skb; | ||
143 | |||
144 | skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how); | ||
145 | if (skb) | ||
146 | skb_reserve(skb, ndev->tx_headroom); | ||
147 | |||
148 | return skb; | ||
149 | } | ||
150 | |||
151 | static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev) | ||
152 | { | ||
153 | nfc_set_parent_dev(ndev->nfc_dev, dev); | ||
154 | } | ||
155 | |||
156 | static inline void nci_set_drvdata(struct nci_dev *ndev, void *data) | ||
157 | { | ||
158 | ndev->driver_data = data; | ||
159 | } | ||
160 | |||
161 | static inline void *nci_get_drvdata(struct nci_dev *ndev) | ||
162 | { | ||
163 | return ndev->driver_data; | ||
164 | } | ||
165 | |||
166 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb); | ||
167 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb); | ||
168 | void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb); | ||
169 | int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload); | ||
170 | int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb); | ||
171 | void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb, | ||
172 | int err); | ||
173 | |||
174 | /* ----- NCI requests ----- */ | ||
175 | #define NCI_REQ_DONE 0 | ||
176 | #define NCI_REQ_PEND 1 | ||
177 | #define NCI_REQ_CANCELED 2 | ||
178 | |||
179 | void nci_req_complete(struct nci_dev *ndev, int result); | ||
180 | |||
181 | /* ----- NCI status code ----- */ | ||
182 | int nci_to_errno(__u8 code); | ||
183 | |||
184 | #endif /* __NCI_CORE_H */ | ||
diff --git a/include/net/nfc.h b/include/net/nfc/nfc.h index 87b51fe15b70..6a7f602aa841 100644 --- a/include/net/nfc.h +++ b/include/net/nfc/nfc.h | |||
@@ -48,6 +48,8 @@ typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb, | |||
48 | int err); | 48 | int err); |
49 | 49 | ||
50 | struct nfc_ops { | 50 | struct nfc_ops { |
51 | int (*dev_up)(struct nfc_dev *dev); | ||
52 | int (*dev_down)(struct nfc_dev *dev); | ||
51 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); | 53 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); |
52 | void (*stop_poll)(struct nfc_dev *dev); | 54 | void (*stop_poll)(struct nfc_dev *dev); |
53 | int (*activate_target)(struct nfc_dev *dev, u32 target_idx, | 55 | int (*activate_target)(struct nfc_dev *dev, u32 target_idx, |
@@ -78,7 +80,9 @@ struct nfc_dev { | |||
78 | int targets_generation; | 80 | int targets_generation; |
79 | spinlock_t targets_lock; | 81 | spinlock_t targets_lock; |
80 | struct device dev; | 82 | struct device dev; |
83 | bool dev_up; | ||
81 | bool polling; | 84 | bool polling; |
85 | bool remote_activated; | ||
82 | struct nfc_genl_data genl_data; | 86 | struct nfc_genl_data genl_data; |
83 | u32 supported_protocols; | 87 | u32 supported_protocols; |
84 | 88 | ||
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ea7f031f3b04..c2df7bf1d374 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -218,7 +218,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], | |||
218 | cp.handle = cpu_to_le16(conn->handle); | 218 | cp.handle = cpu_to_le16(conn->handle); |
219 | memcpy(cp.ltk, ltk, sizeof(cp.ltk)); | 219 | memcpy(cp.ltk, ltk, sizeof(cp.ltk)); |
220 | cp.ediv = ediv; | 220 | cp.ediv = ediv; |
221 | memcpy(cp.rand, rand, sizeof(rand)); | 221 | memcpy(cp.rand, rand, sizeof(cp.rand)); |
222 | 222 | ||
223 | hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); | 223 | hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); |
224 | } | 224 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 56943add45cc..b84458dcc226 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1312,59 +1312,41 @@ int hci_blacklist_clear(struct hci_dev *hdev) | |||
1312 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr) | 1312 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr) |
1313 | { | 1313 | { |
1314 | struct bdaddr_list *entry; | 1314 | struct bdaddr_list *entry; |
1315 | int err; | ||
1316 | 1315 | ||
1317 | if (bacmp(bdaddr, BDADDR_ANY) == 0) | 1316 | if (bacmp(bdaddr, BDADDR_ANY) == 0) |
1318 | return -EBADF; | 1317 | return -EBADF; |
1319 | 1318 | ||
1320 | hci_dev_lock_bh(hdev); | 1319 | if (hci_blacklist_lookup(hdev, bdaddr)) |
1321 | 1320 | return -EEXIST; | |
1322 | if (hci_blacklist_lookup(hdev, bdaddr)) { | ||
1323 | err = -EEXIST; | ||
1324 | goto err; | ||
1325 | } | ||
1326 | 1321 | ||
1327 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); | 1322 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); |
1328 | if (!entry) { | 1323 | if (!entry) |
1329 | err = -ENOMEM; | 1324 | return -ENOMEM; |
1330 | goto err; | ||
1331 | } | ||
1332 | 1325 | ||
1333 | bacpy(&entry->bdaddr, bdaddr); | 1326 | bacpy(&entry->bdaddr, bdaddr); |
1334 | 1327 | ||
1335 | list_add(&entry->list, &hdev->blacklist); | 1328 | list_add(&entry->list, &hdev->blacklist); |
1336 | 1329 | ||
1337 | err = 0; | 1330 | return mgmt_device_blocked(hdev->id, bdaddr); |
1338 | |||
1339 | err: | ||
1340 | hci_dev_unlock_bh(hdev); | ||
1341 | return err; | ||
1342 | } | 1331 | } |
1343 | 1332 | ||
1344 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr) | 1333 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr) |
1345 | { | 1334 | { |
1346 | struct bdaddr_list *entry; | 1335 | struct bdaddr_list *entry; |
1347 | int err = 0; | ||
1348 | |||
1349 | hci_dev_lock_bh(hdev); | ||
1350 | 1336 | ||
1351 | if (bacmp(bdaddr, BDADDR_ANY) == 0) { | 1337 | if (bacmp(bdaddr, BDADDR_ANY) == 0) { |
1352 | hci_blacklist_clear(hdev); | 1338 | return hci_blacklist_clear(hdev); |
1353 | goto done; | ||
1354 | } | 1339 | } |
1355 | 1340 | ||
1356 | entry = hci_blacklist_lookup(hdev, bdaddr); | 1341 | entry = hci_blacklist_lookup(hdev, bdaddr); |
1357 | if (!entry) { | 1342 | if (!entry) { |
1358 | err = -ENOENT; | 1343 | return -ENOENT; |
1359 | goto done; | ||
1360 | } | 1344 | } |
1361 | 1345 | ||
1362 | list_del(&entry->list); | 1346 | list_del(&entry->list); |
1363 | kfree(entry); | 1347 | kfree(entry); |
1364 | 1348 | ||
1365 | done: | 1349 | return mgmt_device_unblocked(hdev->id, bdaddr); |
1366 | hci_dev_unlock_bh(hdev); | ||
1367 | return err; | ||
1368 | } | 1350 | } |
1369 | 1351 | ||
1370 | static void hci_clear_adv_cache(unsigned long arg) | 1352 | static void hci_clear_adv_cache(unsigned long arg) |
@@ -1523,11 +1505,6 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1523 | if (!hdev->workqueue) | 1505 | if (!hdev->workqueue) |
1524 | goto nomem; | 1506 | goto nomem; |
1525 | 1507 | ||
1526 | hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); | ||
1527 | if (IS_ERR(hdev->tfm)) | ||
1528 | BT_INFO("Failed to load transform for ecb(aes): %ld", | ||
1529 | PTR_ERR(hdev->tfm)); | ||
1530 | |||
1531 | hci_register_sysfs(hdev); | 1508 | hci_register_sysfs(hdev); |
1532 | 1509 | ||
1533 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, | 1510 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, |
@@ -1576,9 +1553,6 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
1576 | !test_bit(HCI_SETUP, &hdev->flags)) | 1553 | !test_bit(HCI_SETUP, &hdev->flags)) |
1577 | mgmt_index_removed(hdev->id); | 1554 | mgmt_index_removed(hdev->id); |
1578 | 1555 | ||
1579 | if (!IS_ERR(hdev->tfm)) | ||
1580 | crypto_free_blkcipher(hdev->tfm); | ||
1581 | |||
1582 | hci_notify(hdev, HCI_DEV_UNREG); | 1556 | hci_notify(hdev, HCI_DEV_UNREG); |
1583 | 1557 | ||
1584 | if (hdev->rfkill) { | 1558 | if (hdev->rfkill) { |
@@ -2074,6 +2048,9 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int | |||
2074 | min = c->sent; | 2048 | min = c->sent; |
2075 | conn = c; | 2049 | conn = c; |
2076 | } | 2050 | } |
2051 | |||
2052 | if (hci_conn_num(hdev, type) == num) | ||
2053 | break; | ||
2077 | } | 2054 | } |
2078 | 2055 | ||
2079 | if (conn) { | 2056 | if (conn) { |
@@ -2131,6 +2108,9 @@ static inline void hci_sched_acl(struct hci_dev *hdev) | |||
2131 | 2108 | ||
2132 | BT_DBG("%s", hdev->name); | 2109 | BT_DBG("%s", hdev->name); |
2133 | 2110 | ||
2111 | if (!hci_conn_num(hdev, ACL_LINK)) | ||
2112 | return; | ||
2113 | |||
2134 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 2114 | if (!test_bit(HCI_RAW, &hdev->flags)) { |
2135 | /* ACL tx timeout must be longer than maximum | 2115 | /* ACL tx timeout must be longer than maximum |
2136 | * link supervision timeout (40.9 seconds) */ | 2116 | * link supervision timeout (40.9 seconds) */ |
@@ -2162,6 +2142,9 @@ static inline void hci_sched_sco(struct hci_dev *hdev) | |||
2162 | 2142 | ||
2163 | BT_DBG("%s", hdev->name); | 2143 | BT_DBG("%s", hdev->name); |
2164 | 2144 | ||
2145 | if (!hci_conn_num(hdev, SCO_LINK)) | ||
2146 | return; | ||
2147 | |||
2165 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { | 2148 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { |
2166 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | 2149 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { |
2167 | BT_DBG("skb %p len %d", skb, skb->len); | 2150 | BT_DBG("skb %p len %d", skb, skb->len); |
@@ -2182,6 +2165,9 @@ static inline void hci_sched_esco(struct hci_dev *hdev) | |||
2182 | 2165 | ||
2183 | BT_DBG("%s", hdev->name); | 2166 | BT_DBG("%s", hdev->name); |
2184 | 2167 | ||
2168 | if (!hci_conn_num(hdev, ESCO_LINK)) | ||
2169 | return; | ||
2170 | |||
2185 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, "e))) { | 2171 | while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, "e))) { |
2186 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { | 2172 | while (quote-- && (skb = skb_dequeue(&conn->data_q))) { |
2187 | BT_DBG("skb %p len %d", skb, skb->len); | 2173 | BT_DBG("skb %p len %d", skb, skb->len); |
@@ -2202,6 +2188,9 @@ static inline void hci_sched_le(struct hci_dev *hdev) | |||
2202 | 2188 | ||
2203 | BT_DBG("%s", hdev->name); | 2189 | BT_DBG("%s", hdev->name); |
2204 | 2190 | ||
2191 | if (!hci_conn_num(hdev, LE_LINK)) | ||
2192 | return; | ||
2193 | |||
2205 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 2194 | if (!test_bit(HCI_RAW, &hdev->flags)) { |
2206 | /* LE tx timeout must be longer than maximum | 2195 | /* LE tx timeout must be longer than maximum |
2207 | * link supervision timeout (40.9 seconds) */ | 2196 | * link supervision timeout (40.9 seconds) */ |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7ef4eb4435fb..35083f2aa2ea 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -898,16 +898,15 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
898 | if (!cp) | 898 | if (!cp) |
899 | return; | 899 | return; |
900 | 900 | ||
901 | hci_dev_lock(hdev); | ||
902 | |||
903 | if (cp->enable == 0x01) { | 901 | if (cp->enable == 0x01) { |
904 | del_timer(&hdev->adv_timer); | 902 | del_timer(&hdev->adv_timer); |
903 | |||
904 | hci_dev_lock(hdev); | ||
905 | hci_adv_entries_clear(hdev); | 905 | hci_adv_entries_clear(hdev); |
906 | hci_dev_unlock(hdev); | ||
906 | } else if (cp->enable == 0x00) { | 907 | } else if (cp->enable == 0x00) { |
907 | mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); | 908 | mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); |
908 | } | 909 | } |
909 | |||
910 | hci_dev_unlock(hdev); | ||
911 | } | 910 | } |
912 | 911 | ||
913 | static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) | 912 | static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1103,9 +1102,10 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev, | |||
1103 | return 0; | 1102 | return 0; |
1104 | 1103 | ||
1105 | /* Only request authentication for SSP connections or non-SSP | 1104 | /* Only request authentication for SSP connections or non-SSP |
1106 | * devices with sec_level HIGH */ | 1105 | * devices with sec_level HIGH or if MITM protection is requested */ |
1107 | if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && | 1106 | if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && |
1108 | conn->pending_sec_level != BT_SECURITY_HIGH) | 1107 | conn->pending_sec_level != BT_SECURITY_HIGH && |
1108 | !(conn->auth_type & 0x01)) | ||
1109 | return 0; | 1109 | return 0; |
1110 | 1110 | ||
1111 | return 1; | 1111 | return 1; |
@@ -1412,7 +1412,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1412 | conn->state = BT_CONFIG; | 1412 | conn->state = BT_CONFIG; |
1413 | hci_conn_hold(conn); | 1413 | hci_conn_hold(conn); |
1414 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | 1414 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; |
1415 | mgmt_connected(hdev->id, &ev->bdaddr); | 1415 | mgmt_connected(hdev->id, &ev->bdaddr, conn->type); |
1416 | } else | 1416 | } else |
1417 | conn->state = BT_CONNECTED; | 1417 | conn->state = BT_CONNECTED; |
1418 | 1418 | ||
@@ -2816,7 +2816,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
2816 | goto unlock; | 2816 | goto unlock; |
2817 | } | 2817 | } |
2818 | 2818 | ||
2819 | mgmt_connected(hdev->id, &ev->bdaddr); | 2819 | mgmt_connected(hdev->id, &ev->bdaddr, conn->type); |
2820 | 2820 | ||
2821 | conn->sec_level = BT_SECURITY_LOW; | 2821 | conn->sec_level = BT_SECURITY_LOW; |
2822 | conn->handle = __le16_to_cpu(ev->handle); | 2822 | conn->handle = __le16_to_cpu(ev->handle); |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index ff02cf5e77cc..f6afe3d76a66 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -183,21 +183,35 @@ static int hci_sock_release(struct socket *sock) | |||
183 | static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) | 183 | static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) |
184 | { | 184 | { |
185 | bdaddr_t bdaddr; | 185 | bdaddr_t bdaddr; |
186 | int err; | ||
186 | 187 | ||
187 | if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) | 188 | if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) |
188 | return -EFAULT; | 189 | return -EFAULT; |
189 | 190 | ||
190 | return hci_blacklist_add(hdev, &bdaddr); | 191 | hci_dev_lock_bh(hdev); |
192 | |||
193 | err = hci_blacklist_add(hdev, &bdaddr); | ||
194 | |||
195 | hci_dev_unlock_bh(hdev); | ||
196 | |||
197 | return err; | ||
191 | } | 198 | } |
192 | 199 | ||
193 | static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) | 200 | static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) |
194 | { | 201 | { |
195 | bdaddr_t bdaddr; | 202 | bdaddr_t bdaddr; |
203 | int err; | ||
196 | 204 | ||
197 | if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) | 205 | if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) |
198 | return -EFAULT; | 206 | return -EFAULT; |
199 | 207 | ||
200 | return hci_blacklist_del(hdev, &bdaddr); | 208 | hci_dev_lock_bh(hdev); |
209 | |||
210 | err = hci_blacklist_del(hdev, &bdaddr); | ||
211 | |||
212 | hci_dev_unlock_bh(hdev); | ||
213 | |||
214 | return err; | ||
201 | } | 215 | } |
202 | 216 | ||
203 | /* Ioctls that require bound socket */ | 217 | /* Ioctls that require bound socket */ |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index a6c3aa8be1f7..22f1a6c87035 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -23,6 +23,8 @@ static inline char *link_typetostr(int type) | |||
23 | return "SCO"; | 23 | return "SCO"; |
24 | case ESCO_LINK: | 24 | case ESCO_LINK: |
25 | return "eSCO"; | 25 | return "eSCO"; |
26 | case LE_LINK: | ||
27 | return "LE"; | ||
26 | default: | 28 | default: |
27 | return "UNKNOWN"; | 29 | return "UNKNOWN"; |
28 | } | 30 | } |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index fb68f344c34a..b83979c548b2 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -872,6 +872,9 @@ static int hidp_start(struct hid_device *hid) | |||
872 | struct hidp_session *session = hid->driver_data; | 872 | struct hidp_session *session = hid->driver_data; |
873 | struct hid_report *report; | 873 | struct hid_report *report; |
874 | 874 | ||
875 | if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS) | ||
876 | return 0; | ||
877 | |||
875 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT]. | 878 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT]. |
876 | report_list, list) | 879 | report_list, list) |
877 | hidp_send_report(session, report); | 880 | hidp_send_report(session, report); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b3bdb482bbe6..1611b3544bb1 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -907,6 +907,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
907 | if (!conn->hcon->out && conn->hcon->type == LE_LINK) | 907 | if (!conn->hcon->out && conn->hcon->type == LE_LINK) |
908 | l2cap_le_conn_ready(conn); | 908 | l2cap_le_conn_ready(conn); |
909 | 909 | ||
910 | if (conn->hcon->out && conn->hcon->type == LE_LINK) | ||
911 | smp_conn_security(conn, conn->hcon->pending_sec_level); | ||
912 | |||
910 | read_lock(&conn->chan_lock); | 913 | read_lock(&conn->chan_lock); |
911 | 914 | ||
912 | list_for_each_entry(chan, &conn->chan_l, list) { | 915 | list_for_each_entry(chan, &conn->chan_l, list) { |
@@ -986,8 +989,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
986 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) | 989 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) |
987 | del_timer_sync(&conn->info_timer); | 990 | del_timer_sync(&conn->info_timer); |
988 | 991 | ||
989 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | 992 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { |
990 | del_timer(&conn->security_timer); | 993 | del_timer(&conn->security_timer); |
994 | smp_chan_destroy(conn); | ||
995 | } | ||
991 | 996 | ||
992 | hcon->l2cap_data = NULL; | 997 | hcon->l2cap_data = NULL; |
993 | kfree(conn); | 998 | kfree(conn); |
@@ -1519,7 +1524,9 @@ struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *m | |||
1519 | return skb; | 1524 | return skb; |
1520 | } | 1525 | } |
1521 | 1526 | ||
1522 | struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen) | 1527 | static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, |
1528 | struct msghdr *msg, size_t len, | ||
1529 | u16 control, u16 sdulen) | ||
1523 | { | 1530 | { |
1524 | struct sock *sk = chan->sk; | 1531 | struct sock *sk = chan->sk; |
1525 | struct l2cap_conn *conn = chan->conn; | 1532 | struct l2cap_conn *conn = chan->conn; |
@@ -4093,6 +4100,11 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4093 | 4100 | ||
4094 | BT_DBG("conn %p", conn); | 4101 | BT_DBG("conn %p", conn); |
4095 | 4102 | ||
4103 | if (hcon->type == LE_LINK) { | ||
4104 | smp_distribute_keys(conn, 0); | ||
4105 | del_timer(&conn->security_timer); | ||
4106 | } | ||
4107 | |||
4096 | read_lock(&conn->chan_lock); | 4108 | read_lock(&conn->chan_lock); |
4097 | 4109 | ||
4098 | list_for_each_entry(chan, &conn->chan_l, list) { | 4110 | list_for_each_entry(chan, &conn->chan_l, list) { |
@@ -4105,9 +4117,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4105 | if (chan->scid == L2CAP_CID_LE_DATA) { | 4117 | if (chan->scid == L2CAP_CID_LE_DATA) { |
4106 | if (!status && encrypt) { | 4118 | if (!status && encrypt) { |
4107 | chan->sec_level = hcon->sec_level; | 4119 | chan->sec_level = hcon->sec_level; |
4108 | del_timer(&conn->security_timer); | ||
4109 | l2cap_chan_ready(sk); | 4120 | l2cap_chan_ready(sk); |
4110 | smp_distribute_keys(conn, 0); | ||
4111 | } | 4121 | } |
4112 | 4122 | ||
4113 | bh_unlock_sock(sk); | 4123 | bh_unlock_sock(sk); |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 53e109eb043e..5a94eec06caa 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -908,7 +908,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
908 | struct hci_dev *hdev; | 908 | struct hci_dev *hdev; |
909 | struct mgmt_cp_load_keys *cp; | 909 | struct mgmt_cp_load_keys *cp; |
910 | u16 key_count, expected_len; | 910 | u16 key_count, expected_len; |
911 | int i, err; | 911 | int i; |
912 | 912 | ||
913 | cp = (void *) data; | 913 | cp = (void *) data; |
914 | 914 | ||
@@ -918,9 +918,9 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
918 | key_count = get_unaligned_le16(&cp->key_count); | 918 | key_count = get_unaligned_le16(&cp->key_count); |
919 | 919 | ||
920 | expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info); | 920 | expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info); |
921 | if (expected_len > len) { | 921 | if (expected_len != len) { |
922 | BT_ERR("load_keys: expected at least %u bytes, got %u bytes", | 922 | BT_ERR("load_keys: expected %u bytes, got %u bytes", |
923 | expected_len, len); | 923 | len, expected_len); |
924 | return -EINVAL; | 924 | return -EINVAL; |
925 | } | 925 | } |
926 | 926 | ||
@@ -942,36 +942,17 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
942 | else | 942 | else |
943 | clear_bit(HCI_DEBUG_KEYS, &hdev->flags); | 943 | clear_bit(HCI_DEBUG_KEYS, &hdev->flags); |
944 | 944 | ||
945 | len -= sizeof(*cp); | 945 | for (i = 0; i < key_count; i++) { |
946 | i = 0; | 946 | struct mgmt_key_info *key = &cp->keys[i]; |
947 | |||
948 | while (i < len) { | ||
949 | struct mgmt_key_info *key = (void *) cp->keys + i; | ||
950 | |||
951 | i += sizeof(*key) + key->dlen; | ||
952 | |||
953 | if (key->type == HCI_LK_SMP_LTK) { | ||
954 | struct key_master_id *id = (void *) key->data; | ||
955 | |||
956 | if (key->dlen != sizeof(struct key_master_id)) | ||
957 | continue; | ||
958 | |||
959 | hci_add_ltk(hdev, 0, &key->bdaddr, key->pin_len, | ||
960 | id->ediv, id->rand, key->val); | ||
961 | |||
962 | continue; | ||
963 | } | ||
964 | 947 | ||
965 | hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, | 948 | hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, |
966 | key->pin_len); | 949 | key->pin_len); |
967 | } | 950 | } |
968 | 951 | ||
969 | err = cmd_complete(sk, index, MGMT_OP_LOAD_KEYS, NULL, 0); | ||
970 | |||
971 | hci_dev_unlock_bh(hdev); | 952 | hci_dev_unlock_bh(hdev); |
972 | hci_dev_put(hdev); | 953 | hci_dev_put(hdev); |
973 | 954 | ||
974 | return err; | 955 | return 0; |
975 | } | 956 | } |
976 | 957 | ||
977 | static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) | 958 | static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) |
@@ -1347,6 +1328,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1347 | struct hci_dev *hdev; | 1328 | struct hci_dev *hdev; |
1348 | struct mgmt_cp_pair_device *cp; | 1329 | struct mgmt_cp_pair_device *cp; |
1349 | struct pending_cmd *cmd; | 1330 | struct pending_cmd *cmd; |
1331 | struct adv_entry *entry; | ||
1350 | u8 sec_level, auth_type; | 1332 | u8 sec_level, auth_type; |
1351 | struct hci_conn *conn; | 1333 | struct hci_conn *conn; |
1352 | int err; | 1334 | int err; |
@@ -1364,15 +1346,20 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1364 | 1346 | ||
1365 | hci_dev_lock_bh(hdev); | 1347 | hci_dev_lock_bh(hdev); |
1366 | 1348 | ||
1367 | if (cp->io_cap == 0x03) { | 1349 | sec_level = BT_SECURITY_MEDIUM; |
1368 | sec_level = BT_SECURITY_MEDIUM; | 1350 | if (cp->io_cap == 0x03) |
1369 | auth_type = HCI_AT_DEDICATED_BONDING; | 1351 | auth_type = HCI_AT_DEDICATED_BONDING; |
1370 | } else { | 1352 | else |
1371 | sec_level = BT_SECURITY_HIGH; | ||
1372 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; | 1353 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; |
1373 | } | ||
1374 | 1354 | ||
1375 | conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, auth_type); | 1355 | entry = hci_find_adv_entry(hdev, &cp->bdaddr); |
1356 | if (entry) | ||
1357 | conn = hci_connect(hdev, LE_LINK, &cp->bdaddr, sec_level, | ||
1358 | auth_type); | ||
1359 | else | ||
1360 | conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, | ||
1361 | auth_type); | ||
1362 | |||
1376 | if (IS_ERR(conn)) { | 1363 | if (IS_ERR(conn)) { |
1377 | err = PTR_ERR(conn); | 1364 | err = PTR_ERR(conn); |
1378 | goto unlock; | 1365 | goto unlock; |
@@ -1391,7 +1378,10 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1391 | goto unlock; | 1378 | goto unlock; |
1392 | } | 1379 | } |
1393 | 1380 | ||
1394 | conn->connect_cfm_cb = pairing_complete_cb; | 1381 | /* For LE, just connecting isn't a proof that the pairing finished */ |
1382 | if (!entry) | ||
1383 | conn->connect_cfm_cb = pairing_complete_cb; | ||
1384 | |||
1395 | conn->security_cfm_cb = pairing_complete_cb; | 1385 | conn->security_cfm_cb = pairing_complete_cb; |
1396 | conn->disconn_cfm_cb = pairing_complete_cb; | 1386 | conn->disconn_cfm_cb = pairing_complete_cb; |
1397 | conn->io_capability = cp->io_cap; | 1387 | conn->io_capability = cp->io_cap; |
@@ -1689,13 +1679,12 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, | |||
1689 | u16 len) | 1679 | u16 len) |
1690 | { | 1680 | { |
1691 | struct hci_dev *hdev; | 1681 | struct hci_dev *hdev; |
1692 | struct mgmt_cp_block_device *cp; | 1682 | struct pending_cmd *cmd; |
1683 | struct mgmt_cp_block_device *cp = (void *) data; | ||
1693 | int err; | 1684 | int err; |
1694 | 1685 | ||
1695 | BT_DBG("hci%u", index); | 1686 | BT_DBG("hci%u", index); |
1696 | 1687 | ||
1697 | cp = (void *) data; | ||
1698 | |||
1699 | if (len != sizeof(*cp)) | 1688 | if (len != sizeof(*cp)) |
1700 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, | 1689 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, |
1701 | EINVAL); | 1690 | EINVAL); |
@@ -1705,6 +1694,14 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, | |||
1705 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, | 1694 | return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, |
1706 | ENODEV); | 1695 | ENODEV); |
1707 | 1696 | ||
1697 | hci_dev_lock_bh(hdev); | ||
1698 | |||
1699 | cmd = mgmt_pending_add(sk, MGMT_OP_BLOCK_DEVICE, index, NULL, 0); | ||
1700 | if (!cmd) { | ||
1701 | err = -ENOMEM; | ||
1702 | goto failed; | ||
1703 | } | ||
1704 | |||
1708 | err = hci_blacklist_add(hdev, &cp->bdaddr); | 1705 | err = hci_blacklist_add(hdev, &cp->bdaddr); |
1709 | 1706 | ||
1710 | if (err < 0) | 1707 | if (err < 0) |
@@ -1712,6 +1709,11 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, | |||
1712 | else | 1709 | else |
1713 | err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, | 1710 | err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, |
1714 | NULL, 0); | 1711 | NULL, 0); |
1712 | |||
1713 | mgmt_pending_remove(cmd); | ||
1714 | |||
1715 | failed: | ||
1716 | hci_dev_unlock_bh(hdev); | ||
1715 | hci_dev_put(hdev); | 1717 | hci_dev_put(hdev); |
1716 | 1718 | ||
1717 | return err; | 1719 | return err; |
@@ -1721,13 +1723,12 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, | |||
1721 | u16 len) | 1723 | u16 len) |
1722 | { | 1724 | { |
1723 | struct hci_dev *hdev; | 1725 | struct hci_dev *hdev; |
1724 | struct mgmt_cp_unblock_device *cp; | 1726 | struct pending_cmd *cmd; |
1727 | struct mgmt_cp_unblock_device *cp = (void *) data; | ||
1725 | int err; | 1728 | int err; |
1726 | 1729 | ||
1727 | BT_DBG("hci%u", index); | 1730 | BT_DBG("hci%u", index); |
1728 | 1731 | ||
1729 | cp = (void *) data; | ||
1730 | |||
1731 | if (len != sizeof(*cp)) | 1732 | if (len != sizeof(*cp)) |
1732 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, | 1733 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1733 | EINVAL); | 1734 | EINVAL); |
@@ -1737,6 +1738,14 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, | |||
1737 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, | 1738 | return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1738 | ENODEV); | 1739 | ENODEV); |
1739 | 1740 | ||
1741 | hci_dev_lock_bh(hdev); | ||
1742 | |||
1743 | cmd = mgmt_pending_add(sk, MGMT_OP_UNBLOCK_DEVICE, index, NULL, 0); | ||
1744 | if (!cmd) { | ||
1745 | err = -ENOMEM; | ||
1746 | goto failed; | ||
1747 | } | ||
1748 | |||
1740 | err = hci_blacklist_del(hdev, &cp->bdaddr); | 1749 | err = hci_blacklist_del(hdev, &cp->bdaddr); |
1741 | 1750 | ||
1742 | if (err < 0) | 1751 | if (err < 0) |
@@ -1744,6 +1753,67 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, | |||
1744 | else | 1753 | else |
1745 | err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, | 1754 | err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, |
1746 | NULL, 0); | 1755 | NULL, 0); |
1756 | |||
1757 | mgmt_pending_remove(cmd); | ||
1758 | |||
1759 | failed: | ||
1760 | hci_dev_unlock_bh(hdev); | ||
1761 | hci_dev_put(hdev); | ||
1762 | |||
1763 | return err; | ||
1764 | } | ||
1765 | |||
1766 | static int set_fast_connectable(struct sock *sk, u16 index, | ||
1767 | unsigned char *data, u16 len) | ||
1768 | { | ||
1769 | struct hci_dev *hdev; | ||
1770 | struct mgmt_cp_set_fast_connectable *cp = (void *) data; | ||
1771 | struct hci_cp_write_page_scan_activity acp; | ||
1772 | u8 type; | ||
1773 | int err; | ||
1774 | |||
1775 | BT_DBG("hci%u", index); | ||
1776 | |||
1777 | if (len != sizeof(*cp)) | ||
1778 | return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | ||
1779 | EINVAL); | ||
1780 | |||
1781 | hdev = hci_dev_get(index); | ||
1782 | if (!hdev) | ||
1783 | return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | ||
1784 | ENODEV); | ||
1785 | |||
1786 | hci_dev_lock(hdev); | ||
1787 | |||
1788 | if (cp->enable) { | ||
1789 | type = PAGE_SCAN_TYPE_INTERLACED; | ||
1790 | acp.interval = 0x0024; /* 22.5 msec page scan interval */ | ||
1791 | } else { | ||
1792 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | ||
1793 | acp.interval = 0x0800; /* default 1.28 sec page scan */ | ||
1794 | } | ||
1795 | |||
1796 | acp.window = 0x0012; /* default 11.25 msec page scan window */ | ||
1797 | |||
1798 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, | ||
1799 | sizeof(acp), &acp); | ||
1800 | if (err < 0) { | ||
1801 | err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | ||
1802 | -err); | ||
1803 | goto done; | ||
1804 | } | ||
1805 | |||
1806 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | ||
1807 | if (err < 0) { | ||
1808 | err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | ||
1809 | -err); | ||
1810 | goto done; | ||
1811 | } | ||
1812 | |||
1813 | err = cmd_complete(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, | ||
1814 | NULL, 0); | ||
1815 | done: | ||
1816 | hci_dev_unlock(hdev); | ||
1747 | hci_dev_put(hdev); | 1817 | hci_dev_put(hdev); |
1748 | 1818 | ||
1749 | return err; | 1819 | return err; |
@@ -1869,6 +1939,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
1869 | case MGMT_OP_UNBLOCK_DEVICE: | 1939 | case MGMT_OP_UNBLOCK_DEVICE: |
1870 | err = unblock_device(sk, index, buf + sizeof(*hdr), len); | 1940 | err = unblock_device(sk, index, buf + sizeof(*hdr), len); |
1871 | break; | 1941 | break; |
1942 | case MGMT_OP_SET_FAST_CONNECTABLE: | ||
1943 | err = set_fast_connectable(sk, index, buf + sizeof(*hdr), | ||
1944 | len); | ||
1945 | break; | ||
1872 | default: | 1946 | default: |
1873 | BT_DBG("Unknown op %u", opcode); | 1947 | BT_DBG("Unknown op %u", opcode); |
1874 | err = cmd_status(sk, index, opcode, 0x01); | 1948 | err = cmd_status(sk, index, opcode, 0x01); |
@@ -1977,35 +2051,25 @@ int mgmt_connectable(u16 index, u8 connectable) | |||
1977 | 2051 | ||
1978 | int mgmt_new_key(u16 index, struct link_key *key, u8 persistent) | 2052 | int mgmt_new_key(u16 index, struct link_key *key, u8 persistent) |
1979 | { | 2053 | { |
1980 | struct mgmt_ev_new_key *ev; | 2054 | struct mgmt_ev_new_key ev; |
1981 | int err, total; | ||
1982 | |||
1983 | total = sizeof(struct mgmt_ev_new_key) + key->dlen; | ||
1984 | ev = kzalloc(total, GFP_ATOMIC); | ||
1985 | if (!ev) | ||
1986 | return -ENOMEM; | ||
1987 | |||
1988 | bacpy(&ev->key.bdaddr, &key->bdaddr); | ||
1989 | ev->key.type = key->type; | ||
1990 | memcpy(ev->key.val, key->val, 16); | ||
1991 | ev->key.pin_len = key->pin_len; | ||
1992 | ev->key.dlen = key->dlen; | ||
1993 | ev->store_hint = persistent; | ||
1994 | 2055 | ||
1995 | memcpy(ev->key.data, key->data, key->dlen); | 2056 | memset(&ev, 0, sizeof(ev)); |
1996 | |||
1997 | err = mgmt_event(MGMT_EV_NEW_KEY, index, ev, total, NULL); | ||
1998 | 2057 | ||
1999 | kfree(ev); | 2058 | ev.store_hint = persistent; |
2059 | bacpy(&ev.key.bdaddr, &key->bdaddr); | ||
2060 | ev.key.type = key->type; | ||
2061 | memcpy(ev.key.val, key->val, 16); | ||
2062 | ev.key.pin_len = key->pin_len; | ||
2000 | 2063 | ||
2001 | return err; | 2064 | return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL); |
2002 | } | 2065 | } |
2003 | 2066 | ||
2004 | int mgmt_connected(u16 index, bdaddr_t *bdaddr) | 2067 | int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type) |
2005 | { | 2068 | { |
2006 | struct mgmt_ev_connected ev; | 2069 | struct mgmt_ev_connected ev; |
2007 | 2070 | ||
2008 | bacpy(&ev.bdaddr, bdaddr); | 2071 | bacpy(&ev.bdaddr, bdaddr); |
2072 | ev.link_type = link_type; | ||
2009 | 2073 | ||
2010 | return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL); | 2074 | return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL); |
2011 | } | 2075 | } |
@@ -2260,12 +2324,14 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, | |||
2260 | memset(&ev, 0, sizeof(ev)); | 2324 | memset(&ev, 0, sizeof(ev)); |
2261 | 2325 | ||
2262 | bacpy(&ev.bdaddr, bdaddr); | 2326 | bacpy(&ev.bdaddr, bdaddr); |
2263 | memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); | ||
2264 | ev.rssi = rssi; | 2327 | ev.rssi = rssi; |
2265 | 2328 | ||
2266 | if (eir) | 2329 | if (eir) |
2267 | memcpy(ev.eir, eir, sizeof(ev.eir)); | 2330 | memcpy(ev.eir, eir, sizeof(ev.eir)); |
2268 | 2331 | ||
2332 | if (dev_class) | ||
2333 | memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class)); | ||
2334 | |||
2269 | return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); | 2335 | return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL); |
2270 | } | 2336 | } |
2271 | 2337 | ||
@@ -2286,3 +2352,29 @@ int mgmt_discovering(u16 index, u8 discovering) | |||
2286 | return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering, | 2352 | return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering, |
2287 | sizeof(discovering), NULL); | 2353 | sizeof(discovering), NULL); |
2288 | } | 2354 | } |
2355 | |||
2356 | int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr) | ||
2357 | { | ||
2358 | struct pending_cmd *cmd; | ||
2359 | struct mgmt_ev_device_blocked ev; | ||
2360 | |||
2361 | cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, index); | ||
2362 | |||
2363 | bacpy(&ev.bdaddr, bdaddr); | ||
2364 | |||
2365 | return mgmt_event(MGMT_EV_DEVICE_BLOCKED, index, &ev, sizeof(ev), | ||
2366 | cmd ? cmd->sk : NULL); | ||
2367 | } | ||
2368 | |||
2369 | int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr) | ||
2370 | { | ||
2371 | struct pending_cmd *cmd; | ||
2372 | struct mgmt_ev_device_unblocked ev; | ||
2373 | |||
2374 | cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, index); | ||
2375 | |||
2376 | bacpy(&ev.bdaddr, bdaddr); | ||
2377 | |||
2378 | return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, index, &ev, sizeof(ev), | ||
2379 | cmd ? cmd->sk : NULL); | ||
2380 | } | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 391888b88a92..759b63572641 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -182,18 +182,9 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) | |||
182 | return; | 182 | return; |
183 | 183 | ||
184 | hci_send_acl(conn->hcon, skb, 0); | 184 | hci_send_acl(conn->hcon, skb, 0); |
185 | } | ||
186 | |||
187 | static __u8 seclevel_to_authreq(__u8 level) | ||
188 | { | ||
189 | switch (level) { | ||
190 | case BT_SECURITY_HIGH: | ||
191 | /* Right now we don't support bonding */ | ||
192 | return SMP_AUTH_MITM; | ||
193 | 185 | ||
194 | default: | 186 | mod_timer(&conn->security_timer, jiffies + |
195 | return SMP_AUTH_NONE; | 187 | msecs_to_jiffies(SMP_TIMEOUT)); |
196 | } | ||
197 | } | 188 | } |
198 | 189 | ||
199 | static void build_pairing_cmd(struct l2cap_conn *conn, | 190 | static void build_pairing_cmd(struct l2cap_conn *conn, |
@@ -205,7 +196,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
205 | 196 | ||
206 | dist_keys = 0; | 197 | dist_keys = 0; |
207 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) { | 198 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) { |
208 | dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN; | 199 | dist_keys = SMP_DIST_ENC_KEY; |
209 | authreq |= SMP_AUTH_BONDING; | 200 | authreq |= SMP_AUTH_BONDING; |
210 | } | 201 | } |
211 | 202 | ||
@@ -229,24 +220,184 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
229 | 220 | ||
230 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | 221 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) |
231 | { | 222 | { |
223 | struct smp_chan *smp = conn->smp_chan; | ||
224 | |||
232 | if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || | 225 | if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || |
233 | (max_key_size < SMP_MIN_ENC_KEY_SIZE)) | 226 | (max_key_size < SMP_MIN_ENC_KEY_SIZE)) |
234 | return SMP_ENC_KEY_SIZE; | 227 | return SMP_ENC_KEY_SIZE; |
235 | 228 | ||
236 | conn->smp_key_size = max_key_size; | 229 | smp->smp_key_size = max_key_size; |
237 | 230 | ||
238 | return 0; | 231 | return 0; |
239 | } | 232 | } |
240 | 233 | ||
234 | static void confirm_work(struct work_struct *work) | ||
235 | { | ||
236 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); | ||
237 | struct l2cap_conn *conn = smp->conn; | ||
238 | struct crypto_blkcipher *tfm; | ||
239 | struct smp_cmd_pairing_confirm cp; | ||
240 | int ret; | ||
241 | u8 res[16], reason; | ||
242 | |||
243 | BT_DBG("conn %p", conn); | ||
244 | |||
245 | tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); | ||
246 | if (IS_ERR(tfm)) { | ||
247 | reason = SMP_UNSPECIFIED; | ||
248 | goto error; | ||
249 | } | ||
250 | |||
251 | smp->tfm = tfm; | ||
252 | |||
253 | if (conn->hcon->out) | ||
254 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, | ||
255 | conn->src, conn->hcon->dst_type, conn->dst, | ||
256 | res); | ||
257 | else | ||
258 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | ||
259 | conn->hcon->dst_type, conn->dst, 0, conn->src, | ||
260 | res); | ||
261 | if (ret) { | ||
262 | reason = SMP_UNSPECIFIED; | ||
263 | goto error; | ||
264 | } | ||
265 | |||
266 | swap128(res, cp.confirm_val); | ||
267 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | ||
268 | |||
269 | return; | ||
270 | |||
271 | error: | ||
272 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); | ||
273 | smp_chan_destroy(conn); | ||
274 | } | ||
275 | |||
276 | static void random_work(struct work_struct *work) | ||
277 | { | ||
278 | struct smp_chan *smp = container_of(work, struct smp_chan, random); | ||
279 | struct l2cap_conn *conn = smp->conn; | ||
280 | struct hci_conn *hcon = conn->hcon; | ||
281 | struct crypto_blkcipher *tfm = smp->tfm; | ||
282 | u8 reason, confirm[16], res[16], key[16]; | ||
283 | int ret; | ||
284 | |||
285 | if (IS_ERR_OR_NULL(tfm)) { | ||
286 | reason = SMP_UNSPECIFIED; | ||
287 | goto error; | ||
288 | } | ||
289 | |||
290 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | ||
291 | |||
292 | if (hcon->out) | ||
293 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, | ||
294 | conn->src, hcon->dst_type, conn->dst, | ||
295 | res); | ||
296 | else | ||
297 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, | ||
298 | hcon->dst_type, conn->dst, 0, conn->src, | ||
299 | res); | ||
300 | if (ret) { | ||
301 | reason = SMP_UNSPECIFIED; | ||
302 | goto error; | ||
303 | } | ||
304 | |||
305 | swap128(res, confirm); | ||
306 | |||
307 | if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { | ||
308 | BT_ERR("Pairing failed (confirmation values mismatch)"); | ||
309 | reason = SMP_CONFIRM_FAILED; | ||
310 | goto error; | ||
311 | } | ||
312 | |||
313 | if (hcon->out) { | ||
314 | u8 stk[16], rand[8]; | ||
315 | __le16 ediv; | ||
316 | |||
317 | memset(rand, 0, sizeof(rand)); | ||
318 | ediv = 0; | ||
319 | |||
320 | smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); | ||
321 | swap128(key, stk); | ||
322 | |||
323 | memset(stk + smp->smp_key_size, 0, | ||
324 | SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); | ||
325 | |||
326 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) { | ||
327 | reason = SMP_UNSPECIFIED; | ||
328 | goto error; | ||
329 | } | ||
330 | |||
331 | hci_le_start_enc(hcon, ediv, rand, stk); | ||
332 | hcon->enc_key_size = smp->smp_key_size; | ||
333 | } else { | ||
334 | u8 stk[16], r[16], rand[8]; | ||
335 | __le16 ediv; | ||
336 | |||
337 | memset(rand, 0, sizeof(rand)); | ||
338 | ediv = 0; | ||
339 | |||
340 | swap128(smp->prnd, r); | ||
341 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); | ||
342 | |||
343 | smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); | ||
344 | swap128(key, stk); | ||
345 | |||
346 | memset(stk + smp->smp_key_size, 0, | ||
347 | SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); | ||
348 | |||
349 | hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size, | ||
350 | ediv, rand, stk); | ||
351 | } | ||
352 | |||
353 | return; | ||
354 | |||
355 | error: | ||
356 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); | ||
357 | smp_chan_destroy(conn); | ||
358 | } | ||
359 | |||
360 | static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | ||
361 | { | ||
362 | struct smp_chan *smp; | ||
363 | |||
364 | smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); | ||
365 | if (!smp) | ||
366 | return NULL; | ||
367 | |||
368 | INIT_WORK(&smp->confirm, confirm_work); | ||
369 | INIT_WORK(&smp->random, random_work); | ||
370 | |||
371 | smp->conn = conn; | ||
372 | conn->smp_chan = smp; | ||
373 | |||
374 | hci_conn_hold(conn->hcon); | ||
375 | |||
376 | return smp; | ||
377 | } | ||
378 | |||
379 | void smp_chan_destroy(struct l2cap_conn *conn) | ||
380 | { | ||
381 | kfree(conn->smp_chan); | ||
382 | hci_conn_put(conn->hcon); | ||
383 | } | ||
384 | |||
241 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | 385 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) |
242 | { | 386 | { |
243 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; | 387 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; |
388 | struct smp_chan *smp; | ||
244 | u8 key_size; | 389 | u8 key_size; |
390 | int ret; | ||
245 | 391 | ||
246 | BT_DBG("conn %p", conn); | 392 | BT_DBG("conn %p", conn); |
247 | 393 | ||
248 | conn->preq[0] = SMP_CMD_PAIRING_REQ; | 394 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) |
249 | memcpy(&conn->preq[1], req, sizeof(*req)); | 395 | smp = smp_chan_create(conn); |
396 | |||
397 | smp = conn->smp_chan; | ||
398 | |||
399 | smp->preq[0] = SMP_CMD_PAIRING_REQ; | ||
400 | memcpy(&smp->preq[1], req, sizeof(*req)); | ||
250 | skb_pull(skb, sizeof(*req)); | 401 | skb_pull(skb, sizeof(*req)); |
251 | 402 | ||
252 | if (req->oob_flag) | 403 | if (req->oob_flag) |
@@ -260,32 +411,33 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
260 | return SMP_ENC_KEY_SIZE; | 411 | return SMP_ENC_KEY_SIZE; |
261 | 412 | ||
262 | /* Just works */ | 413 | /* Just works */ |
263 | memset(conn->tk, 0, sizeof(conn->tk)); | 414 | memset(smp->tk, 0, sizeof(smp->tk)); |
415 | |||
416 | ret = smp_rand(smp->prnd); | ||
417 | if (ret) | ||
418 | return SMP_UNSPECIFIED; | ||
264 | 419 | ||
265 | conn->prsp[0] = SMP_CMD_PAIRING_RSP; | 420 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
266 | memcpy(&conn->prsp[1], &rsp, sizeof(rsp)); | 421 | memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); |
267 | 422 | ||
268 | smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); | 423 | smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp); |
269 | 424 | ||
270 | mod_timer(&conn->security_timer, jiffies + | ||
271 | msecs_to_jiffies(SMP_TIMEOUT)); | ||
272 | |||
273 | return 0; | 425 | return 0; |
274 | } | 426 | } |
275 | 427 | ||
276 | static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | 428 | static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) |
277 | { | 429 | { |
278 | struct smp_cmd_pairing *req, *rsp = (void *) skb->data; | 430 | struct smp_cmd_pairing *req, *rsp = (void *) skb->data; |
279 | struct smp_cmd_pairing_confirm cp; | 431 | struct smp_chan *smp = conn->smp_chan; |
280 | struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm; | 432 | struct hci_dev *hdev = conn->hcon->hdev; |
433 | u8 key_size; | ||
281 | int ret; | 434 | int ret; |
282 | u8 res[16], key_size; | ||
283 | 435 | ||
284 | BT_DBG("conn %p", conn); | 436 | BT_DBG("conn %p", conn); |
285 | 437 | ||
286 | skb_pull(skb, sizeof(*rsp)); | 438 | skb_pull(skb, sizeof(*rsp)); |
287 | 439 | ||
288 | req = (void *) &conn->preq[1]; | 440 | req = (void *) &smp->preq[1]; |
289 | 441 | ||
290 | key_size = min(req->max_key_size, rsp->max_key_size); | 442 | key_size = min(req->max_key_size, rsp->max_key_size); |
291 | if (check_enc_key_size(conn, key_size)) | 443 | if (check_enc_key_size(conn, key_size)) |
@@ -295,222 +447,154 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
295 | return SMP_OOB_NOT_AVAIL; | 447 | return SMP_OOB_NOT_AVAIL; |
296 | 448 | ||
297 | /* Just works */ | 449 | /* Just works */ |
298 | memset(conn->tk, 0, sizeof(conn->tk)); | 450 | memset(smp->tk, 0, sizeof(smp->tk)); |
299 | |||
300 | conn->prsp[0] = SMP_CMD_PAIRING_RSP; | ||
301 | memcpy(&conn->prsp[1], rsp, sizeof(*rsp)); | ||
302 | |||
303 | ret = smp_rand(conn->prnd); | ||
304 | if (ret) | ||
305 | return SMP_UNSPECIFIED; | ||
306 | 451 | ||
307 | ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0, | 452 | ret = smp_rand(smp->prnd); |
308 | conn->src, conn->hcon->dst_type, conn->dst, res); | ||
309 | if (ret) | 453 | if (ret) |
310 | return SMP_UNSPECIFIED; | 454 | return SMP_UNSPECIFIED; |
311 | 455 | ||
312 | swap128(res, cp.confirm_val); | 456 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
457 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); | ||
313 | 458 | ||
314 | smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | 459 | queue_work(hdev->workqueue, &smp->confirm); |
315 | 460 | ||
316 | return 0; | 461 | return 0; |
317 | } | 462 | } |
318 | 463 | ||
319 | static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | 464 | static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) |
320 | { | 465 | { |
321 | struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm; | 466 | struct smp_chan *smp = conn->smp_chan; |
467 | struct hci_dev *hdev = conn->hcon->hdev; | ||
322 | 468 | ||
323 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | 469 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); |
324 | 470 | ||
325 | memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf)); | 471 | memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); |
326 | skb_pull(skb, sizeof(conn->pcnf)); | 472 | skb_pull(skb, sizeof(smp->pcnf)); |
327 | 473 | ||
328 | if (conn->hcon->out) { | 474 | if (conn->hcon->out) { |
329 | u8 random[16]; | 475 | u8 random[16]; |
330 | 476 | ||
331 | swap128(conn->prnd, random); | 477 | swap128(smp->prnd, random); |
332 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), | 478 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), |
333 | random); | 479 | random); |
334 | } else { | 480 | } else { |
335 | struct smp_cmd_pairing_confirm cp; | 481 | queue_work(hdev->workqueue, &smp->confirm); |
336 | int ret; | ||
337 | u8 res[16]; | ||
338 | |||
339 | ret = smp_rand(conn->prnd); | ||
340 | if (ret) | ||
341 | return SMP_UNSPECIFIED; | ||
342 | |||
343 | ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, | ||
344 | conn->hcon->dst_type, conn->dst, | ||
345 | 0, conn->src, res); | ||
346 | if (ret) | ||
347 | return SMP_CONFIRM_FAILED; | ||
348 | |||
349 | swap128(res, cp.confirm_val); | ||
350 | |||
351 | smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | ||
352 | } | 482 | } |
353 | 483 | ||
354 | mod_timer(&conn->security_timer, jiffies + | ||
355 | msecs_to_jiffies(SMP_TIMEOUT)); | ||
356 | |||
357 | return 0; | 484 | return 0; |
358 | } | 485 | } |
359 | 486 | ||
360 | static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | 487 | static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) |
361 | { | 488 | { |
362 | struct hci_conn *hcon = conn->hcon; | 489 | struct smp_chan *smp = conn->smp_chan; |
363 | struct crypto_blkcipher *tfm = hcon->hdev->tfm; | 490 | struct hci_dev *hdev = conn->hcon->hdev; |
364 | int ret; | ||
365 | u8 key[16], res[16], random[16], confirm[16]; | ||
366 | 491 | ||
367 | swap128(skb->data, random); | 492 | BT_DBG("conn %p", conn); |
368 | skb_pull(skb, sizeof(random)); | ||
369 | |||
370 | if (conn->hcon->out) | ||
371 | ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0, | ||
372 | conn->src, conn->hcon->dst_type, conn->dst, | ||
373 | res); | ||
374 | else | ||
375 | ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, | ||
376 | conn->hcon->dst_type, conn->dst, 0, conn->src, | ||
377 | res); | ||
378 | if (ret) | ||
379 | return SMP_UNSPECIFIED; | ||
380 | |||
381 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | ||
382 | |||
383 | swap128(res, confirm); | ||
384 | |||
385 | if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) { | ||
386 | BT_ERR("Pairing failed (confirmation values mismatch)"); | ||
387 | return SMP_CONFIRM_FAILED; | ||
388 | } | ||
389 | |||
390 | if (conn->hcon->out) { | ||
391 | u8 stk[16], rand[8]; | ||
392 | __le16 ediv; | ||
393 | |||
394 | memset(rand, 0, sizeof(rand)); | ||
395 | ediv = 0; | ||
396 | 493 | ||
397 | smp_s1(tfm, conn->tk, random, conn->prnd, key); | 494 | swap128(skb->data, smp->rrnd); |
398 | swap128(key, stk); | 495 | skb_pull(skb, sizeof(smp->rrnd)); |
399 | 496 | ||
400 | memset(stk + conn->smp_key_size, 0, | 497 | queue_work(hdev->workqueue, &smp->random); |
401 | SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size); | ||
402 | 498 | ||
403 | hci_le_start_enc(hcon, ediv, rand, stk); | 499 | return 0; |
404 | hcon->enc_key_size = conn->smp_key_size; | 500 | } |
405 | } else { | ||
406 | u8 stk[16], r[16], rand[8]; | ||
407 | __le16 ediv; | ||
408 | 501 | ||
409 | memset(rand, 0, sizeof(rand)); | 502 | static u8 smp_ltk_encrypt(struct l2cap_conn *conn) |
410 | ediv = 0; | 503 | { |
504 | struct link_key *key; | ||
505 | struct key_master_id *master; | ||
506 | struct hci_conn *hcon = conn->hcon; | ||
411 | 507 | ||
412 | swap128(conn->prnd, r); | 508 | key = hci_find_link_key_type(hcon->hdev, conn->dst, |
413 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); | 509 | HCI_LK_SMP_LTK); |
510 | if (!key) | ||
511 | return 0; | ||
414 | 512 | ||
415 | smp_s1(tfm, conn->tk, conn->prnd, random, key); | 513 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, |
416 | swap128(key, stk); | 514 | &hcon->pend)) |
515 | return 1; | ||
417 | 516 | ||
418 | memset(stk + conn->smp_key_size, 0, | 517 | master = (void *) key->data; |
419 | SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size); | 518 | hci_le_start_enc(hcon, master->ediv, master->rand, |
519 | key->val); | ||
520 | hcon->enc_key_size = key->pin_len; | ||
420 | 521 | ||
421 | hci_add_ltk(conn->hcon->hdev, 0, conn->dst, conn->smp_key_size, | 522 | return 1; |
422 | ediv, rand, stk); | ||
423 | } | ||
424 | 523 | ||
425 | return 0; | ||
426 | } | 524 | } |
427 | |||
428 | static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | 525 | static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) |
429 | { | 526 | { |
430 | struct smp_cmd_security_req *rp = (void *) skb->data; | 527 | struct smp_cmd_security_req *rp = (void *) skb->data; |
431 | struct smp_cmd_pairing cp; | 528 | struct smp_cmd_pairing cp; |
432 | struct hci_conn *hcon = conn->hcon; | 529 | struct hci_conn *hcon = conn->hcon; |
530 | struct smp_chan *smp; | ||
433 | 531 | ||
434 | BT_DBG("conn %p", conn); | 532 | BT_DBG("conn %p", conn); |
435 | 533 | ||
436 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | 534 | hcon->pending_sec_level = BT_SECURITY_MEDIUM; |
535 | |||
536 | if (smp_ltk_encrypt(conn)) | ||
437 | return 0; | 537 | return 0; |
438 | 538 | ||
539 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) | ||
540 | return 0; | ||
541 | |||
542 | smp = smp_chan_create(conn); | ||
543 | |||
439 | skb_pull(skb, sizeof(*rp)); | 544 | skb_pull(skb, sizeof(*rp)); |
440 | 545 | ||
441 | memset(&cp, 0, sizeof(cp)); | 546 | memset(&cp, 0, sizeof(cp)); |
442 | build_pairing_cmd(conn, &cp, NULL, rp->auth_req); | 547 | build_pairing_cmd(conn, &cp, NULL, rp->auth_req); |
443 | 548 | ||
444 | conn->preq[0] = SMP_CMD_PAIRING_REQ; | 549 | smp->preq[0] = SMP_CMD_PAIRING_REQ; |
445 | memcpy(&conn->preq[1], &cp, sizeof(cp)); | 550 | memcpy(&smp->preq[1], &cp, sizeof(cp)); |
446 | 551 | ||
447 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 552 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
448 | 553 | ||
449 | mod_timer(&conn->security_timer, jiffies + | ||
450 | msecs_to_jiffies(SMP_TIMEOUT)); | ||
451 | |||
452 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
453 | |||
454 | return 0; | 554 | return 0; |
455 | } | 555 | } |
456 | 556 | ||
457 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | 557 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) |
458 | { | 558 | { |
459 | struct hci_conn *hcon = conn->hcon; | 559 | struct hci_conn *hcon = conn->hcon; |
460 | __u8 authreq; | 560 | struct smp_chan *smp = conn->smp_chan; |
461 | 561 | ||
462 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); | 562 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); |
463 | 563 | ||
464 | if (!lmp_host_le_capable(hcon->hdev)) | 564 | if (!lmp_host_le_capable(hcon->hdev)) |
465 | return 1; | 565 | return 1; |
466 | 566 | ||
467 | if (IS_ERR(hcon->hdev->tfm)) | ||
468 | return 1; | ||
469 | |||
470 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | ||
471 | return 0; | ||
472 | |||
473 | if (sec_level == BT_SECURITY_LOW) | 567 | if (sec_level == BT_SECURITY_LOW) |
474 | return 1; | 568 | return 1; |
475 | 569 | ||
476 | if (hcon->sec_level >= sec_level) | 570 | if (hcon->sec_level >= sec_level) |
477 | return 1; | 571 | return 1; |
478 | 572 | ||
479 | authreq = seclevel_to_authreq(sec_level); | 573 | if (hcon->link_mode & HCI_LM_MASTER) |
480 | 574 | if (smp_ltk_encrypt(conn)) | |
481 | if (hcon->link_mode & HCI_LM_MASTER) { | 575 | goto done; |
482 | struct smp_cmd_pairing cp; | ||
483 | struct link_key *key; | ||
484 | 576 | ||
485 | key = hci_find_link_key_type(hcon->hdev, conn->dst, | 577 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) |
486 | HCI_LK_SMP_LTK); | 578 | return 0; |
487 | if (key) { | ||
488 | struct key_master_id *master = (void *) key->data; | ||
489 | 579 | ||
490 | hci_le_start_enc(hcon, master->ediv, master->rand, | 580 | smp = smp_chan_create(conn); |
491 | key->val); | ||
492 | hcon->enc_key_size = key->pin_len; | ||
493 | 581 | ||
494 | goto done; | 582 | if (hcon->link_mode & HCI_LM_MASTER) { |
495 | } | 583 | struct smp_cmd_pairing cp; |
496 | |||
497 | build_pairing_cmd(conn, &cp, NULL, authreq); | ||
498 | conn->preq[0] = SMP_CMD_PAIRING_REQ; | ||
499 | memcpy(&conn->preq[1], &cp, sizeof(cp)); | ||
500 | 584 | ||
501 | mod_timer(&conn->security_timer, jiffies + | 585 | build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE); |
502 | msecs_to_jiffies(SMP_TIMEOUT)); | 586 | smp->preq[0] = SMP_CMD_PAIRING_REQ; |
587 | memcpy(&smp->preq[1], &cp, sizeof(cp)); | ||
503 | 588 | ||
504 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 589 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
505 | } else { | 590 | } else { |
506 | struct smp_cmd_security_req cp; | 591 | struct smp_cmd_security_req cp; |
507 | cp.auth_req = authreq; | 592 | cp.auth_req = SMP_AUTH_NONE; |
508 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); | 593 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); |
509 | } | 594 | } |
510 | 595 | ||
511 | done: | 596 | done: |
512 | hcon->pending_sec_level = sec_level; | 597 | hcon->pending_sec_level = sec_level; |
513 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
514 | 598 | ||
515 | return 0; | 599 | return 0; |
516 | } | 600 | } |
@@ -518,10 +602,11 @@ done: | |||
518 | static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) | 602 | static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) |
519 | { | 603 | { |
520 | struct smp_cmd_encrypt_info *rp = (void *) skb->data; | 604 | struct smp_cmd_encrypt_info *rp = (void *) skb->data; |
605 | struct smp_chan *smp = conn->smp_chan; | ||
521 | 606 | ||
522 | skb_pull(skb, sizeof(*rp)); | 607 | skb_pull(skb, sizeof(*rp)); |
523 | 608 | ||
524 | memcpy(conn->tk, rp->ltk, sizeof(conn->tk)); | 609 | memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); |
525 | 610 | ||
526 | return 0; | 611 | return 0; |
527 | } | 612 | } |
@@ -529,11 +614,12 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) | |||
529 | static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) | 614 | static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) |
530 | { | 615 | { |
531 | struct smp_cmd_master_ident *rp = (void *) skb->data; | 616 | struct smp_cmd_master_ident *rp = (void *) skb->data; |
617 | struct smp_chan *smp = conn->smp_chan; | ||
532 | 618 | ||
533 | skb_pull(skb, sizeof(*rp)); | 619 | skb_pull(skb, sizeof(*rp)); |
534 | 620 | ||
535 | hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size, | 621 | hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size, |
536 | rp->ediv, rp->rand, conn->tk); | 622 | rp->ediv, rp->rand, smp->tk); |
537 | 623 | ||
538 | smp_distribute_keys(conn, 1); | 624 | smp_distribute_keys(conn, 1); |
539 | 625 | ||
@@ -552,12 +638,6 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
552 | goto done; | 638 | goto done; |
553 | } | 639 | } |
554 | 640 | ||
555 | if (IS_ERR(conn->hcon->hdev->tfm)) { | ||
556 | err = PTR_ERR(conn->hcon->hdev->tfm); | ||
557 | reason = SMP_PAIRING_NOTSUPP; | ||
558 | goto done; | ||
559 | } | ||
560 | |||
561 | skb_pull(skb, sizeof(code)); | 641 | skb_pull(skb, sizeof(code)); |
562 | 642 | ||
563 | switch (code) { | 643 | switch (code) { |
@@ -621,20 +701,21 @@ done: | |||
621 | int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | 701 | int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) |
622 | { | 702 | { |
623 | struct smp_cmd_pairing *req, *rsp; | 703 | struct smp_cmd_pairing *req, *rsp; |
704 | struct smp_chan *smp = conn->smp_chan; | ||
624 | __u8 *keydist; | 705 | __u8 *keydist; |
625 | 706 | ||
626 | BT_DBG("conn %p force %d", conn, force); | 707 | BT_DBG("conn %p force %d", conn, force); |
627 | 708 | ||
628 | if (IS_ERR(conn->hcon->hdev->tfm)) | 709 | if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) |
629 | return PTR_ERR(conn->hcon->hdev->tfm); | 710 | return 0; |
630 | 711 | ||
631 | rsp = (void *) &conn->prsp[1]; | 712 | rsp = (void *) &smp->prsp[1]; |
632 | 713 | ||
633 | /* The responder sends its keys first */ | 714 | /* The responder sends its keys first */ |
634 | if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) | 715 | if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) |
635 | return 0; | 716 | return 0; |
636 | 717 | ||
637 | req = (void *) &conn->preq[1]; | 718 | req = (void *) &smp->preq[1]; |
638 | 719 | ||
639 | if (conn->hcon->out) { | 720 | if (conn->hcon->out) { |
640 | keydist = &rsp->init_key_dist; | 721 | keydist = &rsp->init_key_dist; |
@@ -658,7 +739,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
658 | 739 | ||
659 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); | 740 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); |
660 | 741 | ||
661 | hci_add_ltk(conn->hcon->hdev, 1, conn->dst, conn->smp_key_size, | 742 | hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size, |
662 | ediv, ident.rand, enc.ltk); | 743 | ediv, ident.rand, enc.ltk); |
663 | 744 | ||
664 | ident.ediv = cpu_to_le16(ediv); | 745 | ident.ediv = cpu_to_le16(ediv); |
@@ -698,5 +779,11 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
698 | *keydist &= ~SMP_DIST_SIGN; | 779 | *keydist &= ~SMP_DIST_SIGN; |
699 | } | 780 | } |
700 | 781 | ||
782 | if (conn->hcon->out || force) { | ||
783 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); | ||
784 | del_timer(&conn->security_timer); | ||
785 | smp_chan_destroy(conn); | ||
786 | } | ||
787 | |||
701 | return 0; | 788 | return 0; |
702 | } | 789 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 567e3e54685a..9b1a95e1f56a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1271,9 +1271,11 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | static int ieee80211_set_txq_params(struct wiphy *wiphy, | 1273 | static int ieee80211_set_txq_params(struct wiphy *wiphy, |
1274 | struct net_device *dev, | ||
1274 | struct ieee80211_txq_params *params) | 1275 | struct ieee80211_txq_params *params) |
1275 | { | 1276 | { |
1276 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1277 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1278 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1277 | struct ieee80211_tx_queue_params p; | 1279 | struct ieee80211_tx_queue_params p; |
1278 | 1280 | ||
1279 | if (!local->ops->conf_tx) | 1281 | if (!local->ops->conf_tx) |
@@ -1294,8 +1296,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1294 | if (params->queue >= local->hw.queues) | 1296 | if (params->queue >= local->hw.queues) |
1295 | return -EINVAL; | 1297 | return -EINVAL; |
1296 | 1298 | ||
1297 | local->tx_conf[params->queue] = p; | 1299 | sdata->tx_conf[params->queue] = p; |
1298 | if (drv_conf_tx(local, params->queue, &p)) { | 1300 | if (drv_conf_tx(local, sdata, params->queue, &p)) { |
1299 | wiphy_debug(local->hw.wiphy, | 1301 | wiphy_debug(local->hw.wiphy, |
1300 | "failed to set TX queue parameters for queue %d\n", | 1302 | "failed to set TX queue parameters for queue %d\n", |
1301 | params->queue); | 1303 | params->queue); |
@@ -1869,7 +1871,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1869 | struct ieee80211_channel *chan, bool offchan, | 1871 | struct ieee80211_channel *chan, bool offchan, |
1870 | enum nl80211_channel_type channel_type, | 1872 | enum nl80211_channel_type channel_type, |
1871 | bool channel_type_valid, unsigned int wait, | 1873 | bool channel_type_valid, unsigned int wait, |
1872 | const u8 *buf, size_t len, u64 *cookie) | 1874 | const u8 *buf, size_t len, bool no_cck, |
1875 | u64 *cookie) | ||
1873 | { | 1876 | { |
1874 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1877 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1875 | struct ieee80211_local *local = sdata->local; | 1878 | struct ieee80211_local *local = sdata->local; |
@@ -1896,6 +1899,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1896 | flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | 1899 | flags |= IEEE80211_TX_CTL_TX_OFFCHAN; |
1897 | } | 1900 | } |
1898 | 1901 | ||
1902 | if (no_cck) | ||
1903 | flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | ||
1904 | |||
1899 | if (is_offchan && !offchan) | 1905 | if (is_offchan && !offchan) |
1900 | return -EBUSY; | 1906 | return -EBUSY; |
1901 | 1907 | ||
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index c9141168fd43..883996b2f99f 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -78,57 +78,6 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x", | |||
78 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", | 78 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s", |
79 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); | 79 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); |
80 | 80 | ||
81 | static ssize_t tsf_read(struct file *file, char __user *user_buf, | ||
82 | size_t count, loff_t *ppos) | ||
83 | { | ||
84 | struct ieee80211_local *local = file->private_data; | ||
85 | u64 tsf; | ||
86 | |||
87 | tsf = drv_get_tsf(local); | ||
88 | |||
89 | return mac80211_format_buffer(user_buf, count, ppos, "0x%016llx\n", | ||
90 | (unsigned long long) tsf); | ||
91 | } | ||
92 | |||
93 | static ssize_t tsf_write(struct file *file, | ||
94 | const char __user *user_buf, | ||
95 | size_t count, loff_t *ppos) | ||
96 | { | ||
97 | struct ieee80211_local *local = file->private_data; | ||
98 | unsigned long long tsf; | ||
99 | char buf[100]; | ||
100 | size_t len; | ||
101 | |||
102 | len = min(count, sizeof(buf) - 1); | ||
103 | if (copy_from_user(buf, user_buf, len)) | ||
104 | return -EFAULT; | ||
105 | buf[len] = '\0'; | ||
106 | |||
107 | if (strncmp(buf, "reset", 5) == 0) { | ||
108 | if (local->ops->reset_tsf) { | ||
109 | drv_reset_tsf(local); | ||
110 | wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); | ||
111 | } | ||
112 | } else { | ||
113 | tsf = simple_strtoul(buf, NULL, 0); | ||
114 | if (local->ops->set_tsf) { | ||
115 | drv_set_tsf(local, tsf); | ||
116 | wiphy_info(local->hw.wiphy, | ||
117 | "debugfs set TSF to %#018llx\n", tsf); | ||
118 | |||
119 | } | ||
120 | } | ||
121 | |||
122 | return count; | ||
123 | } | ||
124 | |||
125 | static const struct file_operations tsf_ops = { | ||
126 | .read = tsf_read, | ||
127 | .write = tsf_write, | ||
128 | .open = mac80211_open_file_generic, | ||
129 | .llseek = default_llseek, | ||
130 | }; | ||
131 | |||
132 | static ssize_t reset_write(struct file *file, const char __user *user_buf, | 81 | static ssize_t reset_write(struct file *file, const char __user *user_buf, |
133 | size_t count, loff_t *ppos) | 82 | size_t count, loff_t *ppos) |
134 | { | 83 | { |
@@ -447,7 +396,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
447 | DEBUGFS_ADD(frequency); | 396 | DEBUGFS_ADD(frequency); |
448 | DEBUGFS_ADD(total_ps_buffered); | 397 | DEBUGFS_ADD(total_ps_buffered); |
449 | DEBUGFS_ADD(wep_iv); | 398 | DEBUGFS_ADD(wep_iv); |
450 | DEBUGFS_ADD(tsf); | ||
451 | DEBUGFS_ADD(queues); | 399 | DEBUGFS_ADD(queues); |
452 | DEBUGFS_ADD_MODE(reset, 0200); | 400 | DEBUGFS_ADD_MODE(reset, 0200); |
453 | DEBUGFS_ADD(noack); | 401 | DEBUGFS_ADD(noack); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index dd0462917518..9352819a986b 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "rate.h" | 21 | #include "rate.h" |
22 | #include "debugfs.h" | 22 | #include "debugfs.h" |
23 | #include "debugfs_netdev.h" | 23 | #include "debugfs_netdev.h" |
24 | #include "driver-ops.h" | ||
24 | 25 | ||
25 | static ssize_t ieee80211_if_read( | 26 | static ssize_t ieee80211_if_read( |
26 | struct ieee80211_sub_if_data *sdata, | 27 | struct ieee80211_sub_if_data *sdata, |
@@ -331,6 +332,46 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( | |||
331 | } | 332 | } |
332 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); | 333 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); |
333 | 334 | ||
335 | /* IBSS attributes */ | ||
336 | static ssize_t ieee80211_if_fmt_tsf( | ||
337 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
338 | { | ||
339 | struct ieee80211_local *local = sdata->local; | ||
340 | u64 tsf; | ||
341 | |||
342 | tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata); | ||
343 | |||
344 | return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf); | ||
345 | } | ||
346 | |||
347 | static ssize_t ieee80211_if_parse_tsf( | ||
348 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
349 | { | ||
350 | struct ieee80211_local *local = sdata->local; | ||
351 | unsigned long long tsf; | ||
352 | int ret; | ||
353 | |||
354 | if (strncmp(buf, "reset", 5) == 0) { | ||
355 | if (local->ops->reset_tsf) { | ||
356 | drv_reset_tsf(local, sdata); | ||
357 | wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); | ||
358 | } | ||
359 | } else { | ||
360 | ret = kstrtoull(buf, 10, &tsf); | ||
361 | if (ret < 0) | ||
362 | return -EINVAL; | ||
363 | if (local->ops->set_tsf) { | ||
364 | drv_set_tsf(local, sdata, tsf); | ||
365 | wiphy_info(local->hw.wiphy, | ||
366 | "debugfs set TSF to %#018llx\n", tsf); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | return buflen; | ||
371 | } | ||
372 | __IEEE80211_IF_FILE_W(tsf); | ||
373 | |||
374 | |||
334 | /* WDS attributes */ | 375 | /* WDS attributes */ |
335 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | 376 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); |
336 | 377 | ||
@@ -421,6 +462,11 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
421 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | 462 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); |
422 | } | 463 | } |
423 | 464 | ||
465 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) | ||
466 | { | ||
467 | DEBUGFS_ADD_MODE(tsf, 0600); | ||
468 | } | ||
469 | |||
424 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 470 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
425 | { | 471 | { |
426 | DEBUGFS_ADD(drop_unencrypted); | 472 | DEBUGFS_ADD(drop_unencrypted); |
@@ -515,7 +561,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
515 | add_sta_files(sdata); | 561 | add_sta_files(sdata); |
516 | break; | 562 | break; |
517 | case NL80211_IFTYPE_ADHOC: | 563 | case NL80211_IFTYPE_ADHOC: |
518 | /* XXX */ | 564 | add_ibss_files(sdata); |
519 | break; | 565 | break; |
520 | case NL80211_IFTYPE_AP: | 566 | case NL80211_IFTYPE_AP: |
521 | add_ap_files(sdata); | 567 | add_ap_files(sdata); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 9001ff331f0a..4f845c0845ee 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -413,50 +413,55 @@ static inline void drv_sta_remove(struct ieee80211_local *local, | |||
413 | trace_drv_return_void(local); | 413 | trace_drv_return_void(local); |
414 | } | 414 | } |
415 | 415 | ||
416 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 416 | static inline int drv_conf_tx(struct ieee80211_local *local, |
417 | struct ieee80211_sub_if_data *sdata, u16 queue, | ||
417 | const struct ieee80211_tx_queue_params *params) | 418 | const struct ieee80211_tx_queue_params *params) |
418 | { | 419 | { |
419 | int ret = -EOPNOTSUPP; | 420 | int ret = -EOPNOTSUPP; |
420 | 421 | ||
421 | might_sleep(); | 422 | might_sleep(); |
422 | 423 | ||
423 | trace_drv_conf_tx(local, queue, params); | 424 | trace_drv_conf_tx(local, sdata, queue, params); |
424 | if (local->ops->conf_tx) | 425 | if (local->ops->conf_tx) |
425 | ret = local->ops->conf_tx(&local->hw, queue, params); | 426 | ret = local->ops->conf_tx(&local->hw, queue, params); |
426 | trace_drv_return_int(local, ret); | 427 | trace_drv_return_int(local, ret); |
427 | return ret; | 428 | return ret; |
428 | } | 429 | } |
429 | 430 | ||
430 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | 431 | static inline u64 drv_get_tsf(struct ieee80211_local *local, |
432 | struct ieee80211_sub_if_data *sdata) | ||
431 | { | 433 | { |
432 | u64 ret = -1ULL; | 434 | u64 ret = -1ULL; |
433 | 435 | ||
434 | might_sleep(); | 436 | might_sleep(); |
435 | 437 | ||
436 | trace_drv_get_tsf(local); | 438 | trace_drv_get_tsf(local, sdata); |
437 | if (local->ops->get_tsf) | 439 | if (local->ops->get_tsf) |
438 | ret = local->ops->get_tsf(&local->hw); | 440 | ret = local->ops->get_tsf(&local->hw, &sdata->vif); |
439 | trace_drv_return_u64(local, ret); | 441 | trace_drv_return_u64(local, ret); |
440 | return ret; | 442 | return ret; |
441 | } | 443 | } |
442 | 444 | ||
443 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | 445 | static inline void drv_set_tsf(struct ieee80211_local *local, |
446 | struct ieee80211_sub_if_data *sdata, | ||
447 | u64 tsf) | ||
444 | { | 448 | { |
445 | might_sleep(); | 449 | might_sleep(); |
446 | 450 | ||
447 | trace_drv_set_tsf(local, tsf); | 451 | trace_drv_set_tsf(local, sdata, tsf); |
448 | if (local->ops->set_tsf) | 452 | if (local->ops->set_tsf) |
449 | local->ops->set_tsf(&local->hw, tsf); | 453 | local->ops->set_tsf(&local->hw, &sdata->vif, tsf); |
450 | trace_drv_return_void(local); | 454 | trace_drv_return_void(local); |
451 | } | 455 | } |
452 | 456 | ||
453 | static inline void drv_reset_tsf(struct ieee80211_local *local) | 457 | static inline void drv_reset_tsf(struct ieee80211_local *local, |
458 | struct ieee80211_sub_if_data *sdata) | ||
454 | { | 459 | { |
455 | might_sleep(); | 460 | might_sleep(); |
456 | 461 | ||
457 | trace_drv_reset_tsf(local); | 462 | trace_drv_reset_tsf(local, sdata); |
458 | if (local->ops->reset_tsf) | 463 | if (local->ops->reset_tsf) |
459 | local->ops->reset_tsf(&local->hw); | 464 | local->ops->reset_tsf(&local->hw, &sdata->vif); |
460 | trace_drv_return_void(local); | 465 | trace_drv_return_void(local); |
461 | } | 466 | } |
462 | 467 | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index f47b00dc7afd..a46b279bbbe4 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -697,64 +697,76 @@ TRACE_EVENT(drv_sta_remove, | |||
697 | ); | 697 | ); |
698 | 698 | ||
699 | TRACE_EVENT(drv_conf_tx, | 699 | TRACE_EVENT(drv_conf_tx, |
700 | TP_PROTO(struct ieee80211_local *local, u16 queue, | 700 | TP_PROTO(struct ieee80211_local *local, |
701 | struct ieee80211_sub_if_data *sdata, | ||
702 | u16 queue, | ||
701 | const struct ieee80211_tx_queue_params *params), | 703 | const struct ieee80211_tx_queue_params *params), |
702 | 704 | ||
703 | TP_ARGS(local, queue, params), | 705 | TP_ARGS(local, sdata, queue, params), |
704 | 706 | ||
705 | TP_STRUCT__entry( | 707 | TP_STRUCT__entry( |
706 | LOCAL_ENTRY | 708 | LOCAL_ENTRY |
709 | VIF_ENTRY | ||
707 | __field(u16, queue) | 710 | __field(u16, queue) |
708 | __field(u16, txop) | 711 | __field(u16, txop) |
709 | __field(u16, cw_min) | 712 | __field(u16, cw_min) |
710 | __field(u16, cw_max) | 713 | __field(u16, cw_max) |
711 | __field(u8, aifs) | 714 | __field(u8, aifs) |
715 | __field(bool, uapsd) | ||
712 | ), | 716 | ), |
713 | 717 | ||
714 | TP_fast_assign( | 718 | TP_fast_assign( |
715 | LOCAL_ASSIGN; | 719 | LOCAL_ASSIGN; |
720 | VIF_ASSIGN; | ||
716 | __entry->queue = queue; | 721 | __entry->queue = queue; |
717 | __entry->txop = params->txop; | 722 | __entry->txop = params->txop; |
718 | __entry->cw_max = params->cw_max; | 723 | __entry->cw_max = params->cw_max; |
719 | __entry->cw_min = params->cw_min; | 724 | __entry->cw_min = params->cw_min; |
720 | __entry->aifs = params->aifs; | 725 | __entry->aifs = params->aifs; |
726 | __entry->uapsd = params->uapsd; | ||
721 | ), | 727 | ), |
722 | 728 | ||
723 | TP_printk( | 729 | TP_printk( |
724 | LOCAL_PR_FMT " queue:%d", | 730 | LOCAL_PR_FMT VIF_PR_FMT " queue:%d", |
725 | LOCAL_PR_ARG, __entry->queue | 731 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->queue |
726 | ) | 732 | ) |
727 | ); | 733 | ); |
728 | 734 | ||
729 | DEFINE_EVENT(local_only_evt, drv_get_tsf, | 735 | DEFINE_EVENT(local_sdata_evt, drv_get_tsf, |
730 | TP_PROTO(struct ieee80211_local *local), | 736 | TP_PROTO(struct ieee80211_local *local, |
731 | TP_ARGS(local) | 737 | struct ieee80211_sub_if_data *sdata), |
738 | TP_ARGS(local, sdata) | ||
732 | ); | 739 | ); |
733 | 740 | ||
734 | TRACE_EVENT(drv_set_tsf, | 741 | TRACE_EVENT(drv_set_tsf, |
735 | TP_PROTO(struct ieee80211_local *local, u64 tsf), | 742 | TP_PROTO(struct ieee80211_local *local, |
743 | struct ieee80211_sub_if_data *sdata, | ||
744 | u64 tsf), | ||
736 | 745 | ||
737 | TP_ARGS(local, tsf), | 746 | TP_ARGS(local, sdata, tsf), |
738 | 747 | ||
739 | TP_STRUCT__entry( | 748 | TP_STRUCT__entry( |
740 | LOCAL_ENTRY | 749 | LOCAL_ENTRY |
750 | VIF_ENTRY | ||
741 | __field(u64, tsf) | 751 | __field(u64, tsf) |
742 | ), | 752 | ), |
743 | 753 | ||
744 | TP_fast_assign( | 754 | TP_fast_assign( |
745 | LOCAL_ASSIGN; | 755 | LOCAL_ASSIGN; |
756 | VIF_ASSIGN; | ||
746 | __entry->tsf = tsf; | 757 | __entry->tsf = tsf; |
747 | ), | 758 | ), |
748 | 759 | ||
749 | TP_printk( | 760 | TP_printk( |
750 | LOCAL_PR_FMT " tsf:%llu", | 761 | LOCAL_PR_FMT VIF_PR_FMT " tsf:%llu", |
751 | LOCAL_PR_ARG, (unsigned long long)__entry->tsf | 762 | LOCAL_PR_ARG, VIF_PR_ARG, (unsigned long long)__entry->tsf |
752 | ) | 763 | ) |
753 | ); | 764 | ); |
754 | 765 | ||
755 | DEFINE_EVENT(local_only_evt, drv_reset_tsf, | 766 | DEFINE_EVENT(local_sdata_evt, drv_reset_tsf, |
756 | TP_PROTO(struct ieee80211_local *local), | 767 | TP_PROTO(struct ieee80211_local *local, |
757 | TP_ARGS(local) | 768 | struct ieee80211_sub_if_data *sdata), |
769 | TP_ARGS(local, sdata) | ||
758 | ); | 770 | ); |
759 | 771 | ||
760 | DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, | 772 | DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 4f9235b18a03..41f16dd1a2b0 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -81,7 +81,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
81 | lockdep_assert_held(&ifibss->mtx); | 81 | lockdep_assert_held(&ifibss->mtx); |
82 | 82 | ||
83 | /* Reset own TSF to allow time synchronization work. */ | 83 | /* Reset own TSF to allow time synchronization work. */ |
84 | drv_reset_tsf(local); | 84 | drv_reset_tsf(local, sdata); |
85 | 85 | ||
86 | skb = ifibss->skb; | 86 | skb = ifibss->skb; |
87 | RCU_INIT_POINTER(ifibss->presp, NULL); | 87 | RCU_INIT_POINTER(ifibss->presp, NULL); |
@@ -382,7 +382,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
382 | * second best option: get current TSF | 382 | * second best option: get current TSF |
383 | * (will return -1 if not supported) | 383 | * (will return -1 if not supported) |
384 | */ | 384 | */ |
385 | rx_timestamp = drv_get_tsf(local); | 385 | rx_timestamp = drv_get_tsf(local, sdata); |
386 | } | 386 | } |
387 | 387 | ||
388 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 388 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
@@ -417,7 +417,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
417 | * must be callable in atomic context. | 417 | * must be callable in atomic context. |
418 | */ | 418 | */ |
419 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 419 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
420 | u8 *bssid,u8 *addr, u32 supp_rates, | 420 | u8 *bssid, u8 *addr, u32 supp_rates, |
421 | gfp_t gfp) | 421 | gfp_t gfp) |
422 | { | 422 | { |
423 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 423 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 21186e280ceb..5cadcbbc9a57 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -609,6 +609,8 @@ struct ieee80211_sub_if_data { | |||
609 | __be16 control_port_protocol; | 609 | __be16 control_port_protocol; |
610 | bool control_port_no_encrypt; | 610 | bool control_port_no_encrypt; |
611 | 611 | ||
612 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; | ||
613 | |||
612 | struct work_struct work; | 614 | struct work_struct work; |
613 | struct sk_buff_head skb_queue; | 615 | struct sk_buff_head skb_queue; |
614 | 616 | ||
@@ -751,7 +753,6 @@ struct ieee80211_local { | |||
751 | struct workqueue_struct *workqueue; | 753 | struct workqueue_struct *workqueue; |
752 | 754 | ||
753 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | 755 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; |
754 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; | ||
755 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 756 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
756 | spinlock_t queue_stop_reason_lock; | 757 | spinlock_t queue_stop_reason_lock; |
757 | 758 | ||
@@ -1324,7 +1325,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1324 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1325 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1325 | const u8 *ssid, size_t ssid_len, | 1326 | const u8 *ssid, size_t ssid_len, |
1326 | const u8 *ie, size_t ie_len, | 1327 | const u8 *ie, size_t ie_len, |
1327 | u32 ratemask, bool directed); | 1328 | u32 ratemask, bool directed, bool no_cck); |
1328 | 1329 | ||
1329 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1330 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1330 | const size_t supp_rates_len, | 1331 | const size_t supp_rates_len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a33c58f5137c..f4350262663f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -460,17 +460,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
460 | synchronize_rcu(); | 460 | synchronize_rcu(); |
461 | kfree(old_beacon); | 461 | kfree(old_beacon); |
462 | 462 | ||
463 | /* free all potentially still buffered bcast frames */ | ||
464 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { | ||
465 | local->total_ps_buffered--; | ||
466 | dev_kfree_skb(skb); | ||
467 | } | ||
468 | |||
469 | /* down all dependent devices, that is VLANs */ | 463 | /* down all dependent devices, that is VLANs */ |
470 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 464 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
471 | u.vlan.list) | 465 | u.vlan.list) |
472 | dev_close(vlan->dev); | 466 | dev_close(vlan->dev); |
473 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | 467 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); |
468 | |||
469 | /* free all potentially still buffered bcast frames */ | ||
470 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf); | ||
471 | skb_queue_purge(&sdata->u.ap.ps_bc_buf); | ||
474 | } | 472 | } |
475 | 473 | ||
476 | if (going_down) | 474 | if (going_down) |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 4396906175ae..1213a23ff0fa 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -43,6 +43,10 @@ enum plink_event { | |||
43 | CLS_IGNR | 43 | CLS_IGNR |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | ||
47 | enum ieee80211_self_protected_actioncode action, | ||
48 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | ||
49 | |||
46 | static inline | 50 | static inline |
47 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 51 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
48 | { | 52 | { |
@@ -133,6 +137,10 @@ void mesh_plink_deactivate(struct sta_info *sta) | |||
133 | 137 | ||
134 | spin_lock_bh(&sta->lock); | 138 | spin_lock_bh(&sta->lock); |
135 | deactivated = __mesh_plink_deactivate(sta); | 139 | deactivated = __mesh_plink_deactivate(sta); |
140 | sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); | ||
141 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | ||
142 | sta->sta.addr, sta->llid, sta->plid, | ||
143 | sta->reason); | ||
136 | spin_unlock_bh(&sta->lock); | 144 | spin_unlock_bh(&sta->lock); |
137 | 145 | ||
138 | if (deactivated) | 146 | if (deactivated) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2f92ae2f9706..cd37a4e3c0d7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -160,7 +160,8 @@ static int ecw2cw(int ecw) | |||
160 | */ | 160 | */ |
161 | static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | 161 | static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, |
162 | struct ieee80211_ht_info *hti, | 162 | struct ieee80211_ht_info *hti, |
163 | const u8 *bssid, u16 ap_ht_cap_flags) | 163 | const u8 *bssid, u16 ap_ht_cap_flags, |
164 | bool beacon_htcap_ie) | ||
164 | { | 165 | { |
165 | struct ieee80211_local *local = sdata->local; | 166 | struct ieee80211_local *local = sdata->local; |
166 | struct ieee80211_supported_band *sband; | 167 | struct ieee80211_supported_band *sband; |
@@ -232,6 +233,21 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
232 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); | 233 | WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type)); |
233 | } | 234 | } |
234 | 235 | ||
236 | if (beacon_htcap_ie && (prev_chantype != channel_type)) { | ||
237 | /* | ||
238 | * Whenever the AP announces the HT mode change that can be | ||
239 | * 40MHz intolerant or etc., it would be safer to stop tx | ||
240 | * queues before doing hw config to avoid buffer overflow. | ||
241 | */ | ||
242 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
243 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
244 | |||
245 | /* flush out all packets */ | ||
246 | synchronize_net(); | ||
247 | |||
248 | drv_flush(local, false); | ||
249 | } | ||
250 | |||
235 | /* channel_type change automatically detected */ | 251 | /* channel_type change automatically detected */ |
236 | ieee80211_hw_config(local, 0); | 252 | ieee80211_hw_config(local, 0); |
237 | 253 | ||
@@ -243,6 +259,10 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
243 | IEEE80211_RC_HT_CHANGED, | 259 | IEEE80211_RC_HT_CHANGED, |
244 | channel_type); | 260 | channel_type); |
245 | rcu_read_unlock(); | 261 | rcu_read_unlock(); |
262 | |||
263 | if (beacon_htcap_ie) | ||
264 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
265 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
246 | } | 266 | } |
247 | 267 | ||
248 | ht_opmode = le16_to_cpu(hti->operation_mode); | 268 | ht_opmode = le16_to_cpu(hti->operation_mode); |
@@ -916,8 +936,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
916 | params.aifs, params.cw_min, params.cw_max, | 936 | params.aifs, params.cw_min, params.cw_max, |
917 | params.txop, params.uapsd); | 937 | params.txop, params.uapsd); |
918 | #endif | 938 | #endif |
919 | local->tx_conf[queue] = params; | 939 | sdata->tx_conf[queue] = params; |
920 | if (drv_conf_tx(local, queue, ¶ms)) | 940 | if (drv_conf_tx(local, sdata, queue, ¶ms)) |
921 | wiphy_debug(local->hw.wiphy, | 941 | wiphy_debug(local->hw.wiphy, |
922 | "failed to set TX queue parameters for queue %d\n", | 942 | "failed to set TX queue parameters for queue %d\n", |
923 | queue); | 943 | queue); |
@@ -1219,7 +1239,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1219 | } else { | 1239 | } else { |
1220 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1240 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1221 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, | 1241 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, |
1222 | (u32) -1, true); | 1242 | (u32) -1, true, false); |
1223 | } | 1243 | } |
1224 | 1244 | ||
1225 | ifmgd->probe_send_count++; | 1245 | ifmgd->probe_send_count++; |
@@ -1588,7 +1608,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1588 | (sdata->local->hw.queues >= 4) && | 1608 | (sdata->local->hw.queues >= 4) && |
1589 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 1609 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
1590 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1610 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1591 | cbss->bssid, ap_ht_cap_flags); | 1611 | cbss->bssid, ap_ht_cap_flags, |
1612 | false); | ||
1592 | 1613 | ||
1593 | /* set AID and assoc capability, | 1614 | /* set AID and assoc capability, |
1594 | * ieee80211_set_associated() will tell the driver */ | 1615 | * ieee80211_set_associated() will tell the driver */ |
@@ -1921,24 +1942,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1921 | 1942 | ||
1922 | rcu_read_unlock(); | 1943 | rcu_read_unlock(); |
1923 | 1944 | ||
1924 | /* | ||
1925 | * Whenever the AP announces the HT mode change that can be | ||
1926 | * 40MHz intolerant or etc., it would be safer to stop tx | ||
1927 | * queues before doing hw config to avoid buffer overflow. | ||
1928 | */ | ||
1929 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
1930 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
1931 | |||
1932 | /* flush out all packets */ | ||
1933 | synchronize_net(); | ||
1934 | |||
1935 | drv_flush(local, false); | ||
1936 | |||
1937 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1945 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1938 | bssid, ap_ht_cap_flags); | 1946 | bssid, ap_ht_cap_flags, true); |
1939 | |||
1940 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
1941 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
1942 | } | 1947 | } |
1943 | 1948 | ||
1944 | /* Note: country IE parsing is done for us by cfg80211 */ | 1949 | /* Note: country IE parsing is done for us by cfg80211 */ |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3d5a2cb835c4..f61244c0e0a2 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -233,6 +233,27 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, | |||
233 | /* could not find a basic rate; use original selection */ | 233 | /* could not find a basic rate; use original selection */ |
234 | } | 234 | } |
235 | 235 | ||
236 | static inline s8 | ||
237 | rate_lowest_non_cck_index(struct ieee80211_supported_band *sband, | ||
238 | struct ieee80211_sta *sta) | ||
239 | { | ||
240 | int i; | ||
241 | |||
242 | for (i = 0; i < sband->n_bitrates; i++) { | ||
243 | struct ieee80211_rate *srate = &sband->bitrates[i]; | ||
244 | if ((srate->bitrate == 10) || (srate->bitrate == 20) || | ||
245 | (srate->bitrate == 55) || (srate->bitrate == 110)) | ||
246 | continue; | ||
247 | |||
248 | if (rate_supported(sta, sband->band, i)) | ||
249 | return i; | ||
250 | } | ||
251 | |||
252 | /* No matching rate found */ | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | |||
236 | bool rate_control_send_low(struct ieee80211_sta *sta, | 257 | bool rate_control_send_low(struct ieee80211_sta *sta, |
237 | void *priv_sta, | 258 | void *priv_sta, |
238 | struct ieee80211_tx_rate_control *txrc) | 259 | struct ieee80211_tx_rate_control *txrc) |
@@ -242,7 +263,13 @@ bool rate_control_send_low(struct ieee80211_sta *sta, | |||
242 | int mcast_rate; | 263 | int mcast_rate; |
243 | 264 | ||
244 | if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { | 265 | if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { |
245 | info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); | 266 | if ((sband->band != IEEE80211_BAND_2GHZ) || |
267 | !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) | ||
268 | info->control.rates[0].idx = | ||
269 | rate_lowest_index(txrc->sband, sta); | ||
270 | else | ||
271 | info->control.rates[0].idx = | ||
272 | rate_lowest_non_cck_index(txrc->sband, sta); | ||
246 | info->control.rates[0].count = | 273 | info->control.rates[0].count = |
247 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 274 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
248 | 1 : txrc->hw->max_rate_tries; | 275 | 1 : txrc->hw->max_rate_tries; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 6f09eca01112..830e60f65779 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -660,7 +660,8 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
660 | local->scan_req->ssids[i].ssid, | 660 | local->scan_req->ssids[i].ssid, |
661 | local->scan_req->ssids[i].ssid_len, | 661 | local->scan_req->ssids[i].ssid_len, |
662 | local->scan_req->ie, local->scan_req->ie_len, | 662 | local->scan_req->ie, local->scan_req->ie_len, |
663 | local->scan_req->rates[band], false); | 663 | local->scan_req->rates[band], false, |
664 | local->scan_req->no_cck); | ||
664 | 665 | ||
665 | /* | 666 | /* |
666 | * After sending probe requests, wait for probe responses | 667 | * After sending probe requests, wait for probe responses |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 4b1466d5b6a1..2c9dc360dc6d 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -632,8 +632,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
632 | 632 | ||
633 | qparam.uapsd = false; | 633 | qparam.uapsd = false; |
634 | 634 | ||
635 | local->tx_conf[queue] = qparam; | 635 | sdata->tx_conf[queue] = qparam; |
636 | drv_conf_tx(local, queue, &qparam); | 636 | drv_conf_tx(local, sdata, queue, &qparam); |
637 | } | 637 | } |
638 | 638 | ||
639 | /* after reinitialize QoS TX queues setting to default, | 639 | /* after reinitialize QoS TX queues setting to default, |
@@ -899,14 +899,18 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
899 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 899 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
900 | const u8 *ssid, size_t ssid_len, | 900 | const u8 *ssid, size_t ssid_len, |
901 | const u8 *ie, size_t ie_len, | 901 | const u8 *ie, size_t ie_len, |
902 | u32 ratemask, bool directed) | 902 | u32 ratemask, bool directed, bool no_cck) |
903 | { | 903 | { |
904 | struct sk_buff *skb; | 904 | struct sk_buff *skb; |
905 | 905 | ||
906 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, | 906 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, |
907 | ie, ie_len, directed); | 907 | ie, ie_len, directed); |
908 | if (skb) | 908 | if (skb) { |
909 | if (no_cck) | ||
910 | IEEE80211_SKB_CB(skb)->flags |= | ||
911 | IEEE80211_TX_CTL_NO_CCK_RATE; | ||
909 | ieee80211_tx_skb(sdata, skb); | 912 | ieee80211_tx_skb(sdata, skb); |
913 | } | ||
910 | } | 914 | } |
911 | 915 | ||
912 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 916 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
@@ -1040,8 +1044,15 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1040 | mutex_unlock(&local->sta_mtx); | 1044 | mutex_unlock(&local->sta_mtx); |
1041 | 1045 | ||
1042 | /* reconfigure tx conf */ | 1046 | /* reconfigure tx conf */ |
1043 | for (i = 0; i < hw->queues; i++) | 1047 | list_for_each_entry(sdata, &local->interfaces, list) { |
1044 | drv_conf_tx(local, i, &local->tx_conf[i]); | 1048 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
1049 | sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1050 | !ieee80211_sdata_running(sdata)) | ||
1051 | continue; | ||
1052 | |||
1053 | for (i = 0; i < hw->queues; i++) | ||
1054 | drv_conf_tx(local, sdata, i, &sdata->tx_conf[i]); | ||
1055 | } | ||
1045 | 1056 | ||
1046 | /* reconfigure hardware */ | 1057 | /* reconfigure hardware */ |
1047 | ieee80211_hw_config(local, ~0); | 1058 | ieee80211_hw_config(local, ~0); |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index bac34394c05e..af374fab1a12 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -458,7 +458,7 @@ ieee80211_direct_probe(struct ieee80211_work *wk) | |||
458 | */ | 458 | */ |
459 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, | 459 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, |
460 | wk->probe_auth.ssid_len, NULL, 0, | 460 | wk->probe_auth.ssid_len, NULL, 0, |
461 | (u32) -1, true); | 461 | (u32) -1, true, false); |
462 | 462 | ||
463 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 463 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
464 | run_again(local, wk->timeout); | 464 | run_again(local, wk->timeout); |
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 33e095b124b3..58cddadf8e8e 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig | |||
@@ -13,4 +13,6 @@ menuconfig NFC | |||
13 | To compile this support as a module, choose M here: the module will | 13 | To compile this support as a module, choose M here: the module will |
14 | be called nfc. | 14 | be called nfc. |
15 | 15 | ||
16 | source "net/nfc/nci/Kconfig" | ||
17 | |||
16 | source "drivers/nfc/Kconfig" | 18 | source "drivers/nfc/Kconfig" |
diff --git a/net/nfc/Makefile b/net/nfc/Makefile index 16250c353851..fbb550f2377b 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile | |||
@@ -3,5 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_NFC) += nfc.o | 5 | obj-$(CONFIG_NFC) += nfc.o |
6 | obj-$(CONFIG_NFC_NCI) += nci/ | ||
6 | 7 | ||
7 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o | 8 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o |
diff --git a/net/nfc/core.c b/net/nfc/core.c index 284e2f6a14ff..47e02c1b8c02 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -53,6 +53,80 @@ int nfc_printk(const char *level, const char *format, ...) | |||
53 | EXPORT_SYMBOL(nfc_printk); | 53 | EXPORT_SYMBOL(nfc_printk); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * nfc_dev_up - turn on the NFC device | ||
57 | * | ||
58 | * @dev: The nfc device to be turned on | ||
59 | * | ||
60 | * The device remains up until the nfc_dev_down function is called. | ||
61 | */ | ||
62 | int nfc_dev_up(struct nfc_dev *dev) | ||
63 | { | ||
64 | int rc = 0; | ||
65 | |||
66 | nfc_dbg("dev_name=%s", dev_name(&dev->dev)); | ||
67 | |||
68 | device_lock(&dev->dev); | ||
69 | |||
70 | if (!device_is_registered(&dev->dev)) { | ||
71 | rc = -ENODEV; | ||
72 | goto error; | ||
73 | } | ||
74 | |||
75 | if (dev->dev_up) { | ||
76 | rc = -EALREADY; | ||
77 | goto error; | ||
78 | } | ||
79 | |||
80 | if (dev->ops->dev_up) | ||
81 | rc = dev->ops->dev_up(dev); | ||
82 | |||
83 | if (!rc) | ||
84 | dev->dev_up = true; | ||
85 | |||
86 | error: | ||
87 | device_unlock(&dev->dev); | ||
88 | return rc; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * nfc_dev_down - turn off the NFC device | ||
93 | * | ||
94 | * @dev: The nfc device to be turned off | ||
95 | */ | ||
96 | int nfc_dev_down(struct nfc_dev *dev) | ||
97 | { | ||
98 | int rc = 0; | ||
99 | |||
100 | nfc_dbg("dev_name=%s", dev_name(&dev->dev)); | ||
101 | |||
102 | device_lock(&dev->dev); | ||
103 | |||
104 | if (!device_is_registered(&dev->dev)) { | ||
105 | rc = -ENODEV; | ||
106 | goto error; | ||
107 | } | ||
108 | |||
109 | if (!dev->dev_up) { | ||
110 | rc = -EALREADY; | ||
111 | goto error; | ||
112 | } | ||
113 | |||
114 | if (dev->polling || dev->remote_activated) { | ||
115 | rc = -EBUSY; | ||
116 | goto error; | ||
117 | } | ||
118 | |||
119 | if (dev->ops->dev_down) | ||
120 | dev->ops->dev_down(dev); | ||
121 | |||
122 | dev->dev_up = false; | ||
123 | |||
124 | error: | ||
125 | device_unlock(&dev->dev); | ||
126 | return rc; | ||
127 | } | ||
128 | |||
129 | /** | ||
56 | * nfc_start_poll - start polling for nfc targets | 130 | * nfc_start_poll - start polling for nfc targets |
57 | * | 131 | * |
58 | * @dev: The nfc device that must start polling | 132 | * @dev: The nfc device that must start polling |
@@ -144,6 +218,8 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
144 | } | 218 | } |
145 | 219 | ||
146 | rc = dev->ops->activate_target(dev, target_idx, protocol); | 220 | rc = dev->ops->activate_target(dev, target_idx, protocol); |
221 | if (!rc) | ||
222 | dev->remote_activated = true; | ||
147 | 223 | ||
148 | error: | 224 | error: |
149 | device_unlock(&dev->dev); | 225 | device_unlock(&dev->dev); |
@@ -170,6 +246,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx) | |||
170 | } | 246 | } |
171 | 247 | ||
172 | dev->ops->deactivate_target(dev, target_idx); | 248 | dev->ops->deactivate_target(dev, target_idx); |
249 | dev->remote_activated = false; | ||
173 | 250 | ||
174 | error: | 251 | error: |
175 | device_unlock(&dev->dev); | 252 | device_unlock(&dev->dev); |
diff --git a/net/nfc/nci/Kconfig b/net/nfc/nci/Kconfig new file mode 100644 index 000000000000..decdc49b26d8 --- /dev/null +++ b/net/nfc/nci/Kconfig | |||
@@ -0,0 +1,10 @@ | |||
1 | config NFC_NCI | ||
2 | depends on NFC && EXPERIMENTAL | ||
3 | tristate "NCI protocol support (EXPERIMENTAL)" | ||
4 | default n | ||
5 | help | ||
6 | NCI (NFC Controller Interface) is a communication protocol between | ||
7 | an NFC Controller (NFCC) and a Device Host (DH). | ||
8 | |||
9 | Say Y here to compile NCI support into the kernel or say M to | ||
10 | compile it as module (nci). | ||
diff --git a/net/nfc/nci/Makefile b/net/nfc/nci/Makefile new file mode 100644 index 000000000000..cdb3a2e44471 --- /dev/null +++ b/net/nfc/nci/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the Linux NFC NCI layer. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_NFC_NCI) += nci.o | ||
6 | |||
7 | nci-objs := core.o data.o lib.o ntf.o rsp.o \ No newline at end of file | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c new file mode 100644 index 000000000000..4047e29acb3b --- /dev/null +++ b/net/nfc/nci/core.c | |||
@@ -0,0 +1,797 @@ | |||
1 | /* | ||
2 | * The NFC Controller Interface is the communication protocol between an | ||
3 | * NFC Controller (NFCC) and a Device Host (DH). | ||
4 | * | ||
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
6 | * | ||
7 | * Written by Ilan Elias <ilane@ti.com> | ||
8 | * | ||
9 | * Acknowledgements: | ||
10 | * This file is based on hci_core.c, which was written | ||
11 | * by Maxim Krasnyansky. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 | ||
15 | * as published by the Free Software Foundation | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/types.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | #include <linux/completion.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/bitops.h> | ||
33 | #include <linux/skbuff.h> | ||
34 | |||
35 | #include "../nfc.h" | ||
36 | #include <net/nfc/nci.h> | ||
37 | #include <net/nfc/nci_core.h> | ||
38 | #include <linux/nfc.h> | ||
39 | |||
40 | static void nci_cmd_work(struct work_struct *work); | ||
41 | static void nci_rx_work(struct work_struct *work); | ||
42 | static void nci_tx_work(struct work_struct *work); | ||
43 | |||
44 | /* ---- NCI requests ---- */ | ||
45 | |||
46 | void nci_req_complete(struct nci_dev *ndev, int result) | ||
47 | { | ||
48 | if (ndev->req_status == NCI_REQ_PEND) { | ||
49 | ndev->req_result = result; | ||
50 | ndev->req_status = NCI_REQ_DONE; | ||
51 | complete(&ndev->req_completion); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static void nci_req_cancel(struct nci_dev *ndev, int err) | ||
56 | { | ||
57 | if (ndev->req_status == NCI_REQ_PEND) { | ||
58 | ndev->req_result = err; | ||
59 | ndev->req_status = NCI_REQ_CANCELED; | ||
60 | complete(&ndev->req_completion); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /* Execute request and wait for completion. */ | ||
65 | static int __nci_request(struct nci_dev *ndev, | ||
66 | void (*req)(struct nci_dev *ndev, unsigned long opt), | ||
67 | unsigned long opt, | ||
68 | __u32 timeout) | ||
69 | { | ||
70 | int rc = 0; | ||
71 | unsigned long completion_rc; | ||
72 | |||
73 | ndev->req_status = NCI_REQ_PEND; | ||
74 | |||
75 | init_completion(&ndev->req_completion); | ||
76 | req(ndev, opt); | ||
77 | completion_rc = wait_for_completion_interruptible_timeout( | ||
78 | &ndev->req_completion, | ||
79 | timeout); | ||
80 | |||
81 | nfc_dbg("wait_for_completion return %ld", completion_rc); | ||
82 | |||
83 | if (completion_rc > 0) { | ||
84 | switch (ndev->req_status) { | ||
85 | case NCI_REQ_DONE: | ||
86 | rc = nci_to_errno(ndev->req_result); | ||
87 | break; | ||
88 | |||
89 | case NCI_REQ_CANCELED: | ||
90 | rc = -ndev->req_result; | ||
91 | break; | ||
92 | |||
93 | default: | ||
94 | rc = -ETIMEDOUT; | ||
95 | break; | ||
96 | } | ||
97 | } else { | ||
98 | nfc_err("wait_for_completion_interruptible_timeout failed %ld", | ||
99 | completion_rc); | ||
100 | |||
101 | rc = ((completion_rc == 0) ? (-ETIMEDOUT) : (completion_rc)); | ||
102 | } | ||
103 | |||
104 | ndev->req_status = ndev->req_result = 0; | ||
105 | |||
106 | return rc; | ||
107 | } | ||
108 | |||
109 | static inline int nci_request(struct nci_dev *ndev, | ||
110 | void (*req)(struct nci_dev *ndev, unsigned long opt), | ||
111 | unsigned long opt, __u32 timeout) | ||
112 | { | ||
113 | int rc; | ||
114 | |||
115 | if (!test_bit(NCI_UP, &ndev->flags)) | ||
116 | return -ENETDOWN; | ||
117 | |||
118 | /* Serialize all requests */ | ||
119 | mutex_lock(&ndev->req_lock); | ||
120 | rc = __nci_request(ndev, req, opt, timeout); | ||
121 | mutex_unlock(&ndev->req_lock); | ||
122 | |||
123 | return rc; | ||
124 | } | ||
125 | |||
126 | static void nci_reset_req(struct nci_dev *ndev, unsigned long opt) | ||
127 | { | ||
128 | nci_send_cmd(ndev, NCI_OP_CORE_RESET_CMD, 0, NULL); | ||
129 | } | ||
130 | |||
131 | static void nci_init_req(struct nci_dev *ndev, unsigned long opt) | ||
132 | { | ||
133 | nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL); | ||
134 | } | ||
135 | |||
136 | static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) | ||
137 | { | ||
138 | struct nci_core_conn_create_cmd conn_cmd; | ||
139 | struct nci_rf_disc_map_cmd cmd; | ||
140 | struct disc_map_config *cfg = cmd.mapping_configs; | ||
141 | __u8 *num = &cmd.num_mapping_configs; | ||
142 | int i; | ||
143 | |||
144 | /* create static rf connection */ | ||
145 | conn_cmd.target_handle = 0; | ||
146 | conn_cmd.num_target_specific_params = 0; | ||
147 | nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, 2, &conn_cmd); | ||
148 | |||
149 | /* set rf mapping configurations */ | ||
150 | *num = 0; | ||
151 | |||
152 | /* by default mapping is set to NCI_RF_INTERFACE_FRAME */ | ||
153 | for (i = 0; i < ndev->num_supported_rf_interfaces; i++) { | ||
154 | if (ndev->supported_rf_interfaces[i] == | ||
155 | NCI_RF_INTERFACE_ISO_DEP) { | ||
156 | cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; | ||
157 | cfg[*num].mode = NCI_DISC_MAP_MODE_BOTH; | ||
158 | cfg[*num].rf_interface_type = NCI_RF_INTERFACE_ISO_DEP; | ||
159 | (*num)++; | ||
160 | } else if (ndev->supported_rf_interfaces[i] == | ||
161 | NCI_RF_INTERFACE_NFC_DEP) { | ||
162 | cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; | ||
163 | cfg[*num].mode = NCI_DISC_MAP_MODE_BOTH; | ||
164 | cfg[*num].rf_interface_type = NCI_RF_INTERFACE_NFC_DEP; | ||
165 | (*num)++; | ||
166 | } | ||
167 | |||
168 | if (*num == NCI_MAX_NUM_MAPPING_CONFIGS) | ||
169 | break; | ||
170 | } | ||
171 | |||
172 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD, | ||
173 | (1 + ((*num)*sizeof(struct disc_map_config))), | ||
174 | &cmd); | ||
175 | } | ||
176 | |||
177 | static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | ||
178 | { | ||
179 | struct nci_rf_disc_cmd cmd; | ||
180 | __u32 protocols = opt; | ||
181 | |||
182 | cmd.num_disc_configs = 0; | ||
183 | |||
184 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | ||
185 | (protocols & NFC_PROTO_JEWEL_MASK | ||
186 | || protocols & NFC_PROTO_MIFARE_MASK | ||
187 | || protocols & NFC_PROTO_ISO14443_MASK | ||
188 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | ||
189 | cmd.disc_configs[cmd.num_disc_configs].type = | ||
190 | NCI_DISCOVERY_TYPE_POLL_A_PASSIVE; | ||
191 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | ||
192 | cmd.num_disc_configs++; | ||
193 | } | ||
194 | |||
195 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | ||
196 | (protocols & NFC_PROTO_ISO14443_MASK)) { | ||
197 | cmd.disc_configs[cmd.num_disc_configs].type = | ||
198 | NCI_DISCOVERY_TYPE_POLL_B_PASSIVE; | ||
199 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | ||
200 | cmd.num_disc_configs++; | ||
201 | } | ||
202 | |||
203 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | ||
204 | (protocols & NFC_PROTO_FELICA_MASK | ||
205 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | ||
206 | cmd.disc_configs[cmd.num_disc_configs].type = | ||
207 | NCI_DISCOVERY_TYPE_POLL_F_PASSIVE; | ||
208 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | ||
209 | cmd.num_disc_configs++; | ||
210 | } | ||
211 | |||
212 | nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD, | ||
213 | (1 + (cmd.num_disc_configs*sizeof(struct disc_config))), | ||
214 | &cmd); | ||
215 | } | ||
216 | |||
217 | static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) | ||
218 | { | ||
219 | struct nci_rf_deactivate_cmd cmd; | ||
220 | |||
221 | cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE; | ||
222 | |||
223 | nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD, | ||
224 | sizeof(struct nci_rf_deactivate_cmd), | ||
225 | &cmd); | ||
226 | } | ||
227 | |||
228 | static int nci_open_device(struct nci_dev *ndev) | ||
229 | { | ||
230 | int rc = 0; | ||
231 | |||
232 | mutex_lock(&ndev->req_lock); | ||
233 | |||
234 | if (test_bit(NCI_UP, &ndev->flags)) { | ||
235 | rc = -EALREADY; | ||
236 | goto done; | ||
237 | } | ||
238 | |||
239 | if (ndev->ops->open(ndev)) { | ||
240 | rc = -EIO; | ||
241 | goto done; | ||
242 | } | ||
243 | |||
244 | atomic_set(&ndev->cmd_cnt, 1); | ||
245 | |||
246 | set_bit(NCI_INIT, &ndev->flags); | ||
247 | |||
248 | rc = __nci_request(ndev, nci_reset_req, 0, | ||
249 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); | ||
250 | |||
251 | if (!rc) { | ||
252 | rc = __nci_request(ndev, nci_init_req, 0, | ||
253 | msecs_to_jiffies(NCI_INIT_TIMEOUT)); | ||
254 | } | ||
255 | |||
256 | if (!rc) { | ||
257 | rc = __nci_request(ndev, nci_init_complete_req, 0, | ||
258 | msecs_to_jiffies(NCI_INIT_TIMEOUT)); | ||
259 | } | ||
260 | |||
261 | clear_bit(NCI_INIT, &ndev->flags); | ||
262 | |||
263 | if (!rc) { | ||
264 | set_bit(NCI_UP, &ndev->flags); | ||
265 | } else { | ||
266 | /* Init failed, cleanup */ | ||
267 | skb_queue_purge(&ndev->cmd_q); | ||
268 | skb_queue_purge(&ndev->rx_q); | ||
269 | skb_queue_purge(&ndev->tx_q); | ||
270 | |||
271 | ndev->ops->close(ndev); | ||
272 | ndev->flags = 0; | ||
273 | } | ||
274 | |||
275 | done: | ||
276 | mutex_unlock(&ndev->req_lock); | ||
277 | return rc; | ||
278 | } | ||
279 | |||
280 | static int nci_close_device(struct nci_dev *ndev) | ||
281 | { | ||
282 | nci_req_cancel(ndev, ENODEV); | ||
283 | mutex_lock(&ndev->req_lock); | ||
284 | |||
285 | if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { | ||
286 | del_timer_sync(&ndev->cmd_timer); | ||
287 | mutex_unlock(&ndev->req_lock); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /* Drop RX and TX queues */ | ||
292 | skb_queue_purge(&ndev->rx_q); | ||
293 | skb_queue_purge(&ndev->tx_q); | ||
294 | |||
295 | /* Flush RX and TX wq */ | ||
296 | flush_workqueue(ndev->rx_wq); | ||
297 | flush_workqueue(ndev->tx_wq); | ||
298 | |||
299 | /* Reset device */ | ||
300 | skb_queue_purge(&ndev->cmd_q); | ||
301 | atomic_set(&ndev->cmd_cnt, 1); | ||
302 | |||
303 | set_bit(NCI_INIT, &ndev->flags); | ||
304 | __nci_request(ndev, nci_reset_req, 0, | ||
305 | msecs_to_jiffies(NCI_RESET_TIMEOUT)); | ||
306 | clear_bit(NCI_INIT, &ndev->flags); | ||
307 | |||
308 | /* Flush cmd wq */ | ||
309 | flush_workqueue(ndev->cmd_wq); | ||
310 | |||
311 | /* After this point our queues are empty | ||
312 | * and no works are scheduled. */ | ||
313 | ndev->ops->close(ndev); | ||
314 | |||
315 | /* Clear flags */ | ||
316 | ndev->flags = 0; | ||
317 | |||
318 | mutex_unlock(&ndev->req_lock); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | /* NCI command timer function */ | ||
324 | static void nci_cmd_timer(unsigned long arg) | ||
325 | { | ||
326 | struct nci_dev *ndev = (void *) arg; | ||
327 | |||
328 | nfc_dbg("entry"); | ||
329 | |||
330 | atomic_set(&ndev->cmd_cnt, 1); | ||
331 | queue_work(ndev->cmd_wq, &ndev->cmd_work); | ||
332 | } | ||
333 | |||
334 | static int nci_dev_up(struct nfc_dev *nfc_dev) | ||
335 | { | ||
336 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
337 | |||
338 | nfc_dbg("entry"); | ||
339 | |||
340 | return nci_open_device(ndev); | ||
341 | } | ||
342 | |||
343 | static int nci_dev_down(struct nfc_dev *nfc_dev) | ||
344 | { | ||
345 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
346 | |||
347 | nfc_dbg("entry"); | ||
348 | |||
349 | return nci_close_device(ndev); | ||
350 | } | ||
351 | |||
352 | static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | ||
353 | { | ||
354 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
355 | int rc; | ||
356 | |||
357 | nfc_dbg("entry"); | ||
358 | |||
359 | if (test_bit(NCI_DISCOVERY, &ndev->flags)) { | ||
360 | nfc_err("unable to start poll, since poll is already active"); | ||
361 | return -EBUSY; | ||
362 | } | ||
363 | |||
364 | if (ndev->target_active_prot) { | ||
365 | nfc_err("there is an active target"); | ||
366 | return -EBUSY; | ||
367 | } | ||
368 | |||
369 | if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { | ||
370 | nfc_dbg("target is active, implicitly deactivate..."); | ||
371 | |||
372 | rc = nci_request(ndev, nci_rf_deactivate_req, 0, | ||
373 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | ||
374 | if (rc) | ||
375 | return -EBUSY; | ||
376 | } | ||
377 | |||
378 | rc = nci_request(ndev, nci_rf_discover_req, protocols, | ||
379 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); | ||
380 | |||
381 | if (!rc) | ||
382 | ndev->poll_prots = protocols; | ||
383 | |||
384 | return rc; | ||
385 | } | ||
386 | |||
387 | static void nci_stop_poll(struct nfc_dev *nfc_dev) | ||
388 | { | ||
389 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
390 | |||
391 | nfc_dbg("entry"); | ||
392 | |||
393 | if (!test_bit(NCI_DISCOVERY, &ndev->flags)) { | ||
394 | nfc_err("unable to stop poll, since poll is not active"); | ||
395 | return; | ||
396 | } | ||
397 | |||
398 | nci_request(ndev, nci_rf_deactivate_req, 0, | ||
399 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | ||
400 | } | ||
401 | |||
402 | static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, | ||
403 | __u32 protocol) | ||
404 | { | ||
405 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
406 | |||
407 | nfc_dbg("entry, target_idx %d, protocol 0x%x", target_idx, protocol); | ||
408 | |||
409 | if (!test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { | ||
410 | nfc_err("there is no available target to activate"); | ||
411 | return -EINVAL; | ||
412 | } | ||
413 | |||
414 | if (ndev->target_active_prot) { | ||
415 | nfc_err("there is already an active target"); | ||
416 | return -EBUSY; | ||
417 | } | ||
418 | |||
419 | if (!(ndev->target_available_prots & (1 << protocol))) { | ||
420 | nfc_err("target does not support the requested protocol 0x%x", | ||
421 | protocol); | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | ndev->target_active_prot = protocol; | ||
426 | ndev->target_available_prots = 0; | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx) | ||
432 | { | ||
433 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
434 | |||
435 | nfc_dbg("entry, target_idx %d", target_idx); | ||
436 | |||
437 | if (!ndev->target_active_prot) { | ||
438 | nfc_err("unable to deactivate target, no active target"); | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | ndev->target_active_prot = 0; | ||
443 | |||
444 | if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { | ||
445 | nci_request(ndev, nci_rf_deactivate_req, 0, | ||
446 | msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx, | ||
451 | struct sk_buff *skb, | ||
452 | data_exchange_cb_t cb, | ||
453 | void *cb_context) | ||
454 | { | ||
455 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | ||
456 | int rc; | ||
457 | |||
458 | nfc_dbg("entry, target_idx %d, len %d", target_idx, skb->len); | ||
459 | |||
460 | if (!ndev->target_active_prot) { | ||
461 | nfc_err("unable to exchange data, no active target"); | ||
462 | return -EINVAL; | ||
463 | } | ||
464 | |||
465 | if (test_and_set_bit(NCI_DATA_EXCHANGE, &ndev->flags)) | ||
466 | return -EBUSY; | ||
467 | |||
468 | /* store cb and context to be used on receiving data */ | ||
469 | ndev->data_exchange_cb = cb; | ||
470 | ndev->data_exchange_cb_context = cb_context; | ||
471 | |||
472 | rc = nci_send_data(ndev, ndev->conn_id, skb); | ||
473 | if (rc) | ||
474 | clear_bit(NCI_DATA_EXCHANGE, &ndev->flags); | ||
475 | |||
476 | return rc; | ||
477 | } | ||
478 | |||
479 | static struct nfc_ops nci_nfc_ops = { | ||
480 | .dev_up = nci_dev_up, | ||
481 | .dev_down = nci_dev_down, | ||
482 | .start_poll = nci_start_poll, | ||
483 | .stop_poll = nci_stop_poll, | ||
484 | .activate_target = nci_activate_target, | ||
485 | .deactivate_target = nci_deactivate_target, | ||
486 | .data_exchange = nci_data_exchange, | ||
487 | }; | ||
488 | |||
489 | /* ---- Interface to NCI drivers ---- */ | ||
490 | |||
491 | /** | ||
492 | * nci_allocate_device - allocate a new nci device | ||
493 | * | ||
494 | * @ops: device operations | ||
495 | * @supported_protocols: NFC protocols supported by the device | ||
496 | */ | ||
497 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, | ||
498 | __u32 supported_protocols, | ||
499 | int tx_headroom, | ||
500 | int tx_tailroom) | ||
501 | { | ||
502 | struct nci_dev *ndev; | ||
503 | |||
504 | nfc_dbg("entry, supported_protocols 0x%x", supported_protocols); | ||
505 | |||
506 | if (!ops->open || !ops->close || !ops->send) | ||
507 | return NULL; | ||
508 | |||
509 | if (!supported_protocols) | ||
510 | return NULL; | ||
511 | |||
512 | ndev = kzalloc(sizeof(struct nci_dev), GFP_KERNEL); | ||
513 | if (!ndev) | ||
514 | return NULL; | ||
515 | |||
516 | ndev->ops = ops; | ||
517 | ndev->tx_headroom = tx_headroom; | ||
518 | ndev->tx_tailroom = tx_tailroom; | ||
519 | |||
520 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, | ||
521 | supported_protocols, | ||
522 | tx_headroom + NCI_DATA_HDR_SIZE, | ||
523 | tx_tailroom); | ||
524 | if (!ndev->nfc_dev) | ||
525 | goto free_exit; | ||
526 | |||
527 | nfc_set_drvdata(ndev->nfc_dev, ndev); | ||
528 | |||
529 | return ndev; | ||
530 | |||
531 | free_exit: | ||
532 | kfree(ndev); | ||
533 | return NULL; | ||
534 | } | ||
535 | EXPORT_SYMBOL(nci_allocate_device); | ||
536 | |||
537 | /** | ||
538 | * nci_free_device - deallocate nci device | ||
539 | * | ||
540 | * @ndev: The nci device to deallocate | ||
541 | */ | ||
542 | void nci_free_device(struct nci_dev *ndev) | ||
543 | { | ||
544 | nfc_dbg("entry"); | ||
545 | |||
546 | nfc_free_device(ndev->nfc_dev); | ||
547 | kfree(ndev); | ||
548 | } | ||
549 | EXPORT_SYMBOL(nci_free_device); | ||
550 | |||
551 | /** | ||
552 | * nci_register_device - register a nci device in the nfc subsystem | ||
553 | * | ||
554 | * @dev: The nci device to register | ||
555 | */ | ||
556 | int nci_register_device(struct nci_dev *ndev) | ||
557 | { | ||
558 | int rc; | ||
559 | struct device *dev = &ndev->nfc_dev->dev; | ||
560 | char name[32]; | ||
561 | |||
562 | nfc_dbg("entry"); | ||
563 | |||
564 | rc = nfc_register_device(ndev->nfc_dev); | ||
565 | if (rc) | ||
566 | goto exit; | ||
567 | |||
568 | ndev->flags = 0; | ||
569 | |||
570 | INIT_WORK(&ndev->cmd_work, nci_cmd_work); | ||
571 | snprintf(name, sizeof(name), "%s_nci_cmd_wq", dev_name(dev)); | ||
572 | ndev->cmd_wq = create_singlethread_workqueue(name); | ||
573 | if (!ndev->cmd_wq) { | ||
574 | rc = -ENOMEM; | ||
575 | goto unreg_exit; | ||
576 | } | ||
577 | |||
578 | INIT_WORK(&ndev->rx_work, nci_rx_work); | ||
579 | snprintf(name, sizeof(name), "%s_nci_rx_wq", dev_name(dev)); | ||
580 | ndev->rx_wq = create_singlethread_workqueue(name); | ||
581 | if (!ndev->rx_wq) { | ||
582 | rc = -ENOMEM; | ||
583 | goto destroy_cmd_wq_exit; | ||
584 | } | ||
585 | |||
586 | INIT_WORK(&ndev->tx_work, nci_tx_work); | ||
587 | snprintf(name, sizeof(name), "%s_nci_tx_wq", dev_name(dev)); | ||
588 | ndev->tx_wq = create_singlethread_workqueue(name); | ||
589 | if (!ndev->tx_wq) { | ||
590 | rc = -ENOMEM; | ||
591 | goto destroy_rx_wq_exit; | ||
592 | } | ||
593 | |||
594 | skb_queue_head_init(&ndev->cmd_q); | ||
595 | skb_queue_head_init(&ndev->rx_q); | ||
596 | skb_queue_head_init(&ndev->tx_q); | ||
597 | |||
598 | setup_timer(&ndev->cmd_timer, nci_cmd_timer, | ||
599 | (unsigned long) ndev); | ||
600 | |||
601 | mutex_init(&ndev->req_lock); | ||
602 | |||
603 | goto exit; | ||
604 | |||
605 | destroy_rx_wq_exit: | ||
606 | destroy_workqueue(ndev->rx_wq); | ||
607 | |||
608 | destroy_cmd_wq_exit: | ||
609 | destroy_workqueue(ndev->cmd_wq); | ||
610 | |||
611 | unreg_exit: | ||
612 | nfc_unregister_device(ndev->nfc_dev); | ||
613 | |||
614 | exit: | ||
615 | return rc; | ||
616 | } | ||
617 | EXPORT_SYMBOL(nci_register_device); | ||
618 | |||
619 | /** | ||
620 | * nci_unregister_device - unregister a nci device in the nfc subsystem | ||
621 | * | ||
622 | * @dev: The nci device to unregister | ||
623 | */ | ||
624 | void nci_unregister_device(struct nci_dev *ndev) | ||
625 | { | ||
626 | nfc_dbg("entry"); | ||
627 | |||
628 | nci_close_device(ndev); | ||
629 | |||
630 | destroy_workqueue(ndev->cmd_wq); | ||
631 | destroy_workqueue(ndev->rx_wq); | ||
632 | destroy_workqueue(ndev->tx_wq); | ||
633 | |||
634 | nfc_unregister_device(ndev->nfc_dev); | ||
635 | } | ||
636 | EXPORT_SYMBOL(nci_unregister_device); | ||
637 | |||
638 | /** | ||
639 | * nci_recv_frame - receive frame from NCI drivers | ||
640 | * | ||
641 | * @skb: The sk_buff to receive | ||
642 | */ | ||
643 | int nci_recv_frame(struct sk_buff *skb) | ||
644 | { | ||
645 | struct nci_dev *ndev = (struct nci_dev *) skb->dev; | ||
646 | |||
647 | nfc_dbg("entry, len %d", skb->len); | ||
648 | |||
649 | if (!ndev || (!test_bit(NCI_UP, &ndev->flags) | ||
650 | && !test_bit(NCI_INIT, &ndev->flags))) { | ||
651 | kfree_skb(skb); | ||
652 | return -ENXIO; | ||
653 | } | ||
654 | |||
655 | /* Queue frame for rx worker thread */ | ||
656 | skb_queue_tail(&ndev->rx_q, skb); | ||
657 | queue_work(ndev->rx_wq, &ndev->rx_work); | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | EXPORT_SYMBOL(nci_recv_frame); | ||
662 | |||
663 | static int nci_send_frame(struct sk_buff *skb) | ||
664 | { | ||
665 | struct nci_dev *ndev = (struct nci_dev *) skb->dev; | ||
666 | |||
667 | nfc_dbg("entry, len %d", skb->len); | ||
668 | |||
669 | if (!ndev) { | ||
670 | kfree_skb(skb); | ||
671 | return -ENODEV; | ||
672 | } | ||
673 | |||
674 | /* Get rid of skb owner, prior to sending to the driver. */ | ||
675 | skb_orphan(skb); | ||
676 | |||
677 | return ndev->ops->send(skb); | ||
678 | } | ||
679 | |||
680 | /* Send NCI command */ | ||
681 | int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload) | ||
682 | { | ||
683 | struct nci_ctrl_hdr *hdr; | ||
684 | struct sk_buff *skb; | ||
685 | |||
686 | nfc_dbg("entry, opcode 0x%x, plen %d", opcode, plen); | ||
687 | |||
688 | skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + plen), GFP_KERNEL); | ||
689 | if (!skb) { | ||
690 | nfc_err("no memory for command"); | ||
691 | return -ENOMEM; | ||
692 | } | ||
693 | |||
694 | hdr = (struct nci_ctrl_hdr *) skb_put(skb, NCI_CTRL_HDR_SIZE); | ||
695 | hdr->gid = nci_opcode_gid(opcode); | ||
696 | hdr->oid = nci_opcode_oid(opcode); | ||
697 | hdr->plen = plen; | ||
698 | |||
699 | nci_mt_set((__u8 *)hdr, NCI_MT_CMD_PKT); | ||
700 | nci_pbf_set((__u8 *)hdr, NCI_PBF_LAST); | ||
701 | |||
702 | if (plen) | ||
703 | memcpy(skb_put(skb, plen), payload, plen); | ||
704 | |||
705 | skb->dev = (void *) ndev; | ||
706 | |||
707 | skb_queue_tail(&ndev->cmd_q, skb); | ||
708 | queue_work(ndev->cmd_wq, &ndev->cmd_work); | ||
709 | |||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | /* ---- NCI TX Data worker thread ---- */ | ||
714 | |||
715 | static void nci_tx_work(struct work_struct *work) | ||
716 | { | ||
717 | struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work); | ||
718 | struct sk_buff *skb; | ||
719 | |||
720 | nfc_dbg("entry, credits_cnt %d", atomic_read(&ndev->credits_cnt)); | ||
721 | |||
722 | /* Send queued tx data */ | ||
723 | while (atomic_read(&ndev->credits_cnt)) { | ||
724 | skb = skb_dequeue(&ndev->tx_q); | ||
725 | if (!skb) | ||
726 | return; | ||
727 | |||
728 | atomic_dec(&ndev->credits_cnt); | ||
729 | |||
730 | nfc_dbg("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d", | ||
731 | nci_pbf(skb->data), | ||
732 | nci_conn_id(skb->data), | ||
733 | nci_plen(skb->data)); | ||
734 | |||
735 | nci_send_frame(skb); | ||
736 | } | ||
737 | } | ||
738 | |||
739 | /* ----- NCI RX worker thread (data & control) ----- */ | ||
740 | |||
741 | static void nci_rx_work(struct work_struct *work) | ||
742 | { | ||
743 | struct nci_dev *ndev = container_of(work, struct nci_dev, rx_work); | ||
744 | struct sk_buff *skb; | ||
745 | |||
746 | while ((skb = skb_dequeue(&ndev->rx_q))) { | ||
747 | /* Process frame */ | ||
748 | switch (nci_mt(skb->data)) { | ||
749 | case NCI_MT_RSP_PKT: | ||
750 | nci_rsp_packet(ndev, skb); | ||
751 | break; | ||
752 | |||
753 | case NCI_MT_NTF_PKT: | ||
754 | nci_ntf_packet(ndev, skb); | ||
755 | break; | ||
756 | |||
757 | case NCI_MT_DATA_PKT: | ||
758 | nci_rx_data_packet(ndev, skb); | ||
759 | break; | ||
760 | |||
761 | default: | ||
762 | nfc_err("unknown MT 0x%x", nci_mt(skb->data)); | ||
763 | kfree_skb(skb); | ||
764 | break; | ||
765 | } | ||
766 | } | ||
767 | } | ||
768 | |||
769 | /* ----- NCI TX CMD worker thread ----- */ | ||
770 | |||
771 | static void nci_cmd_work(struct work_struct *work) | ||
772 | { | ||
773 | struct nci_dev *ndev = container_of(work, struct nci_dev, cmd_work); | ||
774 | struct sk_buff *skb; | ||
775 | |||
776 | nfc_dbg("entry, cmd_cnt %d", atomic_read(&ndev->cmd_cnt)); | ||
777 | |||
778 | /* Send queued command */ | ||
779 | if (atomic_read(&ndev->cmd_cnt)) { | ||
780 | skb = skb_dequeue(&ndev->cmd_q); | ||
781 | if (!skb) | ||
782 | return; | ||
783 | |||
784 | atomic_dec(&ndev->cmd_cnt); | ||
785 | |||
786 | nfc_dbg("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", | ||
787 | nci_pbf(skb->data), | ||
788 | nci_opcode_gid(nci_opcode(skb->data)), | ||
789 | nci_opcode_oid(nci_opcode(skb->data)), | ||
790 | nci_plen(skb->data)); | ||
791 | |||
792 | nci_send_frame(skb); | ||
793 | |||
794 | mod_timer(&ndev->cmd_timer, | ||
795 | jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT)); | ||
796 | } | ||
797 | } | ||
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c new file mode 100644 index 000000000000..e5ed90fc1a9c --- /dev/null +++ b/net/nfc/nci/data.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * The NFC Controller Interface is the communication protocol between an | ||
3 | * NFC Controller (NFCC) and a Device Host (DH). | ||
4 | * | ||
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
6 | * | ||
7 | * Written by Ilan Elias <ilane@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 | ||
11 | * as published by the Free Software Foundation | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/bitops.h> | ||
28 | #include <linux/skbuff.h> | ||
29 | |||
30 | #include "../nfc.h" | ||
31 | #include <net/nfc/nci.h> | ||
32 | #include <net/nfc/nci_core.h> | ||
33 | #include <linux/nfc.h> | ||
34 | |||
35 | /* Complete data exchange transaction and forward skb to nfc core */ | ||
36 | void nci_data_exchange_complete(struct nci_dev *ndev, | ||
37 | struct sk_buff *skb, | ||
38 | int err) | ||
39 | { | ||
40 | data_exchange_cb_t cb = ndev->data_exchange_cb; | ||
41 | void *cb_context = ndev->data_exchange_cb_context; | ||
42 | |||
43 | nfc_dbg("entry, len %d, err %d", ((skb) ? (skb->len) : (0)), err); | ||
44 | |||
45 | if (cb) { | ||
46 | ndev->data_exchange_cb = NULL; | ||
47 | ndev->data_exchange_cb_context = 0; | ||
48 | |||
49 | /* forward skb to nfc core */ | ||
50 | cb(cb_context, skb, err); | ||
51 | } else if (skb) { | ||
52 | nfc_err("no rx callback, dropping rx data..."); | ||
53 | |||
54 | /* no waiting callback, free skb */ | ||
55 | kfree_skb(skb); | ||
56 | } | ||
57 | |||
58 | clear_bit(NCI_DATA_EXCHANGE, &ndev->flags); | ||
59 | } | ||
60 | |||
61 | /* ----------------- NCI TX Data ----------------- */ | ||
62 | |||
63 | static inline void nci_push_data_hdr(struct nci_dev *ndev, | ||
64 | __u8 conn_id, | ||
65 | struct sk_buff *skb, | ||
66 | __u8 pbf) | ||
67 | { | ||
68 | struct nci_data_hdr *hdr; | ||
69 | int plen = skb->len; | ||
70 | |||
71 | hdr = (struct nci_data_hdr *) skb_push(skb, NCI_DATA_HDR_SIZE); | ||
72 | hdr->conn_id = conn_id; | ||
73 | hdr->rfu = 0; | ||
74 | hdr->plen = plen; | ||
75 | |||
76 | nci_mt_set((__u8 *)hdr, NCI_MT_DATA_PKT); | ||
77 | nci_pbf_set((__u8 *)hdr, pbf); | ||
78 | |||
79 | skb->dev = (void *) ndev; | ||
80 | } | ||
81 | |||
82 | static int nci_queue_tx_data_frags(struct nci_dev *ndev, | ||
83 | __u8 conn_id, | ||
84 | struct sk_buff *skb) { | ||
85 | int total_len = skb->len; | ||
86 | unsigned char *data = skb->data; | ||
87 | unsigned long flags; | ||
88 | struct sk_buff_head frags_q; | ||
89 | struct sk_buff *skb_frag; | ||
90 | int frag_len; | ||
91 | int rc = 0; | ||
92 | |||
93 | nfc_dbg("entry, conn_id 0x%x, total_len %d", conn_id, total_len); | ||
94 | |||
95 | __skb_queue_head_init(&frags_q); | ||
96 | |||
97 | while (total_len) { | ||
98 | frag_len = min_t(int, total_len, ndev->max_pkt_payload_size); | ||
99 | |||
100 | skb_frag = nci_skb_alloc(ndev, | ||
101 | (NCI_DATA_HDR_SIZE + frag_len), | ||
102 | GFP_KERNEL); | ||
103 | if (skb_frag == NULL) { | ||
104 | rc = -ENOMEM; | ||
105 | goto free_exit; | ||
106 | } | ||
107 | skb_reserve(skb_frag, NCI_DATA_HDR_SIZE); | ||
108 | |||
109 | /* first, copy the data */ | ||
110 | memcpy(skb_put(skb_frag, frag_len), data, frag_len); | ||
111 | |||
112 | /* second, set the header */ | ||
113 | nci_push_data_hdr(ndev, conn_id, skb_frag, | ||
114 | ((total_len == frag_len) ? (NCI_PBF_LAST) : (NCI_PBF_CONT))); | ||
115 | |||
116 | __skb_queue_tail(&frags_q, skb_frag); | ||
117 | |||
118 | data += frag_len; | ||
119 | total_len -= frag_len; | ||
120 | |||
121 | nfc_dbg("frag_len %d, remaining total_len %d", | ||
122 | frag_len, total_len); | ||
123 | } | ||
124 | |||
125 | /* queue all fragments atomically */ | ||
126 | spin_lock_irqsave(&ndev->tx_q.lock, flags); | ||
127 | |||
128 | while ((skb_frag = __skb_dequeue(&frags_q)) != NULL) | ||
129 | __skb_queue_tail(&ndev->tx_q, skb_frag); | ||
130 | |||
131 | spin_unlock_irqrestore(&ndev->tx_q.lock, flags); | ||
132 | |||
133 | /* free the original skb */ | ||
134 | kfree_skb(skb); | ||
135 | |||
136 | goto exit; | ||
137 | |||
138 | free_exit: | ||
139 | while ((skb_frag = __skb_dequeue(&frags_q)) != NULL) | ||
140 | kfree_skb(skb_frag); | ||
141 | |||
142 | exit: | ||
143 | return rc; | ||
144 | } | ||
145 | |||
146 | /* Send NCI data */ | ||
147 | int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb) | ||
148 | { | ||
149 | int rc = 0; | ||
150 | |||
151 | nfc_dbg("entry, conn_id 0x%x, plen %d", conn_id, skb->len); | ||
152 | |||
153 | /* check if the packet need to be fragmented */ | ||
154 | if (skb->len <= ndev->max_pkt_payload_size) { | ||
155 | /* no need to fragment packet */ | ||
156 | nci_push_data_hdr(ndev, conn_id, skb, NCI_PBF_LAST); | ||
157 | |||
158 | skb_queue_tail(&ndev->tx_q, skb); | ||
159 | } else { | ||
160 | /* fragment packet and queue the fragments */ | ||
161 | rc = nci_queue_tx_data_frags(ndev, conn_id, skb); | ||
162 | if (rc) { | ||
163 | nfc_err("failed to fragment tx data packet"); | ||
164 | goto free_exit; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | queue_work(ndev->tx_wq, &ndev->tx_work); | ||
169 | |||
170 | goto exit; | ||
171 | |||
172 | free_exit: | ||
173 | kfree_skb(skb); | ||
174 | |||
175 | exit: | ||
176 | return rc; | ||
177 | } | ||
178 | |||
179 | /* ----------------- NCI RX Data ----------------- */ | ||
180 | |||
181 | static void nci_add_rx_data_frag(struct nci_dev *ndev, | ||
182 | struct sk_buff *skb, | ||
183 | __u8 pbf) | ||
184 | { | ||
185 | int reassembly_len; | ||
186 | int err = 0; | ||
187 | |||
188 | if (ndev->rx_data_reassembly) { | ||
189 | reassembly_len = ndev->rx_data_reassembly->len; | ||
190 | |||
191 | /* first, make enough room for the already accumulated data */ | ||
192 | if (skb_cow_head(skb, reassembly_len)) { | ||
193 | nfc_err("error adding room for accumulated rx data"); | ||
194 | |||
195 | kfree_skb(skb); | ||
196 | skb = 0; | ||
197 | |||
198 | kfree_skb(ndev->rx_data_reassembly); | ||
199 | ndev->rx_data_reassembly = 0; | ||
200 | |||
201 | err = -ENOMEM; | ||
202 | goto exit; | ||
203 | } | ||
204 | |||
205 | /* second, combine the two fragments */ | ||
206 | memcpy(skb_push(skb, reassembly_len), | ||
207 | ndev->rx_data_reassembly->data, | ||
208 | reassembly_len); | ||
209 | |||
210 | /* third, free old reassembly */ | ||
211 | kfree_skb(ndev->rx_data_reassembly); | ||
212 | ndev->rx_data_reassembly = 0; | ||
213 | } | ||
214 | |||
215 | if (pbf == NCI_PBF_CONT) { | ||
216 | /* need to wait for next fragment, store skb and exit */ | ||
217 | ndev->rx_data_reassembly = skb; | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | exit: | ||
222 | nci_data_exchange_complete(ndev, skb, err); | ||
223 | } | ||
224 | |||
225 | /* Rx Data packet */ | ||
226 | void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb) | ||
227 | { | ||
228 | __u8 pbf = nci_pbf(skb->data); | ||
229 | |||
230 | nfc_dbg("entry, len %d", skb->len); | ||
231 | |||
232 | nfc_dbg("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d", | ||
233 | nci_pbf(skb->data), | ||
234 | nci_conn_id(skb->data), | ||
235 | nci_plen(skb->data)); | ||
236 | |||
237 | /* strip the nci data header */ | ||
238 | skb_pull(skb, NCI_DATA_HDR_SIZE); | ||
239 | |||
240 | if (ndev->target_active_prot == NFC_PROTO_MIFARE) { | ||
241 | /* frame I/F => remove the status byte */ | ||
242 | nfc_dbg("NFC_PROTO_MIFARE => remove the status byte"); | ||
243 | skb_trim(skb, (skb->len - 1)); | ||
244 | } | ||
245 | |||
246 | nci_add_rx_data_frag(ndev, skb, pbf); | ||
247 | } | ||
diff --git a/net/nfc/nci/lib.c b/net/nfc/nci/lib.c new file mode 100644 index 000000000000..b19dc2fa90e1 --- /dev/null +++ b/net/nfc/nci/lib.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * The NFC Controller Interface is the communication protocol between an | ||
3 | * NFC Controller (NFCC) and a Device Host (DH). | ||
4 | * | ||
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
6 | * | ||
7 | * Written by Ilan Elias <ilane@ti.com> | ||
8 | * | ||
9 | * Acknowledgements: | ||
10 | * This file is based on lib.c, which was written | ||
11 | * by Maxim Krasnyansky. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 | ||
15 | * as published by the Free Software Foundation | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/errno.h> | ||
32 | |||
33 | #include <net/nfc/nci.h> | ||
34 | |||
35 | /* NCI status codes to Unix errno mapping */ | ||
36 | int nci_to_errno(__u8 code) | ||
37 | { | ||
38 | switch (code) { | ||
39 | case NCI_STATUS_OK: | ||
40 | return 0; | ||
41 | |||
42 | case NCI_STATUS_REJECTED: | ||
43 | return -EBUSY; | ||
44 | |||
45 | case NCI_STATUS_MESSAGE_CORRUPTED: | ||
46 | return -EBADMSG; | ||
47 | |||
48 | case NCI_STATUS_BUFFER_FULL: | ||
49 | return -ENOBUFS; | ||
50 | |||
51 | case NCI_STATUS_NOT_INITIALIZED: | ||
52 | return -EHOSTDOWN; | ||
53 | |||
54 | case NCI_STATUS_SYNTAX_ERROR: | ||
55 | case NCI_STATUS_SEMANTIC_ERROR: | ||
56 | case NCI_STATUS_INVALID_PARAM: | ||
57 | case NCI_STATUS_RF_PROTOCOL_ERROR: | ||
58 | case NCI_STATUS_NFCEE_PROTOCOL_ERROR: | ||
59 | return -EPROTO; | ||
60 | |||
61 | case NCI_STATUS_UNKNOWN_GID: | ||
62 | case NCI_STATUS_UNKNOWN_OID: | ||
63 | return -EBADRQC; | ||
64 | |||
65 | case NCI_STATUS_MESSAGE_SIZE_EXCEEDED: | ||
66 | return -EMSGSIZE; | ||
67 | |||
68 | case NCI_STATUS_DISCOVERY_ALREADY_STARTED: | ||
69 | return -EALREADY; | ||
70 | |||
71 | case NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED: | ||
72 | case NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED: | ||
73 | return -ECONNREFUSED; | ||
74 | |||
75 | case NCI_STATUS_RF_TRANSMISSION_ERROR: | ||
76 | case NCI_STATUS_NFCEE_TRANSMISSION_ERROR: | ||
77 | return -ECOMM; | ||
78 | |||
79 | case NCI_STATUS_RF_TIMEOUT_ERROR: | ||
80 | case NCI_STATUS_NFCEE_TIMEOUT_ERROR: | ||
81 | return -ETIMEDOUT; | ||
82 | |||
83 | case NCI_STATUS_RF_LINK_LOSS_ERROR: | ||
84 | return -ENOLINK; | ||
85 | |||
86 | case NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED: | ||
87 | return -EDQUOT; | ||
88 | |||
89 | case NCI_STATUS_FAILED: | ||
90 | default: | ||
91 | return -ENOSYS; | ||
92 | } | ||
93 | } | ||
94 | EXPORT_SYMBOL(nci_to_errno); | ||
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c new file mode 100644 index 000000000000..96633f5cda4f --- /dev/null +++ b/net/nfc/nci/ntf.c | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * The NFC Controller Interface is the communication protocol between an | ||
3 | * NFC Controller (NFCC) and a Device Host (DH). | ||
4 | * | ||
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
6 | * | ||
7 | * Written by Ilan Elias <ilane@ti.com> | ||
8 | * | ||
9 | * Acknowledgements: | ||
10 | * This file is based on hci_event.c, which was written | ||
11 | * by Maxim Krasnyansky. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 | ||
15 | * as published by the Free Software Foundation | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/types.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/bitops.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | |||
33 | #include "../nfc.h" | ||
34 | #include <net/nfc/nci.h> | ||
35 | #include <net/nfc/nci_core.h> | ||
36 | #include <linux/nfc.h> | ||
37 | |||
38 | /* Handle NCI Notification packets */ | ||
39 | |||
40 | static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, | ||
41 | struct sk_buff *skb) | ||
42 | { | ||
43 | struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; | ||
44 | int i; | ||
45 | |||
46 | nfc_dbg("entry, num_entries %d", ntf->num_entries); | ||
47 | |||
48 | if (ntf->num_entries > NCI_MAX_NUM_CONN) | ||
49 | ntf->num_entries = NCI_MAX_NUM_CONN; | ||
50 | |||
51 | /* update the credits */ | ||
52 | for (i = 0; i < ntf->num_entries; i++) { | ||
53 | nfc_dbg("entry[%d]: conn_id %d, credits %d", i, | ||
54 | ntf->conn_entries[i].conn_id, | ||
55 | ntf->conn_entries[i].credits); | ||
56 | |||
57 | if (ntf->conn_entries[i].conn_id == ndev->conn_id) { | ||
58 | /* found static rf connection */ | ||
59 | atomic_add(ntf->conn_entries[i].credits, | ||
60 | &ndev->credits_cnt); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /* trigger the next tx */ | ||
65 | if (!skb_queue_empty(&ndev->tx_q)) | ||
66 | queue_work(ndev->tx_wq, &ndev->tx_work); | ||
67 | } | ||
68 | |||
69 | static void nci_rf_field_info_ntf_packet(struct nci_dev *ndev, | ||
70 | struct sk_buff *skb) | ||
71 | { | ||
72 | struct nci_rf_field_info_ntf *ntf = (void *) skb->data; | ||
73 | |||
74 | nfc_dbg("entry, rf_field_status %d", ntf->rf_field_status); | ||
75 | } | ||
76 | |||
77 | static int nci_rf_activate_nfca_passive_poll(struct nci_dev *ndev, | ||
78 | struct nci_rf_activate_ntf *ntf, __u8 *data) | ||
79 | { | ||
80 | struct rf_tech_specific_params_nfca_poll *nfca_poll; | ||
81 | struct activation_params_nfca_poll_iso_dep *nfca_poll_iso_dep; | ||
82 | |||
83 | nfca_poll = &ntf->rf_tech_specific_params.nfca_poll; | ||
84 | nfca_poll_iso_dep = &ntf->activation_params.nfca_poll_iso_dep; | ||
85 | |||
86 | nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); | ||
87 | data += 2; | ||
88 | |||
89 | nfca_poll->nfcid1_len = *data++; | ||
90 | |||
91 | nfc_dbg("sens_res 0x%x, nfcid1_len %d", | ||
92 | nfca_poll->sens_res, | ||
93 | nfca_poll->nfcid1_len); | ||
94 | |||
95 | memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); | ||
96 | data += nfca_poll->nfcid1_len; | ||
97 | |||
98 | nfca_poll->sel_res_len = *data++; | ||
99 | |||
100 | if (nfca_poll->sel_res_len != 0) | ||
101 | nfca_poll->sel_res = *data++; | ||
102 | |||
103 | ntf->rf_interface_type = *data++; | ||
104 | ntf->activation_params_len = *data++; | ||
105 | |||
106 | nfc_dbg("sel_res_len %d, sel_res 0x%x, rf_interface_type %d, activation_params_len %d", | ||
107 | nfca_poll->sel_res_len, | ||
108 | nfca_poll->sel_res, | ||
109 | ntf->rf_interface_type, | ||
110 | ntf->activation_params_len); | ||
111 | |||
112 | switch (ntf->rf_interface_type) { | ||
113 | case NCI_RF_INTERFACE_ISO_DEP: | ||
114 | nfca_poll_iso_dep->rats_res_len = *data++; | ||
115 | if (nfca_poll_iso_dep->rats_res_len > 0) { | ||
116 | memcpy(nfca_poll_iso_dep->rats_res, | ||
117 | data, | ||
118 | nfca_poll_iso_dep->rats_res_len); | ||
119 | } | ||
120 | break; | ||
121 | |||
122 | case NCI_RF_INTERFACE_FRAME: | ||
123 | /* no activation params */ | ||
124 | break; | ||
125 | |||
126 | default: | ||
127 | nfc_err("unsupported rf_interface_type 0x%x", | ||
128 | ntf->rf_interface_type); | ||
129 | return -EPROTO; | ||
130 | } | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static void nci_target_found(struct nci_dev *ndev, | ||
136 | struct nci_rf_activate_ntf *ntf) | ||
137 | { | ||
138 | struct nfc_target nfc_tgt; | ||
139 | |||
140 | if (ntf->rf_protocol == NCI_RF_PROTOCOL_T2T) /* T2T MifareUL */ | ||
141 | nfc_tgt.supported_protocols = NFC_PROTO_MIFARE_MASK; | ||
142 | else if (ntf->rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) /* 4A */ | ||
143 | nfc_tgt.supported_protocols = NFC_PROTO_ISO14443_MASK; | ||
144 | |||
145 | nfc_tgt.sens_res = ntf->rf_tech_specific_params.nfca_poll.sens_res; | ||
146 | nfc_tgt.sel_res = ntf->rf_tech_specific_params.nfca_poll.sel_res; | ||
147 | |||
148 | if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) { | ||
149 | nfc_dbg("the target found does not have the desired protocol"); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | nfc_dbg("new target found, supported_protocols 0x%x", | ||
154 | nfc_tgt.supported_protocols); | ||
155 | |||
156 | ndev->target_available_prots = nfc_tgt.supported_protocols; | ||
157 | |||
158 | nfc_targets_found(ndev->nfc_dev, &nfc_tgt, 1); | ||
159 | } | ||
160 | |||
161 | static void nci_rf_activate_ntf_packet(struct nci_dev *ndev, | ||
162 | struct sk_buff *skb) | ||
163 | { | ||
164 | struct nci_rf_activate_ntf ntf; | ||
165 | __u8 *data = skb->data; | ||
166 | int rc = -1; | ||
167 | |||
168 | clear_bit(NCI_DISCOVERY, &ndev->flags); | ||
169 | set_bit(NCI_POLL_ACTIVE, &ndev->flags); | ||
170 | |||
171 | ntf.target_handle = *data++; | ||
172 | ntf.rf_protocol = *data++; | ||
173 | ntf.rf_tech_and_mode = *data++; | ||
174 | ntf.rf_tech_specific_params_len = *data++; | ||
175 | |||
176 | nfc_dbg("target_handle %d, rf_protocol 0x%x, rf_tech_and_mode 0x%x, rf_tech_specific_params_len %d", | ||
177 | ntf.target_handle, | ||
178 | ntf.rf_protocol, | ||
179 | ntf.rf_tech_and_mode, | ||
180 | ntf.rf_tech_specific_params_len); | ||
181 | |||
182 | switch (ntf.rf_tech_and_mode) { | ||
183 | case NCI_NFC_A_PASSIVE_POLL_MODE: | ||
184 | rc = nci_rf_activate_nfca_passive_poll(ndev, &ntf, | ||
185 | data); | ||
186 | break; | ||
187 | |||
188 | default: | ||
189 | nfc_err("unsupported rf_tech_and_mode 0x%x", | ||
190 | ntf.rf_tech_and_mode); | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | if (!rc) | ||
195 | nci_target_found(ndev, &ntf); | ||
196 | } | ||
197 | |||
198 | static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | ||
199 | struct sk_buff *skb) | ||
200 | { | ||
201 | __u8 type = skb->data[0]; | ||
202 | |||
203 | nfc_dbg("entry, type 0x%x", type); | ||
204 | |||
205 | clear_bit(NCI_POLL_ACTIVE, &ndev->flags); | ||
206 | ndev->target_active_prot = 0; | ||
207 | |||
208 | /* drop tx data queue */ | ||
209 | skb_queue_purge(&ndev->tx_q); | ||
210 | |||
211 | /* drop partial rx data packet */ | ||
212 | if (ndev->rx_data_reassembly) { | ||
213 | kfree_skb(ndev->rx_data_reassembly); | ||
214 | ndev->rx_data_reassembly = 0; | ||
215 | } | ||
216 | |||
217 | /* complete the data exchange transaction, if exists */ | ||
218 | if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) | ||
219 | nci_data_exchange_complete(ndev, NULL, -EIO); | ||
220 | } | ||
221 | |||
222 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | ||
223 | { | ||
224 | __u16 ntf_opcode = nci_opcode(skb->data); | ||
225 | |||
226 | nfc_dbg("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", | ||
227 | nci_pbf(skb->data), | ||
228 | nci_opcode_gid(ntf_opcode), | ||
229 | nci_opcode_oid(ntf_opcode), | ||
230 | nci_plen(skb->data)); | ||
231 | |||
232 | /* strip the nci control header */ | ||
233 | skb_pull(skb, NCI_CTRL_HDR_SIZE); | ||
234 | |||
235 | switch (ntf_opcode) { | ||
236 | case NCI_OP_CORE_CONN_CREDITS_NTF: | ||
237 | nci_core_conn_credits_ntf_packet(ndev, skb); | ||
238 | break; | ||
239 | |||
240 | case NCI_OP_RF_FIELD_INFO_NTF: | ||
241 | nci_rf_field_info_ntf_packet(ndev, skb); | ||
242 | break; | ||
243 | |||
244 | case NCI_OP_RF_ACTIVATE_NTF: | ||
245 | nci_rf_activate_ntf_packet(ndev, skb); | ||
246 | break; | ||
247 | |||
248 | case NCI_OP_RF_DEACTIVATE_NTF: | ||
249 | nci_rf_deactivate_ntf_packet(ndev, skb); | ||
250 | break; | ||
251 | |||
252 | default: | ||
253 | nfc_err("unknown ntf opcode 0x%x", ntf_opcode); | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | kfree_skb(skb); | ||
258 | } | ||
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c new file mode 100644 index 000000000000..0403d4cd0917 --- /dev/null +++ b/net/nfc/nci/rsp.c | |||
@@ -0,0 +1,226 @@ | |||
1 | /* | ||
2 | * The NFC Controller Interface is the communication protocol between an | ||
3 | * NFC Controller (NFCC) and a Device Host (DH). | ||
4 | * | ||
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
6 | * | ||
7 | * Written by Ilan Elias <ilane@ti.com> | ||
8 | * | ||
9 | * Acknowledgements: | ||
10 | * This file is based on hci_event.c, which was written | ||
11 | * by Maxim Krasnyansky. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 | ||
15 | * as published by the Free Software Foundation | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/types.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/bitops.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | |||
33 | #include "../nfc.h" | ||
34 | #include <net/nfc/nci.h> | ||
35 | #include <net/nfc/nci_core.h> | ||
36 | |||
37 | /* Handle NCI Response packets */ | ||
38 | |||
39 | static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | ||
40 | { | ||
41 | struct nci_core_reset_rsp *rsp = (void *) skb->data; | ||
42 | |||
43 | nfc_dbg("entry, status 0x%x", rsp->status); | ||
44 | |||
45 | if (rsp->status == NCI_STATUS_OK) | ||
46 | ndev->nci_ver = rsp->nci_ver; | ||
47 | |||
48 | nfc_dbg("nci_ver 0x%x", ndev->nci_ver); | ||
49 | |||
50 | nci_req_complete(ndev, rsp->status); | ||
51 | } | ||
52 | |||
53 | static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | ||
54 | { | ||
55 | struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data; | ||
56 | struct nci_core_init_rsp_2 *rsp_2; | ||
57 | |||
58 | nfc_dbg("entry, status 0x%x", rsp_1->status); | ||
59 | |||
60 | if (rsp_1->status != NCI_STATUS_OK) | ||
61 | return; | ||
62 | |||
63 | ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features); | ||
64 | ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces; | ||
65 | |||
66 | if (ndev->num_supported_rf_interfaces > | ||
67 | NCI_MAX_SUPPORTED_RF_INTERFACES) { | ||
68 | ndev->num_supported_rf_interfaces = | ||
69 | NCI_MAX_SUPPORTED_RF_INTERFACES; | ||
70 | } | ||
71 | |||
72 | memcpy(ndev->supported_rf_interfaces, | ||
73 | rsp_1->supported_rf_interfaces, | ||
74 | ndev->num_supported_rf_interfaces); | ||
75 | |||
76 | rsp_2 = (void *) (skb->data + 6 + ndev->num_supported_rf_interfaces); | ||
77 | |||
78 | ndev->max_logical_connections = | ||
79 | rsp_2->max_logical_connections; | ||
80 | ndev->max_routing_table_size = | ||
81 | __le16_to_cpu(rsp_2->max_routing_table_size); | ||
82 | ndev->max_control_packet_payload_length = | ||
83 | rsp_2->max_control_packet_payload_length; | ||
84 | ndev->rf_sending_buffer_size = | ||
85 | __le16_to_cpu(rsp_2->rf_sending_buffer_size); | ||
86 | ndev->rf_receiving_buffer_size = | ||
87 | __le16_to_cpu(rsp_2->rf_receiving_buffer_size); | ||
88 | ndev->manufacturer_id = | ||
89 | __le16_to_cpu(rsp_2->manufacturer_id); | ||
90 | |||
91 | nfc_dbg("nfcc_features 0x%x", | ||
92 | ndev->nfcc_features); | ||
93 | nfc_dbg("num_supported_rf_interfaces %d", | ||
94 | ndev->num_supported_rf_interfaces); | ||
95 | nfc_dbg("supported_rf_interfaces[0] 0x%x", | ||
96 | ndev->supported_rf_interfaces[0]); | ||
97 | nfc_dbg("supported_rf_interfaces[1] 0x%x", | ||
98 | ndev->supported_rf_interfaces[1]); | ||
99 | nfc_dbg("supported_rf_interfaces[2] 0x%x", | ||
100 | ndev->supported_rf_interfaces[2]); | ||
101 | nfc_dbg("supported_rf_interfaces[3] 0x%x", | ||
102 | ndev->supported_rf_interfaces[3]); | ||
103 | nfc_dbg("max_logical_connections %d", | ||
104 | ndev->max_logical_connections); | ||
105 | nfc_dbg("max_routing_table_size %d", | ||
106 | ndev->max_routing_table_size); | ||
107 | nfc_dbg("max_control_packet_payload_length %d", | ||
108 | ndev->max_control_packet_payload_length); | ||
109 | nfc_dbg("rf_sending_buffer_size %d", | ||
110 | ndev->rf_sending_buffer_size); | ||
111 | nfc_dbg("rf_receiving_buffer_size %d", | ||
112 | ndev->rf_receiving_buffer_size); | ||
113 | nfc_dbg("manufacturer_id 0x%x", | ||
114 | ndev->manufacturer_id); | ||
115 | |||
116 | nci_req_complete(ndev, rsp_1->status); | ||
117 | } | ||
118 | |||
119 | static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, | ||
120 | struct sk_buff *skb) | ||
121 | { | ||
122 | struct nci_core_conn_create_rsp *rsp = (void *) skb->data; | ||
123 | |||
124 | nfc_dbg("entry, status 0x%x", rsp->status); | ||
125 | |||
126 | if (rsp->status != NCI_STATUS_OK) | ||
127 | return; | ||
128 | |||
129 | ndev->max_pkt_payload_size = rsp->max_pkt_payload_size; | ||
130 | ndev->initial_num_credits = rsp->initial_num_credits; | ||
131 | ndev->conn_id = rsp->conn_id; | ||
132 | |||
133 | atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); | ||
134 | |||
135 | nfc_dbg("max_pkt_payload_size %d", ndev->max_pkt_payload_size); | ||
136 | nfc_dbg("initial_num_credits %d", ndev->initial_num_credits); | ||
137 | nfc_dbg("conn_id %d", ndev->conn_id); | ||
138 | } | ||
139 | |||
140 | static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev, | ||
141 | struct sk_buff *skb) | ||
142 | { | ||
143 | __u8 status = skb->data[0]; | ||
144 | |||
145 | nfc_dbg("entry, status 0x%x", status); | ||
146 | |||
147 | nci_req_complete(ndev, status); | ||
148 | } | ||
149 | |||
150 | static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | ||
151 | { | ||
152 | __u8 status = skb->data[0]; | ||
153 | |||
154 | nfc_dbg("entry, status 0x%x", status); | ||
155 | |||
156 | if (status == NCI_STATUS_OK) | ||
157 | set_bit(NCI_DISCOVERY, &ndev->flags); | ||
158 | |||
159 | nci_req_complete(ndev, status); | ||
160 | } | ||
161 | |||
162 | static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, | ||
163 | struct sk_buff *skb) | ||
164 | { | ||
165 | __u8 status = skb->data[0]; | ||
166 | |||
167 | nfc_dbg("entry, status 0x%x", status); | ||
168 | |||
169 | clear_bit(NCI_DISCOVERY, &ndev->flags); | ||
170 | |||
171 | nci_req_complete(ndev, status); | ||
172 | } | ||
173 | |||
174 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | ||
175 | { | ||
176 | __u16 rsp_opcode = nci_opcode(skb->data); | ||
177 | |||
178 | /* we got a rsp, stop the cmd timer */ | ||
179 | del_timer(&ndev->cmd_timer); | ||
180 | |||
181 | nfc_dbg("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", | ||
182 | nci_pbf(skb->data), | ||
183 | nci_opcode_gid(rsp_opcode), | ||
184 | nci_opcode_oid(rsp_opcode), | ||
185 | nci_plen(skb->data)); | ||
186 | |||
187 | /* strip the nci control header */ | ||
188 | skb_pull(skb, NCI_CTRL_HDR_SIZE); | ||
189 | |||
190 | switch (rsp_opcode) { | ||
191 | case NCI_OP_CORE_RESET_RSP: | ||
192 | nci_core_reset_rsp_packet(ndev, skb); | ||
193 | break; | ||
194 | |||
195 | case NCI_OP_CORE_INIT_RSP: | ||
196 | nci_core_init_rsp_packet(ndev, skb); | ||
197 | break; | ||
198 | |||
199 | case NCI_OP_CORE_CONN_CREATE_RSP: | ||
200 | nci_core_conn_create_rsp_packet(ndev, skb); | ||
201 | break; | ||
202 | |||
203 | case NCI_OP_RF_DISCOVER_MAP_RSP: | ||
204 | nci_rf_disc_map_rsp_packet(ndev, skb); | ||
205 | break; | ||
206 | |||
207 | case NCI_OP_RF_DISCOVER_RSP: | ||
208 | nci_rf_disc_rsp_packet(ndev, skb); | ||
209 | break; | ||
210 | |||
211 | case NCI_OP_RF_DEACTIVATE_RSP: | ||
212 | nci_rf_deactivate_rsp_packet(ndev, skb); | ||
213 | break; | ||
214 | |||
215 | default: | ||
216 | nfc_err("unknown rsp opcode 0x%x", rsp_opcode); | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | kfree_skb(skb); | ||
221 | |||
222 | /* trigger the next cmd */ | ||
223 | atomic_set(&ndev->cmd_cnt, 1); | ||
224 | if (!skb_queue_empty(&ndev->cmd_q)) | ||
225 | queue_work(ndev->cmd_wq, &ndev->cmd_work); | ||
226 | } | ||
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index ccdff7953f7d..03f8818e1f16 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -367,6 +367,52 @@ out_putdev: | |||
367 | return rc; | 367 | return rc; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int nfc_genl_dev_up(struct sk_buff *skb, struct genl_info *info) | ||
371 | { | ||
372 | struct nfc_dev *dev; | ||
373 | int rc; | ||
374 | u32 idx; | ||
375 | |||
376 | nfc_dbg("entry"); | ||
377 | |||
378 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) | ||
379 | return -EINVAL; | ||
380 | |||
381 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
382 | |||
383 | dev = nfc_get_device(idx); | ||
384 | if (!dev) | ||
385 | return -ENODEV; | ||
386 | |||
387 | rc = nfc_dev_up(dev); | ||
388 | |||
389 | nfc_put_device(dev); | ||
390 | return rc; | ||
391 | } | ||
392 | |||
393 | static int nfc_genl_dev_down(struct sk_buff *skb, struct genl_info *info) | ||
394 | { | ||
395 | struct nfc_dev *dev; | ||
396 | int rc; | ||
397 | u32 idx; | ||
398 | |||
399 | nfc_dbg("entry"); | ||
400 | |||
401 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) | ||
402 | return -EINVAL; | ||
403 | |||
404 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
405 | |||
406 | dev = nfc_get_device(idx); | ||
407 | if (!dev) | ||
408 | return -ENODEV; | ||
409 | |||
410 | rc = nfc_dev_down(dev); | ||
411 | |||
412 | nfc_put_device(dev); | ||
413 | return rc; | ||
414 | } | ||
415 | |||
370 | static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | 416 | static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) |
371 | { | 417 | { |
372 | struct nfc_dev *dev; | 418 | struct nfc_dev *dev; |
@@ -441,6 +487,16 @@ static struct genl_ops nfc_genl_ops[] = { | |||
441 | .policy = nfc_genl_policy, | 487 | .policy = nfc_genl_policy, |
442 | }, | 488 | }, |
443 | { | 489 | { |
490 | .cmd = NFC_CMD_DEV_UP, | ||
491 | .doit = nfc_genl_dev_up, | ||
492 | .policy = nfc_genl_policy, | ||
493 | }, | ||
494 | { | ||
495 | .cmd = NFC_CMD_DEV_DOWN, | ||
496 | .doit = nfc_genl_dev_down, | ||
497 | .policy = nfc_genl_policy, | ||
498 | }, | ||
499 | { | ||
444 | .cmd = NFC_CMD_START_POLL, | 500 | .cmd = NFC_CMD_START_POLL, |
445 | .doit = nfc_genl_start_poll, | 501 | .doit = nfc_genl_start_poll, |
446 | .policy = nfc_genl_policy, | 502 | .policy = nfc_genl_policy, |
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index aaf9832298f3..b6753f45624e 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #ifndef __LOCAL_NFC_H | 24 | #ifndef __LOCAL_NFC_H |
25 | #define __LOCAL_NFC_H | 25 | #define __LOCAL_NFC_H |
26 | 26 | ||
27 | #include <net/nfc.h> | 27 | #include <net/nfc/nfc.h> |
28 | #include <net/sock.h> | 28 | #include <net/sock.h> |
29 | 29 | ||
30 | __attribute__((format (printf, 2, 3))) | 30 | __attribute__((format (printf, 2, 3))) |
@@ -101,6 +101,10 @@ static inline void nfc_device_iter_exit(struct class_dev_iter *iter) | |||
101 | class_dev_iter_exit(iter); | 101 | class_dev_iter_exit(iter); |
102 | } | 102 | } |
103 | 103 | ||
104 | int nfc_dev_up(struct nfc_dev *dev); | ||
105 | |||
106 | int nfc_dev_down(struct nfc_dev *dev); | ||
107 | |||
104 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | 108 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); |
105 | 109 | ||
106 | int nfc_stop_poll(struct nfc_dev *dev); | 110 | int nfc_stop_poll(struct nfc_dev *dev); |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index be90640a2774..5be19575c340 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -235,7 +235,7 @@ static bool __rfkill_set_hw_state(struct rfkill *rfkill, | |||
235 | else | 235 | else |
236 | rfkill->state &= ~RFKILL_BLOCK_HW; | 236 | rfkill->state &= ~RFKILL_BLOCK_HW; |
237 | *change = prev != blocked; | 237 | *change = prev != blocked; |
238 | any = rfkill->state & RFKILL_BLOCK_ANY; | 238 | any = !!(rfkill->state & RFKILL_BLOCK_ANY); |
239 | spin_unlock_irqrestore(&rfkill->lock, flags); | 239 | spin_unlock_irqrestore(&rfkill->lock, flags); |
240 | 240 | ||
241 | rfkill_led_trigger_event(rfkill); | 241 | rfkill_led_trigger_event(rfkill); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 796a4bdf8b0d..b9ec3061ed72 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -375,7 +375,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
375 | struct ieee80211_channel *chan, bool offchan, | 375 | struct ieee80211_channel *chan, bool offchan, |
376 | enum nl80211_channel_type channel_type, | 376 | enum nl80211_channel_type channel_type, |
377 | bool channel_type_valid, unsigned int wait, | 377 | bool channel_type_valid, unsigned int wait, |
378 | const u8 *buf, size_t len, u64 *cookie); | 378 | const u8 *buf, size_t len, bool no_cck, |
379 | u64 *cookie); | ||
379 | 380 | ||
380 | /* SME */ | 381 | /* SME */ |
381 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 382 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
@@ -406,6 +407,7 @@ void cfg80211_sme_failed_assoc(struct wireless_dev *wdev); | |||
406 | bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); | 407 | bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); |
407 | 408 | ||
408 | /* internal helpers */ | 409 | /* internal helpers */ |
410 | bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher); | ||
409 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | 411 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, |
410 | struct key_params *params, int key_idx, | 412 | struct key_params *params, int key_idx, |
411 | bool pairwise, const u8 *mac_addr); | 413 | bool pairwise, const u8 *mac_addr); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 832f6574e4ed..21fc9702f81c 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -900,7 +900,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
900 | struct ieee80211_channel *chan, bool offchan, | 900 | struct ieee80211_channel *chan, bool offchan, |
901 | enum nl80211_channel_type channel_type, | 901 | enum nl80211_channel_type channel_type, |
902 | bool channel_type_valid, unsigned int wait, | 902 | bool channel_type_valid, unsigned int wait, |
903 | const u8 *buf, size_t len, u64 *cookie) | 903 | const u8 *buf, size_t len, bool no_cck, |
904 | u64 *cookie) | ||
904 | { | 905 | { |
905 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 906 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
906 | const struct ieee80211_mgmt *mgmt; | 907 | const struct ieee80211_mgmt *mgmt; |
@@ -991,7 +992,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
991 | /* Transmit the Action frame as requested by user space */ | 992 | /* Transmit the Action frame as requested by user space */ |
992 | return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan, | 993 | return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan, |
993 | channel_type, channel_type_valid, | 994 | channel_type, channel_type_valid, |
994 | wait, buf, len, cookie); | 995 | wait, buf, len, no_cck, cookie); |
995 | } | 996 | } |
996 | 997 | ||
997 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, | 998 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, |
@@ -1095,3 +1096,14 @@ void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid, | |||
1095 | nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); | 1096 | nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp); |
1096 | } | 1097 | } |
1097 | EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); | 1098 | EXPORT_SYMBOL(cfg80211_gtk_rekey_notify); |
1099 | |||
1100 | void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | ||
1101 | const u8 *bssid, bool preauth, gfp_t gfp) | ||
1102 | { | ||
1103 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1104 | struct wiphy *wiphy = wdev->wiphy; | ||
1105 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
1106 | |||
1107 | nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); | ||
1108 | } | ||
1109 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 11089541bb03..b85075761e24 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -191,6 +191,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
191 | .len = IEEE80211_MAX_DATA_LEN }, | 191 | .len = IEEE80211_MAX_DATA_LEN }, |
192 | [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, | 192 | [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, |
193 | [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, | 193 | [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, |
194 | [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG }, | ||
194 | }; | 195 | }; |
195 | 196 | ||
196 | /* policy for the key attributes */ | 197 | /* policy for the key attributes */ |
@@ -1235,6 +1236,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1235 | goto bad_res; | 1236 | goto bad_res; |
1236 | } | 1237 | } |
1237 | 1238 | ||
1239 | if (!netdev) { | ||
1240 | result = -EINVAL; | ||
1241 | goto bad_res; | ||
1242 | } | ||
1243 | |||
1238 | nla_for_each_nested(nl_txq_params, | 1244 | nla_for_each_nested(nl_txq_params, |
1239 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | 1245 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], |
1240 | rem_txq_params) { | 1246 | rem_txq_params) { |
@@ -1247,6 +1253,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1247 | goto bad_res; | 1253 | goto bad_res; |
1248 | 1254 | ||
1249 | result = rdev->ops->set_txq_params(&rdev->wiphy, | 1255 | result = rdev->ops->set_txq_params(&rdev->wiphy, |
1256 | netdev, | ||
1250 | &txq_params); | 1257 | &txq_params); |
1251 | if (result) | 1258 | if (result) |
1252 | goto bad_res; | 1259 | goto bad_res; |
@@ -2613,7 +2620,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2613 | 2620 | ||
2614 | /* parse WME attributes if sta is WME capable */ | 2621 | /* parse WME attributes if sta is WME capable */ |
2615 | if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && | 2622 | if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) && |
2616 | (params.sta_flags_set & NL80211_STA_FLAG_WME) && | 2623 | (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) && |
2617 | info->attrs[NL80211_ATTR_STA_WME]) { | 2624 | info->attrs[NL80211_ATTR_STA_WME]) { |
2618 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | 2625 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; |
2619 | struct nlattr *nla; | 2626 | struct nlattr *nla; |
@@ -3620,6 +3627,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3620 | } | 3627 | } |
3621 | } | 3628 | } |
3622 | 3629 | ||
3630 | request->no_cck = | ||
3631 | nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | ||
3632 | |||
3623 | request->dev = dev; | 3633 | request->dev = dev; |
3624 | request->wiphy = &rdev->wiphy; | 3634 | request->wiphy = &rdev->wiphy; |
3625 | 3635 | ||
@@ -4126,22 +4136,6 @@ static bool nl80211_valid_wpa_versions(u32 wpa_versions) | |||
4126 | NL80211_WPA_VERSION_2)); | 4136 | NL80211_WPA_VERSION_2)); |
4127 | } | 4137 | } |
4128 | 4138 | ||
4129 | static bool nl80211_valid_akm_suite(u32 akm) | ||
4130 | { | ||
4131 | return akm == WLAN_AKM_SUITE_8021X || | ||
4132 | akm == WLAN_AKM_SUITE_PSK; | ||
4133 | } | ||
4134 | |||
4135 | static bool nl80211_valid_cipher_suite(u32 cipher) | ||
4136 | { | ||
4137 | return cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
4138 | cipher == WLAN_CIPHER_SUITE_WEP104 || | ||
4139 | cipher == WLAN_CIPHER_SUITE_TKIP || | ||
4140 | cipher == WLAN_CIPHER_SUITE_CCMP || | ||
4141 | cipher == WLAN_CIPHER_SUITE_AES_CMAC; | ||
4142 | } | ||
4143 | |||
4144 | |||
4145 | static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | 4139 | static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) |
4146 | { | 4140 | { |
4147 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4141 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -4274,7 +4268,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
4274 | memcpy(settings->ciphers_pairwise, data, len); | 4268 | memcpy(settings->ciphers_pairwise, data, len); |
4275 | 4269 | ||
4276 | for (i = 0; i < settings->n_ciphers_pairwise; i++) | 4270 | for (i = 0; i < settings->n_ciphers_pairwise; i++) |
4277 | if (!nl80211_valid_cipher_suite( | 4271 | if (!cfg80211_supported_cipher_suite( |
4272 | &rdev->wiphy, | ||
4278 | settings->ciphers_pairwise[i])) | 4273 | settings->ciphers_pairwise[i])) |
4279 | return -EINVAL; | 4274 | return -EINVAL; |
4280 | } | 4275 | } |
@@ -4282,7 +4277,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
4282 | if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) { | 4277 | if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) { |
4283 | settings->cipher_group = | 4278 | settings->cipher_group = |
4284 | nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]); | 4279 | nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]); |
4285 | if (!nl80211_valid_cipher_suite(settings->cipher_group)) | 4280 | if (!cfg80211_supported_cipher_suite(&rdev->wiphy, |
4281 | settings->cipher_group)) | ||
4286 | return -EINVAL; | 4282 | return -EINVAL; |
4287 | } | 4283 | } |
4288 | 4284 | ||
@@ -4295,7 +4291,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
4295 | 4291 | ||
4296 | if (info->attrs[NL80211_ATTR_AKM_SUITES]) { | 4292 | if (info->attrs[NL80211_ATTR_AKM_SUITES]) { |
4297 | void *data; | 4293 | void *data; |
4298 | int len, i; | 4294 | int len; |
4299 | 4295 | ||
4300 | data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]); | 4296 | data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]); |
4301 | len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]); | 4297 | len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]); |
@@ -4304,11 +4300,10 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | |||
4304 | if (len % sizeof(u32)) | 4300 | if (len % sizeof(u32)) |
4305 | return -EINVAL; | 4301 | return -EINVAL; |
4306 | 4302 | ||
4307 | memcpy(settings->akm_suites, data, len); | 4303 | if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES) |
4304 | return -EINVAL; | ||
4308 | 4305 | ||
4309 | for (i = 0; i < settings->n_ciphers_pairwise; i++) | 4306 | memcpy(settings->akm_suites, data, len); |
4310 | if (!nl80211_valid_akm_suite(settings->akm_suites[i])) | ||
4311 | return -EINVAL; | ||
4312 | } | 4307 | } |
4313 | 4308 | ||
4314 | return 0; | 4309 | return 0; |
@@ -4527,8 +4522,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4527 | 4522 | ||
4528 | wiphy = &rdev->wiphy; | 4523 | wiphy = &rdev->wiphy; |
4529 | 4524 | ||
4530 | if (info->attrs[NL80211_ATTR_MAC]) | 4525 | if (info->attrs[NL80211_ATTR_MAC]) { |
4531 | ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 4526 | ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
4527 | |||
4528 | if (!is_valid_ether_addr(ibss.bssid)) | ||
4529 | return -EINVAL; | ||
4530 | } | ||
4532 | ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 4531 | ibss.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
4533 | ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 4532 | ibss.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
4534 | 4533 | ||
@@ -5185,6 +5184,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
5185 | struct sk_buff *msg; | 5184 | struct sk_buff *msg; |
5186 | unsigned int wait = 0; | 5185 | unsigned int wait = 0; |
5187 | bool offchan; | 5186 | bool offchan; |
5187 | bool no_cck; | ||
5188 | 5188 | ||
5189 | if (!info->attrs[NL80211_ATTR_FRAME] || | 5189 | if (!info->attrs[NL80211_ATTR_FRAME] || |
5190 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 5190 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
@@ -5221,6 +5221,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
5221 | 5221 | ||
5222 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; | 5222 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; |
5223 | 5223 | ||
5224 | no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); | ||
5225 | |||
5224 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 5226 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
5225 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | 5227 | chan = rdev_freq_to_chan(rdev, freq, channel_type); |
5226 | if (chan == NULL) | 5228 | if (chan == NULL) |
@@ -5241,7 +5243,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
5241 | channel_type_valid, wait, | 5243 | channel_type_valid, wait, |
5242 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 5244 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
5243 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 5245 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
5244 | &cookie); | 5246 | no_cck, &cookie); |
5245 | if (err) | 5247 | if (err) |
5246 | goto free_msg; | 5248 | goto free_msg; |
5247 | 5249 | ||
@@ -7266,6 +7268,52 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | |||
7266 | nlmsg_free(msg); | 7268 | nlmsg_free(msg); |
7267 | } | 7269 | } |
7268 | 7270 | ||
7271 | void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | ||
7272 | struct net_device *netdev, int index, | ||
7273 | const u8 *bssid, bool preauth, gfp_t gfp) | ||
7274 | { | ||
7275 | struct sk_buff *msg; | ||
7276 | struct nlattr *attr; | ||
7277 | void *hdr; | ||
7278 | |||
7279 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
7280 | if (!msg) | ||
7281 | return; | ||
7282 | |||
7283 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PMKSA_CANDIDATE); | ||
7284 | if (!hdr) { | ||
7285 | nlmsg_free(msg); | ||
7286 | return; | ||
7287 | } | ||
7288 | |||
7289 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
7290 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
7291 | |||
7292 | attr = nla_nest_start(msg, NL80211_ATTR_PMKSA_CANDIDATE); | ||
7293 | if (!attr) | ||
7294 | goto nla_put_failure; | ||
7295 | |||
7296 | NLA_PUT_U32(msg, NL80211_PMKSA_CANDIDATE_INDEX, index); | ||
7297 | NLA_PUT(msg, NL80211_PMKSA_CANDIDATE_BSSID, ETH_ALEN, bssid); | ||
7298 | if (preauth) | ||
7299 | NLA_PUT_FLAG(msg, NL80211_PMKSA_CANDIDATE_PREAUTH); | ||
7300 | |||
7301 | nla_nest_end(msg, attr); | ||
7302 | |||
7303 | if (genlmsg_end(msg, hdr) < 0) { | ||
7304 | nlmsg_free(msg); | ||
7305 | return; | ||
7306 | } | ||
7307 | |||
7308 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
7309 | nl80211_mlme_mcgrp.id, gfp); | ||
7310 | return; | ||
7311 | |||
7312 | nla_put_failure: | ||
7313 | genlmsg_cancel(msg, hdr); | ||
7314 | nlmsg_free(msg); | ||
7315 | } | ||
7316 | |||
7269 | void | 7317 | void |
7270 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 7318 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, |
7271 | struct net_device *netdev, const u8 *peer, | 7319 | struct net_device *netdev, const u8 *peer, |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 5d69c56400ae..f24a1fbeaf19 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -113,4 +113,8 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev, | |||
113 | struct net_device *netdev, const u8 *bssid, | 113 | struct net_device *netdev, const u8 *bssid, |
114 | const u8 *replay_ctr, gfp_t gfp); | 114 | const u8 *replay_ctr, gfp_t gfp); |
115 | 115 | ||
116 | void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | ||
117 | struct net_device *netdev, int index, | ||
118 | const u8 *bssid, bool preauth, gfp_t gfp); | ||
119 | |||
116 | #endif /* __NET_WIRELESS_NL80211_H */ | 120 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index b0f003966953..0fb142410404 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -228,6 +228,33 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) | |||
228 | } | 228 | } |
229 | EXPORT_SYMBOL(cfg80211_find_ie); | 229 | EXPORT_SYMBOL(cfg80211_find_ie); |
230 | 230 | ||
231 | const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, | ||
232 | const u8 *ies, int len) | ||
233 | { | ||
234 | struct ieee80211_vendor_ie *ie; | ||
235 | const u8 *pos = ies, *end = ies + len; | ||
236 | int ie_oui; | ||
237 | |||
238 | while (pos < end) { | ||
239 | pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos, | ||
240 | end - pos); | ||
241 | if (!pos) | ||
242 | return NULL; | ||
243 | |||
244 | if (end - pos < sizeof(*ie)) | ||
245 | return NULL; | ||
246 | |||
247 | ie = (struct ieee80211_vendor_ie *)pos; | ||
248 | ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2]; | ||
249 | if (ie_oui == oui && ie->oui_type == oui_type) | ||
250 | return pos; | ||
251 | |||
252 | pos += 2 + ie->len; | ||
253 | } | ||
254 | return NULL; | ||
255 | } | ||
256 | EXPORT_SYMBOL(cfg80211_find_vendor_ie); | ||
257 | |||
231 | static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) | 258 | static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) |
232 | { | 259 | { |
233 | const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); | 260 | const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index dec0fa28372e..6e86d5acf145 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -110,17 +110,22 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
110 | else { | 110 | else { |
111 | int i = 0, j; | 111 | int i = 0, j; |
112 | enum ieee80211_band band; | 112 | enum ieee80211_band band; |
113 | struct ieee80211_supported_band *bands; | ||
114 | struct ieee80211_channel *channel; | ||
113 | 115 | ||
114 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 116 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
115 | if (!wdev->wiphy->bands[band]) | 117 | bands = wdev->wiphy->bands[band]; |
118 | if (!bands) | ||
116 | continue; | 119 | continue; |
117 | for (j = 0; j < wdev->wiphy->bands[band]->n_channels; | 120 | for (j = 0; j < bands->n_channels; j++) { |
118 | i++, j++) | 121 | channel = &bands->channels[j]; |
119 | request->channels[i] = | 122 | if (channel->flags & IEEE80211_CHAN_DISABLED) |
120 | &wdev->wiphy->bands[band]->channels[j]; | 123 | continue; |
121 | request->rates[band] = | 124 | request->channels[i++] = channel; |
122 | (1 << wdev->wiphy->bands[band]->n_bitrates) - 1; | 125 | } |
126 | request->rates[band] = (1 << bands->n_bitrates) - 1; | ||
123 | } | 127 | } |
128 | n_channels = i; | ||
124 | } | 129 | } |
125 | request->n_channels = n_channels; | 130 | request->n_channels = n_channels; |
126 | request->ssids = (void *)&request->channels[n_channels]; | 131 | request->ssids = (void *)&request->channels[n_channels]; |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 39dbf4ad7ca1..6304ed63588a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -151,12 +151,19 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy) | |||
151 | set_mandatory_flags_band(wiphy->bands[band], band); | 151 | set_mandatory_flags_band(wiphy->bands[band], band); |
152 | } | 152 | } |
153 | 153 | ||
154 | bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher) | ||
155 | { | ||
156 | int i; | ||
157 | for (i = 0; i < wiphy->n_cipher_suites; i++) | ||
158 | if (cipher == wiphy->cipher_suites[i]) | ||
159 | return true; | ||
160 | return false; | ||
161 | } | ||
162 | |||
154 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | 163 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, |
155 | struct key_params *params, int key_idx, | 164 | struct key_params *params, int key_idx, |
156 | bool pairwise, const u8 *mac_addr) | 165 | bool pairwise, const u8 *mac_addr) |
157 | { | 166 | { |
158 | int i; | ||
159 | |||
160 | if (key_idx > 5) | 167 | if (key_idx > 5) |
161 | return -EINVAL; | 168 | return -EINVAL; |
162 | 169 | ||
@@ -226,10 +233,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | |||
226 | } | 233 | } |
227 | } | 234 | } |
228 | 235 | ||
229 | for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) | 236 | if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher)) |
230 | if (params->cipher == rdev->wiphy.cipher_suites[i]) | ||
231 | break; | ||
232 | if (i == rdev->wiphy.n_cipher_suites) | ||
233 | return -EINVAL; | 237 | return -EINVAL; |
234 | 238 | ||
235 | return 0; | 239 | return 0; |