diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-01-01 15:39:56 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-01-01 15:39:56 -0500 |
commit | ad86c55bac643a745f480d26689d153ec0f38b04 (patch) | |
tree | 8ae3e20d2f3619021393166fe1f50a8ca00c1c33 | |
parent | 21eb218989523b7bee28900aaec9f9296b70fa27 (diff) | |
parent | 39731b78b4afebb7501c05b68e2443a1b250b41c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
123 files changed, 5206 insertions, 3982 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 9bae7901162d..0d58ff5d2a62 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1430,7 +1430,7 @@ F: Documentation/aoe/ | |||
1430 | F: drivers/block/aoe/ | 1430 | F: drivers/block/aoe/ |
1431 | 1431 | ||
1432 | ATHEROS ATH GENERIC UTILITIES | 1432 | ATHEROS ATH GENERIC UTILITIES |
1433 | M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com> | 1433 | M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> |
1434 | L: linux-wireless@vger.kernel.org | 1434 | L: linux-wireless@vger.kernel.org |
1435 | S: Supported | 1435 | S: Supported |
1436 | F: drivers/net/wireless/ath/* | 1436 | F: drivers/net/wireless/ath/* |
@@ -1438,7 +1438,7 @@ F: drivers/net/wireless/ath/* | |||
1438 | ATHEROS ATH5K WIRELESS DRIVER | 1438 | ATHEROS ATH5K WIRELESS DRIVER |
1439 | M: Jiri Slaby <jirislaby@gmail.com> | 1439 | M: Jiri Slaby <jirislaby@gmail.com> |
1440 | M: Nick Kossifidis <mickflemm@gmail.com> | 1440 | M: Nick Kossifidis <mickflemm@gmail.com> |
1441 | M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com> | 1441 | M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> |
1442 | L: linux-wireless@vger.kernel.org | 1442 | L: linux-wireless@vger.kernel.org |
1443 | L: ath5k-devel@lists.ath5k.org | 1443 | L: ath5k-devel@lists.ath5k.org |
1444 | W: http://wireless.kernel.org/en/users/Drivers/ath5k | 1444 | W: http://wireless.kernel.org/en/users/Drivers/ath5k |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index e15430a82e90..5a9f6bdc88f1 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -176,6 +176,7 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
176 | bcma_err(bus, | 176 | bcma_err(bus, |
177 | "Could not register dev for core 0x%03X\n", | 177 | "Could not register dev for core 0x%03X\n", |
178 | core->id.id); | 178 | core->id.id); |
179 | put_device(&core->dev); | ||
179 | continue; | 180 | continue; |
180 | } | 181 | } |
181 | core->dev_registered = true; | 182 | core->dev_registered = true; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 546d5da0b894..4f16d79c9eb1 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -2754,9 +2754,9 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx, | |||
2754 | mask->control[band].legacy << 4; | 2754 | mask->control[band].legacy << 4; |
2755 | 2755 | ||
2756 | /* copy mcs rate mask */ | 2756 | /* copy mcs rate mask */ |
2757 | mcsrate = mask->control[band].mcs[1]; | 2757 | mcsrate = mask->control[band].ht_mcs[1]; |
2758 | mcsrate <<= 8; | 2758 | mcsrate <<= 8; |
2759 | mcsrate |= mask->control[band].mcs[0]; | 2759 | mcsrate |= mask->control[band].ht_mcs[0]; |
2760 | ratemask[band] |= mcsrate << 12; | 2760 | ratemask[band] |= mcsrate << 12; |
2761 | ratemask[band] |= mcsrate << 28; | 2761 | ratemask[band] |= mcsrate << 28; |
2762 | } | 2762 | } |
@@ -2806,7 +2806,7 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx, | |||
2806 | mask->control[band].legacy << 4; | 2806 | mask->control[band].legacy << 4; |
2807 | 2807 | ||
2808 | /* copy mcs rate mask */ | 2808 | /* copy mcs rate mask */ |
2809 | mcsrate = mask->control[band].mcs[0]; | 2809 | mcsrate = mask->control[band].ht_mcs[0]; |
2810 | ratemask[band] |= mcsrate << 12; | 2810 | ratemask[band] |= mcsrate << 12; |
2811 | ratemask[band] |= mcsrate << 20; | 2811 | ratemask[band] |= mcsrate << 20; |
2812 | } | 2812 | } |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 337c459eda28..e9904e5ccd81 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -11,12 +11,14 @@ ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o | |||
11 | ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o | 11 | ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o |
12 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o | 12 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o |
13 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | 13 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o |
14 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | ||
15 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | 14 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o |
16 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o | 15 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o |
17 | ath9k-$(CONFIG_ATH9K_TX99) += tx99.o | 16 | ath9k-$(CONFIG_ATH9K_TX99) += tx99.o |
18 | ath9k-$(CONFIG_ATH9K_WOW) += wow.o | 17 | ath9k-$(CONFIG_ATH9K_WOW) += wow.o |
19 | 18 | ||
19 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \ | ||
20 | spectral.o | ||
21 | |||
20 | obj-$(CONFIG_ATH9K) += ath9k.o | 22 | obj-$(CONFIG_ATH9K) += ath9k.o |
21 | 23 | ||
22 | ath9k_hw-y:= \ | 24 | ath9k_hw-y:= \ |
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c index bd048cc69a33..a3668433dc02 100644 --- a/drivers/net/wireless/ath/ath9k/antenna.c +++ b/drivers/net/wireless/ath/ath9k/antenna.c | |||
@@ -724,14 +724,14 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
724 | struct ath_ant_comb *antcomb = &sc->ant_comb; | 724 | struct ath_ant_comb *antcomb = &sc->ant_comb; |
725 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | 725 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; |
726 | int curr_main_set; | 726 | int curr_main_set; |
727 | int main_rssi = rs->rs_rssi_ctl0; | 727 | int main_rssi = rs->rs_rssi_ctl[0]; |
728 | int alt_rssi = rs->rs_rssi_ctl1; | 728 | int alt_rssi = rs->rs_rssi_ctl[1]; |
729 | int rx_ant_conf, main_ant_conf; | 729 | int rx_ant_conf, main_ant_conf; |
730 | bool short_scan = false, ret; | 730 | bool short_scan = false, ret; |
731 | 731 | ||
732 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | 732 | rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) & |
733 | ATH_ANT_RX_MASK; | 733 | ATH_ANT_RX_MASK; |
734 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | 734 | main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) & |
735 | ATH_ANT_RX_MASK; | 735 | ATH_ANT_RX_MASK; |
736 | 736 | ||
737 | if (alt_rssi >= antcomb->low_rssi_thresh) { | 737 | if (alt_rssi >= antcomb->low_rssi_thresh) { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 5c95fd9e9c9e..149aba3c7298 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -32,12 +32,8 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah) | |||
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | if (ah->config.pcie_clock_req) | 35 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
36 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 36 | ar9280PciePhy_clkreq_always_on_L1_9280); |
37 | ar9280PciePhy_clkreq_off_L1_9280); | ||
38 | else | ||
39 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
40 | ar9280PciePhy_clkreq_always_on_L1_9280); | ||
41 | 37 | ||
42 | if (AR_SREV_9287_11_OR_LATER(ah)) { | 38 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
43 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1); | 39 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 8d78253c26ce..857ede3a999c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -29,7 +29,8 @@ static void ar9002_hw_set_desc_link(void *ds, u32 ds_link) | |||
29 | ((struct ath_desc*) ds)->ds_link = ds_link; | 29 | ((struct ath_desc*) ds)->ds_link = ds_link; |
30 | } | 30 | } |
31 | 31 | ||
32 | static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | 32 | static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked, |
33 | u32 *sync_cause_p) | ||
33 | { | 34 | { |
34 | u32 isr = 0; | 35 | u32 isr = 0; |
35 | u32 mask2 = 0; | 36 | u32 mask2 = 0; |
@@ -136,7 +137,8 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
136 | } | 137 | } |
137 | 138 | ||
138 | if (sync_cause) { | 139 | if (sync_cause) { |
139 | ath9k_debug_sync_cause(common, sync_cause); | 140 | if (sync_cause_p) |
141 | *sync_cause_p = sync_cause; | ||
140 | fatal_int = | 142 | fatal_int = |
141 | (sync_cause & | 143 | (sync_cause & |
142 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) | 144 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index f087117b2e6b..9a2afa2c690b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -201,7 +201,6 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, | |||
201 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 201 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
202 | freq = centers.synth_center; | 202 | freq = centers.synth_center; |
203 | 203 | ||
204 | ah->config.spurmode = SPUR_ENABLE_EEPROM; | ||
205 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 204 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
206 | cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); | 205 | cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); |
207 | 206 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ec317d6937d6..c8d22eccfef8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -131,6 +131,7 @@ static const struct ar9300_eeprom ar9300_default = { | |||
131 | .thresh62 = 28, | 131 | .thresh62 = 28, |
132 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | 132 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), |
133 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | 133 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), |
134 | .switchcomspdt = 0, | ||
134 | .xlna_bias_strength = 0, | 135 | .xlna_bias_strength = 0, |
135 | .futureModal = { | 136 | .futureModal = { |
136 | 0, 0, 0, 0, 0, 0, 0, | 137 | 0, 0, 0, 0, 0, 0, 0, |
@@ -138,7 +139,7 @@ static const struct ar9300_eeprom ar9300_default = { | |||
138 | }, | 139 | }, |
139 | .base_ext1 = { | 140 | .base_ext1 = { |
140 | .ant_div_control = 0, | 141 | .ant_div_control = 0, |
141 | .future = {0, 0, 0}, | 142 | .future = {0, 0}, |
142 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} | 143 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} |
143 | }, | 144 | }, |
144 | .calFreqPier2G = { | 145 | .calFreqPier2G = { |
@@ -333,6 +334,7 @@ static const struct ar9300_eeprom ar9300_default = { | |||
333 | .thresh62 = 28, | 334 | .thresh62 = 28, |
334 | .papdRateMaskHt20 = LE32(0x0c80c080), | 335 | .papdRateMaskHt20 = LE32(0x0c80c080), |
335 | .papdRateMaskHt40 = LE32(0x0080c080), | 336 | .papdRateMaskHt40 = LE32(0x0080c080), |
337 | .switchcomspdt = 0, | ||
336 | .xlna_bias_strength = 0, | 338 | .xlna_bias_strength = 0, |
337 | .futureModal = { | 339 | .futureModal = { |
338 | 0, 0, 0, 0, 0, 0, 0, | 340 | 0, 0, 0, 0, 0, 0, 0, |
@@ -707,6 +709,7 @@ static const struct ar9300_eeprom ar9300_x113 = { | |||
707 | .thresh62 = 28, | 709 | .thresh62 = 28, |
708 | .papdRateMaskHt20 = LE32(0x0c80c080), | 710 | .papdRateMaskHt20 = LE32(0x0c80c080), |
709 | .papdRateMaskHt40 = LE32(0x0080c080), | 711 | .papdRateMaskHt40 = LE32(0x0080c080), |
712 | .switchcomspdt = 0, | ||
710 | .xlna_bias_strength = 0, | 713 | .xlna_bias_strength = 0, |
711 | .futureModal = { | 714 | .futureModal = { |
712 | 0, 0, 0, 0, 0, 0, 0, | 715 | 0, 0, 0, 0, 0, 0, 0, |
@@ -714,7 +717,7 @@ static const struct ar9300_eeprom ar9300_x113 = { | |||
714 | }, | 717 | }, |
715 | .base_ext1 = { | 718 | .base_ext1 = { |
716 | .ant_div_control = 0, | 719 | .ant_div_control = 0, |
717 | .future = {0, 0, 0}, | 720 | .future = {0, 0}, |
718 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} | 721 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} |
719 | }, | 722 | }, |
720 | .calFreqPier2G = { | 723 | .calFreqPier2G = { |
@@ -909,6 +912,7 @@ static const struct ar9300_eeprom ar9300_x113 = { | |||
909 | .thresh62 = 28, | 912 | .thresh62 = 28, |
910 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | 913 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), |
911 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | 914 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), |
915 | .switchcomspdt = 0, | ||
912 | .xlna_bias_strength = 0, | 916 | .xlna_bias_strength = 0, |
913 | .futureModal = { | 917 | .futureModal = { |
914 | 0, 0, 0, 0, 0, 0, 0, | 918 | 0, 0, 0, 0, 0, 0, 0, |
@@ -1284,6 +1288,7 @@ static const struct ar9300_eeprom ar9300_h112 = { | |||
1284 | .thresh62 = 28, | 1288 | .thresh62 = 28, |
1285 | .papdRateMaskHt20 = LE32(0x0c80c080), | 1289 | .papdRateMaskHt20 = LE32(0x0c80c080), |
1286 | .papdRateMaskHt40 = LE32(0x0080c080), | 1290 | .papdRateMaskHt40 = LE32(0x0080c080), |
1291 | .switchcomspdt = 0, | ||
1287 | .xlna_bias_strength = 0, | 1292 | .xlna_bias_strength = 0, |
1288 | .futureModal = { | 1293 | .futureModal = { |
1289 | 0, 0, 0, 0, 0, 0, 0, | 1294 | 0, 0, 0, 0, 0, 0, 0, |
@@ -1291,7 +1296,7 @@ static const struct ar9300_eeprom ar9300_h112 = { | |||
1291 | }, | 1296 | }, |
1292 | .base_ext1 = { | 1297 | .base_ext1 = { |
1293 | .ant_div_control = 0, | 1298 | .ant_div_control = 0, |
1294 | .future = {0, 0, 0}, | 1299 | .future = {0, 0}, |
1295 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} | 1300 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} |
1296 | }, | 1301 | }, |
1297 | .calFreqPier2G = { | 1302 | .calFreqPier2G = { |
@@ -1486,6 +1491,7 @@ static const struct ar9300_eeprom ar9300_h112 = { | |||
1486 | .thresh62 = 28, | 1491 | .thresh62 = 28, |
1487 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | 1492 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), |
1488 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | 1493 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), |
1494 | .switchcomspdt = 0, | ||
1489 | .xlna_bias_strength = 0, | 1495 | .xlna_bias_strength = 0, |
1490 | .futureModal = { | 1496 | .futureModal = { |
1491 | 0, 0, 0, 0, 0, 0, 0, | 1497 | 0, 0, 0, 0, 0, 0, 0, |
@@ -1861,6 +1867,7 @@ static const struct ar9300_eeprom ar9300_x112 = { | |||
1861 | .thresh62 = 28, | 1867 | .thresh62 = 28, |
1862 | .papdRateMaskHt20 = LE32(0x0c80c080), | 1868 | .papdRateMaskHt20 = LE32(0x0c80c080), |
1863 | .papdRateMaskHt40 = LE32(0x0080c080), | 1869 | .papdRateMaskHt40 = LE32(0x0080c080), |
1870 | .switchcomspdt = 0, | ||
1864 | .xlna_bias_strength = 0, | 1871 | .xlna_bias_strength = 0, |
1865 | .futureModal = { | 1872 | .futureModal = { |
1866 | 0, 0, 0, 0, 0, 0, 0, | 1873 | 0, 0, 0, 0, 0, 0, 0, |
@@ -1868,7 +1875,7 @@ static const struct ar9300_eeprom ar9300_x112 = { | |||
1868 | }, | 1875 | }, |
1869 | .base_ext1 = { | 1876 | .base_ext1 = { |
1870 | .ant_div_control = 0, | 1877 | .ant_div_control = 0, |
1871 | .future = {0, 0, 0}, | 1878 | .future = {0, 0}, |
1872 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} | 1879 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} |
1873 | }, | 1880 | }, |
1874 | .calFreqPier2G = { | 1881 | .calFreqPier2G = { |
@@ -2063,6 +2070,7 @@ static const struct ar9300_eeprom ar9300_x112 = { | |||
2063 | .thresh62 = 28, | 2070 | .thresh62 = 28, |
2064 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | 2071 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), |
2065 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | 2072 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), |
2073 | .switchcomspdt = 0, | ||
2066 | .xlna_bias_strength = 0, | 2074 | .xlna_bias_strength = 0, |
2067 | .futureModal = { | 2075 | .futureModal = { |
2068 | 0, 0, 0, 0, 0, 0, 0, | 2076 | 0, 0, 0, 0, 0, 0, 0, |
@@ -2437,6 +2445,7 @@ static const struct ar9300_eeprom ar9300_h116 = { | |||
2437 | .thresh62 = 28, | 2445 | .thresh62 = 28, |
2438 | .papdRateMaskHt20 = LE32(0x0c80C080), | 2446 | .papdRateMaskHt20 = LE32(0x0c80C080), |
2439 | .papdRateMaskHt40 = LE32(0x0080C080), | 2447 | .papdRateMaskHt40 = LE32(0x0080C080), |
2448 | .switchcomspdt = 0, | ||
2440 | .xlna_bias_strength = 0, | 2449 | .xlna_bias_strength = 0, |
2441 | .futureModal = { | 2450 | .futureModal = { |
2442 | 0, 0, 0, 0, 0, 0, 0, | 2451 | 0, 0, 0, 0, 0, 0, 0, |
@@ -2444,7 +2453,7 @@ static const struct ar9300_eeprom ar9300_h116 = { | |||
2444 | }, | 2453 | }, |
2445 | .base_ext1 = { | 2454 | .base_ext1 = { |
2446 | .ant_div_control = 0, | 2455 | .ant_div_control = 0, |
2447 | .future = {0, 0, 0}, | 2456 | .future = {0, 0}, |
2448 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} | 2457 | .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0} |
2449 | }, | 2458 | }, |
2450 | .calFreqPier2G = { | 2459 | .calFreqPier2G = { |
@@ -2639,6 +2648,7 @@ static const struct ar9300_eeprom ar9300_h116 = { | |||
2639 | .thresh62 = 28, | 2648 | .thresh62 = 28, |
2640 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | 2649 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), |
2641 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | 2650 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), |
2651 | .switchcomspdt = 0, | ||
2642 | .xlna_bias_strength = 0, | 2652 | .xlna_bias_strength = 0, |
2643 | .futureModal = { | 2653 | .futureModal = { |
2644 | 0, 0, 0, 0, 0, 0, 0, | 2654 | 0, 0, 0, 0, 0, 0, 0, |
@@ -4111,6 +4121,37 @@ static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah) | |||
4111 | } | 4121 | } |
4112 | } | 4122 | } |
4113 | 4123 | ||
4124 | static void ar9003_hw_apply_minccapwr_thresh(struct ath_hw *ah, | ||
4125 | bool is2ghz) | ||
4126 | { | ||
4127 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
4128 | const u_int32_t cca_ctrl[AR9300_MAX_CHAINS] = { | ||
4129 | AR_PHY_CCA_CTRL_0, | ||
4130 | AR_PHY_CCA_CTRL_1, | ||
4131 | AR_PHY_CCA_CTRL_2, | ||
4132 | }; | ||
4133 | int chain; | ||
4134 | u32 val; | ||
4135 | |||
4136 | if (is2ghz) { | ||
4137 | if (!(eep->base_ext1.misc_enable & BIT(2))) | ||
4138 | return; | ||
4139 | } else { | ||
4140 | if (!(eep->base_ext1.misc_enable & BIT(3))) | ||
4141 | return; | ||
4142 | } | ||
4143 | |||
4144 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
4145 | if (!(ah->caps.tx_chainmask & BIT(chain))) | ||
4146 | continue; | ||
4147 | |||
4148 | val = ar9003_modal_header(ah, is2ghz)->noiseFloorThreshCh[chain]; | ||
4149 | REG_RMW_FIELD(ah, cca_ctrl[chain], | ||
4150 | AR_PHY_EXT_CCA0_THRESH62_1, val); | ||
4151 | } | ||
4152 | |||
4153 | } | ||
4154 | |||
4114 | static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, | 4155 | static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, |
4115 | struct ath9k_channel *chan) | 4156 | struct ath9k_channel *chan) |
4116 | { | 4157 | { |
@@ -4125,6 +4166,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, | |||
4125 | if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah)) | 4166 | if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah)) |
4126 | ar9003_hw_internal_regulator_apply(ah); | 4167 | ar9003_hw_internal_regulator_apply(ah); |
4127 | ar9003_hw_apply_tuning_caps(ah); | 4168 | ar9003_hw_apply_tuning_caps(ah); |
4169 | ar9003_hw_apply_minccapwr_thresh(ah, chan); | ||
4128 | ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz); | 4170 | ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz); |
4129 | ar9003_hw_thermometer_apply(ah); | 4171 | ar9003_hw_thermometer_apply(ah); |
4130 | ar9003_hw_thermo_cal_apply(ah); | 4172 | ar9003_hw_thermo_cal_apply(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 0e5daa58a4fc..694ca2e680e5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -270,10 +270,20 @@ struct cal_ctl_data_5g { | |||
270 | u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G]; | 270 | u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G]; |
271 | } __packed; | 271 | } __packed; |
272 | 272 | ||
273 | #define MAX_BASE_EXTENSION_FUTURE 2 | ||
274 | |||
273 | struct ar9300_BaseExtension_1 { | 275 | struct ar9300_BaseExtension_1 { |
274 | u8 ant_div_control; | 276 | u8 ant_div_control; |
275 | u8 future[3]; | 277 | u8 future[MAX_BASE_EXTENSION_FUTURE]; |
276 | u8 tempslopextension[8]; | 278 | /* |
279 | * misc_enable: | ||
280 | * | ||
281 | * BIT 0 - TX Gain Cap enable. | ||
282 | * BIT 1 - Uncompressed Checksum enable. | ||
283 | * BIT 2/3 - MinCCApwr enable 2g/5g. | ||
284 | */ | ||
285 | u8 misc_enable; | ||
286 | int8_t tempslopextension[8]; | ||
277 | int8_t quick_drop_low; | 287 | int8_t quick_drop_low; |
278 | int8_t quick_drop_high; | 288 | int8_t quick_drop_high; |
279 | } __packed; | 289 | } __packed; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index f6c5c1b50471..729ffbf07343 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -175,7 +175,8 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link) | |||
175 | ads->ctl10 |= ar9003_calc_ptr_chksum(ads); | 175 | ads->ctl10 |= ar9003_calc_ptr_chksum(ads); |
176 | } | 176 | } |
177 | 177 | ||
178 | static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | 178 | static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked, |
179 | u32 *sync_cause_p) | ||
179 | { | 180 | { |
180 | u32 isr = 0; | 181 | u32 isr = 0; |
181 | u32 mask2 = 0; | 182 | u32 mask2 = 0; |
@@ -310,7 +311,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
310 | ar9003_mci_get_isr(ah, masked); | 311 | ar9003_mci_get_isr(ah, masked); |
311 | 312 | ||
312 | if (sync_cause) { | 313 | if (sync_cause) { |
313 | ath9k_debug_sync_cause(common, sync_cause); | 314 | if (sync_cause_p) |
315 | *sync_cause_p = sync_cause; | ||
314 | fatal_int = | 316 | fatal_int = |
315 | (sync_cause & | 317 | (sync_cause & |
316 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) | 318 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) |
@@ -476,12 +478,12 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
476 | 478 | ||
477 | /* XXX: Keycache */ | 479 | /* XXX: Keycache */ |
478 | rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); | 480 | rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); |
479 | rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00); | 481 | rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00); |
480 | rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01); | 482 | rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01); |
481 | rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02); | 483 | rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02); |
482 | rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10); | 484 | rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10); |
483 | rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11); | 485 | rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11); |
484 | rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12); | 486 | rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12); |
485 | 487 | ||
486 | if (rxsp->status11 & AR_RxKeyIdxValid) | 488 | if (rxsp->status11 & AR_RxKeyIdxValid) |
487 | rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); | 489 | rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index bbbfc4dc59eb..1b441715ba39 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -270,7 +270,7 @@ | |||
270 | #define AR_PHY_AGC (AR_AGC_BASE + 0x14) | 270 | #define AR_PHY_AGC (AR_AGC_BASE + 0x14) |
271 | #define AR_PHY_EXT_ATTEN_CTL_0 (AR_AGC_BASE + 0x18) | 271 | #define AR_PHY_EXT_ATTEN_CTL_0 (AR_AGC_BASE + 0x18) |
272 | #define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c) | 272 | #define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c) |
273 | #define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) | 273 | #define AR_PHY_CCA_CTRL_0 (AR_AGC_BASE + 0x20) |
274 | #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) | 274 | #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) |
275 | 275 | ||
276 | /* | 276 | /* |
@@ -398,6 +398,8 @@ | |||
398 | #define AR9280_PHY_CCA_THRESH62_S 12 | 398 | #define AR9280_PHY_CCA_THRESH62_S 12 |
399 | #define AR_PHY_EXT_CCA0_THRESH62 0x000000FF | 399 | #define AR_PHY_EXT_CCA0_THRESH62 0x000000FF |
400 | #define AR_PHY_EXT_CCA0_THRESH62_S 0 | 400 | #define AR_PHY_EXT_CCA0_THRESH62_S 0 |
401 | #define AR_PHY_EXT_CCA0_THRESH62_1 0x000001FF | ||
402 | #define AR_PHY_EXT_CCA0_THRESH62_1_S 0 | ||
401 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F | 403 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F |
402 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 | 404 | #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 |
403 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 | 405 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 5e5d5cb2458c..f2202e78fa7b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -27,40 +27,15 @@ | |||
27 | #include "common.h" | 27 | #include "common.h" |
28 | #include "mci.h" | 28 | #include "mci.h" |
29 | #include "dfs.h" | 29 | #include "dfs.h" |
30 | 30 | #include "spectral.h" | |
31 | /* | ||
32 | * Header for the ath9k.ko driver core *only* -- hw code nor any other driver | ||
33 | * should rely on this file or its contents. | ||
34 | */ | ||
35 | 31 | ||
36 | struct ath_node; | 32 | struct ath_node; |
33 | struct ath_rate_table; | ||
37 | 34 | ||
38 | /* Macro to expand scalars to 64-bit objects */ | 35 | extern struct ieee80211_ops ath9k_ops; |
39 | 36 | extern int ath9k_modparam_nohwcrypt; | |
40 | #define ito64(x) (sizeof(x) == 1) ? \ | 37 | extern int led_blink; |
41 | (((unsigned long long int)(x)) & (0xff)) : \ | 38 | extern bool is_ath9k_unloaded; |
42 | (sizeof(x) == 2) ? \ | ||
43 | (((unsigned long long int)(x)) & 0xffff) : \ | ||
44 | ((sizeof(x) == 4) ? \ | ||
45 | (((unsigned long long int)(x)) & 0xffffffff) : \ | ||
46 | (unsigned long long int)(x)) | ||
47 | |||
48 | /* increment with wrap-around */ | ||
49 | #define INCR(_l, _sz) do { \ | ||
50 | (_l)++; \ | ||
51 | (_l) &= ((_sz) - 1); \ | ||
52 | } while (0) | ||
53 | |||
54 | /* decrement with wrap-around */ | ||
55 | #define DECR(_l, _sz) do { \ | ||
56 | (_l)--; \ | ||
57 | (_l) &= ((_sz) - 1); \ | ||
58 | } while (0) | ||
59 | |||
60 | #define TSF_TO_TU(_h,_l) \ | ||
61 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
62 | |||
63 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) | ||
64 | 39 | ||
65 | struct ath_config { | 40 | struct ath_config { |
66 | u16 txpowlimit; | 41 | u16 txpowlimit; |
@@ -70,6 +45,17 @@ struct ath_config { | |||
70 | /* Descriptor Management */ | 45 | /* Descriptor Management */ |
71 | /*************************/ | 46 | /*************************/ |
72 | 47 | ||
48 | #define ATH_TXSTATUS_RING_SIZE 512 | ||
49 | |||
50 | /* Macro to expand scalars to 64-bit objects */ | ||
51 | #define ito64(x) (sizeof(x) == 1) ? \ | ||
52 | (((unsigned long long int)(x)) & (0xff)) : \ | ||
53 | (sizeof(x) == 2) ? \ | ||
54 | (((unsigned long long int)(x)) & 0xffff) : \ | ||
55 | ((sizeof(x) == 4) ? \ | ||
56 | (((unsigned long long int)(x)) & 0xffffffff) : \ | ||
57 | (unsigned long long int)(x)) | ||
58 | |||
73 | #define ATH_TXBUF_RESET(_bf) do { \ | 59 | #define ATH_TXBUF_RESET(_bf) do { \ |
74 | (_bf)->bf_lastbf = NULL; \ | 60 | (_bf)->bf_lastbf = NULL; \ |
75 | (_bf)->bf_next = NULL; \ | 61 | (_bf)->bf_next = NULL; \ |
@@ -77,23 +63,6 @@ struct ath_config { | |||
77 | sizeof(struct ath_buf_state)); \ | 63 | sizeof(struct ath_buf_state)); \ |
78 | } while (0) | 64 | } while (0) |
79 | 65 | ||
80 | /** | ||
81 | * enum buffer_type - Buffer type flags | ||
82 | * | ||
83 | * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) | ||
84 | * @BUF_AGGR: Indicates whether the buffer can be aggregated | ||
85 | * (used in aggregation scheduling) | ||
86 | */ | ||
87 | enum buffer_type { | ||
88 | BUF_AMPDU = BIT(0), | ||
89 | BUF_AGGR = BIT(1), | ||
90 | }; | ||
91 | |||
92 | #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) | ||
93 | #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) | ||
94 | |||
95 | #define ATH_TXSTATUS_RING_SIZE 512 | ||
96 | |||
97 | #define DS2PHYS(_dd, _ds) \ | 66 | #define DS2PHYS(_dd, _ds) \ |
98 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | 67 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) |
99 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | 68 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) |
@@ -113,11 +82,20 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
113 | /* RX / TX */ | 82 | /* RX / TX */ |
114 | /***********/ | 83 | /***********/ |
115 | 84 | ||
85 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) | ||
86 | |||
87 | /* increment with wrap-around */ | ||
88 | #define INCR(_l, _sz) do { \ | ||
89 | (_l)++; \ | ||
90 | (_l) &= ((_sz) - 1); \ | ||
91 | } while (0) | ||
92 | |||
116 | #define ATH_RXBUF 512 | 93 | #define ATH_RXBUF 512 |
117 | #define ATH_TXBUF 512 | 94 | #define ATH_TXBUF 512 |
118 | #define ATH_TXBUF_RESERVE 5 | 95 | #define ATH_TXBUF_RESERVE 5 |
119 | #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) | 96 | #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) |
120 | #define ATH_TXMAXTRY 13 | 97 | #define ATH_TXMAXTRY 13 |
98 | #define ATH_MAX_SW_RETRIES 30 | ||
121 | 99 | ||
122 | #define TID_TO_WME_AC(_tid) \ | 100 | #define TID_TO_WME_AC(_tid) \ |
123 | ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \ | 101 | ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \ |
@@ -133,6 +111,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
133 | #define ATH_AGGR_MIN_QDEPTH 2 | 111 | #define ATH_AGGR_MIN_QDEPTH 2 |
134 | /* minimum h/w qdepth for non-aggregated traffic */ | 112 | /* minimum h/w qdepth for non-aggregated traffic */ |
135 | #define ATH_NON_AGGR_MIN_QDEPTH 8 | 113 | #define ATH_NON_AGGR_MIN_QDEPTH 8 |
114 | #define ATH_TX_COMPLETE_POLL_INT 1000 | ||
115 | #define ATH_TXFIFO_DEPTH 8 | ||
116 | #define ATH_TX_ERROR 0x01 | ||
136 | 117 | ||
137 | #define IEEE80211_SEQ_SEQ_SHIFT 4 | 118 | #define IEEE80211_SEQ_SEQ_SHIFT 4 |
138 | #define IEEE80211_SEQ_MAX 4096 | 119 | #define IEEE80211_SEQ_MAX 4096 |
@@ -167,9 +148,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
167 | 148 | ||
168 | #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) | 149 | #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) |
169 | 150 | ||
170 | #define ATH_TX_COMPLETE_POLL_INT 1000 | ||
171 | |||
172 | #define ATH_TXFIFO_DEPTH 8 | ||
173 | struct ath_txq { | 151 | struct ath_txq { |
174 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ | 152 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ |
175 | u32 axq_qnum; /* ath9k hardware queue number */ | 153 | u32 axq_qnum; /* ath9k hardware queue number */ |
@@ -214,6 +192,21 @@ struct ath_rxbuf { | |||
214 | dma_addr_t bf_buf_addr; | 192 | dma_addr_t bf_buf_addr; |
215 | }; | 193 | }; |
216 | 194 | ||
195 | /** | ||
196 | * enum buffer_type - Buffer type flags | ||
197 | * | ||
198 | * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) | ||
199 | * @BUF_AGGR: Indicates whether the buffer can be aggregated | ||
200 | * (used in aggregation scheduling) | ||
201 | */ | ||
202 | enum buffer_type { | ||
203 | BUF_AMPDU = BIT(0), | ||
204 | BUF_AGGR = BIT(1), | ||
205 | }; | ||
206 | |||
207 | #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) | ||
208 | #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) | ||
209 | |||
217 | struct ath_buf_state { | 210 | struct ath_buf_state { |
218 | u8 bf_type; | 211 | u8 bf_type; |
219 | u8 bfs_paprd; | 212 | u8 bfs_paprd; |
@@ -278,7 +271,6 @@ struct ath_tx_control { | |||
278 | struct ieee80211_sta *sta; | 271 | struct ieee80211_sta *sta; |
279 | }; | 272 | }; |
280 | 273 | ||
281 | #define ATH_TX_ERROR 0x01 | ||
282 | 274 | ||
283 | /** | 275 | /** |
284 | * @txq_map: Index is mac80211 queue number. This is | 276 | * @txq_map: Index is mac80211 queue number. This is |
@@ -372,6 +364,22 @@ struct ath_vif { | |||
372 | struct ath_buf *av_bcbuf; | 364 | struct ath_buf *av_bcbuf; |
373 | }; | 365 | }; |
374 | 366 | ||
367 | struct ath9k_vif_iter_data { | ||
368 | u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */ | ||
369 | u8 mask[ETH_ALEN]; /* bssid mask */ | ||
370 | bool has_hw_macaddr; | ||
371 | |||
372 | int naps; /* number of AP vifs */ | ||
373 | int nmeshes; /* number of mesh vifs */ | ||
374 | int nstations; /* number of station vifs */ | ||
375 | int nwds; /* number of WDS vifs */ | ||
376 | int nadhocs; /* number of adhoc vifs */ | ||
377 | }; | ||
378 | |||
379 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | ||
380 | struct ieee80211_vif *vif, | ||
381 | struct ath9k_vif_iter_data *iter_data); | ||
382 | |||
375 | /*******************/ | 383 | /*******************/ |
376 | /* Beacon Handling */ | 384 | /* Beacon Handling */ |
377 | /*******************/ | 385 | /*******************/ |
@@ -387,6 +395,9 @@ struct ath_vif { | |||
387 | #define ATH_DEFAULT_BMISS_LIMIT 10 | 395 | #define ATH_DEFAULT_BMISS_LIMIT 10 |
388 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | 396 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) |
389 | 397 | ||
398 | #define TSF_TO_TU(_h,_l) \ | ||
399 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
400 | |||
390 | struct ath_beacon_config { | 401 | struct ath_beacon_config { |
391 | int beacon_interval; | 402 | int beacon_interval; |
392 | u16 listen_interval; | 403 | u16 listen_interval; |
@@ -420,12 +431,10 @@ struct ath_beacon { | |||
420 | }; | 431 | }; |
421 | 432 | ||
422 | void ath9k_beacon_tasklet(unsigned long data); | 433 | void ath9k_beacon_tasklet(unsigned long data); |
423 | bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); | ||
424 | void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, | 434 | void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, |
425 | u32 changed); | 435 | u32 changed); |
426 | void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif); | 436 | void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif); |
427 | void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); | 437 | void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); |
428 | void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif); | ||
429 | void ath9k_set_beacon(struct ath_softc *sc); | 438 | void ath9k_set_beacon(struct ath_softc *sc); |
430 | bool ath9k_csa_is_finished(struct ath_softc *sc); | 439 | bool ath9k_csa_is_finished(struct ath_softc *sc); |
431 | 440 | ||
@@ -440,10 +449,9 @@ bool ath9k_csa_is_finished(struct ath_softc *sc); | |||
440 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ | 449 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ |
441 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 450 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
442 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 451 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
443 | #define ATH_ANI_MAX_SKIP_COUNT 10 | 452 | #define ATH_ANI_MAX_SKIP_COUNT 10 |
444 | 453 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ | |
445 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ | 454 | #define ATH_PLL_WORK_INTERVAL 100 |
446 | #define ATH_PLL_WORK_INTERVAL 100 | ||
447 | 455 | ||
448 | void ath_tx_complete_poll_work(struct work_struct *work); | 456 | void ath_tx_complete_poll_work(struct work_struct *work); |
449 | void ath_reset_work(struct work_struct *work); | 457 | void ath_reset_work(struct work_struct *work); |
@@ -477,20 +485,19 @@ enum bt_op_flags { | |||
477 | }; | 485 | }; |
478 | 486 | ||
479 | struct ath_btcoex { | 487 | struct ath_btcoex { |
480 | bool hw_timer_enabled; | ||
481 | spinlock_t btcoex_lock; | 488 | spinlock_t btcoex_lock; |
482 | struct timer_list period_timer; /* Timer for BT period */ | 489 | struct timer_list period_timer; /* Timer for BT period */ |
490 | struct timer_list no_stomp_timer; | ||
483 | u32 bt_priority_cnt; | 491 | u32 bt_priority_cnt; |
484 | unsigned long bt_priority_time; | 492 | unsigned long bt_priority_time; |
485 | unsigned long op_flags; | 493 | unsigned long op_flags; |
486 | int bt_stomp_type; /* Types of BT stomping */ | 494 | int bt_stomp_type; /* Types of BT stomping */ |
487 | u32 btcoex_no_stomp; /* in usec */ | 495 | u32 btcoex_no_stomp; /* in msec */ |
488 | u32 btcoex_period; /* in msec */ | 496 | u32 btcoex_period; /* in msec */ |
489 | u32 btscan_no_stomp; /* in usec */ | 497 | u32 btscan_no_stomp; /* in msec */ |
490 | u32 duty_cycle; | 498 | u32 duty_cycle; |
491 | u32 bt_wait_time; | 499 | u32 bt_wait_time; |
492 | int rssi_count; | 500 | int rssi_count; |
493 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ | ||
494 | struct ath_mci_profile mci; | 501 | struct ath_mci_profile mci; |
495 | u8 stomp_audio; | 502 | u8 stomp_audio; |
496 | }; | 503 | }; |
@@ -538,12 +545,6 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size) | |||
538 | } | 545 | } |
539 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 546 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
540 | 547 | ||
541 | struct ath9k_wow_pattern { | ||
542 | u8 pattern_bytes[MAX_PATTERN_SIZE]; | ||
543 | u8 mask_bytes[MAX_PATTERN_SIZE]; | ||
544 | u32 pattern_len; | ||
545 | }; | ||
546 | |||
547 | /********************/ | 548 | /********************/ |
548 | /* LED Control */ | 549 | /* LED Control */ |
549 | /********************/ | 550 | /********************/ |
@@ -575,6 +576,12 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) | |||
575 | /* Wake on Wireless LAN */ | 576 | /* Wake on Wireless LAN */ |
576 | /************************/ | 577 | /************************/ |
577 | 578 | ||
579 | struct ath9k_wow_pattern { | ||
580 | u8 pattern_bytes[MAX_PATTERN_SIZE]; | ||
581 | u8 mask_bytes[MAX_PATTERN_SIZE]; | ||
582 | u32 pattern_len; | ||
583 | }; | ||
584 | |||
578 | #ifdef CONFIG_ATH9K_WOW | 585 | #ifdef CONFIG_ATH9K_WOW |
579 | void ath9k_init_wow(struct ieee80211_hw *hw); | 586 | void ath9k_init_wow(struct ieee80211_hw *hw); |
580 | int ath9k_suspend(struct ieee80211_hw *hw, | 587 | int ath9k_suspend(struct ieee80211_hw *hw, |
@@ -678,13 +685,8 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | |||
678 | * Used when PCI device not fully initialized by bootrom/BIOS | 685 | * Used when PCI device not fully initialized by bootrom/BIOS |
679 | */ | 686 | */ |
680 | #define DEFAULT_CACHELINE 32 | 687 | #define DEFAULT_CACHELINE 32 |
681 | #define ATH_REGCLASSIDS_MAX 10 | ||
682 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 688 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
683 | #define ATH_MAX_SW_RETRIES 30 | ||
684 | #define ATH_CHAN_MAX 255 | ||
685 | |||
686 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 689 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
687 | #define ATH_RATE_DUMMY_MARKER 0 | ||
688 | 690 | ||
689 | enum sc_op_flags { | 691 | enum sc_op_flags { |
690 | SC_OP_INVALID, | 692 | SC_OP_INVALID, |
@@ -703,37 +705,6 @@ enum sc_op_flags { | |||
703 | #define PS_BEACON_SYNC BIT(4) | 705 | #define PS_BEACON_SYNC BIT(4) |
704 | #define PS_WAIT_FOR_ANI BIT(5) | 706 | #define PS_WAIT_FOR_ANI BIT(5) |
705 | 707 | ||
706 | struct ath_rate_table; | ||
707 | |||
708 | struct ath9k_vif_iter_data { | ||
709 | u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */ | ||
710 | u8 mask[ETH_ALEN]; /* bssid mask */ | ||
711 | bool has_hw_macaddr; | ||
712 | |||
713 | int naps; /* number of AP vifs */ | ||
714 | int nmeshes; /* number of mesh vifs */ | ||
715 | int nstations; /* number of station vifs */ | ||
716 | int nwds; /* number of WDS vifs */ | ||
717 | int nadhocs; /* number of adhoc vifs */ | ||
718 | }; | ||
719 | |||
720 | /* enum spectral_mode: | ||
721 | * | ||
722 | * @SPECTRAL_DISABLED: spectral mode is disabled | ||
723 | * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with | ||
724 | * something else. | ||
725 | * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples | ||
726 | * is performed manually. | ||
727 | * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels | ||
728 | * during a channel scan. | ||
729 | */ | ||
730 | enum spectral_mode { | ||
731 | SPECTRAL_DISABLED = 0, | ||
732 | SPECTRAL_BACKGROUND, | ||
733 | SPECTRAL_MANUAL, | ||
734 | SPECTRAL_CHANSCAN, | ||
735 | }; | ||
736 | |||
737 | struct ath_softc { | 708 | struct ath_softc { |
738 | struct ieee80211_hw *hw; | 709 | struct ieee80211_hw *hw; |
739 | struct device *dev; | 710 | struct device *dev; |
@@ -823,162 +794,6 @@ struct ath_softc { | |||
823 | #endif | 794 | #endif |
824 | }; | 795 | }; |
825 | 796 | ||
826 | #define SPECTRAL_SCAN_BITMASK 0x10 | ||
827 | /* Radar info packet format, used for DFS and spectral formats. */ | ||
828 | struct ath_radar_info { | ||
829 | u8 pulse_length_pri; | ||
830 | u8 pulse_length_ext; | ||
831 | u8 pulse_bw_info; | ||
832 | } __packed; | ||
833 | |||
834 | /* The HT20 spectral data has 4 bytes of additional information at it's end. | ||
835 | * | ||
836 | * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
837 | * [7:0]: all bins max_magnitude[9:2] | ||
838 | * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]} | ||
839 | * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) | ||
840 | */ | ||
841 | struct ath_ht20_mag_info { | ||
842 | u8 all_bins[3]; | ||
843 | u8 max_exp; | ||
844 | } __packed; | ||
845 | |||
846 | #define SPECTRAL_HT20_NUM_BINS 56 | ||
847 | |||
848 | /* WARNING: don't actually use this struct! MAC may vary the amount of | ||
849 | * data by -1/+2. This struct is for reference only. | ||
850 | */ | ||
851 | struct ath_ht20_fft_packet { | ||
852 | u8 data[SPECTRAL_HT20_NUM_BINS]; | ||
853 | struct ath_ht20_mag_info mag_info; | ||
854 | struct ath_radar_info radar_info; | ||
855 | } __packed; | ||
856 | |||
857 | #define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet)) | ||
858 | |||
859 | /* Dynamic 20/40 mode: | ||
860 | * | ||
861 | * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
862 | * [7:0]: lower bins max_magnitude[9:2] | ||
863 | * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} | ||
864 | * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
865 | * [7:0]: upper bins max_magnitude[9:2] | ||
866 | * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} | ||
867 | * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) | ||
868 | */ | ||
869 | struct ath_ht20_40_mag_info { | ||
870 | u8 lower_bins[3]; | ||
871 | u8 upper_bins[3]; | ||
872 | u8 max_exp; | ||
873 | } __packed; | ||
874 | |||
875 | #define SPECTRAL_HT20_40_NUM_BINS 128 | ||
876 | |||
877 | /* WARNING: don't actually use this struct! MAC may vary the amount of | ||
878 | * data. This struct is for reference only. | ||
879 | */ | ||
880 | struct ath_ht20_40_fft_packet { | ||
881 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | ||
882 | struct ath_ht20_40_mag_info mag_info; | ||
883 | struct ath_radar_info radar_info; | ||
884 | } __packed; | ||
885 | |||
886 | |||
887 | #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) | ||
888 | |||
889 | /* grabs the max magnitude from the all/upper/lower bins */ | ||
890 | static inline u16 spectral_max_magnitude(u8 *bins) | ||
891 | { | ||
892 | return (bins[0] & 0xc0) >> 6 | | ||
893 | (bins[1] & 0xff) << 2 | | ||
894 | (bins[2] & 0x03) << 10; | ||
895 | } | ||
896 | |||
897 | /* return the max magnitude from the all/upper/lower bins */ | ||
898 | static inline u8 spectral_max_index(u8 *bins) | ||
899 | { | ||
900 | s8 m = (bins[2] & 0xfc) >> 2; | ||
901 | |||
902 | /* TODO: this still doesn't always report the right values ... */ | ||
903 | if (m > 32) | ||
904 | m |= 0xe0; | ||
905 | else | ||
906 | m &= ~0xe0; | ||
907 | |||
908 | return m + 29; | ||
909 | } | ||
910 | |||
911 | /* return the bitmap weight from the all/upper/lower bins */ | ||
912 | static inline u8 spectral_bitmap_weight(u8 *bins) | ||
913 | { | ||
914 | return bins[0] & 0x3f; | ||
915 | } | ||
916 | |||
917 | /* FFT sample format given to userspace via debugfs. | ||
918 | * | ||
919 | * Please keep the type/length at the front position and change | ||
920 | * other fields after adding another sample type | ||
921 | * | ||
922 | * TODO: this might need rework when switching to nl80211-based | ||
923 | * interface. | ||
924 | */ | ||
925 | enum ath_fft_sample_type { | ||
926 | ATH_FFT_SAMPLE_HT20 = 1, | ||
927 | ATH_FFT_SAMPLE_HT20_40, | ||
928 | }; | ||
929 | |||
930 | struct fft_sample_tlv { | ||
931 | u8 type; /* see ath_fft_sample */ | ||
932 | __be16 length; | ||
933 | /* type dependent data follows */ | ||
934 | } __packed; | ||
935 | |||
936 | struct fft_sample_ht20 { | ||
937 | struct fft_sample_tlv tlv; | ||
938 | |||
939 | u8 max_exp; | ||
940 | |||
941 | __be16 freq; | ||
942 | s8 rssi; | ||
943 | s8 noise; | ||
944 | |||
945 | __be16 max_magnitude; | ||
946 | u8 max_index; | ||
947 | u8 bitmap_weight; | ||
948 | |||
949 | __be64 tsf; | ||
950 | |||
951 | u8 data[SPECTRAL_HT20_NUM_BINS]; | ||
952 | } __packed; | ||
953 | |||
954 | struct fft_sample_ht20_40 { | ||
955 | struct fft_sample_tlv tlv; | ||
956 | |||
957 | u8 channel_type; | ||
958 | __be16 freq; | ||
959 | |||
960 | s8 lower_rssi; | ||
961 | s8 upper_rssi; | ||
962 | |||
963 | __be64 tsf; | ||
964 | |||
965 | s8 lower_noise; | ||
966 | s8 upper_noise; | ||
967 | |||
968 | __be16 lower_max_magnitude; | ||
969 | __be16 upper_max_magnitude; | ||
970 | |||
971 | u8 lower_max_index; | ||
972 | u8 upper_max_index; | ||
973 | |||
974 | u8 lower_bitmap_weight; | ||
975 | u8 upper_bitmap_weight; | ||
976 | |||
977 | u8 max_exp; | ||
978 | |||
979 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | ||
980 | } __packed; | ||
981 | |||
982 | /********/ | 797 | /********/ |
983 | /* TX99 */ | 798 | /* TX99 */ |
984 | /********/ | 799 | /********/ |
@@ -999,19 +814,13 @@ static inline int ath9k_tx99_send(struct ath_softc *sc, | |||
999 | } | 814 | } |
1000 | #endif /* CONFIG_ATH9K_TX99 */ | 815 | #endif /* CONFIG_ATH9K_TX99 */ |
1001 | 816 | ||
1002 | void ath9k_tasklet(unsigned long data); | ||
1003 | int ath_cabq_update(struct ath_softc *); | ||
1004 | |||
1005 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) | 817 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) |
1006 | { | 818 | { |
1007 | common->bus_ops->read_cachesize(common, csz); | 819 | common->bus_ops->read_cachesize(common, csz); |
1008 | } | 820 | } |
1009 | 821 | ||
1010 | extern struct ieee80211_ops ath9k_ops; | 822 | void ath9k_tasklet(unsigned long data); |
1011 | extern int ath9k_modparam_nohwcrypt; | 823 | int ath_cabq_update(struct ath_softc *); |
1012 | extern int led_blink; | ||
1013 | extern bool is_ath9k_unloaded; | ||
1014 | |||
1015 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); | 824 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); |
1016 | irqreturn_t ath_isr(int irq, void *dev); | 825 | irqreturn_t ath_isr(int irq, void *dev); |
1017 | int ath_reset(struct ath_softc *sc); | 826 | int ath_reset(struct ath_softc *sc); |
@@ -1020,13 +829,12 @@ void ath_restart_work(struct ath_softc *sc); | |||
1020 | int ath9k_init_device(u16 devid, struct ath_softc *sc, | 829 | int ath9k_init_device(u16 devid, struct ath_softc *sc, |
1021 | const struct ath_bus_ops *bus_ops); | 830 | const struct ath_bus_ops *bus_ops); |
1022 | void ath9k_deinit_device(struct ath_softc *sc); | 831 | void ath9k_deinit_device(struct ath_softc *sc); |
1023 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | ||
1024 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); | 832 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); |
1025 | 833 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); | |
1026 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); | 834 | void ath_start_rfkill_poll(struct ath_softc *sc); |
1027 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | 835 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
1028 | enum spectral_mode spectral_mode); | 836 | void ath9k_ps_wakeup(struct ath_softc *sc); |
1029 | 837 | void ath9k_ps_restore(struct ath_softc *sc); | |
1030 | 838 | ||
1031 | #ifdef CONFIG_ATH9K_PCI | 839 | #ifdef CONFIG_ATH9K_PCI |
1032 | int ath_pci_init(void); | 840 | int ath_pci_init(void); |
@@ -1044,15 +852,4 @@ static inline int ath_ahb_init(void) { return 0; }; | |||
1044 | static inline void ath_ahb_exit(void) {}; | 852 | static inline void ath_ahb_exit(void) {}; |
1045 | #endif | 853 | #endif |
1046 | 854 | ||
1047 | void ath9k_ps_wakeup(struct ath_softc *sc); | ||
1048 | void ath9k_ps_restore(struct ath_softc *sc); | ||
1049 | |||
1050 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); | ||
1051 | |||
1052 | void ath_start_rfkill_poll(struct ath_softc *sc); | ||
1053 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | ||
1054 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | ||
1055 | struct ieee80211_vif *vif, | ||
1056 | struct ath9k_vif_iter_data *iter_data); | ||
1057 | |||
1058 | #endif /* ATH9K_H */ | 855 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 17be35392bb4..112aff720e13 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -274,18 +274,19 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc) | |||
274 | return slot; | 274 | return slot; |
275 | } | 275 | } |
276 | 276 | ||
277 | void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif) | 277 | static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif) |
278 | { | 278 | { |
279 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 279 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
280 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | 280 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; |
281 | struct ath_vif *avp = (void *)vif->drv_priv; | 281 | struct ath_vif *avp = (void *)vif->drv_priv; |
282 | u64 tsfadjust; | 282 | u32 tsfadjust; |
283 | 283 | ||
284 | if (avp->av_bslot == 0) | 284 | if (avp->av_bslot == 0) |
285 | return; | 285 | return; |
286 | 286 | ||
287 | tsfadjust = cur_conf->beacon_interval * avp->av_bslot / ATH_BCBUF; | 287 | tsfadjust = cur_conf->beacon_interval * avp->av_bslot; |
288 | avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); | 288 | tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF; |
289 | avp->tsf_adjust = cpu_to_le64(tsfadjust); | ||
289 | 290 | ||
290 | ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n", | 291 | ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n", |
291 | (unsigned long long)tsfadjust, avp->av_bslot); | 292 | (unsigned long long)tsfadjust, avp->av_bslot); |
@@ -431,6 +432,33 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, | |||
431 | ath9k_hw_enable_interrupts(ah); | 432 | ath9k_hw_enable_interrupts(ah); |
432 | } | 433 | } |
433 | 434 | ||
435 | /* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */ | ||
436 | static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu) | ||
437 | { | ||
438 | u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo; | ||
439 | |||
440 | tsf_mod = tsf & (BIT(10) - 1); | ||
441 | tsf_hi = tsf >> 32; | ||
442 | tsf_lo = ((u32) tsf) >> 10; | ||
443 | |||
444 | mod_hi = tsf_hi % div_tu; | ||
445 | mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu; | ||
446 | |||
447 | return (mod_lo << 10) | tsf_mod; | ||
448 | } | ||
449 | |||
450 | static u32 ath9k_get_next_tbtt(struct ath_softc *sc, u64 tsf, | ||
451 | unsigned int interval) | ||
452 | { | ||
453 | struct ath_hw *ah = sc->sc_ah; | ||
454 | unsigned int offset; | ||
455 | |||
456 | tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time); | ||
457 | offset = ath9k_mod_tsf64_tu(tsf, interval); | ||
458 | |||
459 | return (u32) tsf + TU_TO_USEC(interval) - offset; | ||
460 | } | ||
461 | |||
434 | /* | 462 | /* |
435 | * For multi-bss ap support beacons are either staggered evenly over N slots or | 463 | * For multi-bss ap support beacons are either staggered evenly over N slots or |
436 | * burst together. For the former arrange for the SWBA to be delivered for each | 464 | * burst together. For the former arrange for the SWBA to be delivered for each |
@@ -446,7 +474,8 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc, | |||
446 | /* NB: the beacon interval is kept internally in TU's */ | 474 | /* NB: the beacon interval is kept internally in TU's */ |
447 | intval = TU_TO_USEC(conf->beacon_interval); | 475 | intval = TU_TO_USEC(conf->beacon_interval); |
448 | intval /= ATH_BCBUF; | 476 | intval /= ATH_BCBUF; |
449 | nexttbtt = intval; | 477 | nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah), |
478 | conf->beacon_interval); | ||
450 | 479 | ||
451 | if (conf->enable_beacon) | 480 | if (conf->enable_beacon) |
452 | ah->imask |= ATH9K_INT_SWBA; | 481 | ah->imask |= ATH9K_INT_SWBA; |
@@ -458,7 +487,7 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc, | |||
458 | (conf->enable_beacon) ? "Enable" : "Disable", | 487 | (conf->enable_beacon) ? "Enable" : "Disable", |
459 | nexttbtt, intval, conf->beacon_interval); | 488 | nexttbtt, intval, conf->beacon_interval); |
460 | 489 | ||
461 | ath9k_beacon_init(sc, nexttbtt, intval, true); | 490 | ath9k_beacon_init(sc, nexttbtt, intval, false); |
462 | } | 491 | } |
463 | 492 | ||
464 | /* | 493 | /* |
@@ -475,11 +504,9 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc, | |||
475 | struct ath_hw *ah = sc->sc_ah; | 504 | struct ath_hw *ah = sc->sc_ah; |
476 | struct ath_common *common = ath9k_hw_common(ah); | 505 | struct ath_common *common = ath9k_hw_common(ah); |
477 | struct ath9k_beacon_state bs; | 506 | struct ath9k_beacon_state bs; |
478 | int dtimperiod, dtimcount, sleepduration; | 507 | int dtim_intval, sleepduration; |
479 | int cfpperiod, cfpcount; | 508 | u32 nexttbtt = 0, intval; |
480 | u32 nexttbtt = 0, intval, tsftu; | ||
481 | u64 tsf; | 509 | u64 tsf; |
482 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; | ||
483 | 510 | ||
484 | /* No need to configure beacon if we are not associated */ | 511 | /* No need to configure beacon if we are not associated */ |
485 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | 512 | if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { |
@@ -492,53 +519,25 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc, | |||
492 | intval = conf->beacon_interval; | 519 | intval = conf->beacon_interval; |
493 | 520 | ||
494 | /* | 521 | /* |
495 | * Setup dtim and cfp parameters according to | 522 | * Setup dtim parameters according to |
496 | * last beacon we received (which may be none). | 523 | * last beacon we received (which may be none). |
497 | */ | 524 | */ |
498 | dtimperiod = conf->dtim_period; | 525 | dtim_intval = intval * conf->dtim_period; |
499 | dtimcount = conf->dtim_count; | ||
500 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | ||
501 | dtimcount = 0; | ||
502 | cfpperiod = 1; /* NB: no PCF support yet */ | ||
503 | cfpcount = 0; | ||
504 | |||
505 | sleepduration = conf->listen_interval * intval; | 526 | sleepduration = conf->listen_interval * intval; |
506 | 527 | ||
507 | /* | 528 | /* |
508 | * Pull nexttbtt forward to reflect the current | 529 | * Pull nexttbtt forward to reflect the current |
509 | * TSF and calculate dtim+cfp state for the result. | 530 | * TSF and calculate dtim state for the result. |
510 | */ | 531 | */ |
511 | tsf = ath9k_hw_gettsf64(ah); | 532 | tsf = ath9k_hw_gettsf64(ah); |
512 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | 533 | nexttbtt = ath9k_get_next_tbtt(sc, tsf, intval); |
513 | 534 | ||
514 | num_beacons = tsftu / intval + 1; | 535 | bs.bs_intval = TU_TO_USEC(intval); |
515 | offset = tsftu % intval; | 536 | bs.bs_dtimperiod = conf->dtim_period * bs.bs_intval; |
516 | nexttbtt = tsftu - offset; | ||
517 | if (offset) | ||
518 | nexttbtt += intval; | ||
519 | |||
520 | /* DTIM Beacon every dtimperiod Beacon */ | ||
521 | dtim_dec_count = num_beacons % dtimperiod; | ||
522 | /* CFP every cfpperiod DTIM Beacon */ | ||
523 | cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; | ||
524 | if (dtim_dec_count) | ||
525 | cfp_dec_count++; | ||
526 | |||
527 | dtimcount -= dtim_dec_count; | ||
528 | if (dtimcount < 0) | ||
529 | dtimcount += dtimperiod; | ||
530 | |||
531 | cfpcount -= cfp_dec_count; | ||
532 | if (cfpcount < 0) | ||
533 | cfpcount += cfpperiod; | ||
534 | |||
535 | bs.bs_intval = intval; | ||
536 | bs.bs_nexttbtt = nexttbtt; | 537 | bs.bs_nexttbtt = nexttbtt; |
537 | bs.bs_dtimperiod = dtimperiod*intval; | 538 | bs.bs_nextdtim = nexttbtt; |
538 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; | 539 | if (conf->dtim_period > 1) |
539 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; | 540 | bs.bs_nextdtim = ath9k_get_next_tbtt(sc, tsf, dtim_intval); |
540 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; | ||
541 | bs.bs_cfpmaxduration = 0; | ||
542 | 541 | ||
543 | /* | 542 | /* |
544 | * Calculate the number of consecutive beacons to miss* before taking | 543 | * Calculate the number of consecutive beacons to miss* before taking |
@@ -566,18 +565,16 @@ static void ath9k_beacon_config_sta(struct ath_softc *sc, | |||
566 | * XXX fixed at 100ms | 565 | * XXX fixed at 100ms |
567 | */ | 566 | */ |
568 | 567 | ||
569 | bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); | 568 | bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100), |
569 | sleepduration)); | ||
570 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | 570 | if (bs.bs_sleepduration > bs.bs_dtimperiod) |
571 | bs.bs_sleepduration = bs.bs_dtimperiod; | 571 | bs.bs_sleepduration = bs.bs_dtimperiod; |
572 | 572 | ||
573 | /* TSF out of range threshold fixed at 1 second */ | 573 | /* TSF out of range threshold fixed at 1 second */ |
574 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | 574 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
575 | 575 | ||
576 | ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | 576 | ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n", |
577 | ath_dbg(common, BEACON, | 577 | bs.bs_bmissthreshold, bs.bs_sleepduration); |
578 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | ||
579 | bs.bs_bmissthreshold, bs.bs_sleepduration, | ||
580 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | ||
581 | 578 | ||
582 | /* Set the computed STA beacon timers */ | 579 | /* Set the computed STA beacon timers */ |
583 | 580 | ||
@@ -600,25 +597,11 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc, | |||
600 | 597 | ||
601 | intval = TU_TO_USEC(conf->beacon_interval); | 598 | intval = TU_TO_USEC(conf->beacon_interval); |
602 | 599 | ||
603 | if (conf->ibss_creator) { | 600 | if (conf->ibss_creator) |
604 | nexttbtt = intval; | 601 | nexttbtt = intval; |
605 | } else { | 602 | else |
606 | u32 tbtt, offset, tsftu; | 603 | nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah), |
607 | u64 tsf; | 604 | conf->beacon_interval); |
608 | |||
609 | /* | ||
610 | * Pull nexttbtt forward to reflect the current | ||
611 | * sync'd TSF. | ||
612 | */ | ||
613 | tsf = ath9k_hw_gettsf64(ah); | ||
614 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; | ||
615 | offset = tsftu % conf->beacon_interval; | ||
616 | tbtt = tsftu - offset; | ||
617 | if (offset) | ||
618 | tbtt += conf->beacon_interval; | ||
619 | |||
620 | nexttbtt = TU_TO_USEC(tbtt); | ||
621 | } | ||
622 | 605 | ||
623 | if (conf->enable_beacon) | 606 | if (conf->enable_beacon) |
624 | ah->imask |= ATH9K_INT_SWBA; | 607 | ah->imask |= ATH9K_INT_SWBA; |
@@ -640,7 +623,8 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc, | |||
640 | set_bit(SC_OP_BEACONS, &sc->sc_flags); | 623 | set_bit(SC_OP_BEACONS, &sc->sc_flags); |
641 | } | 624 | } |
642 | 625 | ||
643 | bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | 626 | static bool ath9k_allow_beacon_config(struct ath_softc *sc, |
627 | struct ieee80211_vif *vif) | ||
644 | { | 628 | { |
645 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 629 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
646 | struct ath_vif *avp = (void *)vif->drv_priv; | 630 | struct ath_vif *avp = (void *)vif->drv_priv; |
@@ -711,12 +695,17 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
711 | unsigned long flags; | 695 | unsigned long flags; |
712 | bool skip_beacon = false; | 696 | bool skip_beacon = false; |
713 | 697 | ||
698 | if (vif->type == NL80211_IFTYPE_AP) | ||
699 | ath9k_set_tsfadjust(sc, vif); | ||
700 | |||
701 | if (!ath9k_allow_beacon_config(sc, vif)) | ||
702 | return; | ||
703 | |||
714 | if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { | 704 | if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { |
715 | ath9k_cache_beacon_config(sc, bss_conf); | 705 | ath9k_cache_beacon_config(sc, bss_conf); |
716 | ath9k_set_beacon(sc); | 706 | ath9k_set_beacon(sc); |
717 | set_bit(SC_OP_BEACONS, &sc->sc_flags); | 707 | set_bit(SC_OP_BEACONS, &sc->sc_flags); |
718 | return; | 708 | return; |
719 | |||
720 | } | 709 | } |
721 | 710 | ||
722 | /* | 711 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 9963b0bf9f72..3dfc2c7f1f07 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -66,7 +66,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) | |||
66 | .bt_first_slot_time = 5, | 66 | .bt_first_slot_time = 5, |
67 | .bt_hold_rx_clear = true, | 67 | .bt_hold_rx_clear = true, |
68 | }; | 68 | }; |
69 | u32 i, idx; | ||
70 | bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; | 69 | bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; |
71 | 70 | ||
72 | if (AR_SREV_9300_20_OR_LATER(ah)) | 71 | if (AR_SREV_9300_20_OR_LATER(ah)) |
@@ -88,11 +87,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) | |||
88 | SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | | 87 | SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | |
89 | SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | | 88 | SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | |
90 | AR_BT_DISABLE_BT_ANT; | 89 | AR_BT_DISABLE_BT_ANT; |
91 | |||
92 | for (i = 0; i < 32; i++) { | ||
93 | idx = (debruijn32 << i) >> 27; | ||
94 | ah->hw_gen_timers.gen_timer_index[idx] = i; | ||
95 | } | ||
96 | } | 90 | } |
97 | EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw); | 91 | EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw); |
98 | 92 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index a7e5a05b2eff..768c733cad31 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -98,10 +98,8 @@ struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, | |||
98 | { | 98 | { |
99 | struct ieee80211_channel *curchan = chandef->chan; | 99 | struct ieee80211_channel *curchan = chandef->chan; |
100 | struct ath9k_channel *channel; | 100 | struct ath9k_channel *channel; |
101 | u8 chan_idx; | ||
102 | 101 | ||
103 | chan_idx = curchan->hw_value; | 102 | channel = &ah->channels[curchan->hw_value]; |
104 | channel = &ah->channels[chan_idx]; | ||
105 | ath9k_cmn_update_ichannel(channel, chandef); | 103 | ath9k_cmn_update_ichannel(channel, chandef); |
106 | 104 | ||
107 | return channel; | 105 | return channel; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 2f7dccfdb727..b041052a10ee 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
19 | #include <linux/export.h> | 19 | #include <linux/export.h> |
20 | #include <linux/relay.h> | ||
21 | #include <asm/unaligned.h> | 20 | #include <asm/unaligned.h> |
22 | 21 | ||
23 | #include "ath9k.h" | 22 | #include "ath9k.h" |
@@ -27,6 +26,47 @@ | |||
27 | #define REG_READ_D(_ah, _reg) \ | 26 | #define REG_READ_D(_ah, _reg) \ |
28 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) | 27 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) |
29 | 28 | ||
29 | void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) | ||
30 | { | ||
31 | if (sync_cause) | ||
32 | sc->debug.stats.istats.sync_cause_all++; | ||
33 | if (sync_cause & AR_INTR_SYNC_RTC_IRQ) | ||
34 | sc->debug.stats.istats.sync_rtc_irq++; | ||
35 | if (sync_cause & AR_INTR_SYNC_MAC_IRQ) | ||
36 | sc->debug.stats.istats.sync_mac_irq++; | ||
37 | if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS) | ||
38 | sc->debug.stats.istats.eeprom_illegal_access++; | ||
39 | if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT) | ||
40 | sc->debug.stats.istats.apb_timeout++; | ||
41 | if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT) | ||
42 | sc->debug.stats.istats.pci_mode_conflict++; | ||
43 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) | ||
44 | sc->debug.stats.istats.host1_fatal++; | ||
45 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) | ||
46 | sc->debug.stats.istats.host1_perr++; | ||
47 | if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR) | ||
48 | sc->debug.stats.istats.trcv_fifo_perr++; | ||
49 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP) | ||
50 | sc->debug.stats.istats.radm_cpl_ep++; | ||
51 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT) | ||
52 | sc->debug.stats.istats.radm_cpl_dllp_abort++; | ||
53 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT) | ||
54 | sc->debug.stats.istats.radm_cpl_tlp_abort++; | ||
55 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR) | ||
56 | sc->debug.stats.istats.radm_cpl_ecrc_err++; | ||
57 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) | ||
58 | sc->debug.stats.istats.radm_cpl_timeout++; | ||
59 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) | ||
60 | sc->debug.stats.istats.local_timeout++; | ||
61 | if (sync_cause & AR_INTR_SYNC_PM_ACCESS) | ||
62 | sc->debug.stats.istats.pm_access++; | ||
63 | if (sync_cause & AR_INTR_SYNC_MAC_AWAKE) | ||
64 | sc->debug.stats.istats.mac_awake++; | ||
65 | if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP) | ||
66 | sc->debug.stats.istats.mac_asleep++; | ||
67 | if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS) | ||
68 | sc->debug.stats.istats.mac_sleep_access++; | ||
69 | } | ||
30 | 70 | ||
31 | static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf, | 71 | static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf, |
32 | size_t count, loff_t *ppos) | 72 | size_t count, loff_t *ppos) |
@@ -1016,293 +1056,6 @@ static const struct file_operations fops_recv = { | |||
1016 | .llseek = default_llseek, | 1056 | .llseek = default_llseek, |
1017 | }; | 1057 | }; |
1018 | 1058 | ||
1019 | static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, | ||
1020 | size_t count, loff_t *ppos) | ||
1021 | { | ||
1022 | struct ath_softc *sc = file->private_data; | ||
1023 | char *mode = ""; | ||
1024 | unsigned int len; | ||
1025 | |||
1026 | switch (sc->spectral_mode) { | ||
1027 | case SPECTRAL_DISABLED: | ||
1028 | mode = "disable"; | ||
1029 | break; | ||
1030 | case SPECTRAL_BACKGROUND: | ||
1031 | mode = "background"; | ||
1032 | break; | ||
1033 | case SPECTRAL_CHANSCAN: | ||
1034 | mode = "chanscan"; | ||
1035 | break; | ||
1036 | case SPECTRAL_MANUAL: | ||
1037 | mode = "manual"; | ||
1038 | break; | ||
1039 | } | ||
1040 | len = strlen(mode); | ||
1041 | return simple_read_from_buffer(user_buf, count, ppos, mode, len); | ||
1042 | } | ||
1043 | |||
1044 | static ssize_t write_file_spec_scan_ctl(struct file *file, | ||
1045 | const char __user *user_buf, | ||
1046 | size_t count, loff_t *ppos) | ||
1047 | { | ||
1048 | struct ath_softc *sc = file->private_data; | ||
1049 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1050 | char buf[32]; | ||
1051 | ssize_t len; | ||
1052 | |||
1053 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
1054 | return -EOPNOTSUPP; | ||
1055 | |||
1056 | len = min(count, sizeof(buf) - 1); | ||
1057 | if (copy_from_user(buf, user_buf, len)) | ||
1058 | return -EFAULT; | ||
1059 | |||
1060 | buf[len] = '\0'; | ||
1061 | |||
1062 | if (strncmp("trigger", buf, 7) == 0) { | ||
1063 | ath9k_spectral_scan_trigger(sc->hw); | ||
1064 | } else if (strncmp("background", buf, 9) == 0) { | ||
1065 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND); | ||
1066 | ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); | ||
1067 | } else if (strncmp("chanscan", buf, 8) == 0) { | ||
1068 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN); | ||
1069 | ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); | ||
1070 | } else if (strncmp("manual", buf, 6) == 0) { | ||
1071 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL); | ||
1072 | ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); | ||
1073 | } else if (strncmp("disable", buf, 7) == 0) { | ||
1074 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED); | ||
1075 | ath_dbg(common, CONFIG, "spectral scan: disabled\n"); | ||
1076 | } else { | ||
1077 | return -EINVAL; | ||
1078 | } | ||
1079 | |||
1080 | return count; | ||
1081 | } | ||
1082 | |||
1083 | static const struct file_operations fops_spec_scan_ctl = { | ||
1084 | .read = read_file_spec_scan_ctl, | ||
1085 | .write = write_file_spec_scan_ctl, | ||
1086 | .open = simple_open, | ||
1087 | .owner = THIS_MODULE, | ||
1088 | .llseek = default_llseek, | ||
1089 | }; | ||
1090 | |||
1091 | static ssize_t read_file_spectral_short_repeat(struct file *file, | ||
1092 | char __user *user_buf, | ||
1093 | size_t count, loff_t *ppos) | ||
1094 | { | ||
1095 | struct ath_softc *sc = file->private_data; | ||
1096 | char buf[32]; | ||
1097 | unsigned int len; | ||
1098 | |||
1099 | len = sprintf(buf, "%d\n", sc->spec_config.short_repeat); | ||
1100 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1101 | } | ||
1102 | |||
1103 | static ssize_t write_file_spectral_short_repeat(struct file *file, | ||
1104 | const char __user *user_buf, | ||
1105 | size_t count, loff_t *ppos) | ||
1106 | { | ||
1107 | struct ath_softc *sc = file->private_data; | ||
1108 | unsigned long val; | ||
1109 | char buf[32]; | ||
1110 | ssize_t len; | ||
1111 | |||
1112 | len = min(count, sizeof(buf) - 1); | ||
1113 | if (copy_from_user(buf, user_buf, len)) | ||
1114 | return -EFAULT; | ||
1115 | |||
1116 | buf[len] = '\0'; | ||
1117 | if (kstrtoul(buf, 0, &val)) | ||
1118 | return -EINVAL; | ||
1119 | |||
1120 | if (val < 0 || val > 1) | ||
1121 | return -EINVAL; | ||
1122 | |||
1123 | sc->spec_config.short_repeat = val; | ||
1124 | return count; | ||
1125 | } | ||
1126 | |||
1127 | static const struct file_operations fops_spectral_short_repeat = { | ||
1128 | .read = read_file_spectral_short_repeat, | ||
1129 | .write = write_file_spectral_short_repeat, | ||
1130 | .open = simple_open, | ||
1131 | .owner = THIS_MODULE, | ||
1132 | .llseek = default_llseek, | ||
1133 | }; | ||
1134 | |||
1135 | static ssize_t read_file_spectral_count(struct file *file, | ||
1136 | char __user *user_buf, | ||
1137 | size_t count, loff_t *ppos) | ||
1138 | { | ||
1139 | struct ath_softc *sc = file->private_data; | ||
1140 | char buf[32]; | ||
1141 | unsigned int len; | ||
1142 | |||
1143 | len = sprintf(buf, "%d\n", sc->spec_config.count); | ||
1144 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1145 | } | ||
1146 | |||
1147 | static ssize_t write_file_spectral_count(struct file *file, | ||
1148 | const char __user *user_buf, | ||
1149 | size_t count, loff_t *ppos) | ||
1150 | { | ||
1151 | struct ath_softc *sc = file->private_data; | ||
1152 | unsigned long val; | ||
1153 | char buf[32]; | ||
1154 | ssize_t len; | ||
1155 | |||
1156 | len = min(count, sizeof(buf) - 1); | ||
1157 | if (copy_from_user(buf, user_buf, len)) | ||
1158 | return -EFAULT; | ||
1159 | |||
1160 | buf[len] = '\0'; | ||
1161 | if (kstrtoul(buf, 0, &val)) | ||
1162 | return -EINVAL; | ||
1163 | |||
1164 | if (val < 0 || val > 255) | ||
1165 | return -EINVAL; | ||
1166 | |||
1167 | sc->spec_config.count = val; | ||
1168 | return count; | ||
1169 | } | ||
1170 | |||
1171 | static const struct file_operations fops_spectral_count = { | ||
1172 | .read = read_file_spectral_count, | ||
1173 | .write = write_file_spectral_count, | ||
1174 | .open = simple_open, | ||
1175 | .owner = THIS_MODULE, | ||
1176 | .llseek = default_llseek, | ||
1177 | }; | ||
1178 | |||
1179 | static ssize_t read_file_spectral_period(struct file *file, | ||
1180 | char __user *user_buf, | ||
1181 | size_t count, loff_t *ppos) | ||
1182 | { | ||
1183 | struct ath_softc *sc = file->private_data; | ||
1184 | char buf[32]; | ||
1185 | unsigned int len; | ||
1186 | |||
1187 | len = sprintf(buf, "%d\n", sc->spec_config.period); | ||
1188 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1189 | } | ||
1190 | |||
1191 | static ssize_t write_file_spectral_period(struct file *file, | ||
1192 | const char __user *user_buf, | ||
1193 | size_t count, loff_t *ppos) | ||
1194 | { | ||
1195 | struct ath_softc *sc = file->private_data; | ||
1196 | unsigned long val; | ||
1197 | char buf[32]; | ||
1198 | ssize_t len; | ||
1199 | |||
1200 | len = min(count, sizeof(buf) - 1); | ||
1201 | if (copy_from_user(buf, user_buf, len)) | ||
1202 | return -EFAULT; | ||
1203 | |||
1204 | buf[len] = '\0'; | ||
1205 | if (kstrtoul(buf, 0, &val)) | ||
1206 | return -EINVAL; | ||
1207 | |||
1208 | if (val < 0 || val > 255) | ||
1209 | return -EINVAL; | ||
1210 | |||
1211 | sc->spec_config.period = val; | ||
1212 | return count; | ||
1213 | } | ||
1214 | |||
1215 | static const struct file_operations fops_spectral_period = { | ||
1216 | .read = read_file_spectral_period, | ||
1217 | .write = write_file_spectral_period, | ||
1218 | .open = simple_open, | ||
1219 | .owner = THIS_MODULE, | ||
1220 | .llseek = default_llseek, | ||
1221 | }; | ||
1222 | |||
1223 | static ssize_t read_file_spectral_fft_period(struct file *file, | ||
1224 | char __user *user_buf, | ||
1225 | size_t count, loff_t *ppos) | ||
1226 | { | ||
1227 | struct ath_softc *sc = file->private_data; | ||
1228 | char buf[32]; | ||
1229 | unsigned int len; | ||
1230 | |||
1231 | len = sprintf(buf, "%d\n", sc->spec_config.fft_period); | ||
1232 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1233 | } | ||
1234 | |||
1235 | static ssize_t write_file_spectral_fft_period(struct file *file, | ||
1236 | const char __user *user_buf, | ||
1237 | size_t count, loff_t *ppos) | ||
1238 | { | ||
1239 | struct ath_softc *sc = file->private_data; | ||
1240 | unsigned long val; | ||
1241 | char buf[32]; | ||
1242 | ssize_t len; | ||
1243 | |||
1244 | len = min(count, sizeof(buf) - 1); | ||
1245 | if (copy_from_user(buf, user_buf, len)) | ||
1246 | return -EFAULT; | ||
1247 | |||
1248 | buf[len] = '\0'; | ||
1249 | if (kstrtoul(buf, 0, &val)) | ||
1250 | return -EINVAL; | ||
1251 | |||
1252 | if (val < 0 || val > 15) | ||
1253 | return -EINVAL; | ||
1254 | |||
1255 | sc->spec_config.fft_period = val; | ||
1256 | return count; | ||
1257 | } | ||
1258 | |||
1259 | static const struct file_operations fops_spectral_fft_period = { | ||
1260 | .read = read_file_spectral_fft_period, | ||
1261 | .write = write_file_spectral_fft_period, | ||
1262 | .open = simple_open, | ||
1263 | .owner = THIS_MODULE, | ||
1264 | .llseek = default_llseek, | ||
1265 | }; | ||
1266 | |||
1267 | static struct dentry *create_buf_file_handler(const char *filename, | ||
1268 | struct dentry *parent, | ||
1269 | umode_t mode, | ||
1270 | struct rchan_buf *buf, | ||
1271 | int *is_global) | ||
1272 | { | ||
1273 | struct dentry *buf_file; | ||
1274 | |||
1275 | buf_file = debugfs_create_file(filename, mode, parent, buf, | ||
1276 | &relay_file_operations); | ||
1277 | *is_global = 1; | ||
1278 | return buf_file; | ||
1279 | } | ||
1280 | |||
1281 | static int remove_buf_file_handler(struct dentry *dentry) | ||
1282 | { | ||
1283 | debugfs_remove(dentry); | ||
1284 | |||
1285 | return 0; | ||
1286 | } | ||
1287 | |||
1288 | void ath_debug_send_fft_sample(struct ath_softc *sc, | ||
1289 | struct fft_sample_tlv *fft_sample_tlv) | ||
1290 | { | ||
1291 | int length; | ||
1292 | if (!sc->rfs_chan_spec_scan) | ||
1293 | return; | ||
1294 | |||
1295 | length = __be16_to_cpu(fft_sample_tlv->length) + | ||
1296 | sizeof(*fft_sample_tlv); | ||
1297 | relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length); | ||
1298 | } | ||
1299 | |||
1300 | static struct rchan_callbacks rfs_spec_scan_cb = { | ||
1301 | .create_buf_file = create_buf_file_handler, | ||
1302 | .remove_buf_file = remove_buf_file_handler, | ||
1303 | }; | ||
1304 | |||
1305 | |||
1306 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, | 1059 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, |
1307 | size_t count, loff_t *ppos) | 1060 | size_t count, loff_t *ppos) |
1308 | { | 1061 | { |
@@ -1772,10 +1525,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, | |||
1772 | 1525 | ||
1773 | void ath9k_deinit_debug(struct ath_softc *sc) | 1526 | void ath9k_deinit_debug(struct ath_softc *sc) |
1774 | { | 1527 | { |
1775 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { | 1528 | ath9k_spectral_deinit_debug(sc); |
1776 | relay_close(sc->rfs_chan_spec_scan); | ||
1777 | sc->rfs_chan_spec_scan = NULL; | ||
1778 | } | ||
1779 | } | 1529 | } |
1780 | 1530 | ||
1781 | int ath9k_init_debug(struct ath_hw *ah) | 1531 | int ath9k_init_debug(struct ath_hw *ah) |
@@ -1795,6 +1545,7 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1795 | 1545 | ||
1796 | ath9k_dfs_init_debug(sc); | 1546 | ath9k_dfs_init_debug(sc); |
1797 | ath9k_tx99_init_debug(sc); | 1547 | ath9k_tx99_init_debug(sc); |
1548 | ath9k_spectral_init_debug(sc); | ||
1798 | 1549 | ||
1799 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, | 1550 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, |
1800 | &fops_dma); | 1551 | &fops_dma); |
@@ -1841,23 +1592,6 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1841 | &fops_base_eeprom); | 1592 | &fops_base_eeprom); |
1842 | debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, | 1593 | debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, |
1843 | &fops_modal_eeprom); | 1594 | &fops_modal_eeprom); |
1844 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", | ||
1845 | sc->debug.debugfs_phy, | ||
1846 | 1024, 256, &rfs_spec_scan_cb, | ||
1847 | NULL); | ||
1848 | debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, | ||
1849 | sc->debug.debugfs_phy, sc, | ||
1850 | &fops_spec_scan_ctl); | ||
1851 | debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR, | ||
1852 | sc->debug.debugfs_phy, sc, | ||
1853 | &fops_spectral_short_repeat); | ||
1854 | debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR, | ||
1855 | sc->debug.debugfs_phy, sc, &fops_spectral_count); | ||
1856 | debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR, | ||
1857 | sc->debug.debugfs_phy, sc, &fops_spectral_period); | ||
1858 | debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR, | ||
1859 | sc->debug.debugfs_phy, sc, | ||
1860 | &fops_spectral_fft_period); | ||
1861 | debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, | 1595 | debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, |
1862 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); | 1596 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); |
1863 | debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, | 1597 | debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index d6e3fa4299a4..ec02d38ea8ea 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -292,11 +292,11 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | |||
292 | struct ieee80211_vif *vif, | 292 | struct ieee80211_vif *vif, |
293 | struct ieee80211_sta *sta, | 293 | struct ieee80211_sta *sta, |
294 | struct dentry *dir); | 294 | struct dentry *dir); |
295 | void ath_debug_send_fft_sample(struct ath_softc *sc, | ||
296 | struct fft_sample_tlv *fft_sample); | ||
297 | void ath9k_debug_stat_ant(struct ath_softc *sc, | 295 | void ath9k_debug_stat_ant(struct ath_softc *sc, |
298 | struct ath_hw_antcomb_conf *div_ant_conf, | 296 | struct ath_hw_antcomb_conf *div_ant_conf, |
299 | int main_rssi_avg, int alt_rssi_avg); | 297 | int main_rssi_avg, int alt_rssi_avg); |
298 | void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause); | ||
299 | |||
300 | #else | 300 | #else |
301 | 301 | ||
302 | #define RX_STAT_INC(c) /* NOP */ | 302 | #define RX_STAT_INC(c) /* NOP */ |
@@ -331,6 +331,11 @@ static inline void ath9k_debug_stat_ant(struct ath_softc *sc, | |||
331 | 331 | ||
332 | } | 332 | } |
333 | 333 | ||
334 | static inline void | ||
335 | ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) | ||
336 | { | ||
337 | } | ||
338 | |||
334 | #endif /* CONFIG_ATH9K_DEBUGFS */ | 339 | #endif /* CONFIG_ATH9K_DEBUGFS */ |
335 | 340 | ||
336 | #endif /* DEBUG_H */ | 341 | #endif /* DEBUG_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index 7187d3671512..857bb28b3894 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | |||
158 | return; | 158 | return; |
159 | } | 159 | } |
160 | 160 | ||
161 | ard.rssi = rs->rs_rssi_ctl0; | 161 | ard.rssi = rs->rs_rssi_ctl[0]; |
162 | ard.ext_rssi = rs->rs_rssi_ext0; | 162 | ard.ext_rssi = rs->rs_rssi_ext[0]; |
163 | 163 | ||
164 | /* | 164 | /* |
165 | * hardware stores this as 8 bit signed value. | 165 | * hardware stores this as 8 bit signed value. |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index b4091716e9b3..07b806c56c56 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -1085,31 +1085,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1085 | 1085 | ||
1086 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | 1086 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) |
1087 | { | 1087 | { |
1088 | #define EEP_MAP4K_SPURCHAN \ | 1088 | return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan; |
1089 | (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) | ||
1090 | struct ath_common *common = ath9k_hw_common(ah); | ||
1091 | |||
1092 | u16 spur_val = AR_NO_SPUR; | ||
1093 | |||
1094 | ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n", | ||
1095 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1096 | |||
1097 | switch (ah->config.spurmode) { | ||
1098 | case SPUR_DISABLE: | ||
1099 | break; | ||
1100 | case SPUR_ENABLE_IOCTL: | ||
1101 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1102 | ath_dbg(common, ANI, "Getting spur val from new loc. %d\n", | ||
1103 | spur_val); | ||
1104 | break; | ||
1105 | case SPUR_ENABLE_EEPROM: | ||
1106 | spur_val = EEP_MAP4K_SPURCHAN; | ||
1107 | break; | ||
1108 | } | ||
1109 | |||
1110 | return spur_val; | ||
1111 | |||
1112 | #undef EEP_MAP4K_SPURCHAN | ||
1113 | } | 1089 | } |
1114 | 1090 | ||
1115 | const struct eeprom_ops eep_4k_ops = { | 1091 | const struct eeprom_ops eep_4k_ops = { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index e1d0c217c104..5ba1385c9838 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -1004,31 +1004,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, | |||
1004 | static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, | 1004 | static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, |
1005 | u16 i, bool is2GHz) | 1005 | u16 i, bool is2GHz) |
1006 | { | 1006 | { |
1007 | #define EEP_MAP9287_SPURCHAN \ | 1007 | return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan; |
1008 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) | ||
1009 | |||
1010 | struct ath_common *common = ath9k_hw_common(ah); | ||
1011 | u16 spur_val = AR_NO_SPUR; | ||
1012 | |||
1013 | ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n", | ||
1014 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1015 | |||
1016 | switch (ah->config.spurmode) { | ||
1017 | case SPUR_DISABLE: | ||
1018 | break; | ||
1019 | case SPUR_ENABLE_IOCTL: | ||
1020 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1021 | ath_dbg(common, ANI, "Getting spur val from new loc. %d\n", | ||
1022 | spur_val); | ||
1023 | break; | ||
1024 | case SPUR_ENABLE_EEPROM: | ||
1025 | spur_val = EEP_MAP9287_SPURCHAN; | ||
1026 | break; | ||
1027 | } | ||
1028 | |||
1029 | return spur_val; | ||
1030 | |||
1031 | #undef EEP_MAP9287_SPURCHAN | ||
1032 | } | 1008 | } |
1033 | 1009 | ||
1034 | const struct eeprom_ops eep_ar9287_ops = { | 1010 | const struct eeprom_ops eep_ar9287_ops = { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 39107e31e79a..3218ca994746 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -1348,31 +1348,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1348 | 1348 | ||
1349 | static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | 1349 | static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) |
1350 | { | 1350 | { |
1351 | #define EEP_DEF_SPURCHAN \ | 1351 | return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan; |
1352 | (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) | ||
1353 | struct ath_common *common = ath9k_hw_common(ah); | ||
1354 | |||
1355 | u16 spur_val = AR_NO_SPUR; | ||
1356 | |||
1357 | ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n", | ||
1358 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1359 | |||
1360 | switch (ah->config.spurmode) { | ||
1361 | case SPUR_DISABLE: | ||
1362 | break; | ||
1363 | case SPUR_ENABLE_IOCTL: | ||
1364 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1365 | ath_dbg(common, ANI, "Getting spur val from new loc. %d\n", | ||
1366 | spur_val); | ||
1367 | break; | ||
1368 | case SPUR_ENABLE_EEPROM: | ||
1369 | spur_val = EEP_DEF_SPURCHAN; | ||
1370 | break; | ||
1371 | } | ||
1372 | |||
1373 | return spur_val; | ||
1374 | |||
1375 | #undef EEP_DEF_SPURCHAN | ||
1376 | } | 1352 | } |
1377 | 1353 | ||
1378 | const struct eeprom_ops eep_def_ops = { | 1354 | const struct eeprom_ops eep_def_ops = { |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index c34f21241da9..b1956bf6e01e 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -157,36 +157,6 @@ static void ath_detect_bt_priority(struct ath_softc *sc) | |||
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
160 | static void ath9k_gen_timer_start(struct ath_hw *ah, | ||
161 | struct ath_gen_timer *timer, | ||
162 | u32 trig_timeout, | ||
163 | u32 timer_period) | ||
164 | { | ||
165 | ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period); | ||
166 | |||
167 | if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { | ||
168 | ath9k_hw_disable_interrupts(ah); | ||
169 | ah->imask |= ATH9K_INT_GENTIMER; | ||
170 | ath9k_hw_set_interrupts(ah); | ||
171 | ath9k_hw_enable_interrupts(ah); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | ||
176 | { | ||
177 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | ||
178 | |||
179 | ath9k_hw_gen_timer_stop(ah, timer); | ||
180 | |||
181 | /* if no timer is enabled, turn off interrupt mask */ | ||
182 | if (timer_table->timer_mask.val == 0) { | ||
183 | ath9k_hw_disable_interrupts(ah); | ||
184 | ah->imask &= ~ATH9K_INT_GENTIMER; | ||
185 | ath9k_hw_set_interrupts(ah); | ||
186 | ath9k_hw_enable_interrupts(ah); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | static void ath_mci_ftp_adjust(struct ath_softc *sc) | 160 | static void ath_mci_ftp_adjust(struct ath_softc *sc) |
191 | { | 161 | { |
192 | struct ath_btcoex *btcoex = &sc->btcoex; | 162 | struct ath_btcoex *btcoex = &sc->btcoex; |
@@ -257,19 +227,9 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
257 | 227 | ||
258 | spin_unlock_bh(&btcoex->btcoex_lock); | 228 | spin_unlock_bh(&btcoex->btcoex_lock); |
259 | 229 | ||
260 | /* | 230 | if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) |
261 | * btcoex_period is in msec while (btocex/btscan_)no_stomp are in usec, | 231 | mod_timer(&btcoex->no_stomp_timer, |
262 | * ensure that we properly convert btcoex_period to usec | 232 | jiffies + msecs_to_jiffies(timer_period)); |
263 | * for any comparision with (btcoex/btscan_)no_stomp. | ||
264 | */ | ||
265 | if (btcoex->btcoex_period * 1000 != btcoex->btcoex_no_stomp) { | ||
266 | if (btcoex->hw_timer_enabled) | ||
267 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
268 | |||
269 | ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, | ||
270 | timer_period * 10); | ||
271 | btcoex->hw_timer_enabled = true; | ||
272 | } | ||
273 | 233 | ||
274 | ath9k_ps_restore(sc); | 234 | ath9k_ps_restore(sc); |
275 | 235 | ||
@@ -282,7 +242,7 @@ skip_hw_wakeup: | |||
282 | * Generic tsf based hw timer which configures weight | 242 | * Generic tsf based hw timer which configures weight |
283 | * registers to time slice between wlan and bt traffic | 243 | * registers to time slice between wlan and bt traffic |
284 | */ | 244 | */ |
285 | static void ath_btcoex_no_stomp_timer(void *arg) | 245 | static void ath_btcoex_no_stomp_timer(unsigned long arg) |
286 | { | 246 | { |
287 | struct ath_softc *sc = (struct ath_softc *)arg; | 247 | struct ath_softc *sc = (struct ath_softc *)arg; |
288 | struct ath_hw *ah = sc->sc_ah; | 248 | struct ath_hw *ah = sc->sc_ah; |
@@ -311,24 +271,18 @@ static int ath_init_btcoex_timer(struct ath_softc *sc) | |||
311 | struct ath_btcoex *btcoex = &sc->btcoex; | 271 | struct ath_btcoex *btcoex = &sc->btcoex; |
312 | 272 | ||
313 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; | 273 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; |
314 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 * | 274 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * |
315 | btcoex->btcoex_period / 100; | 275 | btcoex->btcoex_period / 100; |
316 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 * | 276 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * |
317 | btcoex->btcoex_period / 100; | 277 | btcoex->btcoex_period / 100; |
318 | 278 | ||
319 | setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, | 279 | setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, |
320 | (unsigned long) sc); | 280 | (unsigned long) sc); |
281 | setup_timer(&btcoex->no_stomp_timer, ath_btcoex_no_stomp_timer, | ||
282 | (unsigned long) sc); | ||
321 | 283 | ||
322 | spin_lock_init(&btcoex->btcoex_lock); | 284 | spin_lock_init(&btcoex->btcoex_lock); |
323 | 285 | ||
324 | btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah, | ||
325 | ath_btcoex_no_stomp_timer, | ||
326 | ath_btcoex_no_stomp_timer, | ||
327 | (void *) sc, AR_FIRST_NDP_TIMER); | ||
328 | |||
329 | if (!btcoex->no_stomp_timer) | ||
330 | return -ENOMEM; | ||
331 | |||
332 | return 0; | 286 | return 0; |
333 | } | 287 | } |
334 | 288 | ||
@@ -343,10 +297,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) | |||
343 | ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n"); | 297 | ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n"); |
344 | 298 | ||
345 | /* make sure duty cycle timer is also stopped when resuming */ | 299 | /* make sure duty cycle timer is also stopped when resuming */ |
346 | if (btcoex->hw_timer_enabled) { | 300 | del_timer_sync(&btcoex->no_stomp_timer); |
347 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); | ||
348 | btcoex->hw_timer_enabled = false; | ||
349 | } | ||
350 | 301 | ||
351 | btcoex->bt_priority_cnt = 0; | 302 | btcoex->bt_priority_cnt = 0; |
352 | btcoex->bt_priority_time = jiffies; | 303 | btcoex->bt_priority_time = jiffies; |
@@ -363,24 +314,16 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) | |||
363 | void ath9k_btcoex_timer_pause(struct ath_softc *sc) | 314 | void ath9k_btcoex_timer_pause(struct ath_softc *sc) |
364 | { | 315 | { |
365 | struct ath_btcoex *btcoex = &sc->btcoex; | 316 | struct ath_btcoex *btcoex = &sc->btcoex; |
366 | struct ath_hw *ah = sc->sc_ah; | ||
367 | 317 | ||
368 | del_timer_sync(&btcoex->period_timer); | 318 | del_timer_sync(&btcoex->period_timer); |
369 | 319 | del_timer_sync(&btcoex->no_stomp_timer); | |
370 | if (btcoex->hw_timer_enabled) { | ||
371 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
372 | btcoex->hw_timer_enabled = false; | ||
373 | } | ||
374 | } | 320 | } |
375 | 321 | ||
376 | void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) | 322 | void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) |
377 | { | 323 | { |
378 | struct ath_btcoex *btcoex = &sc->btcoex; | 324 | struct ath_btcoex *btcoex = &sc->btcoex; |
379 | 325 | ||
380 | if (btcoex->hw_timer_enabled) { | 326 | del_timer_sync(&btcoex->no_stomp_timer); |
381 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); | ||
382 | btcoex->hw_timer_enabled = false; | ||
383 | } | ||
384 | } | 327 | } |
385 | 328 | ||
386 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) | 329 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) |
@@ -400,12 +343,6 @@ u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) | |||
400 | 343 | ||
401 | void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status) | 344 | void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status) |
402 | { | 345 | { |
403 | struct ath_hw *ah = sc->sc_ah; | ||
404 | |||
405 | if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) | ||
406 | if (status & ATH9K_INT_GENTIMER) | ||
407 | ath_gen_timer_isr(sc->sc_ah); | ||
408 | |||
409 | if (status & ATH9K_INT_MCI) | 346 | if (status & ATH9K_INT_MCI) |
410 | ath_mci_intr(sc); | 347 | ath_mci_intr(sc); |
411 | } | 348 | } |
@@ -447,10 +384,6 @@ void ath9k_deinit_btcoex(struct ath_softc *sc) | |||
447 | { | 384 | { |
448 | struct ath_hw *ah = sc->sc_ah; | 385 | struct ath_hw *ah = sc->sc_ah; |
449 | 386 | ||
450 | if ((sc->btcoex.no_stomp_timer) && | ||
451 | ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE) | ||
452 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); | ||
453 | |||
454 | if (ath9k_hw_mci_is_enabled(ah)) | 387 | if (ath9k_hw_mci_is_enabled(ah)) |
455 | ath_mci_cleanup(sc); | 388 | ath_mci_cleanup(sc); |
456 | } | 389 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 055d7c25e090..58da3468d1f0 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -600,10 +600,15 @@ void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); | |||
600 | struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv); | 600 | struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv); |
601 | 601 | ||
602 | #ifdef CONFIG_MAC80211_LEDS | 602 | #ifdef CONFIG_MAC80211_LEDS |
603 | void ath9k_configure_leds(struct ath9k_htc_priv *priv); | ||
603 | void ath9k_init_leds(struct ath9k_htc_priv *priv); | 604 | void ath9k_init_leds(struct ath9k_htc_priv *priv); |
604 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); | 605 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); |
605 | void ath9k_led_work(struct work_struct *work); | 606 | void ath9k_led_work(struct work_struct *work); |
606 | #else | 607 | #else |
608 | static inline void ath9k_configure_leds(struct ath9k_htc_priv *priv) | ||
609 | { | ||
610 | } | ||
611 | |||
607 | static inline void ath9k_init_leds(struct ath9k_htc_priv *priv) | 612 | static inline void ath9k_init_leds(struct ath9k_htc_priv *priv) |
608 | { | 613 | { |
609 | } | 614 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index e0c03bd64182..8b5757734596 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -70,11 +70,11 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
70 | struct ath9k_beacon_state bs; | 70 | struct ath9k_beacon_state bs; |
71 | enum ath9k_int imask = 0; | 71 | enum ath9k_int imask = 0; |
72 | int dtimperiod, dtimcount, sleepduration; | 72 | int dtimperiod, dtimcount, sleepduration; |
73 | int cfpperiod, cfpcount, bmiss_timeout; | 73 | int bmiss_timeout; |
74 | u32 nexttbtt = 0, intval, tsftu; | 74 | u32 nexttbtt = 0, intval, tsftu; |
75 | __be32 htc_imask = 0; | 75 | __be32 htc_imask = 0; |
76 | u64 tsf; | 76 | u64 tsf; |
77 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; | 77 | int num_beacons, offset, dtim_dec_count; |
78 | int ret __attribute__ ((unused)); | 78 | int ret __attribute__ ((unused)); |
79 | u8 cmd_rsp; | 79 | u8 cmd_rsp; |
80 | 80 | ||
@@ -84,7 +84,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
84 | bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); | 84 | bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * Setup dtim and cfp parameters according to | 87 | * Setup dtim parameters according to |
88 | * last beacon we received (which may be none). | 88 | * last beacon we received (which may be none). |
89 | */ | 89 | */ |
90 | dtimperiod = bss_conf->dtim_period; | 90 | dtimperiod = bss_conf->dtim_period; |
@@ -93,8 +93,6 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
93 | dtimcount = 1; | 93 | dtimcount = 1; |
94 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | 94 | if (dtimcount >= dtimperiod) /* NB: sanity check */ |
95 | dtimcount = 0; | 95 | dtimcount = 0; |
96 | cfpperiod = 1; /* NB: no PCF support yet */ | ||
97 | cfpcount = 0; | ||
98 | 96 | ||
99 | sleepduration = intval; | 97 | sleepduration = intval; |
100 | if (sleepduration <= 0) | 98 | if (sleepduration <= 0) |
@@ -102,7 +100,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
102 | 100 | ||
103 | /* | 101 | /* |
104 | * Pull nexttbtt forward to reflect the current | 102 | * Pull nexttbtt forward to reflect the current |
105 | * TSF and calculate dtim+cfp state for the result. | 103 | * TSF and calculate dtim state for the result. |
106 | */ | 104 | */ |
107 | tsf = ath9k_hw_gettsf64(priv->ah); | 105 | tsf = ath9k_hw_gettsf64(priv->ah); |
108 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | 106 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; |
@@ -115,26 +113,14 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
115 | 113 | ||
116 | /* DTIM Beacon every dtimperiod Beacon */ | 114 | /* DTIM Beacon every dtimperiod Beacon */ |
117 | dtim_dec_count = num_beacons % dtimperiod; | 115 | dtim_dec_count = num_beacons % dtimperiod; |
118 | /* CFP every cfpperiod DTIM Beacon */ | ||
119 | cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; | ||
120 | if (dtim_dec_count) | ||
121 | cfp_dec_count++; | ||
122 | |||
123 | dtimcount -= dtim_dec_count; | 116 | dtimcount -= dtim_dec_count; |
124 | if (dtimcount < 0) | 117 | if (dtimcount < 0) |
125 | dtimcount += dtimperiod; | 118 | dtimcount += dtimperiod; |
126 | 119 | ||
127 | cfpcount -= cfp_dec_count; | 120 | bs.bs_intval = TU_TO_USEC(intval); |
128 | if (cfpcount < 0) | 121 | bs.bs_nexttbtt = TU_TO_USEC(nexttbtt); |
129 | cfpcount += cfpperiod; | 122 | bs.bs_dtimperiod = dtimperiod * bs.bs_intval; |
130 | 123 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount * bs.bs_intval; | |
131 | bs.bs_intval = intval; | ||
132 | bs.bs_nexttbtt = nexttbtt; | ||
133 | bs.bs_dtimperiod = dtimperiod*intval; | ||
134 | bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; | ||
135 | bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; | ||
136 | bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; | ||
137 | bs.bs_cfpmaxduration = 0; | ||
138 | 124 | ||
139 | /* | 125 | /* |
140 | * Calculate the number of consecutive beacons to miss* before taking | 126 | * Calculate the number of consecutive beacons to miss* before taking |
@@ -161,7 +147,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
161 | * XXX fixed at 100ms | 147 | * XXX fixed at 100ms |
162 | */ | 148 | */ |
163 | 149 | ||
164 | bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); | 150 | bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100), |
151 | sleepduration)); | ||
165 | if (bs.bs_sleepduration > bs.bs_dtimperiod) | 152 | if (bs.bs_sleepduration > bs.bs_dtimperiod) |
166 | bs.bs_sleepduration = bs.bs_dtimperiod; | 153 | bs.bs_sleepduration = bs.bs_dtimperiod; |
167 | 154 | ||
@@ -170,10 +157,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
170 | 157 | ||
171 | ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n", | 158 | ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n", |
172 | intval, tsf, tsftu); | 159 | intval, tsf, tsftu); |
173 | ath_dbg(common, CONFIG, | 160 | ath_dbg(common, CONFIG, "bmiss: %u sleep: %u\n", |
174 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | 161 | bs.bs_bmissthreshold, bs.bs_sleepduration); |
175 | bs.bs_bmissthreshold, bs.bs_sleepduration, | ||
176 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | ||
177 | 162 | ||
178 | /* Set the computed STA beacon timers */ | 163 | /* Set the computed STA beacon timers */ |
179 | 164 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 105582d6b714..50f74a2a4cf8 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -255,6 +255,17 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv) | |||
255 | cancel_work_sync(&priv->led_work); | 255 | cancel_work_sync(&priv->led_work); |
256 | } | 256 | } |
257 | 257 | ||
258 | |||
259 | void ath9k_configure_leds(struct ath9k_htc_priv *priv) | ||
260 | { | ||
261 | /* Configure gpio 1 for output */ | ||
262 | ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, | ||
263 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
264 | /* LED off, active low */ | ||
265 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); | ||
266 | |||
267 | } | ||
268 | |||
258 | void ath9k_init_leds(struct ath9k_htc_priv *priv) | 269 | void ath9k_init_leds(struct ath9k_htc_priv *priv) |
259 | { | 270 | { |
260 | int ret; | 271 | int ret; |
@@ -268,11 +279,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) | |||
268 | else | 279 | else |
269 | priv->ah->led_pin = ATH_LED_PIN_DEF; | 280 | priv->ah->led_pin = ATH_LED_PIN_DEF; |
270 | 281 | ||
271 | /* Configure gpio 1 for output */ | 282 | ath9k_configure_leds(priv); |
272 | ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, | ||
273 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
274 | /* LED off, active low */ | ||
275 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); | ||
276 | 283 | ||
277 | snprintf(priv->led_name, sizeof(priv->led_name), | 284 | snprintf(priv->led_name, sizeof(priv->led_name), |
278 | "ath9k_htc-%s", wiphy_name(priv->hw->wiphy)); | 285 | "ath9k_htc-%s", wiphy_name(priv->hw->wiphy)); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index c3676bf1d6c4..b576c44bb314 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -1000,6 +1000,8 @@ int ath9k_htc_resume(struct htc_target *htc_handle) | |||
1000 | 1000 | ||
1001 | ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid, | 1001 | ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid, |
1002 | priv->ah->hw_version.usbdev); | 1002 | priv->ah->hw_version.usbdev); |
1003 | ath9k_configure_leds(priv); | ||
1004 | |||
1003 | return ret; | 1005 | return ret; |
1004 | } | 1006 | } |
1005 | #endif | 1007 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 4f9378ddf07f..cc58a8ee1223 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -49,9 +49,10 @@ static inline bool ath9k_hw_calibrate(struct ath_hw *ah, | |||
49 | return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); | 49 | return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); |
50 | } | 50 | } |
51 | 51 | ||
52 | static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | 52 | static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked, |
53 | u32 *sync_cause_p) | ||
53 | { | 54 | { |
54 | return ath9k_hw_ops(ah)->get_isr(ah, masked); | 55 | return ath9k_hw_ops(ah)->get_isr(ah, masked, sync_cause_p); |
55 | } | 56 | } |
56 | 57 | ||
57 | static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds, | 58 | static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds, |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4ee24b1eec38..a4b1ae026216 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/time.h> | 20 | #include <linux/time.h> |
21 | #include <linux/bitops.h> | ||
21 | #include <asm/unaligned.h> | 22 | #include <asm/unaligned.h> |
22 | 23 | ||
23 | #include "hw.h" | 24 | #include "hw.h" |
@@ -84,48 +85,6 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
84 | 85 | ||
85 | #ifdef CONFIG_ATH9K_DEBUGFS | 86 | #ifdef CONFIG_ATH9K_DEBUGFS |
86 | 87 | ||
87 | void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause) | ||
88 | { | ||
89 | struct ath_softc *sc = common->priv; | ||
90 | if (sync_cause) | ||
91 | sc->debug.stats.istats.sync_cause_all++; | ||
92 | if (sync_cause & AR_INTR_SYNC_RTC_IRQ) | ||
93 | sc->debug.stats.istats.sync_rtc_irq++; | ||
94 | if (sync_cause & AR_INTR_SYNC_MAC_IRQ) | ||
95 | sc->debug.stats.istats.sync_mac_irq++; | ||
96 | if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS) | ||
97 | sc->debug.stats.istats.eeprom_illegal_access++; | ||
98 | if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT) | ||
99 | sc->debug.stats.istats.apb_timeout++; | ||
100 | if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT) | ||
101 | sc->debug.stats.istats.pci_mode_conflict++; | ||
102 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) | ||
103 | sc->debug.stats.istats.host1_fatal++; | ||
104 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) | ||
105 | sc->debug.stats.istats.host1_perr++; | ||
106 | if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR) | ||
107 | sc->debug.stats.istats.trcv_fifo_perr++; | ||
108 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP) | ||
109 | sc->debug.stats.istats.radm_cpl_ep++; | ||
110 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT) | ||
111 | sc->debug.stats.istats.radm_cpl_dllp_abort++; | ||
112 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT) | ||
113 | sc->debug.stats.istats.radm_cpl_tlp_abort++; | ||
114 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR) | ||
115 | sc->debug.stats.istats.radm_cpl_ecrc_err++; | ||
116 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) | ||
117 | sc->debug.stats.istats.radm_cpl_timeout++; | ||
118 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) | ||
119 | sc->debug.stats.istats.local_timeout++; | ||
120 | if (sync_cause & AR_INTR_SYNC_PM_ACCESS) | ||
121 | sc->debug.stats.istats.pm_access++; | ||
122 | if (sync_cause & AR_INTR_SYNC_MAC_AWAKE) | ||
123 | sc->debug.stats.istats.mac_awake++; | ||
124 | if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP) | ||
125 | sc->debug.stats.istats.mac_asleep++; | ||
126 | if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS) | ||
127 | sc->debug.stats.istats.mac_sleep_access++; | ||
128 | } | ||
129 | #endif | 88 | #endif |
130 | 89 | ||
131 | 90 | ||
@@ -438,21 +397,12 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
438 | 397 | ||
439 | static void ath9k_hw_init_config(struct ath_hw *ah) | 398 | static void ath9k_hw_init_config(struct ath_hw *ah) |
440 | { | 399 | { |
441 | int i; | ||
442 | |||
443 | ah->config.dma_beacon_response_time = 1; | 400 | ah->config.dma_beacon_response_time = 1; |
444 | ah->config.sw_beacon_response_time = 6; | 401 | ah->config.sw_beacon_response_time = 6; |
445 | ah->config.additional_swba_backoff = 0; | ||
446 | ah->config.ack_6mb = 0x0; | 402 | ah->config.ack_6mb = 0x0; |
447 | ah->config.cwm_ignore_extcca = 0; | 403 | ah->config.cwm_ignore_extcca = 0; |
448 | ah->config.pcie_clock_req = 0; | ||
449 | ah->config.analog_shiftreg = 1; | 404 | ah->config.analog_shiftreg = 1; |
450 | 405 | ||
451 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | ||
452 | ah->config.spurchans[i][0] = AR_NO_SPUR; | ||
453 | ah->config.spurchans[i][1] = AR_NO_SPUR; | ||
454 | } | ||
455 | |||
456 | ah->config.rx_intr_mitigation = true; | 406 | ah->config.rx_intr_mitigation = true; |
457 | 407 | ||
458 | /* | 408 | /* |
@@ -485,7 +435,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
485 | ah->hw_version.magic = AR5416_MAGIC; | 435 | ah->hw_version.magic = AR5416_MAGIC; |
486 | ah->hw_version.subvendorid = 0; | 436 | ah->hw_version.subvendorid = 0; |
487 | 437 | ||
488 | ah->atim_window = 0; | ||
489 | ah->sta_id1_defaults = | 438 | ah->sta_id1_defaults = |
490 | AR_STA_ID1_CRPT_MIC_ENABLE | | 439 | AR_STA_ID1_CRPT_MIC_ENABLE | |
491 | AR_STA_ID1_MCAST_KSRCH; | 440 | AR_STA_ID1_MCAST_KSRCH; |
@@ -1281,6 +1230,42 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, | |||
1281 | *coef_exponent = coef_exp - 16; | 1230 | *coef_exponent = coef_exp - 16; |
1282 | } | 1231 | } |
1283 | 1232 | ||
1233 | /* AR9330 WAR: | ||
1234 | * call external reset function to reset WMAC if: | ||
1235 | * - doing a cold reset | ||
1236 | * - we have pending frames in the TX queues. | ||
1237 | */ | ||
1238 | static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) | ||
1239 | { | ||
1240 | int i, npend = 0; | ||
1241 | |||
1242 | for (i = 0; i < AR_NUM_QCU; i++) { | ||
1243 | npend = ath9k_hw_numtxpending(ah, i); | ||
1244 | if (npend) | ||
1245 | break; | ||
1246 | } | ||
1247 | |||
1248 | if (ah->external_reset && | ||
1249 | (npend || type == ATH9K_RESET_COLD)) { | ||
1250 | int reset_err = 0; | ||
1251 | |||
1252 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1253 | "reset MAC via external reset\n"); | ||
1254 | |||
1255 | reset_err = ah->external_reset(); | ||
1256 | if (reset_err) { | ||
1257 | ath_err(ath9k_hw_common(ah), | ||
1258 | "External reset failed, err=%d\n", | ||
1259 | reset_err); | ||
1260 | return false; | ||
1261 | } | ||
1262 | |||
1263 | REG_WRITE(ah, AR_RTC_RESET, 1); | ||
1264 | } | ||
1265 | |||
1266 | return true; | ||
1267 | } | ||
1268 | |||
1284 | static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | 1269 | static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) |
1285 | { | 1270 | { |
1286 | u32 rst_flags; | 1271 | u32 rst_flags; |
@@ -1331,38 +1316,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1331 | } | 1316 | } |
1332 | 1317 | ||
1333 | if (AR_SREV_9330(ah)) { | 1318 | if (AR_SREV_9330(ah)) { |
1334 | int npend = 0; | 1319 | if (!ath9k_hw_ar9330_reset_war(ah, type)) |
1335 | int i; | 1320 | return false; |
1336 | |||
1337 | /* AR9330 WAR: | ||
1338 | * call external reset function to reset WMAC if: | ||
1339 | * - doing a cold reset | ||
1340 | * - we have pending frames in the TX queues | ||
1341 | */ | ||
1342 | |||
1343 | for (i = 0; i < AR_NUM_QCU; i++) { | ||
1344 | npend = ath9k_hw_numtxpending(ah, i); | ||
1345 | if (npend) | ||
1346 | break; | ||
1347 | } | ||
1348 | |||
1349 | if (ah->external_reset && | ||
1350 | (npend || type == ATH9K_RESET_COLD)) { | ||
1351 | int reset_err = 0; | ||
1352 | |||
1353 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1354 | "reset MAC via external reset\n"); | ||
1355 | |||
1356 | reset_err = ah->external_reset(); | ||
1357 | if (reset_err) { | ||
1358 | ath_err(ath9k_hw_common(ah), | ||
1359 | "External reset failed, err=%d\n", | ||
1360 | reset_err); | ||
1361 | return false; | ||
1362 | } | ||
1363 | |||
1364 | REG_WRITE(ah, AR_RTC_RESET, 1); | ||
1365 | } | ||
1366 | } | 1321 | } |
1367 | 1322 | ||
1368 | if (ath9k_hw_mci_is_enabled(ah)) | 1323 | if (ath9k_hw_mci_is_enabled(ah)) |
@@ -1372,7 +1327,12 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1372 | 1327 | ||
1373 | REGWRITE_BUFFER_FLUSH(ah); | 1328 | REGWRITE_BUFFER_FLUSH(ah); |
1374 | 1329 | ||
1375 | udelay(50); | 1330 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1331 | udelay(50); | ||
1332 | else if (AR_SREV_9100(ah)) | ||
1333 | udelay(10000); | ||
1334 | else | ||
1335 | udelay(100); | ||
1376 | 1336 | ||
1377 | REG_WRITE(ah, AR_RTC_RC, 0); | 1337 | REG_WRITE(ah, AR_RTC_RC, 0); |
1378 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { | 1338 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { |
@@ -1408,8 +1368,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1408 | 1368 | ||
1409 | REGWRITE_BUFFER_FLUSH(ah); | 1369 | REGWRITE_BUFFER_FLUSH(ah); |
1410 | 1370 | ||
1411 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 1371 | udelay(2); |
1412 | udelay(2); | ||
1413 | 1372 | ||
1414 | if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) | 1373 | if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) |
1415 | REG_WRITE(ah, AR_RC, 0); | 1374 | REG_WRITE(ah, AR_RC, 0); |
@@ -1485,7 +1444,6 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, | |||
1485 | if (AR_SREV_9330(ah)) | 1444 | if (AR_SREV_9330(ah)) |
1486 | ar9003_hw_internal_regulator_apply(ah); | 1445 | ar9003_hw_internal_regulator_apply(ah); |
1487 | ath9k_hw_init_pll(ah, chan); | 1446 | ath9k_hw_init_pll(ah, chan); |
1488 | ath9k_hw_set_rfmode(ah, chan); | ||
1489 | 1447 | ||
1490 | return true; | 1448 | return true; |
1491 | } | 1449 | } |
@@ -1954,6 +1912,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1954 | if (r) | 1912 | if (r) |
1955 | return r; | 1913 | return r; |
1956 | 1914 | ||
1915 | ath9k_hw_set_rfmode(ah, chan); | ||
1916 | |||
1957 | if (ath9k_hw_mci_is_enabled(ah)) | 1917 | if (ath9k_hw_mci_is_enabled(ah)) |
1958 | ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); | 1918 | ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); |
1959 | 1919 | ||
@@ -2264,9 +2224,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) | |||
2264 | case NL80211_IFTYPE_ADHOC: | 2224 | case NL80211_IFTYPE_ADHOC: |
2265 | REG_SET_BIT(ah, AR_TXCFG, | 2225 | REG_SET_BIT(ah, AR_TXCFG, |
2266 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); | 2226 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); |
2267 | REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon + | ||
2268 | TU_TO_USEC(ah->atim_window ? ah->atim_window : 1)); | ||
2269 | flags |= AR_NDP_TIMER_EN; | ||
2270 | case NL80211_IFTYPE_MESH_POINT: | 2227 | case NL80211_IFTYPE_MESH_POINT: |
2271 | case NL80211_IFTYPE_AP: | 2228 | case NL80211_IFTYPE_AP: |
2272 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); | 2229 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); |
@@ -2287,7 +2244,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) | |||
2287 | REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); | 2244 | REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); |
2288 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); | 2245 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); |
2289 | REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); | 2246 | REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); |
2290 | REG_WRITE(ah, AR_NDP_PERIOD, beacon_period); | ||
2291 | 2247 | ||
2292 | REGWRITE_BUFFER_FLUSH(ah); | 2248 | REGWRITE_BUFFER_FLUSH(ah); |
2293 | 2249 | ||
@@ -2304,12 +2260,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
2304 | 2260 | ||
2305 | ENABLE_REGWRITE_BUFFER(ah); | 2261 | ENABLE_REGWRITE_BUFFER(ah); |
2306 | 2262 | ||
2307 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); | 2263 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, bs->bs_nexttbtt); |
2308 | 2264 | REG_WRITE(ah, AR_BEACON_PERIOD, bs->bs_intval); | |
2309 | REG_WRITE(ah, AR_BEACON_PERIOD, | 2265 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bs->bs_intval); |
2310 | TU_TO_USEC(bs->bs_intval)); | ||
2311 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, | ||
2312 | TU_TO_USEC(bs->bs_intval)); | ||
2313 | 2266 | ||
2314 | REGWRITE_BUFFER_FLUSH(ah); | 2267 | REGWRITE_BUFFER_FLUSH(ah); |
2315 | 2268 | ||
@@ -2337,9 +2290,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
2337 | 2290 | ||
2338 | ENABLE_REGWRITE_BUFFER(ah); | 2291 | ENABLE_REGWRITE_BUFFER(ah); |
2339 | 2292 | ||
2340 | REG_WRITE(ah, AR_NEXT_DTIM, | 2293 | REG_WRITE(ah, AR_NEXT_DTIM, bs->bs_nextdtim - SLEEP_SLOP); |
2341 | TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); | 2294 | REG_WRITE(ah, AR_NEXT_TIM, nextTbtt - SLEEP_SLOP); |
2342 | REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); | ||
2343 | 2295 | ||
2344 | REG_WRITE(ah, AR_SLEEP1, | 2296 | REG_WRITE(ah, AR_SLEEP1, |
2345 | SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) | 2297 | SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) |
@@ -2353,8 +2305,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
2353 | REG_WRITE(ah, AR_SLEEP2, | 2305 | REG_WRITE(ah, AR_SLEEP2, |
2354 | SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); | 2306 | SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); |
2355 | 2307 | ||
2356 | REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); | 2308 | REG_WRITE(ah, AR_TIM_PERIOD, beaconintval); |
2357 | REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); | 2309 | REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod); |
2358 | 2310 | ||
2359 | REGWRITE_BUFFER_FLUSH(ah); | 2311 | REGWRITE_BUFFER_FLUSH(ah); |
2360 | 2312 | ||
@@ -2990,20 +2942,6 @@ static const struct ath_gen_timer_configuration gen_tmr_configuration[] = | |||
2990 | 2942 | ||
2991 | /* HW generic timer primitives */ | 2943 | /* HW generic timer primitives */ |
2992 | 2944 | ||
2993 | /* compute and clear index of rightmost 1 */ | ||
2994 | static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) | ||
2995 | { | ||
2996 | u32 b; | ||
2997 | |||
2998 | b = *mask; | ||
2999 | b &= (0-b); | ||
3000 | *mask &= ~b; | ||
3001 | b *= debruijn32; | ||
3002 | b >>= 27; | ||
3003 | |||
3004 | return timer_table->gen_timer_index[b]; | ||
3005 | } | ||
3006 | |||
3007 | u32 ath9k_hw_gettsf32(struct ath_hw *ah) | 2945 | u32 ath9k_hw_gettsf32(struct ath_hw *ah) |
3008 | { | 2946 | { |
3009 | return REG_READ(ah, AR_TSF_L32); | 2947 | return REG_READ(ah, AR_TSF_L32); |
@@ -3019,6 +2957,10 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | |||
3019 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 2957 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
3020 | struct ath_gen_timer *timer; | 2958 | struct ath_gen_timer *timer; |
3021 | 2959 | ||
2960 | if ((timer_index < AR_FIRST_NDP_TIMER) || | ||
2961 | (timer_index >= ATH_MAX_GEN_TIMER)) | ||
2962 | return NULL; | ||
2963 | |||
3022 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); | 2964 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); |
3023 | if (timer == NULL) | 2965 | if (timer == NULL) |
3024 | return NULL; | 2966 | return NULL; |
@@ -3036,23 +2978,13 @@ EXPORT_SYMBOL(ath_gen_timer_alloc); | |||
3036 | 2978 | ||
3037 | void ath9k_hw_gen_timer_start(struct ath_hw *ah, | 2979 | void ath9k_hw_gen_timer_start(struct ath_hw *ah, |
3038 | struct ath_gen_timer *timer, | 2980 | struct ath_gen_timer *timer, |
3039 | u32 trig_timeout, | 2981 | u32 timer_next, |
3040 | u32 timer_period) | 2982 | u32 timer_period) |
3041 | { | 2983 | { |
3042 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 2984 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
3043 | u32 tsf, timer_next; | 2985 | u32 mask = 0; |
3044 | |||
3045 | BUG_ON(!timer_period); | ||
3046 | |||
3047 | set_bit(timer->index, &timer_table->timer_mask.timer_bits); | ||
3048 | |||
3049 | tsf = ath9k_hw_gettsf32(ah); | ||
3050 | 2986 | ||
3051 | timer_next = tsf + trig_timeout; | 2987 | timer_table->timer_mask |= BIT(timer->index); |
3052 | |||
3053 | ath_dbg(ath9k_hw_common(ah), BTCOEX, | ||
3054 | "current tsf %x period %x timer_next %x\n", | ||
3055 | tsf, timer_period, timer_next); | ||
3056 | 2988 | ||
3057 | /* | 2989 | /* |
3058 | * Program generic timer registers | 2990 | * Program generic timer registers |
@@ -3078,10 +3010,19 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, | |||
3078 | (1 << timer->index)); | 3010 | (1 << timer->index)); |
3079 | } | 3011 | } |
3080 | 3012 | ||
3081 | /* Enable both trigger and thresh interrupt masks */ | 3013 | if (timer->trigger) |
3082 | REG_SET_BIT(ah, AR_IMR_S5, | 3014 | mask |= SM(AR_GENTMR_BIT(timer->index), |
3083 | (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | | 3015 | AR_IMR_S5_GENTIMER_TRIG); |
3084 | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); | 3016 | if (timer->overflow) |
3017 | mask |= SM(AR_GENTMR_BIT(timer->index), | ||
3018 | AR_IMR_S5_GENTIMER_THRESH); | ||
3019 | |||
3020 | REG_SET_BIT(ah, AR_IMR_S5, mask); | ||
3021 | |||
3022 | if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { | ||
3023 | ah->imask |= ATH9K_INT_GENTIMER; | ||
3024 | ath9k_hw_set_interrupts(ah); | ||
3025 | } | ||
3085 | } | 3026 | } |
3086 | EXPORT_SYMBOL(ath9k_hw_gen_timer_start); | 3027 | EXPORT_SYMBOL(ath9k_hw_gen_timer_start); |
3087 | 3028 | ||
@@ -3089,11 +3030,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
3089 | { | 3030 | { |
3090 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 3031 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
3091 | 3032 | ||
3092 | if ((timer->index < AR_FIRST_NDP_TIMER) || | ||
3093 | (timer->index >= ATH_MAX_GEN_TIMER)) { | ||
3094 | return; | ||
3095 | } | ||
3096 | |||
3097 | /* Clear generic timer enable bits. */ | 3033 | /* Clear generic timer enable bits. */ |
3098 | REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, | 3034 | REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, |
3099 | gen_tmr_configuration[timer->index].mode_mask); | 3035 | gen_tmr_configuration[timer->index].mode_mask); |
@@ -3113,7 +3049,12 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
3113 | (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | | 3049 | (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | |
3114 | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); | 3050 | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); |
3115 | 3051 | ||
3116 | clear_bit(timer->index, &timer_table->timer_mask.timer_bits); | 3052 | timer_table->timer_mask &= ~BIT(timer->index); |
3053 | |||
3054 | if (timer_table->timer_mask == 0) { | ||
3055 | ah->imask &= ~ATH9K_INT_GENTIMER; | ||
3056 | ath9k_hw_set_interrupts(ah); | ||
3057 | } | ||
3117 | } | 3058 | } |
3118 | EXPORT_SYMBOL(ath9k_hw_gen_timer_stop); | 3059 | EXPORT_SYMBOL(ath9k_hw_gen_timer_stop); |
3119 | 3060 | ||
@@ -3134,32 +3075,32 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
3134 | { | 3075 | { |
3135 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 3076 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
3136 | struct ath_gen_timer *timer; | 3077 | struct ath_gen_timer *timer; |
3137 | struct ath_common *common = ath9k_hw_common(ah); | 3078 | unsigned long trigger_mask, thresh_mask; |
3138 | u32 trigger_mask, thresh_mask, index; | 3079 | unsigned int index; |
3139 | 3080 | ||
3140 | /* get hardware generic timer interrupt status */ | 3081 | /* get hardware generic timer interrupt status */ |
3141 | trigger_mask = ah->intr_gen_timer_trigger; | 3082 | trigger_mask = ah->intr_gen_timer_trigger; |
3142 | thresh_mask = ah->intr_gen_timer_thresh; | 3083 | thresh_mask = ah->intr_gen_timer_thresh; |
3143 | trigger_mask &= timer_table->timer_mask.val; | 3084 | trigger_mask &= timer_table->timer_mask; |
3144 | thresh_mask &= timer_table->timer_mask.val; | 3085 | thresh_mask &= timer_table->timer_mask; |
3145 | 3086 | ||
3146 | trigger_mask &= ~thresh_mask; | 3087 | trigger_mask &= ~thresh_mask; |
3147 | 3088 | ||
3148 | while (thresh_mask) { | 3089 | for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) { |
3149 | index = rightmost_index(timer_table, &thresh_mask); | ||
3150 | timer = timer_table->timers[index]; | 3090 | timer = timer_table->timers[index]; |
3151 | BUG_ON(!timer); | 3091 | if (!timer) |
3152 | ath_dbg(common, BTCOEX, "TSF overflow for Gen timer %d\n", | 3092 | continue; |
3153 | index); | 3093 | if (!timer->overflow) |
3094 | continue; | ||
3154 | timer->overflow(timer->arg); | 3095 | timer->overflow(timer->arg); |
3155 | } | 3096 | } |
3156 | 3097 | ||
3157 | while (trigger_mask) { | 3098 | for_each_set_bit(index, &trigger_mask, ARRAY_SIZE(timer_table->timers)) { |
3158 | index = rightmost_index(timer_table, &trigger_mask); | ||
3159 | timer = timer_table->timers[index]; | 3099 | timer = timer_table->timers[index]; |
3160 | BUG_ON(!timer); | 3100 | if (!timer) |
3161 | ath_dbg(common, BTCOEX, | 3101 | continue; |
3162 | "Gen timer[%d] trigger\n", index); | 3102 | if (!timer->trigger) |
3103 | continue; | ||
3163 | timer->trigger(timer->arg); | 3104 | timer->trigger(timer->arg); |
3164 | } | 3105 | } |
3165 | } | 3106 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b1ff54631dca..6132ffeb3048 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -168,7 +168,7 @@ | |||
168 | #define CAB_TIMEOUT_VAL 10 | 168 | #define CAB_TIMEOUT_VAL 10 |
169 | #define BEACON_TIMEOUT_VAL 10 | 169 | #define BEACON_TIMEOUT_VAL 10 |
170 | #define MIN_BEACON_TIMEOUT_VAL 1 | 170 | #define MIN_BEACON_TIMEOUT_VAL 1 |
171 | #define SLEEP_SLOP 3 | 171 | #define SLEEP_SLOP TU_TO_USEC(3) |
172 | 172 | ||
173 | #define INIT_CONFIG_STATUS 0x00000000 | 173 | #define INIT_CONFIG_STATUS 0x00000000 |
174 | #define INIT_RSSI_THR 0x00000700 | 174 | #define INIT_RSSI_THR 0x00000700 |
@@ -280,10 +280,8 @@ struct ath9k_hw_capabilities { | |||
280 | struct ath9k_ops_config { | 280 | struct ath9k_ops_config { |
281 | int dma_beacon_response_time; | 281 | int dma_beacon_response_time; |
282 | int sw_beacon_response_time; | 282 | int sw_beacon_response_time; |
283 | int additional_swba_backoff; | ||
284 | int ack_6mb; | 283 | int ack_6mb; |
285 | u32 cwm_ignore_extcca; | 284 | u32 cwm_ignore_extcca; |
286 | u8 pcie_clock_req; | ||
287 | u32 pcie_waen; | 285 | u32 pcie_waen; |
288 | u8 analog_shiftreg; | 286 | u8 analog_shiftreg; |
289 | u32 ofdm_trig_low; | 287 | u32 ofdm_trig_low; |
@@ -294,18 +292,11 @@ struct ath9k_ops_config { | |||
294 | int serialize_regmode; | 292 | int serialize_regmode; |
295 | bool rx_intr_mitigation; | 293 | bool rx_intr_mitigation; |
296 | bool tx_intr_mitigation; | 294 | bool tx_intr_mitigation; |
297 | #define SPUR_DISABLE 0 | ||
298 | #define SPUR_ENABLE_IOCTL 1 | ||
299 | #define SPUR_ENABLE_EEPROM 2 | ||
300 | #define AR_SPUR_5413_1 1640 | ||
301 | #define AR_SPUR_5413_2 1200 | ||
302 | #define AR_NO_SPUR 0x8000 | 295 | #define AR_NO_SPUR 0x8000 |
303 | #define AR_BASE_FREQ_2GHZ 2300 | 296 | #define AR_BASE_FREQ_2GHZ 2300 |
304 | #define AR_BASE_FREQ_5GHZ 4900 | 297 | #define AR_BASE_FREQ_5GHZ 4900 |
305 | #define AR_SPUR_FEEQ_BOUND_HT40 19 | 298 | #define AR_SPUR_FEEQ_BOUND_HT40 19 |
306 | #define AR_SPUR_FEEQ_BOUND_HT20 10 | 299 | #define AR_SPUR_FEEQ_BOUND_HT20 10 |
307 | int spurmode; | ||
308 | u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; | ||
309 | u8 max_txtrig_level; | 300 | u8 max_txtrig_level; |
310 | u16 ani_poll_interval; /* ANI poll interval in ms */ | 301 | u16 ani_poll_interval; /* ANI poll interval in ms */ |
311 | 302 | ||
@@ -460,10 +451,6 @@ struct ath9k_beacon_state { | |||
460 | u32 bs_intval; | 451 | u32 bs_intval; |
461 | #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ | 452 | #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ |
462 | u32 bs_dtimperiod; | 453 | u32 bs_dtimperiod; |
463 | u16 bs_cfpperiod; | ||
464 | u16 bs_cfpmaxduration; | ||
465 | u32 bs_cfpnext; | ||
466 | u16 bs_timoffset; | ||
467 | u16 bs_bmissthreshold; | 454 | u16 bs_bmissthreshold; |
468 | u32 bs_sleepduration; | 455 | u32 bs_sleepduration; |
469 | u32 bs_tsfoor_threshold; | 456 | u32 bs_tsfoor_threshold; |
@@ -499,12 +486,6 @@ struct ath9k_hw_version { | |||
499 | 486 | ||
500 | #define AR_GENTMR_BIT(_index) (1 << (_index)) | 487 | #define AR_GENTMR_BIT(_index) (1 << (_index)) |
501 | 488 | ||
502 | /* | ||
503 | * Using de Bruijin sequence to look up 1's index in a 32 bit number | ||
504 | * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001 | ||
505 | */ | ||
506 | #define debruijn32 0x077CB531U | ||
507 | |||
508 | struct ath_gen_timer_configuration { | 489 | struct ath_gen_timer_configuration { |
509 | u32 next_addr; | 490 | u32 next_addr; |
510 | u32 period_addr; | 491 | u32 period_addr; |
@@ -520,12 +501,8 @@ struct ath_gen_timer { | |||
520 | }; | 501 | }; |
521 | 502 | ||
522 | struct ath_gen_timer_table { | 503 | struct ath_gen_timer_table { |
523 | u32 gen_timer_index[32]; | ||
524 | struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER]; | 504 | struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER]; |
525 | union { | 505 | u16 timer_mask; |
526 | unsigned long timer_bits; | ||
527 | u16 val; | ||
528 | } timer_mask; | ||
529 | }; | 506 | }; |
530 | 507 | ||
531 | struct ath_hw_antcomb_conf { | 508 | struct ath_hw_antcomb_conf { |
@@ -690,7 +667,8 @@ struct ath_hw_ops { | |||
690 | struct ath9k_channel *chan, | 667 | struct ath9k_channel *chan, |
691 | u8 rxchainmask, | 668 | u8 rxchainmask, |
692 | bool longcal); | 669 | bool longcal); |
693 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); | 670 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked, |
671 | u32 *sync_cause_p); | ||
694 | void (*set_txdesc)(struct ath_hw *ah, void *ds, | 672 | void (*set_txdesc)(struct ath_hw *ah, void *ds, |
695 | struct ath_tx_info *i); | 673 | struct ath_tx_info *i); |
696 | int (*proc_txdesc)(struct ath_hw *ah, void *ds, | 674 | int (*proc_txdesc)(struct ath_hw *ah, void *ds, |
@@ -786,7 +764,6 @@ struct ath_hw { | |||
786 | u32 txurn_interrupt_mask; | 764 | u32 txurn_interrupt_mask; |
787 | atomic_t intr_ref_cnt; | 765 | atomic_t intr_ref_cnt; |
788 | bool chip_fullsleep; | 766 | bool chip_fullsleep; |
789 | u32 atim_window; | ||
790 | u32 modes_index; | 767 | u32 modes_index; |
791 | 768 | ||
792 | /* Calibration */ | 769 | /* Calibration */ |
@@ -1018,13 +995,6 @@ bool ath9k_hw_check_alive(struct ath_hw *ah); | |||
1018 | 995 | ||
1019 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); | 996 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); |
1020 | 997 | ||
1021 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
1022 | void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause); | ||
1023 | #else | ||
1024 | static inline void ath9k_debug_sync_cause(struct ath_common *common, | ||
1025 | u32 sync_cause) {} | ||
1026 | #endif | ||
1027 | |||
1028 | /* Generic hw timer primitives */ | 998 | /* Generic hw timer primitives */ |
1029 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | 999 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, |
1030 | void (*trigger)(void *), | 1000 | void (*trigger)(void *), |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 609b7e13f3f0..e63465b7eab9 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -470,7 +470,6 @@ static int ath9k_init_queues(struct ath_softc *sc) | |||
470 | 470 | ||
471 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); | 471 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); |
472 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | 472 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); |
473 | |||
474 | ath_cabq_update(sc); | 473 | ath_cabq_update(sc); |
475 | 474 | ||
476 | sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); | 475 | sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); |
@@ -705,7 +704,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
705 | ah->reg_ops.read = ath9k_ioread32; | 704 | ah->reg_ops.read = ath9k_ioread32; |
706 | ah->reg_ops.write = ath9k_iowrite32; | 705 | ah->reg_ops.write = ath9k_iowrite32; |
707 | ah->reg_ops.rmw = ath9k_reg_rmw; | 706 | ah->reg_ops.rmw = ath9k_reg_rmw; |
708 | atomic_set(&ah->intr_ref_cnt, -1); | ||
709 | sc->sc_ah = ah; | 707 | sc->sc_ah = ah; |
710 | pCap = &ah->caps; | 708 | pCap = &ah->caps; |
711 | 709 | ||
@@ -899,7 +897,7 @@ static const struct ieee80211_iface_combination if_comb[] = { | |||
899 | } | 897 | } |
900 | }; | 898 | }; |
901 | 899 | ||
902 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 900 | static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
903 | { | 901 | { |
904 | struct ath_hw *ah = sc->sc_ah; | 902 | struct ath_hw *ah = sc->sc_ah; |
905 | struct ath_common *common = ath9k_hw_common(ah); | 903 | struct ath_common *common = ath9k_hw_common(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 6a18f9d3e9cc..89d7e206992b 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -481,8 +481,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
481 | | AR_Q_MISC_CBR_INCR_DIS0); | 481 | | AR_Q_MISC_CBR_INCR_DIS0); |
482 | value = (qi->tqi_readyTime - | 482 | value = (qi->tqi_readyTime - |
483 | (ah->config.sw_beacon_response_time - | 483 | (ah->config.sw_beacon_response_time - |
484 | ah->config.dma_beacon_response_time) - | 484 | ah->config.dma_beacon_response_time)) * 1024; |
485 | ah->config.additional_swba_backoff) * 1024; | ||
486 | REG_WRITE(ah, AR_QRDYTIMECFG(q), | 485 | REG_WRITE(ah, AR_QRDYTIMECFG(q), |
487 | value | AR_Q_RDYTIMECFG_EN); | 486 | value | AR_Q_RDYTIMECFG_EN); |
488 | REG_SET_BIT(ah, AR_DMISC(q), | 487 | REG_SET_BIT(ah, AR_DMISC(q), |
@@ -550,25 +549,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
550 | 549 | ||
551 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { | 550 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { |
552 | rs->rs_rssi = ATH9K_RSSI_BAD; | 551 | rs->rs_rssi = ATH9K_RSSI_BAD; |
553 | rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD; | 552 | rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD; |
554 | rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD; | 553 | rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD; |
555 | rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD; | 554 | rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD; |
556 | rs->rs_rssi_ext0 = ATH9K_RSSI_BAD; | 555 | rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD; |
557 | rs->rs_rssi_ext1 = ATH9K_RSSI_BAD; | 556 | rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD; |
558 | rs->rs_rssi_ext2 = ATH9K_RSSI_BAD; | 557 | rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD; |
559 | } else { | 558 | } else { |
560 | rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); | 559 | rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); |
561 | rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0, | 560 | rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0, |
562 | AR_RxRSSIAnt00); | 561 | AR_RxRSSIAnt00); |
563 | rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0, | 562 | rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0, |
564 | AR_RxRSSIAnt01); | 563 | AR_RxRSSIAnt01); |
565 | rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0, | 564 | rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0, |
566 | AR_RxRSSIAnt02); | 565 | AR_RxRSSIAnt02); |
567 | rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4, | 566 | rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4, |
568 | AR_RxRSSIAnt10); | 567 | AR_RxRSSIAnt10); |
569 | rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4, | 568 | rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4, |
570 | AR_RxRSSIAnt11); | 569 | AR_RxRSSIAnt11); |
571 | rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4, | 570 | rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4, |
572 | AR_RxRSSIAnt12); | 571 | AR_RxRSSIAnt12); |
573 | } | 572 | } |
574 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) | 573 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index e3eed81f2439..10271373a0cd 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -133,12 +133,8 @@ struct ath_rx_status { | |||
133 | u8 rs_rate; | 133 | u8 rs_rate; |
134 | u8 rs_antenna; | 134 | u8 rs_antenna; |
135 | u8 rs_more; | 135 | u8 rs_more; |
136 | int8_t rs_rssi_ctl0; | 136 | int8_t rs_rssi_ctl[3]; |
137 | int8_t rs_rssi_ctl1; | 137 | int8_t rs_rssi_ext[3]; |
138 | int8_t rs_rssi_ctl2; | ||
139 | int8_t rs_rssi_ext0; | ||
140 | int8_t rs_rssi_ext1; | ||
141 | int8_t rs_rssi_ext2; | ||
142 | u8 rs_isaggr; | 138 | u8 rs_isaggr; |
143 | u8 rs_firstaggr; | 139 | u8 rs_firstaggr; |
144 | u8 rs_moreaggr; | 140 | u8 rs_moreaggr; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index b1dcf89138d3..173a889f9dbb 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -508,6 +508,9 @@ void ath9k_tasklet(unsigned long data) | |||
508 | wake_up(&sc->tx_wait); | 508 | wake_up(&sc->tx_wait); |
509 | } | 509 | } |
510 | 510 | ||
511 | if (status & ATH9K_INT_GENTIMER) | ||
512 | ath_gen_timer_isr(sc->sc_ah); | ||
513 | |||
511 | ath9k_btcoex_handle_interrupt(sc, status); | 514 | ath9k_btcoex_handle_interrupt(sc, status); |
512 | 515 | ||
513 | /* re-enable hardware interrupt */ | 516 | /* re-enable hardware interrupt */ |
@@ -538,6 +541,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
538 | struct ath_hw *ah = sc->sc_ah; | 541 | struct ath_hw *ah = sc->sc_ah; |
539 | struct ath_common *common = ath9k_hw_common(ah); | 542 | struct ath_common *common = ath9k_hw_common(ah); |
540 | enum ath9k_int status; | 543 | enum ath9k_int status; |
544 | u32 sync_cause; | ||
541 | bool sched = false; | 545 | bool sched = false; |
542 | 546 | ||
543 | /* | 547 | /* |
@@ -564,7 +568,8 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
564 | * bits we haven't explicitly enabled so we mask the | 568 | * bits we haven't explicitly enabled so we mask the |
565 | * value to insure we only process bits we requested. | 569 | * value to insure we only process bits we requested. |
566 | */ | 570 | */ |
567 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ | 571 | ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */ |
572 | ath9k_debug_sync_cause(sc, sync_cause); | ||
568 | status &= ah->imask; /* discard unasked-for bits */ | 573 | status &= ah->imask; /* discard unasked-for bits */ |
569 | 574 | ||
570 | /* | 575 | /* |
@@ -757,6 +762,8 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
757 | */ | 762 | */ |
758 | ath9k_cmn_init_crypto(sc->sc_ah); | 763 | ath9k_cmn_init_crypto(sc->sc_ah); |
759 | 764 | ||
765 | ath9k_hw_reset_tsf(ah); | ||
766 | |||
760 | spin_unlock_bh(&sc->sc_pcu_lock); | 767 | spin_unlock_bh(&sc->sc_pcu_lock); |
761 | 768 | ||
762 | mutex_unlock(&sc->mutex); | 769 | mutex_unlock(&sc->mutex); |
@@ -1657,13 +1664,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1657 | } | 1664 | } |
1658 | 1665 | ||
1659 | if ((changed & BSS_CHANGED_BEACON_ENABLED) || | 1666 | if ((changed & BSS_CHANGED_BEACON_ENABLED) || |
1660 | (changed & BSS_CHANGED_BEACON_INT)) { | 1667 | (changed & BSS_CHANGED_BEACON_INT)) |
1661 | if (ah->opmode == NL80211_IFTYPE_AP && | 1668 | ath9k_beacon_config(sc, vif, changed); |
1662 | bss_conf->enable_beacon) | ||
1663 | ath9k_set_tsfadjust(sc, vif); | ||
1664 | if (ath9k_allow_beacon_config(sc, vif)) | ||
1665 | ath9k_beacon_config(sc, vif, changed); | ||
1666 | } | ||
1667 | 1669 | ||
1668 | if (changed & BSS_CHANGED_ERP_SLOT) { | 1670 | if (changed & BSS_CHANGED_ERP_SLOT) { |
1669 | if (bss_conf->use_short_slot) | 1671 | if (bss_conf->use_short_slot) |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 0ac1b5f04256..71799fcade54 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -200,7 +200,7 @@ skip_tuning: | |||
200 | if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE) | 200 | if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE) |
201 | btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE; | 201 | btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE; |
202 | 202 | ||
203 | btcoex->btcoex_no_stomp = btcoex->btcoex_period * 1000 * | 203 | btcoex->btcoex_no_stomp = btcoex->btcoex_period * |
204 | (100 - btcoex->duty_cycle) / 100; | 204 | (100 - btcoex->duty_cycle) / 100; |
205 | 205 | ||
206 | ath9k_hw_btcoex_enable(sc->sc_ah); | 206 | ath9k_hw_btcoex_enable(sc->sc_ah); |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 95ddca5495d4..3692b2a501a2 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/dma-mapping.h> | 17 | #include <linux/dma-mapping.h> |
18 | #include <linux/relay.h> | ||
19 | #include "ath9k.h" | 18 | #include "ath9k.h" |
20 | #include "ar9003_mac.h" | 19 | #include "ar9003_mac.h" |
21 | 20 | ||
@@ -906,6 +905,7 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
906 | struct ath_hw *ah = common->ah; | 905 | struct ath_hw *ah = common->ah; |
907 | int last_rssi; | 906 | int last_rssi; |
908 | int rssi = rx_stats->rs_rssi; | 907 | int rssi = rx_stats->rs_rssi; |
908 | int i, j; | ||
909 | 909 | ||
910 | /* | 910 | /* |
911 | * RSSI is not available for subframes in an A-MPDU. | 911 | * RSSI is not available for subframes in an A-MPDU. |
@@ -924,6 +924,20 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
924 | return; | 924 | return; |
925 | } | 925 | } |
926 | 926 | ||
927 | for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) { | ||
928 | s8 rssi; | ||
929 | |||
930 | if (!(ah->rxchainmask & BIT(i))) | ||
931 | continue; | ||
932 | |||
933 | rssi = rx_stats->rs_rssi_ctl[i]; | ||
934 | if (rssi != ATH9K_RSSI_BAD) { | ||
935 | rxs->chains |= BIT(j); | ||
936 | rxs->chain_signal[j] = ah->noise + rssi; | ||
937 | } | ||
938 | j++; | ||
939 | } | ||
940 | |||
927 | /* | 941 | /* |
928 | * Update Beacon RSSI, this is used by ANI. | 942 | * Update Beacon RSSI, this is used by ANI. |
929 | */ | 943 | */ |
@@ -960,186 +974,6 @@ static void ath9k_process_tsf(struct ath_rx_status *rs, | |||
960 | rxs->mactime += 0x100000000ULL; | 974 | rxs->mactime += 0x100000000ULL; |
961 | } | 975 | } |
962 | 976 | ||
963 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
964 | static s8 fix_rssi_inv_only(u8 rssi_val) | ||
965 | { | ||
966 | if (rssi_val == 128) | ||
967 | rssi_val = 0; | ||
968 | return (s8) rssi_val; | ||
969 | } | ||
970 | #endif | ||
971 | |||
972 | /* returns 1 if this was a spectral frame, even if not handled. */ | ||
973 | static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | ||
974 | struct ath_rx_status *rs, u64 tsf) | ||
975 | { | ||
976 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
977 | struct ath_hw *ah = sc->sc_ah; | ||
978 | u8 num_bins, *bins, *vdata = (u8 *)hdr; | ||
979 | struct fft_sample_ht20 fft_sample_20; | ||
980 | struct fft_sample_ht20_40 fft_sample_40; | ||
981 | struct fft_sample_tlv *tlv; | ||
982 | struct ath_radar_info *radar_info; | ||
983 | int len = rs->rs_datalen; | ||
984 | int dc_pos; | ||
985 | u16 fft_len, length, freq = ah->curchan->chan->center_freq; | ||
986 | enum nl80211_channel_type chan_type; | ||
987 | |||
988 | /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer | ||
989 | * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT | ||
990 | * yet, but this is supposed to be possible as well. | ||
991 | */ | ||
992 | if (rs->rs_phyerr != ATH9K_PHYERR_RADAR && | ||
993 | rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT && | ||
994 | rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL) | ||
995 | return 0; | ||
996 | |||
997 | /* check if spectral scan bit is set. This does not have to be checked | ||
998 | * if received through a SPECTRAL phy error, but shouldn't hurt. | ||
999 | */ | ||
1000 | radar_info = ((struct ath_radar_info *)&vdata[len]) - 1; | ||
1001 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) | ||
1002 | return 0; | ||
1003 | |||
1004 | chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef); | ||
1005 | if ((chan_type == NL80211_CHAN_HT40MINUS) || | ||
1006 | (chan_type == NL80211_CHAN_HT40PLUS)) { | ||
1007 | fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; | ||
1008 | num_bins = SPECTRAL_HT20_40_NUM_BINS; | ||
1009 | bins = (u8 *)fft_sample_40.data; | ||
1010 | } else { | ||
1011 | fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN; | ||
1012 | num_bins = SPECTRAL_HT20_NUM_BINS; | ||
1013 | bins = (u8 *)fft_sample_20.data; | ||
1014 | } | ||
1015 | |||
1016 | /* Variation in the data length is possible and will be fixed later */ | ||
1017 | if ((len > fft_len + 2) || (len < fft_len - 1)) | ||
1018 | return 1; | ||
1019 | |||
1020 | switch (len - fft_len) { | ||
1021 | case 0: | ||
1022 | /* length correct, nothing to do. */ | ||
1023 | memcpy(bins, vdata, num_bins); | ||
1024 | break; | ||
1025 | case -1: | ||
1026 | /* first byte missing, duplicate it. */ | ||
1027 | memcpy(&bins[1], vdata, num_bins - 1); | ||
1028 | bins[0] = vdata[0]; | ||
1029 | break; | ||
1030 | case 2: | ||
1031 | /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ | ||
1032 | memcpy(bins, vdata, 30); | ||
1033 | bins[30] = vdata[31]; | ||
1034 | memcpy(&bins[31], &vdata[33], num_bins - 31); | ||
1035 | break; | ||
1036 | case 1: | ||
1037 | /* MAC added 2 extra bytes AND first byte is missing. */ | ||
1038 | bins[0] = vdata[0]; | ||
1039 | memcpy(&bins[1], vdata, 30); | ||
1040 | bins[31] = vdata[31]; | ||
1041 | memcpy(&bins[32], &vdata[33], num_bins - 32); | ||
1042 | break; | ||
1043 | default: | ||
1044 | return 1; | ||
1045 | } | ||
1046 | |||
1047 | /* DC value (value in the middle) is the blind spot of the spectral | ||
1048 | * sample and invalid, interpolate it. | ||
1049 | */ | ||
1050 | dc_pos = num_bins / 2; | ||
1051 | bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; | ||
1052 | |||
1053 | if ((chan_type == NL80211_CHAN_HT40MINUS) || | ||
1054 | (chan_type == NL80211_CHAN_HT40PLUS)) { | ||
1055 | s8 lower_rssi, upper_rssi; | ||
1056 | s16 ext_nf; | ||
1057 | u8 lower_max_index, upper_max_index; | ||
1058 | u8 lower_bitmap_w, upper_bitmap_w; | ||
1059 | u16 lower_mag, upper_mag; | ||
1060 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
1061 | struct ath_ht20_40_mag_info *mag_info; | ||
1062 | |||
1063 | if (caldata) | ||
1064 | ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan, | ||
1065 | caldata->nfCalHist[3].privNF); | ||
1066 | else | ||
1067 | ext_nf = ATH_DEFAULT_NOISE_FLOOR; | ||
1068 | |||
1069 | length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv); | ||
1070 | fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40; | ||
1071 | fft_sample_40.tlv.length = __cpu_to_be16(length); | ||
1072 | fft_sample_40.freq = __cpu_to_be16(freq); | ||
1073 | fft_sample_40.channel_type = chan_type; | ||
1074 | |||
1075 | if (chan_type == NL80211_CHAN_HT40PLUS) { | ||
1076 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
1077 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0); | ||
1078 | |||
1079 | fft_sample_40.lower_noise = ah->noise; | ||
1080 | fft_sample_40.upper_noise = ext_nf; | ||
1081 | } else { | ||
1082 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0); | ||
1083 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
1084 | |||
1085 | fft_sample_40.lower_noise = ext_nf; | ||
1086 | fft_sample_40.upper_noise = ah->noise; | ||
1087 | } | ||
1088 | fft_sample_40.lower_rssi = lower_rssi; | ||
1089 | fft_sample_40.upper_rssi = upper_rssi; | ||
1090 | |||
1091 | mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1; | ||
1092 | lower_mag = spectral_max_magnitude(mag_info->lower_bins); | ||
1093 | upper_mag = spectral_max_magnitude(mag_info->upper_bins); | ||
1094 | fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag); | ||
1095 | fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag); | ||
1096 | lower_max_index = spectral_max_index(mag_info->lower_bins); | ||
1097 | upper_max_index = spectral_max_index(mag_info->upper_bins); | ||
1098 | fft_sample_40.lower_max_index = lower_max_index; | ||
1099 | fft_sample_40.upper_max_index = upper_max_index; | ||
1100 | lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins); | ||
1101 | upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins); | ||
1102 | fft_sample_40.lower_bitmap_weight = lower_bitmap_w; | ||
1103 | fft_sample_40.upper_bitmap_weight = upper_bitmap_w; | ||
1104 | fft_sample_40.max_exp = mag_info->max_exp & 0xf; | ||
1105 | |||
1106 | fft_sample_40.tsf = __cpu_to_be64(tsf); | ||
1107 | |||
1108 | tlv = (struct fft_sample_tlv *)&fft_sample_40; | ||
1109 | } else { | ||
1110 | u8 max_index, bitmap_w; | ||
1111 | u16 magnitude; | ||
1112 | struct ath_ht20_mag_info *mag_info; | ||
1113 | |||
1114 | length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv); | ||
1115 | fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20; | ||
1116 | fft_sample_20.tlv.length = __cpu_to_be16(length); | ||
1117 | fft_sample_20.freq = __cpu_to_be16(freq); | ||
1118 | |||
1119 | fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
1120 | fft_sample_20.noise = ah->noise; | ||
1121 | |||
1122 | mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; | ||
1123 | magnitude = spectral_max_magnitude(mag_info->all_bins); | ||
1124 | fft_sample_20.max_magnitude = __cpu_to_be16(magnitude); | ||
1125 | max_index = spectral_max_index(mag_info->all_bins); | ||
1126 | fft_sample_20.max_index = max_index; | ||
1127 | bitmap_w = spectral_bitmap_weight(mag_info->all_bins); | ||
1128 | fft_sample_20.bitmap_weight = bitmap_w; | ||
1129 | fft_sample_20.max_exp = mag_info->max_exp & 0xf; | ||
1130 | |||
1131 | fft_sample_20.tsf = __cpu_to_be64(tsf); | ||
1132 | |||
1133 | tlv = (struct fft_sample_tlv *)&fft_sample_20; | ||
1134 | } | ||
1135 | |||
1136 | ath_debug_send_fft_sample(sc, tlv); | ||
1137 | return 1; | ||
1138 | #else | ||
1139 | return 0; | ||
1140 | #endif | ||
1141 | } | ||
1142 | |||
1143 | static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr) | 977 | static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr) |
1144 | { | 978 | { |
1145 | struct ath_hw *ah = sc->sc_ah; | 979 | struct ath_hw *ah = sc->sc_ah; |
diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c new file mode 100644 index 000000000000..11adb5eb51cc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/spectral.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/relay.h> | ||
18 | #include "ath9k.h" | ||
19 | |||
20 | static s8 fix_rssi_inv_only(u8 rssi_val) | ||
21 | { | ||
22 | if (rssi_val == 128) | ||
23 | rssi_val = 0; | ||
24 | return (s8) rssi_val; | ||
25 | } | ||
26 | |||
27 | static void ath_debug_send_fft_sample(struct ath_softc *sc, | ||
28 | struct fft_sample_tlv *fft_sample_tlv) | ||
29 | { | ||
30 | int length; | ||
31 | if (!sc->rfs_chan_spec_scan) | ||
32 | return; | ||
33 | |||
34 | length = __be16_to_cpu(fft_sample_tlv->length) + | ||
35 | sizeof(*fft_sample_tlv); | ||
36 | relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length); | ||
37 | } | ||
38 | |||
39 | /* returns 1 if this was a spectral frame, even if not handled. */ | ||
40 | int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | ||
41 | struct ath_rx_status *rs, u64 tsf) | ||
42 | { | ||
43 | struct ath_hw *ah = sc->sc_ah; | ||
44 | u8 num_bins, *bins, *vdata = (u8 *)hdr; | ||
45 | struct fft_sample_ht20 fft_sample_20; | ||
46 | struct fft_sample_ht20_40 fft_sample_40; | ||
47 | struct fft_sample_tlv *tlv; | ||
48 | struct ath_radar_info *radar_info; | ||
49 | int len = rs->rs_datalen; | ||
50 | int dc_pos; | ||
51 | u16 fft_len, length, freq = ah->curchan->chan->center_freq; | ||
52 | enum nl80211_channel_type chan_type; | ||
53 | |||
54 | /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer | ||
55 | * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT | ||
56 | * yet, but this is supposed to be possible as well. | ||
57 | */ | ||
58 | if (rs->rs_phyerr != ATH9K_PHYERR_RADAR && | ||
59 | rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT && | ||
60 | rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL) | ||
61 | return 0; | ||
62 | |||
63 | /* check if spectral scan bit is set. This does not have to be checked | ||
64 | * if received through a SPECTRAL phy error, but shouldn't hurt. | ||
65 | */ | ||
66 | radar_info = ((struct ath_radar_info *)&vdata[len]) - 1; | ||
67 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) | ||
68 | return 0; | ||
69 | |||
70 | chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef); | ||
71 | if ((chan_type == NL80211_CHAN_HT40MINUS) || | ||
72 | (chan_type == NL80211_CHAN_HT40PLUS)) { | ||
73 | fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; | ||
74 | num_bins = SPECTRAL_HT20_40_NUM_BINS; | ||
75 | bins = (u8 *)fft_sample_40.data; | ||
76 | } else { | ||
77 | fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN; | ||
78 | num_bins = SPECTRAL_HT20_NUM_BINS; | ||
79 | bins = (u8 *)fft_sample_20.data; | ||
80 | } | ||
81 | |||
82 | /* Variation in the data length is possible and will be fixed later */ | ||
83 | if ((len > fft_len + 2) || (len < fft_len - 1)) | ||
84 | return 1; | ||
85 | |||
86 | switch (len - fft_len) { | ||
87 | case 0: | ||
88 | /* length correct, nothing to do. */ | ||
89 | memcpy(bins, vdata, num_bins); | ||
90 | break; | ||
91 | case -1: | ||
92 | /* first byte missing, duplicate it. */ | ||
93 | memcpy(&bins[1], vdata, num_bins - 1); | ||
94 | bins[0] = vdata[0]; | ||
95 | break; | ||
96 | case 2: | ||
97 | /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ | ||
98 | memcpy(bins, vdata, 30); | ||
99 | bins[30] = vdata[31]; | ||
100 | memcpy(&bins[31], &vdata[33], num_bins - 31); | ||
101 | break; | ||
102 | case 1: | ||
103 | /* MAC added 2 extra bytes AND first byte is missing. */ | ||
104 | bins[0] = vdata[0]; | ||
105 | memcpy(&bins[1], vdata, 30); | ||
106 | bins[31] = vdata[31]; | ||
107 | memcpy(&bins[32], &vdata[33], num_bins - 32); | ||
108 | break; | ||
109 | default: | ||
110 | return 1; | ||
111 | } | ||
112 | |||
113 | /* DC value (value in the middle) is the blind spot of the spectral | ||
114 | * sample and invalid, interpolate it. | ||
115 | */ | ||
116 | dc_pos = num_bins / 2; | ||
117 | bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; | ||
118 | |||
119 | if ((chan_type == NL80211_CHAN_HT40MINUS) || | ||
120 | (chan_type == NL80211_CHAN_HT40PLUS)) { | ||
121 | s8 lower_rssi, upper_rssi; | ||
122 | s16 ext_nf; | ||
123 | u8 lower_max_index, upper_max_index; | ||
124 | u8 lower_bitmap_w, upper_bitmap_w; | ||
125 | u16 lower_mag, upper_mag; | ||
126 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
127 | struct ath_ht20_40_mag_info *mag_info; | ||
128 | |||
129 | if (caldata) | ||
130 | ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan, | ||
131 | caldata->nfCalHist[3].privNF); | ||
132 | else | ||
133 | ext_nf = ATH_DEFAULT_NOISE_FLOOR; | ||
134 | |||
135 | length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv); | ||
136 | fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40; | ||
137 | fft_sample_40.tlv.length = __cpu_to_be16(length); | ||
138 | fft_sample_40.freq = __cpu_to_be16(freq); | ||
139 | fft_sample_40.channel_type = chan_type; | ||
140 | |||
141 | if (chan_type == NL80211_CHAN_HT40PLUS) { | ||
142 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); | ||
143 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]); | ||
144 | |||
145 | fft_sample_40.lower_noise = ah->noise; | ||
146 | fft_sample_40.upper_noise = ext_nf; | ||
147 | } else { | ||
148 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]); | ||
149 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); | ||
150 | |||
151 | fft_sample_40.lower_noise = ext_nf; | ||
152 | fft_sample_40.upper_noise = ah->noise; | ||
153 | } | ||
154 | fft_sample_40.lower_rssi = lower_rssi; | ||
155 | fft_sample_40.upper_rssi = upper_rssi; | ||
156 | |||
157 | mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1; | ||
158 | lower_mag = spectral_max_magnitude(mag_info->lower_bins); | ||
159 | upper_mag = spectral_max_magnitude(mag_info->upper_bins); | ||
160 | fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag); | ||
161 | fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag); | ||
162 | lower_max_index = spectral_max_index(mag_info->lower_bins); | ||
163 | upper_max_index = spectral_max_index(mag_info->upper_bins); | ||
164 | fft_sample_40.lower_max_index = lower_max_index; | ||
165 | fft_sample_40.upper_max_index = upper_max_index; | ||
166 | lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins); | ||
167 | upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins); | ||
168 | fft_sample_40.lower_bitmap_weight = lower_bitmap_w; | ||
169 | fft_sample_40.upper_bitmap_weight = upper_bitmap_w; | ||
170 | fft_sample_40.max_exp = mag_info->max_exp & 0xf; | ||
171 | |||
172 | fft_sample_40.tsf = __cpu_to_be64(tsf); | ||
173 | |||
174 | tlv = (struct fft_sample_tlv *)&fft_sample_40; | ||
175 | } else { | ||
176 | u8 max_index, bitmap_w; | ||
177 | u16 magnitude; | ||
178 | struct ath_ht20_mag_info *mag_info; | ||
179 | |||
180 | length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv); | ||
181 | fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20; | ||
182 | fft_sample_20.tlv.length = __cpu_to_be16(length); | ||
183 | fft_sample_20.freq = __cpu_to_be16(freq); | ||
184 | |||
185 | fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]); | ||
186 | fft_sample_20.noise = ah->noise; | ||
187 | |||
188 | mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; | ||
189 | magnitude = spectral_max_magnitude(mag_info->all_bins); | ||
190 | fft_sample_20.max_magnitude = __cpu_to_be16(magnitude); | ||
191 | max_index = spectral_max_index(mag_info->all_bins); | ||
192 | fft_sample_20.max_index = max_index; | ||
193 | bitmap_w = spectral_bitmap_weight(mag_info->all_bins); | ||
194 | fft_sample_20.bitmap_weight = bitmap_w; | ||
195 | fft_sample_20.max_exp = mag_info->max_exp & 0xf; | ||
196 | |||
197 | fft_sample_20.tsf = __cpu_to_be64(tsf); | ||
198 | |||
199 | tlv = (struct fft_sample_tlv *)&fft_sample_20; | ||
200 | } | ||
201 | |||
202 | ath_debug_send_fft_sample(sc, tlv); | ||
203 | |||
204 | return 1; | ||
205 | } | ||
206 | |||
207 | /*********************/ | ||
208 | /* spectral_scan_ctl */ | ||
209 | /*********************/ | ||
210 | |||
211 | static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, | ||
212 | size_t count, loff_t *ppos) | ||
213 | { | ||
214 | struct ath_softc *sc = file->private_data; | ||
215 | char *mode = ""; | ||
216 | unsigned int len; | ||
217 | |||
218 | switch (sc->spectral_mode) { | ||
219 | case SPECTRAL_DISABLED: | ||
220 | mode = "disable"; | ||
221 | break; | ||
222 | case SPECTRAL_BACKGROUND: | ||
223 | mode = "background"; | ||
224 | break; | ||
225 | case SPECTRAL_CHANSCAN: | ||
226 | mode = "chanscan"; | ||
227 | break; | ||
228 | case SPECTRAL_MANUAL: | ||
229 | mode = "manual"; | ||
230 | break; | ||
231 | } | ||
232 | len = strlen(mode); | ||
233 | return simple_read_from_buffer(user_buf, count, ppos, mode, len); | ||
234 | } | ||
235 | |||
236 | static ssize_t write_file_spec_scan_ctl(struct file *file, | ||
237 | const char __user *user_buf, | ||
238 | size_t count, loff_t *ppos) | ||
239 | { | ||
240 | struct ath_softc *sc = file->private_data; | ||
241 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
242 | char buf[32]; | ||
243 | ssize_t len; | ||
244 | |||
245 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
246 | return -EOPNOTSUPP; | ||
247 | |||
248 | len = min(count, sizeof(buf) - 1); | ||
249 | if (copy_from_user(buf, user_buf, len)) | ||
250 | return -EFAULT; | ||
251 | |||
252 | buf[len] = '\0'; | ||
253 | |||
254 | if (strncmp("trigger", buf, 7) == 0) { | ||
255 | ath9k_spectral_scan_trigger(sc->hw); | ||
256 | } else if (strncmp("background", buf, 9) == 0) { | ||
257 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND); | ||
258 | ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); | ||
259 | } else if (strncmp("chanscan", buf, 8) == 0) { | ||
260 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN); | ||
261 | ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); | ||
262 | } else if (strncmp("manual", buf, 6) == 0) { | ||
263 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL); | ||
264 | ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); | ||
265 | } else if (strncmp("disable", buf, 7) == 0) { | ||
266 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED); | ||
267 | ath_dbg(common, CONFIG, "spectral scan: disabled\n"); | ||
268 | } else { | ||
269 | return -EINVAL; | ||
270 | } | ||
271 | |||
272 | return count; | ||
273 | } | ||
274 | |||
275 | static const struct file_operations fops_spec_scan_ctl = { | ||
276 | .read = read_file_spec_scan_ctl, | ||
277 | .write = write_file_spec_scan_ctl, | ||
278 | .open = simple_open, | ||
279 | .owner = THIS_MODULE, | ||
280 | .llseek = default_llseek, | ||
281 | }; | ||
282 | |||
283 | /*************************/ | ||
284 | /* spectral_short_repeat */ | ||
285 | /*************************/ | ||
286 | |||
287 | static ssize_t read_file_spectral_short_repeat(struct file *file, | ||
288 | char __user *user_buf, | ||
289 | size_t count, loff_t *ppos) | ||
290 | { | ||
291 | struct ath_softc *sc = file->private_data; | ||
292 | char buf[32]; | ||
293 | unsigned int len; | ||
294 | |||
295 | len = sprintf(buf, "%d\n", sc->spec_config.short_repeat); | ||
296 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
297 | } | ||
298 | |||
299 | static ssize_t write_file_spectral_short_repeat(struct file *file, | ||
300 | const char __user *user_buf, | ||
301 | size_t count, loff_t *ppos) | ||
302 | { | ||
303 | struct ath_softc *sc = file->private_data; | ||
304 | unsigned long val; | ||
305 | char buf[32]; | ||
306 | ssize_t len; | ||
307 | |||
308 | len = min(count, sizeof(buf) - 1); | ||
309 | if (copy_from_user(buf, user_buf, len)) | ||
310 | return -EFAULT; | ||
311 | |||
312 | buf[len] = '\0'; | ||
313 | if (kstrtoul(buf, 0, &val)) | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (val < 0 || val > 1) | ||
317 | return -EINVAL; | ||
318 | |||
319 | sc->spec_config.short_repeat = val; | ||
320 | return count; | ||
321 | } | ||
322 | |||
323 | static const struct file_operations fops_spectral_short_repeat = { | ||
324 | .read = read_file_spectral_short_repeat, | ||
325 | .write = write_file_spectral_short_repeat, | ||
326 | .open = simple_open, | ||
327 | .owner = THIS_MODULE, | ||
328 | .llseek = default_llseek, | ||
329 | }; | ||
330 | |||
331 | /******************/ | ||
332 | /* spectral_count */ | ||
333 | /******************/ | ||
334 | |||
335 | static ssize_t read_file_spectral_count(struct file *file, | ||
336 | char __user *user_buf, | ||
337 | size_t count, loff_t *ppos) | ||
338 | { | ||
339 | struct ath_softc *sc = file->private_data; | ||
340 | char buf[32]; | ||
341 | unsigned int len; | ||
342 | |||
343 | len = sprintf(buf, "%d\n", sc->spec_config.count); | ||
344 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
345 | } | ||
346 | |||
347 | static ssize_t write_file_spectral_count(struct file *file, | ||
348 | const char __user *user_buf, | ||
349 | size_t count, loff_t *ppos) | ||
350 | { | ||
351 | struct ath_softc *sc = file->private_data; | ||
352 | unsigned long val; | ||
353 | char buf[32]; | ||
354 | ssize_t len; | ||
355 | |||
356 | len = min(count, sizeof(buf) - 1); | ||
357 | if (copy_from_user(buf, user_buf, len)) | ||
358 | return -EFAULT; | ||
359 | |||
360 | buf[len] = '\0'; | ||
361 | if (kstrtoul(buf, 0, &val)) | ||
362 | return -EINVAL; | ||
363 | |||
364 | if (val < 0 || val > 255) | ||
365 | return -EINVAL; | ||
366 | |||
367 | sc->spec_config.count = val; | ||
368 | return count; | ||
369 | } | ||
370 | |||
371 | static const struct file_operations fops_spectral_count = { | ||
372 | .read = read_file_spectral_count, | ||
373 | .write = write_file_spectral_count, | ||
374 | .open = simple_open, | ||
375 | .owner = THIS_MODULE, | ||
376 | .llseek = default_llseek, | ||
377 | }; | ||
378 | |||
379 | /*******************/ | ||
380 | /* spectral_period */ | ||
381 | /*******************/ | ||
382 | |||
383 | static ssize_t read_file_spectral_period(struct file *file, | ||
384 | char __user *user_buf, | ||
385 | size_t count, loff_t *ppos) | ||
386 | { | ||
387 | struct ath_softc *sc = file->private_data; | ||
388 | char buf[32]; | ||
389 | unsigned int len; | ||
390 | |||
391 | len = sprintf(buf, "%d\n", sc->spec_config.period); | ||
392 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
393 | } | ||
394 | |||
395 | static ssize_t write_file_spectral_period(struct file *file, | ||
396 | const char __user *user_buf, | ||
397 | size_t count, loff_t *ppos) | ||
398 | { | ||
399 | struct ath_softc *sc = file->private_data; | ||
400 | unsigned long val; | ||
401 | char buf[32]; | ||
402 | ssize_t len; | ||
403 | |||
404 | len = min(count, sizeof(buf) - 1); | ||
405 | if (copy_from_user(buf, user_buf, len)) | ||
406 | return -EFAULT; | ||
407 | |||
408 | buf[len] = '\0'; | ||
409 | if (kstrtoul(buf, 0, &val)) | ||
410 | return -EINVAL; | ||
411 | |||
412 | if (val < 0 || val > 255) | ||
413 | return -EINVAL; | ||
414 | |||
415 | sc->spec_config.period = val; | ||
416 | return count; | ||
417 | } | ||
418 | |||
419 | static const struct file_operations fops_spectral_period = { | ||
420 | .read = read_file_spectral_period, | ||
421 | .write = write_file_spectral_period, | ||
422 | .open = simple_open, | ||
423 | .owner = THIS_MODULE, | ||
424 | .llseek = default_llseek, | ||
425 | }; | ||
426 | |||
427 | /***********************/ | ||
428 | /* spectral_fft_period */ | ||
429 | /***********************/ | ||
430 | |||
431 | static ssize_t read_file_spectral_fft_period(struct file *file, | ||
432 | char __user *user_buf, | ||
433 | size_t count, loff_t *ppos) | ||
434 | { | ||
435 | struct ath_softc *sc = file->private_data; | ||
436 | char buf[32]; | ||
437 | unsigned int len; | ||
438 | |||
439 | len = sprintf(buf, "%d\n", sc->spec_config.fft_period); | ||
440 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
441 | } | ||
442 | |||
443 | static ssize_t write_file_spectral_fft_period(struct file *file, | ||
444 | const char __user *user_buf, | ||
445 | size_t count, loff_t *ppos) | ||
446 | { | ||
447 | struct ath_softc *sc = file->private_data; | ||
448 | unsigned long val; | ||
449 | char buf[32]; | ||
450 | ssize_t len; | ||
451 | |||
452 | len = min(count, sizeof(buf) - 1); | ||
453 | if (copy_from_user(buf, user_buf, len)) | ||
454 | return -EFAULT; | ||
455 | |||
456 | buf[len] = '\0'; | ||
457 | if (kstrtoul(buf, 0, &val)) | ||
458 | return -EINVAL; | ||
459 | |||
460 | if (val < 0 || val > 15) | ||
461 | return -EINVAL; | ||
462 | |||
463 | sc->spec_config.fft_period = val; | ||
464 | return count; | ||
465 | } | ||
466 | |||
467 | static const struct file_operations fops_spectral_fft_period = { | ||
468 | .read = read_file_spectral_fft_period, | ||
469 | .write = write_file_spectral_fft_period, | ||
470 | .open = simple_open, | ||
471 | .owner = THIS_MODULE, | ||
472 | .llseek = default_llseek, | ||
473 | }; | ||
474 | |||
475 | /*******************/ | ||
476 | /* Relay interface */ | ||
477 | /*******************/ | ||
478 | |||
479 | static struct dentry *create_buf_file_handler(const char *filename, | ||
480 | struct dentry *parent, | ||
481 | umode_t mode, | ||
482 | struct rchan_buf *buf, | ||
483 | int *is_global) | ||
484 | { | ||
485 | struct dentry *buf_file; | ||
486 | |||
487 | buf_file = debugfs_create_file(filename, mode, parent, buf, | ||
488 | &relay_file_operations); | ||
489 | *is_global = 1; | ||
490 | return buf_file; | ||
491 | } | ||
492 | |||
493 | static int remove_buf_file_handler(struct dentry *dentry) | ||
494 | { | ||
495 | debugfs_remove(dentry); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | struct rchan_callbacks rfs_spec_scan_cb = { | ||
501 | .create_buf_file = create_buf_file_handler, | ||
502 | .remove_buf_file = remove_buf_file_handler, | ||
503 | }; | ||
504 | |||
505 | /*********************/ | ||
506 | /* Debug Init/Deinit */ | ||
507 | /*********************/ | ||
508 | |||
509 | void ath9k_spectral_deinit_debug(struct ath_softc *sc) | ||
510 | { | ||
511 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { | ||
512 | relay_close(sc->rfs_chan_spec_scan); | ||
513 | sc->rfs_chan_spec_scan = NULL; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | void ath9k_spectral_init_debug(struct ath_softc *sc) | ||
518 | { | ||
519 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", | ||
520 | sc->debug.debugfs_phy, | ||
521 | 1024, 256, &rfs_spec_scan_cb, | ||
522 | NULL); | ||
523 | debugfs_create_file("spectral_scan_ctl", | ||
524 | S_IRUSR | S_IWUSR, | ||
525 | sc->debug.debugfs_phy, sc, | ||
526 | &fops_spec_scan_ctl); | ||
527 | debugfs_create_file("spectral_short_repeat", | ||
528 | S_IRUSR | S_IWUSR, | ||
529 | sc->debug.debugfs_phy, sc, | ||
530 | &fops_spectral_short_repeat); | ||
531 | debugfs_create_file("spectral_count", | ||
532 | S_IRUSR | S_IWUSR, | ||
533 | sc->debug.debugfs_phy, sc, | ||
534 | &fops_spectral_count); | ||
535 | debugfs_create_file("spectral_period", | ||
536 | S_IRUSR | S_IWUSR, | ||
537 | sc->debug.debugfs_phy, sc, | ||
538 | &fops_spectral_period); | ||
539 | debugfs_create_file("spectral_fft_period", | ||
540 | S_IRUSR | S_IWUSR, | ||
541 | sc->debug.debugfs_phy, sc, | ||
542 | &fops_spectral_fft_period); | ||
543 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h new file mode 100644 index 000000000000..ead63412ee1a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/spectral.h | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef SPECTRAL_H | ||
18 | #define SPECTRAL_H | ||
19 | |||
20 | /* enum spectral_mode: | ||
21 | * | ||
22 | * @SPECTRAL_DISABLED: spectral mode is disabled | ||
23 | * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with | ||
24 | * something else. | ||
25 | * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples | ||
26 | * is performed manually. | ||
27 | * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels | ||
28 | * during a channel scan. | ||
29 | */ | ||
30 | enum spectral_mode { | ||
31 | SPECTRAL_DISABLED = 0, | ||
32 | SPECTRAL_BACKGROUND, | ||
33 | SPECTRAL_MANUAL, | ||
34 | SPECTRAL_CHANSCAN, | ||
35 | }; | ||
36 | |||
37 | #define SPECTRAL_SCAN_BITMASK 0x10 | ||
38 | /* Radar info packet format, used for DFS and spectral formats. */ | ||
39 | struct ath_radar_info { | ||
40 | u8 pulse_length_pri; | ||
41 | u8 pulse_length_ext; | ||
42 | u8 pulse_bw_info; | ||
43 | } __packed; | ||
44 | |||
45 | /* The HT20 spectral data has 4 bytes of additional information at it's end. | ||
46 | * | ||
47 | * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
48 | * [7:0]: all bins max_magnitude[9:2] | ||
49 | * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]} | ||
50 | * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) | ||
51 | */ | ||
52 | struct ath_ht20_mag_info { | ||
53 | u8 all_bins[3]; | ||
54 | u8 max_exp; | ||
55 | } __packed; | ||
56 | |||
57 | #define SPECTRAL_HT20_NUM_BINS 56 | ||
58 | |||
59 | /* WARNING: don't actually use this struct! MAC may vary the amount of | ||
60 | * data by -1/+2. This struct is for reference only. | ||
61 | */ | ||
62 | struct ath_ht20_fft_packet { | ||
63 | u8 data[SPECTRAL_HT20_NUM_BINS]; | ||
64 | struct ath_ht20_mag_info mag_info; | ||
65 | struct ath_radar_info radar_info; | ||
66 | } __packed; | ||
67 | |||
68 | #define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet)) | ||
69 | |||
70 | /* Dynamic 20/40 mode: | ||
71 | * | ||
72 | * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
73 | * [7:0]: lower bins max_magnitude[9:2] | ||
74 | * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} | ||
75 | * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
76 | * [7:0]: upper bins max_magnitude[9:2] | ||
77 | * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} | ||
78 | * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) | ||
79 | */ | ||
80 | struct ath_ht20_40_mag_info { | ||
81 | u8 lower_bins[3]; | ||
82 | u8 upper_bins[3]; | ||
83 | u8 max_exp; | ||
84 | } __packed; | ||
85 | |||
86 | #define SPECTRAL_HT20_40_NUM_BINS 128 | ||
87 | |||
88 | /* WARNING: don't actually use this struct! MAC may vary the amount of | ||
89 | * data. This struct is for reference only. | ||
90 | */ | ||
91 | struct ath_ht20_40_fft_packet { | ||
92 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | ||
93 | struct ath_ht20_40_mag_info mag_info; | ||
94 | struct ath_radar_info radar_info; | ||
95 | } __packed; | ||
96 | |||
97 | |||
98 | #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) | ||
99 | |||
100 | /* grabs the max magnitude from the all/upper/lower bins */ | ||
101 | static inline u16 spectral_max_magnitude(u8 *bins) | ||
102 | { | ||
103 | return (bins[0] & 0xc0) >> 6 | | ||
104 | (bins[1] & 0xff) << 2 | | ||
105 | (bins[2] & 0x03) << 10; | ||
106 | } | ||
107 | |||
108 | /* return the max magnitude from the all/upper/lower bins */ | ||
109 | static inline u8 spectral_max_index(u8 *bins) | ||
110 | { | ||
111 | s8 m = (bins[2] & 0xfc) >> 2; | ||
112 | |||
113 | /* TODO: this still doesn't always report the right values ... */ | ||
114 | if (m > 32) | ||
115 | m |= 0xe0; | ||
116 | else | ||
117 | m &= ~0xe0; | ||
118 | |||
119 | return m + 29; | ||
120 | } | ||
121 | |||
122 | /* return the bitmap weight from the all/upper/lower bins */ | ||
123 | static inline u8 spectral_bitmap_weight(u8 *bins) | ||
124 | { | ||
125 | return bins[0] & 0x3f; | ||
126 | } | ||
127 | |||
128 | /* FFT sample format given to userspace via debugfs. | ||
129 | * | ||
130 | * Please keep the type/length at the front position and change | ||
131 | * other fields after adding another sample type | ||
132 | * | ||
133 | * TODO: this might need rework when switching to nl80211-based | ||
134 | * interface. | ||
135 | */ | ||
136 | enum ath_fft_sample_type { | ||
137 | ATH_FFT_SAMPLE_HT20 = 1, | ||
138 | ATH_FFT_SAMPLE_HT20_40, | ||
139 | }; | ||
140 | |||
141 | struct fft_sample_tlv { | ||
142 | u8 type; /* see ath_fft_sample */ | ||
143 | __be16 length; | ||
144 | /* type dependent data follows */ | ||
145 | } __packed; | ||
146 | |||
147 | struct fft_sample_ht20 { | ||
148 | struct fft_sample_tlv tlv; | ||
149 | |||
150 | u8 max_exp; | ||
151 | |||
152 | __be16 freq; | ||
153 | s8 rssi; | ||
154 | s8 noise; | ||
155 | |||
156 | __be16 max_magnitude; | ||
157 | u8 max_index; | ||
158 | u8 bitmap_weight; | ||
159 | |||
160 | __be64 tsf; | ||
161 | |||
162 | u8 data[SPECTRAL_HT20_NUM_BINS]; | ||
163 | } __packed; | ||
164 | |||
165 | struct fft_sample_ht20_40 { | ||
166 | struct fft_sample_tlv tlv; | ||
167 | |||
168 | u8 channel_type; | ||
169 | __be16 freq; | ||
170 | |||
171 | s8 lower_rssi; | ||
172 | s8 upper_rssi; | ||
173 | |||
174 | __be64 tsf; | ||
175 | |||
176 | s8 lower_noise; | ||
177 | s8 upper_noise; | ||
178 | |||
179 | __be16 lower_max_magnitude; | ||
180 | __be16 upper_max_magnitude; | ||
181 | |||
182 | u8 lower_max_index; | ||
183 | u8 upper_max_index; | ||
184 | |||
185 | u8 lower_bitmap_weight; | ||
186 | u8 upper_bitmap_weight; | ||
187 | |||
188 | u8 max_exp; | ||
189 | |||
190 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | ||
191 | } __packed; | ||
192 | |||
193 | void ath9k_spectral_init_debug(struct ath_softc *sc); | ||
194 | void ath9k_spectral_deinit_debug(struct ath_softc *sc); | ||
195 | |||
196 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); | ||
197 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | ||
198 | enum spectral_mode spectral_mode); | ||
199 | |||
200 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
201 | int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | ||
202 | struct ath_rx_status *rs, u64 tsf); | ||
203 | #else | ||
204 | static inline int ath_process_fft(struct ath_softc *sc, | ||
205 | struct ieee80211_hdr *hdr, | ||
206 | struct ath_rx_status *rs, u64 tsf) | ||
207 | { | ||
208 | return 0; | ||
209 | } | ||
210 | #endif /* CONFIG_ATH9K_DEBUGFS */ | ||
211 | |||
212 | #endif /* SPECTRAL_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index a907bc94800d..9d735c55a0f3 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -174,14 +174,7 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, | |||
174 | static struct ath_atx_tid * | 174 | static struct ath_atx_tid * |
175 | ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb) | 175 | ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb) |
176 | { | 176 | { |
177 | struct ieee80211_hdr *hdr; | 177 | u8 tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
178 | u8 tidno = 0; | ||
179 | |||
180 | hdr = (struct ieee80211_hdr *) skb->data; | ||
181 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
182 | tidno = ieee80211_get_qos_ctl(hdr)[0]; | ||
183 | |||
184 | tidno &= IEEE80211_QOS_CTL_TID_MASK; | ||
185 | return ATH_AN_2_TID(an, tidno); | 178 | return ATH_AN_2_TID(an, tidno); |
186 | } | 179 | } |
187 | 180 | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 8f37562e0b11..750626b0e22d 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c | |||
@@ -2060,22 +2060,28 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) | |||
2060 | case WCN36XX_HAL_OTA_TX_COMPL_IND: | 2060 | case WCN36XX_HAL_OTA_TX_COMPL_IND: |
2061 | case WCN36XX_HAL_MISSED_BEACON_IND: | 2061 | case WCN36XX_HAL_MISSED_BEACON_IND: |
2062 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: | 2062 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: |
2063 | mutex_lock(&wcn->hal_ind_mutex); | ||
2064 | msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); | 2063 | msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); |
2065 | if (msg_ind) { | 2064 | if (!msg_ind) |
2066 | msg_ind->msg_len = len; | 2065 | goto nomem; |
2067 | msg_ind->msg = kmalloc(len, GFP_KERNEL); | 2066 | msg_ind->msg_len = len; |
2068 | memcpy(msg_ind->msg, buf, len); | 2067 | msg_ind->msg = kmalloc(len, GFP_KERNEL); |
2069 | list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); | 2068 | if (!msg_ind->msg) { |
2070 | queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); | 2069 | kfree(msg_ind); |
2071 | wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); | 2070 | nomem: |
2071 | /* | ||
2072 | * FIXME: Do something smarter then just | ||
2073 | * printing an error. | ||
2074 | */ | ||
2075 | wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", | ||
2076 | msg_header->msg_type); | ||
2077 | break; | ||
2072 | } | 2078 | } |
2079 | memcpy(msg_ind->msg, buf, len); | ||
2080 | mutex_lock(&wcn->hal_ind_mutex); | ||
2081 | list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); | ||
2082 | queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); | ||
2073 | mutex_unlock(&wcn->hal_ind_mutex); | 2083 | mutex_unlock(&wcn->hal_ind_mutex); |
2074 | if (msg_ind) | 2084 | wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); |
2075 | break; | ||
2076 | /* FIXME: Do something smarter then just printing an error. */ | ||
2077 | wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", | ||
2078 | msg_header->msg_type); | ||
2079 | break; | 2085 | break; |
2080 | default: | 2086 | default: |
2081 | wcn36xx_err("SMD_EVENT (%d) not supported\n", | 2087 | wcn36xx_err("SMD_EVENT (%d) not supported\n", |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 2082402d4b63..5681b9862023 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -36,7 +36,6 @@ brcmfmac-objs += \ | |||
36 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ | 36 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ |
37 | dhd_sdio.o \ | 37 | dhd_sdio.o \ |
38 | bcmsdh.o \ | 38 | bcmsdh.o \ |
39 | bcmsdh_sdmmc.o \ | ||
40 | sdio_chip.o | 39 | sdio_chip.o |
41 | brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ | 40 | brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ |
42 | usb.o | 41 | usb.o |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index 06848e426f9a..12c27d13df7f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | |||
@@ -101,35 +101,41 @@ struct brcmf_proto_bcdc_header { | |||
101 | * plus any space that might be needed | 101 | * plus any space that might be needed |
102 | * for bus alignment padding. | 102 | * for bus alignment padding. |
103 | */ | 103 | */ |
104 | #define ROUND_UP_MARGIN 2048 /* Biggest bus block size possible for | ||
105 | * round off at the end of buffer | ||
106 | * Currently is SDIO | ||
107 | */ | ||
108 | |||
109 | struct brcmf_bcdc { | 104 | struct brcmf_bcdc { |
110 | u16 reqid; | 105 | u16 reqid; |
111 | u8 bus_header[BUS_HEADER_LEN]; | 106 | u8 bus_header[BUS_HEADER_LEN]; |
112 | struct brcmf_proto_bcdc_dcmd msg; | 107 | struct brcmf_proto_bcdc_dcmd msg; |
113 | unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; | 108 | unsigned char buf[BRCMF_DCMD_MAXLEN]; |
114 | }; | 109 | }; |
115 | 110 | ||
116 | static int brcmf_proto_bcdc_msg(struct brcmf_pub *drvr) | 111 | |
112 | static int | ||
113 | brcmf_proto_bcdc_msg(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, | ||
114 | uint len, bool set) | ||
117 | { | 115 | { |
118 | struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; | 116 | struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; |
119 | int len = le32_to_cpu(bcdc->msg.len) + | 117 | struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; |
120 | sizeof(struct brcmf_proto_bcdc_dcmd); | 118 | u32 flags; |
121 | 119 | ||
122 | brcmf_dbg(BCDC, "Enter\n"); | 120 | brcmf_dbg(BCDC, "Enter\n"); |
123 | 121 | ||
124 | /* NOTE : bcdc->msg.len holds the desired length of the buffer to be | 122 | memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd)); |
125 | * returned. Only up to BCDC_MAX_MSG_SIZE of this buffer area | 123 | |
126 | * is actually sent to the dongle | 124 | msg->cmd = cpu_to_le32(cmd); |
127 | */ | 125 | msg->len = cpu_to_le32(len); |
128 | if (len > BCDC_MAX_MSG_SIZE) | 126 | flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT); |
129 | len = BCDC_MAX_MSG_SIZE; | 127 | if (set) |
128 | flags |= BCDC_DCMD_SET; | ||
129 | flags = (flags & ~BCDC_DCMD_IF_MASK) | | ||
130 | (ifidx << BCDC_DCMD_IF_SHIFT); | ||
131 | msg->flags = cpu_to_le32(flags); | ||
132 | |||
133 | if (buf) | ||
134 | memcpy(bcdc->buf, buf, len); | ||
130 | 135 | ||
131 | /* Send request */ | 136 | /* Send request */ |
132 | return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len); | 137 | return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, |
138 | len + sizeof(struct brcmf_proto_bcdc_dcmd)); | ||
133 | } | 139 | } |
134 | 140 | ||
135 | static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) | 141 | static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) |
@@ -161,19 +167,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
161 | 167 | ||
162 | brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); | 168 | brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); |
163 | 169 | ||
164 | memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd)); | 170 | ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false); |
165 | |||
166 | msg->cmd = cpu_to_le32(cmd); | ||
167 | msg->len = cpu_to_le32(len); | ||
168 | flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT); | ||
169 | flags = (flags & ~BCDC_DCMD_IF_MASK) | | ||
170 | (ifidx << BCDC_DCMD_IF_SHIFT); | ||
171 | msg->flags = cpu_to_le32(flags); | ||
172 | |||
173 | if (buf) | ||
174 | memcpy(bcdc->buf, buf, len); | ||
175 | |||
176 | ret = brcmf_proto_bcdc_msg(drvr); | ||
177 | if (ret < 0) { | 171 | if (ret < 0) { |
178 | brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", | 172 | brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", |
179 | ret); | 173 | ret); |
@@ -227,19 +221,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
227 | 221 | ||
228 | brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); | 222 | brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); |
229 | 223 | ||
230 | memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd)); | 224 | ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true); |
231 | |||
232 | msg->cmd = cpu_to_le32(cmd); | ||
233 | msg->len = cpu_to_le32(len); | ||
234 | flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT) | BCDC_DCMD_SET; | ||
235 | flags = (flags & ~BCDC_DCMD_IF_MASK) | | ||
236 | (ifidx << BCDC_DCMD_IF_SHIFT); | ||
237 | msg->flags = cpu_to_le32(flags); | ||
238 | |||
239 | if (buf) | ||
240 | memcpy(bcdc->buf, buf, len); | ||
241 | |||
242 | ret = brcmf_proto_bcdc_msg(drvr); | ||
243 | if (ret < 0) | 225 | if (ret < 0) |
244 | goto done; | 226 | goto done; |
245 | 227 | ||
@@ -347,6 +329,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | |||
347 | return 0; | 329 | return 0; |
348 | } | 330 | } |
349 | 331 | ||
332 | static int | ||
333 | brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset, | ||
334 | struct sk_buff *pktbuf) | ||
335 | { | ||
336 | brcmf_proto_bcdc_hdrpush(drvr, ifidx, offset, pktbuf); | ||
337 | return brcmf_bus_txdata(drvr->bus_if, pktbuf); | ||
338 | } | ||
339 | |||
340 | |||
350 | int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) | 341 | int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) |
351 | { | 342 | { |
352 | struct brcmf_bcdc *bcdc; | 343 | struct brcmf_bcdc *bcdc; |
@@ -361,15 +352,15 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) | |||
361 | goto fail; | 352 | goto fail; |
362 | } | 353 | } |
363 | 354 | ||
364 | drvr->proto->hdrpush = brcmf_proto_bcdc_hdrpush; | ||
365 | drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull; | 355 | drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull; |
366 | drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd; | 356 | drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd; |
367 | drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd; | 357 | drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd; |
358 | drvr->proto->txdata = brcmf_proto_bcdc_txdata; | ||
368 | drvr->proto->pd = bcdc; | 359 | drvr->proto->pd = bcdc; |
369 | 360 | ||
370 | drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; | 361 | drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; |
371 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + | 362 | drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + |
372 | sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN; | 363 | sizeof(struct brcmf_proto_bcdc_dcmd); |
373 | return 0; | 364 | return 0; |
374 | 365 | ||
375 | fail: | 366 | fail: |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 91651ec7f13f..2b5cde67e728 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -23,9 +23,17 @@ | |||
23 | #include <linux/completion.h> | 23 | #include <linux/completion.h> |
24 | #include <linux/scatterlist.h> | 24 | #include <linux/scatterlist.h> |
25 | #include <linux/mmc/sdio.h> | 25 | #include <linux/mmc/sdio.h> |
26 | #include <linux/mmc/core.h> | ||
26 | #include <linux/mmc/sdio_func.h> | 27 | #include <linux/mmc/sdio_func.h> |
28 | #include <linux/mmc/sdio_ids.h> | ||
27 | #include <linux/mmc/card.h> | 29 | #include <linux/mmc/card.h> |
30 | #include <linux/mmc/host.h> | ||
31 | #include <linux/platform_device.h> | ||
28 | #include <linux/platform_data/brcmfmac-sdio.h> | 32 | #include <linux/platform_data/brcmfmac-sdio.h> |
33 | #include <linux/suspend.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <net/cfg80211.h> | ||
29 | 37 | ||
30 | #include <defs.h> | 38 | #include <defs.h> |
31 | #include <brcm_hw_ids.h> | 39 | #include <brcm_hw_ids.h> |
@@ -35,11 +43,21 @@ | |||
35 | #include "dhd_bus.h" | 43 | #include "dhd_bus.h" |
36 | #include "dhd_dbg.h" | 44 | #include "dhd_dbg.h" |
37 | #include "sdio_host.h" | 45 | #include "sdio_host.h" |
46 | #include "sdio_chip.h" | ||
38 | 47 | ||
39 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 | 48 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 |
40 | 49 | ||
50 | #define SDIO_VENDOR_ID_BROADCOM 0x02d0 | ||
41 | 51 | ||
42 | static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id) | 52 | #define DMA_ALIGN_MASK 0x03 |
53 | |||
54 | #define SDIO_FUNC1_BLOCKSIZE 64 | ||
55 | #define SDIO_FUNC2_BLOCKSIZE 512 | ||
56 | /* Maximum milliseconds to wait for F2 to come up */ | ||
57 | #define SDIO_WAIT_F2RDY 3000 | ||
58 | |||
59 | |||
60 | static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id) | ||
43 | { | 61 | { |
44 | struct brcmf_bus *bus_if = dev_get_drvdata(dev_id); | 62 | struct brcmf_bus *bus_if = dev_get_drvdata(dev_id); |
45 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 63 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
@@ -54,27 +72,46 @@ static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id) | |||
54 | sdiodev->irq_en = false; | 72 | sdiodev->irq_en = false; |
55 | } | 73 | } |
56 | 74 | ||
57 | brcmf_sdbrcm_isr(sdiodev->bus); | 75 | brcmf_sdio_isr(sdiodev->bus); |
58 | 76 | ||
59 | return IRQ_HANDLED; | 77 | return IRQ_HANDLED; |
60 | } | 78 | } |
61 | 79 | ||
62 | static void brcmf_sdio_ib_irqhandler(struct sdio_func *func) | 80 | static void brcmf_sdiod_ib_irqhandler(struct sdio_func *func) |
63 | { | 81 | { |
64 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev); | 82 | struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev); |
65 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 83 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
66 | 84 | ||
67 | brcmf_dbg(INTR, "IB intr triggered\n"); | 85 | brcmf_dbg(INTR, "IB intr triggered\n"); |
68 | 86 | ||
69 | brcmf_sdbrcm_isr(sdiodev->bus); | 87 | brcmf_sdio_isr(sdiodev->bus); |
70 | } | 88 | } |
71 | 89 | ||
72 | /* dummy handler for SDIO function 2 interrupt */ | 90 | /* dummy handler for SDIO function 2 interrupt */ |
73 | static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func) | 91 | static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func) |
92 | { | ||
93 | } | ||
94 | |||
95 | static bool brcmf_sdiod_pm_resume_error(struct brcmf_sdio_dev *sdiodev) | ||
74 | { | 96 | { |
97 | bool is_err = false; | ||
98 | #ifdef CONFIG_PM_SLEEP | ||
99 | is_err = atomic_read(&sdiodev->suspend); | ||
100 | #endif | ||
101 | return is_err; | ||
75 | } | 102 | } |
76 | 103 | ||
77 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | 104 | static void brcmf_sdiod_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, |
105 | wait_queue_head_t *wq) | ||
106 | { | ||
107 | #ifdef CONFIG_PM_SLEEP | ||
108 | int retry = 0; | ||
109 | while (atomic_read(&sdiodev->suspend) && retry++ != 30) | ||
110 | wait_event_timeout(*wq, false, HZ/100); | ||
111 | #endif | ||
112 | } | ||
113 | |||
114 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) | ||
78 | { | 115 | { |
79 | int ret = 0; | 116 | int ret = 0; |
80 | u8 data; | 117 | u8 data; |
@@ -84,7 +121,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
84 | brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n", | 121 | brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n", |
85 | sdiodev->pdata->oob_irq_nr); | 122 | sdiodev->pdata->oob_irq_nr); |
86 | ret = request_irq(sdiodev->pdata->oob_irq_nr, | 123 | ret = request_irq(sdiodev->pdata->oob_irq_nr, |
87 | brcmf_sdio_oob_irqhandler, | 124 | brcmf_sdiod_oob_irqhandler, |
88 | sdiodev->pdata->oob_irq_flags, | 125 | sdiodev->pdata->oob_irq_flags, |
89 | "brcmf_oob_intr", | 126 | "brcmf_oob_intr", |
90 | &sdiodev->func[1]->dev); | 127 | &sdiodev->func[1]->dev); |
@@ -108,36 +145,36 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
108 | sdio_claim_host(sdiodev->func[1]); | 145 | sdio_claim_host(sdiodev->func[1]); |
109 | 146 | ||
110 | /* must configure SDIO_CCCR_IENx to enable irq */ | 147 | /* must configure SDIO_CCCR_IENx to enable irq */ |
111 | data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); | 148 | data = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_IENx, &ret); |
112 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | 149 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; |
113 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); | 150 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); |
114 | 151 | ||
115 | /* redirect, configure and enable io for interrupt signal */ | 152 | /* redirect, configure and enable io for interrupt signal */ |
116 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | 153 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; |
117 | if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) | 154 | if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) |
118 | data |= SDIO_SEPINT_ACT_HI; | 155 | data |= SDIO_SEPINT_ACT_HI; |
119 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); | 156 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); |
120 | 157 | ||
121 | sdio_release_host(sdiodev->func[1]); | 158 | sdio_release_host(sdiodev->func[1]); |
122 | } else { | 159 | } else { |
123 | brcmf_dbg(SDIO, "Entering\n"); | 160 | brcmf_dbg(SDIO, "Entering\n"); |
124 | sdio_claim_host(sdiodev->func[1]); | 161 | sdio_claim_host(sdiodev->func[1]); |
125 | sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler); | 162 | sdio_claim_irq(sdiodev->func[1], brcmf_sdiod_ib_irqhandler); |
126 | sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler); | 163 | sdio_claim_irq(sdiodev->func[2], brcmf_sdiod_dummy_irqhandler); |
127 | sdio_release_host(sdiodev->func[1]); | 164 | sdio_release_host(sdiodev->func[1]); |
128 | } | 165 | } |
129 | 166 | ||
130 | return 0; | 167 | return 0; |
131 | } | 168 | } |
132 | 169 | ||
133 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | 170 | int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev) |
134 | { | 171 | { |
135 | brcmf_dbg(SDIO, "Entering\n"); | 172 | brcmf_dbg(SDIO, "Entering\n"); |
136 | 173 | ||
137 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { | 174 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { |
138 | sdio_claim_host(sdiodev->func[1]); | 175 | sdio_claim_host(sdiodev->func[1]); |
139 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); | 176 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); |
140 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); | 177 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); |
141 | sdio_release_host(sdiodev->func[1]); | 178 | sdio_release_host(sdiodev->func[1]); |
142 | 179 | ||
143 | if (sdiodev->oob_irq_requested) { | 180 | if (sdiodev->oob_irq_requested) { |
@@ -160,8 +197,117 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
160 | return 0; | 197 | return 0; |
161 | } | 198 | } |
162 | 199 | ||
200 | static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, | ||
201 | uint regaddr, u8 byte) | ||
202 | { | ||
203 | int err_ret; | ||
204 | |||
205 | /* | ||
206 | * Can only directly write to some F0 registers. | ||
207 | * Handle CCCR_IENx and CCCR_ABORT command | ||
208 | * as a special case. | ||
209 | */ | ||
210 | if ((regaddr == SDIO_CCCR_ABORT) || | ||
211 | (regaddr == SDIO_CCCR_IENx)) | ||
212 | sdio_writeb(func, byte, regaddr, &err_ret); | ||
213 | else | ||
214 | sdio_f0_writeb(func, byte, regaddr, &err_ret); | ||
215 | |||
216 | return err_ret; | ||
217 | } | ||
218 | |||
219 | static int brcmf_sdiod_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, | ||
220 | uint func, uint regaddr, u8 *byte) | ||
221 | { | ||
222 | int err_ret; | ||
223 | |||
224 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); | ||
225 | |||
226 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); | ||
227 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
228 | return -EIO; | ||
229 | |||
230 | if (rw && func == 0) { | ||
231 | /* handle F0 separately */ | ||
232 | err_ret = brcmf_sdiod_f0_writeb(sdiodev->func[func], | ||
233 | regaddr, *byte); | ||
234 | } else { | ||
235 | if (rw) /* CMD52 Write */ | ||
236 | sdio_writeb(sdiodev->func[func], *byte, regaddr, | ||
237 | &err_ret); | ||
238 | else if (func == 0) { | ||
239 | *byte = sdio_f0_readb(sdiodev->func[func], regaddr, | ||
240 | &err_ret); | ||
241 | } else { | ||
242 | *byte = sdio_readb(sdiodev->func[func], regaddr, | ||
243 | &err_ret); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | if (err_ret) { | ||
248 | /* | ||
249 | * SleepCSR register access can fail when | ||
250 | * waking up the device so reduce this noise | ||
251 | * in the logs. | ||
252 | */ | ||
253 | if (regaddr != SBSDIO_FUNC1_SLEEPCSR) | ||
254 | brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | ||
255 | rw ? "write" : "read", func, regaddr, *byte, | ||
256 | err_ret); | ||
257 | else | ||
258 | brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | ||
259 | rw ? "write" : "read", func, regaddr, *byte, | ||
260 | err_ret); | ||
261 | } | ||
262 | return err_ret; | ||
263 | } | ||
264 | |||
265 | static int brcmf_sdiod_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, | ||
266 | uint func, uint addr, u32 *word, | ||
267 | uint nbytes) | ||
268 | { | ||
269 | int err_ret = -EIO; | ||
270 | |||
271 | if (func == 0) { | ||
272 | brcmf_err("Only CMD52 allowed to F0\n"); | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | |||
276 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | ||
277 | rw, func, addr, nbytes); | ||
278 | |||
279 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | ||
280 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
281 | return -EIO; | ||
282 | |||
283 | if (rw) { /* CMD52 Write */ | ||
284 | if (nbytes == 4) | ||
285 | sdio_writel(sdiodev->func[func], *word, addr, | ||
286 | &err_ret); | ||
287 | else if (nbytes == 2) | ||
288 | sdio_writew(sdiodev->func[func], (*word & 0xFFFF), | ||
289 | addr, &err_ret); | ||
290 | else | ||
291 | brcmf_err("Invalid nbytes: %d\n", nbytes); | ||
292 | } else { /* CMD52 Read */ | ||
293 | if (nbytes == 4) | ||
294 | *word = sdio_readl(sdiodev->func[func], addr, &err_ret); | ||
295 | else if (nbytes == 2) | ||
296 | *word = sdio_readw(sdiodev->func[func], addr, | ||
297 | &err_ret) & 0xFFFF; | ||
298 | else | ||
299 | brcmf_err("Invalid nbytes: %d\n", nbytes); | ||
300 | } | ||
301 | |||
302 | if (err_ret) | ||
303 | brcmf_err("Failed to %s word, Err: 0x%08x\n", | ||
304 | rw ? "write" : "read", err_ret); | ||
305 | |||
306 | return err_ret; | ||
307 | } | ||
308 | |||
163 | static int | 309 | static int |
164 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | 310 | brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) |
165 | { | 311 | { |
166 | int err = 0, i; | 312 | int err = 0, i; |
167 | u8 addr[3]; | 313 | u8 addr[3]; |
@@ -176,7 +322,7 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
176 | do { | 322 | do { |
177 | if (retry) | 323 | if (retry) |
178 | usleep_range(1000, 2000); | 324 | usleep_range(1000, 2000); |
179 | err = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, | 325 | err = brcmf_sdiod_request_byte(sdiodev, SDIOH_WRITE, |
180 | SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i, | 326 | SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i, |
181 | &addr[i]); | 327 | &addr[i]); |
182 | } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 328 | } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
@@ -192,13 +338,13 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
192 | } | 338 | } |
193 | 339 | ||
194 | static int | 340 | static int |
195 | brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr) | 341 | brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr) |
196 | { | 342 | { |
197 | uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; | 343 | uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; |
198 | int err = 0; | 344 | int err = 0; |
199 | 345 | ||
200 | if (bar0 != sdiodev->sbwad) { | 346 | if (bar0 != sdiodev->sbwad) { |
201 | err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); | 347 | err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0); |
202 | if (err) | 348 | if (err) |
203 | return err; | 349 | return err; |
204 | 350 | ||
@@ -213,9 +359,8 @@ brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr) | |||
213 | return 0; | 359 | return 0; |
214 | } | 360 | } |
215 | 361 | ||
216 | int | 362 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
217 | brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | 363 | void *data, bool write) |
218 | void *data, bool write) | ||
219 | { | 364 | { |
220 | u8 func_num, reg_size; | 365 | u8 func_num, reg_size; |
221 | s32 retry = 0; | 366 | s32 retry = 0; |
@@ -237,7 +382,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
237 | func_num = SDIO_FUNC_1; | 382 | func_num = SDIO_FUNC_1; |
238 | reg_size = 4; | 383 | reg_size = 4; |
239 | 384 | ||
240 | ret = brcmf_sdio_addrprep(sdiodev, reg_size, &addr); | 385 | ret = brcmf_sdiod_addrprep(sdiodev, reg_size, &addr); |
241 | if (ret) | 386 | if (ret) |
242 | goto done; | 387 | goto done; |
243 | } | 388 | } |
@@ -248,10 +393,10 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
248 | if (retry) /* wait for 1 ms till bus get settled down */ | 393 | if (retry) /* wait for 1 ms till bus get settled down */ |
249 | usleep_range(1000, 2000); | 394 | usleep_range(1000, 2000); |
250 | if (reg_size == 1) | 395 | if (reg_size == 1) |
251 | ret = brcmf_sdioh_request_byte(sdiodev, write, | 396 | ret = brcmf_sdiod_request_byte(sdiodev, write, |
252 | func_num, addr, data); | 397 | func_num, addr, data); |
253 | else | 398 | else |
254 | ret = brcmf_sdioh_request_word(sdiodev, write, | 399 | ret = brcmf_sdiod_request_word(sdiodev, write, |
255 | func_num, addr, data, 4); | 400 | func_num, addr, data, 4); |
256 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 401 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
257 | 402 | ||
@@ -262,13 +407,13 @@ done: | |||
262 | return ret; | 407 | return ret; |
263 | } | 408 | } |
264 | 409 | ||
265 | u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | 410 | u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) |
266 | { | 411 | { |
267 | u8 data; | 412 | u8 data; |
268 | int retval; | 413 | int retval; |
269 | 414 | ||
270 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); | 415 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
271 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 416 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, false); |
272 | brcmf_dbg(SDIO, "data:0x%02x\n", data); | 417 | brcmf_dbg(SDIO, "data:0x%02x\n", data); |
273 | 418 | ||
274 | if (ret) | 419 | if (ret) |
@@ -277,13 +422,13 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
277 | return data; | 422 | return data; |
278 | } | 423 | } |
279 | 424 | ||
280 | u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | 425 | u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) |
281 | { | 426 | { |
282 | u32 data; | 427 | u32 data; |
283 | int retval; | 428 | int retval; |
284 | 429 | ||
285 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); | 430 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
286 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 431 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, false); |
287 | brcmf_dbg(SDIO, "data:0x%08x\n", data); | 432 | brcmf_dbg(SDIO, "data:0x%08x\n", data); |
288 | 433 | ||
289 | if (ret) | 434 | if (ret) |
@@ -292,37 +437,37 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
292 | return data; | 437 | return data; |
293 | } | 438 | } |
294 | 439 | ||
295 | void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, | 440 | void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, |
296 | u8 data, int *ret) | 441 | u8 data, int *ret) |
297 | { | 442 | { |
298 | int retval; | 443 | int retval; |
299 | 444 | ||
300 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); | 445 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); |
301 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 446 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, true); |
302 | 447 | ||
303 | if (ret) | 448 | if (ret) |
304 | *ret = retval; | 449 | *ret = retval; |
305 | } | 450 | } |
306 | 451 | ||
307 | void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | 452 | void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, |
308 | u32 data, int *ret) | 453 | u32 data, int *ret) |
309 | { | 454 | { |
310 | int retval; | 455 | int retval; |
311 | 456 | ||
312 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); | 457 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); |
313 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 458 | retval = brcmf_sdiod_regrw_helper(sdiodev, addr, &data, true); |
314 | 459 | ||
315 | if (ret) | 460 | if (ret) |
316 | *ret = retval; | 461 | *ret = retval; |
317 | } | 462 | } |
318 | 463 | ||
319 | static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | 464 | static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, |
320 | bool write, u32 addr, struct sk_buff *pkt) | 465 | bool write, u32 addr, struct sk_buff *pkt) |
321 | { | 466 | { |
322 | unsigned int req_sz; | 467 | unsigned int req_sz; |
323 | 468 | ||
324 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | 469 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); |
325 | if (brcmf_pm_resume_error(sdiodev)) | 470 | if (brcmf_sdiod_pm_resume_error(sdiodev)) |
326 | return -EIO; | 471 | return -EIO; |
327 | 472 | ||
328 | /* Single skb use the standard mmc interface */ | 473 | /* Single skb use the standard mmc interface */ |
@@ -345,7 +490,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
345 | } | 490 | } |
346 | 491 | ||
347 | /** | 492 | /** |
348 | * brcmf_sdio_sglist_rw - SDIO interface function for block data access | 493 | * brcmf_sdiod_sglist_rw - SDIO interface function for block data access |
349 | * @sdiodev: brcmfmac sdio device | 494 | * @sdiodev: brcmfmac sdio device |
350 | * @fn: SDIO function number | 495 | * @fn: SDIO function number |
351 | * @write: direction flag | 496 | * @write: direction flag |
@@ -356,9 +501,9 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
356 | * stack for block data access. It assumes that the skb passed down by the | 501 | * stack for block data access. It assumes that the skb passed down by the |
357 | * caller has already been padded and aligned. | 502 | * caller has already been padded and aligned. |
358 | */ | 503 | */ |
359 | static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | 504 | static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, |
360 | bool write, u32 addr, | 505 | bool write, u32 addr, |
361 | struct sk_buff_head *pktlist) | 506 | struct sk_buff_head *pktlist) |
362 | { | 507 | { |
363 | unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; | 508 | unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; |
364 | unsigned int max_req_sz, orig_offset, dst_offset; | 509 | unsigned int max_req_sz, orig_offset, dst_offset; |
@@ -376,8 +521,8 @@ static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
376 | if (!pktlist->qlen) | 521 | if (!pktlist->qlen) |
377 | return -EINVAL; | 522 | return -EINVAL; |
378 | 523 | ||
379 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | 524 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); |
380 | if (brcmf_pm_resume_error(sdiodev)) | 525 | if (brcmf_sdiod_pm_resume_error(sdiodev)) |
381 | return -EIO; | 526 | return -EIO; |
382 | 527 | ||
383 | target_list = pktlist; | 528 | target_list = pktlist; |
@@ -524,9 +669,7 @@ exit: | |||
524 | return ret; | 669 | return ret; |
525 | } | 670 | } |
526 | 671 | ||
527 | int | 672 | int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes) |
528 | brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | ||
529 | uint flags, u8 *buf, uint nbytes) | ||
530 | { | 673 | { |
531 | struct sk_buff *mypkt; | 674 | struct sk_buff *mypkt; |
532 | int err; | 675 | int err; |
@@ -538,7 +681,7 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
538 | return -EIO; | 681 | return -EIO; |
539 | } | 682 | } |
540 | 683 | ||
541 | err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt); | 684 | err = brcmf_sdiod_recv_pkt(sdiodev, mypkt); |
542 | if (!err) | 685 | if (!err) |
543 | memcpy(buf, mypkt->data, nbytes); | 686 | memcpy(buf, mypkt->data, nbytes); |
544 | 687 | ||
@@ -546,50 +689,47 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
546 | return err; | 689 | return err; |
547 | } | 690 | } |
548 | 691 | ||
549 | int | 692 | int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt) |
550 | brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | ||
551 | uint flags, struct sk_buff *pkt) | ||
552 | { | 693 | { |
553 | uint width; | 694 | u32 addr = sdiodev->sbwad; |
554 | int err = 0; | 695 | int err = 0; |
555 | 696 | ||
556 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", | 697 | brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len); |
557 | fn, addr, pkt->len); | ||
558 | 698 | ||
559 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 699 | err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); |
560 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); | ||
561 | if (err) | 700 | if (err) |
562 | goto done; | 701 | goto done; |
563 | 702 | ||
564 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt); | 703 | err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, pkt); |
565 | 704 | ||
566 | done: | 705 | done: |
567 | return err; | 706 | return err; |
568 | } | 707 | } |
569 | 708 | ||
570 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 709 | int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev, |
571 | uint flags, struct sk_buff_head *pktq, uint totlen) | 710 | struct sk_buff_head *pktq, uint totlen) |
572 | { | 711 | { |
573 | struct sk_buff *glom_skb; | 712 | struct sk_buff *glom_skb; |
574 | struct sk_buff *skb; | 713 | struct sk_buff *skb; |
575 | uint width; | 714 | u32 addr = sdiodev->sbwad; |
576 | int err = 0; | 715 | int err = 0; |
577 | 716 | ||
578 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", | 717 | brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", |
579 | fn, addr, pktq->qlen); | 718 | addr, pktq->qlen); |
580 | 719 | ||
581 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 720 | err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); |
582 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); | ||
583 | if (err) | 721 | if (err) |
584 | goto done; | 722 | goto done; |
585 | 723 | ||
586 | if (pktq->qlen == 1) | 724 | if (pktq->qlen == 1) |
587 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq->next); | 725 | err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, |
726 | pktq->next); | ||
588 | else if (!sdiodev->sg_support) { | 727 | else if (!sdiodev->sg_support) { |
589 | glom_skb = brcmu_pkt_buf_get_skb(totlen); | 728 | glom_skb = brcmu_pkt_buf_get_skb(totlen); |
590 | if (!glom_skb) | 729 | if (!glom_skb) |
591 | return -ENOMEM; | 730 | return -ENOMEM; |
592 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, glom_skb); | 731 | err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, |
732 | glom_skb); | ||
593 | if (err) | 733 | if (err) |
594 | goto done; | 734 | goto done; |
595 | 735 | ||
@@ -598,18 +738,17 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
598 | skb_pull(glom_skb, skb->len); | 738 | skb_pull(glom_skb, skb->len); |
599 | } | 739 | } |
600 | } else | 740 | } else |
601 | err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq); | 741 | err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, false, addr, |
742 | pktq); | ||
602 | 743 | ||
603 | done: | 744 | done: |
604 | return err; | 745 | return err; |
605 | } | 746 | } |
606 | 747 | ||
607 | int | 748 | int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes) |
608 | brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | ||
609 | uint flags, u8 *buf, uint nbytes) | ||
610 | { | 749 | { |
611 | struct sk_buff *mypkt; | 750 | struct sk_buff *mypkt; |
612 | uint width; | 751 | u32 addr = sdiodev->sbwad; |
613 | int err; | 752 | int err; |
614 | 753 | ||
615 | mypkt = brcmu_pkt_buf_get_skb(nbytes); | 754 | mypkt = brcmu_pkt_buf_get_skb(nbytes); |
@@ -621,48 +760,47 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
621 | 760 | ||
622 | memcpy(mypkt->data, buf, nbytes); | 761 | memcpy(mypkt->data, buf, nbytes); |
623 | 762 | ||
624 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 763 | err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); |
625 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); | ||
626 | 764 | ||
627 | if (!err) | 765 | if (!err) |
628 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt); | 766 | err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr, |
767 | mypkt); | ||
629 | 768 | ||
630 | brcmu_pkt_buf_free_skb(mypkt); | 769 | brcmu_pkt_buf_free_skb(mypkt); |
631 | return err; | 770 | return err; |
632 | 771 | ||
633 | } | 772 | } |
634 | 773 | ||
635 | int | 774 | int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev, |
636 | brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 775 | struct sk_buff_head *pktq) |
637 | uint flags, struct sk_buff_head *pktq) | ||
638 | { | 776 | { |
639 | struct sk_buff *skb; | 777 | struct sk_buff *skb; |
640 | uint width; | 778 | u32 addr = sdiodev->sbwad; |
641 | int err; | 779 | int err; |
642 | 780 | ||
643 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", | 781 | brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen); |
644 | fn, addr, pktq->qlen); | ||
645 | 782 | ||
646 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 783 | err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); |
647 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); | ||
648 | if (err) | 784 | if (err) |
649 | return err; | 785 | return err; |
650 | 786 | ||
651 | if (pktq->qlen == 1 || !sdiodev->sg_support) | 787 | if (pktq->qlen == 1 || !sdiodev->sg_support) |
652 | skb_queue_walk(pktq, skb) { | 788 | skb_queue_walk(pktq, skb) { |
653 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, skb); | 789 | err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, |
790 | addr, skb); | ||
654 | if (err) | 791 | if (err) |
655 | break; | 792 | break; |
656 | } | 793 | } |
657 | else | 794 | else |
658 | err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq); | 795 | err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr, |
796 | pktq); | ||
659 | 797 | ||
660 | return err; | 798 | return err; |
661 | } | 799 | } |
662 | 800 | ||
663 | int | 801 | int |
664 | brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | 802 | brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, |
665 | u8 *data, uint size) | 803 | u8 *data, uint size) |
666 | { | 804 | { |
667 | int bcmerror = 0; | 805 | int bcmerror = 0; |
668 | struct sk_buff *pkt; | 806 | struct sk_buff *pkt; |
@@ -689,7 +827,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
689 | /* Do the transfer(s) */ | 827 | /* Do the transfer(s) */ |
690 | while (size) { | 828 | while (size) { |
691 | /* Set the backplane window to include the start address */ | 829 | /* Set the backplane window to include the start address */ |
692 | bcmerror = brcmf_sdcard_set_sbaddr_window(sdiodev, address); | 830 | bcmerror = brcmf_sdiod_set_sbaddr_window(sdiodev, address); |
693 | if (bcmerror) | 831 | if (bcmerror) |
694 | break; | 832 | break; |
695 | 833 | ||
@@ -703,8 +841,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
703 | skb_put(pkt, dsize); | 841 | skb_put(pkt, dsize); |
704 | if (write) | 842 | if (write) |
705 | memcpy(pkt->data, data, dsize); | 843 | memcpy(pkt->data, data, dsize); |
706 | bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, | 844 | bcmerror = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, |
707 | sdaddr, pkt); | 845 | sdaddr, pkt); |
708 | if (bcmerror) { | 846 | if (bcmerror) { |
709 | brcmf_err("membytes transfer failed\n"); | 847 | brcmf_err("membytes transfer failed\n"); |
710 | break; | 848 | break; |
@@ -726,7 +864,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
726 | dev_kfree_skb(pkt); | 864 | dev_kfree_skb(pkt); |
727 | 865 | ||
728 | /* Return the window to backplane enumeration space for core access */ | 866 | /* Return the window to backplane enumeration space for core access */ |
729 | if (brcmf_sdcard_set_sbaddr_window(sdiodev, sdiodev->sbwad)) | 867 | if (brcmf_sdiod_set_sbaddr_window(sdiodev, sdiodev->sbwad)) |
730 | brcmf_err("FAILED to set window back to 0x%x\n", | 868 | brcmf_err("FAILED to set window back to 0x%x\n", |
731 | sdiodev->sbwad); | 869 | sdiodev->sbwad); |
732 | 870 | ||
@@ -735,65 +873,337 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
735 | return bcmerror; | 873 | return bcmerror; |
736 | } | 874 | } |
737 | 875 | ||
738 | int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | 876 | int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn) |
739 | { | 877 | { |
740 | char t_func = (char)fn; | 878 | char t_func = (char)fn; |
741 | brcmf_dbg(SDIO, "Enter\n"); | 879 | brcmf_dbg(SDIO, "Enter\n"); |
742 | 880 | ||
743 | /* issue abort cmd52 command through F0 */ | 881 | /* issue abort cmd52 command through F0 */ |
744 | brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, | 882 | brcmf_sdiod_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, |
745 | SDIO_CCCR_ABORT, &t_func); | 883 | SDIO_CCCR_ABORT, &t_func); |
746 | 884 | ||
747 | brcmf_dbg(SDIO, "Exit\n"); | 885 | brcmf_dbg(SDIO, "Exit\n"); |
748 | return 0; | 886 | return 0; |
749 | } | 887 | } |
750 | 888 | ||
751 | int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | 889 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) |
890 | { | ||
891 | sdiodev->bus_if->state = BRCMF_BUS_DOWN; | ||
892 | |||
893 | if (sdiodev->bus) { | ||
894 | brcmf_sdio_remove(sdiodev->bus); | ||
895 | sdiodev->bus = NULL; | ||
896 | } | ||
897 | |||
898 | /* Disable Function 2 */ | ||
899 | sdio_claim_host(sdiodev->func[2]); | ||
900 | sdio_disable_func(sdiodev->func[2]); | ||
901 | sdio_release_host(sdiodev->func[2]); | ||
902 | |||
903 | /* Disable Function 1 */ | ||
904 | sdio_claim_host(sdiodev->func[1]); | ||
905 | sdio_disable_func(sdiodev->func[1]); | ||
906 | sdio_release_host(sdiodev->func[1]); | ||
907 | |||
908 | sdiodev->sbwad = 0; | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) | ||
752 | { | 914 | { |
753 | u32 regs = 0; | 915 | struct sdio_func *func; |
916 | struct mmc_host *host; | ||
917 | uint max_blocks; | ||
754 | int ret = 0; | 918 | int ret = 0; |
755 | 919 | ||
756 | ret = brcmf_sdioh_attach(sdiodev); | 920 | sdiodev->num_funcs = 2; |
757 | if (ret) | 921 | |
922 | sdio_claim_host(sdiodev->func[1]); | ||
923 | |||
924 | ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE); | ||
925 | if (ret) { | ||
926 | brcmf_err("Failed to set F1 blocksize\n"); | ||
927 | sdio_release_host(sdiodev->func[1]); | ||
928 | goto out; | ||
929 | } | ||
930 | ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE); | ||
931 | if (ret) { | ||
932 | brcmf_err("Failed to set F2 blocksize\n"); | ||
933 | sdio_release_host(sdiodev->func[1]); | ||
934 | goto out; | ||
935 | } | ||
936 | |||
937 | /* increase F2 timeout */ | ||
938 | sdiodev->func[2]->enable_timeout = SDIO_WAIT_F2RDY; | ||
939 | |||
940 | /* Enable Function 1 */ | ||
941 | ret = sdio_enable_func(sdiodev->func[1]); | ||
942 | sdio_release_host(sdiodev->func[1]); | ||
943 | if (ret) { | ||
944 | brcmf_err("Failed to enable F1: err=%d\n", ret); | ||
758 | goto out; | 945 | goto out; |
946 | } | ||
759 | 947 | ||
760 | regs = SI_ENUM_BASE; | 948 | /* |
949 | * determine host related variables after brcmf_sdiod_probe() | ||
950 | * as func->cur_blksize is properly set and F2 init has been | ||
951 | * completed successfully. | ||
952 | */ | ||
953 | func = sdiodev->func[2]; | ||
954 | host = func->card->host; | ||
955 | sdiodev->sg_support = host->max_segs > 1; | ||
956 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
957 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
958 | max_blocks * func->cur_blksize); | ||
959 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
960 | SG_MAX_SINGLE_ALLOC); | ||
961 | sdiodev->max_segment_size = host->max_seg_size; | ||
761 | 962 | ||
762 | /* try to attach to the target device */ | 963 | /* try to attach to the target device */ |
763 | sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev); | 964 | sdiodev->bus = brcmf_sdio_probe(sdiodev); |
764 | if (!sdiodev->bus) { | 965 | if (!sdiodev->bus) { |
765 | brcmf_err("device attach failed\n"); | ||
766 | ret = -ENODEV; | 966 | ret = -ENODEV; |
767 | goto out; | 967 | goto out; |
768 | } | 968 | } |
769 | 969 | ||
770 | out: | 970 | out: |
771 | if (ret) | 971 | if (ret) |
772 | brcmf_sdio_remove(sdiodev); | 972 | brcmf_sdiod_remove(sdiodev); |
773 | 973 | ||
774 | return ret; | 974 | return ret; |
775 | } | 975 | } |
776 | 976 | ||
777 | int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev) | 977 | /* devices we support, null terminated */ |
978 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | ||
979 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)}, | ||
980 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, | ||
981 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | ||
982 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | ||
983 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | ||
984 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, | ||
985 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, | ||
986 | { /* end: all zeroes */ }, | ||
987 | }; | ||
988 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | ||
989 | |||
990 | static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata; | ||
991 | |||
992 | |||
993 | static int brcmf_ops_sdio_probe(struct sdio_func *func, | ||
994 | const struct sdio_device_id *id) | ||
778 | { | 995 | { |
779 | sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 996 | int err; |
997 | struct brcmf_sdio_dev *sdiodev; | ||
998 | struct brcmf_bus *bus_if; | ||
780 | 999 | ||
781 | if (sdiodev->bus) { | 1000 | brcmf_dbg(SDIO, "Enter\n"); |
782 | brcmf_sdbrcm_disconnect(sdiodev->bus); | 1001 | brcmf_dbg(SDIO, "Class=%x\n", func->class); |
783 | sdiodev->bus = NULL; | 1002 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); |
1003 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); | ||
1004 | brcmf_dbg(SDIO, "Function#: %d\n", func->num); | ||
1005 | |||
1006 | /* Consume func num 1 but dont do anything with it. */ | ||
1007 | if (func->num == 1) | ||
1008 | return 0; | ||
1009 | |||
1010 | /* Ignore anything but func 2 */ | ||
1011 | if (func->num != 2) | ||
1012 | return -ENODEV; | ||
1013 | |||
1014 | bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL); | ||
1015 | if (!bus_if) | ||
1016 | return -ENOMEM; | ||
1017 | sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); | ||
1018 | if (!sdiodev) { | ||
1019 | kfree(bus_if); | ||
1020 | return -ENOMEM; | ||
784 | } | 1021 | } |
785 | 1022 | ||
786 | brcmf_sdioh_detach(sdiodev); | 1023 | /* store refs to functions used. mmc_card does |
1024 | * not hold the F0 function pointer. | ||
1025 | */ | ||
1026 | sdiodev->func[0] = kmemdup(func, sizeof(*func), GFP_KERNEL); | ||
1027 | sdiodev->func[0]->num = 0; | ||
1028 | sdiodev->func[1] = func->card->sdio_func[0]; | ||
1029 | sdiodev->func[2] = func; | ||
1030 | |||
1031 | sdiodev->bus_if = bus_if; | ||
1032 | bus_if->bus_priv.sdio = sdiodev; | ||
1033 | bus_if->proto_type = BRCMF_PROTO_BCDC; | ||
1034 | dev_set_drvdata(&func->dev, bus_if); | ||
1035 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); | ||
1036 | sdiodev->dev = &sdiodev->func[1]->dev; | ||
1037 | sdiodev->pdata = brcmfmac_sdio_pdata; | ||
1038 | |||
1039 | atomic_set(&sdiodev->suspend, false); | ||
1040 | init_waitqueue_head(&sdiodev->request_byte_wait); | ||
1041 | init_waitqueue_head(&sdiodev->request_word_wait); | ||
1042 | init_waitqueue_head(&sdiodev->request_buffer_wait); | ||
1043 | |||
1044 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); | ||
1045 | err = brcmf_sdiod_probe(sdiodev); | ||
1046 | if (err) { | ||
1047 | brcmf_err("F2 error, probe failed %d...\n", err); | ||
1048 | goto fail; | ||
1049 | } | ||
787 | 1050 | ||
788 | sdiodev->sbwad = 0; | 1051 | brcmf_dbg(SDIO, "F2 init completed...\n"); |
1052 | return 0; | ||
1053 | |||
1054 | fail: | ||
1055 | dev_set_drvdata(&func->dev, NULL); | ||
1056 | dev_set_drvdata(&sdiodev->func[1]->dev, NULL); | ||
1057 | kfree(sdiodev->func[0]); | ||
1058 | kfree(sdiodev); | ||
1059 | kfree(bus_if); | ||
1060 | return err; | ||
1061 | } | ||
1062 | |||
1063 | static void brcmf_ops_sdio_remove(struct sdio_func *func) | ||
1064 | { | ||
1065 | struct brcmf_bus *bus_if; | ||
1066 | struct brcmf_sdio_dev *sdiodev; | ||
1067 | |||
1068 | brcmf_dbg(SDIO, "Enter\n"); | ||
1069 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); | ||
1070 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); | ||
1071 | brcmf_dbg(SDIO, "Function: %d\n", func->num); | ||
1072 | |||
1073 | if (func->num != 1 && func->num != 2) | ||
1074 | return; | ||
1075 | |||
1076 | bus_if = dev_get_drvdata(&func->dev); | ||
1077 | if (bus_if) { | ||
1078 | sdiodev = bus_if->bus_priv.sdio; | ||
1079 | brcmf_sdiod_remove(sdiodev); | ||
1080 | |||
1081 | dev_set_drvdata(&sdiodev->func[1]->dev, NULL); | ||
1082 | dev_set_drvdata(&sdiodev->func[2]->dev, NULL); | ||
1083 | |||
1084 | kfree(bus_if); | ||
1085 | kfree(sdiodev->func[0]); | ||
1086 | kfree(sdiodev); | ||
1087 | } | ||
1088 | |||
1089 | brcmf_dbg(SDIO, "Exit\n"); | ||
1090 | } | ||
1091 | |||
1092 | #ifdef CONFIG_PM_SLEEP | ||
1093 | static int brcmf_ops_sdio_suspend(struct device *dev) | ||
1094 | { | ||
1095 | mmc_pm_flag_t sdio_flags; | ||
1096 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
1097 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
1098 | int ret = 0; | ||
1099 | |||
1100 | brcmf_dbg(SDIO, "\n"); | ||
1101 | |||
1102 | atomic_set(&sdiodev->suspend, true); | ||
1103 | |||
1104 | sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); | ||
1105 | if (!(sdio_flags & MMC_PM_KEEP_POWER)) { | ||
1106 | brcmf_err("Host can't keep power while suspended\n"); | ||
1107 | return -EINVAL; | ||
1108 | } | ||
1109 | |||
1110 | ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); | ||
1111 | if (ret) { | ||
1112 | brcmf_err("Failed to set pm_flags\n"); | ||
1113 | return ret; | ||
1114 | } | ||
1115 | |||
1116 | brcmf_sdio_wd_timer(sdiodev->bus, 0); | ||
1117 | |||
1118 | return ret; | ||
1119 | } | ||
1120 | |||
1121 | static int brcmf_ops_sdio_resume(struct device *dev) | ||
1122 | { | ||
1123 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
1124 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
1125 | |||
1126 | brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); | ||
1127 | atomic_set(&sdiodev->suspend, false); | ||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | static const struct dev_pm_ops brcmf_sdio_pm_ops = { | ||
1132 | .suspend = brcmf_ops_sdio_suspend, | ||
1133 | .resume = brcmf_ops_sdio_resume, | ||
1134 | }; | ||
1135 | #endif /* CONFIG_PM_SLEEP */ | ||
1136 | |||
1137 | static struct sdio_driver brcmf_sdmmc_driver = { | ||
1138 | .probe = brcmf_ops_sdio_probe, | ||
1139 | .remove = brcmf_ops_sdio_remove, | ||
1140 | .name = BRCMFMAC_SDIO_PDATA_NAME, | ||
1141 | .id_table = brcmf_sdmmc_ids, | ||
1142 | #ifdef CONFIG_PM_SLEEP | ||
1143 | .drv = { | ||
1144 | .pm = &brcmf_sdio_pm_ops, | ||
1145 | }, | ||
1146 | #endif /* CONFIG_PM_SLEEP */ | ||
1147 | }; | ||
1148 | |||
1149 | static int brcmf_sdio_pd_probe(struct platform_device *pdev) | ||
1150 | { | ||
1151 | brcmf_dbg(SDIO, "Enter\n"); | ||
1152 | |||
1153 | brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev); | ||
1154 | |||
1155 | if (brcmfmac_sdio_pdata->power_on) | ||
1156 | brcmfmac_sdio_pdata->power_on(); | ||
1157 | |||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | static int brcmf_sdio_pd_remove(struct platform_device *pdev) | ||
1162 | { | ||
1163 | brcmf_dbg(SDIO, "Enter\n"); | ||
1164 | |||
1165 | if (brcmfmac_sdio_pdata->power_off) | ||
1166 | brcmfmac_sdio_pdata->power_off(); | ||
1167 | |||
1168 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
789 | 1169 | ||
790 | return 0; | 1170 | return 0; |
791 | } | 1171 | } |
792 | 1172 | ||
793 | void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable) | 1173 | static struct platform_driver brcmf_sdio_pd = { |
1174 | .remove = brcmf_sdio_pd_remove, | ||
1175 | .driver = { | ||
1176 | .name = BRCMFMAC_SDIO_PDATA_NAME, | ||
1177 | .owner = THIS_MODULE, | ||
1178 | } | ||
1179 | }; | ||
1180 | |||
1181 | void brcmf_sdio_register(void) | ||
1182 | { | ||
1183 | int ret; | ||
1184 | |||
1185 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | ||
1186 | if (ret) | ||
1187 | brcmf_err("sdio_register_driver failed: %d\n", ret); | ||
1188 | } | ||
1189 | |||
1190 | void brcmf_sdio_exit(void) | ||
794 | { | 1191 | { |
795 | if (enable) | 1192 | brcmf_dbg(SDIO, "Enter\n"); |
796 | brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); | 1193 | |
1194 | if (brcmfmac_sdio_pdata) | ||
1195 | platform_driver_unregister(&brcmf_sdio_pd); | ||
797 | else | 1196 | else |
798 | brcmf_sdbrcm_wd_timer(sdiodev->bus, 0); | 1197 | sdio_unregister_driver(&brcmf_sdmmc_driver); |
1198 | } | ||
1199 | |||
1200 | void __init brcmf_sdio_init(void) | ||
1201 | { | ||
1202 | int ret; | ||
1203 | |||
1204 | brcmf_dbg(SDIO, "Enter\n"); | ||
1205 | |||
1206 | ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe); | ||
1207 | if (ret == -ENODEV) | ||
1208 | brcmf_dbg(SDIO, "No platform data available.\n"); | ||
799 | } | 1209 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c deleted file mode 100644 index a511c27122b8..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ /dev/null | |||
@@ -1,552 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/mmc/sdio.h> | ||
20 | #include <linux/mmc/core.h> | ||
21 | #include <linux/mmc/sdio_func.h> | ||
22 | #include <linux/mmc/sdio_ids.h> | ||
23 | #include <linux/mmc/card.h> | ||
24 | #include <linux/mmc/host.h> | ||
25 | #include <linux/suspend.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/sched.h> /* request_irq() */ | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
31 | #include <net/cfg80211.h> | ||
32 | |||
33 | #include <defs.h> | ||
34 | #include <brcm_hw_ids.h> | ||
35 | #include <brcmu_utils.h> | ||
36 | #include <brcmu_wifi.h> | ||
37 | #include "sdio_host.h" | ||
38 | #include "sdio_chip.h" | ||
39 | #include "dhd_dbg.h" | ||
40 | #include "dhd_bus.h" | ||
41 | |||
42 | #define SDIO_VENDOR_ID_BROADCOM 0x02d0 | ||
43 | |||
44 | #define DMA_ALIGN_MASK 0x03 | ||
45 | |||
46 | #define SDIO_FUNC1_BLOCKSIZE 64 | ||
47 | #define SDIO_FUNC2_BLOCKSIZE 512 | ||
48 | |||
49 | /* devices we support, null terminated */ | ||
50 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | ||
51 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)}, | ||
52 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, | ||
53 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | ||
54 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | ||
55 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | ||
56 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, | ||
57 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, | ||
58 | { /* end: all zeroes */ }, | ||
59 | }; | ||
60 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | ||
61 | |||
62 | static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata; | ||
63 | |||
64 | |||
65 | bool | ||
66 | brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) | ||
67 | { | ||
68 | bool is_err = false; | ||
69 | #ifdef CONFIG_PM_SLEEP | ||
70 | is_err = atomic_read(&sdiodev->suspend); | ||
71 | #endif | ||
72 | return is_err; | ||
73 | } | ||
74 | |||
75 | void | ||
76 | brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq) | ||
77 | { | ||
78 | #ifdef CONFIG_PM_SLEEP | ||
79 | int retry = 0; | ||
80 | while (atomic_read(&sdiodev->suspend) && retry++ != 30) | ||
81 | wait_event_timeout(*wq, false, HZ/100); | ||
82 | #endif | ||
83 | } | ||
84 | |||
85 | static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, | ||
86 | uint regaddr, u8 *byte) | ||
87 | { | ||
88 | struct sdio_func *sdfunc = sdiodev->func[0]; | ||
89 | int err_ret; | ||
90 | |||
91 | /* | ||
92 | * Can only directly write to some F0 registers. | ||
93 | * Handle F2 enable/disable and Abort command | ||
94 | * as a special case. | ||
95 | */ | ||
96 | if (regaddr == SDIO_CCCR_IOEx) { | ||
97 | sdfunc = sdiodev->func[2]; | ||
98 | if (sdfunc) { | ||
99 | if (*byte & SDIO_FUNC_ENABLE_2) { | ||
100 | /* Enable Function 2 */ | ||
101 | err_ret = sdio_enable_func(sdfunc); | ||
102 | if (err_ret) | ||
103 | brcmf_err("enable F2 failed:%d\n", | ||
104 | err_ret); | ||
105 | } else { | ||
106 | /* Disable Function 2 */ | ||
107 | err_ret = sdio_disable_func(sdfunc); | ||
108 | if (err_ret) | ||
109 | brcmf_err("Disable F2 failed:%d\n", | ||
110 | err_ret); | ||
111 | } | ||
112 | } else { | ||
113 | err_ret = -ENOENT; | ||
114 | } | ||
115 | } else if ((regaddr == SDIO_CCCR_ABORT) || | ||
116 | (regaddr == SDIO_CCCR_IENx)) { | ||
117 | sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func), | ||
118 | GFP_KERNEL); | ||
119 | if (!sdfunc) | ||
120 | return -ENOMEM; | ||
121 | sdfunc->num = 0; | ||
122 | sdio_writeb(sdfunc, *byte, regaddr, &err_ret); | ||
123 | kfree(sdfunc); | ||
124 | } else if (regaddr < 0xF0) { | ||
125 | brcmf_err("F0 Wr:0x%02x: write disallowed\n", regaddr); | ||
126 | err_ret = -EPERM; | ||
127 | } else { | ||
128 | sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); | ||
129 | } | ||
130 | |||
131 | return err_ret; | ||
132 | } | ||
133 | |||
134 | int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, | ||
135 | uint regaddr, u8 *byte) | ||
136 | { | ||
137 | int err_ret; | ||
138 | |||
139 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); | ||
140 | |||
141 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); | ||
142 | if (brcmf_pm_resume_error(sdiodev)) | ||
143 | return -EIO; | ||
144 | |||
145 | if (rw && func == 0) { | ||
146 | /* handle F0 separately */ | ||
147 | err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); | ||
148 | } else { | ||
149 | if (rw) /* CMD52 Write */ | ||
150 | sdio_writeb(sdiodev->func[func], *byte, regaddr, | ||
151 | &err_ret); | ||
152 | else if (func == 0) { | ||
153 | *byte = sdio_f0_readb(sdiodev->func[func], regaddr, | ||
154 | &err_ret); | ||
155 | } else { | ||
156 | *byte = sdio_readb(sdiodev->func[func], regaddr, | ||
157 | &err_ret); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | if (err_ret) { | ||
162 | /* | ||
163 | * SleepCSR register access can fail when | ||
164 | * waking up the device so reduce this noise | ||
165 | * in the logs. | ||
166 | */ | ||
167 | if (regaddr != SBSDIO_FUNC1_SLEEPCSR) | ||
168 | brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | ||
169 | rw ? "write" : "read", func, regaddr, *byte, | ||
170 | err_ret); | ||
171 | else | ||
172 | brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", | ||
173 | rw ? "write" : "read", func, regaddr, *byte, | ||
174 | err_ret); | ||
175 | } | ||
176 | return err_ret; | ||
177 | } | ||
178 | |||
179 | int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, | ||
180 | uint rw, uint func, uint addr, u32 *word, | ||
181 | uint nbytes) | ||
182 | { | ||
183 | int err_ret = -EIO; | ||
184 | |||
185 | if (func == 0) { | ||
186 | brcmf_err("Only CMD52 allowed to F0\n"); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | |||
190 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | ||
191 | rw, func, addr, nbytes); | ||
192 | |||
193 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | ||
194 | if (brcmf_pm_resume_error(sdiodev)) | ||
195 | return -EIO; | ||
196 | |||
197 | if (rw) { /* CMD52 Write */ | ||
198 | if (nbytes == 4) | ||
199 | sdio_writel(sdiodev->func[func], *word, addr, | ||
200 | &err_ret); | ||
201 | else if (nbytes == 2) | ||
202 | sdio_writew(sdiodev->func[func], (*word & 0xFFFF), | ||
203 | addr, &err_ret); | ||
204 | else | ||
205 | brcmf_err("Invalid nbytes: %d\n", nbytes); | ||
206 | } else { /* CMD52 Read */ | ||
207 | if (nbytes == 4) | ||
208 | *word = sdio_readl(sdiodev->func[func], addr, &err_ret); | ||
209 | else if (nbytes == 2) | ||
210 | *word = sdio_readw(sdiodev->func[func], addr, | ||
211 | &err_ret) & 0xFFFF; | ||
212 | else | ||
213 | brcmf_err("Invalid nbytes: %d\n", nbytes); | ||
214 | } | ||
215 | |||
216 | if (err_ret) | ||
217 | brcmf_err("Failed to %s word, Err: 0x%08x\n", | ||
218 | rw ? "write" : "read", err_ret); | ||
219 | |||
220 | return err_ret; | ||
221 | } | ||
222 | |||
223 | static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) | ||
224 | { | ||
225 | /* read 24 bits and return valid 17 bit addr */ | ||
226 | int i, ret; | ||
227 | u32 scratch, regdata; | ||
228 | __le32 scratch_le; | ||
229 | u8 *ptr = (u8 *)&scratch_le; | ||
230 | |||
231 | for (i = 0; i < 3; i++) { | ||
232 | regdata = brcmf_sdio_regrl(sdiodev, regaddr, &ret); | ||
233 | if (ret != 0) | ||
234 | brcmf_err("Can't read!\n"); | ||
235 | |||
236 | *ptr++ = (u8) regdata; | ||
237 | regaddr++; | ||
238 | } | ||
239 | |||
240 | /* Only the lower 17-bits are valid */ | ||
241 | scratch = le32_to_cpu(scratch_le); | ||
242 | scratch &= 0x0001FFFF; | ||
243 | return scratch; | ||
244 | } | ||
245 | |||
246 | static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) | ||
247 | { | ||
248 | int err_ret; | ||
249 | u32 fbraddr; | ||
250 | u8 func; | ||
251 | |||
252 | brcmf_dbg(SDIO, "\n"); | ||
253 | |||
254 | /* Get the Card's common CIS address */ | ||
255 | sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, | ||
256 | SDIO_CCCR_CIS); | ||
257 | brcmf_dbg(SDIO, "Card's Common CIS Ptr = 0x%x\n", | ||
258 | sdiodev->func_cis_ptr[0]); | ||
259 | |||
260 | /* Get the Card's function CIS (for each function) */ | ||
261 | for (fbraddr = SDIO_FBR_BASE(1), func = 1; | ||
262 | func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { | ||
263 | sdiodev->func_cis_ptr[func] = | ||
264 | brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); | ||
265 | brcmf_dbg(SDIO, "Function %d CIS Ptr = 0x%x\n", | ||
266 | func, sdiodev->func_cis_ptr[func]); | ||
267 | } | ||
268 | |||
269 | /* Enable Function 1 */ | ||
270 | err_ret = sdio_enable_func(sdiodev->func[1]); | ||
271 | if (err_ret) | ||
272 | brcmf_err("Failed to enable F1 Err: 0x%08x\n", err_ret); | ||
273 | |||
274 | return false; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * Public entry points & extern's | ||
279 | */ | ||
280 | int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) | ||
281 | { | ||
282 | int err_ret = 0; | ||
283 | struct mmc_host *host; | ||
284 | struct sdio_func *func; | ||
285 | uint max_blocks; | ||
286 | |||
287 | brcmf_dbg(SDIO, "\n"); | ||
288 | |||
289 | sdiodev->num_funcs = 2; | ||
290 | |||
291 | sdio_claim_host(sdiodev->func[1]); | ||
292 | |||
293 | err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE); | ||
294 | if (err_ret) { | ||
295 | brcmf_err("Failed to set F1 blocksize\n"); | ||
296 | goto out; | ||
297 | } | ||
298 | |||
299 | err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE); | ||
300 | if (err_ret) { | ||
301 | brcmf_err("Failed to set F2 blocksize\n"); | ||
302 | goto out; | ||
303 | } | ||
304 | |||
305 | brcmf_sdioh_enablefuncs(sdiodev); | ||
306 | |||
307 | /* | ||
308 | * determine host related variables after brcmf_sdio_probe() | ||
309 | * as func->cur_blksize is properly set and F2 init has been | ||
310 | * completed successfully. | ||
311 | */ | ||
312 | func = sdiodev->func[2]; | ||
313 | host = func->card->host; | ||
314 | sdiodev->sg_support = host->max_segs > 1; | ||
315 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
316 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
317 | max_blocks * func->cur_blksize); | ||
318 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
319 | SG_MAX_SINGLE_ALLOC); | ||
320 | sdiodev->max_segment_size = host->max_seg_size; | ||
321 | out: | ||
322 | sdio_release_host(sdiodev->func[1]); | ||
323 | brcmf_dbg(SDIO, "Done\n"); | ||
324 | return err_ret; | ||
325 | } | ||
326 | |||
327 | void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) | ||
328 | { | ||
329 | brcmf_dbg(SDIO, "\n"); | ||
330 | |||
331 | /* Disable Function 2 */ | ||
332 | sdio_claim_host(sdiodev->func[2]); | ||
333 | sdio_disable_func(sdiodev->func[2]); | ||
334 | sdio_release_host(sdiodev->func[2]); | ||
335 | |||
336 | /* Disable Function 1 */ | ||
337 | sdio_claim_host(sdiodev->func[1]); | ||
338 | sdio_disable_func(sdiodev->func[1]); | ||
339 | sdio_release_host(sdiodev->func[1]); | ||
340 | |||
341 | } | ||
342 | |||
343 | static int brcmf_ops_sdio_probe(struct sdio_func *func, | ||
344 | const struct sdio_device_id *id) | ||
345 | { | ||
346 | int err; | ||
347 | struct brcmf_sdio_dev *sdiodev; | ||
348 | struct brcmf_bus *bus_if; | ||
349 | |||
350 | brcmf_dbg(SDIO, "Enter\n"); | ||
351 | brcmf_dbg(SDIO, "Class=%x\n", func->class); | ||
352 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); | ||
353 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); | ||
354 | brcmf_dbg(SDIO, "Function#: %d\n", func->num); | ||
355 | |||
356 | /* Consume func num 1 but dont do anything with it. */ | ||
357 | if (func->num == 1) | ||
358 | return 0; | ||
359 | |||
360 | /* Ignore anything but func 2 */ | ||
361 | if (func->num != 2) | ||
362 | return -ENODEV; | ||
363 | |||
364 | bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL); | ||
365 | if (!bus_if) | ||
366 | return -ENOMEM; | ||
367 | sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); | ||
368 | if (!sdiodev) { | ||
369 | kfree(bus_if); | ||
370 | return -ENOMEM; | ||
371 | } | ||
372 | |||
373 | sdiodev->func[0] = func->card->sdio_func[0]; | ||
374 | sdiodev->func[1] = func->card->sdio_func[0]; | ||
375 | sdiodev->func[2] = func; | ||
376 | |||
377 | sdiodev->bus_if = bus_if; | ||
378 | bus_if->bus_priv.sdio = sdiodev; | ||
379 | dev_set_drvdata(&func->dev, bus_if); | ||
380 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); | ||
381 | sdiodev->dev = &sdiodev->func[1]->dev; | ||
382 | sdiodev->pdata = brcmfmac_sdio_pdata; | ||
383 | |||
384 | atomic_set(&sdiodev->suspend, false); | ||
385 | init_waitqueue_head(&sdiodev->request_byte_wait); | ||
386 | init_waitqueue_head(&sdiodev->request_word_wait); | ||
387 | init_waitqueue_head(&sdiodev->request_buffer_wait); | ||
388 | |||
389 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n"); | ||
390 | err = brcmf_sdio_probe(sdiodev); | ||
391 | if (err) { | ||
392 | brcmf_err("F2 error, probe failed %d...\n", err); | ||
393 | goto fail; | ||
394 | } | ||
395 | |||
396 | brcmf_dbg(SDIO, "F2 init completed...\n"); | ||
397 | return 0; | ||
398 | |||
399 | fail: | ||
400 | dev_set_drvdata(&func->dev, NULL); | ||
401 | dev_set_drvdata(&sdiodev->func[1]->dev, NULL); | ||
402 | kfree(sdiodev); | ||
403 | kfree(bus_if); | ||
404 | return err; | ||
405 | } | ||
406 | |||
407 | static void brcmf_ops_sdio_remove(struct sdio_func *func) | ||
408 | { | ||
409 | struct brcmf_bus *bus_if; | ||
410 | struct brcmf_sdio_dev *sdiodev; | ||
411 | |||
412 | brcmf_dbg(SDIO, "Enter\n"); | ||
413 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); | ||
414 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); | ||
415 | brcmf_dbg(SDIO, "Function: %d\n", func->num); | ||
416 | |||
417 | if (func->num != 1 && func->num != 2) | ||
418 | return; | ||
419 | |||
420 | bus_if = dev_get_drvdata(&func->dev); | ||
421 | if (bus_if) { | ||
422 | sdiodev = bus_if->bus_priv.sdio; | ||
423 | brcmf_sdio_remove(sdiodev); | ||
424 | |||
425 | dev_set_drvdata(&sdiodev->func[1]->dev, NULL); | ||
426 | dev_set_drvdata(&sdiodev->func[2]->dev, NULL); | ||
427 | |||
428 | kfree(bus_if); | ||
429 | kfree(sdiodev); | ||
430 | } | ||
431 | |||
432 | brcmf_dbg(SDIO, "Exit\n"); | ||
433 | } | ||
434 | |||
435 | #ifdef CONFIG_PM_SLEEP | ||
436 | static int brcmf_sdio_suspend(struct device *dev) | ||
437 | { | ||
438 | mmc_pm_flag_t sdio_flags; | ||
439 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
440 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
441 | int ret = 0; | ||
442 | |||
443 | brcmf_dbg(SDIO, "\n"); | ||
444 | |||
445 | atomic_set(&sdiodev->suspend, true); | ||
446 | |||
447 | sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); | ||
448 | if (!(sdio_flags & MMC_PM_KEEP_POWER)) { | ||
449 | brcmf_err("Host can't keep power while suspended\n"); | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | |||
453 | ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); | ||
454 | if (ret) { | ||
455 | brcmf_err("Failed to set pm_flags\n"); | ||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | brcmf_sdio_wdtmr_enable(sdiodev, false); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | static int brcmf_sdio_resume(struct device *dev) | ||
465 | { | ||
466 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
467 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
468 | |||
469 | brcmf_sdio_wdtmr_enable(sdiodev, true); | ||
470 | atomic_set(&sdiodev->suspend, false); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static const struct dev_pm_ops brcmf_sdio_pm_ops = { | ||
475 | .suspend = brcmf_sdio_suspend, | ||
476 | .resume = brcmf_sdio_resume, | ||
477 | }; | ||
478 | #endif /* CONFIG_PM_SLEEP */ | ||
479 | |||
480 | static struct sdio_driver brcmf_sdmmc_driver = { | ||
481 | .probe = brcmf_ops_sdio_probe, | ||
482 | .remove = brcmf_ops_sdio_remove, | ||
483 | .name = BRCMFMAC_SDIO_PDATA_NAME, | ||
484 | .id_table = brcmf_sdmmc_ids, | ||
485 | #ifdef CONFIG_PM_SLEEP | ||
486 | .drv = { | ||
487 | .pm = &brcmf_sdio_pm_ops, | ||
488 | }, | ||
489 | #endif /* CONFIG_PM_SLEEP */ | ||
490 | }; | ||
491 | |||
492 | static int brcmf_sdio_pd_probe(struct platform_device *pdev) | ||
493 | { | ||
494 | brcmf_dbg(SDIO, "Enter\n"); | ||
495 | |||
496 | brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev); | ||
497 | |||
498 | if (brcmfmac_sdio_pdata->power_on) | ||
499 | brcmfmac_sdio_pdata->power_on(); | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static int brcmf_sdio_pd_remove(struct platform_device *pdev) | ||
505 | { | ||
506 | brcmf_dbg(SDIO, "Enter\n"); | ||
507 | |||
508 | if (brcmfmac_sdio_pdata->power_off) | ||
509 | brcmfmac_sdio_pdata->power_off(); | ||
510 | |||
511 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static struct platform_driver brcmf_sdio_pd = { | ||
517 | .remove = brcmf_sdio_pd_remove, | ||
518 | .driver = { | ||
519 | .name = BRCMFMAC_SDIO_PDATA_NAME, | ||
520 | .owner = THIS_MODULE, | ||
521 | } | ||
522 | }; | ||
523 | |||
524 | void brcmf_sdio_register(void) | ||
525 | { | ||
526 | int ret; | ||
527 | |||
528 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | ||
529 | if (ret) | ||
530 | brcmf_err("sdio_register_driver failed: %d\n", ret); | ||
531 | } | ||
532 | |||
533 | void brcmf_sdio_exit(void) | ||
534 | { | ||
535 | brcmf_dbg(SDIO, "Enter\n"); | ||
536 | |||
537 | if (brcmfmac_sdio_pdata) | ||
538 | platform_driver_unregister(&brcmf_sdio_pd); | ||
539 | else | ||
540 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
541 | } | ||
542 | |||
543 | void __init brcmf_sdio_init(void) | ||
544 | { | ||
545 | int ret; | ||
546 | |||
547 | brcmf_dbg(SDIO, "Enter\n"); | ||
548 | |||
549 | ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe); | ||
550 | if (ret == -ENODEV) | ||
551 | brcmf_dbg(SDIO, "No platform data available.\n"); | ||
552 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 6a54905528be..5c12a07673fa 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -24,6 +24,12 @@ enum brcmf_bus_state { | |||
24 | BRCMF_BUS_DATA /* Ready for frame transfers */ | 24 | BRCMF_BUS_DATA /* Ready for frame transfers */ |
25 | }; | 25 | }; |
26 | 26 | ||
27 | /* The level of bus communication with the dongle */ | ||
28 | enum brcmf_bus_protocol_type { | ||
29 | BRCMF_PROTO_BCDC, | ||
30 | BRCMF_PROTO_MSGBUF | ||
31 | }; | ||
32 | |||
27 | struct brcmf_bus_dcmd { | 33 | struct brcmf_bus_dcmd { |
28 | char *name; | 34 | char *name; |
29 | char *param; | 35 | char *param; |
@@ -65,6 +71,7 @@ struct brcmf_bus_ops { | |||
65 | * struct brcmf_bus - interface structure between common and bus layer | 71 | * struct brcmf_bus - interface structure between common and bus layer |
66 | * | 72 | * |
67 | * @bus_priv: pointer to private bus device. | 73 | * @bus_priv: pointer to private bus device. |
74 | * @proto_type: protocol type, bcdc or msgbuf | ||
68 | * @dev: device pointer of bus device. | 75 | * @dev: device pointer of bus device. |
69 | * @drvr: public driver information. | 76 | * @drvr: public driver information. |
70 | * @state: operational state of the bus interface. | 77 | * @state: operational state of the bus interface. |
@@ -80,6 +87,7 @@ struct brcmf_bus { | |||
80 | struct brcmf_sdio_dev *sdio; | 87 | struct brcmf_sdio_dev *sdio; |
81 | struct brcmf_usbdev *usb; | 88 | struct brcmf_usbdev *usb; |
82 | } bus_priv; | 89 | } bus_priv; |
90 | enum brcmf_bus_protocol_type proto_type; | ||
83 | struct device *dev; | 91 | struct device *dev; |
84 | struct brcmf_pub *drvr; | 92 | struct brcmf_pub *drvr; |
85 | enum brcmf_bus_state state; | 93 | enum brcmf_bus_state state; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 0f95f3e79c10..f214510e3bee 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -260,9 +260,6 @@ struct rte_console { | |||
260 | #define MAX_HDR_READ (1 << 6) | 260 | #define MAX_HDR_READ (1 << 6) |
261 | #define MAX_RX_DATASZ 2048 | 261 | #define MAX_RX_DATASZ 2048 |
262 | 262 | ||
263 | /* Maximum milliseconds to wait for F2 to come up */ | ||
264 | #define BRCMF_WAIT_F2RDY 3000 | ||
265 | |||
266 | /* Bump up limit on waiting for HT to account for first startup; | 263 | /* Bump up limit on waiting for HT to account for first startup; |
267 | * if the image is doing a CRC calculation before programming the PMU | 264 | * if the image is doing a CRC calculation before programming the PMU |
268 | * for HT availability, it could take a couple hundred ms more, so | 265 | * for HT availability, it could take a couple hundred ms more, so |
@@ -559,7 +556,7 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = { | |||
559 | }; | 556 | }; |
560 | 557 | ||
561 | 558 | ||
562 | static const struct firmware *brcmf_sdbrcm_get_fw(struct brcmf_sdio *bus, | 559 | static const struct firmware *brcmf_sdio_get_fw(struct brcmf_sdio *bus, |
563 | enum brcmf_firmware_type type) | 560 | enum brcmf_firmware_type type) |
564 | { | 561 | { |
565 | const struct firmware *fw; | 562 | const struct firmware *fw; |
@@ -624,8 +621,8 @@ r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset) | |||
624 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 621 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
625 | int ret; | 622 | int ret; |
626 | 623 | ||
627 | *regvar = brcmf_sdio_regrl(bus->sdiodev, | 624 | *regvar = brcmf_sdiod_regrl(bus->sdiodev, |
628 | bus->ci->c_inf[idx].base + offset, &ret); | 625 | bus->ci->c_inf[idx].base + offset, &ret); |
629 | 626 | ||
630 | return ret; | 627 | return ret; |
631 | } | 628 | } |
@@ -636,15 +633,15 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) | |||
636 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 633 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
637 | int ret; | 634 | int ret; |
638 | 635 | ||
639 | brcmf_sdio_regwl(bus->sdiodev, | 636 | brcmf_sdiod_regwl(bus->sdiodev, |
640 | bus->ci->c_inf[idx].base + reg_offset, | 637 | bus->ci->c_inf[idx].base + reg_offset, |
641 | regval, &ret); | 638 | regval, &ret); |
642 | 639 | ||
643 | return ret; | 640 | return ret; |
644 | } | 641 | } |
645 | 642 | ||
646 | static int | 643 | static int |
647 | brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on) | 644 | brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) |
648 | { | 645 | { |
649 | u8 wr_val = 0, rd_val, cmp_val, bmask; | 646 | u8 wr_val = 0, rd_val, cmp_val, bmask; |
650 | int err = 0; | 647 | int err = 0; |
@@ -654,8 +651,8 @@ brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on) | |||
654 | 651 | ||
655 | wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); | 652 | wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); |
656 | /* 1st KSO write goes to AOS wake up core if device is asleep */ | 653 | /* 1st KSO write goes to AOS wake up core if device is asleep */ |
657 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | 654 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, |
658 | wr_val, &err); | 655 | wr_val, &err); |
659 | if (err) { | 656 | if (err) { |
660 | brcmf_err("SDIO_AOS KSO write error: %d\n", err); | 657 | brcmf_err("SDIO_AOS KSO write error: %d\n", err); |
661 | return err; | 658 | return err; |
@@ -685,15 +682,15 @@ brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on) | |||
685 | * just one write attempt may fail, | 682 | * just one write attempt may fail, |
686 | * read it back until it matches written value | 683 | * read it back until it matches written value |
687 | */ | 684 | */ |
688 | rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | 685 | rd_val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, |
689 | &err); | 686 | &err); |
690 | if (((rd_val & bmask) == cmp_val) && !err) | 687 | if (((rd_val & bmask) == cmp_val) && !err) |
691 | break; | 688 | break; |
692 | brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n", | 689 | brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n", |
693 | try_cnt, MAX_KSO_ATTEMPTS, err); | 690 | try_cnt, MAX_KSO_ATTEMPTS, err); |
694 | udelay(KSO_WAIT_US); | 691 | udelay(KSO_WAIT_US); |
695 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | 692 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, |
696 | wr_val, &err); | 693 | wr_val, &err); |
697 | } while (try_cnt++ < MAX_KSO_ATTEMPTS); | 694 | } while (try_cnt++ < MAX_KSO_ATTEMPTS); |
698 | 695 | ||
699 | return err; | 696 | return err; |
@@ -704,7 +701,7 @@ brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on) | |||
704 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) | 701 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) |
705 | 702 | ||
706 | /* Turn backplane clock on or off */ | 703 | /* Turn backplane clock on or off */ |
707 | static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | 704 | static int brcmf_sdio_htclk(struct brcmf_sdio *bus, bool on, bool pendok) |
708 | { | 705 | { |
709 | int err; | 706 | int err; |
710 | u8 clkctl, clkreq, devctl; | 707 | u8 clkctl, clkreq, devctl; |
@@ -724,16 +721,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
724 | clkreq = | 721 | clkreq = |
725 | bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; | 722 | bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; |
726 | 723 | ||
727 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 724 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
728 | clkreq, &err); | 725 | clkreq, &err); |
729 | if (err) { | 726 | if (err) { |
730 | brcmf_err("HT Avail request error: %d\n", err); | 727 | brcmf_err("HT Avail request error: %d\n", err); |
731 | return -EBADE; | 728 | return -EBADE; |
732 | } | 729 | } |
733 | 730 | ||
734 | /* Check current status */ | 731 | /* Check current status */ |
735 | clkctl = brcmf_sdio_regrb(bus->sdiodev, | 732 | clkctl = brcmf_sdiod_regrb(bus->sdiodev, |
736 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 733 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
737 | if (err) { | 734 | if (err) { |
738 | brcmf_err("HT Avail read error: %d\n", err); | 735 | brcmf_err("HT Avail read error: %d\n", err); |
739 | return -EBADE; | 736 | return -EBADE; |
@@ -742,8 +739,8 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
742 | /* Go to pending and await interrupt if appropriate */ | 739 | /* Go to pending and await interrupt if appropriate */ |
743 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { | 740 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { |
744 | /* Allow only clock-available interrupt */ | 741 | /* Allow only clock-available interrupt */ |
745 | devctl = brcmf_sdio_regrb(bus->sdiodev, | 742 | devctl = brcmf_sdiod_regrb(bus->sdiodev, |
746 | SBSDIO_DEVICE_CTL, &err); | 743 | SBSDIO_DEVICE_CTL, &err); |
747 | if (err) { | 744 | if (err) { |
748 | brcmf_err("Devctl error setting CA: %d\n", | 745 | brcmf_err("Devctl error setting CA: %d\n", |
749 | err); | 746 | err); |
@@ -751,28 +748,28 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
751 | } | 748 | } |
752 | 749 | ||
753 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; | 750 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; |
754 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | 751 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
755 | devctl, &err); | 752 | devctl, &err); |
756 | brcmf_dbg(SDIO, "CLKCTL: set PENDING\n"); | 753 | brcmf_dbg(SDIO, "CLKCTL: set PENDING\n"); |
757 | bus->clkstate = CLK_PENDING; | 754 | bus->clkstate = CLK_PENDING; |
758 | 755 | ||
759 | return 0; | 756 | return 0; |
760 | } else if (bus->clkstate == CLK_PENDING) { | 757 | } else if (bus->clkstate == CLK_PENDING) { |
761 | /* Cancel CA-only interrupt filter */ | 758 | /* Cancel CA-only interrupt filter */ |
762 | devctl = brcmf_sdio_regrb(bus->sdiodev, | 759 | devctl = brcmf_sdiod_regrb(bus->sdiodev, |
763 | SBSDIO_DEVICE_CTL, &err); | 760 | SBSDIO_DEVICE_CTL, &err); |
764 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 761 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
765 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | 762 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
766 | devctl, &err); | 763 | devctl, &err); |
767 | } | 764 | } |
768 | 765 | ||
769 | /* Otherwise, wait here (polling) for HT Avail */ | 766 | /* Otherwise, wait here (polling) for HT Avail */ |
770 | timeout = jiffies + | 767 | timeout = jiffies + |
771 | msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); | 768 | msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); |
772 | while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { | 769 | while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { |
773 | clkctl = brcmf_sdio_regrb(bus->sdiodev, | 770 | clkctl = brcmf_sdiod_regrb(bus->sdiodev, |
774 | SBSDIO_FUNC1_CHIPCLKCSR, | 771 | SBSDIO_FUNC1_CHIPCLKCSR, |
775 | &err); | 772 | &err); |
776 | if (time_after(jiffies, timeout)) | 773 | if (time_after(jiffies, timeout)) |
777 | break; | 774 | break; |
778 | else | 775 | else |
@@ -805,16 +802,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
805 | 802 | ||
806 | if (bus->clkstate == CLK_PENDING) { | 803 | if (bus->clkstate == CLK_PENDING) { |
807 | /* Cancel CA-only interrupt filter */ | 804 | /* Cancel CA-only interrupt filter */ |
808 | devctl = brcmf_sdio_regrb(bus->sdiodev, | 805 | devctl = brcmf_sdiod_regrb(bus->sdiodev, |
809 | SBSDIO_DEVICE_CTL, &err); | 806 | SBSDIO_DEVICE_CTL, &err); |
810 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 807 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
811 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | 808 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
812 | devctl, &err); | 809 | devctl, &err); |
813 | } | 810 | } |
814 | 811 | ||
815 | bus->clkstate = CLK_SDONLY; | 812 | bus->clkstate = CLK_SDONLY; |
816 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 813 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
817 | clkreq, &err); | 814 | clkreq, &err); |
818 | brcmf_dbg(SDIO, "CLKCTL: turned OFF\n"); | 815 | brcmf_dbg(SDIO, "CLKCTL: turned OFF\n"); |
819 | if (err) { | 816 | if (err) { |
820 | brcmf_err("Failed access turning clock off: %d\n", | 817 | brcmf_err("Failed access turning clock off: %d\n", |
@@ -826,7 +823,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
826 | } | 823 | } |
827 | 824 | ||
828 | /* Change idle/active SD state */ | 825 | /* Change idle/active SD state */ |
829 | static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) | 826 | static int brcmf_sdio_sdclk(struct brcmf_sdio *bus, bool on) |
830 | { | 827 | { |
831 | brcmf_dbg(SDIO, "Enter\n"); | 828 | brcmf_dbg(SDIO, "Enter\n"); |
832 | 829 | ||
@@ -839,7 +836,7 @@ static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) | |||
839 | } | 836 | } |
840 | 837 | ||
841 | /* Transition SD and backplane clock readiness */ | 838 | /* Transition SD and backplane clock readiness */ |
842 | static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | 839 | static int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) |
843 | { | 840 | { |
844 | #ifdef DEBUG | 841 | #ifdef DEBUG |
845 | uint oldstate = bus->clkstate; | 842 | uint oldstate = bus->clkstate; |
@@ -850,7 +847,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
850 | /* Early exit if we're already there */ | 847 | /* Early exit if we're already there */ |
851 | if (bus->clkstate == target) { | 848 | if (bus->clkstate == target) { |
852 | if (target == CLK_AVAIL) { | 849 | if (target == CLK_AVAIL) { |
853 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 850 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); |
854 | bus->activity = true; | 851 | bus->activity = true; |
855 | } | 852 | } |
856 | return 0; | 853 | return 0; |
@@ -860,32 +857,32 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
860 | case CLK_AVAIL: | 857 | case CLK_AVAIL: |
861 | /* Make sure SD clock is available */ | 858 | /* Make sure SD clock is available */ |
862 | if (bus->clkstate == CLK_NONE) | 859 | if (bus->clkstate == CLK_NONE) |
863 | brcmf_sdbrcm_sdclk(bus, true); | 860 | brcmf_sdio_sdclk(bus, true); |
864 | /* Now request HT Avail on the backplane */ | 861 | /* Now request HT Avail on the backplane */ |
865 | brcmf_sdbrcm_htclk(bus, true, pendok); | 862 | brcmf_sdio_htclk(bus, true, pendok); |
866 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 863 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); |
867 | bus->activity = true; | 864 | bus->activity = true; |
868 | break; | 865 | break; |
869 | 866 | ||
870 | case CLK_SDONLY: | 867 | case CLK_SDONLY: |
871 | /* Remove HT request, or bring up SD clock */ | 868 | /* Remove HT request, or bring up SD clock */ |
872 | if (bus->clkstate == CLK_NONE) | 869 | if (bus->clkstate == CLK_NONE) |
873 | brcmf_sdbrcm_sdclk(bus, true); | 870 | brcmf_sdio_sdclk(bus, true); |
874 | else if (bus->clkstate == CLK_AVAIL) | 871 | else if (bus->clkstate == CLK_AVAIL) |
875 | brcmf_sdbrcm_htclk(bus, false, false); | 872 | brcmf_sdio_htclk(bus, false, false); |
876 | else | 873 | else |
877 | brcmf_err("request for %d -> %d\n", | 874 | brcmf_err("request for %d -> %d\n", |
878 | bus->clkstate, target); | 875 | bus->clkstate, target); |
879 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 876 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); |
880 | break; | 877 | break; |
881 | 878 | ||
882 | case CLK_NONE: | 879 | case CLK_NONE: |
883 | /* Make sure to remove HT request */ | 880 | /* Make sure to remove HT request */ |
884 | if (bus->clkstate == CLK_AVAIL) | 881 | if (bus->clkstate == CLK_AVAIL) |
885 | brcmf_sdbrcm_htclk(bus, false, false); | 882 | brcmf_sdio_htclk(bus, false, false); |
886 | /* Now remove the SD clock */ | 883 | /* Now remove the SD clock */ |
887 | brcmf_sdbrcm_sdclk(bus, false); | 884 | brcmf_sdio_sdclk(bus, false); |
888 | brcmf_sdbrcm_wd_timer(bus, 0); | 885 | brcmf_sdio_wd_timer(bus, 0); |
889 | break; | 886 | break; |
890 | } | 887 | } |
891 | #ifdef DEBUG | 888 | #ifdef DEBUG |
@@ -896,7 +893,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
896 | } | 893 | } |
897 | 894 | ||
898 | static int | 895 | static int |
899 | brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | 896 | brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) |
900 | { | 897 | { |
901 | int err = 0; | 898 | int err = 0; |
902 | brcmf_dbg(TRACE, "Enter\n"); | 899 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -919,13 +916,13 @@ brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
919 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | 916 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && |
920 | data_ok(bus))) | 917 | data_ok(bus))) |
921 | return -EBUSY; | 918 | return -EBUSY; |
922 | err = brcmf_sdbrcm_kso_control(bus, false); | 919 | err = brcmf_sdio_kso_control(bus, false); |
923 | /* disable watchdog */ | 920 | /* disable watchdog */ |
924 | if (!err) | 921 | if (!err) |
925 | brcmf_sdbrcm_wd_timer(bus, 0); | 922 | brcmf_sdio_wd_timer(bus, 0); |
926 | } else { | 923 | } else { |
927 | bus->idlecount = 0; | 924 | bus->idlecount = 0; |
928 | err = brcmf_sdbrcm_kso_control(bus, true); | 925 | err = brcmf_sdio_kso_control(bus, true); |
929 | } | 926 | } |
930 | if (!err) { | 927 | if (!err) { |
931 | /* Change state */ | 928 | /* Change state */ |
@@ -943,16 +940,16 @@ end: | |||
943 | /* control clocks */ | 940 | /* control clocks */ |
944 | if (sleep) { | 941 | if (sleep) { |
945 | if (!bus->sr_enabled) | 942 | if (!bus->sr_enabled) |
946 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok); | 943 | brcmf_sdio_clkctl(bus, CLK_NONE, pendok); |
947 | } else { | 944 | } else { |
948 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok); | 945 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); |
949 | } | 946 | } |
950 | 947 | ||
951 | return err; | 948 | return err; |
952 | 949 | ||
953 | } | 950 | } |
954 | 951 | ||
955 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | 952 | static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus) |
956 | { | 953 | { |
957 | u32 intstatus = 0; | 954 | u32 intstatus = 0; |
958 | u32 hmb_data; | 955 | u32 hmb_data; |
@@ -1028,7 +1025,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
1028 | return intstatus; | 1025 | return intstatus; |
1029 | } | 1026 | } |
1030 | 1027 | ||
1031 | static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | 1028 | static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) |
1032 | { | 1029 | { |
1033 | uint retries = 0; | 1030 | uint retries = 0; |
1034 | u16 lastrbc; | 1031 | u16 lastrbc; |
@@ -1040,18 +1037,18 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1040 | rtx ? ", send NAK" : ""); | 1037 | rtx ? ", send NAK" : ""); |
1041 | 1038 | ||
1042 | if (abort) | 1039 | if (abort) |
1043 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 1040 | brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2); |
1044 | 1041 | ||
1045 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 1042 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
1046 | SFC_RF_TERM, &err); | 1043 | SFC_RF_TERM, &err); |
1047 | bus->sdcnt.f1regdata++; | 1044 | bus->sdcnt.f1regdata++; |
1048 | 1045 | ||
1049 | /* Wait until the packet has been flushed (device/FIFO stable) */ | 1046 | /* Wait until the packet has been flushed (device/FIFO stable) */ |
1050 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { | 1047 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { |
1051 | hi = brcmf_sdio_regrb(bus->sdiodev, | 1048 | hi = brcmf_sdiod_regrb(bus->sdiodev, |
1052 | SBSDIO_FUNC1_RFRAMEBCHI, &err); | 1049 | SBSDIO_FUNC1_RFRAMEBCHI, &err); |
1053 | lo = brcmf_sdio_regrb(bus->sdiodev, | 1050 | lo = brcmf_sdiod_regrb(bus->sdiodev, |
1054 | SBSDIO_FUNC1_RFRAMEBCLO, &err); | 1051 | SBSDIO_FUNC1_RFRAMEBCLO, &err); |
1055 | bus->sdcnt.f1regdata += 2; | 1052 | bus->sdcnt.f1regdata += 2; |
1056 | 1053 | ||
1057 | if ((hi == 0) && (lo == 0)) | 1054 | if ((hi == 0) && (lo == 0)) |
@@ -1088,7 +1085,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1088 | } | 1085 | } |
1089 | 1086 | ||
1090 | /* return total length of buffer chain */ | 1087 | /* return total length of buffer chain */ |
1091 | static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus) | 1088 | static uint brcmf_sdio_glom_len(struct brcmf_sdio *bus) |
1092 | { | 1089 | { |
1093 | struct sk_buff *p; | 1090 | struct sk_buff *p; |
1094 | uint total; | 1091 | uint total; |
@@ -1099,7 +1096,7 @@ static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus) | |||
1099 | return total; | 1096 | return total; |
1100 | } | 1097 | } |
1101 | 1098 | ||
1102 | static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) | 1099 | static void brcmf_sdio_free_glom(struct brcmf_sdio *bus) |
1103 | { | 1100 | { |
1104 | struct sk_buff *cur, *next; | 1101 | struct sk_buff *cur, *next; |
1105 | 1102 | ||
@@ -1187,7 +1184,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, | |||
1187 | if ((u16)(~(len ^ checksum))) { | 1184 | if ((u16)(~(len ^ checksum))) { |
1188 | brcmf_err("HW header checksum error\n"); | 1185 | brcmf_err("HW header checksum error\n"); |
1189 | bus->sdcnt.rx_badhdr++; | 1186 | bus->sdcnt.rx_badhdr++; |
1190 | brcmf_sdbrcm_rxfail(bus, false, false); | 1187 | brcmf_sdio_rxfail(bus, false, false); |
1191 | return -EIO; | 1188 | return -EIO; |
1192 | } | 1189 | } |
1193 | if (len < SDPCM_HDRLEN) { | 1190 | if (len < SDPCM_HDRLEN) { |
@@ -1219,7 +1216,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, | |||
1219 | type != BRCMF_SDIO_FT_SUPER) { | 1216 | type != BRCMF_SDIO_FT_SUPER) { |
1220 | brcmf_err("HW header length too long\n"); | 1217 | brcmf_err("HW header length too long\n"); |
1221 | bus->sdcnt.rx_toolong++; | 1218 | bus->sdcnt.rx_toolong++; |
1222 | brcmf_sdbrcm_rxfail(bus, false, false); | 1219 | brcmf_sdio_rxfail(bus, false, false); |
1223 | rd->len = 0; | 1220 | rd->len = 0; |
1224 | return -EPROTO; | 1221 | return -EPROTO; |
1225 | } | 1222 | } |
@@ -1238,7 +1235,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, | |||
1238 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { | 1235 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { |
1239 | brcmf_err("seq %d: bad data offset\n", rx_seq); | 1236 | brcmf_err("seq %d: bad data offset\n", rx_seq); |
1240 | bus->sdcnt.rx_badhdr++; | 1237 | bus->sdcnt.rx_badhdr++; |
1241 | brcmf_sdbrcm_rxfail(bus, false, false); | 1238 | brcmf_sdio_rxfail(bus, false, false); |
1242 | rd->len = 0; | 1239 | rd->len = 0; |
1243 | return -ENXIO; | 1240 | return -ENXIO; |
1244 | } | 1241 | } |
@@ -1311,7 +1308,7 @@ static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, | |||
1311 | trace_brcmf_sdpcm_hdr(SDPCM_TX + !!(bus->txglom), header); | 1308 | trace_brcmf_sdpcm_hdr(SDPCM_TX + !!(bus->txglom), header); |
1312 | } | 1309 | } |
1313 | 1310 | ||
1314 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | 1311 | static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq) |
1315 | { | 1312 | { |
1316 | u16 dlen, totlen; | 1313 | u16 dlen, totlen; |
1317 | u8 *dptr, num = 0; | 1314 | u8 *dptr, num = 0; |
@@ -1391,7 +1388,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1391 | } | 1388 | } |
1392 | pfirst = pnext = NULL; | 1389 | pfirst = pnext = NULL; |
1393 | } else { | 1390 | } else { |
1394 | brcmf_sdbrcm_free_glom(bus); | 1391 | brcmf_sdio_free_glom(bus); |
1395 | num = 0; | 1392 | num = 0; |
1396 | } | 1393 | } |
1397 | 1394 | ||
@@ -1414,16 +1411,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1414 | } | 1411 | } |
1415 | 1412 | ||
1416 | pfirst = skb_peek(&bus->glom); | 1413 | pfirst = skb_peek(&bus->glom); |
1417 | dlen = (u16) brcmf_sdbrcm_glom_len(bus); | 1414 | dlen = (u16) brcmf_sdio_glom_len(bus); |
1418 | 1415 | ||
1419 | /* Do an SDIO read for the superframe. Configurable iovar to | 1416 | /* Do an SDIO read for the superframe. Configurable iovar to |
1420 | * read directly into the chained packet, or allocate a large | 1417 | * read directly into the chained packet, or allocate a large |
1421 | * packet and and copy into the chain. | 1418 | * packet and and copy into the chain. |
1422 | */ | 1419 | */ |
1423 | sdio_claim_host(bus->sdiodev->func[1]); | 1420 | sdio_claim_host(bus->sdiodev->func[1]); |
1424 | errcode = brcmf_sdcard_recv_chain(bus->sdiodev, | 1421 | errcode = brcmf_sdiod_recv_chain(bus->sdiodev, |
1425 | bus->sdiodev->sbwad, | 1422 | &bus->glom, dlen); |
1426 | SDIO_FUNC_2, F2SYNC, &bus->glom, dlen); | ||
1427 | sdio_release_host(bus->sdiodev->func[1]); | 1423 | sdio_release_host(bus->sdiodev->func[1]); |
1428 | bus->sdcnt.f2rxdata++; | 1424 | bus->sdcnt.f2rxdata++; |
1429 | 1425 | ||
@@ -1434,12 +1430,12 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1434 | 1430 | ||
1435 | sdio_claim_host(bus->sdiodev->func[1]); | 1431 | sdio_claim_host(bus->sdiodev->func[1]); |
1436 | if (bus->glomerr++ < 3) { | 1432 | if (bus->glomerr++ < 3) { |
1437 | brcmf_sdbrcm_rxfail(bus, true, true); | 1433 | brcmf_sdio_rxfail(bus, true, true); |
1438 | } else { | 1434 | } else { |
1439 | bus->glomerr = 0; | 1435 | bus->glomerr = 0; |
1440 | brcmf_sdbrcm_rxfail(bus, true, false); | 1436 | brcmf_sdio_rxfail(bus, true, false); |
1441 | bus->sdcnt.rxglomfail++; | 1437 | bus->sdcnt.rxglomfail++; |
1442 | brcmf_sdbrcm_free_glom(bus); | 1438 | brcmf_sdio_free_glom(bus); |
1443 | } | 1439 | } |
1444 | sdio_release_host(bus->sdiodev->func[1]); | 1440 | sdio_release_host(bus->sdiodev->func[1]); |
1445 | return 0; | 1441 | return 0; |
@@ -1487,12 +1483,12 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1487 | if (bus->glomerr++ < 3) { | 1483 | if (bus->glomerr++ < 3) { |
1488 | /* Restore superframe header space */ | 1484 | /* Restore superframe header space */ |
1489 | skb_push(pfirst, sfdoff); | 1485 | skb_push(pfirst, sfdoff); |
1490 | brcmf_sdbrcm_rxfail(bus, true, true); | 1486 | brcmf_sdio_rxfail(bus, true, true); |
1491 | } else { | 1487 | } else { |
1492 | bus->glomerr = 0; | 1488 | bus->glomerr = 0; |
1493 | brcmf_sdbrcm_rxfail(bus, true, false); | 1489 | brcmf_sdio_rxfail(bus, true, false); |
1494 | bus->sdcnt.rxglomfail++; | 1490 | bus->sdcnt.rxglomfail++; |
1495 | brcmf_sdbrcm_free_glom(bus); | 1491 | brcmf_sdio_free_glom(bus); |
1496 | } | 1492 | } |
1497 | sdio_release_host(bus->sdiodev->func[1]); | 1493 | sdio_release_host(bus->sdiodev->func[1]); |
1498 | bus->cur_read.len = 0; | 1494 | bus->cur_read.len = 0; |
@@ -1536,8 +1532,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1536 | return num; | 1532 | return num; |
1537 | } | 1533 | } |
1538 | 1534 | ||
1539 | static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition, | 1535 | static int brcmf_sdio_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition, |
1540 | bool *pending) | 1536 | bool *pending) |
1541 | { | 1537 | { |
1542 | DECLARE_WAITQUEUE(wait, current); | 1538 | DECLARE_WAITQUEUE(wait, current); |
1543 | int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT); | 1539 | int timeout = msecs_to_jiffies(DCMD_RESP_TIMEOUT); |
@@ -1558,7 +1554,7 @@ static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition, | |||
1558 | return timeout; | 1554 | return timeout; |
1559 | } | 1555 | } |
1560 | 1556 | ||
1561 | static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_sdio *bus) | 1557 | static int brcmf_sdio_dcmd_resp_wake(struct brcmf_sdio *bus) |
1562 | { | 1558 | { |
1563 | if (waitqueue_active(&bus->dcmd_resp_wait)) | 1559 | if (waitqueue_active(&bus->dcmd_resp_wait)) |
1564 | wake_up_interruptible(&bus->dcmd_resp_wait); | 1560 | wake_up_interruptible(&bus->dcmd_resp_wait); |
@@ -1566,7 +1562,7 @@ static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_sdio *bus) | |||
1566 | return 0; | 1562 | return 0; |
1567 | } | 1563 | } |
1568 | static void | 1564 | static void |
1569 | brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | 1565 | brcmf_sdio_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) |
1570 | { | 1566 | { |
1571 | uint rdlen, pad; | 1567 | uint rdlen, pad; |
1572 | u8 *buf = NULL, *rbuf; | 1568 | u8 *buf = NULL, *rbuf; |
@@ -1604,7 +1600,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | |||
1604 | if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) { | 1600 | if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) { |
1605 | brcmf_err("%d-byte control read exceeds %d-byte buffer\n", | 1601 | brcmf_err("%d-byte control read exceeds %d-byte buffer\n", |
1606 | rdlen, bus->sdiodev->bus_if->maxctl); | 1602 | rdlen, bus->sdiodev->bus_if->maxctl); |
1607 | brcmf_sdbrcm_rxfail(bus, false, false); | 1603 | brcmf_sdio_rxfail(bus, false, false); |
1608 | goto done; | 1604 | goto done; |
1609 | } | 1605 | } |
1610 | 1606 | ||
@@ -1612,15 +1608,12 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | |||
1612 | brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", | 1608 | brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", |
1613 | len, len - doff, bus->sdiodev->bus_if->maxctl); | 1609 | len, len - doff, bus->sdiodev->bus_if->maxctl); |
1614 | bus->sdcnt.rx_toolong++; | 1610 | bus->sdcnt.rx_toolong++; |
1615 | brcmf_sdbrcm_rxfail(bus, false, false); | 1611 | brcmf_sdio_rxfail(bus, false, false); |
1616 | goto done; | 1612 | goto done; |
1617 | } | 1613 | } |
1618 | 1614 | ||
1619 | /* Read remain of frame body */ | 1615 | /* Read remain of frame body */ |
1620 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, | 1616 | sdret = brcmf_sdiod_recv_buf(bus->sdiodev, rbuf, rdlen); |
1621 | bus->sdiodev->sbwad, | ||
1622 | SDIO_FUNC_2, | ||
1623 | F2SYNC, rbuf, rdlen); | ||
1624 | bus->sdcnt.f2rxdata++; | 1617 | bus->sdcnt.f2rxdata++; |
1625 | 1618 | ||
1626 | /* Control frame failures need retransmission */ | 1619 | /* Control frame failures need retransmission */ |
@@ -1628,7 +1621,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) | |||
1628 | brcmf_err("read %d control bytes failed: %d\n", | 1621 | brcmf_err("read %d control bytes failed: %d\n", |
1629 | rdlen, sdret); | 1622 | rdlen, sdret); |
1630 | bus->sdcnt.rxc_errors++; | 1623 | bus->sdcnt.rxc_errors++; |
1631 | brcmf_sdbrcm_rxfail(bus, true, true); | 1624 | brcmf_sdio_rxfail(bus, true, true); |
1632 | goto done; | 1625 | goto done; |
1633 | } else | 1626 | } else |
1634 | memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen); | 1627 | memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen); |
@@ -1653,11 +1646,11 @@ gotpkt: | |||
1653 | 1646 | ||
1654 | done: | 1647 | done: |
1655 | /* Awake any waiters */ | 1648 | /* Awake any waiters */ |
1656 | brcmf_sdbrcm_dcmd_resp_wake(bus); | 1649 | brcmf_sdio_dcmd_resp_wake(bus); |
1657 | } | 1650 | } |
1658 | 1651 | ||
1659 | /* Pad read to blocksize for efficiency */ | 1652 | /* Pad read to blocksize for efficiency */ |
1660 | static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) | 1653 | static void brcmf_sdio_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) |
1661 | { | 1654 | { |
1662 | if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) { | 1655 | if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) { |
1663 | *pad = bus->blocksize - (*rdlen % bus->blocksize); | 1656 | *pad = bus->blocksize - (*rdlen % bus->blocksize); |
@@ -1694,7 +1687,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1694 | u8 cnt; | 1687 | u8 cnt; |
1695 | brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", | 1688 | brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", |
1696 | bus->glomd, skb_peek(&bus->glom)); | 1689 | bus->glomd, skb_peek(&bus->glom)); |
1697 | cnt = brcmf_sdbrcm_rxglom(bus, rd->seq_num); | 1690 | cnt = brcmf_sdio_rxglom(bus, rd->seq_num); |
1698 | brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); | 1691 | brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); |
1699 | rd->seq_num += cnt - 1; | 1692 | rd->seq_num += cnt - 1; |
1700 | rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; | 1693 | rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; |
@@ -1705,17 +1698,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1705 | /* read header first for unknow frame length */ | 1698 | /* read header first for unknow frame length */ |
1706 | sdio_claim_host(bus->sdiodev->func[1]); | 1699 | sdio_claim_host(bus->sdiodev->func[1]); |
1707 | if (!rd->len) { | 1700 | if (!rd->len) { |
1708 | ret = brcmf_sdcard_recv_buf(bus->sdiodev, | 1701 | ret = brcmf_sdiod_recv_buf(bus->sdiodev, |
1709 | bus->sdiodev->sbwad, | 1702 | bus->rxhdr, BRCMF_FIRSTREAD); |
1710 | SDIO_FUNC_2, F2SYNC, | ||
1711 | bus->rxhdr, | ||
1712 | BRCMF_FIRSTREAD); | ||
1713 | bus->sdcnt.f2rxhdrs++; | 1703 | bus->sdcnt.f2rxhdrs++; |
1714 | if (ret < 0) { | 1704 | if (ret < 0) { |
1715 | brcmf_err("RXHEADER FAILED: %d\n", | 1705 | brcmf_err("RXHEADER FAILED: %d\n", |
1716 | ret); | 1706 | ret); |
1717 | bus->sdcnt.rx_hdrfail++; | 1707 | bus->sdcnt.rx_hdrfail++; |
1718 | brcmf_sdbrcm_rxfail(bus, true, true); | 1708 | brcmf_sdio_rxfail(bus, true, true); |
1719 | sdio_release_host(bus->sdiodev->func[1]); | 1709 | sdio_release_host(bus->sdiodev->func[1]); |
1720 | continue; | 1710 | continue; |
1721 | } | 1711 | } |
@@ -1734,9 +1724,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1734 | } | 1724 | } |
1735 | 1725 | ||
1736 | if (rd->channel == SDPCM_CONTROL_CHANNEL) { | 1726 | if (rd->channel == SDPCM_CONTROL_CHANNEL) { |
1737 | brcmf_sdbrcm_read_control(bus, bus->rxhdr, | 1727 | brcmf_sdio_read_control(bus, bus->rxhdr, |
1738 | rd->len, | 1728 | rd->len, |
1739 | rd->dat_offset); | 1729 | rd->dat_offset); |
1740 | /* prepare the descriptor for the next read */ | 1730 | /* prepare the descriptor for the next read */ |
1741 | rd->len = rd->len_nxtfrm << 4; | 1731 | rd->len = rd->len_nxtfrm << 4; |
1742 | rd->len_nxtfrm = 0; | 1732 | rd->len_nxtfrm = 0; |
@@ -1750,14 +1740,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1750 | head_read = BRCMF_FIRSTREAD; | 1740 | head_read = BRCMF_FIRSTREAD; |
1751 | } | 1741 | } |
1752 | 1742 | ||
1753 | brcmf_pad(bus, &pad, &rd->len_left); | 1743 | brcmf_sdio_pad(bus, &pad, &rd->len_left); |
1754 | 1744 | ||
1755 | pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + | 1745 | pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + |
1756 | bus->head_align); | 1746 | bus->head_align); |
1757 | if (!pkt) { | 1747 | if (!pkt) { |
1758 | /* Give up on data, request rtx of events */ | 1748 | /* Give up on data, request rtx of events */ |
1759 | brcmf_err("brcmu_pkt_buf_get_skb failed\n"); | 1749 | brcmf_err("brcmu_pkt_buf_get_skb failed\n"); |
1760 | brcmf_sdbrcm_rxfail(bus, false, | 1750 | brcmf_sdio_rxfail(bus, false, |
1761 | RETRYCHAN(rd->channel)); | 1751 | RETRYCHAN(rd->channel)); |
1762 | sdio_release_host(bus->sdiodev->func[1]); | 1752 | sdio_release_host(bus->sdiodev->func[1]); |
1763 | continue; | 1753 | continue; |
@@ -1765,8 +1755,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1765 | skb_pull(pkt, head_read); | 1755 | skb_pull(pkt, head_read); |
1766 | pkt_align(pkt, rd->len_left, bus->head_align); | 1756 | pkt_align(pkt, rd->len_left, bus->head_align); |
1767 | 1757 | ||
1768 | ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1758 | ret = brcmf_sdiod_recv_pkt(bus->sdiodev, pkt); |
1769 | SDIO_FUNC_2, F2SYNC, pkt); | ||
1770 | bus->sdcnt.f2rxdata++; | 1759 | bus->sdcnt.f2rxdata++; |
1771 | sdio_release_host(bus->sdiodev->func[1]); | 1760 | sdio_release_host(bus->sdiodev->func[1]); |
1772 | 1761 | ||
@@ -1775,7 +1764,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1775 | rd->len, rd->channel, ret); | 1764 | rd->len, rd->channel, ret); |
1776 | brcmu_pkt_buf_free_skb(pkt); | 1765 | brcmu_pkt_buf_free_skb(pkt); |
1777 | sdio_claim_host(bus->sdiodev->func[1]); | 1766 | sdio_claim_host(bus->sdiodev->func[1]); |
1778 | brcmf_sdbrcm_rxfail(bus, true, | 1767 | brcmf_sdio_rxfail(bus, true, |
1779 | RETRYCHAN(rd->channel)); | 1768 | RETRYCHAN(rd->channel)); |
1780 | sdio_release_host(bus->sdiodev->func[1]); | 1769 | sdio_release_host(bus->sdiodev->func[1]); |
1781 | continue; | 1770 | continue; |
@@ -1800,7 +1789,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1800 | rd->len, | 1789 | rd->len, |
1801 | roundup(rd_new.len, 16) >> 4); | 1790 | roundup(rd_new.len, 16) >> 4); |
1802 | rd->len = 0; | 1791 | rd->len = 0; |
1803 | brcmf_sdbrcm_rxfail(bus, true, true); | 1792 | brcmf_sdio_rxfail(bus, true, true); |
1804 | sdio_release_host(bus->sdiodev->func[1]); | 1793 | sdio_release_host(bus->sdiodev->func[1]); |
1805 | brcmu_pkt_buf_free_skb(pkt); | 1794 | brcmu_pkt_buf_free_skb(pkt); |
1806 | continue; | 1795 | continue; |
@@ -1822,7 +1811,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1822 | /* Force retry w/normal header read */ | 1811 | /* Force retry w/normal header read */ |
1823 | rd->len = 0; | 1812 | rd->len = 0; |
1824 | sdio_claim_host(bus->sdiodev->func[1]); | 1813 | sdio_claim_host(bus->sdiodev->func[1]); |
1825 | brcmf_sdbrcm_rxfail(bus, false, true); | 1814 | brcmf_sdio_rxfail(bus, false, true); |
1826 | sdio_release_host(bus->sdiodev->func[1]); | 1815 | sdio_release_host(bus->sdiodev->func[1]); |
1827 | brcmu_pkt_buf_free_skb(pkt); | 1816 | brcmu_pkt_buf_free_skb(pkt); |
1828 | continue; | 1817 | continue; |
@@ -1847,7 +1836,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1847 | brcmf_err("%s: glom superframe w/o " | 1836 | brcmf_err("%s: glom superframe w/o " |
1848 | "descriptor!\n", __func__); | 1837 | "descriptor!\n", __func__); |
1849 | sdio_claim_host(bus->sdiodev->func[1]); | 1838 | sdio_claim_host(bus->sdiodev->func[1]); |
1850 | brcmf_sdbrcm_rxfail(bus, false, false); | 1839 | brcmf_sdio_rxfail(bus, false, false); |
1851 | sdio_release_host(bus->sdiodev->func[1]); | 1840 | sdio_release_host(bus->sdiodev->func[1]); |
1852 | } | 1841 | } |
1853 | /* prepare the descriptor for the next read */ | 1842 | /* prepare the descriptor for the next read */ |
@@ -1891,7 +1880,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1891 | } | 1880 | } |
1892 | 1881 | ||
1893 | static void | 1882 | static void |
1894 | brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | 1883 | brcmf_sdio_wait_event_wakeup(struct brcmf_sdio *bus) |
1895 | { | 1884 | { |
1896 | if (waitqueue_active(&bus->ctrl_wait)) | 1885 | if (waitqueue_active(&bus->ctrl_wait)) |
1897 | wake_up_interruptible(&bus->ctrl_wait); | 1886 | wake_up_interruptible(&bus->ctrl_wait); |
@@ -2107,8 +2096,8 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq) | |||
2107 | 2096 | ||
2108 | /* Writes a HW/SW header into the packet and sends it. */ | 2097 | /* Writes a HW/SW header into the packet and sends it. */ |
2109 | /* Assumes: (a) header space already there, (b) caller holds lock */ | 2098 | /* Assumes: (a) header space already there, (b) caller holds lock */ |
2110 | static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | 2099 | static int brcmf_sdio_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq, |
2111 | uint chan) | 2100 | uint chan) |
2112 | { | 2101 | { |
2113 | int ret; | 2102 | int ret; |
2114 | int i; | 2103 | int i; |
@@ -2121,8 +2110,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | |||
2121 | goto done; | 2110 | goto done; |
2122 | 2111 | ||
2123 | sdio_claim_host(bus->sdiodev->func[1]); | 2112 | sdio_claim_host(bus->sdiodev->func[1]); |
2124 | ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 2113 | ret = brcmf_sdiod_send_pkt(bus->sdiodev, pktq); |
2125 | SDIO_FUNC_2, F2SYNC, pktq); | ||
2126 | bus->sdcnt.f2txdata++; | 2114 | bus->sdcnt.f2txdata++; |
2127 | 2115 | ||
2128 | if (ret < 0) { | 2116 | if (ret < 0) { |
@@ -2131,17 +2119,17 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | |||
2131 | ret); | 2119 | ret); |
2132 | bus->sdcnt.tx_sderrs++; | 2120 | bus->sdcnt.tx_sderrs++; |
2133 | 2121 | ||
2134 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2122 | brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2); |
2135 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 2123 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2136 | SFC_WF_TERM, NULL); | 2124 | SFC_WF_TERM, NULL); |
2137 | bus->sdcnt.f1regdata++; | 2125 | bus->sdcnt.f1regdata++; |
2138 | 2126 | ||
2139 | for (i = 0; i < 3; i++) { | 2127 | for (i = 0; i < 3; i++) { |
2140 | u8 hi, lo; | 2128 | u8 hi, lo; |
2141 | hi = brcmf_sdio_regrb(bus->sdiodev, | 2129 | hi = brcmf_sdiod_regrb(bus->sdiodev, |
2142 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); | 2130 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
2143 | lo = brcmf_sdio_regrb(bus->sdiodev, | 2131 | lo = brcmf_sdiod_regrb(bus->sdiodev, |
2144 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); | 2132 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
2145 | bus->sdcnt.f1regdata += 2; | 2133 | bus->sdcnt.f1regdata += 2; |
2146 | if ((hi == 0) && (lo == 0)) | 2134 | if ((hi == 0) && (lo == 0)) |
2147 | break; | 2135 | break; |
@@ -2160,7 +2148,7 @@ done: | |||
2160 | return ret; | 2148 | return ret; |
2161 | } | 2149 | } |
2162 | 2150 | ||
2163 | static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | 2151 | static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) |
2164 | { | 2152 | { |
2165 | struct sk_buff *pkt; | 2153 | struct sk_buff *pkt; |
2166 | struct sk_buff_head pktq; | 2154 | struct sk_buff_head pktq; |
@@ -2194,7 +2182,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2194 | if (i == 0) | 2182 | if (i == 0) |
2195 | break; | 2183 | break; |
2196 | 2184 | ||
2197 | ret = brcmf_sdbrcm_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); | 2185 | ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); |
2198 | cnt += i; | 2186 | cnt += i; |
2199 | 2187 | ||
2200 | /* In poll mode, need to check for other events */ | 2188 | /* In poll mode, need to check for other events */ |
@@ -2223,7 +2211,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2223 | return cnt; | 2211 | return cnt; |
2224 | } | 2212 | } |
2225 | 2213 | ||
2226 | static void brcmf_sdbrcm_bus_stop(struct device *dev) | 2214 | static void brcmf_sdio_bus_stop(struct device *dev) |
2227 | { | 2215 | { |
2228 | u32 local_hostintmask; | 2216 | u32 local_hostintmask; |
2229 | u8 saveclk; | 2217 | u8 saveclk; |
@@ -2243,7 +2231,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2243 | sdio_claim_host(bus->sdiodev->func[1]); | 2231 | sdio_claim_host(bus->sdiodev->func[1]); |
2244 | 2232 | ||
2245 | /* Enable clock for device interrupts */ | 2233 | /* Enable clock for device interrupts */ |
2246 | brcmf_sdbrcm_bus_sleep(bus, false, false); | 2234 | brcmf_sdio_bus_sleep(bus, false, false); |
2247 | 2235 | ||
2248 | /* Disable and clear interrupts at the chip level also */ | 2236 | /* Disable and clear interrupts at the chip level also */ |
2249 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); | 2237 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); |
@@ -2254,26 +2242,25 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2254 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2242 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2255 | 2243 | ||
2256 | /* Force clocks on backplane to be sure F2 interrupt propagates */ | 2244 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
2257 | saveclk = brcmf_sdio_regrb(bus->sdiodev, | 2245 | saveclk = brcmf_sdiod_regrb(bus->sdiodev, |
2258 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 2246 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
2259 | if (!err) { | 2247 | if (!err) { |
2260 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 2248 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
2261 | (saveclk | SBSDIO_FORCE_HT), &err); | 2249 | (saveclk | SBSDIO_FORCE_HT), &err); |
2262 | } | 2250 | } |
2263 | if (err) | 2251 | if (err) |
2264 | brcmf_err("Failed to force clock for F2: err %d\n", err); | 2252 | brcmf_err("Failed to force clock for F2: err %d\n", err); |
2265 | 2253 | ||
2266 | /* Turn off the bus (F2), free any pending packets */ | 2254 | /* Turn off the bus (F2), free any pending packets */ |
2267 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); | 2255 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); |
2268 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1, | 2256 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); |
2269 | NULL); | ||
2270 | 2257 | ||
2271 | /* Clear any pending interrupts now that F2 is disabled */ | 2258 | /* Clear any pending interrupts now that F2 is disabled */ |
2272 | w_sdreg32(bus, local_hostintmask, | 2259 | w_sdreg32(bus, local_hostintmask, |
2273 | offsetof(struct sdpcmd_regs, intstatus)); | 2260 | offsetof(struct sdpcmd_regs, intstatus)); |
2274 | 2261 | ||
2275 | /* Turn off the backplane clock (only) */ | 2262 | /* Turn off the backplane clock (only) */ |
2276 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | 2263 | brcmf_sdio_clkctl(bus, CLK_SDONLY, false); |
2277 | sdio_release_host(bus->sdiodev->func[1]); | 2264 | sdio_release_host(bus->sdiodev->func[1]); |
2278 | 2265 | ||
2279 | /* Clear the data packet queues */ | 2266 | /* Clear the data packet queues */ |
@@ -2282,20 +2269,20 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2282 | /* Clear any held glomming stuff */ | 2269 | /* Clear any held glomming stuff */ |
2283 | if (bus->glomd) | 2270 | if (bus->glomd) |
2284 | brcmu_pkt_buf_free_skb(bus->glomd); | 2271 | brcmu_pkt_buf_free_skb(bus->glomd); |
2285 | brcmf_sdbrcm_free_glom(bus); | 2272 | brcmf_sdio_free_glom(bus); |
2286 | 2273 | ||
2287 | /* Clear rx control and wake any waiters */ | 2274 | /* Clear rx control and wake any waiters */ |
2288 | spin_lock_bh(&bus->rxctl_lock); | 2275 | spin_lock_bh(&bus->rxctl_lock); |
2289 | bus->rxlen = 0; | 2276 | bus->rxlen = 0; |
2290 | spin_unlock_bh(&bus->rxctl_lock); | 2277 | spin_unlock_bh(&bus->rxctl_lock); |
2291 | brcmf_sdbrcm_dcmd_resp_wake(bus); | 2278 | brcmf_sdio_dcmd_resp_wake(bus); |
2292 | 2279 | ||
2293 | /* Reset some F2 state stuff */ | 2280 | /* Reset some F2 state stuff */ |
2294 | bus->rxskip = false; | 2281 | bus->rxskip = false; |
2295 | bus->tx_seq = bus->rx_seq = 0; | 2282 | bus->tx_seq = bus->rx_seq = 0; |
2296 | } | 2283 | } |
2297 | 2284 | ||
2298 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | 2285 | static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus) |
2299 | { | 2286 | { |
2300 | unsigned long flags; | 2287 | unsigned long flags; |
2301 | 2288 | ||
@@ -2320,7 +2307,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | |||
2320 | addr = bus->ci->c_inf[idx].base + | 2307 | addr = bus->ci->c_inf[idx].base + |
2321 | offsetof(struct sdpcmd_regs, intstatus); | 2308 | offsetof(struct sdpcmd_regs, intstatus); |
2322 | 2309 | ||
2323 | ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, false); | 2310 | val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret); |
2324 | bus->sdcnt.f1regdata++; | 2311 | bus->sdcnt.f1regdata++; |
2325 | if (ret != 0) | 2312 | if (ret != 0) |
2326 | val = 0; | 2313 | val = 0; |
@@ -2330,7 +2317,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | |||
2330 | 2317 | ||
2331 | /* Clear interrupts */ | 2318 | /* Clear interrupts */ |
2332 | if (val) { | 2319 | if (val) { |
2333 | ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, true); | 2320 | brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret); |
2334 | bus->sdcnt.f1regdata++; | 2321 | bus->sdcnt.f1regdata++; |
2335 | } | 2322 | } |
2336 | 2323 | ||
@@ -2344,7 +2331,7 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | |||
2344 | return ret; | 2331 | return ret; |
2345 | } | 2332 | } |
2346 | 2333 | ||
2347 | static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | 2334 | static void brcmf_sdio_dpc(struct brcmf_sdio *bus) |
2348 | { | 2335 | { |
2349 | u32 newstatus = 0; | 2336 | u32 newstatus = 0; |
2350 | unsigned long intstatus; | 2337 | unsigned long intstatus; |
@@ -2363,8 +2350,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2363 | 2350 | ||
2364 | #ifdef DEBUG | 2351 | #ifdef DEBUG |
2365 | /* Check for inconsistent device control */ | 2352 | /* Check for inconsistent device control */ |
2366 | devctl = brcmf_sdio_regrb(bus->sdiodev, | 2353 | devctl = brcmf_sdiod_regrb(bus->sdiodev, |
2367 | SBSDIO_DEVICE_CTL, &err); | 2354 | SBSDIO_DEVICE_CTL, &err); |
2368 | if (err) { | 2355 | if (err) { |
2369 | brcmf_err("error reading DEVCTL: %d\n", err); | 2356 | brcmf_err("error reading DEVCTL: %d\n", err); |
2370 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2357 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
@@ -2372,8 +2359,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2372 | #endif /* DEBUG */ | 2359 | #endif /* DEBUG */ |
2373 | 2360 | ||
2374 | /* Read CSR, if clock on switch to AVAIL, else ignore */ | 2361 | /* Read CSR, if clock on switch to AVAIL, else ignore */ |
2375 | clkctl = brcmf_sdio_regrb(bus->sdiodev, | 2362 | clkctl = brcmf_sdiod_regrb(bus->sdiodev, |
2376 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 2363 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
2377 | if (err) { | 2364 | if (err) { |
2378 | brcmf_err("error reading CSR: %d\n", | 2365 | brcmf_err("error reading CSR: %d\n", |
2379 | err); | 2366 | err); |
@@ -2384,16 +2371,16 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2384 | devctl, clkctl); | 2371 | devctl, clkctl); |
2385 | 2372 | ||
2386 | if (SBSDIO_HTAV(clkctl)) { | 2373 | if (SBSDIO_HTAV(clkctl)) { |
2387 | devctl = brcmf_sdio_regrb(bus->sdiodev, | 2374 | devctl = brcmf_sdiod_regrb(bus->sdiodev, |
2388 | SBSDIO_DEVICE_CTL, &err); | 2375 | SBSDIO_DEVICE_CTL, &err); |
2389 | if (err) { | 2376 | if (err) { |
2390 | brcmf_err("error reading DEVCTL: %d\n", | 2377 | brcmf_err("error reading DEVCTL: %d\n", |
2391 | err); | 2378 | err); |
2392 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2379 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2393 | } | 2380 | } |
2394 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 2381 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
2395 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | 2382 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
2396 | devctl, &err); | 2383 | devctl, &err); |
2397 | if (err) { | 2384 | if (err) { |
2398 | brcmf_err("error writing DEVCTL: %d\n", | 2385 | brcmf_err("error writing DEVCTL: %d\n", |
2399 | err); | 2386 | err); |
@@ -2404,7 +2391,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2404 | } | 2391 | } |
2405 | 2392 | ||
2406 | /* Make sure backplane clock is on */ | 2393 | /* Make sure backplane clock is on */ |
2407 | brcmf_sdbrcm_bus_sleep(bus, false, true); | 2394 | brcmf_sdio_bus_sleep(bus, false, true); |
2408 | 2395 | ||
2409 | /* Pending interrupt indicates new device status */ | 2396 | /* Pending interrupt indicates new device status */ |
2410 | if (atomic_read(&bus->ipend) > 0) { | 2397 | if (atomic_read(&bus->ipend) > 0) { |
@@ -2435,7 +2422,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2435 | /* Handle host mailbox indication */ | 2422 | /* Handle host mailbox indication */ |
2436 | if (intstatus & I_HMB_HOST_INT) { | 2423 | if (intstatus & I_HMB_HOST_INT) { |
2437 | intstatus &= ~I_HMB_HOST_INT; | 2424 | intstatus &= ~I_HMB_HOST_INT; |
2438 | intstatus |= brcmf_sdbrcm_hostmail(bus); | 2425 | intstatus |= brcmf_sdio_hostmail(bus); |
2439 | } | 2426 | } |
2440 | 2427 | ||
2441 | sdio_release_host(bus->sdiodev->func[1]); | 2428 | sdio_release_host(bus->sdiodev->func[1]); |
@@ -2480,16 +2467,15 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2480 | set_bit(n, (unsigned long *)&bus->intstatus.counter); | 2467 | set_bit(n, (unsigned long *)&bus->intstatus.counter); |
2481 | } | 2468 | } |
2482 | 2469 | ||
2483 | brcmf_sdbrcm_clrintr(bus); | 2470 | brcmf_sdio_clrintr(bus); |
2484 | 2471 | ||
2485 | if (data_ok(bus) && bus->ctrl_frame_stat && | 2472 | if (data_ok(bus) && bus->ctrl_frame_stat && |
2486 | (bus->clkstate == CLK_AVAIL)) { | 2473 | (bus->clkstate == CLK_AVAIL)) { |
2487 | int i; | 2474 | int i; |
2488 | 2475 | ||
2489 | sdio_claim_host(bus->sdiodev->func[1]); | 2476 | sdio_claim_host(bus->sdiodev->func[1]); |
2490 | err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, | 2477 | err = brcmf_sdiod_send_buf(bus->sdiodev, bus->ctrl_frame_buf, |
2491 | SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, | 2478 | (u32)bus->ctrl_frame_len); |
2492 | (u32) bus->ctrl_frame_len); | ||
2493 | 2479 | ||
2494 | if (err < 0) { | 2480 | if (err < 0) { |
2495 | /* On failure, abort the command and | 2481 | /* On failure, abort the command and |
@@ -2498,20 +2484,20 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2498 | err); | 2484 | err); |
2499 | bus->sdcnt.tx_sderrs++; | 2485 | bus->sdcnt.tx_sderrs++; |
2500 | 2486 | ||
2501 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2487 | brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2); |
2502 | 2488 | ||
2503 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 2489 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2504 | SFC_WF_TERM, &err); | 2490 | SFC_WF_TERM, &err); |
2505 | bus->sdcnt.f1regdata++; | 2491 | bus->sdcnt.f1regdata++; |
2506 | 2492 | ||
2507 | for (i = 0; i < 3; i++) { | 2493 | for (i = 0; i < 3; i++) { |
2508 | u8 hi, lo; | 2494 | u8 hi, lo; |
2509 | hi = brcmf_sdio_regrb(bus->sdiodev, | 2495 | hi = brcmf_sdiod_regrb(bus->sdiodev, |
2510 | SBSDIO_FUNC1_WFRAMEBCHI, | 2496 | SBSDIO_FUNC1_WFRAMEBCHI, |
2511 | &err); | 2497 | &err); |
2512 | lo = brcmf_sdio_regrb(bus->sdiodev, | 2498 | lo = brcmf_sdiod_regrb(bus->sdiodev, |
2513 | SBSDIO_FUNC1_WFRAMEBCLO, | 2499 | SBSDIO_FUNC1_WFRAMEBCLO, |
2514 | &err); | 2500 | &err); |
2515 | bus->sdcnt.f1regdata += 2; | 2501 | bus->sdcnt.f1regdata += 2; |
2516 | if ((hi == 0) && (lo == 0)) | 2502 | if ((hi == 0) && (lo == 0)) |
2517 | break; | 2503 | break; |
@@ -2522,7 +2508,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2522 | } | 2508 | } |
2523 | sdio_release_host(bus->sdiodev->func[1]); | 2509 | sdio_release_host(bus->sdiodev->func[1]); |
2524 | bus->ctrl_frame_stat = false; | 2510 | bus->ctrl_frame_stat = false; |
2525 | brcmf_sdbrcm_wait_event_wakeup(bus); | 2511 | brcmf_sdio_wait_event_wakeup(bus); |
2526 | } | 2512 | } |
2527 | /* Send queued frames (limit 1 if rx may still be pending) */ | 2513 | /* Send queued frames (limit 1 if rx may still be pending) */ |
2528 | else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && | 2514 | else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && |
@@ -2530,7 +2516,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2530 | && data_ok(bus)) { | 2516 | && data_ok(bus)) { |
2531 | framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : | 2517 | framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : |
2532 | txlimit; | 2518 | txlimit; |
2533 | framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); | 2519 | framecnt = brcmf_sdio_sendfromq(bus, framecnt); |
2534 | txlimit -= framecnt; | 2520 | txlimit -= framecnt; |
2535 | } | 2521 | } |
2536 | 2522 | ||
@@ -2552,12 +2538,12 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2552 | bus->activity = false; | 2538 | bus->activity = false; |
2553 | brcmf_dbg(SDIO, "idle state\n"); | 2539 | brcmf_dbg(SDIO, "idle state\n"); |
2554 | sdio_claim_host(bus->sdiodev->func[1]); | 2540 | sdio_claim_host(bus->sdiodev->func[1]); |
2555 | brcmf_sdbrcm_bus_sleep(bus, true, false); | 2541 | brcmf_sdio_bus_sleep(bus, true, false); |
2556 | sdio_release_host(bus->sdiodev->func[1]); | 2542 | sdio_release_host(bus->sdiodev->func[1]); |
2557 | } | 2543 | } |
2558 | } | 2544 | } |
2559 | 2545 | ||
2560 | static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev) | 2546 | static struct pktq *brcmf_sdio_bus_gettxq(struct device *dev) |
2561 | { | 2547 | { |
2562 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2548 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2563 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2549 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
@@ -2566,7 +2552,7 @@ static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev) | |||
2566 | return &bus->txq; | 2552 | return &bus->txq; |
2567 | } | 2553 | } |
2568 | 2554 | ||
2569 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | 2555 | static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) |
2570 | { | 2556 | { |
2571 | int ret = -EBADE; | 2557 | int ret = -EBADE; |
2572 | uint datalen, prec; | 2558 | uint datalen, prec; |
@@ -2622,7 +2608,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2622 | #ifdef DEBUG | 2608 | #ifdef DEBUG |
2623 | #define CONSOLE_LINE_MAX 192 | 2609 | #define CONSOLE_LINE_MAX 192 |
2624 | 2610 | ||
2625 | static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) | 2611 | static int brcmf_sdio_readconsole(struct brcmf_sdio *bus) |
2626 | { | 2612 | { |
2627 | struct brcmf_console *c = &bus->console; | 2613 | struct brcmf_console *c = &bus->console; |
2628 | u8 line[CONSOLE_LINE_MAX], ch; | 2614 | u8 line[CONSOLE_LINE_MAX], ch; |
@@ -2635,8 +2621,8 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) | |||
2635 | 2621 | ||
2636 | /* Read console log struct */ | 2622 | /* Read console log struct */ |
2637 | addr = bus->console_addr + offsetof(struct rte_console, log_le); | 2623 | addr = bus->console_addr + offsetof(struct rte_console, log_le); |
2638 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le, | 2624 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le, |
2639 | sizeof(c->log_le)); | 2625 | sizeof(c->log_le)); |
2640 | if (rv < 0) | 2626 | if (rv < 0) |
2641 | return rv; | 2627 | return rv; |
2642 | 2628 | ||
@@ -2661,7 +2647,7 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) | |||
2661 | 2647 | ||
2662 | /* Read the console buffer */ | 2648 | /* Read the console buffer */ |
2663 | addr = le32_to_cpu(c->log_le.buf); | 2649 | addr = le32_to_cpu(c->log_le.buf); |
2664 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize); | 2650 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize); |
2665 | if (rv < 0) | 2651 | if (rv < 0) |
2666 | return rv; | 2652 | return rv; |
2667 | 2653 | ||
@@ -2699,14 +2685,13 @@ break2: | |||
2699 | } | 2685 | } |
2700 | #endif /* DEBUG */ | 2686 | #endif /* DEBUG */ |
2701 | 2687 | ||
2702 | static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | 2688 | static int brcmf_sdio_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) |
2703 | { | 2689 | { |
2704 | int i; | 2690 | int i; |
2705 | int ret; | 2691 | int ret; |
2706 | 2692 | ||
2707 | bus->ctrl_frame_stat = false; | 2693 | bus->ctrl_frame_stat = false; |
2708 | ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, | 2694 | ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len); |
2709 | SDIO_FUNC_2, F2SYNC, frame, len); | ||
2710 | 2695 | ||
2711 | if (ret < 0) { | 2696 | if (ret < 0) { |
2712 | /* On failure, abort the command and terminate the frame */ | 2697 | /* On failure, abort the command and terminate the frame */ |
@@ -2714,18 +2699,18 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | |||
2714 | ret); | 2699 | ret); |
2715 | bus->sdcnt.tx_sderrs++; | 2700 | bus->sdcnt.tx_sderrs++; |
2716 | 2701 | ||
2717 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2702 | brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2); |
2718 | 2703 | ||
2719 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, | 2704 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2720 | SFC_WF_TERM, NULL); | 2705 | SFC_WF_TERM, NULL); |
2721 | bus->sdcnt.f1regdata++; | 2706 | bus->sdcnt.f1regdata++; |
2722 | 2707 | ||
2723 | for (i = 0; i < 3; i++) { | 2708 | for (i = 0; i < 3; i++) { |
2724 | u8 hi, lo; | 2709 | u8 hi, lo; |
2725 | hi = brcmf_sdio_regrb(bus->sdiodev, | 2710 | hi = brcmf_sdiod_regrb(bus->sdiodev, |
2726 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); | 2711 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
2727 | lo = brcmf_sdio_regrb(bus->sdiodev, | 2712 | lo = brcmf_sdiod_regrb(bus->sdiodev, |
2728 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); | 2713 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
2729 | bus->sdcnt.f1regdata += 2; | 2714 | bus->sdcnt.f1regdata += 2; |
2730 | if (hi == 0 && lo == 0) | 2715 | if (hi == 0 && lo == 0) |
2731 | break; | 2716 | break; |
@@ -2739,7 +2724,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | |||
2739 | } | 2724 | } |
2740 | 2725 | ||
2741 | static int | 2726 | static int |
2742 | brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | 2727 | brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) |
2743 | { | 2728 | { |
2744 | u8 *frame; | 2729 | u8 *frame; |
2745 | u16 len, pad; | 2730 | u16 len, pad; |
@@ -2783,7 +2768,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2783 | 2768 | ||
2784 | /* Make sure backplane clock is on */ | 2769 | /* Make sure backplane clock is on */ |
2785 | sdio_claim_host(bus->sdiodev->func[1]); | 2770 | sdio_claim_host(bus->sdiodev->func[1]); |
2786 | brcmf_sdbrcm_bus_sleep(bus, false, false); | 2771 | brcmf_sdio_bus_sleep(bus, false, false); |
2787 | sdio_release_host(bus->sdiodev->func[1]); | 2772 | sdio_release_host(bus->sdiodev->func[1]); |
2788 | 2773 | ||
2789 | hd_info.len = (u16)msglen; | 2774 | hd_info.len = (u16)msglen; |
@@ -2827,7 +2812,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2827 | 2812 | ||
2828 | do { | 2813 | do { |
2829 | sdio_claim_host(bus->sdiodev->func[1]); | 2814 | sdio_claim_host(bus->sdiodev->func[1]); |
2830 | ret = brcmf_tx_frame(bus, frame, len); | 2815 | ret = brcmf_sdio_tx_frame(bus, frame, len); |
2831 | sdio_release_host(bus->sdiodev->func[1]); | 2816 | sdio_release_host(bus->sdiodev->func[1]); |
2832 | } while (ret < 0 && retries++ < TXRETRIES); | 2817 | } while (ret < 0 && retries++ < TXRETRIES); |
2833 | } | 2818 | } |
@@ -2837,7 +2822,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2837 | bus->activity = false; | 2822 | bus->activity = false; |
2838 | sdio_claim_host(bus->sdiodev->func[1]); | 2823 | sdio_claim_host(bus->sdiodev->func[1]); |
2839 | brcmf_dbg(INFO, "idle\n"); | 2824 | brcmf_dbg(INFO, "idle\n"); |
2840 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | 2825 | brcmf_sdio_clkctl(bus, CLK_NONE, true); |
2841 | sdio_release_host(bus->sdiodev->func[1]); | 2826 | sdio_release_host(bus->sdiodev->func[1]); |
2842 | } | 2827 | } |
2843 | 2828 | ||
@@ -2871,8 +2856,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2871 | * address of sdpcm_shared structure | 2856 | * address of sdpcm_shared structure |
2872 | */ | 2857 | */ |
2873 | sdio_claim_host(bus->sdiodev->func[1]); | 2858 | sdio_claim_host(bus->sdiodev->func[1]); |
2874 | brcmf_sdbrcm_bus_sleep(bus, false, false); | 2859 | brcmf_sdio_bus_sleep(bus, false, false); |
2875 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4); | 2860 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4); |
2876 | sdio_release_host(bus->sdiodev->func[1]); | 2861 | sdio_release_host(bus->sdiodev->func[1]); |
2877 | if (rv < 0) | 2862 | if (rv < 0) |
2878 | return rv; | 2863 | return rv; |
@@ -2892,8 +2877,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2892 | } | 2877 | } |
2893 | 2878 | ||
2894 | /* Read hndrte_shared structure */ | 2879 | /* Read hndrte_shared structure */ |
2895 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le, | 2880 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le, |
2896 | sizeof(struct sdpcm_shared_le)); | 2881 | sizeof(struct sdpcm_shared_le)); |
2897 | if (rv < 0) | 2882 | if (rv < 0) |
2898 | return rv; | 2883 | return rv; |
2899 | 2884 | ||
@@ -2929,22 +2914,22 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | |||
2929 | 2914 | ||
2930 | /* obtain console information from device memory */ | 2915 | /* obtain console information from device memory */ |
2931 | addr = sh->console_addr + offsetof(struct rte_console, log_le); | 2916 | addr = sh->console_addr + offsetof(struct rte_console, log_le); |
2932 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, | 2917 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, |
2933 | (u8 *)&sh_val, sizeof(u32)); | 2918 | (u8 *)&sh_val, sizeof(u32)); |
2934 | if (rv < 0) | 2919 | if (rv < 0) |
2935 | return rv; | 2920 | return rv; |
2936 | console_ptr = le32_to_cpu(sh_val); | 2921 | console_ptr = le32_to_cpu(sh_val); |
2937 | 2922 | ||
2938 | addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size); | 2923 | addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size); |
2939 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, | 2924 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, |
2940 | (u8 *)&sh_val, sizeof(u32)); | 2925 | (u8 *)&sh_val, sizeof(u32)); |
2941 | if (rv < 0) | 2926 | if (rv < 0) |
2942 | return rv; | 2927 | return rv; |
2943 | console_size = le32_to_cpu(sh_val); | 2928 | console_size = le32_to_cpu(sh_val); |
2944 | 2929 | ||
2945 | addr = sh->console_addr + offsetof(struct rte_console, log_le.idx); | 2930 | addr = sh->console_addr + offsetof(struct rte_console, log_le.idx); |
2946 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, | 2931 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, |
2947 | (u8 *)&sh_val, sizeof(u32)); | 2932 | (u8 *)&sh_val, sizeof(u32)); |
2948 | if (rv < 0) | 2933 | if (rv < 0) |
2949 | return rv; | 2934 | return rv; |
2950 | console_index = le32_to_cpu(sh_val); | 2935 | console_index = le32_to_cpu(sh_val); |
@@ -2958,8 +2943,8 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | |||
2958 | 2943 | ||
2959 | /* obtain the console data from device */ | 2944 | /* obtain the console data from device */ |
2960 | conbuf[console_size] = '\0'; | 2945 | conbuf[console_size] = '\0'; |
2961 | rv = brcmf_sdio_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf, | 2946 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf, |
2962 | console_size); | 2947 | console_size); |
2963 | if (rv < 0) | 2948 | if (rv < 0) |
2964 | goto done; | 2949 | goto done; |
2965 | 2950 | ||
@@ -2996,8 +2981,8 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | |||
2996 | return 0; | 2981 | return 0; |
2997 | } | 2982 | } |
2998 | 2983 | ||
2999 | error = brcmf_sdio_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr, | 2984 | error = brcmf_sdiod_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr, |
3000 | sizeof(struct brcmf_trap_info)); | 2985 | sizeof(struct brcmf_trap_info)); |
3001 | if (error < 0) | 2986 | if (error < 0) |
3002 | return error; | 2987 | return error; |
3003 | 2988 | ||
@@ -3040,14 +3025,14 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | |||
3040 | 3025 | ||
3041 | sdio_claim_host(bus->sdiodev->func[1]); | 3026 | sdio_claim_host(bus->sdiodev->func[1]); |
3042 | if (sh->assert_file_addr != 0) { | 3027 | if (sh->assert_file_addr != 0) { |
3043 | error = brcmf_sdio_ramrw(bus->sdiodev, false, | 3028 | error = brcmf_sdiod_ramrw(bus->sdiodev, false, |
3044 | sh->assert_file_addr, (u8 *)file, 80); | 3029 | sh->assert_file_addr, (u8 *)file, 80); |
3045 | if (error < 0) | 3030 | if (error < 0) |
3046 | return error; | 3031 | return error; |
3047 | } | 3032 | } |
3048 | if (sh->assert_exp_addr != 0) { | 3033 | if (sh->assert_exp_addr != 0) { |
3049 | error = brcmf_sdio_ramrw(bus->sdiodev, false, | 3034 | error = brcmf_sdiod_ramrw(bus->sdiodev, false, |
3050 | sh->assert_exp_addr, (u8 *)expr, 80); | 3035 | sh->assert_exp_addr, (u8 *)expr, 80); |
3051 | if (error < 0) | 3036 | if (error < 0) |
3052 | return error; | 3037 | return error; |
3053 | } | 3038 | } |
@@ -3059,7 +3044,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | |||
3059 | return simple_read_from_buffer(data, count, &pos, buf, res); | 3044 | return simple_read_from_buffer(data, count, &pos, buf, res); |
3060 | } | 3045 | } |
3061 | 3046 | ||
3062 | static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus) | 3047 | static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) |
3063 | { | 3048 | { |
3064 | int error; | 3049 | int error; |
3065 | struct sdpcm_shared sh; | 3050 | struct sdpcm_shared sh; |
@@ -3080,8 +3065,8 @@ static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus) | |||
3080 | return 0; | 3065 | return 0; |
3081 | } | 3066 | } |
3082 | 3067 | ||
3083 | static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data, | 3068 | static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data, |
3084 | size_t count, loff_t *ppos) | 3069 | size_t count, loff_t *ppos) |
3085 | { | 3070 | { |
3086 | int error = 0; | 3071 | int error = 0; |
3087 | struct sdpcm_shared sh; | 3072 | struct sdpcm_shared sh; |
@@ -3122,7 +3107,7 @@ static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data, | |||
3122 | struct brcmf_sdio *bus = f->private_data; | 3107 | struct brcmf_sdio *bus = f->private_data; |
3123 | int res; | 3108 | int res; |
3124 | 3109 | ||
3125 | res = brcmf_sdbrcm_died_dump(bus, data, count, ppos); | 3110 | res = brcmf_sdio_died_dump(bus, data, count, ppos); |
3126 | if (res > 0) | 3111 | if (res > 0) |
3127 | *ppos += res; | 3112 | *ppos += res; |
3128 | return (ssize_t)res; | 3113 | return (ssize_t)res; |
@@ -3147,7 +3132,7 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | |||
3147 | brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt); | 3132 | brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt); |
3148 | } | 3133 | } |
3149 | #else | 3134 | #else |
3150 | static int brcmf_sdbrcm_checkdied(struct brcmf_sdio *bus) | 3135 | static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) |
3151 | { | 3136 | { |
3152 | return 0; | 3137 | return 0; |
3153 | } | 3138 | } |
@@ -3158,7 +3143,7 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | |||
3158 | #endif /* DEBUG */ | 3143 | #endif /* DEBUG */ |
3159 | 3144 | ||
3160 | static int | 3145 | static int |
3161 | brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | 3146 | brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) |
3162 | { | 3147 | { |
3163 | int timeleft; | 3148 | int timeleft; |
3164 | uint rxlen = 0; | 3149 | uint rxlen = 0; |
@@ -3171,7 +3156,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | |||
3171 | brcmf_dbg(TRACE, "Enter\n"); | 3156 | brcmf_dbg(TRACE, "Enter\n"); |
3172 | 3157 | ||
3173 | /* Wait until control frame is available */ | 3158 | /* Wait until control frame is available */ |
3174 | timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending); | 3159 | timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending); |
3175 | 3160 | ||
3176 | spin_lock_bh(&bus->rxctl_lock); | 3161 | spin_lock_bh(&bus->rxctl_lock); |
3177 | rxlen = bus->rxlen; | 3162 | rxlen = bus->rxlen; |
@@ -3188,13 +3173,13 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | |||
3188 | rxlen, msglen); | 3173 | rxlen, msglen); |
3189 | } else if (timeleft == 0) { | 3174 | } else if (timeleft == 0) { |
3190 | brcmf_err("resumed on timeout\n"); | 3175 | brcmf_err("resumed on timeout\n"); |
3191 | brcmf_sdbrcm_checkdied(bus); | 3176 | brcmf_sdio_checkdied(bus); |
3192 | } else if (pending) { | 3177 | } else if (pending) { |
3193 | brcmf_dbg(CTL, "cancelled\n"); | 3178 | brcmf_dbg(CTL, "cancelled\n"); |
3194 | return -ERESTARTSYS; | 3179 | return -ERESTARTSYS; |
3195 | } else { | 3180 | } else { |
3196 | brcmf_dbg(CTL, "resumed for unknown reason?\n"); | 3181 | brcmf_dbg(CTL, "resumed for unknown reason?\n"); |
3197 | brcmf_sdbrcm_checkdied(bus); | 3182 | brcmf_sdio_checkdied(bus); |
3198 | } | 3183 | } |
3199 | 3184 | ||
3200 | if (rxlen) | 3185 | if (rxlen) |
@@ -3205,7 +3190,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) | |||
3205 | return rxlen ? (int)rxlen : -ETIMEDOUT; | 3190 | return rxlen ? (int)rxlen : -ETIMEDOUT; |
3206 | } | 3191 | } |
3207 | 3192 | ||
3208 | static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | 3193 | static bool brcmf_sdio_download_state(struct brcmf_sdio *bus, bool enter) |
3209 | { | 3194 | { |
3210 | struct chip_info *ci = bus->ci; | 3195 | struct chip_info *ci = bus->ci; |
3211 | 3196 | ||
@@ -3230,7 +3215,7 @@ static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | |||
3230 | return true; | 3215 | return true; |
3231 | } | 3216 | } |
3232 | 3217 | ||
3233 | static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) | 3218 | static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus) |
3234 | { | 3219 | { |
3235 | const struct firmware *fw; | 3220 | const struct firmware *fw; |
3236 | int err; | 3221 | int err; |
@@ -3238,7 +3223,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) | |||
3238 | int address; | 3223 | int address; |
3239 | int len; | 3224 | int len; |
3240 | 3225 | ||
3241 | fw = brcmf_sdbrcm_get_fw(bus, BRCMF_FIRMWARE_BIN); | 3226 | fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN); |
3242 | if (fw == NULL) | 3227 | if (fw == NULL) |
3243 | return -ENOENT; | 3228 | return -ENOENT; |
3244 | 3229 | ||
@@ -3252,8 +3237,8 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) | |||
3252 | while (offset < fw->size) { | 3237 | while (offset < fw->size) { |
3253 | len = ((offset + MEMBLOCK) < fw->size) ? MEMBLOCK : | 3238 | len = ((offset + MEMBLOCK) < fw->size) ? MEMBLOCK : |
3254 | fw->size - offset; | 3239 | fw->size - offset; |
3255 | err = brcmf_sdio_ramrw(bus->sdiodev, true, address, | 3240 | err = brcmf_sdiod_ramrw(bus->sdiodev, true, address, |
3256 | (u8 *)&fw->data[offset], len); | 3241 | (u8 *)&fw->data[offset], len); |
3257 | if (err) { | 3242 | if (err) { |
3258 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", | 3243 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", |
3259 | err, len, address); | 3244 | err, len, address); |
@@ -3278,8 +3263,8 @@ failure: | |||
3278 | * by two NULs. | 3263 | * by two NULs. |
3279 | */ | 3264 | */ |
3280 | 3265 | ||
3281 | static int brcmf_process_nvram_vars(struct brcmf_sdio *bus, | 3266 | static int brcmf_sdio_strip_nvram(struct brcmf_sdio *bus, |
3282 | const struct firmware *nv) | 3267 | const struct firmware *nv) |
3283 | { | 3268 | { |
3284 | char *varbuf; | 3269 | char *varbuf; |
3285 | char *dp; | 3270 | char *dp; |
@@ -3343,44 +3328,48 @@ err: | |||
3343 | return ret; | 3328 | return ret; |
3344 | } | 3329 | } |
3345 | 3330 | ||
3346 | static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) | 3331 | static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus) |
3347 | { | 3332 | { |
3348 | const struct firmware *nv; | 3333 | const struct firmware *nv; |
3349 | int ret; | 3334 | int ret; |
3350 | 3335 | ||
3351 | nv = brcmf_sdbrcm_get_fw(bus, BRCMF_FIRMWARE_NVRAM); | 3336 | nv = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM); |
3352 | if (nv == NULL) | 3337 | if (nv == NULL) |
3353 | return -ENOENT; | 3338 | return -ENOENT; |
3354 | 3339 | ||
3355 | ret = brcmf_process_nvram_vars(bus, nv); | 3340 | ret = brcmf_sdio_strip_nvram(bus, nv); |
3356 | 3341 | ||
3357 | release_firmware(nv); | 3342 | release_firmware(nv); |
3358 | 3343 | ||
3359 | return ret; | 3344 | return ret; |
3360 | } | 3345 | } |
3361 | 3346 | ||
3362 | static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | 3347 | static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus) |
3363 | { | 3348 | { |
3364 | int bcmerror = -1; | 3349 | int bcmerror = -EFAULT; |
3350 | |||
3351 | |||
3352 | sdio_claim_host(bus->sdiodev->func[1]); | ||
3353 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | ||
3365 | 3354 | ||
3366 | /* Keep arm in reset */ | 3355 | /* Keep arm in reset */ |
3367 | if (!brcmf_sdbrcm_download_state(bus, true)) { | 3356 | if (!brcmf_sdio_download_state(bus, true)) { |
3368 | brcmf_err("error placing ARM core in reset\n"); | 3357 | brcmf_err("error placing ARM core in reset\n"); |
3369 | goto err; | 3358 | goto err; |
3370 | } | 3359 | } |
3371 | 3360 | ||
3372 | if (brcmf_sdbrcm_download_code_file(bus)) { | 3361 | if (brcmf_sdio_download_code_file(bus)) { |
3373 | brcmf_err("dongle image file download failed\n"); | 3362 | brcmf_err("dongle image file download failed\n"); |
3374 | goto err; | 3363 | goto err; |
3375 | } | 3364 | } |
3376 | 3365 | ||
3377 | if (brcmf_sdbrcm_download_nvram(bus)) { | 3366 | if (brcmf_sdio_download_nvram(bus)) { |
3378 | brcmf_err("dongle nvram file download failed\n"); | 3367 | brcmf_err("dongle nvram file download failed\n"); |
3379 | goto err; | 3368 | goto err; |
3380 | } | 3369 | } |
3381 | 3370 | ||
3382 | /* Take arm out of reset */ | 3371 | /* Take arm out of reset */ |
3383 | if (!brcmf_sdbrcm_download_state(bus, false)) { | 3372 | if (!brcmf_sdio_download_state(bus, false)) { |
3384 | brcmf_err("error getting out of ARM core reset\n"); | 3373 | brcmf_err("error getting out of ARM core reset\n"); |
3385 | goto err; | 3374 | goto err; |
3386 | } | 3375 | } |
@@ -3388,10 +3377,12 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | |||
3388 | bcmerror = 0; | 3377 | bcmerror = 0; |
3389 | 3378 | ||
3390 | err: | 3379 | err: |
3380 | brcmf_sdio_clkctl(bus, CLK_SDONLY, false); | ||
3381 | sdio_release_host(bus->sdiodev->func[1]); | ||
3391 | return bcmerror; | 3382 | return bcmerror; |
3392 | } | 3383 | } |
3393 | 3384 | ||
3394 | static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus) | 3385 | static bool brcmf_sdio_sr_capable(struct brcmf_sdio *bus) |
3395 | { | 3386 | { |
3396 | u32 addr, reg; | 3387 | u32 addr, reg; |
3397 | 3388 | ||
@@ -3403,47 +3394,45 @@ static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus) | |||
3403 | 3394 | ||
3404 | /* read PMU chipcontrol register 3*/ | 3395 | /* read PMU chipcontrol register 3*/ |
3405 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr); | 3396 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr); |
3406 | brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL); | 3397 | brcmf_sdiod_regwl(bus->sdiodev, addr, 3, NULL); |
3407 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data); | 3398 | addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data); |
3408 | reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL); | 3399 | reg = brcmf_sdiod_regrl(bus->sdiodev, addr, NULL); |
3409 | 3400 | ||
3410 | return (bool)reg; | 3401 | return (bool)reg; |
3411 | } | 3402 | } |
3412 | 3403 | ||
3413 | static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus) | 3404 | static void brcmf_sdio_sr_init(struct brcmf_sdio *bus) |
3414 | { | 3405 | { |
3415 | int err = 0; | 3406 | int err = 0; |
3416 | u8 val; | 3407 | u8 val; |
3417 | 3408 | ||
3418 | brcmf_dbg(TRACE, "Enter\n"); | 3409 | brcmf_dbg(TRACE, "Enter\n"); |
3419 | 3410 | ||
3420 | val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, | 3411 | val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err); |
3421 | &err); | ||
3422 | if (err) { | 3412 | if (err) { |
3423 | brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n"); | 3413 | brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n"); |
3424 | return; | 3414 | return; |
3425 | } | 3415 | } |
3426 | 3416 | ||
3427 | val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT; | 3417 | val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT; |
3428 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, | 3418 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err); |
3429 | val, &err); | ||
3430 | if (err) { | 3419 | if (err) { |
3431 | brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n"); | 3420 | brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n"); |
3432 | return; | 3421 | return; |
3433 | } | 3422 | } |
3434 | 3423 | ||
3435 | /* Add CMD14 Support */ | 3424 | /* Add CMD14 Support */ |
3436 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP, | 3425 | brcmf_sdiod_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP, |
3437 | (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | | 3426 | (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | |
3438 | SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT), | 3427 | SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT), |
3439 | &err); | 3428 | &err); |
3440 | if (err) { | 3429 | if (err) { |
3441 | brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n"); | 3430 | brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n"); |
3442 | return; | 3431 | return; |
3443 | } | 3432 | } |
3444 | 3433 | ||
3445 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 3434 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
3446 | SBSDIO_FORCE_HT, &err); | 3435 | SBSDIO_FORCE_HT, &err); |
3447 | if (err) { | 3436 | if (err) { |
3448 | brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n"); | 3437 | brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n"); |
3449 | return; | 3438 | return; |
@@ -3455,7 +3444,7 @@ static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus) | |||
3455 | } | 3444 | } |
3456 | 3445 | ||
3457 | /* enable KSO bit */ | 3446 | /* enable KSO bit */ |
3458 | static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus) | 3447 | static int brcmf_sdio_kso_init(struct brcmf_sdio *bus) |
3459 | { | 3448 | { |
3460 | u8 val; | 3449 | u8 val; |
3461 | int err = 0; | 3450 | int err = 0; |
@@ -3466,8 +3455,7 @@ static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus) | |||
3466 | if (bus->ci->c_inf[1].rev < 12) | 3455 | if (bus->ci->c_inf[1].rev < 12) |
3467 | return 0; | 3456 | return 0; |
3468 | 3457 | ||
3469 | val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | 3458 | val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err); |
3470 | &err); | ||
3471 | if (err) { | 3459 | if (err) { |
3472 | brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n"); | 3460 | brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n"); |
3473 | return err; | 3461 | return err; |
@@ -3476,8 +3464,8 @@ static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus) | |||
3476 | if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) { | 3464 | if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) { |
3477 | val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << | 3465 | val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << |
3478 | SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); | 3466 | SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); |
3479 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, | 3467 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, |
3480 | val, &err); | 3468 | val, &err); |
3481 | if (err) { | 3469 | if (err) { |
3482 | brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n"); | 3470 | brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n"); |
3483 | return err; | 3471 | return err; |
@@ -3488,25 +3476,7 @@ static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus) | |||
3488 | } | 3476 | } |
3489 | 3477 | ||
3490 | 3478 | ||
3491 | static bool | 3479 | static int brcmf_sdio_bus_preinit(struct device *dev) |
3492 | brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | ||
3493 | { | ||
3494 | bool ret; | ||
3495 | |||
3496 | sdio_claim_host(bus->sdiodev->func[1]); | ||
3497 | |||
3498 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
3499 | |||
3500 | ret = _brcmf_sdbrcm_download_firmware(bus) == 0; | ||
3501 | |||
3502 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | ||
3503 | |||
3504 | sdio_release_host(bus->sdiodev->func[1]); | ||
3505 | |||
3506 | return ret; | ||
3507 | } | ||
3508 | |||
3509 | static int brcmf_sdbrcm_bus_preinit(struct device *dev) | ||
3510 | { | 3480 | { |
3511 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 3481 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
3512 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 3482 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
@@ -3565,13 +3535,11 @@ done: | |||
3565 | return err; | 3535 | return err; |
3566 | } | 3536 | } |
3567 | 3537 | ||
3568 | static int brcmf_sdbrcm_bus_init(struct device *dev) | 3538 | static int brcmf_sdio_bus_init(struct device *dev) |
3569 | { | 3539 | { |
3570 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 3540 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
3571 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 3541 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
3572 | struct brcmf_sdio *bus = sdiodev->bus; | 3542 | struct brcmf_sdio *bus = sdiodev->bus; |
3573 | unsigned long timeout; | ||
3574 | u8 ready, enable; | ||
3575 | int err, ret = 0; | 3543 | int err, ret = 0; |
3576 | u8 saveclk; | 3544 | u8 saveclk; |
3577 | 3545 | ||
@@ -3579,8 +3547,9 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3579 | 3547 | ||
3580 | /* try to download image and nvram to the dongle */ | 3548 | /* try to download image and nvram to the dongle */ |
3581 | if (bus_if->state == BRCMF_BUS_DOWN) { | 3549 | if (bus_if->state == BRCMF_BUS_DOWN) { |
3582 | if (!(brcmf_sdbrcm_download_firmware(bus))) | 3550 | err = brcmf_sdio_download_firmware(bus); |
3583 | return -1; | 3551 | if (err) |
3552 | return err; | ||
3584 | } | 3553 | } |
3585 | 3554 | ||
3586 | if (!bus->sdiodev->bus_if->drvr) | 3555 | if (!bus->sdiodev->bus_if->drvr) |
@@ -3588,21 +3557,21 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3588 | 3557 | ||
3589 | /* Start the watchdog timer */ | 3558 | /* Start the watchdog timer */ |
3590 | bus->sdcnt.tickcnt = 0; | 3559 | bus->sdcnt.tickcnt = 0; |
3591 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 3560 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); |
3592 | 3561 | ||
3593 | sdio_claim_host(bus->sdiodev->func[1]); | 3562 | sdio_claim_host(bus->sdiodev->func[1]); |
3594 | 3563 | ||
3595 | /* Make sure backplane clock is on, needed to generate F2 interrupt */ | 3564 | /* Make sure backplane clock is on, needed to generate F2 interrupt */ |
3596 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 3565 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
3597 | if (bus->clkstate != CLK_AVAIL) | 3566 | if (bus->clkstate != CLK_AVAIL) |
3598 | goto exit; | 3567 | goto exit; |
3599 | 3568 | ||
3600 | /* Force clocks on backplane to be sure F2 interrupt propagates */ | 3569 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
3601 | saveclk = brcmf_sdio_regrb(bus->sdiodev, | 3570 | saveclk = brcmf_sdiod_regrb(bus->sdiodev, |
3602 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 3571 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
3603 | if (!err) { | 3572 | if (!err) { |
3604 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 3573 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
3605 | (saveclk | SBSDIO_FORCE_HT), &err); | 3574 | (saveclk | SBSDIO_FORCE_HT), &err); |
3606 | } | 3575 | } |
3607 | if (err) { | 3576 | if (err) { |
3608 | brcmf_err("Failed to force clock for F2: err %d\n", err); | 3577 | brcmf_err("Failed to force clock for F2: err %d\n", err); |
@@ -3612,56 +3581,42 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3612 | /* Enable function 2 (frame transfers) */ | 3581 | /* Enable function 2 (frame transfers) */ |
3613 | w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, | 3582 | w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, |
3614 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); | 3583 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); |
3615 | enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); | 3584 | err = sdio_enable_func(bus->sdiodev->func[SDIO_FUNC_2]); |
3616 | |||
3617 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL); | ||
3618 | 3585 | ||
3619 | timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); | ||
3620 | ready = 0; | ||
3621 | while (enable != ready) { | ||
3622 | ready = brcmf_sdio_regrb(bus->sdiodev, | ||
3623 | SDIO_CCCR_IORx, NULL); | ||
3624 | if (time_after(jiffies, timeout)) | ||
3625 | break; | ||
3626 | else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) | ||
3627 | /* prevent busy waiting if it takes too long */ | ||
3628 | msleep_interruptible(20); | ||
3629 | } | ||
3630 | 3586 | ||
3631 | brcmf_dbg(INFO, "enable 0x%02x, ready 0x%02x\n", enable, ready); | 3587 | brcmf_dbg(INFO, "enable F2: err=%d\n", err); |
3632 | 3588 | ||
3633 | /* If F2 successfully enabled, set core and enable interrupts */ | 3589 | /* If F2 successfully enabled, set core and enable interrupts */ |
3634 | if (ready == enable) { | 3590 | if (!err) { |
3635 | /* Set up the interrupt mask and enable interrupts */ | 3591 | /* Set up the interrupt mask and enable interrupts */ |
3636 | bus->hostintmask = HOSTINTMASK; | 3592 | bus->hostintmask = HOSTINTMASK; |
3637 | w_sdreg32(bus, bus->hostintmask, | 3593 | w_sdreg32(bus, bus->hostintmask, |
3638 | offsetof(struct sdpcmd_regs, hostintmask)); | 3594 | offsetof(struct sdpcmd_regs, hostintmask)); |
3639 | 3595 | ||
3640 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err); | 3596 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err); |
3641 | } else { | 3597 | } else { |
3642 | /* Disable F2 again */ | 3598 | /* Disable F2 again */ |
3643 | enable = SDIO_FUNC_ENABLE_1; | 3599 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); |
3644 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL); | ||
3645 | ret = -ENODEV; | 3600 | ret = -ENODEV; |
3646 | } | 3601 | } |
3647 | 3602 | ||
3648 | if (brcmf_sdbrcm_sr_capable(bus)) { | 3603 | if (brcmf_sdio_sr_capable(bus)) { |
3649 | brcmf_sdbrcm_sr_init(bus); | 3604 | brcmf_sdio_sr_init(bus); |
3650 | } else { | 3605 | } else { |
3651 | /* Restore previous clock setting */ | 3606 | /* Restore previous clock setting */ |
3652 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 3607 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
3653 | saveclk, &err); | 3608 | saveclk, &err); |
3654 | } | 3609 | } |
3655 | 3610 | ||
3656 | if (ret == 0) { | 3611 | if (ret == 0) { |
3657 | ret = brcmf_sdio_intr_register(bus->sdiodev); | 3612 | ret = brcmf_sdiod_intr_register(bus->sdiodev); |
3658 | if (ret != 0) | 3613 | if (ret != 0) |
3659 | brcmf_err("intr register failed:%d\n", ret); | 3614 | brcmf_err("intr register failed:%d\n", ret); |
3660 | } | 3615 | } |
3661 | 3616 | ||
3662 | /* If we didn't come up, turn off backplane clock */ | 3617 | /* If we didn't come up, turn off backplane clock */ |
3663 | if (bus_if->state != BRCMF_BUS_DATA) | 3618 | if (bus_if->state != BRCMF_BUS_DATA) |
3664 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); | 3619 | brcmf_sdio_clkctl(bus, CLK_NONE, false); |
3665 | 3620 | ||
3666 | exit: | 3621 | exit: |
3667 | sdio_release_host(bus->sdiodev->func[1]); | 3622 | sdio_release_host(bus->sdiodev->func[1]); |
@@ -3669,10 +3624,8 @@ exit: | |||
3669 | return ret; | 3624 | return ret; |
3670 | } | 3625 | } |
3671 | 3626 | ||
3672 | void brcmf_sdbrcm_isr(void *arg) | 3627 | void brcmf_sdio_isr(struct brcmf_sdio *bus) |
3673 | { | 3628 | { |
3674 | struct brcmf_sdio *bus = (struct brcmf_sdio *) arg; | ||
3675 | |||
3676 | brcmf_dbg(TRACE, "Enter\n"); | 3629 | brcmf_dbg(TRACE, "Enter\n"); |
3677 | 3630 | ||
3678 | if (!bus) { | 3631 | if (!bus) { |
@@ -3702,7 +3655,7 @@ void brcmf_sdbrcm_isr(void *arg) | |||
3702 | queue_work(bus->brcmf_wq, &bus->datawork); | 3655 | queue_work(bus->brcmf_wq, &bus->datawork); |
3703 | } | 3656 | } |
3704 | 3657 | ||
3705 | static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | 3658 | static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) |
3706 | { | 3659 | { |
3707 | #ifdef DEBUG | 3660 | #ifdef DEBUG |
3708 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); | 3661 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); |
@@ -3726,9 +3679,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3726 | u8 devpend; | 3679 | u8 devpend; |
3727 | 3680 | ||
3728 | sdio_claim_host(bus->sdiodev->func[1]); | 3681 | sdio_claim_host(bus->sdiodev->func[1]); |
3729 | devpend = brcmf_sdio_regrb(bus->sdiodev, | 3682 | devpend = brcmf_sdiod_regrb(bus->sdiodev, |
3730 | SDIO_CCCR_INTx, | 3683 | SDIO_CCCR_INTx, |
3731 | NULL); | 3684 | NULL); |
3732 | sdio_release_host(bus->sdiodev->func[1]); | 3685 | sdio_release_host(bus->sdiodev->func[1]); |
3733 | intstatus = | 3686 | intstatus = |
3734 | devpend & (INTR_STATUS_FUNC1 | | 3687 | devpend & (INTR_STATUS_FUNC1 | |
@@ -3758,8 +3711,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3758 | bus->console.count -= bus->console_interval; | 3711 | bus->console.count -= bus->console_interval; |
3759 | sdio_claim_host(bus->sdiodev->func[1]); | 3712 | sdio_claim_host(bus->sdiodev->func[1]); |
3760 | /* Make sure backplane clock is on */ | 3713 | /* Make sure backplane clock is on */ |
3761 | brcmf_sdbrcm_bus_sleep(bus, false, false); | 3714 | brcmf_sdio_bus_sleep(bus, false, false); |
3762 | if (brcmf_sdbrcm_readconsole(bus) < 0) | 3715 | if (brcmf_sdio_readconsole(bus) < 0) |
3763 | /* stop on error */ | 3716 | /* stop on error */ |
3764 | bus->console_interval = 0; | 3717 | bus->console_interval = 0; |
3765 | sdio_release_host(bus->sdiodev->func[1]); | 3718 | sdio_release_host(bus->sdiodev->func[1]); |
@@ -3773,11 +3726,11 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3773 | bus->idlecount = 0; | 3726 | bus->idlecount = 0; |
3774 | if (bus->activity) { | 3727 | if (bus->activity) { |
3775 | bus->activity = false; | 3728 | bus->activity = false; |
3776 | brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); | 3729 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); |
3777 | } else { | 3730 | } else { |
3778 | brcmf_dbg(SDIO, "idle\n"); | 3731 | brcmf_dbg(SDIO, "idle\n"); |
3779 | sdio_claim_host(bus->sdiodev->func[1]); | 3732 | sdio_claim_host(bus->sdiodev->func[1]); |
3780 | brcmf_sdbrcm_bus_sleep(bus, true, false); | 3733 | brcmf_sdio_bus_sleep(bus, true, false); |
3781 | sdio_release_host(bus->sdiodev->func[1]); | 3734 | sdio_release_host(bus->sdiodev->func[1]); |
3782 | } | 3735 | } |
3783 | } | 3736 | } |
@@ -3792,12 +3745,12 @@ static void brcmf_sdio_dataworker(struct work_struct *work) | |||
3792 | datawork); | 3745 | datawork); |
3793 | 3746 | ||
3794 | while (atomic_read(&bus->dpc_tskcnt)) { | 3747 | while (atomic_read(&bus->dpc_tskcnt)) { |
3795 | brcmf_sdbrcm_dpc(bus); | 3748 | brcmf_sdio_dpc(bus); |
3796 | atomic_dec(&bus->dpc_tskcnt); | 3749 | atomic_dec(&bus->dpc_tskcnt); |
3797 | } | 3750 | } |
3798 | } | 3751 | } |
3799 | 3752 | ||
3800 | static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) | 3753 | static void brcmf_sdio_release_malloc(struct brcmf_sdio *bus) |
3801 | { | 3754 | { |
3802 | brcmf_dbg(TRACE, "Enter\n"); | 3755 | brcmf_dbg(TRACE, "Enter\n"); |
3803 | 3756 | ||
@@ -3806,7 +3759,7 @@ static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) | |||
3806 | bus->rxlen = 0; | 3759 | bus->rxlen = 0; |
3807 | } | 3760 | } |
3808 | 3761 | ||
3809 | static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) | 3762 | static bool brcmf_sdio_probe_malloc(struct brcmf_sdio *bus) |
3810 | { | 3763 | { |
3811 | brcmf_dbg(TRACE, "Enter\n"); | 3764 | brcmf_dbg(TRACE, "Enter\n"); |
3812 | 3765 | ||
@@ -3823,7 +3776,7 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) | |||
3823 | } | 3776 | } |
3824 | 3777 | ||
3825 | static bool | 3778 | static bool |
3826 | brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | 3779 | brcmf_sdio_probe_attach(struct brcmf_sdio *bus) |
3827 | { | 3780 | { |
3828 | u8 clkctl = 0; | 3781 | u8 clkctl = 0; |
3829 | int err = 0; | 3782 | int err = 0; |
@@ -3836,18 +3789,18 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3836 | sdio_claim_host(bus->sdiodev->func[1]); | 3789 | sdio_claim_host(bus->sdiodev->func[1]); |
3837 | 3790 | ||
3838 | pr_debug("F1 signature read @0x18000000=0x%4x\n", | 3791 | pr_debug("F1 signature read @0x18000000=0x%4x\n", |
3839 | brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL)); | 3792 | brcmf_sdiod_regrl(bus->sdiodev, SI_ENUM_BASE, NULL)); |
3840 | 3793 | ||
3841 | /* | 3794 | /* |
3842 | * Force PLL off until brcmf_sdio_chip_attach() | 3795 | * Force PLL off until brcmf_sdio_chip_attach() |
3843 | * programs PLL control regs | 3796 | * programs PLL control regs |
3844 | */ | 3797 | */ |
3845 | 3798 | ||
3846 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 3799 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
3847 | BRCMF_INIT_CLKCTL1, &err); | 3800 | BRCMF_INIT_CLKCTL1, &err); |
3848 | if (!err) | 3801 | if (!err) |
3849 | clkctl = brcmf_sdio_regrb(bus->sdiodev, | 3802 | clkctl = brcmf_sdiod_regrb(bus->sdiodev, |
3850 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 3803 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
3851 | 3804 | ||
3852 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { | 3805 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { |
3853 | brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", | 3806 | brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", |
@@ -3855,12 +3808,12 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3855 | goto fail; | 3808 | goto fail; |
3856 | } | 3809 | } |
3857 | 3810 | ||
3858 | if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci, regsva)) { | 3811 | if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) { |
3859 | brcmf_err("brcmf_sdio_chip_attach failed!\n"); | 3812 | brcmf_err("brcmf_sdio_chip_attach failed!\n"); |
3860 | goto fail; | 3813 | goto fail; |
3861 | } | 3814 | } |
3862 | 3815 | ||
3863 | if (brcmf_sdbrcm_kso_init(bus)) { | 3816 | if (brcmf_sdio_kso_init(bus)) { |
3864 | brcmf_err("error enabling KSO\n"); | 3817 | brcmf_err("error enabling KSO\n"); |
3865 | goto fail; | 3818 | goto fail; |
3866 | } | 3819 | } |
@@ -3879,33 +3832,33 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3879 | } | 3832 | } |
3880 | 3833 | ||
3881 | /* Set card control so an SDIO card reset does a WLAN backplane reset */ | 3834 | /* Set card control so an SDIO card reset does a WLAN backplane reset */ |
3882 | reg_val = brcmf_sdio_regrb(bus->sdiodev, | 3835 | reg_val = brcmf_sdiod_regrb(bus->sdiodev, |
3883 | SDIO_CCCR_BRCM_CARDCTRL, &err); | 3836 | SDIO_CCCR_BRCM_CARDCTRL, &err); |
3884 | if (err) | 3837 | if (err) |
3885 | goto fail; | 3838 | goto fail; |
3886 | 3839 | ||
3887 | reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET; | 3840 | reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET; |
3888 | 3841 | ||
3889 | brcmf_sdio_regwb(bus->sdiodev, | 3842 | brcmf_sdiod_regwb(bus->sdiodev, |
3890 | SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err); | 3843 | SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err); |
3891 | if (err) | 3844 | if (err) |
3892 | goto fail; | 3845 | goto fail; |
3893 | 3846 | ||
3894 | /* set PMUControl so a backplane reset does PMU state reload */ | 3847 | /* set PMUControl so a backplane reset does PMU state reload */ |
3895 | reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base, | 3848 | reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base, |
3896 | pmucontrol); | 3849 | pmucontrol); |
3897 | reg_val = brcmf_sdio_regrl(bus->sdiodev, | 3850 | reg_val = brcmf_sdiod_regrl(bus->sdiodev, |
3898 | reg_addr, | 3851 | reg_addr, |
3899 | &err); | 3852 | &err); |
3900 | if (err) | 3853 | if (err) |
3901 | goto fail; | 3854 | goto fail; |
3902 | 3855 | ||
3903 | reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT); | 3856 | reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT); |
3904 | 3857 | ||
3905 | brcmf_sdio_regwl(bus->sdiodev, | 3858 | brcmf_sdiod_regwl(bus->sdiodev, |
3906 | reg_addr, | 3859 | reg_addr, |
3907 | reg_val, | 3860 | reg_val, |
3908 | &err); | 3861 | &err); |
3909 | if (err) | 3862 | if (err) |
3910 | goto fail; | 3863 | goto fail; |
3911 | 3864 | ||
@@ -3935,21 +3888,20 @@ fail: | |||
3935 | return false; | 3888 | return false; |
3936 | } | 3889 | } |
3937 | 3890 | ||
3938 | static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | 3891 | static bool brcmf_sdio_probe_init(struct brcmf_sdio *bus) |
3939 | { | 3892 | { |
3940 | brcmf_dbg(TRACE, "Enter\n"); | 3893 | brcmf_dbg(TRACE, "Enter\n"); |
3941 | 3894 | ||
3942 | sdio_claim_host(bus->sdiodev->func[1]); | 3895 | sdio_claim_host(bus->sdiodev->func[1]); |
3943 | 3896 | ||
3944 | /* Disable F2 to clear any intermediate frame state on the dongle */ | 3897 | /* Disable F2 to clear any intermediate frame state on the dongle */ |
3945 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, | 3898 | sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); |
3946 | SDIO_FUNC_ENABLE_1, NULL); | ||
3947 | 3899 | ||
3948 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 3900 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
3949 | bus->rxflow = false; | 3901 | bus->rxflow = false; |
3950 | 3902 | ||
3951 | /* Done with backplane-dependent accesses, can drop clock... */ | 3903 | /* Done with backplane-dependent accesses, can drop clock... */ |
3952 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | 3904 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); |
3953 | 3905 | ||
3954 | sdio_release_host(bus->sdiodev->func[1]); | 3906 | sdio_release_host(bus->sdiodev->func[1]); |
3955 | 3907 | ||
@@ -3970,7 +3922,7 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | |||
3970 | } | 3922 | } |
3971 | 3923 | ||
3972 | static int | 3924 | static int |
3973 | brcmf_sdbrcm_watchdog_thread(void *data) | 3925 | brcmf_sdio_watchdog_thread(void *data) |
3974 | { | 3926 | { |
3975 | struct brcmf_sdio *bus = (struct brcmf_sdio *)data; | 3927 | struct brcmf_sdio *bus = (struct brcmf_sdio *)data; |
3976 | 3928 | ||
@@ -3980,7 +3932,7 @@ brcmf_sdbrcm_watchdog_thread(void *data) | |||
3980 | if (kthread_should_stop()) | 3932 | if (kthread_should_stop()) |
3981 | break; | 3933 | break; |
3982 | if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { | 3934 | if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { |
3983 | brcmf_sdbrcm_bus_watchdog(bus); | 3935 | brcmf_sdio_bus_watchdog(bus); |
3984 | /* Count the tick for reference */ | 3936 | /* Count the tick for reference */ |
3985 | bus->sdcnt.tickcnt++; | 3937 | bus->sdcnt.tickcnt++; |
3986 | } else | 3938 | } else |
@@ -3990,7 +3942,7 @@ brcmf_sdbrcm_watchdog_thread(void *data) | |||
3990 | } | 3942 | } |
3991 | 3943 | ||
3992 | static void | 3944 | static void |
3993 | brcmf_sdbrcm_watchdog(unsigned long data) | 3945 | brcmf_sdio_watchdog(unsigned long data) |
3994 | { | 3946 | { |
3995 | struct brcmf_sdio *bus = (struct brcmf_sdio *)data; | 3947 | struct brcmf_sdio *bus = (struct brcmf_sdio *)data; |
3996 | 3948 | ||
@@ -4003,14 +3955,14 @@ brcmf_sdbrcm_watchdog(unsigned long data) | |||
4003 | } | 3955 | } |
4004 | } | 3956 | } |
4005 | 3957 | ||
4006 | static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus) | 3958 | static void brcmf_sdio_release_dongle(struct brcmf_sdio *bus) |
4007 | { | 3959 | { |
4008 | brcmf_dbg(TRACE, "Enter\n"); | 3960 | brcmf_dbg(TRACE, "Enter\n"); |
4009 | 3961 | ||
4010 | if (bus->ci) { | 3962 | if (bus->ci) { |
4011 | sdio_claim_host(bus->sdiodev->func[1]); | 3963 | sdio_claim_host(bus->sdiodev->func[1]); |
4012 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 3964 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
4013 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); | 3965 | brcmf_sdio_clkctl(bus, CLK_NONE, false); |
4014 | sdio_release_host(bus->sdiodev->func[1]); | 3966 | sdio_release_host(bus->sdiodev->func[1]); |
4015 | brcmf_sdio_chip_detach(&bus->ci); | 3967 | brcmf_sdio_chip_detach(&bus->ci); |
4016 | if (bus->vars && bus->varsz) | 3968 | if (bus->vars && bus->varsz) |
@@ -4021,53 +3973,23 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus) | |||
4021 | brcmf_dbg(TRACE, "Disconnected\n"); | 3973 | brcmf_dbg(TRACE, "Disconnected\n"); |
4022 | } | 3974 | } |
4023 | 3975 | ||
4024 | /* Detach and free everything */ | ||
4025 | static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) | ||
4026 | { | ||
4027 | brcmf_dbg(TRACE, "Enter\n"); | ||
4028 | |||
4029 | if (bus) { | ||
4030 | /* De-register interrupt handler */ | ||
4031 | brcmf_sdio_intr_unregister(bus->sdiodev); | ||
4032 | |||
4033 | cancel_work_sync(&bus->datawork); | ||
4034 | if (bus->brcmf_wq) | ||
4035 | destroy_workqueue(bus->brcmf_wq); | ||
4036 | |||
4037 | if (bus->sdiodev->bus_if->drvr) { | ||
4038 | brcmf_detach(bus->sdiodev->dev); | ||
4039 | brcmf_sdbrcm_release_dongle(bus); | ||
4040 | } | ||
4041 | |||
4042 | brcmu_pkt_buf_free_skb(bus->txglom_sgpad); | ||
4043 | brcmf_sdbrcm_release_malloc(bus); | ||
4044 | kfree(bus->hdrbuf); | ||
4045 | kfree(bus); | ||
4046 | } | ||
4047 | |||
4048 | brcmf_dbg(TRACE, "Disconnected\n"); | ||
4049 | } | ||
4050 | |||
4051 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | 3976 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { |
4052 | .stop = brcmf_sdbrcm_bus_stop, | 3977 | .stop = brcmf_sdio_bus_stop, |
4053 | .preinit = brcmf_sdbrcm_bus_preinit, | 3978 | .preinit = brcmf_sdio_bus_preinit, |
4054 | .init = brcmf_sdbrcm_bus_init, | 3979 | .init = brcmf_sdio_bus_init, |
4055 | .txdata = brcmf_sdbrcm_bus_txdata, | 3980 | .txdata = brcmf_sdio_bus_txdata, |
4056 | .txctl = brcmf_sdbrcm_bus_txctl, | 3981 | .txctl = brcmf_sdio_bus_txctl, |
4057 | .rxctl = brcmf_sdbrcm_bus_rxctl, | 3982 | .rxctl = brcmf_sdio_bus_rxctl, |
4058 | .gettxq = brcmf_sdbrcm_bus_gettxq, | 3983 | .gettxq = brcmf_sdio_bus_gettxq, |
4059 | }; | 3984 | }; |
4060 | 3985 | ||
4061 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | 3986 | struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) |
4062 | { | 3987 | { |
4063 | int ret; | 3988 | int ret; |
4064 | struct brcmf_sdio *bus; | 3989 | struct brcmf_sdio *bus; |
4065 | 3990 | ||
4066 | brcmf_dbg(TRACE, "Enter\n"); | 3991 | brcmf_dbg(TRACE, "Enter\n"); |
4067 | 3992 | ||
4068 | /* We make an assumption about address window mappings: | ||
4069 | * regsva == SI_ENUM_BASE*/ | ||
4070 | |||
4071 | /* Allocate private bus interface state */ | 3993 | /* Allocate private bus interface state */ |
4072 | bus = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC); | 3994 | bus = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC); |
4073 | if (!bus) | 3995 | if (!bus) |
@@ -4101,8 +4023,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4101 | } | 4023 | } |
4102 | 4024 | ||
4103 | /* attempt to attach to the dongle */ | 4025 | /* attempt to attach to the dongle */ |
4104 | if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { | 4026 | if (!(brcmf_sdio_probe_attach(bus))) { |
4105 | brcmf_err("brcmf_sdbrcm_probe_attach failed\n"); | 4027 | brcmf_err("brcmf_sdio_probe_attach failed\n"); |
4106 | goto fail; | 4028 | goto fail; |
4107 | } | 4029 | } |
4108 | 4030 | ||
@@ -4114,11 +4036,11 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4114 | /* Set up the watchdog timer */ | 4036 | /* Set up the watchdog timer */ |
4115 | init_timer(&bus->timer); | 4037 | init_timer(&bus->timer); |
4116 | bus->timer.data = (unsigned long)bus; | 4038 | bus->timer.data = (unsigned long)bus; |
4117 | bus->timer.function = brcmf_sdbrcm_watchdog; | 4039 | bus->timer.function = brcmf_sdio_watchdog; |
4118 | 4040 | ||
4119 | /* Initialize watchdog thread */ | 4041 | /* Initialize watchdog thread */ |
4120 | init_completion(&bus->watchdog_wait); | 4042 | init_completion(&bus->watchdog_wait); |
4121 | bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread, | 4043 | bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread, |
4122 | bus, "brcmf_watchdog"); | 4044 | bus, "brcmf_watchdog"); |
4123 | if (IS_ERR(bus->watchdog_tsk)) { | 4045 | if (IS_ERR(bus->watchdog_tsk)) { |
4124 | pr_warn("brcmf_watchdog thread failed to start\n"); | 4046 | pr_warn("brcmf_watchdog thread failed to start\n"); |
@@ -4144,13 +4066,13 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4144 | } | 4066 | } |
4145 | 4067 | ||
4146 | /* Allocate buffers */ | 4068 | /* Allocate buffers */ |
4147 | if (!(brcmf_sdbrcm_probe_malloc(bus))) { | 4069 | if (!(brcmf_sdio_probe_malloc(bus))) { |
4148 | brcmf_err("brcmf_sdbrcm_probe_malloc failed\n"); | 4070 | brcmf_err("brcmf_sdio_probe_malloc failed\n"); |
4149 | goto fail; | 4071 | goto fail; |
4150 | } | 4072 | } |
4151 | 4073 | ||
4152 | if (!(brcmf_sdbrcm_probe_init(bus))) { | 4074 | if (!(brcmf_sdio_probe_init(bus))) { |
4153 | brcmf_err("brcmf_sdbrcm_probe_init failed\n"); | 4075 | brcmf_err("brcmf_sdio_probe_init failed\n"); |
4154 | goto fail; | 4076 | goto fail; |
4155 | } | 4077 | } |
4156 | 4078 | ||
@@ -4167,24 +4089,38 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4167 | return bus; | 4089 | return bus; |
4168 | 4090 | ||
4169 | fail: | 4091 | fail: |
4170 | brcmf_sdbrcm_release(bus); | 4092 | brcmf_sdio_remove(bus); |
4171 | return NULL; | 4093 | return NULL; |
4172 | } | 4094 | } |
4173 | 4095 | ||
4174 | void brcmf_sdbrcm_disconnect(void *ptr) | 4096 | /* Detach and free everything */ |
4097 | void brcmf_sdio_remove(struct brcmf_sdio *bus) | ||
4175 | { | 4098 | { |
4176 | struct brcmf_sdio *bus = (struct brcmf_sdio *)ptr; | ||
4177 | |||
4178 | brcmf_dbg(TRACE, "Enter\n"); | 4099 | brcmf_dbg(TRACE, "Enter\n"); |
4179 | 4100 | ||
4180 | if (bus) | 4101 | if (bus) { |
4181 | brcmf_sdbrcm_release(bus); | 4102 | /* De-register interrupt handler */ |
4103 | brcmf_sdiod_intr_unregister(bus->sdiodev); | ||
4104 | |||
4105 | cancel_work_sync(&bus->datawork); | ||
4106 | if (bus->brcmf_wq) | ||
4107 | destroy_workqueue(bus->brcmf_wq); | ||
4108 | |||
4109 | if (bus->sdiodev->bus_if->drvr) { | ||
4110 | brcmf_detach(bus->sdiodev->dev); | ||
4111 | brcmf_sdio_release_dongle(bus); | ||
4112 | } | ||
4113 | |||
4114 | brcmu_pkt_buf_free_skb(bus->txglom_sgpad); | ||
4115 | brcmf_sdio_release_malloc(bus); | ||
4116 | kfree(bus->hdrbuf); | ||
4117 | kfree(bus); | ||
4118 | } | ||
4182 | 4119 | ||
4183 | brcmf_dbg(TRACE, "Disconnected\n"); | 4120 | brcmf_dbg(TRACE, "Disconnected\n"); |
4184 | } | 4121 | } |
4185 | 4122 | ||
4186 | void | 4123 | void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick) |
4187 | brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick) | ||
4188 | { | 4124 | { |
4189 | /* Totally stop the timer */ | 4125 | /* Totally stop the timer */ |
4190 | if (!wdtick && bus->wd_timer_valid) { | 4126 | if (!wdtick && bus->wd_timer_valid) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index b72d3395499a..22adbe311d20 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -68,7 +68,7 @@ brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | |||
68 | 68 | ||
69 | brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); | 69 | brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); |
70 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 70 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, |
71 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data"); | 71 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); |
72 | 72 | ||
73 | err = brcmf_fil_cmd_data(ifp, cmd, data, len, true); | 73 | err = brcmf_fil_cmd_data(ifp, cmd, data, len, true); |
74 | mutex_unlock(&ifp->drvr->proto_block); | 74 | mutex_unlock(&ifp->drvr->proto_block); |
@@ -86,7 +86,7 @@ brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | |||
86 | 86 | ||
87 | brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); | 87 | brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); |
88 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 88 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, |
89 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data"); | 89 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); |
90 | 90 | ||
91 | mutex_unlock(&ifp->drvr->proto_block); | 91 | mutex_unlock(&ifp->drvr->proto_block); |
92 | 92 | ||
@@ -155,7 +155,7 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, | |||
155 | 155 | ||
156 | brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); | 156 | brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); |
157 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 157 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, |
158 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data"); | 158 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); |
159 | 159 | ||
160 | buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, | 160 | buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, |
161 | sizeof(drvr->proto_buf)); | 161 | sizeof(drvr->proto_buf)); |
@@ -195,7 +195,7 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, | |||
195 | 195 | ||
196 | brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); | 196 | brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); |
197 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 197 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, |
198 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data"); | 198 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); |
199 | 199 | ||
200 | mutex_unlock(&drvr->proto_block); | 200 | mutex_unlock(&drvr->proto_block); |
201 | return err; | 201 | return err; |
@@ -278,7 +278,7 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, | |||
278 | 278 | ||
279 | brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); | 279 | brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); |
280 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 280 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, |
281 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data"); | 281 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); |
282 | 282 | ||
283 | buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, | 283 | buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, |
284 | drvr->proto_buf, sizeof(drvr->proto_buf)); | 284 | drvr->proto_buf, sizeof(drvr->proto_buf)); |
@@ -317,7 +317,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, | |||
317 | } | 317 | } |
318 | brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); | 318 | brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); |
319 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, | 319 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, |
320 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data"); | 320 | min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); |
321 | 321 | ||
322 | mutex_unlock(&drvr->proto_block); | 322 | mutex_unlock(&drvr->proto_block); |
323 | return err; | 323 | return err; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index e9bdfdb95d8f..7918c1033662 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -838,7 +838,7 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) | |||
838 | brcmf_fws_hanger_cleanup(fws, matchfn, ifidx); | 838 | brcmf_fws_hanger_cleanup(fws, matchfn, ifidx); |
839 | } | 839 | } |
840 | 840 | ||
841 | static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) | 841 | static u8 brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) |
842 | { | 842 | { |
843 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | 843 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; |
844 | u8 *wlh; | 844 | u8 *wlh; |
@@ -887,9 +887,7 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) | |||
887 | if (fillers) | 887 | if (fillers) |
888 | memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers); | 888 | memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers); |
889 | 889 | ||
890 | brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX), | 890 | return (u8)(data_offset >> 2); |
891 | data_offset >> 2, skb); | ||
892 | return 0; | ||
893 | } | 891 | } |
894 | 892 | ||
895 | static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, | 893 | static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, |
@@ -897,10 +895,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, | |||
897 | int fifo, bool send_immediately) | 895 | int fifo, bool send_immediately) |
898 | { | 896 | { |
899 | struct sk_buff *skb; | 897 | struct sk_buff *skb; |
900 | struct brcmf_bus *bus; | ||
901 | struct brcmf_skbuff_cb *skcb; | 898 | struct brcmf_skbuff_cb *skcb; |
902 | s32 err; | 899 | s32 err; |
903 | u32 len; | 900 | u32 len; |
901 | u8 data_offset; | ||
902 | int ifidx; | ||
904 | 903 | ||
905 | /* check delayedQ and suppressQ in one call using bitmap */ | 904 | /* check delayedQ and suppressQ in one call using bitmap */ |
906 | if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0) | 905 | if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0) |
@@ -928,13 +927,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, | |||
928 | skcb->state = BRCMF_FWS_SKBSTATE_TIM; | 927 | skcb->state = BRCMF_FWS_SKBSTATE_TIM; |
929 | skcb->htod = 0; | 928 | skcb->htod = 0; |
930 | skcb->htod_seq = 0; | 929 | skcb->htod_seq = 0; |
931 | bus = fws->drvr->bus_if; | 930 | data_offset = brcmf_fws_hdrpush(fws, skb); |
932 | err = brcmf_fws_hdrpush(fws, skb); | 931 | ifidx = brcmf_skb_if_flags_get_field(skb, INDEX); |
933 | if (err == 0) { | 932 | brcmf_fws_unlock(fws); |
934 | brcmf_fws_unlock(fws); | 933 | err = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb); |
935 | err = brcmf_bus_txdata(bus, skb); | 934 | brcmf_fws_lock(fws); |
936 | brcmf_fws_lock(fws); | ||
937 | } | ||
938 | if (err) | 935 | if (err) |
939 | brcmu_pkt_buf_free_skb(skb); | 936 | brcmu_pkt_buf_free_skb(skb); |
940 | return true; | 937 | return true; |
@@ -1393,7 +1390,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | |||
1393 | entry->generation = genbit; | 1390 | entry->generation = genbit; |
1394 | 1391 | ||
1395 | ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); | 1392 | ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); |
1396 | if (ret == 0) | 1393 | if (ret == 0) { |
1397 | brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); | 1394 | brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); |
1398 | brcmf_skbcb(skb)->htod_seq = seq; | 1395 | brcmf_skbcb(skb)->htod_seq = seq; |
1399 | if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { | 1396 | if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { |
@@ -1404,6 +1401,8 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | |||
1404 | } | 1401 | } |
1405 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, | 1402 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, |
1406 | skb); | 1403 | skb); |
1404 | } | ||
1405 | |||
1407 | if (ret != 0) { | 1406 | if (ret != 0) { |
1408 | /* suppress q is full or hdrpull failed, drop this packet */ | 1407 | /* suppress q is full or hdrpull failed, drop this packet */ |
1409 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, | 1408 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, |
@@ -1717,7 +1716,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | |||
1717 | return 0; | 1716 | return 0; |
1718 | } | 1717 | } |
1719 | 1718 | ||
1720 | static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, | 1719 | static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, |
1721 | struct sk_buff *p) | 1720 | struct sk_buff *p) |
1722 | { | 1721 | { |
1723 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); | 1722 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); |
@@ -1735,7 +1734,7 @@ static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, | |||
1735 | flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; | 1734 | flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; |
1736 | } | 1735 | } |
1737 | brcmf_skb_htod_tag_set_field(p, FLAGS, flags); | 1736 | brcmf_skb_htod_tag_set_field(p, FLAGS, flags); |
1738 | brcmf_fws_hdrpush(fws, p); | 1737 | return brcmf_fws_hdrpush(fws, p); |
1739 | } | 1738 | } |
1740 | 1739 | ||
1741 | static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, | 1740 | static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, |
@@ -1803,20 +1802,21 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, | |||
1803 | { | 1802 | { |
1804 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); | 1803 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); |
1805 | struct brcmf_fws_mac_descriptor *entry; | 1804 | struct brcmf_fws_mac_descriptor *entry; |
1806 | struct brcmf_bus *bus = fws->drvr->bus_if; | ||
1807 | int rc; | 1805 | int rc; |
1808 | u8 ifidx; | 1806 | u8 ifidx; |
1807 | u8 data_offset; | ||
1809 | 1808 | ||
1810 | entry = skcb->mac; | 1809 | entry = skcb->mac; |
1811 | if (IS_ERR(entry)) | 1810 | if (IS_ERR(entry)) |
1812 | return PTR_ERR(entry); | 1811 | return PTR_ERR(entry); |
1813 | 1812 | ||
1814 | brcmf_fws_precommit_skb(fws, fifo, skb); | 1813 | data_offset = brcmf_fws_precommit_skb(fws, fifo, skb); |
1815 | entry->transit_count++; | 1814 | entry->transit_count++; |
1816 | if (entry->suppressed) | 1815 | if (entry->suppressed) |
1817 | entry->suppr_transit_count++; | 1816 | entry->suppr_transit_count++; |
1817 | ifidx = brcmf_skb_if_flags_get_field(skb, INDEX); | ||
1818 | brcmf_fws_unlock(fws); | 1818 | brcmf_fws_unlock(fws); |
1819 | rc = brcmf_bus_txdata(bus, skb); | 1819 | rc = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb); |
1820 | brcmf_fws_lock(fws); | 1820 | brcmf_fws_lock(fws); |
1821 | brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name, | 1821 | brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name, |
1822 | skcb->if_flags, skcb->htod, rc); | 1822 | skcb->if_flags, skcb->htod, rc); |
@@ -1977,10 +1977,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) | |||
1977 | &skb, true); | 1977 | &skb, true); |
1978 | ifidx = brcmf_skb_if_flags_get_field(skb, | 1978 | ifidx = brcmf_skb_if_flags_get_field(skb, |
1979 | INDEX); | 1979 | INDEX); |
1980 | brcmf_proto_hdrpush(drvr, ifidx, 0, skb); | 1980 | /* Use proto layer to send data frame */ |
1981 | /* Use bus module to send data frame */ | ||
1982 | brcmf_fws_unlock(fws); | 1981 | brcmf_fws_unlock(fws); |
1983 | ret = brcmf_bus_txdata(drvr->bus_if, skb); | 1982 | ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); |
1984 | brcmf_fws_lock(fws); | 1983 | brcmf_fws_lock(fws); |
1985 | if (ret < 0) | 1984 | if (ret < 0) |
1986 | brcmf_txfinalize(drvr, skb, false); | 1985 | brcmf_txfinalize(drvr, skb, false); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c index 87eb2bd4c072..b6b464184946 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c | |||
@@ -39,7 +39,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) | |||
39 | if (brcmf_proto_bcdc_attach(drvr)) | 39 | if (brcmf_proto_bcdc_attach(drvr)) |
40 | goto fail; | 40 | goto fail; |
41 | 41 | ||
42 | if ((proto->hdrpush == NULL) || (proto->hdrpull == NULL) || | 42 | if ((proto->txdata == NULL) || (proto->hdrpull == NULL) || |
43 | (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) { | 43 | (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) { |
44 | brcmf_err("Not all proto handlers have been installed\n"); | 44 | brcmf_err("Not all proto handlers have been installed\n"); |
45 | goto fail; | 45 | goto fail; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h index 8de1b3bce228..482fb0ba4a30 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h | |||
@@ -17,14 +17,14 @@ | |||
17 | #define BRCMFMAC_PROTO_H | 17 | #define BRCMFMAC_PROTO_H |
18 | 18 | ||
19 | struct brcmf_proto { | 19 | struct brcmf_proto { |
20 | void (*hdrpush)(struct brcmf_pub *drvr, int ifidx, u8 offset, | ||
21 | struct sk_buff *skb); | ||
22 | int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | 20 | int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, |
23 | struct sk_buff *skb); | 21 | struct sk_buff *skb); |
24 | int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, | 22 | int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, |
25 | void *buf, uint len); | 23 | void *buf, uint len); |
26 | int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, | 24 | int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, |
27 | uint len); | 25 | uint len); |
26 | int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset, | ||
27 | struct sk_buff *skb); | ||
28 | void *pd; | 28 | void *pd; |
29 | }; | 29 | }; |
30 | 30 | ||
@@ -32,11 +32,6 @@ struct brcmf_proto { | |||
32 | int brcmf_proto_attach(struct brcmf_pub *drvr); | 32 | int brcmf_proto_attach(struct brcmf_pub *drvr); |
33 | void brcmf_proto_detach(struct brcmf_pub *drvr); | 33 | void brcmf_proto_detach(struct brcmf_pub *drvr); |
34 | 34 | ||
35 | static inline void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | ||
36 | u8 offset, struct sk_buff *skb) | ||
37 | { | ||
38 | drvr->proto->hdrpush(drvr, ifidx, offset, skb); | ||
39 | } | ||
40 | static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, | 35 | static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, |
41 | u8 *ifidx, struct sk_buff *skb) | 36 | u8 *ifidx, struct sk_buff *skb) |
42 | { | 37 | { |
@@ -52,6 +47,11 @@ static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx, | |||
52 | { | 47 | { |
53 | return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len); | 48 | return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len); |
54 | } | 49 | } |
50 | static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx, | ||
51 | u8 offset, struct sk_buff *skb) | ||
52 | { | ||
53 | return drvr->proto->txdata(drvr, ifidx, offset, skb); | ||
54 | } | ||
55 | 55 | ||
56 | 56 | ||
57 | #endif /* BRCMFMAC_PROTO_H */ | 57 | #endif /* BRCMFMAC_PROTO_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index 2096a14ef1fb..5f39f28e6efb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
@@ -112,9 +112,9 @@ brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev, | |||
112 | 112 | ||
113 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 113 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
114 | 114 | ||
115 | regdata = brcmf_sdio_regrl(sdiodev, | 115 | regdata = brcmf_sdiod_regrl(sdiodev, |
116 | CORE_SB(ci->c_inf[idx].base, sbidhigh), | 116 | CORE_SB(ci->c_inf[idx].base, sbidhigh), |
117 | NULL); | 117 | NULL); |
118 | return SBCOREREV(regdata); | 118 | return SBCOREREV(regdata); |
119 | } | 119 | } |
120 | 120 | ||
@@ -140,9 +140,9 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
140 | if (idx == BRCMF_MAX_CORENUM) | 140 | if (idx == BRCMF_MAX_CORENUM) |
141 | return false; | 141 | return false; |
142 | 142 | ||
143 | regdata = brcmf_sdio_regrl(sdiodev, | 143 | regdata = brcmf_sdiod_regrl(sdiodev, |
144 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 144 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
145 | NULL); | 145 | NULL); |
146 | regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | | 146 | regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | |
147 | SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); | 147 | SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); |
148 | return (SSB_TMSLOW_CLOCK == regdata); | 148 | return (SSB_TMSLOW_CLOCK == regdata); |
@@ -160,13 +160,13 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
160 | if (idx == BRCMF_MAX_CORENUM) | 160 | if (idx == BRCMF_MAX_CORENUM) |
161 | return false; | 161 | return false; |
162 | 162 | ||
163 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 163 | regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
164 | NULL); | 164 | NULL); |
165 | ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; | 165 | ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; |
166 | 166 | ||
167 | regdata = brcmf_sdio_regrl(sdiodev, | 167 | regdata = brcmf_sdiod_regrl(sdiodev, |
168 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 168 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
169 | NULL); | 169 | NULL); |
170 | ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); | 170 | ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); |
171 | 171 | ||
172 | return ret; | 172 | return ret; |
@@ -182,79 +182,79 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
182 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 182 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
183 | base = ci->c_inf[idx].base; | 183 | base = ci->c_inf[idx].base; |
184 | 184 | ||
185 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); | 185 | regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); |
186 | if (regdata & SSB_TMSLOW_RESET) | 186 | if (regdata & SSB_TMSLOW_RESET) |
187 | return; | 187 | return; |
188 | 188 | ||
189 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); | 189 | regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); |
190 | if ((regdata & SSB_TMSLOW_CLOCK) != 0) { | 190 | if ((regdata & SSB_TMSLOW_CLOCK) != 0) { |
191 | /* | 191 | /* |
192 | * set target reject and spin until busy is clear | 192 | * set target reject and spin until busy is clear |
193 | * (preserve core-specific bits) | 193 | * (preserve core-specific bits) |
194 | */ | 194 | */ |
195 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), | 195 | regdata = brcmf_sdiod_regrl(sdiodev, |
196 | NULL); | 196 | CORE_SB(base, sbtmstatelow), NULL); |
197 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), | 197 | brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
198 | regdata | SSB_TMSLOW_REJECT, NULL); | 198 | regdata | SSB_TMSLOW_REJECT, NULL); |
199 | 199 | ||
200 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), | 200 | regdata = brcmf_sdiod_regrl(sdiodev, |
201 | NULL); | 201 | CORE_SB(base, sbtmstatelow), NULL); |
202 | udelay(1); | 202 | udelay(1); |
203 | SPINWAIT((brcmf_sdio_regrl(sdiodev, | 203 | SPINWAIT((brcmf_sdiod_regrl(sdiodev, |
204 | CORE_SB(base, sbtmstatehigh), | 204 | CORE_SB(base, sbtmstatehigh), |
205 | NULL) & | 205 | NULL) & |
206 | SSB_TMSHIGH_BUSY), 100000); | 206 | SSB_TMSHIGH_BUSY), 100000); |
207 | 207 | ||
208 | regdata = brcmf_sdio_regrl(sdiodev, | 208 | regdata = brcmf_sdiod_regrl(sdiodev, |
209 | CORE_SB(base, sbtmstatehigh), | 209 | CORE_SB(base, sbtmstatehigh), |
210 | NULL); | 210 | NULL); |
211 | if (regdata & SSB_TMSHIGH_BUSY) | 211 | if (regdata & SSB_TMSHIGH_BUSY) |
212 | brcmf_err("core state still busy\n"); | 212 | brcmf_err("core state still busy\n"); |
213 | 213 | ||
214 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow), | 214 | regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow), |
215 | NULL); | 215 | NULL); |
216 | if (regdata & SSB_IDLOW_INITIATOR) { | 216 | if (regdata & SSB_IDLOW_INITIATOR) { |
217 | regdata = brcmf_sdio_regrl(sdiodev, | 217 | regdata = brcmf_sdiod_regrl(sdiodev, |
218 | CORE_SB(base, sbimstate), | 218 | CORE_SB(base, sbimstate), |
219 | NULL); | 219 | NULL); |
220 | regdata |= SSB_IMSTATE_REJECT; | 220 | regdata |= SSB_IMSTATE_REJECT; |
221 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate), | 221 | brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate), |
222 | regdata, NULL); | 222 | regdata, NULL); |
223 | regdata = brcmf_sdio_regrl(sdiodev, | 223 | regdata = brcmf_sdiod_regrl(sdiodev, |
224 | CORE_SB(base, sbimstate), | 224 | CORE_SB(base, sbimstate), |
225 | NULL); | 225 | NULL); |
226 | udelay(1); | 226 | udelay(1); |
227 | SPINWAIT((brcmf_sdio_regrl(sdiodev, | 227 | SPINWAIT((brcmf_sdiod_regrl(sdiodev, |
228 | CORE_SB(base, sbimstate), | 228 | CORE_SB(base, sbimstate), |
229 | NULL) & | 229 | NULL) & |
230 | SSB_IMSTATE_BUSY), 100000); | 230 | SSB_IMSTATE_BUSY), 100000); |
231 | } | 231 | } |
232 | 232 | ||
233 | /* set reset and reject while enabling the clocks */ | 233 | /* set reset and reject while enabling the clocks */ |
234 | regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | | 234 | regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | |
235 | SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET; | 235 | SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET; |
236 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), | 236 | brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
237 | regdata, NULL); | 237 | regdata, NULL); |
238 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), | 238 | regdata = brcmf_sdiod_regrl(sdiodev, |
239 | NULL); | 239 | CORE_SB(base, sbtmstatelow), NULL); |
240 | udelay(10); | 240 | udelay(10); |
241 | 241 | ||
242 | /* clear the initiator reject bit */ | 242 | /* clear the initiator reject bit */ |
243 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow), | 243 | regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow), |
244 | NULL); | 244 | NULL); |
245 | if (regdata & SSB_IDLOW_INITIATOR) { | 245 | if (regdata & SSB_IDLOW_INITIATOR) { |
246 | regdata = brcmf_sdio_regrl(sdiodev, | 246 | regdata = brcmf_sdiod_regrl(sdiodev, |
247 | CORE_SB(base, sbimstate), | 247 | CORE_SB(base, sbimstate), |
248 | NULL); | 248 | NULL); |
249 | regdata &= ~SSB_IMSTATE_REJECT; | 249 | regdata &= ~SSB_IMSTATE_REJECT; |
250 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate), | 250 | brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate), |
251 | regdata, NULL); | 251 | regdata, NULL); |
252 | } | 252 | } |
253 | } | 253 | } |
254 | 254 | ||
255 | /* leave reset and reject asserted */ | 255 | /* leave reset and reject asserted */ |
256 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), | 256 | brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
257 | (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL); | 257 | (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL); |
258 | udelay(1); | 258 | udelay(1); |
259 | } | 259 | } |
260 | 260 | ||
@@ -270,9 +270,9 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
270 | return; | 270 | return; |
271 | 271 | ||
272 | /* if core is already in reset, just return */ | 272 | /* if core is already in reset, just return */ |
273 | regdata = brcmf_sdio_regrl(sdiodev, | 273 | regdata = brcmf_sdiod_regrl(sdiodev, |
274 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 274 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
275 | NULL); | 275 | NULL); |
276 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) | 276 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) |
277 | return; | 277 | return; |
278 | 278 | ||
@@ -281,24 +281,24 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
281 | * extra 10ms is taken into account for firmware load stage | 281 | * extra 10ms is taken into account for firmware load stage |
282 | * after 10300us carry on disabling the core anyway | 282 | * after 10300us carry on disabling the core anyway |
283 | */ | 283 | */ |
284 | SPINWAIT(brcmf_sdio_regrl(sdiodev, | 284 | SPINWAIT(brcmf_sdiod_regrl(sdiodev, |
285 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, | ||
286 | NULL), 10300); | ||
287 | regdata = brcmf_sdio_regrl(sdiodev, | ||
288 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, | 285 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, |
289 | NULL); | 286 | NULL), 10300); |
287 | regdata = brcmf_sdiod_regrl(sdiodev, | ||
288 | ci->c_inf[idx].wrapbase+BCMA_RESET_ST, | ||
289 | NULL); | ||
290 | if (regdata) | 290 | if (regdata) |
291 | brcmf_err("disabling core 0x%x with reset status %x\n", | 291 | brcmf_err("disabling core 0x%x with reset status %x\n", |
292 | coreid, regdata); | 292 | coreid, regdata); |
293 | 293 | ||
294 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 294 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
295 | BCMA_RESET_CTL_RESET, NULL); | 295 | BCMA_RESET_CTL_RESET, NULL); |
296 | udelay(1); | 296 | udelay(1); |
297 | 297 | ||
298 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 298 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
299 | core_bits, NULL); | 299 | core_bits, NULL); |
300 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 300 | regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
301 | NULL); | 301 | NULL); |
302 | usleep_range(10, 20); | 302 | usleep_range(10, 20); |
303 | 303 | ||
304 | } | 304 | } |
@@ -325,47 +325,47 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
325 | * set reset while enabling the clock and | 325 | * set reset while enabling the clock and |
326 | * forcing them on throughout the core | 326 | * forcing them on throughout the core |
327 | */ | 327 | */ |
328 | brcmf_sdio_regwl(sdiodev, | 328 | brcmf_sdiod_regwl(sdiodev, |
329 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 329 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
330 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET, | 330 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET, |
331 | NULL); | 331 | NULL); |
332 | regdata = brcmf_sdio_regrl(sdiodev, | 332 | regdata = brcmf_sdiod_regrl(sdiodev, |
333 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 333 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
334 | NULL); | 334 | NULL); |
335 | udelay(1); | 335 | udelay(1); |
336 | 336 | ||
337 | /* clear any serror */ | 337 | /* clear any serror */ |
338 | regdata = brcmf_sdio_regrl(sdiodev, | 338 | regdata = brcmf_sdiod_regrl(sdiodev, |
339 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), | 339 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), |
340 | NULL); | 340 | NULL); |
341 | if (regdata & SSB_TMSHIGH_SERR) | 341 | if (regdata & SSB_TMSHIGH_SERR) |
342 | brcmf_sdio_regwl(sdiodev, | 342 | brcmf_sdiod_regwl(sdiodev, |
343 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), | 343 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), |
344 | 0, NULL); | 344 | 0, NULL); |
345 | 345 | ||
346 | regdata = brcmf_sdio_regrl(sdiodev, | 346 | regdata = brcmf_sdiod_regrl(sdiodev, |
347 | CORE_SB(ci->c_inf[idx].base, sbimstate), | 347 | CORE_SB(ci->c_inf[idx].base, sbimstate), |
348 | NULL); | 348 | NULL); |
349 | if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) | 349 | if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) |
350 | brcmf_sdio_regwl(sdiodev, | 350 | brcmf_sdiod_regwl(sdiodev, |
351 | CORE_SB(ci->c_inf[idx].base, sbimstate), | 351 | CORE_SB(ci->c_inf[idx].base, sbimstate), |
352 | regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO), | 352 | regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO), |
353 | NULL); | 353 | NULL); |
354 | 354 | ||
355 | /* clear reset and allow it to propagate throughout the core */ | 355 | /* clear reset and allow it to propagate throughout the core */ |
356 | brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 356 | brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
357 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL); | 357 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL); |
358 | regdata = brcmf_sdio_regrl(sdiodev, | 358 | regdata = brcmf_sdiod_regrl(sdiodev, |
359 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 359 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
360 | NULL); | 360 | NULL); |
361 | udelay(1); | 361 | udelay(1); |
362 | 362 | ||
363 | /* leave clock enabled */ | 363 | /* leave clock enabled */ |
364 | brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 364 | brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
365 | SSB_TMSLOW_CLOCK, NULL); | 365 | SSB_TMSLOW_CLOCK, NULL); |
366 | regdata = brcmf_sdio_regrl(sdiodev, | 366 | regdata = brcmf_sdiod_regrl(sdiodev, |
367 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 367 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
368 | NULL); | 368 | NULL); |
369 | udelay(1); | 369 | udelay(1); |
370 | } | 370 | } |
371 | 371 | ||
@@ -384,21 +384,21 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
384 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits); | 384 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits); |
385 | 385 | ||
386 | /* now do initialization sequence */ | 386 | /* now do initialization sequence */ |
387 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 387 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
388 | core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); | 388 | core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); |
389 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 389 | regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
390 | NULL); | 390 | NULL); |
391 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 391 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
392 | 0, NULL); | 392 | 0, NULL); |
393 | regdata = brcmf_sdio_regrl(sdiodev, | 393 | regdata = brcmf_sdiod_regrl(sdiodev, |
394 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 394 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
395 | NULL); | 395 | NULL); |
396 | udelay(1); | 396 | udelay(1); |
397 | 397 | ||
398 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 398 | brcmf_sdiod_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
399 | core_bits | BCMA_IOCTL_CLK, NULL); | 399 | core_bits | BCMA_IOCTL_CLK, NULL); |
400 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 400 | regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
401 | NULL); | 401 | NULL); |
402 | udelay(1); | 402 | udelay(1); |
403 | } | 403 | } |
404 | 404 | ||
@@ -438,7 +438,7 @@ static inline int brcmf_sdio_chip_cichk(struct chip_info *ci) | |||
438 | #endif | 438 | #endif |
439 | 439 | ||
440 | static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | 440 | static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, |
441 | struct chip_info *ci, u32 regs) | 441 | struct chip_info *ci) |
442 | { | 442 | { |
443 | u32 regdata; | 443 | u32 regdata; |
444 | int ret; | 444 | int ret; |
@@ -449,10 +449,10 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
449 | * other ways of recognition should be added here. | 449 | * other ways of recognition should be added here. |
450 | */ | 450 | */ |
451 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; | 451 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; |
452 | ci->c_inf[0].base = regs; | 452 | ci->c_inf[0].base = SI_ENUM_BASE; |
453 | regdata = brcmf_sdio_regrl(sdiodev, | 453 | regdata = brcmf_sdiod_regrl(sdiodev, |
454 | CORE_CC_REG(ci->c_inf[0].base, chipid), | 454 | CORE_CC_REG(ci->c_inf[0].base, chipid), |
455 | NULL); | 455 | NULL); |
456 | ci->chip = regdata & CID_ID_MASK; | 456 | ci->chip = regdata & CID_ID_MASK; |
457 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; | 457 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; |
458 | if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && | 458 | if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && |
@@ -607,7 +607,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
607 | 607 | ||
608 | /* Try forcing SDIO core to do ALPAvail request only */ | 608 | /* Try forcing SDIO core to do ALPAvail request only */ |
609 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; | 609 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; |
610 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); | 610 | brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); |
611 | if (err) { | 611 | if (err) { |
612 | brcmf_err("error writing for HT off\n"); | 612 | brcmf_err("error writing for HT off\n"); |
613 | return err; | 613 | return err; |
@@ -615,8 +615,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
615 | 615 | ||
616 | /* If register supported, wait for ALPAvail and then force ALP */ | 616 | /* If register supported, wait for ALPAvail and then force ALP */ |
617 | /* This may take up to 15 milliseconds */ | 617 | /* This may take up to 15 milliseconds */ |
618 | clkval = brcmf_sdio_regrb(sdiodev, | 618 | clkval = brcmf_sdiod_regrb(sdiodev, |
619 | SBSDIO_FUNC1_CHIPCLKCSR, NULL); | 619 | SBSDIO_FUNC1_CHIPCLKCSR, NULL); |
620 | 620 | ||
621 | if ((clkval & ~SBSDIO_AVBITS) != clkset) { | 621 | if ((clkval & ~SBSDIO_AVBITS) != clkset) { |
622 | brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n", | 622 | brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n", |
@@ -624,8 +624,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
624 | return -EACCES; | 624 | return -EACCES; |
625 | } | 625 | } |
626 | 626 | ||
627 | SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev, | 627 | SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev, |
628 | SBSDIO_FUNC1_CHIPCLKCSR, NULL)), | 628 | SBSDIO_FUNC1_CHIPCLKCSR, NULL)), |
629 | !SBSDIO_ALPAV(clkval)), | 629 | !SBSDIO_ALPAV(clkval)), |
630 | PMU_MAX_TRANSITION_DLY); | 630 | PMU_MAX_TRANSITION_DLY); |
631 | if (!SBSDIO_ALPAV(clkval)) { | 631 | if (!SBSDIO_ALPAV(clkval)) { |
@@ -635,11 +635,11 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
635 | } | 635 | } |
636 | 636 | ||
637 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; | 637 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; |
638 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); | 638 | brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); |
639 | udelay(65); | 639 | udelay(65); |
640 | 640 | ||
641 | /* Also, disable the extra SDIO pull-ups */ | 641 | /* Also, disable the extra SDIO pull-ups */ |
642 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); | 642 | brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); |
643 | 643 | ||
644 | return 0; | 644 | return 0; |
645 | } | 645 | } |
@@ -654,16 +654,16 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, | |||
654 | ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); | 654 | ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); |
655 | 655 | ||
656 | /* get chipcommon capabilites */ | 656 | /* get chipcommon capabilites */ |
657 | ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev, | 657 | ci->c_inf[0].caps = brcmf_sdiod_regrl(sdiodev, |
658 | CORE_CC_REG(base, capabilities), | 658 | CORE_CC_REG(base, capabilities), |
659 | NULL); | 659 | NULL); |
660 | 660 | ||
661 | /* get pmu caps & rev */ | 661 | /* get pmu caps & rev */ |
662 | if (ci->c_inf[0].caps & CC_CAP_PMU) { | 662 | if (ci->c_inf[0].caps & CC_CAP_PMU) { |
663 | ci->pmucaps = | 663 | ci->pmucaps = |
664 | brcmf_sdio_regrl(sdiodev, | 664 | brcmf_sdiod_regrl(sdiodev, |
665 | CORE_CC_REG(base, pmucapabilities), | 665 | CORE_CC_REG(base, pmucapabilities), |
666 | NULL); | 666 | NULL); |
667 | ci->pmurev = ci->pmucaps & PCAP_REV_MASK; | 667 | ci->pmurev = ci->pmucaps & PCAP_REV_MASK; |
668 | } | 668 | } |
669 | 669 | ||
@@ -681,7 +681,7 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, | |||
681 | } | 681 | } |
682 | 682 | ||
683 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | 683 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, |
684 | struct chip_info **ci_ptr, u32 regs) | 684 | struct chip_info **ci_ptr) |
685 | { | 685 | { |
686 | int ret; | 686 | int ret; |
687 | struct chip_info *ci; | 687 | struct chip_info *ci; |
@@ -697,16 +697,16 @@ int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | |||
697 | if (ret != 0) | 697 | if (ret != 0) |
698 | goto err; | 698 | goto err; |
699 | 699 | ||
700 | ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs); | 700 | ret = brcmf_sdio_chip_recognition(sdiodev, ci); |
701 | if (ret != 0) | 701 | if (ret != 0) |
702 | goto err; | 702 | goto err; |
703 | 703 | ||
704 | brcmf_sdio_chip_buscoresetup(sdiodev, ci); | 704 | brcmf_sdio_chip_buscoresetup(sdiodev, ci); |
705 | 705 | ||
706 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup), | 706 | brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup), |
707 | 0, NULL); | 707 | 0, NULL); |
708 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), | 708 | brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), |
709 | 0, NULL); | 709 | 0, NULL); |
710 | 710 | ||
711 | *ci_ptr = ci; | 711 | *ci_ptr = ci; |
712 | return 0; | 712 | return 0; |
@@ -784,12 +784,12 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
784 | } | 784 | } |
785 | } | 785 | } |
786 | addr = CORE_CC_REG(base, chipcontrol_addr); | 786 | addr = CORE_CC_REG(base, chipcontrol_addr); |
787 | brcmf_sdio_regwl(sdiodev, addr, 1, NULL); | 787 | brcmf_sdiod_regwl(sdiodev, addr, 1, NULL); |
788 | cc_data_temp = brcmf_sdio_regrl(sdiodev, addr, NULL); | 788 | cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL); |
789 | cc_data_temp &= ~str_mask; | 789 | cc_data_temp &= ~str_mask; |
790 | drivestrength_sel <<= str_shift; | 790 | drivestrength_sel <<= str_shift; |
791 | cc_data_temp |= drivestrength_sel; | 791 | cc_data_temp |= drivestrength_sel; |
792 | brcmf_sdio_regwl(sdiodev, addr, cc_data_temp, NULL); | 792 | brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL); |
793 | 793 | ||
794 | brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n", | 794 | brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n", |
795 | str_tab[i].strength, drivestrength, cc_data_temp); | 795 | str_tab[i].strength, drivestrength, cc_data_temp); |
@@ -816,8 +816,8 @@ brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr, | |||
816 | memset(nvram_ularray, 0xaa, nvram_sz); | 816 | memset(nvram_ularray, 0xaa, nvram_sz); |
817 | 817 | ||
818 | /* Read the vars list to temp buffer for comparison */ | 818 | /* Read the vars list to temp buffer for comparison */ |
819 | err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray, | 819 | err = brcmf_sdiod_ramrw(sdiodev, false, nvram_addr, nvram_ularray, |
820 | nvram_sz); | 820 | nvram_sz); |
821 | if (err) { | 821 | if (err) { |
822 | brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n", | 822 | brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n", |
823 | err, nvram_sz, nvram_addr); | 823 | err, nvram_sz, nvram_addr); |
@@ -850,7 +850,7 @@ static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev, | |||
850 | nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase; | 850 | nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase; |
851 | 851 | ||
852 | /* Write the vars list */ | 852 | /* Write the vars list */ |
853 | err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz); | 853 | err = brcmf_sdiod_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz); |
854 | if (err) { | 854 | if (err) { |
855 | brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n", | 855 | brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n", |
856 | err, nvram_sz, nvram_addr); | 856 | err, nvram_sz, nvram_addr); |
@@ -874,8 +874,8 @@ static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev, | |||
874 | nvram_addr, nvram_sz, token); | 874 | nvram_addr, nvram_sz, token); |
875 | 875 | ||
876 | /* Write the length token to the last word */ | 876 | /* Write the length token to the last word */ |
877 | if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase), | 877 | if (brcmf_sdiod_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase), |
878 | (u8 *)&token_le, 4)) | 878 | (u8 *)&token_le, 4)) |
879 | return false; | 879 | return false; |
880 | 880 | ||
881 | return true; | 881 | return true; |
@@ -891,7 +891,7 @@ brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev, | |||
891 | ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0); | 891 | ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0); |
892 | 892 | ||
893 | /* clear length token */ | 893 | /* clear length token */ |
894 | brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4); | 894 | brcmf_sdiod_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4); |
895 | } | 895 | } |
896 | 896 | ||
897 | static bool | 897 | static bool |
@@ -913,7 +913,7 @@ brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | |||
913 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); | 913 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); |
914 | reg_addr = ci->c_inf[core_idx].base; | 914 | reg_addr = ci->c_inf[core_idx].base; |
915 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); | 915 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); |
916 | brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); | 916 | brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); |
917 | 917 | ||
918 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); | 918 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0); |
919 | 919 | ||
@@ -942,11 +942,11 @@ brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci, | |||
942 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); | 942 | core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV); |
943 | reg_addr = ci->c_inf[core_idx].base; | 943 | reg_addr = ci->c_inf[core_idx].base; |
944 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); | 944 | reg_addr += offsetof(struct sdpcmd_regs, intstatus); |
945 | brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); | 945 | brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); |
946 | 946 | ||
947 | /* Write reset vector to address 0 */ | 947 | /* Write reset vector to address 0 */ |
948 | brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec, | 948 | brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec, |
949 | sizeof(ci->rst_vec)); | 949 | sizeof(ci->rst_vec)); |
950 | 950 | ||
951 | /* restore ARM */ | 951 | /* restore ARM */ |
952 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0); | 952 | ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h index 507c61c991fa..d0f4b45b24c7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h | |||
@@ -224,7 +224,7 @@ struct sdpcmd_regs { | |||
224 | }; | 224 | }; |
225 | 225 | ||
226 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | 226 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, |
227 | struct chip_info **ci_ptr, u32 regs); | 227 | struct chip_info **ci_ptr); |
228 | void brcmf_sdio_chip_detach(struct chip_info **ci_ptr); | 228 | void brcmf_sdio_chip_detach(struct chip_info **ci_ptr); |
229 | void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | 229 | void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, |
230 | struct chip_info *ci, u32 drivestrength); | 230 | struct chip_info *ci, u32 drivestrength); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index fc0d4f0129db..a0981b32c729 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -164,9 +164,8 @@ struct brcmf_sdio; | |||
164 | struct brcmf_sdio_dev { | 164 | struct brcmf_sdio_dev { |
165 | struct sdio_func *func[SDIO_MAX_FUNCS]; | 165 | struct sdio_func *func[SDIO_MAX_FUNCS]; |
166 | u8 num_funcs; /* Supported funcs on client */ | 166 | u8 num_funcs; /* Supported funcs on client */ |
167 | u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; | ||
168 | u32 sbwad; /* Save backplane window address */ | 167 | u32 sbwad; /* Save backplane window address */ |
169 | void *bus; | 168 | struct brcmf_sdio *bus; |
170 | atomic_t suspend; /* suspend flag */ | 169 | atomic_t suspend; /* suspend flag */ |
171 | wait_queue_head_t request_byte_wait; | 170 | wait_queue_head_t request_byte_wait; |
172 | wait_queue_head_t request_word_wait; | 171 | wait_queue_head_t request_word_wait; |
@@ -185,22 +184,19 @@ struct brcmf_sdio_dev { | |||
185 | }; | 184 | }; |
186 | 185 | ||
187 | /* Register/deregister interrupt handler. */ | 186 | /* Register/deregister interrupt handler. */ |
188 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); | 187 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev); |
189 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); | 188 | int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev); |
190 | 189 | ||
191 | /* sdio device register access interface */ | 190 | /* sdio device register access interface */ |
192 | u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); | 191 | u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
193 | u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); | 192 | u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
194 | void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data, | 193 | void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data, |
195 | int *ret); | 194 | int *ret); |
196 | void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, | 195 | void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, |
197 | int *ret); | 196 | int *ret); |
198 | int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | ||
199 | void *data, bool write); | ||
200 | 197 | ||
201 | /* Buffer transfer to/from device (client) core via cmd53. | 198 | /* Buffer transfer to/from device (client) core via cmd53. |
202 | * fn: function number | 199 | * fn: function number |
203 | * addr: backplane address (i.e. >= regsva from attach) | ||
204 | * flags: backplane width, address increment, sync/async | 200 | * flags: backplane width, address increment, sync/async |
205 | * buf: pointer to memory data buffer | 201 | * buf: pointer to memory data buffer |
206 | * nbytes: number of bytes to transfer to/from buf | 202 | * nbytes: number of bytes to transfer to/from buf |
@@ -210,17 +206,14 @@ int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
210 | * Returns 0 or error code. | 206 | * Returns 0 or error code. |
211 | * NOTE: Async operation is not currently supported. | 207 | * NOTE: Async operation is not currently supported. |
212 | */ | 208 | */ |
213 | int brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 209 | int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev, |
214 | uint flags, struct sk_buff_head *pktq); | 210 | struct sk_buff_head *pktq); |
215 | int brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 211 | int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes); |
216 | uint flags, u8 *buf, uint nbytes); | 212 | |
217 | 213 | int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt); | |
218 | int brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 214 | int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes); |
219 | uint flags, struct sk_buff *pkt); | 215 | int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev, |
220 | int brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 216 | struct sk_buff_head *pktq, uint totlen); |
221 | uint flags, u8 *buf, uint nbytes); | ||
222 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | ||
223 | uint flags, struct sk_buff_head *pktq, uint totlen); | ||
224 | 217 | ||
225 | /* Flags bits */ | 218 | /* Flags bits */ |
226 | 219 | ||
@@ -236,43 +229,16 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
236 | * nbytes: number of bytes to transfer to/from buf | 229 | * nbytes: number of bytes to transfer to/from buf |
237 | * Returns 0 or error code. | 230 | * Returns 0 or error code. |
238 | */ | 231 | */ |
239 | int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, | 232 | int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, |
240 | u8 *buf, uint nbytes); | 233 | u8 *data, uint size); |
241 | int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | ||
242 | u8 *data, uint size); | ||
243 | 234 | ||
244 | /* Issue an abort to the specified function */ | 235 | /* Issue an abort to the specified function */ |
245 | int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); | 236 | int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); |
246 | |||
247 | /* platform specific/high level functions */ | ||
248 | int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); | ||
249 | int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); | ||
250 | |||
251 | /* attach, return handler on success, NULL if failed. | ||
252 | * The handler shall be provided by all subsequent calls. No local cache | ||
253 | * cfghdl points to the starting address of pci device mapped memory | ||
254 | */ | ||
255 | int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev); | ||
256 | void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev); | ||
257 | |||
258 | /* read or write one byte using cmd52 */ | ||
259 | int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc, | ||
260 | uint addr, u8 *byte); | ||
261 | |||
262 | /* read or write 2/4 bytes using cmd53 */ | ||
263 | int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc, | ||
264 | uint addr, u32 *word, uint nbyte); | ||
265 | |||
266 | /* Watchdog timer interface for pm ops */ | ||
267 | void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable); | ||
268 | 237 | ||
269 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev); | 238 | struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); |
270 | void brcmf_sdbrcm_disconnect(void *ptr); | 239 | void brcmf_sdio_remove(struct brcmf_sdio *bus); |
271 | void brcmf_sdbrcm_isr(void *arg); | 240 | void brcmf_sdio_isr(struct brcmf_sdio *bus); |
272 | 241 | ||
273 | void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick); | 242 | void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick); |
274 | 243 | ||
275 | void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, | ||
276 | wait_queue_head_t *wq); | ||
277 | bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev); | ||
278 | #endif /* _BRCM_SDH_H_ */ | 244 | #endif /* _BRCM_SDH_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 51c4de054b15..c345c32eb631 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -1253,6 +1253,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) | |||
1253 | bus->ops = &brcmf_usb_bus_ops; | 1253 | bus->ops = &brcmf_usb_bus_ops; |
1254 | bus->chip = bus_pub->devid; | 1254 | bus->chip = bus_pub->devid; |
1255 | bus->chiprev = bus_pub->chiprev; | 1255 | bus->chiprev = bus_pub->chiprev; |
1256 | bus->proto_type = BRCMF_PROTO_BCDC; | ||
1256 | 1257 | ||
1257 | /* Attach to the common driver interface */ | 1258 | /* Attach to the common driver interface */ |
1258 | ret = brcmf_attach(dev); | 1259 | ret = brcmf_attach(dev); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 217f1ca321a0..9f4239d31c08 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -322,12 +322,6 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) | |||
322 | 322 | ||
323 | flush_workqueue(priv->workqueue); | 323 | flush_workqueue(priv->workqueue); |
324 | 324 | ||
325 | /* User space software may expect getting rfkill changes | ||
326 | * even if interface is down, trans->down will leave the RF | ||
327 | * kill interrupt enabled | ||
328 | */ | ||
329 | iwl_trans_stop_hw(priv->trans, false); | ||
330 | |||
331 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 325 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
332 | } | 326 | } |
333 | 327 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 7aad766865cf..fd9f6cf96cfd 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -1313,7 +1313,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | /* Reset chip to save power until we load uCode during "up". */ | 1315 | /* Reset chip to save power until we load uCode during "up". */ |
1316 | iwl_trans_stop_hw(priv->trans, false); | 1316 | iwl_trans_stop_device(priv->trans); |
1317 | 1317 | ||
1318 | priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg, | 1318 | priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg, |
1319 | priv->eeprom_blob, | 1319 | priv->eeprom_blob, |
@@ -1458,7 +1458,7 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1458 | 1458 | ||
1459 | dev_kfree_skb(priv->beacon_skb); | 1459 | dev_kfree_skb(priv->beacon_skb); |
1460 | 1460 | ||
1461 | iwl_trans_stop_hw(priv->trans, true); | 1461 | iwl_trans_op_mode_leave(priv->trans); |
1462 | ieee80211_free_hw(priv->hw); | 1462 | ieee80211_free_hw(priv->hw); |
1463 | } | 1463 | } |
1464 | 1464 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 3c34a72a5d64..5fb37724c096 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -108,7 +108,7 @@ static const struct iwl_base_params iwl7000_base_params = { | |||
108 | }; | 108 | }; |
109 | 109 | ||
110 | static const struct iwl_ht_params iwl7000_ht_params = { | 110 | static const struct iwl_ht_params iwl7000_ht_params = { |
111 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | 111 | .stbc = true, |
112 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | 112 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), |
113 | }; | 113 | }; |
114 | 114 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 0b916249669e..e05440ff5cd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -162,12 +162,14 @@ struct iwl_base_params { | |||
162 | }; | 162 | }; |
163 | 163 | ||
164 | /* | 164 | /* |
165 | * @stbc: support Tx STBC and 1*SS Rx STBC | ||
165 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | 166 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic |
166 | * @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40 | 167 | * @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40 |
167 | */ | 168 | */ |
168 | struct iwl_ht_params { | 169 | struct iwl_ht_params { |
169 | enum ieee80211_smps_mode smps_mode; | 170 | enum ieee80211_smps_mode smps_mode; |
170 | const bool ht_greenfield_support; /* if used set to true */ | 171 | const bool ht_greenfield_support; /* if used set to true */ |
172 | const bool stbc; | ||
171 | bool use_rts_for_aggregation; | 173 | bool use_rts_for_aggregation; |
172 | u8 ht40_bands; | 174 | u8 ht40_bands; |
173 | }; | 175 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index ff570027e9dd..4bebfb58fc7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -322,6 +322,41 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces, | |||
322 | pieces->img[type].sec[sec].offset = offset; | 322 | pieces->img[type].sec[sec].offset = offset; |
323 | } | 323 | } |
324 | 324 | ||
325 | static int iwl_store_cscheme(struct iwl_fw *fw, const u8 *data, const u32 len) | ||
326 | { | ||
327 | int i, j; | ||
328 | struct iwl_fw_cscheme_list *l = (struct iwl_fw_cscheme_list *)data; | ||
329 | struct iwl_fw_cipher_scheme *fwcs; | ||
330 | struct ieee80211_cipher_scheme *cs; | ||
331 | u32 cipher; | ||
332 | |||
333 | if (len < sizeof(*l) || | ||
334 | len < sizeof(l->size) + l->size * sizeof(l->cs[0])) | ||
335 | return -EINVAL; | ||
336 | |||
337 | for (i = 0, j = 0; i < IWL_UCODE_MAX_CS && i < l->size; i++) { | ||
338 | fwcs = &l->cs[j]; | ||
339 | cipher = le32_to_cpu(fwcs->cipher); | ||
340 | |||
341 | /* we skip schemes with zero cipher suite selector */ | ||
342 | if (!cipher) | ||
343 | continue; | ||
344 | |||
345 | cs = &fw->cs[j++]; | ||
346 | cs->cipher = cipher; | ||
347 | cs->iftype = BIT(NL80211_IFTYPE_STATION); | ||
348 | cs->hdr_len = fwcs->hdr_len; | ||
349 | cs->pn_len = fwcs->pn_len; | ||
350 | cs->pn_off = fwcs->pn_off; | ||
351 | cs->key_idx_off = fwcs->key_idx_off; | ||
352 | cs->key_idx_mask = fwcs->key_idx_mask; | ||
353 | cs->key_idx_shift = fwcs->key_idx_shift; | ||
354 | cs->mic_len = fwcs->mic_len; | ||
355 | } | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
325 | /* | 360 | /* |
326 | * Gets uCode section from tlv. | 361 | * Gets uCode section from tlv. |
327 | */ | 362 | */ |
@@ -729,6 +764,10 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
729 | return -EINVAL; | 764 | return -EINVAL; |
730 | } | 765 | } |
731 | break; | 766 | break; |
767 | case IWL_UCODE_TLV_CSCHEME: | ||
768 | if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len)) | ||
769 | goto invalid_tlv_len; | ||
770 | break; | ||
732 | default: | 771 | default: |
733 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); | 772 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); |
734 | break; | 773 | break; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index f4a6d317a023..4380c16580eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -751,6 +751,13 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | |||
751 | ht_info->ht_supported = true; | 751 | ht_info->ht_supported = true; |
752 | ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40; | 752 | ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40; |
753 | 753 | ||
754 | if (cfg->ht_params->stbc) { | ||
755 | ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | ||
756 | |||
757 | if (tx_chains > 1) | ||
758 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; | ||
759 | } | ||
760 | |||
754 | if (iwlwifi_mod_params.amsdu_size_8K) | 761 | if (iwlwifi_mod_params.amsdu_size_8K) |
755 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | 762 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |
756 | 763 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 6c6c35c5228c..4f95734b2811 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -125,6 +125,7 @@ enum iwl_ucode_tlv_type { | |||
125 | IWL_UCODE_TLV_SECURE_SEC_INIT = 25, | 125 | IWL_UCODE_TLV_SECURE_SEC_INIT = 25, |
126 | IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26, | 126 | IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26, |
127 | IWL_UCODE_TLV_NUM_OF_CPU = 27, | 127 | IWL_UCODE_TLV_NUM_OF_CPU = 27, |
128 | IWL_UCODE_TLV_CSCHEME = 28, | ||
128 | }; | 129 | }; |
129 | 130 | ||
130 | struct iwl_ucode_tlv { | 131 | struct iwl_ucode_tlv { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 75db087120c3..8704e3042ca1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -92,6 +92,9 @@ | |||
92 | * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API | 92 | * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API |
93 | * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command | 93 | * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command |
94 | * containing CAM (Continuous Active Mode) indication. | 94 | * containing CAM (Continuous Active Mode) indication. |
95 | * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a | ||
96 | * single bound interface). | ||
97 | * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save | ||
95 | */ | 98 | */ |
96 | enum iwl_ucode_tlv_flag { | 99 | enum iwl_ucode_tlv_flag { |
97 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 100 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
@@ -113,7 +116,9 @@ enum iwl_ucode_tlv_flag { | |||
113 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), | 116 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), |
114 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), | 117 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), |
115 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), | 118 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), |
119 | IWL_UCODE_TLV_FLAGS_P2P_PS = BIT(21), | ||
116 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), | 120 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), |
121 | IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), | ||
117 | }; | 122 | }; |
118 | 123 | ||
119 | /* The default calibrate table size if not specified by firmware file */ | 124 | /* The default calibrate table size if not specified by firmware file */ |
@@ -209,6 +214,44 @@ enum iwl_fw_phy_cfg { | |||
209 | FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS, | 214 | FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS, |
210 | }; | 215 | }; |
211 | 216 | ||
217 | #define IWL_UCODE_MAX_CS 1 | ||
218 | |||
219 | /** | ||
220 | * struct iwl_fw_cipher_scheme - a cipher scheme supported by FW. | ||
221 | * @cipher: a cipher suite selector | ||
222 | * @flags: cipher scheme flags (currently reserved for a future use) | ||
223 | * @hdr_len: a size of MPDU security header | ||
224 | * @pn_len: a size of PN | ||
225 | * @pn_off: an offset of pn from the beginning of the security header | ||
226 | * @key_idx_off: an offset of key index byte in the security header | ||
227 | * @key_idx_mask: a bit mask of key_idx bits | ||
228 | * @key_idx_shift: bit shift needed to get key_idx | ||
229 | * @mic_len: mic length in bytes | ||
230 | * @hw_cipher: a HW cipher index used in host commands | ||
231 | */ | ||
232 | struct iwl_fw_cipher_scheme { | ||
233 | __le32 cipher; | ||
234 | u8 flags; | ||
235 | u8 hdr_len; | ||
236 | u8 pn_len; | ||
237 | u8 pn_off; | ||
238 | u8 key_idx_off; | ||
239 | u8 key_idx_mask; | ||
240 | u8 key_idx_shift; | ||
241 | u8 mic_len; | ||
242 | u8 hw_cipher; | ||
243 | } __packed; | ||
244 | |||
245 | /** | ||
246 | * struct iwl_fw_cscheme_list - a cipher scheme list | ||
247 | * @size: a number of entries | ||
248 | * @cs: cipher scheme entries | ||
249 | */ | ||
250 | struct iwl_fw_cscheme_list { | ||
251 | u8 size; | ||
252 | struct iwl_fw_cipher_scheme cs[]; | ||
253 | } __packed; | ||
254 | |||
212 | /** | 255 | /** |
213 | * struct iwl_fw - variables associated with the firmware | 256 | * struct iwl_fw - variables associated with the firmware |
214 | * | 257 | * |
@@ -224,6 +267,7 @@ enum iwl_fw_phy_cfg { | |||
224 | * @inst_evtlog_size: event log size for runtime ucode. | 267 | * @inst_evtlog_size: event log size for runtime ucode. |
225 | * @inst_errlog_ptr: error log offfset for runtime ucode. | 268 | * @inst_errlog_ptr: error log offfset for runtime ucode. |
226 | * @mvm_fw: indicates this is MVM firmware | 269 | * @mvm_fw: indicates this is MVM firmware |
270 | * @cipher_scheme: optional external cipher scheme. | ||
227 | */ | 271 | */ |
228 | struct iwl_fw { | 272 | struct iwl_fw { |
229 | u32 ucode_ver; | 273 | u32 ucode_ver; |
@@ -243,6 +287,8 @@ struct iwl_fw { | |||
243 | u32 phy_config; | 287 | u32 phy_config; |
244 | 288 | ||
245 | bool mvm_fw; | 289 | bool mvm_fw; |
290 | |||
291 | struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; | ||
246 | }; | 292 | }; |
247 | 293 | ||
248 | static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw) | 294 | static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 94aef22df73a..a48decc6c68f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -263,13 +263,20 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
263 | struct iwl_nvm_data *data, | 263 | struct iwl_nvm_data *data, |
264 | struct ieee80211_sta_vht_cap *vht_cap) | 264 | struct ieee80211_sta_vht_cap *vht_cap) |
265 | { | 265 | { |
266 | int num_ants = num_of_ant(data->valid_rx_ant); | ||
267 | int bf_sts_cap = num_ants - 1; | ||
268 | |||
266 | vht_cap->vht_supported = true; | 269 | vht_cap->vht_supported = true; |
267 | 270 | ||
268 | vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | | 271 | vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | |
269 | IEEE80211_VHT_CAP_RXSTBC_1 | | 272 | IEEE80211_VHT_CAP_RXSTBC_1 | |
270 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | 273 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | |
274 | bf_sts_cap << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | | ||
271 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | 275 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; |
272 | 276 | ||
277 | if (num_ants > 1) | ||
278 | vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; | ||
279 | |||
273 | if (iwlwifi_mod_params.amsdu_size_8K) | 280 | if (iwlwifi_mod_params.amsdu_size_8K) |
274 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | 281 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; |
275 | 282 | ||
@@ -283,16 +290,22 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
283 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | | 290 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | |
284 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); | 291 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); |
285 | 292 | ||
286 | if (num_of_ant(data->valid_rx_ant) == 1 || | 293 | /* Max rate for Long GI NSS=2 80Mhz is 780Mbps */ |
294 | vht_cap->vht_mcs.rx_highest = cpu_to_le16(780); | ||
295 | |||
296 | if (num_ants == 1 || | ||
287 | cfg->rx_with_siso_diversity) { | 297 | cfg->rx_with_siso_diversity) { |
288 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | 298 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | |
289 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | 299 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; |
290 | /* this works because NOT_SUPPORTED == 3 */ | 300 | /* this works because NOT_SUPPORTED == 3 */ |
291 | vht_cap->vht_mcs.rx_mcs_map |= | 301 | vht_cap->vht_mcs.rx_mcs_map |= |
292 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); | 302 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); |
303 | /* Max rate for Long GI NSS=1 80Mhz is 390Mbps */ | ||
304 | vht_cap->vht_mcs.rx_highest = cpu_to_le16(390); | ||
293 | } | 305 | } |
294 | 306 | ||
295 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; | 307 | vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; |
308 | vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest; | ||
296 | } | 309 | } |
297 | 310 | ||
298 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 311 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 976448a57d02..f50e6c62ebc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -155,14 +155,12 @@ void iwl_opmode_deregister(const char *name); | |||
155 | 155 | ||
156 | /** | 156 | /** |
157 | * struct iwl_op_mode - operational mode | 157 | * struct iwl_op_mode - operational mode |
158 | * @ops - pointer to its own ops | ||
158 | * | 159 | * |
159 | * This holds an implementation of the mac80211 / fw API. | 160 | * This holds an implementation of the mac80211 / fw API. |
160 | * | ||
161 | * @ops - pointer to its own ops | ||
162 | */ | 161 | */ |
163 | struct iwl_op_mode { | 162 | struct iwl_op_mode { |
164 | const struct iwl_op_mode_ops *ops; | 163 | const struct iwl_op_mode_ops *ops; |
165 | const struct iwl_trans *trans; | ||
166 | 164 | ||
167 | char op_mode_specific[0] __aligned(sizeof(void *)); | 165 | char op_mode_specific[0] __aligned(sizeof(void *)); |
168 | }; | 166 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 143292b4dbbf..0c3647858909 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -70,6 +70,7 @@ | |||
70 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
71 | #include "iwl-config.h" | 71 | #include "iwl-config.h" |
72 | #include "iwl-fw.h" | 72 | #include "iwl-fw.h" |
73 | #include "iwl-op-mode.h" | ||
73 | 74 | ||
74 | /** | 75 | /** |
75 | * DOC: Transport layer - what is it ? | 76 | * DOC: Transport layer - what is it ? |
@@ -100,8 +101,7 @@ | |||
100 | * start_fw | 101 | * start_fw |
101 | * | 102 | * |
102 | * 5) Then when finished (or reset): | 103 | * 5) Then when finished (or reset): |
103 | * stop_fw (a.k.a. stop device for the moment) | 104 | * stop_device |
104 | * stop_hw | ||
105 | * | 105 | * |
106 | * 6) Eventually, the free function will be called. | 106 | * 6) Eventually, the free function will be called. |
107 | */ | 107 | */ |
@@ -318,6 +318,24 @@ enum iwl_d3_status { | |||
318 | }; | 318 | }; |
319 | 319 | ||
320 | /** | 320 | /** |
321 | * enum iwl_trans_status: transport status flags | ||
322 | * @STATUS_SYNC_HCMD_ACTIVE: a SYNC command is being processed | ||
323 | * @STATUS_DEVICE_ENABLED: APM is enabled | ||
324 | * @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up) | ||
325 | * @STATUS_INT_ENABLED: interrupts are enabled | ||
326 | * @STATUS_RFKILL: the HW RFkill switch is in KILL position | ||
327 | * @STATUS_FW_ERROR: the fw is in error state | ||
328 | */ | ||
329 | enum iwl_trans_status { | ||
330 | STATUS_SYNC_HCMD_ACTIVE, | ||
331 | STATUS_DEVICE_ENABLED, | ||
332 | STATUS_TPOWER_PMI, | ||
333 | STATUS_INT_ENABLED, | ||
334 | STATUS_RFKILL, | ||
335 | STATUS_FW_ERROR, | ||
336 | }; | ||
337 | |||
338 | /** | ||
321 | * struct iwl_trans_config - transport configuration | 339 | * struct iwl_trans_config - transport configuration |
322 | * | 340 | * |
323 | * @op_mode: pointer to the upper layer. | 341 | * @op_mode: pointer to the upper layer. |
@@ -361,9 +379,7 @@ struct iwl_trans; | |||
361 | * | 379 | * |
362 | * @start_hw: starts the HW- from that point on, the HW can send interrupts | 380 | * @start_hw: starts the HW- from that point on, the HW can send interrupts |
363 | * May sleep | 381 | * May sleep |
364 | * @stop_hw: stops the HW- from that point on, the HW will be in low power but | 382 | * @op_mode_leave: Turn off the HW RF kill indication if on |
365 | * will still issue interrupt if the HW RF kill is triggered unless | ||
366 | * op_mode_leaving is true. | ||
367 | * May sleep | 383 | * May sleep |
368 | * @start_fw: allocates and inits all the resources for the transport | 384 | * @start_fw: allocates and inits all the resources for the transport |
369 | * layer. Also kick a fw image. | 385 | * layer. Also kick a fw image. |
@@ -371,8 +387,11 @@ struct iwl_trans; | |||
371 | * @fw_alive: called when the fw sends alive notification. If the fw provides | 387 | * @fw_alive: called when the fw sends alive notification. If the fw provides |
372 | * the SCD base address in SRAM, then provide it here, or 0 otherwise. | 388 | * the SCD base address in SRAM, then provide it here, or 0 otherwise. |
373 | * May sleep | 389 | * May sleep |
374 | * @stop_device:stops the whole device (embedded CPU put to reset) | 390 | * @stop_device: stops the whole device (embedded CPU put to reset) and stops |
375 | * May sleep | 391 | * the HW. From that point on, the HW will be in low power but will still |
392 | * issue interrupt if the HW RF kill is triggered. This callback must do | ||
393 | * the right thing and not crash even if start_hw() was called but not | ||
394 | * start_fw(). May sleep | ||
376 | * @d3_suspend: put the device into the correct mode for WoWLAN during | 395 | * @d3_suspend: put the device into the correct mode for WoWLAN during |
377 | * suspend. This is optional, if not implemented WoWLAN will not be | 396 | * suspend. This is optional, if not implemented WoWLAN will not be |
378 | * supported. This callback may sleep. | 397 | * supported. This callback may sleep. |
@@ -418,7 +437,7 @@ struct iwl_trans; | |||
418 | struct iwl_trans_ops { | 437 | struct iwl_trans_ops { |
419 | 438 | ||
420 | int (*start_hw)(struct iwl_trans *iwl_trans); | 439 | int (*start_hw)(struct iwl_trans *iwl_trans); |
421 | void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving); | 440 | void (*op_mode_leave)(struct iwl_trans *iwl_trans); |
422 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, | 441 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, |
423 | bool run_in_rfkill); | 442 | bool run_in_rfkill); |
424 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); | 443 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); |
@@ -479,6 +498,7 @@ enum iwl_trans_state { | |||
479 | * @ops - pointer to iwl_trans_ops | 498 | * @ops - pointer to iwl_trans_ops |
480 | * @op_mode - pointer to the op_mode | 499 | * @op_mode - pointer to the op_mode |
481 | * @cfg - pointer to the configuration | 500 | * @cfg - pointer to the configuration |
501 | * @status: a bit-mask of transport status flags | ||
482 | * @dev - pointer to struct device * that represents the device | 502 | * @dev - pointer to struct device * that represents the device |
483 | * @hw_id: a u32 with the ID of the device / subdevice. | 503 | * @hw_id: a u32 with the ID of the device / subdevice. |
484 | * Set during transport allocation. | 504 | * Set during transport allocation. |
@@ -499,6 +519,7 @@ struct iwl_trans { | |||
499 | struct iwl_op_mode *op_mode; | 519 | struct iwl_op_mode *op_mode; |
500 | const struct iwl_cfg *cfg; | 520 | const struct iwl_cfg *cfg; |
501 | enum iwl_trans_state state; | 521 | enum iwl_trans_state state; |
522 | unsigned long status; | ||
502 | 523 | ||
503 | struct device *dev; | 524 | struct device *dev; |
504 | u32 hw_rev; | 525 | u32 hw_rev; |
@@ -540,15 +561,14 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans) | |||
540 | return trans->ops->start_hw(trans); | 561 | return trans->ops->start_hw(trans); |
541 | } | 562 | } |
542 | 563 | ||
543 | static inline void iwl_trans_stop_hw(struct iwl_trans *trans, | 564 | static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans) |
544 | bool op_mode_leaving) | ||
545 | { | 565 | { |
546 | might_sleep(); | 566 | might_sleep(); |
547 | 567 | ||
548 | trans->ops->stop_hw(trans, op_mode_leaving); | 568 | if (trans->ops->op_mode_leave) |
569 | trans->ops->op_mode_leave(trans); | ||
549 | 570 | ||
550 | if (op_mode_leaving) | 571 | trans->op_mode = NULL; |
551 | trans->op_mode = NULL; | ||
552 | 572 | ||
553 | trans->state = IWL_TRANS_NO_FW; | 573 | trans->state = IWL_TRANS_NO_FW; |
554 | } | 574 | } |
@@ -570,6 +590,7 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans, | |||
570 | 590 | ||
571 | WARN_ON_ONCE(!trans->rx_mpdu_cmd); | 591 | WARN_ON_ONCE(!trans->rx_mpdu_cmd); |
572 | 592 | ||
593 | clear_bit(STATUS_FW_ERROR, &trans->status); | ||
573 | return trans->ops->start_fw(trans, fw, run_in_rfkill); | 594 | return trans->ops->start_fw(trans, fw, run_in_rfkill); |
574 | } | 595 | } |
575 | 596 | ||
@@ -601,6 +622,9 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
601 | { | 622 | { |
602 | int ret; | 623 | int ret; |
603 | 624 | ||
625 | if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) | ||
626 | return -EIO; | ||
627 | |||
604 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) { | 628 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) { |
605 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 629 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
606 | return -EIO; | 630 | return -EIO; |
@@ -640,6 +664,9 @@ static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, | |||
640 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 664 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
641 | struct iwl_device_cmd *dev_cmd, int queue) | 665 | struct iwl_device_cmd *dev_cmd, int queue) |
642 | { | 666 | { |
667 | if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) | ||
668 | return -EIO; | ||
669 | |||
643 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | 670 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
644 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 671 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
645 | 672 | ||
@@ -760,7 +787,8 @@ static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr, | |||
760 | 787 | ||
761 | static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) | 788 | static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) |
762 | { | 789 | { |
763 | trans->ops->set_pmi(trans, state); | 790 | if (trans->ops->set_pmi) |
791 | trans->ops->set_pmi(trans, state); | ||
764 | } | 792 | } |
765 | 793 | ||
766 | static inline void | 794 | static inline void |
@@ -780,6 +808,16 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags) | |||
780 | __release(nic_access); | 808 | __release(nic_access); |
781 | } | 809 | } |
782 | 810 | ||
811 | static inline void iwl_trans_fw_error(struct iwl_trans *trans) | ||
812 | { | ||
813 | if (WARN_ON_ONCE(!trans->op_mode)) | ||
814 | return; | ||
815 | |||
816 | /* prevent double restarts due to the same erroneous FW */ | ||
817 | if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) | ||
818 | iwl_op_mode_nic_error(trans->op_mode); | ||
819 | } | ||
820 | |||
783 | /***************************************************** | 821 | /***************************************************** |
784 | * driver (transport) register/unregister functions | 822 | * driver (transport) register/unregister functions |
785 | ******************************************************/ | 823 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index 285d8c7486f5..f98ec2b23898 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile | |||
@@ -1,10 +1,9 @@ | |||
1 | obj-$(CONFIG_IWLMVM) += iwlmvm.o | 1 | obj-$(CONFIG_IWLMVM) += iwlmvm.o |
2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o | 2 | iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o |
3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o | 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o |
4 | iwlmvm-y += scan.o time-event.o rs.o | 4 | iwlmvm-y += scan.o time-event.o rs.o |
5 | iwlmvm-y += power.o power_legacy.o bt-coex.o | 5 | iwlmvm-y += power.o power_legacy.o bt-coex.o |
6 | iwlmvm-y += led.o tt.o | 6 | iwlmvm-y += led.o tt.o |
7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | ||
8 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o | 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o |
9 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o | 8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o |
10 | 9 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/binding.c b/drivers/net/wireless/iwlwifi/mvm/binding.c index 93fd1457954b..57d3eed86efa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/binding.c +++ b/drivers/net/wireless/iwlwifi/mvm/binding.c | |||
@@ -183,15 +183,29 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
183 | if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) | 183 | if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) |
184 | return -EINVAL; | 184 | return -EINVAL; |
185 | 185 | ||
186 | /* | ||
187 | * Update SF - Disable if needed. if this fails, SF might still be on | ||
188 | * while many macs are bound, which is forbidden - so fail the binding. | ||
189 | */ | ||
190 | if (iwl_mvm_sf_update(mvm, vif, false)) | ||
191 | return -EINVAL; | ||
192 | |||
186 | return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true); | 193 | return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true); |
187 | } | 194 | } |
188 | 195 | ||
189 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 196 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
190 | { | 197 | { |
191 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 198 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
199 | int ret; | ||
192 | 200 | ||
193 | if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) | 201 | if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) |
194 | return -EINVAL; | 202 | return -EINVAL; |
195 | 203 | ||
196 | return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false); | 204 | ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false); |
205 | |||
206 | if (!ret) | ||
207 | if (iwl_mvm_sf_update(mvm, vif, true)) | ||
208 | IWL_ERR(mvm, "Failed to update SF state\n"); | ||
209 | |||
210 | return ret; | ||
197 | } | 211 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 67f6a2071653..b8667575bc10 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
@@ -63,6 +63,150 @@ | |||
63 | #include "mvm.h" | 63 | #include "mvm.h" |
64 | #include "debugfs.h" | 64 | #include "debugfs.h" |
65 | 65 | ||
66 | static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | ||
67 | struct ieee80211_vif *vif, | ||
68 | enum iwl_dbgfs_pm_mask param, int val) | ||
69 | { | ||
70 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
71 | struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm; | ||
72 | |||
73 | dbgfs_pm->mask |= param; | ||
74 | |||
75 | switch (param) { | ||
76 | case MVM_DEBUGFS_PM_KEEP_ALIVE: { | ||
77 | struct ieee80211_hw *hw = mvm->hw; | ||
78 | int dtimper = hw->conf.ps_dtim_period ?: 1; | ||
79 | int dtimper_msec = dtimper * vif->bss_conf.beacon_int; | ||
80 | |||
81 | IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val); | ||
82 | if (val * MSEC_PER_SEC < 3 * dtimper_msec) | ||
83 | IWL_WARN(mvm, | ||
84 | "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n", | ||
85 | val * MSEC_PER_SEC, 3 * dtimper_msec); | ||
86 | dbgfs_pm->keep_alive_seconds = val; | ||
87 | break; | ||
88 | } | ||
89 | case MVM_DEBUGFS_PM_SKIP_OVER_DTIM: | ||
90 | IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n", | ||
91 | val ? "enabled" : "disabled"); | ||
92 | dbgfs_pm->skip_over_dtim = val; | ||
93 | break; | ||
94 | case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS: | ||
95 | IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val); | ||
96 | dbgfs_pm->skip_dtim_periods = val; | ||
97 | break; | ||
98 | case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT: | ||
99 | IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val); | ||
100 | dbgfs_pm->rx_data_timeout = val; | ||
101 | break; | ||
102 | case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT: | ||
103 | IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val); | ||
104 | dbgfs_pm->tx_data_timeout = val; | ||
105 | break; | ||
106 | case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: | ||
107 | IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); | ||
108 | dbgfs_pm->disable_power_off = val; | ||
109 | break; | ||
110 | case MVM_DEBUGFS_PM_LPRX_ENA: | ||
111 | IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); | ||
112 | dbgfs_pm->lprx_ena = val; | ||
113 | break; | ||
114 | case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD: | ||
115 | IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val); | ||
116 | dbgfs_pm->lprx_rssi_threshold = val; | ||
117 | break; | ||
118 | case MVM_DEBUGFS_PM_SNOOZE_ENABLE: | ||
119 | IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val); | ||
120 | dbgfs_pm->snooze_ena = val; | ||
121 | break; | ||
122 | case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING: | ||
123 | IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val); | ||
124 | dbgfs_pm->uapsd_misbehaving = val; | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf, | ||
130 | size_t count, loff_t *ppos) | ||
131 | { | ||
132 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
133 | struct iwl_mvm *mvm = mvmvif->mvm; | ||
134 | enum iwl_dbgfs_pm_mask param; | ||
135 | int val, ret; | ||
136 | |||
137 | if (!strncmp("keep_alive=", buf, 11)) { | ||
138 | if (sscanf(buf + 11, "%d", &val) != 1) | ||
139 | return -EINVAL; | ||
140 | param = MVM_DEBUGFS_PM_KEEP_ALIVE; | ||
141 | } else if (!strncmp("skip_over_dtim=", buf, 15)) { | ||
142 | if (sscanf(buf + 15, "%d", &val) != 1) | ||
143 | return -EINVAL; | ||
144 | param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM; | ||
145 | } else if (!strncmp("skip_dtim_periods=", buf, 18)) { | ||
146 | if (sscanf(buf + 18, "%d", &val) != 1) | ||
147 | return -EINVAL; | ||
148 | param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS; | ||
149 | } else if (!strncmp("rx_data_timeout=", buf, 16)) { | ||
150 | if (sscanf(buf + 16, "%d", &val) != 1) | ||
151 | return -EINVAL; | ||
152 | param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT; | ||
153 | } else if (!strncmp("tx_data_timeout=", buf, 16)) { | ||
154 | if (sscanf(buf + 16, "%d", &val) != 1) | ||
155 | return -EINVAL; | ||
156 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; | ||
157 | } else if (!strncmp("disable_power_off=", buf, 18) && | ||
158 | !(mvm->fw->ucode_capa.flags & | ||
159 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) { | ||
160 | if (sscanf(buf + 18, "%d", &val) != 1) | ||
161 | return -EINVAL; | ||
162 | param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; | ||
163 | } else if (!strncmp("lprx=", buf, 5)) { | ||
164 | if (sscanf(buf + 5, "%d", &val) != 1) | ||
165 | return -EINVAL; | ||
166 | param = MVM_DEBUGFS_PM_LPRX_ENA; | ||
167 | } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) { | ||
168 | if (sscanf(buf + 20, "%d", &val) != 1) | ||
169 | return -EINVAL; | ||
170 | if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val < | ||
171 | POWER_LPRX_RSSI_THRESHOLD_MIN) | ||
172 | return -EINVAL; | ||
173 | param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD; | ||
174 | } else if (!strncmp("snooze_enable=", buf, 14)) { | ||
175 | if (sscanf(buf + 14, "%d", &val) != 1) | ||
176 | return -EINVAL; | ||
177 | param = MVM_DEBUGFS_PM_SNOOZE_ENABLE; | ||
178 | } else if (!strncmp("uapsd_misbehaving=", buf, 18)) { | ||
179 | if (sscanf(buf + 18, "%d", &val) != 1) | ||
180 | return -EINVAL; | ||
181 | param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING; | ||
182 | } else { | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | |||
186 | mutex_lock(&mvm->mutex); | ||
187 | iwl_dbgfs_update_pm(mvm, vif, param, val); | ||
188 | ret = iwl_mvm_power_update_mode(mvm, vif); | ||
189 | mutex_unlock(&mvm->mutex); | ||
190 | |||
191 | return ret ?: count; | ||
192 | } | ||
193 | |||
194 | static ssize_t iwl_dbgfs_pm_params_read(struct file *file, | ||
195 | char __user *user_buf, | ||
196 | size_t count, loff_t *ppos) | ||
197 | { | ||
198 | struct ieee80211_vif *vif = file->private_data; | ||
199 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
200 | struct iwl_mvm *mvm = mvmvif->mvm; | ||
201 | char buf[512]; | ||
202 | int bufsz = sizeof(buf); | ||
203 | int pos; | ||
204 | |||
205 | pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz); | ||
206 | |||
207 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
208 | } | ||
209 | |||
66 | static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | 210 | static ssize_t iwl_dbgfs_mac_params_read(struct file *file, |
67 | char __user *user_buf, | 211 | char __user *user_buf, |
68 | size_t count, loff_t *ppos) | 212 | size_t count, loff_t *ppos) |
@@ -98,14 +242,17 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | |||
98 | if (vif->type == NL80211_IFTYPE_STATION && | 242 | if (vif->type == NL80211_IFTYPE_STATION && |
99 | ap_sta_id != IWL_MVM_STATION_COUNT) { | 243 | ap_sta_id != IWL_MVM_STATION_COUNT) { |
100 | struct ieee80211_sta *sta; | 244 | struct ieee80211_sta *sta; |
101 | struct iwl_mvm_sta *mvm_sta; | ||
102 | 245 | ||
103 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id], | 246 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id], |
104 | lockdep_is_held(&mvm->mutex)); | 247 | lockdep_is_held(&mvm->mutex)); |
105 | mvm_sta = (void *)sta->drv_priv; | 248 | if (!IS_ERR_OR_NULL(sta)) { |
106 | pos += scnprintf(buf+pos, bufsz-pos, | 249 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
107 | "ap_sta_id %d - reduced Tx power %d\n", | 250 | |
108 | ap_sta_id, mvm_sta->bt_reduced_txpower); | 251 | pos += scnprintf(buf+pos, bufsz-pos, |
252 | "ap_sta_id %d - reduced Tx power %d\n", | ||
253 | ap_sta_id, | ||
254 | mvm_sta->bt_reduced_txpower); | ||
255 | } | ||
109 | } | 256 | } |
110 | 257 | ||
111 | rcu_read_lock(); | 258 | rcu_read_lock(); |
@@ -122,6 +269,201 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | |||
122 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 269 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
123 | } | 270 | } |
124 | 271 | ||
272 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, | ||
273 | enum iwl_dbgfs_bf_mask param, int value) | ||
274 | { | ||
275 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
276 | struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; | ||
277 | |||
278 | dbgfs_bf->mask |= param; | ||
279 | |||
280 | switch (param) { | ||
281 | case MVM_DEBUGFS_BF_ENERGY_DELTA: | ||
282 | dbgfs_bf->bf_energy_delta = value; | ||
283 | break; | ||
284 | case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA: | ||
285 | dbgfs_bf->bf_roaming_energy_delta = value; | ||
286 | break; | ||
287 | case MVM_DEBUGFS_BF_ROAMING_STATE: | ||
288 | dbgfs_bf->bf_roaming_state = value; | ||
289 | break; | ||
290 | case MVM_DEBUGFS_BF_TEMP_THRESHOLD: | ||
291 | dbgfs_bf->bf_temp_threshold = value; | ||
292 | break; | ||
293 | case MVM_DEBUGFS_BF_TEMP_FAST_FILTER: | ||
294 | dbgfs_bf->bf_temp_fast_filter = value; | ||
295 | break; | ||
296 | case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER: | ||
297 | dbgfs_bf->bf_temp_slow_filter = value; | ||
298 | break; | ||
299 | case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: | ||
300 | dbgfs_bf->bf_enable_beacon_filter = value; | ||
301 | break; | ||
302 | case MVM_DEBUGFS_BF_DEBUG_FLAG: | ||
303 | dbgfs_bf->bf_debug_flag = value; | ||
304 | break; | ||
305 | case MVM_DEBUGFS_BF_ESCAPE_TIMER: | ||
306 | dbgfs_bf->bf_escape_timer = value; | ||
307 | break; | ||
308 | case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT: | ||
309 | dbgfs_bf->ba_enable_beacon_abort = value; | ||
310 | break; | ||
311 | case MVM_DEBUGFS_BA_ESCAPE_TIMER: | ||
312 | dbgfs_bf->ba_escape_timer = value; | ||
313 | break; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf, | ||
318 | size_t count, loff_t *ppos) | ||
319 | { | ||
320 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
321 | struct iwl_mvm *mvm = mvmvif->mvm; | ||
322 | enum iwl_dbgfs_bf_mask param; | ||
323 | int value, ret = 0; | ||
324 | |||
325 | if (!strncmp("bf_energy_delta=", buf, 16)) { | ||
326 | if (sscanf(buf+16, "%d", &value) != 1) | ||
327 | return -EINVAL; | ||
328 | if (value < IWL_BF_ENERGY_DELTA_MIN || | ||
329 | value > IWL_BF_ENERGY_DELTA_MAX) | ||
330 | return -EINVAL; | ||
331 | param = MVM_DEBUGFS_BF_ENERGY_DELTA; | ||
332 | } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) { | ||
333 | if (sscanf(buf+24, "%d", &value) != 1) | ||
334 | return -EINVAL; | ||
335 | if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN || | ||
336 | value > IWL_BF_ROAMING_ENERGY_DELTA_MAX) | ||
337 | return -EINVAL; | ||
338 | param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA; | ||
339 | } else if (!strncmp("bf_roaming_state=", buf, 17)) { | ||
340 | if (sscanf(buf+17, "%d", &value) != 1) | ||
341 | return -EINVAL; | ||
342 | if (value < IWL_BF_ROAMING_STATE_MIN || | ||
343 | value > IWL_BF_ROAMING_STATE_MAX) | ||
344 | return -EINVAL; | ||
345 | param = MVM_DEBUGFS_BF_ROAMING_STATE; | ||
346 | } else if (!strncmp("bf_temp_threshold=", buf, 18)) { | ||
347 | if (sscanf(buf+18, "%d", &value) != 1) | ||
348 | return -EINVAL; | ||
349 | if (value < IWL_BF_TEMP_THRESHOLD_MIN || | ||
350 | value > IWL_BF_TEMP_THRESHOLD_MAX) | ||
351 | return -EINVAL; | ||
352 | param = MVM_DEBUGFS_BF_TEMP_THRESHOLD; | ||
353 | } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) { | ||
354 | if (sscanf(buf+20, "%d", &value) != 1) | ||
355 | return -EINVAL; | ||
356 | if (value < IWL_BF_TEMP_FAST_FILTER_MIN || | ||
357 | value > IWL_BF_TEMP_FAST_FILTER_MAX) | ||
358 | return -EINVAL; | ||
359 | param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER; | ||
360 | } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) { | ||
361 | if (sscanf(buf+20, "%d", &value) != 1) | ||
362 | return -EINVAL; | ||
363 | if (value < IWL_BF_TEMP_SLOW_FILTER_MIN || | ||
364 | value > IWL_BF_TEMP_SLOW_FILTER_MAX) | ||
365 | return -EINVAL; | ||
366 | param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER; | ||
367 | } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { | ||
368 | if (sscanf(buf+24, "%d", &value) != 1) | ||
369 | return -EINVAL; | ||
370 | if (value < 0 || value > 1) | ||
371 | return -EINVAL; | ||
372 | param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER; | ||
373 | } else if (!strncmp("bf_debug_flag=", buf, 14)) { | ||
374 | if (sscanf(buf+14, "%d", &value) != 1) | ||
375 | return -EINVAL; | ||
376 | if (value < 0 || value > 1) | ||
377 | return -EINVAL; | ||
378 | param = MVM_DEBUGFS_BF_DEBUG_FLAG; | ||
379 | } else if (!strncmp("bf_escape_timer=", buf, 16)) { | ||
380 | if (sscanf(buf+16, "%d", &value) != 1) | ||
381 | return -EINVAL; | ||
382 | if (value < IWL_BF_ESCAPE_TIMER_MIN || | ||
383 | value > IWL_BF_ESCAPE_TIMER_MAX) | ||
384 | return -EINVAL; | ||
385 | param = MVM_DEBUGFS_BF_ESCAPE_TIMER; | ||
386 | } else if (!strncmp("ba_escape_timer=", buf, 16)) { | ||
387 | if (sscanf(buf+16, "%d", &value) != 1) | ||
388 | return -EINVAL; | ||
389 | if (value < IWL_BA_ESCAPE_TIMER_MIN || | ||
390 | value > IWL_BA_ESCAPE_TIMER_MAX) | ||
391 | return -EINVAL; | ||
392 | param = MVM_DEBUGFS_BA_ESCAPE_TIMER; | ||
393 | } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) { | ||
394 | if (sscanf(buf+23, "%d", &value) != 1) | ||
395 | return -EINVAL; | ||
396 | if (value < 0 || value > 1) | ||
397 | return -EINVAL; | ||
398 | param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT; | ||
399 | } else { | ||
400 | return -EINVAL; | ||
401 | } | ||
402 | |||
403 | mutex_lock(&mvm->mutex); | ||
404 | iwl_dbgfs_update_bf(vif, param, value); | ||
405 | if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) | ||
406 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); | ||
407 | else | ||
408 | ret = iwl_mvm_enable_beacon_filter(mvm, vif); | ||
409 | mutex_unlock(&mvm->mutex); | ||
410 | |||
411 | return ret ?: count; | ||
412 | } | ||
413 | |||
414 | static ssize_t iwl_dbgfs_bf_params_read(struct file *file, | ||
415 | char __user *user_buf, | ||
416 | size_t count, loff_t *ppos) | ||
417 | { | ||
418 | struct ieee80211_vif *vif = file->private_data; | ||
419 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
420 | char buf[256]; | ||
421 | int pos = 0; | ||
422 | const size_t bufsz = sizeof(buf); | ||
423 | struct iwl_beacon_filter_cmd cmd = { | ||
424 | IWL_BF_CMD_CONFIG_DEFAULTS, | ||
425 | .bf_enable_beacon_filter = | ||
426 | cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT), | ||
427 | .ba_enable_beacon_abort = | ||
428 | cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT), | ||
429 | }; | ||
430 | |||
431 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | ||
432 | if (mvmvif->bf_data.bf_enabled) | ||
433 | cmd.bf_enable_beacon_filter = cpu_to_le32(1); | ||
434 | else | ||
435 | cmd.bf_enable_beacon_filter = 0; | ||
436 | |||
437 | pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", | ||
438 | le32_to_cpu(cmd.bf_energy_delta)); | ||
439 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", | ||
440 | le32_to_cpu(cmd.bf_roaming_energy_delta)); | ||
441 | pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", | ||
442 | le32_to_cpu(cmd.bf_roaming_state)); | ||
443 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n", | ||
444 | le32_to_cpu(cmd.bf_temp_threshold)); | ||
445 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n", | ||
446 | le32_to_cpu(cmd.bf_temp_fast_filter)); | ||
447 | pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n", | ||
448 | le32_to_cpu(cmd.bf_temp_slow_filter)); | ||
449 | pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", | ||
450 | le32_to_cpu(cmd.bf_enable_beacon_filter)); | ||
451 | pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", | ||
452 | le32_to_cpu(cmd.bf_debug_flag)); | ||
453 | pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", | ||
454 | le32_to_cpu(cmd.bf_escape_timer)); | ||
455 | pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", | ||
456 | le32_to_cpu(cmd.ba_escape_timer)); | ||
457 | pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", | ||
458 | le32_to_cpu(cmd.ba_enable_beacon_abort)); | ||
459 | |||
460 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
461 | } | ||
462 | |||
463 | #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ | ||
464 | _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) | ||
465 | #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ | ||
466 | _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) | ||
125 | #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \ | 467 | #define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do { \ |
126 | if (!debugfs_create_file(#name, mode, parent, vif, \ | 468 | if (!debugfs_create_file(#name, mode, parent, vif, \ |
127 | &iwl_dbgfs_##name##_ops)) \ | 469 | &iwl_dbgfs_##name##_ops)) \ |
@@ -129,6 +471,8 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | |||
129 | } while (0) | 471 | } while (0) |
130 | 472 | ||
131 | MVM_DEBUGFS_READ_FILE_OPS(mac_params); | 473 | MVM_DEBUGFS_READ_FILE_OPS(mac_params); |
474 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32); | ||
475 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256); | ||
132 | 476 | ||
133 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 477 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
134 | { | 478 | { |
@@ -152,9 +496,21 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
152 | return; | 496 | return; |
153 | } | 497 | } |
154 | 498 | ||
499 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && | ||
500 | ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || | ||
501 | (vif->type == NL80211_IFTYPE_STATION && vif->p2p && | ||
502 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS))) | ||
503 | MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | | ||
504 | S_IRUSR); | ||
505 | |||
155 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, | 506 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, |
156 | S_IRUSR); | 507 | S_IRUSR); |
157 | 508 | ||
509 | if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && | ||
510 | mvmvif == mvm->bf_allowed_vif) | ||
511 | MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, | ||
512 | S_IRUSR | S_IWUSR); | ||
513 | |||
158 | /* | 514 | /* |
159 | * Create symlink for convenience pointing to interface specific | 515 | * Create symlink for convenience pointing to interface specific |
160 | * debugfs entries for the driver. For example, under | 516 | * debugfs entries for the driver. For example, under |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 5cb93ae5cd2f..cb78e5539357 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -85,6 +85,8 @@ | |||
85 | * PBW Snoozing enabled | 85 | * PBW Snoozing enabled |
86 | * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask | 86 | * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask |
87 | * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. | 87 | * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. |
88 | * @POWER_FLAGS_AP_UAPSD_MISBEHAVING_ENA_MSK: AP/GO's uAPSD misbehaving | ||
89 | * detection enablement | ||
88 | */ | 90 | */ |
89 | enum iwl_power_flags { | 91 | enum iwl_power_flags { |
90 | POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), | 92 | POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), |
@@ -94,6 +96,7 @@ enum iwl_power_flags { | |||
94 | POWER_FLAGS_BT_SCO_ENA = BIT(8), | 96 | POWER_FLAGS_BT_SCO_ENA = BIT(8), |
95 | POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9), | 97 | POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9), |
96 | POWER_FLAGS_LPRX_ENA_MSK = BIT(11), | 98 | POWER_FLAGS_LPRX_ENA_MSK = BIT(11), |
99 | POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK = BIT(12), | ||
97 | }; | 100 | }; |
98 | 101 | ||
99 | #define IWL_POWER_VEC_SIZE 5 | 102 | #define IWL_POWER_VEC_SIZE 5 |
@@ -228,6 +231,19 @@ struct iwl_mac_power_cmd { | |||
228 | u8 reserved; | 231 | u8 reserved; |
229 | } __packed; | 232 | } __packed; |
230 | 233 | ||
234 | /* | ||
235 | * struct iwl_uapsd_misbehaving_ap_notif - FW sends this notification when | ||
236 | * associated AP is identified as improperly implementing uAPSD protocol. | ||
237 | * PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78 | ||
238 | * @sta_id: index of station in uCode's station table - associated AP ID in | ||
239 | * this context. | ||
240 | */ | ||
241 | struct iwl_uapsd_misbehaving_ap_notif { | ||
242 | __le32 sta_id; | ||
243 | u8 mac_id; | ||
244 | u8 reserved[3]; | ||
245 | } __packed; | ||
246 | |||
231 | /** | 247 | /** |
232 | * struct iwl_beacon_filter_cmd | 248 | * struct iwl_beacon_filter_cmd |
233 | * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) | 249 | * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index 4aca5933a65d..8c73ba74b6fd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
@@ -138,7 +138,14 @@ enum iwl_sta_flags { | |||
138 | 138 | ||
139 | /** | 139 | /** |
140 | * enum iwl_sta_key_flag - key flags for the ADD_STA host command | 140 | * enum iwl_sta_key_flag - key flags for the ADD_STA host command |
141 | * @STA_KEY_FLG_EN_MSK: mask for encryption algorithm | 141 | * @STA_KEY_FLG_NO_ENC: no encryption |
142 | * @STA_KEY_FLG_WEP: WEP encryption algorithm | ||
143 | * @STA_KEY_FLG_CCM: CCMP encryption algorithm | ||
144 | * @STA_KEY_FLG_TKIP: TKIP encryption algorithm | ||
145 | * @STA_KEY_FLG_EXT: extended cipher algorithm (depends on the FW support) | ||
146 | * @STA_KEY_FLG_CMAC: CMAC encryption algorithm | ||
147 | * @STA_KEY_FLG_ENC_UNKNOWN: unknown encryption algorithm | ||
148 | * @STA_KEY_FLG_EN_MSK: mask for encryption algorithmi value | ||
142 | * @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from | 149 | * @STA_KEY_FLG_WEP_KEY_MAP: wep is either a group key (0 - legacy WEP) or from |
143 | * station info array (1 - n 1X mode) | 150 | * station info array (1 - n 1X mode) |
144 | * @STA_KEY_FLG_KEYID_MSK: the index of the key | 151 | * @STA_KEY_FLG_KEYID_MSK: the index of the key |
@@ -152,6 +159,7 @@ enum iwl_sta_key_flag { | |||
152 | STA_KEY_FLG_WEP = (1 << 0), | 159 | STA_KEY_FLG_WEP = (1 << 0), |
153 | STA_KEY_FLG_CCM = (2 << 0), | 160 | STA_KEY_FLG_CCM = (2 << 0), |
154 | STA_KEY_FLG_TKIP = (3 << 0), | 161 | STA_KEY_FLG_TKIP = (3 << 0), |
162 | STA_KEY_FLG_EXT = (4 << 0), | ||
155 | STA_KEY_FLG_CMAC = (6 << 0), | 163 | STA_KEY_FLG_CMAC = (6 << 0), |
156 | STA_KEY_FLG_ENC_UNKNOWN = (7 << 0), | 164 | STA_KEY_FLG_ENC_UNKNOWN = (7 << 0), |
157 | STA_KEY_FLG_EN_MSK = (7 << 0), | 165 | STA_KEY_FLG_EN_MSK = (7 << 0), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index d606197bde8f..22864671d66c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -132,6 +132,7 @@ enum iwl_tx_flags { | |||
132 | #define TX_CMD_SEC_WEP 0x01 | 132 | #define TX_CMD_SEC_WEP 0x01 |
133 | #define TX_CMD_SEC_CCM 0x02 | 133 | #define TX_CMD_SEC_CCM 0x02 |
134 | #define TX_CMD_SEC_TKIP 0x03 | 134 | #define TX_CMD_SEC_TKIP 0x03 |
135 | #define TX_CMD_SEC_EXT 0x04 | ||
135 | #define TX_CMD_SEC_MSK 0x07 | 136 | #define TX_CMD_SEC_MSK 0x07 |
136 | #define TX_CMD_SEC_WEP_KEY_IDX_POS 6 | 137 | #define TX_CMD_SEC_WEP_KEY_IDX_POS 6 |
137 | #define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0 | 138 | #define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index bad5a552dd8d..1c3079714c2b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -141,6 +141,7 @@ enum { | |||
141 | 141 | ||
142 | /* Power - legacy power table command */ | 142 | /* Power - legacy power table command */ |
143 | POWER_TABLE_CMD = 0x77, | 143 | POWER_TABLE_CMD = 0x77, |
144 | PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78, | ||
144 | 145 | ||
145 | /* Thermal Throttling*/ | 146 | /* Thermal Throttling*/ |
146 | REPLY_THERMAL_MNG_BACKOFF = 0x7e, | 147 | REPLY_THERMAL_MNG_BACKOFF = 0x7e, |
@@ -183,6 +184,7 @@ enum { | |||
183 | BT_PROFILE_NOTIFICATION = 0xce, | 184 | BT_PROFILE_NOTIFICATION = 0xce, |
184 | BT_COEX_CI = 0x5d, | 185 | BT_COEX_CI = 0x5d, |
185 | 186 | ||
187 | REPLY_SF_CFG_CMD = 0xd1, | ||
186 | REPLY_BEACON_FILTERING_CMD = 0xd2, | 188 | REPLY_BEACON_FILTERING_CMD = 0xd2, |
187 | 189 | ||
188 | REPLY_DEBUG_CMD = 0xf0, | 190 | REPLY_DEBUG_CMD = 0xf0, |
@@ -1052,6 +1054,7 @@ enum iwl_mvm_rx_status { | |||
1052 | RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), | 1054 | RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), |
1053 | RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), | 1055 | RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), |
1054 | RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), | 1056 | RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), |
1057 | RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8), | ||
1055 | RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), | 1058 | RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), |
1056 | RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8), | 1059 | RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8), |
1057 | RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8), | 1060 | RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8), |
@@ -1131,6 +1134,7 @@ struct iwl_set_calib_default_cmd { | |||
1131 | } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */ | 1134 | } __packed; /* PHY_CALIB_OVERRIDE_VALUES_S */ |
1132 | 1135 | ||
1133 | #define MAX_PORT_ID_NUM 2 | 1136 | #define MAX_PORT_ID_NUM 2 |
1137 | #define MAX_MCAST_FILTERING_ADDRESSES 256 | ||
1134 | 1138 | ||
1135 | /** | 1139 | /** |
1136 | * struct iwl_mcast_filter_cmd - configure multicast filter. | 1140 | * struct iwl_mcast_filter_cmd - configure multicast filter. |
@@ -1363,4 +1367,65 @@ struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */ | |||
1363 | struct mvm_statistics_general general; | 1367 | struct mvm_statistics_general general; |
1364 | } __packed; | 1368 | } __packed; |
1365 | 1369 | ||
1370 | /*********************************** | ||
1371 | * Smart Fifo API | ||
1372 | ***********************************/ | ||
1373 | /* Smart Fifo state */ | ||
1374 | enum iwl_sf_state { | ||
1375 | SF_LONG_DELAY_ON = 0, /* should never be called by driver */ | ||
1376 | SF_FULL_ON, | ||
1377 | SF_UNINIT, | ||
1378 | SF_INIT_OFF, | ||
1379 | SF_HW_NUM_STATES | ||
1380 | }; | ||
1381 | |||
1382 | /* Smart Fifo possible scenario */ | ||
1383 | enum iwl_sf_scenario { | ||
1384 | SF_SCENARIO_SINGLE_UNICAST, | ||
1385 | SF_SCENARIO_AGG_UNICAST, | ||
1386 | SF_SCENARIO_MULTICAST, | ||
1387 | SF_SCENARIO_BA_RESP, | ||
1388 | SF_SCENARIO_TX_RESP, | ||
1389 | SF_NUM_SCENARIO | ||
1390 | }; | ||
1391 | |||
1392 | #define SF_TRANSIENT_STATES_NUMBER 2 /* SF_LONG_DELAY_ON and SF_FULL_ON */ | ||
1393 | #define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */ | ||
1394 | |||
1395 | /* smart FIFO default values */ | ||
1396 | #define SF_W_MARK_SISO 4096 | ||
1397 | #define SF_W_MARK_MIMO2 8192 | ||
1398 | #define SF_W_MARK_MIMO3 6144 | ||
1399 | #define SF_W_MARK_LEGACY 4096 | ||
1400 | #define SF_W_MARK_SCAN 4096 | ||
1401 | |||
1402 | /* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */ | ||
1403 | #define SF_SINGLE_UNICAST_IDLE_TIMER 320 /* 300 uSec */ | ||
1404 | #define SF_SINGLE_UNICAST_AGING_TIMER 2016 /* 2 mSec */ | ||
1405 | #define SF_AGG_UNICAST_IDLE_TIMER 320 /* 300 uSec */ | ||
1406 | #define SF_AGG_UNICAST_AGING_TIMER 2016 /* 2 mSec */ | ||
1407 | #define SF_MCAST_IDLE_TIMER 2016 /* 2 mSec */ | ||
1408 | #define SF_MCAST_AGING_TIMER 10016 /* 10 mSec */ | ||
1409 | #define SF_BA_IDLE_TIMER 320 /* 300 uSec */ | ||
1410 | #define SF_BA_AGING_TIMER 2016 /* 2 mSec */ | ||
1411 | #define SF_TX_RE_IDLE_TIMER 320 /* 300 uSec */ | ||
1412 | #define SF_TX_RE_AGING_TIMER 2016 /* 2 mSec */ | ||
1413 | |||
1414 | #define SF_LONG_DELAY_AGING_TIMER 1000000 /* 1 Sec */ | ||
1415 | |||
1416 | /** | ||
1417 | * Smart Fifo configuration command. | ||
1418 | * @state: smart fifo state, types listed in iwl_sf_sate. | ||
1419 | * @watermark: Minimum allowed availabe free space in RXF for transient state. | ||
1420 | * @long_delay_timeouts: aging and idle timer values for each scenario | ||
1421 | * in long delay state. | ||
1422 | * @full_on_timeouts: timer values for each scenario in full on state. | ||
1423 | */ | ||
1424 | struct iwl_sf_cfg_cmd { | ||
1425 | enum iwl_sf_state state; | ||
1426 | __le32 watermark[SF_TRANSIENT_STATES_NUMBER]; | ||
1427 | __le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; | ||
1428 | __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; | ||
1429 | } __packed; /* SF_CFG_API_S_VER_2 */ | ||
1430 | |||
1366 | #endif /* __fw_api_h__ */ | 1431 | #endif /* __fw_api_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 70e5297646b2..27ba104a3540 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -241,7 +241,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
241 | 241 | ||
242 | lockdep_assert_held(&mvm->mutex); | 242 | lockdep_assert_held(&mvm->mutex); |
243 | 243 | ||
244 | if (mvm->init_ucode_complete) | 244 | if (WARN_ON_ONCE(mvm->init_ucode_complete)) |
245 | return 0; | 245 | return 0; |
246 | 246 | ||
247 | iwl_init_notification_wait(&mvm->notif_wait, | 247 | iwl_init_notification_wait(&mvm->notif_wait, |
@@ -287,7 +287,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
287 | IWL_DEBUG_RF_KILL(mvm, | 287 | IWL_DEBUG_RF_KILL(mvm, |
288 | "jump over all phy activities due to RF kill\n"); | 288 | "jump over all phy activities due to RF kill\n"); |
289 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); | 289 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); |
290 | return 1; | 290 | ret = 1; |
291 | goto out; | ||
291 | } | 292 | } |
292 | 293 | ||
293 | /* Send TX valid antennas before triggering calibrations */ | 294 | /* Send TX valid antennas before triggering calibrations */ |
@@ -319,9 +320,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
319 | error: | 320 | error: |
320 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); | 321 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); |
321 | out: | 322 | out: |
322 | if (!iwlmvm_mod_params.init_dbg) { | 323 | if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) { |
323 | iwl_trans_stop_device(mvm->trans); | ||
324 | } else if (!mvm->nvm_data) { | ||
325 | /* we want to debug INIT and we have no NVM - fake */ | 324 | /* we want to debug INIT and we have no NVM - fake */ |
326 | mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) + | 325 | mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) + |
327 | sizeof(struct ieee80211_channel) + | 326 | sizeof(struct ieee80211_channel) + |
@@ -370,11 +369,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
370 | ret = -ERFKILL; | 369 | ret = -ERFKILL; |
371 | goto error; | 370 | goto error; |
372 | } | 371 | } |
373 | /* should stop & start HW since that INIT image just loaded */ | 372 | if (!iwlmvm_mod_params.init_dbg) { |
374 | iwl_trans_stop_hw(mvm->trans, false); | 373 | /* |
375 | ret = iwl_trans_start_hw(mvm->trans); | 374 | * should stop and start HW since that INIT |
376 | if (ret) | 375 | * image just loaded |
377 | return ret; | 376 | */ |
377 | iwl_trans_stop_device(mvm->trans); | ||
378 | ret = iwl_trans_start_hw(mvm->trans); | ||
379 | if (ret) | ||
380 | return ret; | ||
381 | } | ||
378 | } | 382 | } |
379 | 383 | ||
380 | if (iwlmvm_mod_params.init_dbg) | 384 | if (iwlmvm_mod_params.init_dbg) |
@@ -386,6 +390,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
386 | goto error; | 390 | goto error; |
387 | } | 391 | } |
388 | 392 | ||
393 | ret = iwl_mvm_sf_update(mvm, NULL, false); | ||
394 | if (ret) | ||
395 | IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); | ||
396 | |||
389 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); | 397 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
390 | if (ret) | 398 | if (ret) |
391 | goto error; | 399 | goto error; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index afc4419be46d..2f5269359dce 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -261,6 +261,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
261 | 261 | ||
262 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 262 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
263 | 263 | ||
264 | /* currently FW API supports only one optional cipher scheme */ | ||
265 | if (mvm->fw->cs && mvm->fw->cs->cipher) { | ||
266 | mvm->hw->n_cipher_schemes = 1; | ||
267 | mvm->hw->cipher_schemes = mvm->fw->cs; | ||
268 | } | ||
269 | |||
264 | #ifdef CONFIG_PM_SLEEP | 270 | #ifdef CONFIG_PM_SLEEP |
265 | if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len && | 271 | if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len && |
266 | mvm->trans->ops->d3_suspend && | 272 | mvm->trans->ops->d3_suspend && |
@@ -399,7 +405,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, | |||
399 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | 405 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) |
400 | { | 406 | { |
401 | iwl_trans_stop_device(mvm->trans); | 407 | iwl_trans_stop_device(mvm->trans); |
402 | iwl_trans_stop_hw(mvm->trans, false); | ||
403 | 408 | ||
404 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 409 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
405 | 410 | ||
@@ -471,7 +476,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) | |||
471 | cancel_work_sync(&mvm->roc_done_wk); | 476 | cancel_work_sync(&mvm->roc_done_wk); |
472 | 477 | ||
473 | iwl_trans_stop_device(mvm->trans); | 478 | iwl_trans_stop_device(mvm->trans); |
474 | iwl_trans_stop_hw(mvm->trans, false); | ||
475 | 479 | ||
476 | iwl_mvm_async_handlers_purge(mvm); | 480 | iwl_mvm_async_handlers_purge(mvm); |
477 | /* async_handlers_list is empty and will stay empty: HW is stopped */ | 481 | /* async_handlers_list is empty and will stay empty: HW is stopped */ |
@@ -488,17 +492,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) | |||
488 | cancel_work_sync(&mvm->async_handlers_wk); | 492 | cancel_work_sync(&mvm->async_handlers_wk); |
489 | } | 493 | } |
490 | 494 | ||
491 | static void iwl_mvm_pm_disable_iterator(void *data, u8 *mac, | ||
492 | struct ieee80211_vif *vif) | ||
493 | { | ||
494 | struct iwl_mvm *mvm = data; | ||
495 | int ret; | ||
496 | |||
497 | ret = iwl_mvm_power_disable(mvm, vif); | ||
498 | if (ret) | ||
499 | IWL_ERR(mvm, "failed to disable power management\n"); | ||
500 | } | ||
501 | |||
502 | static void iwl_mvm_power_update_iterator(void *data, u8 *mac, | 495 | static void iwl_mvm_power_update_iterator(void *data, u8 *mac, |
503 | struct ieee80211_vif *vif) | 496 | struct ieee80211_vif *vif) |
504 | { | 497 | { |
@@ -521,6 +514,20 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) | |||
521 | return NULL; | 514 | return NULL; |
522 | } | 515 | } |
523 | 516 | ||
517 | static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
518 | s8 tx_power) | ||
519 | { | ||
520 | /* FW is in charge of regulatory enforcement */ | ||
521 | struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = { | ||
522 | .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id, | ||
523 | .pwr_restriction = cpu_to_le16(tx_power), | ||
524 | }; | ||
525 | |||
526 | return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC, | ||
527 | sizeof(reduce_txpwr_cmd), | ||
528 | &reduce_txpwr_cmd); | ||
529 | } | ||
530 | |||
524 | static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | 531 | static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, |
525 | struct ieee80211_vif *vif) | 532 | struct ieee80211_vif *vif) |
526 | { | 533 | { |
@@ -541,26 +548,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
541 | if (ret) | 548 | if (ret) |
542 | goto out_unlock; | 549 | goto out_unlock; |
543 | 550 | ||
544 | /* | 551 | /* Counting number of interfaces is needed for legacy PM */ |
545 | * TODO: remove this temporary code. | ||
546 | * Currently MVM FW supports power management only on single MAC. | ||
547 | * If new interface added, disable PM on existing interface. | ||
548 | * P2P device is a special case, since it is handled by FW similary to | ||
549 | * scan. If P2P deviced is added, PM remains enabled on existing | ||
550 | * interface. | ||
551 | * Note: the method below does not count the new interface being added | ||
552 | * at this moment. | ||
553 | */ | ||
554 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) | 552 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) |
555 | mvm->vif_count++; | 553 | mvm->vif_count++; |
556 | if (mvm->vif_count > 1) { | ||
557 | IWL_DEBUG_MAC80211(mvm, | ||
558 | "Disable power on existing interfaces\n"); | ||
559 | ieee80211_iterate_active_interfaces_atomic( | ||
560 | mvm->hw, | ||
561 | IEEE80211_IFACE_ITER_NORMAL, | ||
562 | iwl_mvm_pm_disable_iterator, mvm); | ||
563 | } | ||
564 | 554 | ||
565 | /* | 555 | /* |
566 | * The AP binding flow can be done only after the beacon | 556 | * The AP binding flow can be done only after the beacon |
@@ -591,11 +581,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
591 | if (ret) | 581 | if (ret) |
592 | goto out_release; | 582 | goto out_release; |
593 | 583 | ||
594 | /* | 584 | iwl_mvm_power_disable(mvm, vif); |
595 | * Update power state on the new interface. Admittedly, based on | ||
596 | * mac80211 logics this power update will disable power management | ||
597 | */ | ||
598 | iwl_mvm_power_update_mode(mvm, vif); | ||
599 | 585 | ||
600 | /* beacon filtering */ | 586 | /* beacon filtering */ |
601 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); | 587 | ret = iwl_mvm_disable_beacon_filter(mvm, vif); |
@@ -656,9 +642,12 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
656 | out_release: | 642 | out_release: |
657 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) | 643 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) |
658 | mvm->vif_count--; | 644 | mvm->vif_count--; |
645 | |||
646 | /* TODO: remove this when legacy PM will be discarded */ | ||
659 | ieee80211_iterate_active_interfaces( | 647 | ieee80211_iterate_active_interfaces( |
660 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 648 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
661 | iwl_mvm_power_update_iterator, mvm); | 649 | iwl_mvm_power_update_iterator, mvm); |
650 | |||
662 | iwl_mvm_mac_ctxt_release(mvm, vif); | 651 | iwl_mvm_mac_ctxt_release(mvm, vif); |
663 | out_unlock: | 652 | out_unlock: |
664 | mutex_unlock(&mvm->mutex); | 653 | mutex_unlock(&mvm->mutex); |
@@ -744,21 +733,13 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
744 | mvmvif->phy_ctxt = NULL; | 733 | mvmvif->phy_ctxt = NULL; |
745 | } | 734 | } |
746 | 735 | ||
747 | /* | ||
748 | * TODO: remove this temporary code. | ||
749 | * Currently MVM FW supports power management only on single MAC. | ||
750 | * Check if only one additional interface remains after removing | ||
751 | * current one. Update power mode on the remaining interface. | ||
752 | */ | ||
753 | if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE) | 736 | if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE) |
754 | mvm->vif_count--; | 737 | mvm->vif_count--; |
755 | IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n", | 738 | |
756 | mvm->vif_count); | 739 | /* TODO: remove this when legacy PM will be discarded */ |
757 | if (mvm->vif_count == 1) { | 740 | ieee80211_iterate_active_interfaces( |
758 | ieee80211_iterate_active_interfaces( | 741 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
759 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 742 | iwl_mvm_power_update_iterator, mvm); |
760 | iwl_mvm_power_update_iterator, mvm); | ||
761 | } | ||
762 | 743 | ||
763 | iwl_mvm_mac_ctxt_remove(mvm, vif); | 744 | iwl_mvm_mac_ctxt_remove(mvm, vif); |
764 | 745 | ||
@@ -767,23 +748,91 @@ out_release: | |||
767 | mutex_unlock(&mvm->mutex); | 748 | mutex_unlock(&mvm->mutex); |
768 | } | 749 | } |
769 | 750 | ||
770 | static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 751 | static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed) |
771 | s8 tx_power) | ||
772 | { | 752 | { |
773 | /* FW is in charge of regulatory enforcement */ | 753 | return 0; |
774 | struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = { | 754 | } |
775 | .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id, | 755 | |
776 | .pwr_restriction = cpu_to_le16(tx_power), | 756 | struct iwl_mvm_mc_iter_data { |
757 | struct iwl_mvm *mvm; | ||
758 | int port_id; | ||
759 | }; | ||
760 | |||
761 | static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, | ||
762 | struct ieee80211_vif *vif) | ||
763 | { | ||
764 | struct iwl_mvm_mc_iter_data *data = _data; | ||
765 | struct iwl_mvm *mvm = data->mvm; | ||
766 | struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; | ||
767 | int ret, len; | ||
768 | |||
769 | /* if we don't have free ports, mcast frames will be dropped */ | ||
770 | if (WARN_ON_ONCE(data->port_id >= MAX_PORT_ID_NUM)) | ||
771 | return; | ||
772 | |||
773 | if (vif->type != NL80211_IFTYPE_STATION || | ||
774 | !vif->bss_conf.assoc) | ||
775 | return; | ||
776 | |||
777 | cmd->port_id = data->port_id++; | ||
778 | memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); | ||
779 | len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); | ||
780 | |||
781 | ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, len, cmd); | ||
782 | if (ret) | ||
783 | IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); | ||
784 | } | ||
785 | |||
786 | static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) | ||
787 | { | ||
788 | struct iwl_mvm_mc_iter_data iter_data = { | ||
789 | .mvm = mvm, | ||
777 | }; | 790 | }; |
778 | 791 | ||
779 | return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC, | 792 | lockdep_assert_held(&mvm->mutex); |
780 | sizeof(reduce_txpwr_cmd), | 793 | |
781 | &reduce_txpwr_cmd); | 794 | if (WARN_ON_ONCE(!mvm->mcast_filter_cmd)) |
795 | return; | ||
796 | |||
797 | ieee80211_iterate_active_interfaces( | ||
798 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
799 | iwl_mvm_mc_iface_iterator, &iter_data); | ||
782 | } | 800 | } |
783 | 801 | ||
784 | static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed) | 802 | static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw, |
803 | struct netdev_hw_addr_list *mc_list) | ||
785 | { | 804 | { |
786 | return 0; | 805 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
806 | struct iwl_mcast_filter_cmd *cmd; | ||
807 | struct netdev_hw_addr *addr; | ||
808 | int addr_count = netdev_hw_addr_list_count(mc_list); | ||
809 | bool pass_all = false; | ||
810 | int len; | ||
811 | |||
812 | if (addr_count > MAX_MCAST_FILTERING_ADDRESSES) { | ||
813 | pass_all = true; | ||
814 | addr_count = 0; | ||
815 | } | ||
816 | |||
817 | len = roundup(sizeof(*cmd) + addr_count * ETH_ALEN, 4); | ||
818 | cmd = kzalloc(len, GFP_ATOMIC); | ||
819 | if (!cmd) | ||
820 | return 0; | ||
821 | |||
822 | if (pass_all) { | ||
823 | cmd->pass_all = 1; | ||
824 | return (u64)(unsigned long)cmd; | ||
825 | } | ||
826 | |||
827 | netdev_hw_addr_list_for_each(addr, mc_list) { | ||
828 | IWL_DEBUG_MAC80211(mvm, "mcast addr (%d): %pM\n", | ||
829 | cmd->count, addr->addr); | ||
830 | memcpy(&cmd->addr_list[cmd->count * ETH_ALEN], | ||
831 | addr->addr, ETH_ALEN); | ||
832 | cmd->count++; | ||
833 | } | ||
834 | |||
835 | return (u64)(unsigned long)cmd; | ||
787 | } | 836 | } |
788 | 837 | ||
789 | static void iwl_mvm_configure_filter(struct ieee80211_hw *hw, | 838 | static void iwl_mvm_configure_filter(struct ieee80211_hw *hw, |
@@ -791,21 +840,22 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw, | |||
791 | unsigned int *total_flags, | 840 | unsigned int *total_flags, |
792 | u64 multicast) | 841 | u64 multicast) |
793 | { | 842 | { |
794 | *total_flags = 0; | 843 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
795 | } | 844 | struct iwl_mcast_filter_cmd *cmd = (void *)(unsigned long)multicast; |
796 | 845 | ||
797 | static int iwl_mvm_configure_mcast_filter(struct iwl_mvm *mvm, | 846 | mutex_lock(&mvm->mutex); |
798 | struct ieee80211_vif *vif) | 847 | |
799 | { | 848 | /* replace previous configuration */ |
800 | struct iwl_mcast_filter_cmd mcast_filter_cmd = { | 849 | kfree(mvm->mcast_filter_cmd); |
801 | .pass_all = 1, | 850 | mvm->mcast_filter_cmd = cmd; |
802 | }; | ||
803 | 851 | ||
804 | memcpy(mcast_filter_cmd.bssid, vif->bss_conf.bssid, ETH_ALEN); | 852 | if (!cmd) |
853 | goto out; | ||
805 | 854 | ||
806 | return iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, | 855 | iwl_mvm_recalc_multicast(mvm); |
807 | sizeof(mcast_filter_cmd), | 856 | out: |
808 | &mcast_filter_cmd); | 857 | mutex_unlock(&mvm->mutex); |
858 | *total_flags = 0; | ||
809 | } | 859 | } |
810 | 860 | ||
811 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | 861 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, |
@@ -828,7 +878,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
828 | IWL_ERR(mvm, "failed to update quotas\n"); | 878 | IWL_ERR(mvm, "failed to update quotas\n"); |
829 | return; | 879 | return; |
830 | } | 880 | } |
831 | iwl_mvm_configure_mcast_filter(mvm, vif); | ||
832 | 881 | ||
833 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, | 882 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, |
834 | &mvm->status)) { | 883 | &mvm->status)) { |
@@ -850,7 +899,17 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
850 | iwl_mvm_protect_session(mvm, vif, dur, dur, | 899 | iwl_mvm_protect_session(mvm, vif, dur, dur, |
851 | 5 * dur); | 900 | 5 * dur); |
852 | } | 901 | } |
902 | |||
903 | iwl_mvm_sf_update(mvm, vif, false); | ||
904 | iwl_mvm_power_vif_assoc(mvm, vif); | ||
853 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | 905 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { |
906 | /* | ||
907 | * If update fails - SF might be running in associated | ||
908 | * mode while disassociated - which is forbidden. | ||
909 | */ | ||
910 | WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false), | ||
911 | "Failed to update SF upon disassociation\n"); | ||
912 | |||
854 | /* remove AP station now that the MAC is unassoc */ | 913 | /* remove AP station now that the MAC is unassoc */ |
855 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); | 914 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); |
856 | if (ret) | 915 | if (ret) |
@@ -862,6 +921,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
862 | IWL_ERR(mvm, "failed to update quotas\n"); | 921 | IWL_ERR(mvm, "failed to update quotas\n"); |
863 | } | 922 | } |
864 | 923 | ||
924 | iwl_mvm_recalc_multicast(mvm); | ||
925 | |||
865 | /* reset rssi values */ | 926 | /* reset rssi values */ |
866 | mvmvif->bf_data.ave_beacon_signal = 0; | 927 | mvmvif->bf_data.ave_beacon_signal = 0; |
867 | 928 | ||
@@ -882,7 +943,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
882 | */ | 943 | */ |
883 | iwl_mvm_remove_time_event(mvm, mvmvif, | 944 | iwl_mvm_remove_time_event(mvm, mvmvif, |
884 | &mvmvif->time_event_data); | 945 | &mvmvif->time_event_data); |
885 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_QOS)) { | 946 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | |
947 | BSS_CHANGED_QOS)) { | ||
886 | ret = iwl_mvm_power_update_mode(mvm, vif); | 948 | ret = iwl_mvm_power_update_mode(mvm, vif); |
887 | if (ret) | 949 | if (ret) |
888 | IWL_ERR(mvm, "failed to update power mode\n"); | 950 | IWL_ERR(mvm, "failed to update power mode\n"); |
@@ -991,11 +1053,16 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, | |||
991 | struct ieee80211_bss_conf *bss_conf, | 1053 | struct ieee80211_bss_conf *bss_conf, |
992 | u32 changes) | 1054 | u32 changes) |
993 | { | 1055 | { |
1056 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
994 | enum ieee80211_bss_change ht_change = BSS_CHANGED_ERP_CTS_PROT | | 1057 | enum ieee80211_bss_change ht_change = BSS_CHANGED_ERP_CTS_PROT | |
995 | BSS_CHANGED_HT | | 1058 | BSS_CHANGED_HT | |
996 | BSS_CHANGED_BANDWIDTH; | 1059 | BSS_CHANGED_BANDWIDTH; |
997 | int ret; | 1060 | int ret; |
998 | 1061 | ||
1062 | /* Changes will be applied when the AP/IBSS is started */ | ||
1063 | if (!mvmvif->ap_ibss_active) | ||
1064 | return; | ||
1065 | |||
999 | if (changes & ht_change) { | 1066 | if (changes & ht_change) { |
1000 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif); | 1067 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif); |
1001 | if (ret) | 1068 | if (ret) |
@@ -1114,6 +1181,28 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
1114 | } | 1181 | } |
1115 | } | 1182 | } |
1116 | 1183 | ||
1184 | static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, | ||
1185 | struct ieee80211_vif *vif, | ||
1186 | struct ieee80211_sta *sta) | ||
1187 | { | ||
1188 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
1189 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | ||
1190 | |||
1191 | /* | ||
1192 | * This is called before mac80211 does RCU synchronisation, | ||
1193 | * so here we already invalidate our internal RCU-protected | ||
1194 | * station pointer. The rest of the code will thus no longer | ||
1195 | * be able to find the station this way, and we don't rely | ||
1196 | * on further RCU synchronisation after the sta_state() | ||
1197 | * callback deleted the station. | ||
1198 | */ | ||
1199 | mutex_lock(&mvm->mutex); | ||
1200 | if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id])) | ||
1201 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], | ||
1202 | ERR_PTR(-ENOENT)); | ||
1203 | mutex_unlock(&mvm->mutex); | ||
1204 | } | ||
1205 | |||
1117 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | 1206 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, |
1118 | struct ieee80211_vif *vif, | 1207 | struct ieee80211_vif *vif, |
1119 | struct ieee80211_sta *sta, | 1208 | struct ieee80211_sta *sta, |
@@ -1200,6 +1289,17 @@ static int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
1200 | return 0; | 1289 | return 0; |
1201 | } | 1290 | } |
1202 | 1291 | ||
1292 | static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, | ||
1293 | struct ieee80211_vif *vif, | ||
1294 | struct ieee80211_sta *sta, u32 changed) | ||
1295 | { | ||
1296 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
1297 | |||
1298 | if (vif->type == NL80211_IFTYPE_STATION && | ||
1299 | changed & IEEE80211_RC_NSS_CHANGED) | ||
1300 | iwl_mvm_sf_update(mvm, vif, false); | ||
1301 | } | ||
1302 | |||
1203 | static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw, | 1303 | static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw, |
1204 | struct ieee80211_vif *vif, u16 ac, | 1304 | struct ieee80211_vif *vif, u16 ac, |
1205 | const struct ieee80211_tx_queue_params *params) | 1305 | const struct ieee80211_tx_queue_params *params) |
@@ -1322,7 +1422,12 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | |||
1322 | */ | 1422 | */ |
1323 | return 0; | 1423 | return 0; |
1324 | default: | 1424 | default: |
1325 | return -EOPNOTSUPP; | 1425 | /* currently FW supports only one optional cipher scheme */ |
1426 | if (hw->n_cipher_schemes && | ||
1427 | hw->cipher_schemes->cipher == key->cipher) | ||
1428 | key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; | ||
1429 | else | ||
1430 | return -EOPNOTSUPP; | ||
1326 | } | 1431 | } |
1327 | 1432 | ||
1328 | mutex_lock(&mvm->mutex); | 1433 | mutex_lock(&mvm->mutex); |
@@ -1528,7 +1633,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, | |||
1528 | goto out; | 1633 | goto out; |
1529 | } | 1634 | } |
1530 | 1635 | ||
1531 | ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, | 1636 | ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, |
1532 | ctx->rx_chains_static, | 1637 | ctx->rx_chains_static, |
1533 | ctx->rx_chains_dynamic); | 1638 | ctx->rx_chains_dynamic); |
1534 | if (ret) { | 1639 | if (ret) { |
@@ -1572,7 +1677,7 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
1572 | return; | 1677 | return; |
1573 | 1678 | ||
1574 | mutex_lock(&mvm->mutex); | 1679 | mutex_lock(&mvm->mutex); |
1575 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, | 1680 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, |
1576 | ctx->rx_chains_static, | 1681 | ctx->rx_chains_static, |
1577 | ctx->rx_chains_dynamic); | 1682 | ctx->rx_chains_dynamic); |
1578 | iwl_mvm_bt_coex_vif_change(mvm); | 1683 | iwl_mvm_bt_coex_vif_change(mvm); |
@@ -1615,7 +1720,13 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
1615 | goto out_unlock; | 1720 | goto out_unlock; |
1616 | 1721 | ||
1617 | /* | 1722 | /* |
1618 | * Setting the quota at this stage is only required for monitor | 1723 | * Power state must be updated before quotas, |
1724 | * otherwise fw will complain. | ||
1725 | */ | ||
1726 | mvm->bound_vif_cnt++; | ||
1727 | iwl_mvm_power_update_binding(mvm, vif, true); | ||
1728 | |||
1729 | /* Setting the quota at this stage is only required for monitor | ||
1619 | * interfaces. For the other types, the bss_info changed flow | 1730 | * interfaces. For the other types, the bss_info changed flow |
1620 | * will handle quota settings. | 1731 | * will handle quota settings. |
1621 | */ | 1732 | */ |
@@ -1630,6 +1741,8 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
1630 | 1741 | ||
1631 | out_remove_binding: | 1742 | out_remove_binding: |
1632 | iwl_mvm_binding_remove_vif(mvm, vif); | 1743 | iwl_mvm_binding_remove_vif(mvm, vif); |
1744 | mvm->bound_vif_cnt--; | ||
1745 | iwl_mvm_power_update_binding(mvm, vif, false); | ||
1633 | out_unlock: | 1746 | out_unlock: |
1634 | mutex_unlock(&mvm->mutex); | 1747 | mutex_unlock(&mvm->mutex); |
1635 | if (ret) | 1748 | if (ret) |
@@ -1663,6 +1776,9 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1663 | iwl_mvm_binding_remove_vif(mvm, vif); | 1776 | iwl_mvm_binding_remove_vif(mvm, vif); |
1664 | out_unlock: | 1777 | out_unlock: |
1665 | mvmvif->phy_ctxt = NULL; | 1778 | mvmvif->phy_ctxt = NULL; |
1779 | mvm->bound_vif_cnt--; | ||
1780 | iwl_mvm_power_update_binding(mvm, vif, false); | ||
1781 | |||
1666 | mutex_unlock(&mvm->mutex); | 1782 | mutex_unlock(&mvm->mutex); |
1667 | } | 1783 | } |
1668 | 1784 | ||
@@ -1757,14 +1873,17 @@ struct ieee80211_ops iwl_mvm_hw_ops = { | |||
1757 | .add_interface = iwl_mvm_mac_add_interface, | 1873 | .add_interface = iwl_mvm_mac_add_interface, |
1758 | .remove_interface = iwl_mvm_mac_remove_interface, | 1874 | .remove_interface = iwl_mvm_mac_remove_interface, |
1759 | .config = iwl_mvm_mac_config, | 1875 | .config = iwl_mvm_mac_config, |
1876 | .prepare_multicast = iwl_mvm_prepare_multicast, | ||
1760 | .configure_filter = iwl_mvm_configure_filter, | 1877 | .configure_filter = iwl_mvm_configure_filter, |
1761 | .bss_info_changed = iwl_mvm_bss_info_changed, | 1878 | .bss_info_changed = iwl_mvm_bss_info_changed, |
1762 | .hw_scan = iwl_mvm_mac_hw_scan, | 1879 | .hw_scan = iwl_mvm_mac_hw_scan, |
1763 | .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, | 1880 | .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, |
1881 | .sta_pre_rcu_remove = iwl_mvm_sta_pre_rcu_remove, | ||
1764 | .sta_state = iwl_mvm_mac_sta_state, | 1882 | .sta_state = iwl_mvm_mac_sta_state, |
1765 | .sta_notify = iwl_mvm_mac_sta_notify, | 1883 | .sta_notify = iwl_mvm_mac_sta_notify, |
1766 | .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames, | 1884 | .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames, |
1767 | .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, | 1885 | .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, |
1886 | .sta_rc_update = iwl_mvm_sta_rc_update, | ||
1768 | .conf_tx = iwl_mvm_mac_conf_tx, | 1887 | .conf_tx = iwl_mvm_mac_conf_tx, |
1769 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, | 1888 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, |
1770 | .sched_scan_start = iwl_mvm_mac_sched_scan_start, | 1889 | .sched_scan_start = iwl_mvm_mac_sched_scan_start, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 7dc57cfe5803..84edf3649ad2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -163,6 +163,8 @@ struct iwl_mvm_power_ops { | |||
163 | struct ieee80211_vif *vif); | 163 | struct ieee80211_vif *vif); |
164 | int (*power_update_device_mode)(struct iwl_mvm *mvm); | 164 | int (*power_update_device_mode)(struct iwl_mvm *mvm); |
165 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 165 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
166 | void (*power_update_binding)(struct iwl_mvm *mvm, | ||
167 | struct ieee80211_vif *vif, bool assign); | ||
166 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 168 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
167 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 169 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
168 | char *buf, int bufsz); | 170 | char *buf, int bufsz); |
@@ -181,6 +183,7 @@ enum iwl_dbgfs_pm_mask { | |||
181 | MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), | 183 | MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), |
182 | MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), | 184 | MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), |
183 | MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8), | 185 | MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8), |
186 | MVM_DEBUGFS_PM_UAPSD_MISBEHAVING = BIT(9), | ||
184 | }; | 187 | }; |
185 | 188 | ||
186 | struct iwl_dbgfs_pm { | 189 | struct iwl_dbgfs_pm { |
@@ -193,6 +196,7 @@ struct iwl_dbgfs_pm { | |||
193 | bool lprx_ena; | 196 | bool lprx_ena; |
194 | u32 lprx_rssi_threshold; | 197 | u32 lprx_rssi_threshold; |
195 | bool snooze_ena; | 198 | bool snooze_ena; |
199 | bool uapsd_misbehaving; | ||
196 | int mask; | 200 | int mask; |
197 | }; | 201 | }; |
198 | 202 | ||
@@ -269,8 +273,8 @@ struct iwl_mvm_vif_bf_data { | |||
269 | * @bcast_sta: station used for broadcast packets. Used by the following | 273 | * @bcast_sta: station used for broadcast packets. Used by the following |
270 | * vifs: P2P_DEVICE, GO and AP. | 274 | * vifs: P2P_DEVICE, GO and AP. |
271 | * @beacon_skb: the skb used to hold the AP/GO beacon template | 275 | * @beacon_skb: the skb used to hold the AP/GO beacon template |
272 | * @smps_requests: the requests of of differents parts of the driver, regard | 276 | * @smps_requests: the SMPS requests of differents parts of the driver, |
273 | the desired smps mode. | 277 | * combined on update to yield the overall request to mac80211. |
274 | */ | 278 | */ |
275 | struct iwl_mvm_vif { | 279 | struct iwl_mvm_vif { |
276 | u16 id; | 280 | u16 id; |
@@ -331,6 +335,11 @@ struct iwl_mvm_vif { | |||
331 | #endif | 335 | #endif |
332 | 336 | ||
333 | enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; | 337 | enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; |
338 | |||
339 | /* FW identified misbehaving AP */ | ||
340 | u8 uapsd_misbehaving_bssid[ETH_ALEN]; | ||
341 | |||
342 | bool pm_prevented; | ||
334 | }; | 343 | }; |
335 | 344 | ||
336 | static inline struct iwl_mvm_vif * | 345 | static inline struct iwl_mvm_vif * |
@@ -479,6 +488,7 @@ struct iwl_mvm { | |||
479 | /* Scan status, cmd (pre-allocated) and auxiliary station */ | 488 | /* Scan status, cmd (pre-allocated) and auxiliary station */ |
480 | enum iwl_scan_status scan_status; | 489 | enum iwl_scan_status scan_status; |
481 | struct iwl_scan_cmd *scan_cmd; | 490 | struct iwl_scan_cmd *scan_cmd; |
491 | struct iwl_mcast_filter_cmd *mcast_filter_cmd; | ||
482 | 492 | ||
483 | /* rx chain antennas set through debugfs for the scan command */ | 493 | /* rx chain antennas set through debugfs for the scan command */ |
484 | u8 scan_rx_ant; | 494 | u8 scan_rx_ant; |
@@ -489,6 +499,9 @@ struct iwl_mvm { | |||
489 | u8 scan_last_antenna_idx; /* to toggle TX between antennas */ | 499 | u8 scan_last_antenna_idx; /* to toggle TX between antennas */ |
490 | u8 mgmt_last_antenna_idx; | 500 | u8 mgmt_last_antenna_idx; |
491 | 501 | ||
502 | /* last smart fifo state that was successfully sent to firmware */ | ||
503 | enum iwl_sf_state sf_state; | ||
504 | |||
492 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 505 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
493 | struct dentry *debugfs_dir; | 506 | struct dentry *debugfs_dir; |
494 | u32 dbgfs_sram_offset, dbgfs_sram_len; | 507 | u32 dbgfs_sram_offset, dbgfs_sram_len; |
@@ -512,12 +525,6 @@ struct iwl_mvm { | |||
512 | */ | 525 | */ |
513 | unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; | 526 | unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)]; |
514 | 527 | ||
515 | /* | ||
516 | * This counter of created interfaces is referenced only in conjunction | ||
517 | * with FW limitation related to power management. Currently PM is | ||
518 | * supported only on a single interface. | ||
519 | * IMPORTANT: this variable counts all interfaces except P2P device. | ||
520 | */ | ||
521 | u8 vif_count; | 528 | u8 vif_count; |
522 | 529 | ||
523 | /* -1 for always, 0 for never, >0 for that many times */ | 530 | /* -1 for always, 0 for never, >0 for that many times */ |
@@ -560,6 +567,11 @@ struct iwl_mvm { | |||
560 | u8 aux_queue; | 567 | u8 aux_queue; |
561 | u8 first_agg_queue; | 568 | u8 first_agg_queue; |
562 | u8 last_agg_queue; | 569 | u8 last_agg_queue; |
570 | |||
571 | u8 bound_vif_cnt; | ||
572 | |||
573 | /* Indicate if device power save is allowed */ | ||
574 | bool ps_prevented; | ||
563 | }; | 575 | }; |
564 | 576 | ||
565 | /* Extract MVM priv from op_mode and _hw */ | 577 | /* Extract MVM priv from op_mode and _hw */ |
@@ -778,6 +790,19 @@ static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm) | |||
778 | return 0; | 790 | return 0; |
779 | } | 791 | } |
780 | 792 | ||
793 | static inline void iwl_mvm_power_update_binding(struct iwl_mvm *mvm, | ||
794 | struct ieee80211_vif *vif, | ||
795 | bool assign) | ||
796 | { | ||
797 | if (mvm->pm_ops->power_update_binding) | ||
798 | mvm->pm_ops->power_update_binding(mvm, vif, assign); | ||
799 | } | ||
800 | |||
801 | void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | ||
802 | int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, | ||
803 | struct iwl_rx_cmd_buffer *rxb, | ||
804 | struct iwl_device_cmd *cmd); | ||
805 | |||
781 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 806 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
782 | static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm, | 807 | static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm, |
783 | struct ieee80211_vif *vif, | 808 | struct ieee80211_vif *vif, |
@@ -869,4 +894,8 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm); | |||
869 | void iwl_mvm_tt_exit(struct iwl_mvm *mvm); | 894 | void iwl_mvm_tt_exit(struct iwl_mvm *mvm); |
870 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); | 895 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); |
871 | 896 | ||
897 | /* smart fifo */ | ||
898 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
899 | bool added_vif); | ||
900 | |||
872 | #endif /* __IWL_MVM_H__ */ | 901 | #endif /* __IWL_MVM_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index d86083c6f445..a362430477a0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -236,6 +236,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
236 | false), | 236 | false), |
237 | 237 | ||
238 | RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false), | 238 | RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false), |
239 | RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION, | ||
240 | iwl_mvm_power_uapsd_misbehaving_ap_notif, false), | ||
239 | }; | 241 | }; |
240 | #undef RX_HANDLER | 242 | #undef RX_HANDLER |
241 | #define CMD(x) [x] = #x | 243 | #define CMD(x) [x] = #x |
@@ -311,6 +313,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
311 | CMD(REPLY_THERMAL_MNG_BACKOFF), | 313 | CMD(REPLY_THERMAL_MNG_BACKOFF), |
312 | CMD(MAC_PM_POWER_TABLE), | 314 | CMD(MAC_PM_POWER_TABLE), |
313 | CMD(BT_COEX_CI), | 315 | CMD(BT_COEX_CI), |
316 | CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), | ||
314 | }; | 317 | }; |
315 | #undef CMD | 318 | #undef CMD |
316 | 319 | ||
@@ -341,7 +344,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
341 | 344 | ||
342 | op_mode = hw->priv; | 345 | op_mode = hw->priv; |
343 | op_mode->ops = &iwl_mvm_ops; | 346 | op_mode->ops = &iwl_mvm_ops; |
344 | op_mode->trans = trans; | ||
345 | 347 | ||
346 | mvm = IWL_OP_MODE_GET_MVM(op_mode); | 348 | mvm = IWL_OP_MODE_GET_MVM(op_mode); |
347 | mvm->dev = trans->dev; | 349 | mvm->dev = trans->dev; |
@@ -359,6 +361,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
359 | mvm->aux_queue = 11; | 361 | mvm->aux_queue = 11; |
360 | mvm->first_agg_queue = 12; | 362 | mvm->first_agg_queue = 12; |
361 | } | 363 | } |
364 | mvm->sf_state = SF_UNINIT; | ||
362 | 365 | ||
363 | mutex_init(&mvm->mutex); | 366 | mutex_init(&mvm->mutex); |
364 | spin_lock_init(&mvm->async_handlers_lock); | 367 | spin_lock_init(&mvm->async_handlers_lock); |
@@ -424,7 +427,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
424 | * there is no need to unnecessarily power up the NIC at driver load | 427 | * there is no need to unnecessarily power up the NIC at driver load |
425 | */ | 428 | */ |
426 | if (iwlwifi_mod_params.nvm_file) { | 429 | if (iwlwifi_mod_params.nvm_file) { |
427 | iwl_nvm_init(mvm); | 430 | err = iwl_nvm_init(mvm); |
431 | if (err) | ||
432 | goto out_free; | ||
428 | } else { | 433 | } else { |
429 | err = iwl_trans_start_hw(mvm->trans); | 434 | err = iwl_trans_start_hw(mvm->trans); |
430 | if (err) | 435 | if (err) |
@@ -432,16 +437,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
432 | 437 | ||
433 | mutex_lock(&mvm->mutex); | 438 | mutex_lock(&mvm->mutex); |
434 | err = iwl_run_init_mvm_ucode(mvm, true); | 439 | err = iwl_run_init_mvm_ucode(mvm, true); |
440 | iwl_trans_stop_device(trans); | ||
435 | mutex_unlock(&mvm->mutex); | 441 | mutex_unlock(&mvm->mutex); |
436 | /* returns 0 if successful, 1 if success but in rfkill */ | 442 | /* returns 0 if successful, 1 if success but in rfkill */ |
437 | if (err < 0 && !iwlmvm_mod_params.init_dbg) { | 443 | if (err < 0 && !iwlmvm_mod_params.init_dbg) { |
438 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); | 444 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); |
439 | goto out_free; | 445 | goto out_free; |
440 | } | 446 | } |
441 | |||
442 | /* Stop the hw after the ALIVE and NVM has been read */ | ||
443 | if (!iwlmvm_mod_params.init_dbg) | ||
444 | iwl_trans_stop_hw(mvm->trans, false); | ||
445 | } | 447 | } |
446 | 448 | ||
447 | scan_size = sizeof(struct iwl_scan_cmd) + | 449 | scan_size = sizeof(struct iwl_scan_cmd) + |
@@ -474,7 +476,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
474 | iwl_phy_db_free(mvm->phy_db); | 476 | iwl_phy_db_free(mvm->phy_db); |
475 | kfree(mvm->scan_cmd); | 477 | kfree(mvm->scan_cmd); |
476 | if (!iwlwifi_mod_params.nvm_file) | 478 | if (!iwlwifi_mod_params.nvm_file) |
477 | iwl_trans_stop_hw(trans, true); | 479 | iwl_trans_op_mode_leave(trans); |
478 | ieee80211_free_hw(mvm->hw); | 480 | ieee80211_free_hw(mvm->hw); |
479 | return NULL; | 481 | return NULL; |
480 | } | 482 | } |
@@ -491,12 +493,14 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
491 | ieee80211_unregister_hw(mvm->hw); | 493 | ieee80211_unregister_hw(mvm->hw); |
492 | 494 | ||
493 | kfree(mvm->scan_cmd); | 495 | kfree(mvm->scan_cmd); |
496 | kfree(mvm->mcast_filter_cmd); | ||
497 | mvm->mcast_filter_cmd = NULL; | ||
494 | 498 | ||
495 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) | 499 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) |
496 | kfree(mvm->d3_resume_sram); | 500 | kfree(mvm->d3_resume_sram); |
497 | #endif | 501 | #endif |
498 | 502 | ||
499 | iwl_trans_stop_hw(mvm->trans, true); | 503 | iwl_trans_op_mode_leave(mvm->trans); |
500 | 504 | ||
501 | iwl_phy_db_free(mvm->phy_db); | 505 | iwl_phy_db_free(mvm->phy_db); |
502 | mvm->phy_db = NULL; | 506 | mvm->phy_db = NULL; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 550824aa84ea..483ecc67501f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -186,6 +186,92 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm, | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | 188 | ||
189 | static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, | ||
190 | struct ieee80211_vif *vif, | ||
191 | struct iwl_mac_power_cmd *cmd) | ||
192 | { | ||
193 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
194 | enum ieee80211_ac_numbers ac; | ||
195 | bool tid_found = false; | ||
196 | |||
197 | for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) { | ||
198 | if (!mvmvif->queue_params[ac].uapsd) | ||
199 | continue; | ||
200 | |||
201 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) | ||
202 | cmd->flags |= | ||
203 | cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK); | ||
204 | |||
205 | cmd->uapsd_ac_flags |= BIT(ac); | ||
206 | |||
207 | /* QNDP TID - the highest TID with no admission control */ | ||
208 | if (!tid_found && !mvmvif->queue_params[ac].acm) { | ||
209 | tid_found = true; | ||
210 | switch (ac) { | ||
211 | case IEEE80211_AC_VO: | ||
212 | cmd->qndp_tid = 6; | ||
213 | break; | ||
214 | case IEEE80211_AC_VI: | ||
215 | cmd->qndp_tid = 5; | ||
216 | break; | ||
217 | case IEEE80211_AC_BE: | ||
218 | cmd->qndp_tid = 0; | ||
219 | break; | ||
220 | case IEEE80211_AC_BK: | ||
221 | cmd->qndp_tid = 1; | ||
222 | break; | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | |||
227 | if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) | ||
228 | return; | ||
229 | |||
230 | cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK); | ||
231 | |||
232 | if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) | | ||
233 | BIT(IEEE80211_AC_VI) | | ||
234 | BIT(IEEE80211_AC_BE) | | ||
235 | BIT(IEEE80211_AC_BK))) { | ||
236 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK); | ||
237 | cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL); | ||
238 | cmd->snooze_window = (mvm->cur_ucode == IWL_UCODE_WOWLAN) ? | ||
239 | cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) : | ||
240 | cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW); | ||
241 | } | ||
242 | |||
243 | cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; | ||
244 | |||
245 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags & | ||
246 | cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | ||
247 | cmd->rx_data_timeout_uapsd = | ||
248 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); | ||
249 | cmd->tx_data_timeout_uapsd = | ||
250 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | ||
251 | } else { | ||
252 | cmd->rx_data_timeout_uapsd = | ||
253 | cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); | ||
254 | cmd->tx_data_timeout_uapsd = | ||
255 | cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); | ||
256 | } | ||
257 | |||
258 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | ||
259 | cmd->heavy_tx_thld_packets = | ||
260 | IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS; | ||
261 | cmd->heavy_rx_thld_packets = | ||
262 | IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS; | ||
263 | } else { | ||
264 | cmd->heavy_tx_thld_packets = | ||
265 | IWL_MVM_PS_HEAVY_TX_THLD_PACKETS; | ||
266 | cmd->heavy_rx_thld_packets = | ||
267 | IWL_MVM_PS_HEAVY_RX_THLD_PACKETS; | ||
268 | } | ||
269 | cmd->heavy_tx_thld_percentage = | ||
270 | IWL_MVM_PS_HEAVY_TX_THLD_PERCENT; | ||
271 | cmd->heavy_rx_thld_percentage = | ||
272 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; | ||
273 | } | ||
274 | |||
189 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | 275 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, |
190 | struct ieee80211_vif *vif, | 276 | struct ieee80211_vif *vif, |
191 | struct iwl_mac_power_cmd *cmd) | 277 | struct iwl_mac_power_cmd *cmd) |
@@ -198,8 +284,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
198 | bool radar_detect = false; | 284 | bool radar_detect = false; |
199 | struct iwl_mvm_vif *mvmvif __maybe_unused = | 285 | struct iwl_mvm_vif *mvmvif __maybe_unused = |
200 | iwl_mvm_vif_from_mac80211(vif); | 286 | iwl_mvm_vif_from_mac80211(vif); |
201 | enum ieee80211_ac_numbers ac; | 287 | bool allow_uapsd = true; |
202 | bool tid_found = false; | ||
203 | 288 | ||
204 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | 289 | cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, |
205 | mvmvif->color)); | 290 | mvmvif->color)); |
@@ -217,7 +302,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
217 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); | 302 | keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); |
218 | cmd->keep_alive_seconds = cpu_to_le16(keep_alive); | 303 | cmd->keep_alive_seconds = cpu_to_le16(keep_alive); |
219 | 304 | ||
220 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | 305 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM || |
306 | mvm->ps_prevented) | ||
221 | return; | 307 | return; |
222 | 308 | ||
223 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 309 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
@@ -227,7 +313,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
227 | mvmvif->dbgfs_pm.disable_power_off) | 313 | mvmvif->dbgfs_pm.disable_power_off) |
228 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); | 314 | cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); |
229 | #endif | 315 | #endif |
230 | if (!vif->bss_conf.ps) | 316 | if (!vif->bss_conf.ps || mvmvif->pm_prevented) |
231 | return; | 317 | return; |
232 | 318 | ||
233 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | 319 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); |
@@ -269,81 +355,24 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
269 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | 355 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); |
270 | } | 356 | } |
271 | 357 | ||
272 | for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) { | 358 | if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, |
273 | if (!mvmvif->queue_params[ac].uapsd) | 359 | ETH_ALEN)) |
274 | continue; | 360 | allow_uapsd = false; |
275 | |||
276 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) | ||
277 | cmd->flags |= | ||
278 | cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK); | ||
279 | |||
280 | cmd->uapsd_ac_flags |= BIT(ac); | ||
281 | 361 | ||
282 | /* QNDP TID - the highest TID with no admission control */ | 362 | if (vif->p2p && |
283 | if (!tid_found && !mvmvif->queue_params[ac].acm) { | 363 | !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD)) |
284 | tid_found = true; | 364 | allow_uapsd = false; |
285 | switch (ac) { | 365 | /* |
286 | case IEEE80211_AC_VO: | 366 | * Avoid using uAPSD if P2P client is associated to GO that uses |
287 | cmd->qndp_tid = 6; | 367 | * opportunistic power save. This is due to current FW limitation. |
288 | break; | 368 | */ |
289 | case IEEE80211_AC_VI: | 369 | if (vif->p2p && |
290 | cmd->qndp_tid = 5; | 370 | vif->bss_conf.p2p_noa_attr.oppps_ctwindow & |
291 | break; | 371 | IEEE80211_P2P_OPPPS_ENABLE_BIT) |
292 | case IEEE80211_AC_BE: | 372 | allow_uapsd = false; |
293 | cmd->qndp_tid = 0; | ||
294 | break; | ||
295 | case IEEE80211_AC_BK: | ||
296 | cmd->qndp_tid = 1; | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { | ||
303 | if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) | | ||
304 | BIT(IEEE80211_AC_VI) | | ||
305 | BIT(IEEE80211_AC_BE) | | ||
306 | BIT(IEEE80211_AC_BK))) { | ||
307 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK); | ||
308 | cmd->snooze_interval = | ||
309 | cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL); | ||
310 | cmd->snooze_window = | ||
311 | (mvm->cur_ucode == IWL_UCODE_WOWLAN) ? | ||
312 | cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) : | ||
313 | cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW); | ||
314 | } | ||
315 | |||
316 | cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; | ||
317 | |||
318 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags & | ||
319 | cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | ||
320 | cmd->rx_data_timeout_uapsd = | ||
321 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); | ||
322 | cmd->tx_data_timeout_uapsd = | ||
323 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | ||
324 | } else { | ||
325 | cmd->rx_data_timeout_uapsd = | ||
326 | cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); | ||
327 | cmd->tx_data_timeout_uapsd = | ||
328 | cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); | ||
329 | } | ||
330 | 373 | ||
331 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | 374 | if (allow_uapsd) |
332 | cmd->heavy_tx_thld_packets = | 375 | iwl_mvm_power_configure_uapsd(mvm, vif, cmd); |
333 | IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS; | ||
334 | cmd->heavy_rx_thld_packets = | ||
335 | IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS; | ||
336 | } else { | ||
337 | cmd->heavy_tx_thld_packets = | ||
338 | IWL_MVM_PS_HEAVY_TX_THLD_PACKETS; | ||
339 | cmd->heavy_rx_thld_packets = | ||
340 | IWL_MVM_PS_HEAVY_RX_THLD_PACKETS; | ||
341 | } | ||
342 | cmd->heavy_tx_thld_percentage = | ||
343 | IWL_MVM_PS_HEAVY_TX_THLD_PERCENT; | ||
344 | cmd->heavy_rx_thld_percentage = | ||
345 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; | ||
346 | } | ||
347 | 376 | ||
348 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 377 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
349 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) | 378 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) |
@@ -381,6 +410,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
381 | cmd->flags &= | 410 | cmd->flags &= |
382 | cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK); | 411 | cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK); |
383 | } | 412 | } |
413 | if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) { | ||
414 | u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK; | ||
415 | if (mvmvif->dbgfs_pm.uapsd_misbehaving) | ||
416 | cmd->flags |= cpu_to_le16(flag); | ||
417 | else | ||
418 | cmd->flags &= cpu_to_le16(flag); | ||
419 | } | ||
384 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 420 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
385 | } | 421 | } |
386 | 422 | ||
@@ -391,18 +427,11 @@ static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm, | |||
391 | bool ba_enable; | 427 | bool ba_enable; |
392 | struct iwl_mac_power_cmd cmd = {}; | 428 | struct iwl_mac_power_cmd cmd = {}; |
393 | 429 | ||
394 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 430 | if (vif->type != NL80211_IFTYPE_STATION) |
395 | return 0; | 431 | return 0; |
396 | 432 | ||
397 | /* | 433 | if (vif->p2p && |
398 | * TODO: The following vif_count verification is temporary condition. | 434 | !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)) |
399 | * Avoid power mode update if more than one interface is currently | ||
400 | * active. Remove this condition when FW will support power management | ||
401 | * on multiple MACs. | ||
402 | */ | ||
403 | IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n", | ||
404 | mvm->vif_count); | ||
405 | if (mvm->vif_count > 1) | ||
406 | return 0; | 435 | return 0; |
407 | 436 | ||
408 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 437 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
@@ -446,7 +475,7 @@ static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, | |||
446 | sizeof(cmd), &cmd); | 475 | sizeof(cmd), &cmd); |
447 | } | 476 | } |
448 | 477 | ||
449 | static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | 478 | static int _iwl_mvm_power_update_device(struct iwl_mvm *mvm, bool force_disable) |
450 | { | 479 | { |
451 | struct iwl_device_power_cmd cmd = { | 480 | struct iwl_device_power_cmd cmd = { |
452 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), | 481 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), |
@@ -455,7 +484,8 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | |||
455 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) | 484 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) |
456 | return 0; | 485 | return 0; |
457 | 486 | ||
458 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | 487 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM || |
488 | force_disable) | ||
459 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); | 489 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); |
460 | 490 | ||
461 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 491 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -472,6 +502,78 @@ static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | |||
472 | &cmd); | 502 | &cmd); |
473 | } | 503 | } |
474 | 504 | ||
505 | static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | ||
506 | { | ||
507 | return _iwl_mvm_power_update_device(mvm, false); | ||
508 | } | ||
509 | |||
510 | void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
511 | { | ||
512 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
513 | |||
514 | if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid, | ||
515 | ETH_ALEN)) | ||
516 | memset(mvmvif->uapsd_misbehaving_bssid, 0, ETH_ALEN); | ||
517 | } | ||
518 | |||
519 | static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac, | ||
520 | struct ieee80211_vif *vif) | ||
521 | { | ||
522 | u8 *ap_sta_id = _data; | ||
523 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
524 | |||
525 | /* The ap_sta_id is not expected to change during current association | ||
526 | * so no explicit protection is needed | ||
527 | */ | ||
528 | if (mvmvif->ap_sta_id == *ap_sta_id) | ||
529 | memcpy(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, | ||
530 | ETH_ALEN); | ||
531 | } | ||
532 | |||
533 | int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, | ||
534 | struct iwl_rx_cmd_buffer *rxb, | ||
535 | struct iwl_device_cmd *cmd) | ||
536 | { | ||
537 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
538 | struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data; | ||
539 | u8 ap_sta_id = le32_to_cpu(notif->sta_id); | ||
540 | |||
541 | ieee80211_iterate_active_interfaces_atomic( | ||
542 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
543 | iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id); | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static void iwl_mvm_power_binding_iterator(void *_data, u8 *mac, | ||
549 | struct ieee80211_vif *vif) | ||
550 | { | ||
551 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
552 | struct iwl_mvm *mvm = _data; | ||
553 | int ret; | ||
554 | |||
555 | mvmvif->pm_prevented = (mvm->bound_vif_cnt <= 1) ? false : true; | ||
556 | |||
557 | ret = iwl_mvm_power_mac_update_mode(mvm, vif); | ||
558 | WARN_ONCE(ret, "Failed to update power parameters on a specific vif\n"); | ||
559 | } | ||
560 | |||
561 | static void _iwl_mvm_power_update_binding(struct iwl_mvm *mvm, | ||
562 | struct ieee80211_vif *vif, | ||
563 | bool assign) | ||
564 | { | ||
565 | if (vif->type == NL80211_IFTYPE_MONITOR) { | ||
566 | int ret = _iwl_mvm_power_update_device(mvm, assign); | ||
567 | mvm->ps_prevented = assign; | ||
568 | WARN_ONCE(ret, "Failed to update power device state\n"); | ||
569 | } | ||
570 | |||
571 | ieee80211_iterate_active_interfaces(mvm->hw, | ||
572 | IEEE80211_IFACE_ITER_NORMAL, | ||
573 | iwl_mvm_power_binding_iterator, | ||
574 | mvm); | ||
575 | } | ||
576 | |||
475 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 577 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
476 | static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | 578 | static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, |
477 | struct ieee80211_vif *vif, char *buf, | 579 | struct ieee80211_vif *vif, char *buf, |
@@ -494,70 +596,58 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | |||
494 | pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", | 596 | pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", |
495 | le16_to_cpu(cmd.keep_alive_seconds)); | 597 | le16_to_cpu(cmd.keep_alive_seconds)); |
496 | 598 | ||
497 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { | 599 | if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) |
498 | pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n", | 600 | return pos; |
499 | (cmd.flags & | 601 | |
500 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? | 602 | pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n", |
501 | 1 : 0); | 603 | (cmd.flags & |
502 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", | 604 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0); |
503 | cmd.skip_dtim_periods); | 605 | pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", |
504 | if (!(cmd.flags & | 606 | cmd.skip_dtim_periods); |
505 | cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) { | 607 | if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) { |
506 | pos += scnprintf(buf+pos, bufsz-pos, | 608 | pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n", |
507 | "rx_data_timeout = %d\n", | 609 | le32_to_cpu(cmd.rx_data_timeout)); |
508 | le32_to_cpu(cmd.rx_data_timeout)); | 610 | pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", |
509 | pos += scnprintf(buf+pos, bufsz-pos, | 611 | le32_to_cpu(cmd.tx_data_timeout)); |
510 | "tx_data_timeout = %d\n", | ||
511 | le32_to_cpu(cmd.tx_data_timeout)); | ||
512 | } | ||
513 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | ||
514 | pos += scnprintf(buf+pos, bufsz-pos, | ||
515 | "lprx_rssi_threshold = %d\n", | ||
516 | cmd.lprx_rssi_threshold); | ||
517 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { | ||
518 | pos += | ||
519 | scnprintf(buf+pos, bufsz-pos, | ||
520 | "rx_data_timeout_uapsd = %d\n", | ||
521 | le32_to_cpu(cmd.rx_data_timeout_uapsd)); | ||
522 | pos += | ||
523 | scnprintf(buf+pos, bufsz-pos, | ||
524 | "tx_data_timeout_uapsd = %d\n", | ||
525 | le32_to_cpu(cmd.tx_data_timeout_uapsd)); | ||
526 | pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", | ||
527 | cmd.qndp_tid); | ||
528 | pos += scnprintf(buf+pos, bufsz-pos, | ||
529 | "uapsd_ac_flags = 0x%x\n", | ||
530 | cmd.uapsd_ac_flags); | ||
531 | pos += scnprintf(buf+pos, bufsz-pos, | ||
532 | "uapsd_max_sp = %d\n", | ||
533 | cmd.uapsd_max_sp); | ||
534 | pos += scnprintf(buf+pos, bufsz-pos, | ||
535 | "heavy_tx_thld_packets = %d\n", | ||
536 | cmd.heavy_tx_thld_packets); | ||
537 | pos += scnprintf(buf+pos, bufsz-pos, | ||
538 | "heavy_rx_thld_packets = %d\n", | ||
539 | cmd.heavy_rx_thld_packets); | ||
540 | pos += scnprintf(buf+pos, bufsz-pos, | ||
541 | "heavy_tx_thld_percentage = %d\n", | ||
542 | cmd.heavy_tx_thld_percentage); | ||
543 | pos += scnprintf(buf+pos, bufsz-pos, | ||
544 | "heavy_rx_thld_percentage = %d\n", | ||
545 | cmd.heavy_rx_thld_percentage); | ||
546 | pos += | ||
547 | scnprintf(buf+pos, bufsz-pos, "snooze_enable = %d\n", | ||
548 | (cmd.flags & | ||
549 | cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) ? | ||
550 | 1 : 0); | ||
551 | } | ||
552 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | ||
553 | pos += scnprintf(buf+pos, bufsz-pos, | ||
554 | "snooze_interval = %d\n", | ||
555 | cmd.snooze_interval); | ||
556 | pos += scnprintf(buf+pos, bufsz-pos, | ||
557 | "snooze_window = %d\n", | ||
558 | cmd.snooze_window); | ||
559 | } | ||
560 | } | 612 | } |
613 | if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) | ||
614 | pos += scnprintf(buf+pos, bufsz-pos, | ||
615 | "lprx_rssi_threshold = %d\n", | ||
616 | cmd.lprx_rssi_threshold); | ||
617 | |||
618 | if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) | ||
619 | return pos; | ||
620 | |||
621 | pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n", | ||
622 | le32_to_cpu(cmd.rx_data_timeout_uapsd)); | ||
623 | pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n", | ||
624 | le32_to_cpu(cmd.tx_data_timeout_uapsd)); | ||
625 | pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid); | ||
626 | pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n", | ||
627 | cmd.uapsd_ac_flags); | ||
628 | pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n", | ||
629 | cmd.uapsd_max_sp); | ||
630 | pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n", | ||
631 | cmd.heavy_tx_thld_packets); | ||
632 | pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n", | ||
633 | cmd.heavy_rx_thld_packets); | ||
634 | pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n", | ||
635 | cmd.heavy_tx_thld_percentage); | ||
636 | pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n", | ||
637 | cmd.heavy_rx_thld_percentage); | ||
638 | pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n", | ||
639 | (cmd.flags & | ||
640 | cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ? | ||
641 | 1 : 0); | ||
642 | |||
643 | if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK))) | ||
644 | return pos; | ||
645 | |||
646 | pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n", | ||
647 | cmd.snooze_interval); | ||
648 | pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n", | ||
649 | cmd.snooze_window); | ||
650 | |||
561 | return pos; | 651 | return pos; |
562 | } | 652 | } |
563 | 653 | ||
@@ -654,6 +744,7 @@ const struct iwl_mvm_power_ops pm_mac_ops = { | |||
654 | .power_update_mode = iwl_mvm_power_mac_update_mode, | 744 | .power_update_mode = iwl_mvm_power_mac_update_mode, |
655 | .power_update_device_mode = iwl_mvm_power_update_device, | 745 | .power_update_device_mode = iwl_mvm_power_update_device, |
656 | .power_disable = iwl_mvm_power_mac_disable, | 746 | .power_disable = iwl_mvm_power_mac_disable, |
747 | .power_update_binding = _iwl_mvm_power_update_binding, | ||
657 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 748 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
658 | .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, | 749 | .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, |
659 | #endif | 750 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index bf6e29f5b4d0..d6d28d7b442b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -42,9 +42,16 @@ | |||
42 | 42 | ||
43 | #define RS_NAME "iwl-mvm-rs" | 43 | #define RS_NAME "iwl-mvm-rs" |
44 | 44 | ||
45 | #define NUM_TRY_BEFORE_ANT_TOGGLE 1 | 45 | #define NUM_TRY_BEFORE_ANT_TOGGLE 1 |
46 | #define IWL_NUMBER_TRY 1 | 46 | #define RS_LEGACY_RETRIES_PER_RATE 1 |
47 | #define IWL_HT_NUMBER_TRY 3 | 47 | #define RS_HT_VHT_RETRIES_PER_RATE 2 |
48 | #define RS_HT_VHT_RETRIES_PER_RATE_TW 1 | ||
49 | #define RS_INITIAL_MIMO_NUM_RATES 3 | ||
50 | #define RS_INITIAL_SISO_NUM_RATES 3 | ||
51 | #define RS_INITIAL_LEGACY_NUM_RATES LINK_QUAL_MAX_RETRY_NUM | ||
52 | #define RS_SECONDARY_LEGACY_NUM_RATES LINK_QUAL_MAX_RETRY_NUM | ||
53 | #define RS_SECONDARY_SISO_NUM_RATES 3 | ||
54 | #define RS_SECONDARY_SISO_RETRIES 1 | ||
48 | 55 | ||
49 | #define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ | 56 | #define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ |
50 | #define IWL_RATE_MIN_FAILURE_TH 3 /* min failures to calc tpt */ | 57 | #define IWL_RATE_MIN_FAILURE_TH 3 /* min failures to calc tpt */ |
@@ -123,6 +130,12 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { | |||
123 | IWL_DECLARE_MCS_RATE(9), /* MCS 9 */ | 130 | IWL_DECLARE_MCS_RATE(9), /* MCS 9 */ |
124 | }; | 131 | }; |
125 | 132 | ||
133 | enum rs_action { | ||
134 | RS_ACTION_STAY = 0, | ||
135 | RS_ACTION_DOWNSCALE = -1, | ||
136 | RS_ACTION_UPSCALE = 1, | ||
137 | }; | ||
138 | |||
126 | enum rs_column_mode { | 139 | enum rs_column_mode { |
127 | RS_INVALID = 0, | 140 | RS_INVALID = 0, |
128 | RS_LEGACY, | 141 | RS_LEGACY, |
@@ -351,20 +364,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
351 | struct sk_buff *skb, | 364 | struct sk_buff *skb, |
352 | struct ieee80211_sta *sta, | 365 | struct ieee80211_sta *sta, |
353 | struct iwl_lq_sta *lq_sta); | 366 | struct iwl_lq_sta *lq_sta); |
354 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, | 367 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, |
355 | struct ieee80211_sta *sta, | 368 | struct ieee80211_sta *sta, |
356 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 369 | struct iwl_lq_sta *lq_sta, |
370 | const struct rs_rate *initial_rate); | ||
357 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); | 371 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); |
358 | 372 | ||
359 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
360 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | ||
361 | u32 *rate_n_flags); | ||
362 | #else | ||
363 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | ||
364 | u32 *rate_n_flags) | ||
365 | {} | ||
366 | #endif | ||
367 | |||
368 | /** | 373 | /** |
369 | * The following tables contain the expected throughput metrics for all rates | 374 | * The following tables contain the expected throughput metrics for all rates |
370 | * | 375 | * |
@@ -504,30 +509,6 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) | |||
504 | return (ant_type & valid_antenna) == ant_type; | 509 | return (ant_type & valid_antenna) == ant_type; |
505 | } | 510 | } |
506 | 511 | ||
507 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
508 | /** | ||
509 | * Program the device to use fixed rate for frame transmit | ||
510 | * This is for debugging/testing only | ||
511 | * once the device start use fixed rate, we need to reload the module | ||
512 | * to being back the normal operation. | ||
513 | */ | ||
514 | static void rs_program_fix_rate(struct iwl_mvm *mvm, | ||
515 | struct iwl_lq_sta *lq_sta) | ||
516 | { | ||
517 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ | ||
518 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | ||
519 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | ||
520 | |||
521 | IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n", | ||
522 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); | ||
523 | |||
524 | if (lq_sta->dbg_fixed_rate) { | ||
525 | rs_fill_link_cmd(NULL, NULL, lq_sta, lq_sta->dbg_fixed_rate); | ||
526 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false); | ||
527 | } | ||
528 | } | ||
529 | #endif | ||
530 | |||
531 | static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, | 512 | static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, |
532 | struct iwl_lq_sta *lq_data, u8 tid, | 513 | struct iwl_lq_sta *lq_data, u8 tid, |
533 | struct ieee80211_sta *sta) | 514 | struct ieee80211_sta *sta) |
@@ -658,7 +639,7 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | |||
658 | 639 | ||
659 | /* Convert rs_rate object into ucode rate bitmask */ | 640 | /* Convert rs_rate object into ucode rate bitmask */ |
660 | static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, | 641 | static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, |
661 | struct rs_rate *rate) | 642 | struct rs_rate *rate) |
662 | { | 643 | { |
663 | u32 ucode_rate = 0; | 644 | u32 ucode_rate = 0; |
664 | int index = rate->index; | 645 | int index = rate->index; |
@@ -785,8 +766,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
785 | 766 | ||
786 | /* switch to another antenna/antennas and return 1 */ | 767 | /* switch to another antenna/antennas and return 1 */ |
787 | /* if no other valid antenna found, return 0 */ | 768 | /* if no other valid antenna found, return 0 */ |
788 | static int rs_toggle_antenna(u32 valid_ant, u32 *ucode_rate, | 769 | static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate) |
789 | struct rs_rate *rate) | ||
790 | { | 770 | { |
791 | u8 new_ant_type; | 771 | u8 new_ant_type; |
792 | 772 | ||
@@ -807,9 +787,6 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *ucode_rate, | |||
807 | 787 | ||
808 | rate->ant = new_ant_type; | 788 | rate->ant = new_ant_type; |
809 | 789 | ||
810 | /* TODO: get rid of ucode_rate here. This should handle only rs_rate */ | ||
811 | *ucode_rate &= ~RATE_MCS_ANT_ABC_MSK; | ||
812 | *ucode_rate |= new_ant_type << RATE_MCS_ANT_POS; | ||
813 | return 1; | 790 | return 1; |
814 | } | 791 | } |
815 | 792 | ||
@@ -883,65 +860,73 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, | |||
883 | return (high << 8) | low; | 860 | return (high << 8) | low; |
884 | } | 861 | } |
885 | 862 | ||
886 | static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | 863 | static inline bool rs_rate_supported(struct iwl_lq_sta *lq_sta, |
887 | struct rs_rate *rate, | 864 | struct rs_rate *rate) |
888 | u8 scale_index, u8 ht_possible) | ||
889 | { | 865 | { |
890 | s32 low; | 866 | return BIT(rate->index) & rs_get_supported_rates(lq_sta, rate); |
891 | u16 rate_mask; | 867 | } |
868 | |||
869 | /* Get the next supported lower rate in the current column. | ||
870 | * Return true if bottom rate in the current column was reached | ||
871 | */ | ||
872 | static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta, | ||
873 | struct rs_rate *rate) | ||
874 | { | ||
875 | u8 low; | ||
892 | u16 high_low; | 876 | u16 high_low; |
893 | u8 switch_to_legacy = 0; | 877 | u16 rate_mask; |
894 | struct iwl_mvm *mvm = lq_sta->drv; | 878 | struct iwl_mvm *mvm = lq_sta->drv; |
895 | 879 | ||
896 | /* check if we need to switch from HT to legacy rates. | 880 | rate_mask = rs_get_supported_rates(lq_sta, rate); |
897 | * assumption is that mandatory rates (1Mbps or 6Mbps) | 881 | high_low = rs_get_adjacent_rate(mvm, rate->index, rate_mask, |
898 | * are always supported (spec demand) */ | 882 | rate->type); |
899 | if (!is_legacy(rate) && (!ht_possible || !scale_index)) { | 883 | low = high_low & 0xff; |
900 | switch_to_legacy = 1; | 884 | |
901 | WARN_ON_ONCE(scale_index < IWL_RATE_MCS_0_INDEX && | 885 | /* Bottom rate of column reached */ |
902 | scale_index > IWL_RATE_MCS_9_INDEX); | 886 | if (low == IWL_RATE_INVALID) |
903 | scale_index = rs_ht_to_legacy[scale_index]; | 887 | return true; |
888 | |||
889 | rate->index = low; | ||
890 | return false; | ||
891 | } | ||
892 | |||
893 | /* Get the next rate to use following a column downgrade */ | ||
894 | static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, | ||
895 | struct rs_rate *rate) | ||
896 | { | ||
897 | struct iwl_mvm *mvm = lq_sta->drv; | ||
898 | |||
899 | if (is_legacy(rate)) { | ||
900 | /* No column to downgrade from Legacy */ | ||
901 | return; | ||
902 | } else if (is_siso(rate)) { | ||
903 | /* Downgrade to Legacy if we were in SISO */ | ||
904 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 904 | if (lq_sta->band == IEEE80211_BAND_5GHZ) |
905 | rate->type = LQ_LEGACY_A; | 905 | rate->type = LQ_LEGACY_A; |
906 | else | 906 | else |
907 | rate->type = LQ_LEGACY_G; | 907 | rate->type = LQ_LEGACY_G; |
908 | 908 | ||
909 | if (num_of_ant(rate->ant) > 1) | ||
910 | rate->ant = | ||
911 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); | ||
912 | |||
913 | rate->bw = RATE_MCS_CHAN_WIDTH_20; | 909 | rate->bw = RATE_MCS_CHAN_WIDTH_20; |
914 | rate->sgi = false; | ||
915 | } | ||
916 | 910 | ||
917 | rate_mask = rs_get_supported_rates(lq_sta, rate); | 911 | WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX && |
912 | rate->index > IWL_RATE_MCS_9_INDEX); | ||
918 | 913 | ||
919 | /* Mask with station rate restriction */ | 914 | rate->index = rs_ht_to_legacy[rate->index]; |
920 | if (is_legacy(rate)) { | 915 | } else { |
921 | /* supp_rates has no CCK bits in A mode */ | 916 | /* Downgrade to SISO with same MCS if in MIMO */ |
922 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 917 | rate->type = is_vht_mimo2(rate) ? |
923 | rate_mask = (u16)(rate_mask & | 918 | LQ_VHT_SISO : LQ_HT_SISO; |
924 | (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); | ||
925 | else | ||
926 | rate_mask = (u16)(rate_mask & lq_sta->supp_rates); | ||
927 | } | 919 | } |
928 | 920 | ||
929 | /* If we switched from HT to legacy, check current rate */ | ||
930 | if (switch_to_legacy && (rate_mask & (1 << scale_index))) { | ||
931 | low = scale_index; | ||
932 | goto out; | ||
933 | } | ||
934 | 921 | ||
935 | high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask, | 922 | if (num_of_ant(rate->ant) > 1) |
936 | rate->type); | 923 | rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); |
937 | low = high_low & 0xff; | ||
938 | 924 | ||
939 | if (low == IWL_RATE_INVALID) | 925 | /* Relevant in both switching to SISO or Legacy */ |
940 | low = scale_index; | 926 | rate->sgi = false; |
941 | 927 | ||
942 | out: | 928 | if (!rs_rate_supported(lq_sta, rate)) |
943 | rate->index = low; | 929 | rs_get_lower_rate_in_column(lq_sta, rate); |
944 | return ucode_rate_from_rs_rate(lq_sta->drv, rate); | ||
945 | } | 930 | } |
946 | 931 | ||
947 | /* Simple function to compare two rate scale table types */ | 932 | /* Simple function to compare two rate scale table types */ |
@@ -1137,14 +1122,9 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
1137 | tmp_tbl = curr_tbl; | 1122 | tmp_tbl = curr_tbl; |
1138 | else if (rs_rate_match(&rate, &other_tbl->rate)) | 1123 | else if (rs_rate_match(&rate, &other_tbl->rate)) |
1139 | tmp_tbl = other_tbl; | 1124 | tmp_tbl = other_tbl; |
1140 | else { | 1125 | else |
1141 | IWL_DEBUG_RATE(mvm, | ||
1142 | "Tx packet rate doesn't match ACTIVE or SEARCH tables\n"); | ||
1143 | rs_dump_rate(mvm, &rate, "Tx PACKET:"); | ||
1144 | rs_dump_rate(mvm, &curr_tbl->rate, "CURRENT:"); | ||
1145 | rs_dump_rate(mvm, &other_tbl->rate, "OTHER:"); | ||
1146 | continue; | 1126 | continue; |
1147 | } | 1127 | |
1148 | rs_collect_tx_data(tmp_tbl, rate.index, 1, | 1128 | rs_collect_tx_data(tmp_tbl, rate.index, 1, |
1149 | i < retries ? 0 : legacy_success); | 1129 | i < retries ? 0 : legacy_success); |
1150 | } | 1130 | } |
@@ -1471,10 +1451,7 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm, | |||
1471 | struct iwl_lq_sta *lq_sta, | 1451 | struct iwl_lq_sta *lq_sta, |
1472 | struct rs_rate *rate) | 1452 | struct rs_rate *rate) |
1473 | { | 1453 | { |
1474 | u32 ucode_rate; | 1454 | rs_fill_lq_cmd(mvm, sta, lq_sta, rate); |
1475 | |||
1476 | ucode_rate = ucode_rate_from_rs_rate(mvm, rate); | ||
1477 | rs_fill_link_cmd(mvm, sta, lq_sta, ucode_rate); | ||
1478 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); | 1455 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); |
1479 | } | 1456 | } |
1480 | 1457 | ||
@@ -1634,10 +1611,6 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, | |||
1634 | rate->index = rate_idx; | 1611 | rate->index = rate_idx; |
1635 | } | 1612 | } |
1636 | 1613 | ||
1637 | /* TODO: remove current_rate and keep using rs_rate all the way until | ||
1638 | * we need to fill in the rs_table in the LQ command | ||
1639 | */ | ||
1640 | search_tbl->current_rate = ucode_rate_from_rs_rate(mvm, rate); | ||
1641 | IWL_DEBUG_RATE(mvm, "Switched to column %d: Index %d\n", | 1614 | IWL_DEBUG_RATE(mvm, "Switched to column %d: Index %d\n", |
1642 | col_id, rate->index); | 1615 | col_id, rate->index); |
1643 | 1616 | ||
@@ -1649,6 +1622,97 @@ err: | |||
1649 | return -1; | 1622 | return -1; |
1650 | } | 1623 | } |
1651 | 1624 | ||
1625 | static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, | ||
1626 | struct iwl_scale_tbl_info *tbl, | ||
1627 | s32 sr, int low, int high, | ||
1628 | int current_tpt, | ||
1629 | int low_tpt, int high_tpt) | ||
1630 | { | ||
1631 | enum rs_action action = RS_ACTION_STAY; | ||
1632 | |||
1633 | /* Too many failures, decrease rate */ | ||
1634 | if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { | ||
1635 | IWL_DEBUG_RATE(mvm, | ||
1636 | "decrease rate because of low SR\n"); | ||
1637 | action = RS_ACTION_DOWNSCALE; | ||
1638 | /* No throughput measured yet for adjacent rates; try increase. */ | ||
1639 | } else if ((low_tpt == IWL_INVALID_VALUE) && | ||
1640 | (high_tpt == IWL_INVALID_VALUE)) { | ||
1641 | if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { | ||
1642 | IWL_DEBUG_RATE(mvm, | ||
1643 | "Good SR and no high rate measurement. " | ||
1644 | "Increase rate\n"); | ||
1645 | action = RS_ACTION_UPSCALE; | ||
1646 | } else if (low != IWL_RATE_INVALID) { | ||
1647 | IWL_DEBUG_RATE(mvm, | ||
1648 | "Remain in current rate\n"); | ||
1649 | action = RS_ACTION_STAY; | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | /* Both adjacent throughputs are measured, but neither one has better | ||
1654 | * throughput; we're using the best rate, don't change it! | ||
1655 | */ | ||
1656 | else if ((low_tpt != IWL_INVALID_VALUE) && | ||
1657 | (high_tpt != IWL_INVALID_VALUE) && | ||
1658 | (low_tpt < current_tpt) && | ||
1659 | (high_tpt < current_tpt)) { | ||
1660 | IWL_DEBUG_RATE(mvm, | ||
1661 | "Both high and low are worse. " | ||
1662 | "Maintain rate\n"); | ||
1663 | action = RS_ACTION_STAY; | ||
1664 | } | ||
1665 | |||
1666 | /* At least one adjacent rate's throughput is measured, | ||
1667 | * and may have better performance. | ||
1668 | */ | ||
1669 | else { | ||
1670 | /* Higher adjacent rate's throughput is measured */ | ||
1671 | if (high_tpt != IWL_INVALID_VALUE) { | ||
1672 | /* Higher rate has better throughput */ | ||
1673 | if (high_tpt > current_tpt && | ||
1674 | sr >= IWL_RATE_INCREASE_TH) { | ||
1675 | IWL_DEBUG_RATE(mvm, | ||
1676 | "Higher rate is better and good " | ||
1677 | "SR. Increate rate\n"); | ||
1678 | action = RS_ACTION_UPSCALE; | ||
1679 | } else { | ||
1680 | IWL_DEBUG_RATE(mvm, | ||
1681 | "Higher rate isn't better OR " | ||
1682 | "no good SR. Maintain rate\n"); | ||
1683 | action = RS_ACTION_STAY; | ||
1684 | } | ||
1685 | |||
1686 | /* Lower adjacent rate's throughput is measured */ | ||
1687 | } else if (low_tpt != IWL_INVALID_VALUE) { | ||
1688 | /* Lower rate has better throughput */ | ||
1689 | if (low_tpt > current_tpt) { | ||
1690 | IWL_DEBUG_RATE(mvm, | ||
1691 | "Lower rate is better. " | ||
1692 | "Decrease rate\n"); | ||
1693 | action = RS_ACTION_DOWNSCALE; | ||
1694 | } else if (sr >= IWL_RATE_INCREASE_TH) { | ||
1695 | IWL_DEBUG_RATE(mvm, | ||
1696 | "Lower rate isn't better and " | ||
1697 | "good SR. Increase rate\n"); | ||
1698 | action = RS_ACTION_UPSCALE; | ||
1699 | } | ||
1700 | } | ||
1701 | } | ||
1702 | |||
1703 | /* Sanity check; asked for decrease, but success rate or throughput | ||
1704 | * has been good at old rate. Don't change it. | ||
1705 | */ | ||
1706 | if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && | ||
1707 | ((sr > IWL_RATE_HIGH_TH) || | ||
1708 | (current_tpt > (100 * tbl->expected_tpt[low])))) { | ||
1709 | IWL_DEBUG_RATE(mvm, | ||
1710 | "Sanity check failed. Maintain rate\n"); | ||
1711 | action = RS_ACTION_STAY; | ||
1712 | } | ||
1713 | |||
1714 | return action; | ||
1715 | } | ||
1652 | 1716 | ||
1653 | /* | 1717 | /* |
1654 | * Do rate scaling and search for new modulation mode. | 1718 | * Do rate scaling and search for new modulation mode. |
@@ -1669,11 +1733,10 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1669 | int low_tpt = IWL_INVALID_VALUE; | 1733 | int low_tpt = IWL_INVALID_VALUE; |
1670 | int high_tpt = IWL_INVALID_VALUE; | 1734 | int high_tpt = IWL_INVALID_VALUE; |
1671 | u32 fail_count; | 1735 | u32 fail_count; |
1672 | s8 scale_action = 0; | 1736 | enum rs_action scale_action = RS_ACTION_STAY; |
1673 | u16 rate_mask; | 1737 | u16 rate_mask; |
1674 | u8 update_lq = 0; | 1738 | u8 update_lq = 0; |
1675 | struct iwl_scale_tbl_info *tbl, *tbl1; | 1739 | struct iwl_scale_tbl_info *tbl, *tbl1; |
1676 | u16 rate_scale_index_msk = 0; | ||
1677 | u8 active_tbl = 0; | 1740 | u8 active_tbl = 0; |
1678 | u8 done_search = 0; | 1741 | u8 done_search = 0; |
1679 | u16 high_low; | 1742 | u16 high_low; |
@@ -1690,8 +1753,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1690 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 1753 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
1691 | return; | 1754 | return; |
1692 | 1755 | ||
1693 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; | ||
1694 | |||
1695 | tid = rs_get_tid(lq_sta, hdr); | 1756 | tid = rs_get_tid(lq_sta, hdr); |
1696 | if ((tid != IWL_MAX_TID_COUNT) && | 1757 | if ((tid != IWL_MAX_TID_COUNT) && |
1697 | (lq_sta->tx_agg_tid_en & (1 << tid))) { | 1758 | (lq_sta->tx_agg_tid_en & (1 << tid))) { |
@@ -1730,33 +1791,13 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1730 | /* rates available for this association, and for modulation mode */ | 1791 | /* rates available for this association, and for modulation mode */ |
1731 | rate_mask = rs_get_supported_rates(lq_sta, rate); | 1792 | rate_mask = rs_get_supported_rates(lq_sta, rate); |
1732 | 1793 | ||
1733 | /* mask with station rate restriction */ | 1794 | if (!(BIT(index) & rate_mask)) { |
1734 | if (is_legacy(rate)) { | ||
1735 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | ||
1736 | /* supp_rates has no CCK bits in A mode */ | ||
1737 | rate_scale_index_msk = (u16) (rate_mask & | ||
1738 | (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); | ||
1739 | else | ||
1740 | rate_scale_index_msk = (u16) (rate_mask & | ||
1741 | lq_sta->supp_rates); | ||
1742 | |||
1743 | } else { | ||
1744 | rate_scale_index_msk = rate_mask; | ||
1745 | } | ||
1746 | |||
1747 | if (!rate_scale_index_msk) | ||
1748 | rate_scale_index_msk = rate_mask; | ||
1749 | |||
1750 | if (!((BIT(index) & rate_scale_index_msk))) { | ||
1751 | IWL_ERR(mvm, "Current Rate is not valid\n"); | 1795 | IWL_ERR(mvm, "Current Rate is not valid\n"); |
1752 | if (lq_sta->search_better_tbl) { | 1796 | if (lq_sta->search_better_tbl) { |
1753 | /* revert to active table if search table is not valid*/ | 1797 | /* revert to active table if search table is not valid*/ |
1754 | rate->type = LQ_NONE; | 1798 | rate->type = LQ_NONE; |
1755 | lq_sta->search_better_tbl = 0; | 1799 | lq_sta->search_better_tbl = 0; |
1756 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1800 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
1757 | /* get "active" rate info */ | ||
1758 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | ||
1759 | tbl->rate.index = index; | ||
1760 | rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate); | 1801 | rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate); |
1761 | } | 1802 | } |
1762 | return; | 1803 | return; |
@@ -1847,7 +1888,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1847 | tbl = &(lq_sta->lq_info[active_tbl]); | 1888 | tbl = &(lq_sta->lq_info[active_tbl]); |
1848 | 1889 | ||
1849 | /* Revert to "active" rate and throughput info */ | 1890 | /* Revert to "active" rate and throughput info */ |
1850 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | 1891 | index = tbl->rate.index; |
1851 | current_tpt = lq_sta->last_tpt; | 1892 | current_tpt = lq_sta->last_tpt; |
1852 | 1893 | ||
1853 | /* Need to set up a new rate table in uCode */ | 1894 | /* Need to set up a new rate table in uCode */ |
@@ -1863,8 +1904,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1863 | 1904 | ||
1864 | /* (Else) not in search of better modulation mode, try for better | 1905 | /* (Else) not in search of better modulation mode, try for better |
1865 | * starting rate, while staying in this mode. */ | 1906 | * starting rate, while staying in this mode. */ |
1866 | high_low = rs_get_adjacent_rate(mvm, index, rate_scale_index_msk, | 1907 | high_low = rs_get_adjacent_rate(mvm, index, rate_mask, rate->type); |
1867 | rate->type); | ||
1868 | low = high_low & 0xff; | 1908 | low = high_low & 0xff; |
1869 | high = (high_low >> 8) & 0xff; | 1909 | high = (high_low >> 8) & 0xff; |
1870 | 1910 | ||
@@ -1887,85 +1927,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1887 | rs_pretty_lq_type(rate->type), index, current_tpt, sr, | 1927 | rs_pretty_lq_type(rate->type), index, current_tpt, sr, |
1888 | low, high, low_tpt, high_tpt); | 1928 | low, high, low_tpt, high_tpt); |
1889 | 1929 | ||
1890 | scale_action = 0; | 1930 | scale_action = rs_get_rate_action(mvm, tbl, sr, low, high, |
1891 | 1931 | current_tpt, low_tpt, high_tpt); | |
1892 | /* Too many failures, decrease rate */ | ||
1893 | if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { | ||
1894 | IWL_DEBUG_RATE(mvm, | ||
1895 | "decrease rate because of low SR\n"); | ||
1896 | scale_action = -1; | ||
1897 | /* No throughput measured yet for adjacent rates; try increase. */ | ||
1898 | } else if ((low_tpt == IWL_INVALID_VALUE) && | ||
1899 | (high_tpt == IWL_INVALID_VALUE)) { | ||
1900 | if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { | ||
1901 | IWL_DEBUG_RATE(mvm, | ||
1902 | "Good SR and no high rate measurement. " | ||
1903 | "Increase rate\n"); | ||
1904 | scale_action = 1; | ||
1905 | } else if (low != IWL_RATE_INVALID) { | ||
1906 | IWL_DEBUG_RATE(mvm, | ||
1907 | "Remain in current rate\n"); | ||
1908 | scale_action = 0; | ||
1909 | } | ||
1910 | } | ||
1911 | |||
1912 | /* Both adjacent throughputs are measured, but neither one has better | ||
1913 | * throughput; we're using the best rate, don't change it! */ | ||
1914 | else if ((low_tpt != IWL_INVALID_VALUE) && | ||
1915 | (high_tpt != IWL_INVALID_VALUE) && | ||
1916 | (low_tpt < current_tpt) && | ||
1917 | (high_tpt < current_tpt)) { | ||
1918 | IWL_DEBUG_RATE(mvm, | ||
1919 | "Both high and low are worse. " | ||
1920 | "Maintain rate\n"); | ||
1921 | scale_action = 0; | ||
1922 | } | ||
1923 | |||
1924 | /* At least one adjacent rate's throughput is measured, | ||
1925 | * and may have better performance. */ | ||
1926 | else { | ||
1927 | /* Higher adjacent rate's throughput is measured */ | ||
1928 | if (high_tpt != IWL_INVALID_VALUE) { | ||
1929 | /* Higher rate has better throughput */ | ||
1930 | if (high_tpt > current_tpt && | ||
1931 | sr >= IWL_RATE_INCREASE_TH) { | ||
1932 | IWL_DEBUG_RATE(mvm, | ||
1933 | "Higher rate is better and good " | ||
1934 | "SR. Increate rate\n"); | ||
1935 | scale_action = 1; | ||
1936 | } else { | ||
1937 | IWL_DEBUG_RATE(mvm, | ||
1938 | "Higher rate isn't better OR " | ||
1939 | "no good SR. Maintain rate\n"); | ||
1940 | scale_action = 0; | ||
1941 | } | ||
1942 | |||
1943 | /* Lower adjacent rate's throughput is measured */ | ||
1944 | } else if (low_tpt != IWL_INVALID_VALUE) { | ||
1945 | /* Lower rate has better throughput */ | ||
1946 | if (low_tpt > current_tpt) { | ||
1947 | IWL_DEBUG_RATE(mvm, | ||
1948 | "Lower rate is better. " | ||
1949 | "Decrease rate\n"); | ||
1950 | scale_action = -1; | ||
1951 | } else if (sr >= IWL_RATE_INCREASE_TH) { | ||
1952 | IWL_DEBUG_RATE(mvm, | ||
1953 | "Lower rate isn't better and " | ||
1954 | "good SR. Increase rate\n"); | ||
1955 | scale_action = 1; | ||
1956 | } | ||
1957 | } | ||
1958 | } | ||
1959 | |||
1960 | /* Sanity check; asked for decrease, but success rate or throughput | ||
1961 | * has been good at old rate. Don't change it. */ | ||
1962 | if ((scale_action == -1) && (low != IWL_RATE_INVALID) && | ||
1963 | ((sr > IWL_RATE_HIGH_TH) || | ||
1964 | (current_tpt > (100 * tbl->expected_tpt[low])))) { | ||
1965 | IWL_DEBUG_RATE(mvm, | ||
1966 | "Sanity check failed. Maintain rate\n"); | ||
1967 | scale_action = 0; | ||
1968 | } | ||
1969 | 1932 | ||
1970 | /* Force a search in case BT doesn't like us being in MIMO */ | 1933 | /* Force a search in case BT doesn't like us being in MIMO */ |
1971 | if (is_mimo(rate) && | 1934 | if (is_mimo(rate) && |
@@ -1977,7 +1940,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1977 | } | 1940 | } |
1978 | 1941 | ||
1979 | switch (scale_action) { | 1942 | switch (scale_action) { |
1980 | case -1: | 1943 | case RS_ACTION_DOWNSCALE: |
1981 | /* Decrease starting rate, update uCode's rate table */ | 1944 | /* Decrease starting rate, update uCode's rate table */ |
1982 | if (low != IWL_RATE_INVALID) { | 1945 | if (low != IWL_RATE_INVALID) { |
1983 | update_lq = 1; | 1946 | update_lq = 1; |
@@ -1988,7 +1951,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1988 | } | 1951 | } |
1989 | 1952 | ||
1990 | break; | 1953 | break; |
1991 | case 1: | 1954 | case RS_ACTION_UPSCALE: |
1992 | /* Increase starting rate, update uCode's rate table */ | 1955 | /* Increase starting rate, update uCode's rate table */ |
1993 | if (high != IWL_RATE_INVALID) { | 1956 | if (high != IWL_RATE_INVALID) { |
1994 | update_lq = 1; | 1957 | update_lq = 1; |
@@ -1999,7 +1962,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
1999 | } | 1962 | } |
2000 | 1963 | ||
2001 | break; | 1964 | break; |
2002 | case 0: | 1965 | case RS_ACTION_STAY: |
2003 | /* No change */ | 1966 | /* No change */ |
2004 | default: | 1967 | default: |
2005 | break; | 1968 | break; |
@@ -2053,11 +2016,11 @@ lq_update: | |||
2053 | rs_rate_scale_clear_window(&(tbl->win[i])); | 2016 | rs_rate_scale_clear_window(&(tbl->win[i])); |
2054 | 2017 | ||
2055 | /* Use new "search" start rate */ | 2018 | /* Use new "search" start rate */ |
2056 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | 2019 | index = tbl->rate.index; |
2057 | 2020 | ||
2058 | rs_dump_rate(mvm, &tbl->rate, | 2021 | rs_dump_rate(mvm, &tbl->rate, |
2059 | "Switch to SEARCH TABLE:"); | 2022 | "Switch to SEARCH TABLE:"); |
2060 | rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate); | 2023 | rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate); |
2061 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); | 2024 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); |
2062 | } else { | 2025 | } else { |
2063 | done_search = 1; | 2026 | done_search = 1; |
@@ -2095,8 +2058,6 @@ lq_update: | |||
2095 | } | 2058 | } |
2096 | 2059 | ||
2097 | out: | 2060 | out: |
2098 | tbl->rate.index = index; | ||
2099 | tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate); | ||
2100 | lq_sta->last_txrate_idx = index; | 2061 | lq_sta->last_txrate_idx = index; |
2101 | } | 2062 | } |
2102 | 2063 | ||
@@ -2123,7 +2084,6 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
2123 | struct iwl_scale_tbl_info *tbl; | 2084 | struct iwl_scale_tbl_info *tbl; |
2124 | struct rs_rate *rate; | 2085 | struct rs_rate *rate; |
2125 | int i; | 2086 | int i; |
2126 | u32 ucode_rate; | ||
2127 | u8 active_tbl = 0; | 2087 | u8 active_tbl = 0; |
2128 | u8 valid_tx_ant; | 2088 | u8 valid_tx_ant; |
2129 | 2089 | ||
@@ -2154,9 +2114,6 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
2154 | else | 2114 | else |
2155 | rate->type = LQ_LEGACY_G; | 2115 | rate->type = LQ_LEGACY_G; |
2156 | 2116 | ||
2157 | ucode_rate = ucode_rate_from_rs_rate(mvm, rate); | ||
2158 | tbl->current_rate = ucode_rate; | ||
2159 | |||
2160 | WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B); | 2117 | WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B); |
2161 | if (rate->ant == ANT_A) | 2118 | if (rate->ant == ANT_A) |
2162 | tbl->column = RS_COLUMN_LEGACY_ANT_A; | 2119 | tbl->column = RS_COLUMN_LEGACY_ANT_A; |
@@ -2164,7 +2121,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
2164 | tbl->column = RS_COLUMN_LEGACY_ANT_B; | 2121 | tbl->column = RS_COLUMN_LEGACY_ANT_B; |
2165 | 2122 | ||
2166 | rs_set_expected_tpt_table(lq_sta, tbl); | 2123 | rs_set_expected_tpt_table(lq_sta, tbl); |
2167 | rs_fill_link_cmd(NULL, NULL, lq_sta, ucode_rate); | 2124 | rs_fill_lq_cmd(NULL, NULL, lq_sta, rate); |
2168 | /* TODO restore station should remember the lq cmd */ | 2125 | /* TODO restore station should remember the lq cmd */ |
2169 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init); | 2126 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init); |
2170 | } | 2127 | } |
@@ -2250,6 +2207,10 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, | |||
2250 | if (i == IWL_RATE_9M_INDEX) | 2207 | if (i == IWL_RATE_9M_INDEX) |
2251 | continue; | 2208 | continue; |
2252 | 2209 | ||
2210 | /* Disable MCS9 as a workaround */ | ||
2211 | if (i == IWL_RATE_MCS_9_INDEX) | ||
2212 | continue; | ||
2213 | |||
2253 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ | 2214 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ |
2254 | if (i == IWL_RATE_MCS_9_INDEX && | 2215 | if (i == IWL_RATE_MCS_9_INDEX && |
2255 | sta->bandwidth == IEEE80211_STA_RX_BW_20) | 2216 | sta->bandwidth == IEEE80211_STA_RX_BW_20) |
@@ -2268,6 +2229,10 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, | |||
2268 | if (i == IWL_RATE_9M_INDEX) | 2229 | if (i == IWL_RATE_9M_INDEX) |
2269 | continue; | 2230 | continue; |
2270 | 2231 | ||
2232 | /* Disable MCS9 as a workaround */ | ||
2233 | if (i == IWL_RATE_MCS_9_INDEX) | ||
2234 | continue; | ||
2235 | |||
2271 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ | 2236 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ |
2272 | if (i == IWL_RATE_MCS_9_INDEX && | 2237 | if (i == IWL_RATE_MCS_9_INDEX && |
2273 | sta->bandwidth == IEEE80211_STA_RX_BW_20) | 2238 | sta->bandwidth == IEEE80211_STA_RX_BW_20) |
@@ -2306,7 +2271,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2306 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2271 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
2307 | 2272 | ||
2308 | lq_sta->flush_timer = 0; | 2273 | lq_sta->flush_timer = 0; |
2309 | lq_sta->supp_rates = sta->supp_rates[sband->band]; | ||
2310 | 2274 | ||
2311 | IWL_DEBUG_RATE(mvm, | 2275 | IWL_DEBUG_RATE(mvm, |
2312 | "LQ: *** rate scale station global init for station %d ***\n", | 2276 | "LQ: *** rate scale station global init for station %d ***\n", |
@@ -2395,112 +2359,164 @@ static void rs_rate_update(void *mvm_r, | |||
2395 | iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); | 2359 | iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); |
2396 | } | 2360 | } |
2397 | 2361 | ||
2398 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, | 2362 | #ifdef CONFIG_MAC80211_DEBUGFS |
2399 | struct ieee80211_sta *sta, | 2363 | static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm, |
2400 | struct iwl_lq_sta *lq_sta, u32 new_rate) | 2364 | struct iwl_lq_cmd *lq_cmd, |
2365 | enum ieee80211_band band, | ||
2366 | u32 ucode_rate) | ||
2401 | { | 2367 | { |
2402 | struct rs_rate rate; | 2368 | struct rs_rate rate; |
2403 | int index = 0; | 2369 | int i; |
2404 | int repeat_rate = 0; | 2370 | int num_rates = ARRAY_SIZE(lq_cmd->rs_table); |
2405 | u8 ant_toggle_cnt = 0; | 2371 | __le32 ucode_rate_le32 = cpu_to_le32(ucode_rate); |
2406 | u8 use_ht_possible = 1; | ||
2407 | u8 valid_tx_ant = 0; | ||
2408 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | ||
2409 | 2372 | ||
2410 | /* Override starting rate (index 0) if needed for debug purposes */ | 2373 | for (i = 0; i < num_rates; i++) |
2411 | rs_dbgfs_set_mcs(lq_sta, &new_rate); | 2374 | lq_cmd->rs_table[i] = ucode_rate_le32; |
2412 | 2375 | ||
2413 | rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate); | 2376 | rs_rate_from_ucode_rate(ucode_rate, band, &rate); |
2414 | 2377 | ||
2415 | /* How many times should we repeat the initial rate? */ | 2378 | if (is_mimo(&rate)) |
2416 | if (is_legacy(&rate)) { | 2379 | lq_cmd->mimo_delim = num_rates - 1; |
2417 | ant_toggle_cnt = 1; | 2380 | else |
2418 | repeat_rate = IWL_NUMBER_TRY; | 2381 | lq_cmd->mimo_delim = 0; |
2419 | } else { | 2382 | } |
2420 | repeat_rate = min(IWL_HT_NUMBER_TRY, | 2383 | #endif /* CONFIG_MAC80211_DEBUGFS */ |
2421 | LINK_QUAL_AGG_DISABLE_START_DEF - 1); | 2384 | |
2385 | static void rs_fill_rates_for_column(struct iwl_mvm *mvm, | ||
2386 | struct iwl_lq_sta *lq_sta, | ||
2387 | struct rs_rate *rate, | ||
2388 | __le32 *rs_table, int *rs_table_index, | ||
2389 | int num_rates, int num_retries, | ||
2390 | u8 valid_tx_ant, bool toggle_ant) | ||
2391 | { | ||
2392 | int i, j; | ||
2393 | __le32 ucode_rate; | ||
2394 | bool bottom_reached = false; | ||
2395 | int prev_rate_idx = rate->index; | ||
2396 | int end = LINK_QUAL_MAX_RETRY_NUM; | ||
2397 | int index = *rs_table_index; | ||
2398 | |||
2399 | for (i = 0; i < num_rates && index < end; i++) { | ||
2400 | ucode_rate = cpu_to_le32(ucode_rate_from_rs_rate(mvm, rate)); | ||
2401 | for (j = 0; j < num_retries && index < end; j++, index++) | ||
2402 | rs_table[index] = ucode_rate; | ||
2403 | |||
2404 | if (toggle_ant) | ||
2405 | rs_toggle_antenna(valid_tx_ant, rate); | ||
2406 | |||
2407 | prev_rate_idx = rate->index; | ||
2408 | bottom_reached = rs_get_lower_rate_in_column(lq_sta, rate); | ||
2409 | if (bottom_reached && !is_legacy(rate)) | ||
2410 | break; | ||
2422 | } | 2411 | } |
2423 | 2412 | ||
2424 | lq_cmd->mimo_delim = is_mimo(&rate) ? 1 : 0; | 2413 | if (!bottom_reached) |
2414 | rate->index = prev_rate_idx; | ||
2425 | 2415 | ||
2426 | /* Fill 1st table entry (index 0) */ | 2416 | *rs_table_index = index; |
2427 | lq_cmd->rs_table[index] = cpu_to_le32(new_rate); | 2417 | } |
2428 | 2418 | ||
2429 | if (num_of_ant(rate.ant) == 1) | 2419 | /* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI |
2430 | lq_cmd->single_stream_ant_msk = rate.ant; | 2420 | * column the rate table should look like this: |
2431 | /* otherwise we don't modify the existing value */ | 2421 | * |
2422 | * rate[0] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI | ||
2423 | * rate[1] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI | ||
2424 | * rate[2] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI | ||
2425 | * rate[3] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI | ||
2426 | * rate[4] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI | ||
2427 | * rate[5] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI | ||
2428 | * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI | ||
2429 | * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI | ||
2430 | * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI | ||
2431 | * rate[9] 0x800B Legacy | ANT: B Rate: 36 Mbps | ||
2432 | * rate[10] 0x4009 Legacy | ANT: A Rate: 24 Mbps | ||
2433 | * rate[11] 0x8007 Legacy | ANT: B Rate: 18 Mbps | ||
2434 | * rate[12] 0x4005 Legacy | ANT: A Rate: 12 Mbps | ||
2435 | * rate[13] 0x800F Legacy | ANT: B Rate: 9 Mbps | ||
2436 | * rate[14] 0x400D Legacy | ANT: A Rate: 6 Mbps | ||
2437 | * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps | ||
2438 | */ | ||
2439 | static void rs_build_rates_table(struct iwl_mvm *mvm, | ||
2440 | struct iwl_lq_sta *lq_sta, | ||
2441 | const struct rs_rate *initial_rate) | ||
2442 | { | ||
2443 | struct rs_rate rate; | ||
2444 | int num_rates, num_retries, index = 0; | ||
2445 | u8 valid_tx_ant = 0; | ||
2446 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | ||
2447 | bool toggle_ant = false; | ||
2448 | |||
2449 | memcpy(&rate, initial_rate, sizeof(struct rs_rate)); | ||
2432 | 2450 | ||
2433 | index++; | ||
2434 | repeat_rate--; | ||
2435 | if (mvm) | 2451 | if (mvm) |
2436 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | 2452 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
2437 | 2453 | ||
2438 | /* Fill rest of rate table */ | 2454 | if (is_siso(&rate)) { |
2439 | while (index < LINK_QUAL_MAX_RETRY_NUM) { | 2455 | num_rates = RS_INITIAL_SISO_NUM_RATES; |
2440 | /* Repeat initial/next rate. | 2456 | num_retries = RS_HT_VHT_RETRIES_PER_RATE; |
2441 | * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. | 2457 | } else if (is_mimo(&rate)) { |
2442 | * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ | 2458 | num_rates = RS_INITIAL_MIMO_NUM_RATES; |
2443 | while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { | 2459 | num_retries = RS_HT_VHT_RETRIES_PER_RATE; |
2444 | if (is_legacy(&rate)) { | 2460 | } else { |
2445 | if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) | 2461 | num_rates = RS_INITIAL_LEGACY_NUM_RATES; |
2446 | ant_toggle_cnt++; | 2462 | num_retries = RS_LEGACY_RETRIES_PER_RATE; |
2447 | else if (mvm && | 2463 | toggle_ant = true; |
2448 | rs_toggle_antenna(valid_tx_ant, | 2464 | } |
2449 | &new_rate, &rate)) | ||
2450 | ant_toggle_cnt = 1; | ||
2451 | } | ||
2452 | 2465 | ||
2453 | /* Override next rate if needed for debug purposes */ | 2466 | rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index, |
2454 | rs_dbgfs_set_mcs(lq_sta, &new_rate); | 2467 | num_rates, num_retries, valid_tx_ant, |
2468 | toggle_ant); | ||
2455 | 2469 | ||
2456 | /* Fill next table entry */ | 2470 | rs_get_lower_rate_down_column(lq_sta, &rate); |
2457 | lq_cmd->rs_table[index] = | ||
2458 | cpu_to_le32(new_rate); | ||
2459 | repeat_rate--; | ||
2460 | index++; | ||
2461 | } | ||
2462 | 2471 | ||
2463 | rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate); | 2472 | if (is_siso(&rate)) { |
2473 | num_rates = RS_SECONDARY_SISO_NUM_RATES; | ||
2474 | num_retries = RS_SECONDARY_SISO_RETRIES; | ||
2475 | } else if (is_legacy(&rate)) { | ||
2476 | num_rates = RS_SECONDARY_LEGACY_NUM_RATES; | ||
2477 | num_retries = RS_LEGACY_RETRIES_PER_RATE; | ||
2478 | } else { | ||
2479 | WARN_ON_ONCE(1); | ||
2480 | } | ||
2464 | 2481 | ||
2465 | /* Indicate to uCode which entries might be MIMO. | 2482 | toggle_ant = true; |
2466 | * If initial rate was MIMO, this will finally end up | ||
2467 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ | ||
2468 | if (is_mimo(&rate)) | ||
2469 | lq_cmd->mimo_delim = index; | ||
2470 | 2483 | ||
2471 | /* Get next rate */ | 2484 | rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index, |
2472 | new_rate = rs_get_lower_rate(lq_sta, &rate, rate.index, | 2485 | num_rates, num_retries, valid_tx_ant, |
2473 | use_ht_possible); | 2486 | toggle_ant); |
2474 | 2487 | ||
2475 | /* How many times should we repeat the next rate? */ | 2488 | rs_get_lower_rate_down_column(lq_sta, &rate); |
2476 | if (is_legacy(&rate)) { | ||
2477 | if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) | ||
2478 | ant_toggle_cnt++; | ||
2479 | else if (mvm && | ||
2480 | rs_toggle_antenna(valid_tx_ant, | ||
2481 | &new_rate, &rate)) | ||
2482 | ant_toggle_cnt = 1; | ||
2483 | 2489 | ||
2484 | repeat_rate = IWL_NUMBER_TRY; | 2490 | num_rates = RS_SECONDARY_LEGACY_NUM_RATES; |
2485 | } else { | 2491 | num_retries = RS_LEGACY_RETRIES_PER_RATE; |
2486 | repeat_rate = IWL_HT_NUMBER_TRY; | ||
2487 | } | ||
2488 | 2492 | ||
2489 | /* Don't allow HT rates after next pass. | 2493 | rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index, |
2490 | * rs_get_lower_rate() will change type to LQ_LEGACY_A | 2494 | num_rates, num_retries, valid_tx_ant, |
2491 | * or LQ_LEGACY_G. | 2495 | toggle_ant); |
2492 | */ | ||
2493 | use_ht_possible = 0; | ||
2494 | 2496 | ||
2495 | /* Override next rate if needed for debug purposes */ | 2497 | } |
2496 | rs_dbgfs_set_mcs(lq_sta, &new_rate); | ||
2497 | 2498 | ||
2498 | /* Fill next table entry */ | 2499 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, |
2499 | lq_cmd->rs_table[index] = cpu_to_le32(new_rate); | 2500 | struct ieee80211_sta *sta, |
2501 | struct iwl_lq_sta *lq_sta, | ||
2502 | const struct rs_rate *initial_rate) | ||
2503 | { | ||
2504 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | ||
2505 | u8 ant = initial_rate->ant; | ||
2500 | 2506 | ||
2501 | index++; | 2507 | #ifdef CONFIG_MAC80211_DEBUGFS |
2502 | repeat_rate--; | 2508 | if (lq_sta->dbg_fixed_rate) { |
2503 | } | 2509 | rs_build_rates_table_from_fixed(mvm, lq_cmd, |
2510 | lq_sta->band, | ||
2511 | lq_sta->dbg_fixed_rate); | ||
2512 | ant = (lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >> | ||
2513 | RATE_MCS_ANT_POS; | ||
2514 | } else | ||
2515 | #endif | ||
2516 | rs_build_rates_table(mvm, lq_sta, initial_rate); | ||
2517 | |||
2518 | if (num_of_ant(ant) == 1) | ||
2519 | lq_cmd->single_stream_ant_msk = ant; | ||
2504 | 2520 | ||
2505 | lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | 2521 | lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
2506 | lq_cmd->agg_disable_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 2522 | lq_cmd->agg_disable_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
@@ -2534,31 +2550,6 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, | |||
2534 | } | 2550 | } |
2535 | 2551 | ||
2536 | #ifdef CONFIG_MAC80211_DEBUGFS | 2552 | #ifdef CONFIG_MAC80211_DEBUGFS |
2537 | static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | ||
2538 | u32 *rate_n_flags) | ||
2539 | { | ||
2540 | struct iwl_mvm *mvm; | ||
2541 | u8 valid_tx_ant; | ||
2542 | u8 ant_sel_tx; | ||
2543 | |||
2544 | mvm = lq_sta->drv; | ||
2545 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | ||
2546 | if (lq_sta->dbg_fixed_rate) { | ||
2547 | ant_sel_tx = | ||
2548 | ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | ||
2549 | >> RATE_MCS_ANT_POS); | ||
2550 | if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) { | ||
2551 | *rate_n_flags = lq_sta->dbg_fixed_rate; | ||
2552 | } else { | ||
2553 | lq_sta->dbg_fixed_rate = 0; | ||
2554 | IWL_ERR(mvm, | ||
2555 | "Invalid antenna selection 0x%X, Valid is 0x%X\n", | ||
2556 | ant_sel_tx, valid_tx_ant); | ||
2557 | IWL_DEBUG_RATE(mvm, "Fixed rate OFF\n"); | ||
2558 | } | ||
2559 | } | ||
2560 | } | ||
2561 | |||
2562 | static int rs_pretty_print_rate(char *buf, const u32 rate) | 2553 | static int rs_pretty_print_rate(char *buf, const u32 rate) |
2563 | { | 2554 | { |
2564 | 2555 | ||
@@ -2612,6 +2603,31 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) | |||
2612 | (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : ""); | 2603 | (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : ""); |
2613 | } | 2604 | } |
2614 | 2605 | ||
2606 | /** | ||
2607 | * Program the device to use fixed rate for frame transmit | ||
2608 | * This is for debugging/testing only | ||
2609 | * once the device start use fixed rate, we need to reload the module | ||
2610 | * to being back the normal operation. | ||
2611 | */ | ||
2612 | static void rs_program_fix_rate(struct iwl_mvm *mvm, | ||
2613 | struct iwl_lq_sta *lq_sta) | ||
2614 | { | ||
2615 | lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ | ||
2616 | lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | ||
2617 | lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ | ||
2618 | |||
2619 | IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n", | ||
2620 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); | ||
2621 | |||
2622 | if (lq_sta->dbg_fixed_rate) { | ||
2623 | struct rs_rate rate; | ||
2624 | rs_rate_from_ucode_rate(lq_sta->dbg_fixed_rate, | ||
2625 | lq_sta->band, &rate); | ||
2626 | rs_fill_lq_cmd(NULL, NULL, lq_sta, &rate); | ||
2627 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false); | ||
2628 | } | ||
2629 | } | ||
2630 | |||
2615 | static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | 2631 | static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, |
2616 | const char __user *user_buf, size_t count, loff_t *ppos) | 2632 | const char __user *user_buf, size_t count, loff_t *ppos) |
2617 | { | 2633 | { |
@@ -2702,12 +2718,10 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2702 | lq_sta->lq.initial_rate_index[3]); | 2718 | lq_sta->lq.initial_rate_index[3]); |
2703 | 2719 | ||
2704 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | 2720 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { |
2705 | u32 rate = le32_to_cpu(lq_sta->lq.rs_table[i]); | 2721 | u32 r = le32_to_cpu(lq_sta->lq.rs_table[i]); |
2706 | desc += sprintf(buff+desc, | ||
2707 | " rate[%d] 0x%X ", | ||
2708 | i, rate); | ||
2709 | 2722 | ||
2710 | desc += rs_pretty_print_rate(buff+desc, rate); | 2723 | desc += sprintf(buff+desc, " rate[%d] 0x%X ", i, r); |
2724 | desc += rs_pretty_print_rate(buff+desc, r); | ||
2711 | } | 2725 | } |
2712 | 2726 | ||
2713 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2727 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
@@ -2741,14 +2755,14 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, | |||
2741 | rate = &tbl->rate; | 2755 | rate = &tbl->rate; |
2742 | desc += sprintf(buff+desc, | 2756 | desc += sprintf(buff+desc, |
2743 | "%s type=%d SGI=%d BW=%s DUP=0\n" | 2757 | "%s type=%d SGI=%d BW=%s DUP=0\n" |
2744 | "rate=0x%X\n", | 2758 | "index=%d\n", |
2745 | lq_sta->active_tbl == i ? "*" : "x", | 2759 | lq_sta->active_tbl == i ? "*" : "x", |
2746 | rate->type, | 2760 | rate->type, |
2747 | rate->sgi, | 2761 | rate->sgi, |
2748 | is_ht20(rate) ? "20Mhz" : | 2762 | is_ht20(rate) ? "20Mhz" : |
2749 | is_ht40(rate) ? "40Mhz" : | 2763 | is_ht40(rate) ? "40Mhz" : |
2750 | is_ht80(rate) ? "80Mhz" : "ERR", | 2764 | is_ht80(rate) ? "80Mhz" : "ERR", |
2751 | tbl->current_rate); | 2765 | rate->index); |
2752 | for (j = 0; j < IWL_RATE_COUNT; j++) { | 2766 | for (j = 0; j < IWL_RATE_COUNT; j++) { |
2753 | desc += sprintf(buff+desc, | 2767 | desc += sprintf(buff+desc, |
2754 | "counter=%d success=%d %%=%d\n", | 2768 | "counter=%d success=%d %%=%d\n", |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index b32960796384..c31aa59728ea 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -278,7 +278,6 @@ struct iwl_scale_tbl_info { | |||
278 | struct rs_rate rate; | 278 | struct rs_rate rate; |
279 | enum rs_column column; | 279 | enum rs_column column; |
280 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | 280 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ |
281 | u32 current_rate; /* rate_n_flags, uCode API format */ | ||
282 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | 281 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ |
283 | }; | 282 | }; |
284 | 283 | ||
@@ -315,7 +314,6 @@ struct iwl_lq_sta { | |||
315 | enum ieee80211_band band; | 314 | enum ieee80211_band band; |
316 | 315 | ||
317 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 316 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
318 | u32 supp_rates; | ||
319 | u16 active_legacy_rate; | 317 | u16 active_legacy_rate; |
320 | u16 active_siso_rate; | 318 | u16 active_siso_rate; |
321 | u16 active_mimo2_rate; | 319 | u16 active_mimo2_rate; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 3a1f3982109d..454341cc3b27 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -251,6 +251,12 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, | |||
251 | stats->flag |= RX_FLAG_DECRYPTED; | 251 | stats->flag |= RX_FLAG_DECRYPTED; |
252 | return 0; | 252 | return 0; |
253 | 253 | ||
254 | case RX_MPDU_RES_STATUS_SEC_EXT_ENC: | ||
255 | if (!(rx_pkt_status & RX_MPDU_RES_STATUS_MIC_OK)) | ||
256 | return -1; | ||
257 | stats->flag |= RX_FLAG_DECRYPTED; | ||
258 | return 0; | ||
259 | |||
254 | default: | 260 | default: |
255 | IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status); | 261 | IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status); |
256 | } | 262 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c new file mode 100644 index 000000000000..97bb3c3e75ce --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c | |||
@@ -0,0 +1,291 @@ | |||
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) 2013 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 COPYING. | ||
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) 2013 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 "mvm.h" | ||
64 | |||
65 | /* For counting bound interfaces */ | ||
66 | struct iwl_mvm_active_iface_iterator_data { | ||
67 | struct ieee80211_vif *ignore_vif; | ||
68 | u8 sta_vif_ap_sta_id; | ||
69 | enum iwl_sf_state sta_vif_state; | ||
70 | int num_active_macs; | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * Count bound interfaces which are not p2p, besides data->ignore_vif. | ||
75 | * data->station_vif will point to one bound vif of type station, if exists. | ||
76 | */ | ||
77 | static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac, | ||
78 | struct ieee80211_vif *vif) | ||
79 | { | ||
80 | struct iwl_mvm_active_iface_iterator_data *data = _data; | ||
81 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
82 | |||
83 | if (vif == data->ignore_vif || !mvmvif->phy_ctxt || | ||
84 | vif->type == NL80211_IFTYPE_P2P_DEVICE) | ||
85 | return; | ||
86 | |||
87 | data->num_active_macs++; | ||
88 | |||
89 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
90 | data->sta_vif_ap_sta_id = mvmvif->ap_sta_id; | ||
91 | if (vif->bss_conf.assoc) | ||
92 | data->sta_vif_state = SF_FULL_ON; | ||
93 | else | ||
94 | data->sta_vif_state = SF_INIT_OFF; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Aging and idle timeouts for the different possible scenarios | ||
100 | * in SF_FULL_ON state. | ||
101 | */ | ||
102 | static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { | ||
103 | { | ||
104 | cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER), | ||
105 | cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER) | ||
106 | }, | ||
107 | { | ||
108 | cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER), | ||
109 | cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER) | ||
110 | }, | ||
111 | { | ||
112 | cpu_to_le32(SF_MCAST_AGING_TIMER), | ||
113 | cpu_to_le32(SF_MCAST_IDLE_TIMER) | ||
114 | }, | ||
115 | { | ||
116 | cpu_to_le32(SF_BA_AGING_TIMER), | ||
117 | cpu_to_le32(SF_BA_IDLE_TIMER) | ||
118 | }, | ||
119 | { | ||
120 | cpu_to_le32(SF_TX_RE_AGING_TIMER), | ||
121 | cpu_to_le32(SF_TX_RE_IDLE_TIMER) | ||
122 | }, | ||
123 | }; | ||
124 | |||
125 | static void iwl_mvm_fill_sf_command(struct iwl_sf_cfg_cmd *sf_cmd, | ||
126 | struct ieee80211_sta *sta) | ||
127 | { | ||
128 | int i, j, watermark; | ||
129 | |||
130 | sf_cmd->watermark[SF_LONG_DELAY_ON] = cpu_to_le32(SF_W_MARK_SCAN); | ||
131 | |||
132 | /* | ||
133 | * If we are in association flow - check antenna configuration | ||
134 | * capabilities of the AP station, and choose the watermark accordingly. | ||
135 | */ | ||
136 | if (sta) { | ||
137 | if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) { | ||
138 | switch (sta->rx_nss) { | ||
139 | case 1: | ||
140 | watermark = SF_W_MARK_SISO; | ||
141 | break; | ||
142 | case 2: | ||
143 | watermark = SF_W_MARK_MIMO2; | ||
144 | break; | ||
145 | default: | ||
146 | watermark = SF_W_MARK_MIMO3; | ||
147 | break; | ||
148 | } | ||
149 | } else { | ||
150 | watermark = SF_W_MARK_LEGACY; | ||
151 | } | ||
152 | /* default watermark value for unassociated mode. */ | ||
153 | } else { | ||
154 | watermark = SF_W_MARK_MIMO2; | ||
155 | } | ||
156 | sf_cmd->watermark[SF_FULL_ON] = cpu_to_le32(watermark); | ||
157 | |||
158 | for (i = 0; i < SF_NUM_SCENARIO; i++) { | ||
159 | for (j = 0; j < SF_NUM_TIMEOUT_TYPES; j++) { | ||
160 | sf_cmd->long_delay_timeouts[i][j] = | ||
161 | cpu_to_le32(SF_LONG_DELAY_AGING_TIMER); | ||
162 | } | ||
163 | } | ||
164 | BUILD_BUG_ON(sizeof(sf_full_timeout) != | ||
165 | sizeof(__le32) * SF_NUM_SCENARIO * SF_NUM_TIMEOUT_TYPES); | ||
166 | |||
167 | memcpy(sf_cmd->full_on_timeouts, sf_full_timeout, | ||
168 | sizeof(sf_full_timeout)); | ||
169 | } | ||
170 | |||
171 | static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, | ||
172 | enum iwl_sf_state new_state) | ||
173 | { | ||
174 | struct iwl_sf_cfg_cmd sf_cmd = { | ||
175 | .state = new_state, | ||
176 | }; | ||
177 | struct ieee80211_sta *sta; | ||
178 | int ret = 0; | ||
179 | |||
180 | /* | ||
181 | * If an associated AP sta changed its antenna configuration, the state | ||
182 | * will remain FULL_ON but SF parameters need to be reconsidered. | ||
183 | */ | ||
184 | if (new_state != SF_FULL_ON && mvm->sf_state == new_state) | ||
185 | return 0; | ||
186 | |||
187 | switch (new_state) { | ||
188 | case SF_UNINIT: | ||
189 | break; | ||
190 | case SF_FULL_ON: | ||
191 | if (sta_id == IWL_MVM_STATION_COUNT) { | ||
192 | IWL_ERR(mvm, | ||
193 | "No station: Cannot switch SF to FULL_ON\n"); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | rcu_read_lock(); | ||
197 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | ||
198 | if (IS_ERR_OR_NULL(sta)) { | ||
199 | IWL_ERR(mvm, "Invalid station id\n"); | ||
200 | rcu_read_unlock(); | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | iwl_mvm_fill_sf_command(&sf_cmd, sta); | ||
204 | rcu_read_unlock(); | ||
205 | break; | ||
206 | case SF_INIT_OFF: | ||
207 | iwl_mvm_fill_sf_command(&sf_cmd, NULL); | ||
208 | break; | ||
209 | default: | ||
210 | WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n", | ||
211 | new_state); | ||
212 | return -EINVAL; | ||
213 | } | ||
214 | |||
215 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_SF_CFG_CMD, CMD_ASYNC, | ||
216 | sizeof(sf_cmd), &sf_cmd); | ||
217 | if (!ret) | ||
218 | mvm->sf_state = new_state; | ||
219 | |||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Update Smart fifo: | ||
225 | * Count bound interfaces that are not to be removed, ignoring p2p devices, | ||
226 | * and set new state accordingly. | ||
227 | */ | ||
228 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif, | ||
229 | bool remove_vif) | ||
230 | { | ||
231 | enum iwl_sf_state new_state; | ||
232 | u8 sta_id = IWL_MVM_STATION_COUNT; | ||
233 | struct iwl_mvm_vif *mvmvif = NULL; | ||
234 | struct iwl_mvm_active_iface_iterator_data data = { | ||
235 | .ignore_vif = changed_vif, | ||
236 | .sta_vif_state = SF_UNINIT, | ||
237 | .sta_vif_ap_sta_id = IWL_MVM_STATION_COUNT, | ||
238 | }; | ||
239 | |||
240 | if (IWL_UCODE_API(mvm->fw->ucode_ver) < 8) | ||
241 | return 0; | ||
242 | |||
243 | /* | ||
244 | * Ignore the call if we are in HW Restart flow, or if the handled | ||
245 | * vif is a p2p device. | ||
246 | */ | ||
247 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) || | ||
248 | (changed_vif && changed_vif->type == NL80211_IFTYPE_P2P_DEVICE)) | ||
249 | return 0; | ||
250 | |||
251 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
252 | IEEE80211_IFACE_ITER_NORMAL, | ||
253 | iwl_mvm_bound_iface_iterator, | ||
254 | &data); | ||
255 | |||
256 | /* If changed_vif exists and is not to be removed, add to the count */ | ||
257 | if (changed_vif && !remove_vif) | ||
258 | data.num_active_macs++; | ||
259 | |||
260 | switch (data.num_active_macs) { | ||
261 | case 0: | ||
262 | /* If there are no active macs - change state to SF_INIT_OFF */ | ||
263 | new_state = SF_INIT_OFF; | ||
264 | break; | ||
265 | case 1: | ||
266 | if (remove_vif) { | ||
267 | /* The one active mac left is of type station | ||
268 | * and we filled the relevant data during iteration | ||
269 | */ | ||
270 | new_state = data.sta_vif_state; | ||
271 | sta_id = data.sta_vif_ap_sta_id; | ||
272 | } else { | ||
273 | if (WARN_ON(!changed_vif)) | ||
274 | return -EINVAL; | ||
275 | if (changed_vif->type != NL80211_IFTYPE_STATION) { | ||
276 | new_state = SF_UNINIT; | ||
277 | } else if (changed_vif->bss_conf.assoc) { | ||
278 | mvmvif = iwl_mvm_vif_from_mac80211(changed_vif); | ||
279 | sta_id = mvmvif->ap_sta_id; | ||
280 | new_state = SF_FULL_ON; | ||
281 | } else { | ||
282 | new_state = SF_INIT_OFF; | ||
283 | } | ||
284 | } | ||
285 | break; | ||
286 | default: | ||
287 | /* If there are multiple active macs - change to SF_UNINIT */ | ||
288 | new_state = SF_UNINIT; | ||
289 | } | ||
290 | return iwl_mvm_sf_config(mvm, sta_id, new_state); | ||
291 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 7a5b7473eafa..0a8af2083ddc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -452,8 +452,15 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) | |||
452 | rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], | 452 | rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], |
453 | lockdep_is_held(&mvm->mutex)); | 453 | lockdep_is_held(&mvm->mutex)); |
454 | 454 | ||
455 | /* This station is in use */ | 455 | /* |
456 | if (!IS_ERR(sta)) | 456 | * This station is in use or RCU-removed; the latter happens in |
457 | * managed mode, where mac80211 removes the station before we | ||
458 | * can remove it from firmware (we can only do that after the | ||
459 | * MAC is marked unassociated), and possibly while the deauth | ||
460 | * frame to disconnect from the AP is still queued. Then, the | ||
461 | * station pointer is -ENOENT when the last skb is reclaimed. | ||
462 | */ | ||
463 | if (!IS_ERR(sta) || PTR_ERR(sta) == -ENOENT) | ||
457 | continue; | 464 | continue; |
458 | 465 | ||
459 | if (PTR_ERR(sta) == -EINVAL) { | 466 | if (PTR_ERR(sta) == -EINVAL) { |
@@ -932,19 +939,6 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
932 | IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n", | 939 | IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n", |
933 | sta->addr, tid); | 940 | sta->addr, tid); |
934 | 941 | ||
935 | if (mvm->cfg->ht_params->use_rts_for_aggregation) { | ||
936 | /* | ||
937 | * switch to RTS/CTS if it is the prefer protection | ||
938 | * method for HT traffic | ||
939 | * this function also sends the LQ command | ||
940 | */ | ||
941 | return iwl_mvm_tx_protection(mvm, mvmsta, true); | ||
942 | /* | ||
943 | * TODO: remove the TLC_RTS flag when we tear down the last | ||
944 | * AGG session (agg_tids_count in DVM) | ||
945 | */ | ||
946 | } | ||
947 | |||
948 | return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, false); | 942 | return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, false); |
949 | } | 943 | } |
950 | 944 | ||
@@ -1123,8 +1117,8 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
1123 | memcpy(cmd.key, keyconf->key, keyconf->keylen); | 1117 | memcpy(cmd.key, keyconf->key, keyconf->keylen); |
1124 | break; | 1118 | break; |
1125 | default: | 1119 | default: |
1126 | WARN_ON(1); | 1120 | key_flags |= cpu_to_le16(STA_KEY_FLG_EXT); |
1127 | return -EINVAL; | 1121 | memcpy(cmd.key, keyconf->key, keyconf->keylen); |
1128 | } | 1122 | } |
1129 | 1123 | ||
1130 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | 1124 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
@@ -1288,8 +1282,8 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | |||
1288 | 0, NULL, CMD_SYNC); | 1282 | 0, NULL, CMD_SYNC); |
1289 | break; | 1283 | break; |
1290 | default: | 1284 | default: |
1291 | IWL_ERR(mvm, "Unknown cipher %x\n", keyconf->cipher); | 1285 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, |
1292 | ret = -EINVAL; | 1286 | sta_id, 0, NULL, CMD_SYNC); |
1293 | } | 1287 | } |
1294 | 1288 | ||
1295 | if (ret) | 1289 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 18be04da8e3f..a0ec7b3473bd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -340,7 +340,7 @@ static void check_exit_ctkill(struct work_struct *work) | |||
340 | 340 | ||
341 | iwl_trans_start_hw(mvm->trans); | 341 | iwl_trans_start_hw(mvm->trans); |
342 | temp = check_nic_temperature(mvm); | 342 | temp = check_nic_temperature(mvm); |
343 | iwl_trans_stop_hw(mvm->trans, false); | 343 | iwl_trans_stop_device(mvm->trans); |
344 | 344 | ||
345 | if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { | 345 | if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { |
346 | IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); | 346 | IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index d87649ac88e1..735f86da7985 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -253,8 +253,7 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, | |||
253 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | 253 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); |
254 | break; | 254 | break; |
255 | default: | 255 | default: |
256 | IWL_ERR(mvm, "Unknown encode cipher %x\n", keyconf->cipher); | 256 | tx_cmd->sec_ctl |= TX_CMD_SEC_EXT; |
257 | break; | ||
258 | } | 257 | } |
259 | } | 258 | } |
260 | 259 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 56cf819bc0c7..f4aff56a36da 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -518,6 +518,11 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
518 | int i; | 518 | int i; |
519 | 519 | ||
520 | lockdep_assert_held(&mvm->mutex); | 520 | lockdep_assert_held(&mvm->mutex); |
521 | |||
522 | /* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */ | ||
523 | if (num_of_ant(iwl_fw_valid_rx_ant(mvm->fw)) == 1) | ||
524 | return; | ||
525 | |||
521 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | 526 | mvmvif = iwl_mvm_vif_from_mac80211(vif); |
522 | mvmvif->smps_requests[req_type] = smps_request; | 527 | mvmvif->smps_requests[req_type] = smps_request; |
523 | for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { | 528 | for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 051268c037b1..674c75b0d002 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -256,7 +256,6 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) | |||
256 | * @hw_base: pci hardware address support | 256 | * @hw_base: pci hardware address support |
257 | * @ucode_write_complete: indicates that the ucode has been copied. | 257 | * @ucode_write_complete: indicates that the ucode has been copied. |
258 | * @ucode_write_waitq: wait queue for uCode load | 258 | * @ucode_write_waitq: wait queue for uCode load |
259 | * @status - transport specific status flags | ||
260 | * @cmd_queue - command queue number | 259 | * @cmd_queue - command queue number |
261 | * @rx_buf_size_8k: 8 kB RX buffer size | 260 | * @rx_buf_size_8k: 8 kB RX buffer size |
262 | * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes) | 261 | * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes) |
@@ -296,7 +295,6 @@ struct iwl_trans_pcie { | |||
296 | wait_queue_head_t ucode_write_waitq; | 295 | wait_queue_head_t ucode_write_waitq; |
297 | wait_queue_head_t wait_command_queue; | 296 | wait_queue_head_t wait_command_queue; |
298 | 297 | ||
299 | unsigned long status; | ||
300 | u8 cmd_queue; | 298 | u8 cmd_queue; |
301 | u8 cmd_fifo; | 299 | u8 cmd_fifo; |
302 | u8 n_no_reclaim_cmds; | 300 | u8 n_no_reclaim_cmds; |
@@ -315,24 +313,6 @@ struct iwl_trans_pcie { | |||
315 | spinlock_t reg_lock; | 313 | spinlock_t reg_lock; |
316 | }; | 314 | }; |
317 | 315 | ||
318 | /** | ||
319 | * enum iwl_pcie_status: status of the PCIe transport | ||
320 | * @STATUS_HCMD_ACTIVE: a SYNC command is being processed | ||
321 | * @STATUS_DEVICE_ENABLED: APM is enabled | ||
322 | * @STATUS_TPOWER_PMI: the device might be asleep (need to wake it up) | ||
323 | * @STATUS_INT_ENABLED: interrupts are enabled | ||
324 | * @STATUS_RFKILL: the HW RFkill switch is in KILL position | ||
325 | * @STATUS_FW_ERROR: the fw is in error state | ||
326 | */ | ||
327 | enum iwl_pcie_status { | ||
328 | STATUS_HCMD_ACTIVE, | ||
329 | STATUS_DEVICE_ENABLED, | ||
330 | STATUS_TPOWER_PMI, | ||
331 | STATUS_INT_ENABLED, | ||
332 | STATUS_RFKILL, | ||
333 | STATUS_FW_ERROR, | ||
334 | }; | ||
335 | |||
336 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 316 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
337 | ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) | 317 | ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) |
338 | 318 | ||
@@ -399,8 +379,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans); | |||
399 | ******************************************************/ | 379 | ******************************************************/ |
400 | static inline void iwl_disable_interrupts(struct iwl_trans *trans) | 380 | static inline void iwl_disable_interrupts(struct iwl_trans *trans) |
401 | { | 381 | { |
402 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 382 | clear_bit(STATUS_INT_ENABLED, &trans->status); |
403 | clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); | ||
404 | 383 | ||
405 | /* disable interrupts from uCode/NIC to host */ | 384 | /* disable interrupts from uCode/NIC to host */ |
406 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); | 385 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); |
@@ -417,7 +396,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) | |||
417 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 396 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
418 | 397 | ||
419 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); | 398 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); |
420 | set_bit(STATUS_INT_ENABLED, &trans_pcie->status); | 399 | set_bit(STATUS_INT_ENABLED, &trans->status); |
421 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | 400 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); |
422 | } | 401 | } |
423 | 402 | ||
@@ -477,12 +456,4 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) | |||
477 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | 456 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); |
478 | } | 457 | } |
479 | 458 | ||
480 | static inline void iwl_nic_error(struct iwl_trans *trans) | ||
481 | { | ||
482 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
483 | |||
484 | set_bit(STATUS_FW_ERROR, &trans_pcie->status); | ||
485 | iwl_op_mode_nic_error(trans->op_mode); | ||
486 | } | ||
487 | |||
488 | #endif /* __iwl_trans_int_pcie_h__ */ | 459 | #endif /* __iwl_trans_int_pcie_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 1d6bf7b98e2d..7aeec5ccefa5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -162,11 +162,8 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, | |||
162 | rxq->write_actual = (rxq->write & ~0x7); | 162 | rxq->write_actual = (rxq->write & ~0x7); |
163 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); | 163 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); |
164 | } else { | 164 | } else { |
165 | struct iwl_trans_pcie *trans_pcie = | ||
166 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
167 | |||
168 | /* If power-saving is in use, make sure device is awake */ | 165 | /* If power-saving is in use, make sure device is awake */ |
169 | if (test_bit(STATUS_TPOWER_PMI, &trans_pcie->status)) { | 166 | if (test_bit(STATUS_TPOWER_PMI, &trans->status)) { |
170 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); | 167 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); |
171 | 168 | ||
172 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 169 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
@@ -222,7 +219,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) | |||
222 | * stopped, we cannot access the HW (in particular not prph). | 219 | * stopped, we cannot access the HW (in particular not prph). |
223 | * So don't try to restock if the APM has been already stopped. | 220 | * So don't try to restock if the APM has been already stopped. |
224 | */ | 221 | */ |
225 | if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) | 222 | if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status)) |
226 | return; | 223 | return; |
227 | 224 | ||
228 | spin_lock_irqsave(&rxq->lock, flags); | 225 | spin_lock_irqsave(&rxq->lock, flags); |
@@ -791,7 +788,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) | |||
791 | APMS_CLK_VAL_MRB_FUNC_MODE) || | 788 | APMS_CLK_VAL_MRB_FUNC_MODE) || |
792 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & | 789 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & |
793 | APMG_PS_CTRL_VAL_RESET_REQ))) { | 790 | APMG_PS_CTRL_VAL_RESET_REQ))) { |
794 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 791 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
795 | iwl_op_mode_wimax_active(trans->op_mode); | 792 | iwl_op_mode_wimax_active(trans->op_mode); |
796 | wake_up(&trans_pcie->wait_command_queue); | 793 | wake_up(&trans_pcie->wait_command_queue); |
797 | return; | 794 | return; |
@@ -800,14 +797,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) | |||
800 | iwl_pcie_dump_csr(trans); | 797 | iwl_pcie_dump_csr(trans); |
801 | iwl_dump_fh(trans, NULL); | 798 | iwl_dump_fh(trans, NULL); |
802 | 799 | ||
803 | /* set the ERROR bit before we wake up the caller */ | ||
804 | set_bit(STATUS_FW_ERROR, &trans_pcie->status); | ||
805 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | ||
806 | wake_up(&trans_pcie->wait_command_queue); | ||
807 | |||
808 | local_bh_disable(); | 800 | local_bh_disable(); |
809 | iwl_nic_error(trans); | 801 | /* The STATUS_FW_ERROR bit is set in this function. This must happen |
802 | * before we wake up the command caller, to ensure a proper cleanup. */ | ||
803 | iwl_trans_fw_error(trans); | ||
810 | local_bh_enable(); | 804 | local_bh_enable(); |
805 | |||
806 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); | ||
807 | wake_up(&trans_pcie->wait_command_queue); | ||
811 | } | 808 | } |
812 | 809 | ||
813 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | 810 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) |
@@ -894,14 +891,14 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
894 | 891 | ||
895 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 892 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
896 | if (hw_rfkill) { | 893 | if (hw_rfkill) { |
897 | set_bit(STATUS_RFKILL, &trans_pcie->status); | 894 | set_bit(STATUS_RFKILL, &trans->status); |
898 | if (test_and_clear_bit(STATUS_HCMD_ACTIVE, | 895 | if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE, |
899 | &trans_pcie->status)) | 896 | &trans->status)) |
900 | IWL_DEBUG_RF_KILL(trans, | 897 | IWL_DEBUG_RF_KILL(trans, |
901 | "Rfkill while SYNC HCMD in flight\n"); | 898 | "Rfkill while SYNC HCMD in flight\n"); |
902 | wake_up(&trans_pcie->wait_command_queue); | 899 | wake_up(&trans_pcie->wait_command_queue); |
903 | } else { | 900 | } else { |
904 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | 901 | clear_bit(STATUS_RFKILL, &trans->status); |
905 | } | 902 | } |
906 | 903 | ||
907 | handled |= CSR_INT_BIT_RF_KILL; | 904 | handled |= CSR_INT_BIT_RF_KILL; |
@@ -1005,7 +1002,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
1005 | 1002 | ||
1006 | /* Re-enable all interrupts */ | 1003 | /* Re-enable all interrupts */ |
1007 | /* only Re-enable if disabled by irq */ | 1004 | /* only Re-enable if disabled by irq */ |
1008 | if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status)) | 1005 | if (test_bit(STATUS_INT_ENABLED, &trans->status)) |
1009 | iwl_enable_interrupts(trans); | 1006 | iwl_enable_interrupts(trans); |
1010 | /* Re-enable RF_KILL if it occurred */ | 1007 | /* Re-enable RF_KILL if it occurred */ |
1011 | else if (handled & CSR_INT_BIT_RF_KILL) | 1008 | else if (handled & CSR_INT_BIT_RF_KILL) |
@@ -1160,7 +1157,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) | |||
1160 | * the handler can be scheduled because of a previous | 1157 | * the handler can be scheduled because of a previous |
1161 | * interrupt. | 1158 | * interrupt. |
1162 | */ | 1159 | */ |
1163 | if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 1160 | if (test_bit(STATUS_INT_ENABLED, &trans->status) && |
1164 | !trans_pcie->inta) | 1161 | !trans_pcie->inta) |
1165 | iwl_enable_interrupts(trans); | 1162 | iwl_enable_interrupts(trans); |
1166 | return IRQ_NONE; | 1163 | return IRQ_NONE; |
@@ -1290,7 +1287,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) | |||
1290 | /* re-enable interrupts here since we don't have anything to service. | 1287 | /* re-enable interrupts here since we don't have anything to service. |
1291 | * only Re-enable if disabled by irq. | 1288 | * only Re-enable if disabled by irq. |
1292 | */ | 1289 | */ |
1293 | if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 1290 | if (test_bit(STATUS_INT_ENABLED, &trans->status) && |
1294 | !trans_pcie->inta) | 1291 | !trans_pcie->inta) |
1295 | iwl_enable_interrupts(trans); | 1292 | iwl_enable_interrupts(trans); |
1296 | 1293 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index cde9c16f6e4f..eecd38e3f15f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -150,7 +150,6 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) | |||
150 | */ | 150 | */ |
151 | static int iwl_pcie_apm_init(struct iwl_trans *trans) | 151 | static int iwl_pcie_apm_init(struct iwl_trans *trans) |
152 | { | 152 | { |
153 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
154 | int ret = 0; | 153 | int ret = 0; |
155 | IWL_DEBUG_INFO(trans, "Init card's basic functions\n"); | 154 | IWL_DEBUG_INFO(trans, "Init card's basic functions\n"); |
156 | 155 | ||
@@ -223,7 +222,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) | |||
223 | /* Clear the interrupt in APMG if the NIC is in RFKILL */ | 222 | /* Clear the interrupt in APMG if the NIC is in RFKILL */ |
224 | iwl_write_prph(trans, APMG_RTC_INT_STT_REG, APMG_RTC_INT_STT_RFKILL); | 223 | iwl_write_prph(trans, APMG_RTC_INT_STT_REG, APMG_RTC_INT_STT_RFKILL); |
225 | 224 | ||
226 | set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); | 225 | set_bit(STATUS_DEVICE_ENABLED, &trans->status); |
227 | 226 | ||
228 | out: | 227 | out: |
229 | return ret; | 228 | return ret; |
@@ -249,10 +248,9 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans) | |||
249 | 248 | ||
250 | static void iwl_pcie_apm_stop(struct iwl_trans *trans) | 249 | static void iwl_pcie_apm_stop(struct iwl_trans *trans) |
251 | { | 250 | { |
252 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
253 | IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n"); | 251 | IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n"); |
254 | 252 | ||
255 | clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); | 253 | clear_bit(STATUS_DEVICE_ENABLED, &trans->status); |
256 | 254 | ||
257 | /* Stop device's DMA activity */ | 255 | /* Stop device's DMA activity */ |
258 | iwl_pcie_apm_stop_master(trans); | 256 | iwl_pcie_apm_stop_master(trans); |
@@ -582,7 +580,6 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | |||
582 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | 580 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, |
583 | const struct fw_img *fw, bool run_in_rfkill) | 581 | const struct fw_img *fw, bool run_in_rfkill) |
584 | { | 582 | { |
585 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
586 | int ret; | 583 | int ret; |
587 | bool hw_rfkill; | 584 | bool hw_rfkill; |
588 | 585 | ||
@@ -592,16 +589,14 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
592 | return -EIO; | 589 | return -EIO; |
593 | } | 590 | } |
594 | 591 | ||
595 | clear_bit(STATUS_FW_ERROR, &trans_pcie->status); | ||
596 | |||
597 | iwl_enable_rfkill_int(trans); | 592 | iwl_enable_rfkill_int(trans); |
598 | 593 | ||
599 | /* If platform's RF_KILL switch is NOT set to KILL */ | 594 | /* If platform's RF_KILL switch is NOT set to KILL */ |
600 | hw_rfkill = iwl_is_rfkill_set(trans); | 595 | hw_rfkill = iwl_is_rfkill_set(trans); |
601 | if (hw_rfkill) | 596 | if (hw_rfkill) |
602 | set_bit(STATUS_RFKILL, &trans_pcie->status); | 597 | set_bit(STATUS_RFKILL, &trans->status); |
603 | else | 598 | else |
604 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | 599 | clear_bit(STATUS_RFKILL, &trans->status); |
605 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 600 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
606 | if (hw_rfkill && !run_in_rfkill) | 601 | if (hw_rfkill && !run_in_rfkill) |
607 | return -ERFKILL; | 602 | return -ERFKILL; |
@@ -641,6 +636,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
641 | { | 636 | { |
642 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 637 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
643 | unsigned long flags; | 638 | unsigned long flags; |
639 | bool hw_rfkill; | ||
644 | 640 | ||
645 | /* tell the device to stop sending interrupts */ | 641 | /* tell the device to stop sending interrupts */ |
646 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 642 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
@@ -657,7 +653,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
657 | * restart. So don't process again if the device is | 653 | * restart. So don't process again if the device is |
658 | * already dead. | 654 | * already dead. |
659 | */ | 655 | */ |
660 | if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { | 656 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) { |
661 | iwl_pcie_tx_stop(trans); | 657 | iwl_pcie_tx_stop(trans); |
662 | iwl_pcie_rx_stop(trans); | 658 | iwl_pcie_rx_stop(trans); |
663 | 659 | ||
@@ -681,17 +677,34 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
681 | iwl_disable_interrupts(trans); | 677 | iwl_disable_interrupts(trans); |
682 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 678 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
683 | 679 | ||
684 | iwl_enable_rfkill_int(trans); | ||
685 | |||
686 | /* stop and reset the on-board processor */ | 680 | /* stop and reset the on-board processor */ |
687 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 681 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
688 | 682 | ||
689 | /* clear all status bits */ | 683 | /* clear all status bits */ |
690 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 684 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
691 | clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); | 685 | clear_bit(STATUS_INT_ENABLED, &trans->status); |
692 | clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); | 686 | clear_bit(STATUS_DEVICE_ENABLED, &trans->status); |
693 | clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status); | 687 | clear_bit(STATUS_TPOWER_PMI, &trans->status); |
694 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | 688 | clear_bit(STATUS_RFKILL, &trans->status); |
689 | |||
690 | /* | ||
691 | * Even if we stop the HW, we still want the RF kill | ||
692 | * interrupt | ||
693 | */ | ||
694 | iwl_enable_rfkill_int(trans); | ||
695 | |||
696 | /* | ||
697 | * Check again since the RF kill state may have changed while | ||
698 | * all the interrupts were disabled, in this case we couldn't | ||
699 | * receive the RF kill interrupt and update the state in the | ||
700 | * op_mode. | ||
701 | */ | ||
702 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
703 | if (hw_rfkill) | ||
704 | set_bit(STATUS_RFKILL, &trans->status); | ||
705 | else | ||
706 | clear_bit(STATUS_RFKILL, &trans->status); | ||
707 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | ||
695 | } | 708 | } |
696 | 709 | ||
697 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) | 710 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) |
@@ -776,7 +789,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
776 | 789 | ||
777 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | 790 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) |
778 | { | 791 | { |
779 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
780 | bool hw_rfkill; | 792 | bool hw_rfkill; |
781 | int err; | 793 | int err; |
782 | 794 | ||
@@ -798,21 +810,20 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | |||
798 | 810 | ||
799 | hw_rfkill = iwl_is_rfkill_set(trans); | 811 | hw_rfkill = iwl_is_rfkill_set(trans); |
800 | if (hw_rfkill) | 812 | if (hw_rfkill) |
801 | set_bit(STATUS_RFKILL, &trans_pcie->status); | 813 | set_bit(STATUS_RFKILL, &trans->status); |
802 | else | 814 | else |
803 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | 815 | clear_bit(STATUS_RFKILL, &trans->status); |
804 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 816 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
805 | 817 | ||
806 | return 0; | 818 | return 0; |
807 | } | 819 | } |
808 | 820 | ||
809 | static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | 821 | static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans) |
810 | bool op_mode_leaving) | ||
811 | { | 822 | { |
812 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 823 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
813 | bool hw_rfkill; | ||
814 | unsigned long flags; | 824 | unsigned long flags; |
815 | 825 | ||
826 | /* disable interrupts - don't enable HW RF kill interrupt */ | ||
816 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 827 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
817 | iwl_disable_interrupts(trans); | 828 | iwl_disable_interrupts(trans); |
818 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 829 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
@@ -824,27 +835,6 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | |||
824 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 835 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
825 | 836 | ||
826 | iwl_pcie_disable_ict(trans); | 837 | iwl_pcie_disable_ict(trans); |
827 | |||
828 | if (!op_mode_leaving) { | ||
829 | /* | ||
830 | * Even if we stop the HW, we still want the RF kill | ||
831 | * interrupt | ||
832 | */ | ||
833 | iwl_enable_rfkill_int(trans); | ||
834 | |||
835 | /* | ||
836 | * Check again since the RF kill state may have changed while | ||
837 | * all the interrupts were disabled, in this case we couldn't | ||
838 | * receive the RF kill interrupt and update the state in the | ||
839 | * op_mode. | ||
840 | */ | ||
841 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
842 | if (hw_rfkill) | ||
843 | set_bit(STATUS_RFKILL, &trans_pcie->status); | ||
844 | else | ||
845 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||
846 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | ||
847 | } | ||
848 | } | 838 | } |
849 | 839 | ||
850 | static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) | 840 | static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) |
@@ -928,12 +918,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
928 | 918 | ||
929 | static void iwl_trans_pcie_set_pmi(struct iwl_trans *trans, bool state) | 919 | static void iwl_trans_pcie_set_pmi(struct iwl_trans *trans, bool state) |
930 | { | 920 | { |
931 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
932 | |||
933 | if (state) | 921 | if (state) |
934 | set_bit(STATUS_TPOWER_PMI, &trans_pcie->status); | 922 | set_bit(STATUS_TPOWER_PMI, &trans->status); |
935 | else | 923 | else |
936 | clear_bit(STATUS_TPOWER_PMI, &trans_pcie->status); | 924 | clear_bit(STATUS_TPOWER_PMI, &trans->status); |
937 | } | 925 | } |
938 | 926 | ||
939 | static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, | 927 | static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, |
@@ -1457,7 +1445,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | |||
1457 | 1445 | ||
1458 | static const struct iwl_trans_ops trans_ops_pcie = { | 1446 | static const struct iwl_trans_ops trans_ops_pcie = { |
1459 | .start_hw = iwl_trans_pcie_start_hw, | 1447 | .start_hw = iwl_trans_pcie_start_hw, |
1460 | .stop_hw = iwl_trans_pcie_stop_hw, | 1448 | .op_mode_leave = iwl_trans_pcie_op_mode_leave, |
1461 | .fw_alive = iwl_trans_pcie_fw_alive, | 1449 | .fw_alive = iwl_trans_pcie_fw_alive, |
1462 | .start_fw = iwl_trans_pcie_start_fw, | 1450 | .start_fw = iwl_trans_pcie_start_fw, |
1463 | .stop_device = iwl_trans_pcie_stop_device, | 1451 | .stop_device = iwl_trans_pcie_stop_device, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index a4ef5cc11100..8df24787c141 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
207 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | 207 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, |
208 | le32_to_cpu(txq->scratchbufs[i].scratch)); | 208 | le32_to_cpu(txq->scratchbufs[i].scratch)); |
209 | 209 | ||
210 | iwl_nic_error(trans); | 210 | iwl_trans_fw_error(trans); |
211 | } | 211 | } |
212 | 212 | ||
213 | /* | 213 | /* |
@@ -300,10 +300,8 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) | |||
300 | iwl_write32(trans, HBUS_TARG_WRPTR, | 300 | iwl_write32(trans, HBUS_TARG_WRPTR, |
301 | txq->q.write_ptr | (txq_id << 8)); | 301 | txq->q.write_ptr | (txq_id << 8)); |
302 | } else { | 302 | } else { |
303 | struct iwl_trans_pcie *trans_pcie = | ||
304 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
305 | /* if we're trying to save power */ | 303 | /* if we're trying to save power */ |
306 | if (test_bit(STATUS_TPOWER_PMI, &trans_pcie->status)) { | 304 | if (test_bit(STATUS_TPOWER_PMI, &trans->status)) { |
307 | /* wake up nic if it's powered down ... | 305 | /* wake up nic if it's powered down ... |
308 | * uCode will wake up, and interrupt us again, so next | 306 | * uCode will wake up, and interrupt us again, so next |
309 | * time we'll skip this part. */ | 307 | * time we'll skip this part. */ |
@@ -1023,7 +1021,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
1023 | if (nfreed++ > 0) { | 1021 | if (nfreed++ > 0) { |
1024 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", | 1022 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", |
1025 | idx, q->write_ptr, q->read_ptr); | 1023 | idx, q->write_ptr, q->read_ptr); |
1026 | iwl_nic_error(trans); | 1024 | iwl_trans_fw_error(trans); |
1027 | } | 1025 | } |
1028 | } | 1026 | } |
1029 | 1027 | ||
@@ -1449,12 +1447,12 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | |||
1449 | iwl_pcie_cmdq_reclaim(trans, txq_id, index); | 1447 | iwl_pcie_cmdq_reclaim(trans, txq_id, index); |
1450 | 1448 | ||
1451 | if (!(meta->flags & CMD_ASYNC)) { | 1449 | if (!(meta->flags & CMD_ASYNC)) { |
1452 | if (!test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { | 1450 | if (!test_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status)) { |
1453 | IWL_WARN(trans, | 1451 | IWL_WARN(trans, |
1454 | "HCMD_ACTIVE already clear for command %s\n", | 1452 | "HCMD_ACTIVE already clear for command %s\n", |
1455 | get_cmd_string(trans_pcie, cmd->hdr.cmd)); | 1453 | get_cmd_string(trans_pcie, cmd->hdr.cmd)); |
1456 | } | 1454 | } |
1457 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 1455 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
1458 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", | 1456 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", |
1459 | get_cmd_string(trans_pcie, cmd->hdr.cmd)); | 1457 | get_cmd_string(trans_pcie, cmd->hdr.cmd)); |
1460 | wake_up(&trans_pcie->wait_command_queue); | 1458 | wake_up(&trans_pcie->wait_command_queue); |
@@ -1499,8 +1497,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1499 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 1497 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
1500 | get_cmd_string(trans_pcie, cmd->id)); | 1498 | get_cmd_string(trans_pcie, cmd->id)); |
1501 | 1499 | ||
1502 | if (WARN(test_and_set_bit(STATUS_HCMD_ACTIVE, | 1500 | if (WARN(test_and_set_bit(STATUS_SYNC_HCMD_ACTIVE, |
1503 | &trans_pcie->status), | 1501 | &trans->status), |
1504 | "Command %s: a command is already active!\n", | 1502 | "Command %s: a command is already active!\n", |
1505 | get_cmd_string(trans_pcie, cmd->id))) | 1503 | get_cmd_string(trans_pcie, cmd->id))) |
1506 | return -EIO; | 1504 | return -EIO; |
@@ -1511,7 +1509,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1511 | cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd); | 1509 | cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd); |
1512 | if (cmd_idx < 0) { | 1510 | if (cmd_idx < 0) { |
1513 | ret = cmd_idx; | 1511 | ret = cmd_idx; |
1514 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 1512 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
1515 | IWL_ERR(trans, | 1513 | IWL_ERR(trans, |
1516 | "Error sending %s: enqueue_hcmd failed: %d\n", | 1514 | "Error sending %s: enqueue_hcmd failed: %d\n", |
1517 | get_cmd_string(trans_pcie, cmd->id), ret); | 1515 | get_cmd_string(trans_pcie, cmd->id), ret); |
@@ -1523,8 +1521,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1523 | 1521 | ||
1524 | timeout -= COMMAND_POKE_TIMEOUT; | 1522 | timeout -= COMMAND_POKE_TIMEOUT; |
1525 | ret = wait_event_timeout(trans_pcie->wait_command_queue, | 1523 | ret = wait_event_timeout(trans_pcie->wait_command_queue, |
1526 | !test_bit(STATUS_HCMD_ACTIVE, | 1524 | !test_bit(STATUS_SYNC_HCMD_ACTIVE, |
1527 | &trans_pcie->status), | 1525 | &trans->status), |
1528 | COMMAND_POKE_TIMEOUT); | 1526 | COMMAND_POKE_TIMEOUT); |
1529 | if (ret) | 1527 | if (ret) |
1530 | break; | 1528 | break; |
@@ -1552,17 +1550,17 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1552 | IWL_ERR(trans, "Current CMD queue read_ptr %d write_ptr %d\n", | 1550 | IWL_ERR(trans, "Current CMD queue read_ptr %d write_ptr %d\n", |
1553 | q->read_ptr, q->write_ptr); | 1551 | q->read_ptr, q->write_ptr); |
1554 | 1552 | ||
1555 | clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status); | 1553 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
1556 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", | 1554 | IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", |
1557 | get_cmd_string(trans_pcie, cmd->id)); | 1555 | get_cmd_string(trans_pcie, cmd->id)); |
1558 | ret = -ETIMEDOUT; | 1556 | ret = -ETIMEDOUT; |
1559 | 1557 | ||
1560 | iwl_nic_error(trans); | 1558 | iwl_trans_fw_error(trans); |
1561 | 1559 | ||
1562 | goto cancel; | 1560 | goto cancel; |
1563 | } | 1561 | } |
1564 | 1562 | ||
1565 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) { | 1563 | if (test_bit(STATUS_FW_ERROR, &trans->status)) { |
1566 | IWL_ERR(trans, "FW error in SYNC CMD %s\n", | 1564 | IWL_ERR(trans, "FW error in SYNC CMD %s\n", |
1567 | get_cmd_string(trans_pcie, cmd->id)); | 1565 | get_cmd_string(trans_pcie, cmd->id)); |
1568 | dump_stack(); | 1566 | dump_stack(); |
@@ -1571,7 +1569,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1571 | } | 1569 | } |
1572 | 1570 | ||
1573 | if (!(cmd->flags & CMD_SEND_IN_RFKILL) && | 1571 | if (!(cmd->flags & CMD_SEND_IN_RFKILL) && |
1574 | test_bit(STATUS_RFKILL, &trans_pcie->status)) { | 1572 | test_bit(STATUS_RFKILL, &trans->status)) { |
1575 | IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n"); | 1573 | IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n"); |
1576 | ret = -ERFKILL; | 1574 | ret = -ERFKILL; |
1577 | goto cancel; | 1575 | goto cancel; |
@@ -1608,13 +1606,8 @@ cancel: | |||
1608 | 1606 | ||
1609 | int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | 1607 | int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) |
1610 | { | 1608 | { |
1611 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1612 | |||
1613 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) | ||
1614 | return -EIO; | ||
1615 | |||
1616 | if (!(cmd->flags & CMD_SEND_IN_RFKILL) && | 1609 | if (!(cmd->flags & CMD_SEND_IN_RFKILL) && |
1617 | test_bit(STATUS_RFKILL, &trans_pcie->status)) { | 1610 | test_bit(STATUS_RFKILL, &trans->status)) { |
1618 | IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", | 1611 | IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", |
1619 | cmd->id); | 1612 | cmd->id); |
1620 | return -ERFKILL; | 1613 | return -ERFKILL; |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 4d23647faef0..b994679abce0 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -538,23 +538,40 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy, | |||
538 | struct regulatory_request *request) | 538 | struct regulatory_request *request) |
539 | { | 539 | { |
540 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | 540 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
541 | struct mwifiex_private *priv = mwifiex_get_priv(adapter, | ||
542 | MWIFIEX_BSS_ROLE_ANY); | ||
541 | 543 | ||
542 | wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n", | 544 | wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n", |
543 | request->alpha2[0], request->alpha2[1]); | 545 | request->alpha2[0], request->alpha2[1]); |
544 | 546 | ||
545 | memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2)); | ||
546 | |||
547 | switch (request->initiator) { | 547 | switch (request->initiator) { |
548 | case NL80211_REGDOM_SET_BY_DRIVER: | 548 | case NL80211_REGDOM_SET_BY_DRIVER: |
549 | case NL80211_REGDOM_SET_BY_CORE: | 549 | case NL80211_REGDOM_SET_BY_CORE: |
550 | case NL80211_REGDOM_SET_BY_USER: | 550 | case NL80211_REGDOM_SET_BY_USER: |
551 | break; | ||
552 | /* Todo: apply driver specific changes in channel flags based | ||
553 | on the request initiator if necessary. */ | ||
554 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 551 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
555 | break; | 552 | break; |
553 | default: | ||
554 | wiphy_err(wiphy, "unknown regdom initiator: %d\n", | ||
555 | request->initiator); | ||
556 | return; | ||
557 | } | ||
558 | |||
559 | /* Don't send world or same regdom info to firmware */ | ||
560 | if (strncmp(request->alpha2, "00", 2) && | ||
561 | strncmp(request->alpha2, adapter->country_code, | ||
562 | sizeof(request->alpha2))) { | ||
563 | memcpy(adapter->country_code, request->alpha2, | ||
564 | sizeof(request->alpha2)); | ||
565 | mwifiex_send_domain_info_cmd_fw(wiphy); | ||
566 | |||
567 | if (adapter->dt_node) { | ||
568 | char txpwr[] = {"marvell,00_txpwrlimit"}; | ||
569 | |||
570 | memcpy(&txpwr[8], adapter->country_code, 2); | ||
571 | mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, | ||
572 | txpwr); | ||
573 | } | ||
556 | } | 574 | } |
557 | mwifiex_send_domain_info_cmd_fw(wiphy); | ||
558 | } | 575 | } |
559 | 576 | ||
560 | /* | 577 | /* |
@@ -1171,10 +1188,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1171 | else | 1188 | else |
1172 | bitmap_rates[1] = mask->control[band].legacy; | 1189 | bitmap_rates[1] = mask->control[band].legacy; |
1173 | 1190 | ||
1174 | /* Fill MCS rates */ | 1191 | /* Fill HT MCS rates */ |
1175 | bitmap_rates[2] = mask->control[band].mcs[0]; | 1192 | bitmap_rates[2] = mask->control[band].ht_mcs[0]; |
1176 | if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) | 1193 | if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) |
1177 | bitmap_rates[2] |= mask->control[band].mcs[1] << 8; | 1194 | bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; |
1178 | 1195 | ||
1179 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, | 1196 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, |
1180 | HostCmd_ACT_GEN_SET, 0, bitmap_rates); | 1197 | HostCmd_ACT_GEN_SET, 0, bitmap_rates); |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 8fcb500fa09b..4cee6ceb7e9e 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -468,8 +468,6 @@ enum P2P_MODES { | |||
468 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | 468 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) |
469 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | 469 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) |
470 | 470 | ||
471 | #define CFG_DATA_TYPE_CAL 2 | ||
472 | |||
473 | struct mwifiex_ie_types_header { | 471 | struct mwifiex_ie_types_header { |
474 | __le16 type; | 472 | __le16 type; |
475 | __le16 len; | 473 | __le16 len; |
@@ -1592,12 +1590,6 @@ struct mwifiex_ie_list { | |||
1592 | struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX]; | 1590 | struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX]; |
1593 | } __packed; | 1591 | } __packed; |
1594 | 1592 | ||
1595 | struct host_cmd_ds_802_11_cfg_data { | ||
1596 | __le16 action; | ||
1597 | __le16 type; | ||
1598 | __le16 data_len; | ||
1599 | } __packed; | ||
1600 | |||
1601 | struct coalesce_filt_field_param { | 1593 | struct coalesce_filt_field_param { |
1602 | u8 operation; | 1594 | u8 operation; |
1603 | u8 operand_len; | 1595 | u8 operand_len; |
@@ -1678,7 +1670,6 @@ struct host_cmd_ds_command { | |||
1678 | struct host_cmd_ds_sys_config uap_sys_config; | 1670 | struct host_cmd_ds_sys_config uap_sys_config; |
1679 | struct host_cmd_ds_sta_deauth sta_deauth; | 1671 | struct host_cmd_ds_sta_deauth sta_deauth; |
1680 | struct host_cmd_11ac_vht_cfg vht_cfg; | 1672 | struct host_cmd_11ac_vht_cfg vht_cfg; |
1681 | struct host_cmd_ds_802_11_cfg_data cfg_data; | ||
1682 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; | 1673 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; |
1683 | } params; | 1674 | } params; |
1684 | } __packed; | 1675 | } __packed; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index dc34457557f3..ab3416449bfd 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <net/lib80211.h> | 32 | #include <net/lib80211.h> |
33 | #include <linux/firmware.h> | 33 | #include <linux/firmware.h> |
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/of.h> | ||
35 | 36 | ||
36 | #include "decl.h" | 37 | #include "decl.h" |
37 | #include "ioctl.h" | 38 | #include "ioctl.h" |
@@ -739,6 +740,7 @@ struct mwifiex_adapter { | |||
739 | u8 scan_delay_cnt; | 740 | u8 scan_delay_cnt; |
740 | u8 empty_tx_q_cnt; | 741 | u8 empty_tx_q_cnt; |
741 | const struct firmware *cal_data; | 742 | const struct firmware *cal_data; |
743 | struct device_node *dt_node; | ||
742 | 744 | ||
743 | /* 11AC */ | 745 | /* 11AC */ |
744 | u32 is_hw_11ac_capable; | 746 | u32 is_hw_11ac_capable; |
@@ -1151,6 +1153,8 @@ void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, | |||
1151 | void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, | 1153 | void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, |
1152 | struct mwifiex_bssdescriptor *bss_desc); | 1154 | struct mwifiex_bssdescriptor *bss_desc); |
1153 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); | 1155 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); |
1156 | int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, | ||
1157 | struct device_node *node, const char *prefix); | ||
1154 | 1158 | ||
1155 | extern const struct ethtool_ops mwifiex_ethtool_ops; | 1159 | extern const struct ethtool_ops mwifiex_ethtool_ops; |
1156 | 1160 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 1efa43ec1c6e..9c2404cd755f 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -1156,30 +1156,61 @@ static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst) | |||
1156 | return d - dst; | 1156 | return d - dst; |
1157 | } | 1157 | } |
1158 | 1158 | ||
1159 | int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, | ||
1160 | struct device_node *node, const char *prefix) | ||
1161 | { | ||
1162 | #ifdef CONFIG_OF | ||
1163 | struct property *prop; | ||
1164 | size_t len = strlen(prefix); | ||
1165 | int ret; | ||
1166 | |||
1167 | /* look for all matching property names */ | ||
1168 | for_each_property_of_node(node, prop) { | ||
1169 | if (len > strlen(prop->name) || | ||
1170 | strncmp(prop->name, prefix, len)) | ||
1171 | continue; | ||
1172 | |||
1173 | /* property header is 6 bytes */ | ||
1174 | if (prop && prop->value && prop->length > 6) { | ||
1175 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, | ||
1176 | HostCmd_ACT_GEN_SET, 0, | ||
1177 | prop); | ||
1178 | if (ret) | ||
1179 | return ret; | ||
1180 | } | ||
1181 | } | ||
1182 | #endif | ||
1183 | return 0; | ||
1184 | } | ||
1185 | |||
1159 | /* This function prepares command of set_cfg_data. */ | 1186 | /* This function prepares command of set_cfg_data. */ |
1160 | static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, | 1187 | static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, |
1161 | struct host_cmd_ds_command *cmd, | 1188 | struct host_cmd_ds_command *cmd, void *data_buf) |
1162 | u16 cmd_action) | ||
1163 | { | 1189 | { |
1164 | struct host_cmd_ds_802_11_cfg_data *cfg_data = &cmd->params.cfg_data; | ||
1165 | struct mwifiex_adapter *adapter = priv->adapter; | 1190 | struct mwifiex_adapter *adapter = priv->adapter; |
1166 | u32 len, cal_data_offset; | 1191 | struct property *prop = data_buf; |
1167 | u8 *tmp_cmd = (u8 *)cmd; | 1192 | u32 len; |
1193 | u8 *data = (u8 *)cmd + S_DS_GEN; | ||
1194 | int ret; | ||
1168 | 1195 | ||
1169 | cal_data_offset = S_DS_GEN + sizeof(*cfg_data); | 1196 | if (prop) { |
1170 | if ((adapter->cal_data->data) && (adapter->cal_data->size > 0)) | 1197 | len = prop->length; |
1198 | ret = of_property_read_u8_array(adapter->dt_node, prop->name, | ||
1199 | data, len); | ||
1200 | if (ret) | ||
1201 | return ret; | ||
1202 | dev_dbg(adapter->dev, | ||
1203 | "download cfg_data from device tree: %s\n", prop->name); | ||
1204 | } else if (adapter->cal_data->data && adapter->cal_data->size > 0) { | ||
1171 | len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data, | 1205 | len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data, |
1172 | adapter->cal_data->size, | 1206 | adapter->cal_data->size, data); |
1173 | (u8 *)(tmp_cmd + cal_data_offset)); | 1207 | dev_dbg(adapter->dev, "download cfg_data from config file\n"); |
1174 | else | 1208 | } else { |
1175 | return -1; | 1209 | return -1; |
1176 | 1210 | } | |
1177 | cfg_data->action = cpu_to_le16(cmd_action); | ||
1178 | cfg_data->type = cpu_to_le16(CFG_DATA_TYPE_CAL); | ||
1179 | cfg_data->data_len = cpu_to_le16(len); | ||
1180 | 1211 | ||
1181 | cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); | 1212 | cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); |
1182 | cmd->size = cpu_to_le16(S_DS_GEN + sizeof(*cfg_data) + len); | 1213 | cmd->size = cpu_to_le16(S_DS_GEN + len); |
1183 | 1214 | ||
1184 | return 0; | 1215 | return 0; |
1185 | } | 1216 | } |
@@ -1267,7 +1298,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1267 | ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); | 1298 | ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); |
1268 | break; | 1299 | break; |
1269 | case HostCmd_CMD_CFG_DATA: | 1300 | case HostCmd_CMD_CFG_DATA: |
1270 | ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, cmd_action); | 1301 | ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, data_buf); |
1271 | break; | 1302 | break; |
1272 | case HostCmd_CMD_MAC_CONTROL: | 1303 | case HostCmd_CMD_MAC_CONTROL: |
1273 | ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, | 1304 | ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, |
@@ -1527,7 +1558,19 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1527 | if (ret) | 1558 | if (ret) |
1528 | return -1; | 1559 | return -1; |
1529 | 1560 | ||
1530 | /* Download calibration data to firmware */ | 1561 | /* Download calibration data to firmware. |
1562 | * The cal-data can be read from device tree and/or | ||
1563 | * a configuration file and downloaded to firmware. | ||
1564 | */ | ||
1565 | adapter->dt_node = | ||
1566 | of_find_node_by_name(NULL, "marvell_cfgdata"); | ||
1567 | if (adapter->dt_node) { | ||
1568 | ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, | ||
1569 | "marvell,caldata"); | ||
1570 | if (ret) | ||
1571 | return -1; | ||
1572 | } | ||
1573 | |||
1531 | if (adapter->cal_data) { | 1574 | if (adapter->cal_data) { |
1532 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, | 1575 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, |
1533 | HostCmd_ACT_GEN_SET, 0, NULL); | 1576 | HostCmd_ACT_GEN_SET, 0, NULL); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index a09398fe9e2a..3edc92fad319 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -205,6 +205,14 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
205 | return 0; | 205 | return 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { | ||
209 | rcu_read_unlock(); | ||
210 | wiphy_dbg(priv->wdev->wiphy, | ||
211 | "11D: skip setting domain info in FW\n"); | ||
212 | return 0; | ||
213 | } | ||
214 | memcpy(priv->adapter->country_code, &country_ie[2], 2); | ||
215 | |||
208 | domain_info->country_code[0] = country_ie[2]; | 216 | domain_info->country_code[0] = country_ie[2]; |
209 | domain_info->country_code[1] = country_ie[3]; | 217 | domain_info->country_code[1] = country_ie[3]; |
210 | domain_info->country_code[2] = ' '; | 218 | domain_info->country_code[2] = ' '; |
@@ -226,6 +234,13 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
226 | return -1; | 234 | return -1; |
227 | } | 235 | } |
228 | 236 | ||
237 | if (priv->adapter->dt_node) { | ||
238 | char txpwr[] = {"marvell,00_txpwrlimit"}; | ||
239 | |||
240 | memcpy(&txpwr[8], priv->adapter->country_code, 2); | ||
241 | mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr); | ||
242 | } | ||
243 | |||
229 | return 0; | 244 | return 0; |
230 | } | 245 | } |
231 | 246 | ||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e9abc7b536cd..80a10212b1b9 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -747,6 +747,8 @@ enum station_parameters_apply_mask { | |||
747 | * @supported_channels_len: number of supported channels | 747 | * @supported_channels_len: number of supported channels |
748 | * @supported_oper_classes: supported oper classes in IEEE 802.11 format | 748 | * @supported_oper_classes: supported oper classes in IEEE 802.11 format |
749 | * @supported_oper_classes_len: number of supported operating classes | 749 | * @supported_oper_classes_len: number of supported operating classes |
750 | * @opmode_notif: operating mode field from Operating Mode Notification | ||
751 | * @opmode_notif_used: information if operating mode field is used | ||
750 | */ | 752 | */ |
751 | struct station_parameters { | 753 | struct station_parameters { |
752 | const u8 *supported_rates; | 754 | const u8 *supported_rates; |
@@ -770,6 +772,8 @@ struct station_parameters { | |||
770 | u8 supported_channels_len; | 772 | u8 supported_channels_len; |
771 | const u8 *supported_oper_classes; | 773 | const u8 *supported_oper_classes; |
772 | u8 supported_oper_classes_len; | 774 | u8 supported_oper_classes_len; |
775 | u8 opmode_notif; | ||
776 | bool opmode_notif_used; | ||
773 | }; | 777 | }; |
774 | 778 | ||
775 | /** | 779 | /** |
@@ -1762,7 +1766,8 @@ enum wiphy_params_flags { | |||
1762 | struct cfg80211_bitrate_mask { | 1766 | struct cfg80211_bitrate_mask { |
1763 | struct { | 1767 | struct { |
1764 | u32 legacy; | 1768 | u32 legacy; |
1765 | u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; | 1769 | u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN]; |
1770 | u16 vht_mcs[NL80211_VHT_NSS_MAX]; | ||
1766 | } control[IEEE80211_NUM_BANDS]; | 1771 | } control[IEEE80211_NUM_BANDS]; |
1767 | }; | 1772 | }; |
1768 | /** | 1773 | /** |
@@ -2676,6 +2681,34 @@ struct wiphy_coalesce_support { | |||
2676 | }; | 2681 | }; |
2677 | 2682 | ||
2678 | /** | 2683 | /** |
2684 | * enum wiphy_vendor_command_flags - validation flags for vendor commands | ||
2685 | * @WIPHY_VENDOR_CMD_NEED_WDEV: vendor command requires wdev | ||
2686 | * @WIPHY_VENDOR_CMD_NEED_NETDEV: vendor command requires netdev | ||
2687 | * @WIPHY_VENDOR_CMD_NEED_RUNNING: interface/wdev must be up & running | ||
2688 | * (must be combined with %_WDEV or %_NETDEV) | ||
2689 | */ | ||
2690 | enum wiphy_vendor_command_flags { | ||
2691 | WIPHY_VENDOR_CMD_NEED_WDEV = BIT(0), | ||
2692 | WIPHY_VENDOR_CMD_NEED_NETDEV = BIT(1), | ||
2693 | WIPHY_VENDOR_CMD_NEED_RUNNING = BIT(2), | ||
2694 | }; | ||
2695 | |||
2696 | /** | ||
2697 | * struct wiphy_vendor_command - vendor command definition | ||
2698 | * @info: vendor command identifying information, as used in nl80211 | ||
2699 | * @flags: flags, see &enum wiphy_vendor_command_flags | ||
2700 | * @doit: callback for the operation, note that wdev is %NULL if the | ||
2701 | * flags didn't ask for a wdev and non-%NULL otherwise; the data | ||
2702 | * pointer may be %NULL if userspace provided no data at all | ||
2703 | */ | ||
2704 | struct wiphy_vendor_command { | ||
2705 | struct nl80211_vendor_cmd_info info; | ||
2706 | u32 flags; | ||
2707 | int (*doit)(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
2708 | const void *data, int data_len); | ||
2709 | }; | ||
2710 | |||
2711 | /** | ||
2679 | * struct wiphy - wireless hardware description | 2712 | * struct wiphy - wireless hardware description |
2680 | * @reg_notifier: the driver's regulatory notification callback, | 2713 | * @reg_notifier: the driver's regulatory notification callback, |
2681 | * note that if your driver uses wiphy_apply_custom_regulatory() | 2714 | * note that if your driver uses wiphy_apply_custom_regulatory() |
@@ -2788,6 +2821,9 @@ struct wiphy_coalesce_support { | |||
2788 | * @extended_capabilities_mask: mask of the valid values | 2821 | * @extended_capabilities_mask: mask of the valid values |
2789 | * @extended_capabilities_len: length of the extended capabilities | 2822 | * @extended_capabilities_len: length of the extended capabilities |
2790 | * @coalesce: packet coalescing support information | 2823 | * @coalesce: packet coalescing support information |
2824 | * | ||
2825 | * @vendor_commands: array of vendor commands supported by the hardware | ||
2826 | * @n_vendor_commands: number of vendor commands | ||
2791 | */ | 2827 | */ |
2792 | struct wiphy { | 2828 | struct wiphy { |
2793 | /* assign these fields before you register the wiphy */ | 2829 | /* assign these fields before you register the wiphy */ |
@@ -2899,6 +2935,9 @@ struct wiphy { | |||
2899 | 2935 | ||
2900 | const struct wiphy_coalesce_support *coalesce; | 2936 | const struct wiphy_coalesce_support *coalesce; |
2901 | 2937 | ||
2938 | const struct wiphy_vendor_command *vendor_commands; | ||
2939 | int n_vendor_commands; | ||
2940 | |||
2902 | char priv[0] __aligned(NETDEV_ALIGN); | 2941 | char priv[0] __aligned(NETDEV_ALIGN); |
2903 | }; | 2942 | }; |
2904 | 2943 | ||
@@ -3843,6 +3882,75 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy); | |||
3843 | */ | 3882 | */ |
3844 | void wiphy_rfkill_stop_polling(struct wiphy *wiphy); | 3883 | void wiphy_rfkill_stop_polling(struct wiphy *wiphy); |
3845 | 3884 | ||
3885 | /** | ||
3886 | * DOC: Vendor commands | ||
3887 | * | ||
3888 | * Occasionally, there are special protocol or firmware features that | ||
3889 | * can't be implemented very openly. For this and similar cases, the | ||
3890 | * vendor command functionality allows implementing the features with | ||
3891 | * (typically closed-source) userspace and firmware, using nl80211 as | ||
3892 | * the configuration mechanism. | ||
3893 | * | ||
3894 | * A driver supporting vendor commands must register them as an array | ||
3895 | * in struct wiphy, with handlers for each one, each command has an | ||
3896 | * OUI and sub command ID to identify it. | ||
3897 | * | ||
3898 | * Note that this feature should not be (ab)used to implement protocol | ||
3899 | * features that could openly be shared across drivers. In particular, | ||
3900 | * it must never be required to use vendor commands to implement any | ||
3901 | * "normal" functionality that higher-level userspace like connection | ||
3902 | * managers etc. need. | ||
3903 | */ | ||
3904 | |||
3905 | struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy, | ||
3906 | enum nl80211_commands cmd, | ||
3907 | enum nl80211_attrs attr, | ||
3908 | int approxlen); | ||
3909 | |||
3910 | /** | ||
3911 | * cfg80211_vendor_cmd_alloc_reply_skb - allocate vendor command reply | ||
3912 | * @wiphy: the wiphy | ||
3913 | * @approxlen: an upper bound of the length of the data that will | ||
3914 | * be put into the skb | ||
3915 | * | ||
3916 | * This function allocates and pre-fills an skb for a reply to | ||
3917 | * a vendor command. Since it is intended for a reply, calling | ||
3918 | * it outside of a vendor command's doit() operation is invalid. | ||
3919 | * | ||
3920 | * The returned skb is pre-filled with some identifying data in | ||
3921 | * a way that any data that is put into the skb (with skb_put(), | ||
3922 | * nla_put() or similar) will end up being within the | ||
3923 | * %NL80211_ATTR_VENDOR_DATA attribute, so all that needs to be done | ||
3924 | * with the skb is adding data for the corresponding userspace tool | ||
3925 | * which can then read that data out of the vendor data attribute. | ||
3926 | * You must not modify the skb in any other way. | ||
3927 | * | ||
3928 | * When done, call cfg80211_vendor_cmd_reply() with the skb and return | ||
3929 | * its error code as the result of the doit() operation. | ||
3930 | * | ||
3931 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. | ||
3932 | */ | ||
3933 | static inline struct sk_buff * | ||
3934 | cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int approxlen) | ||
3935 | { | ||
3936 | return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_VENDOR, | ||
3937 | NL80211_ATTR_VENDOR_DATA, approxlen); | ||
3938 | } | ||
3939 | |||
3940 | /** | ||
3941 | * cfg80211_vendor_cmd_reply - send the reply skb | ||
3942 | * @skb: The skb, must have been allocated with | ||
3943 | * cfg80211_vendor_cmd_alloc_reply_skb() | ||
3944 | * | ||
3945 | * Since calling this function will usually be the last thing | ||
3946 | * before returning from the vendor command doit() you should | ||
3947 | * return the error code. Note that this function consumes the | ||
3948 | * skb regardless of the return value. | ||
3949 | * | ||
3950 | * Return: An error code or 0 on success. | ||
3951 | */ | ||
3952 | int cfg80211_vendor_cmd_reply(struct sk_buff *skb); | ||
3953 | |||
3846 | #ifdef CONFIG_NL80211_TESTMODE | 3954 | #ifdef CONFIG_NL80211_TESTMODE |
3847 | /** | 3955 | /** |
3848 | * DOC: Test mode | 3956 | * DOC: Test mode |
@@ -3878,8 +3986,12 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy); | |||
3878 | * | 3986 | * |
3879 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. | 3987 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. |
3880 | */ | 3988 | */ |
3881 | struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, | 3989 | static inline struct sk_buff * |
3882 | int approxlen); | 3990 | cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, int approxlen) |
3991 | { | ||
3992 | return __cfg80211_alloc_reply_skb(wiphy, NL80211_CMD_TESTMODE, | ||
3993 | NL80211_ATTR_TESTDATA, approxlen); | ||
3994 | } | ||
3883 | 3995 | ||
3884 | /** | 3996 | /** |
3885 | * cfg80211_testmode_reply - send the reply skb | 3997 | * cfg80211_testmode_reply - send the reply skb |
@@ -3893,7 +4005,10 @@ struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, | |||
3893 | * | 4005 | * |
3894 | * Return: An error code or 0 on success. | 4006 | * Return: An error code or 0 on success. |
3895 | */ | 4007 | */ |
3896 | int cfg80211_testmode_reply(struct sk_buff *skb); | 4008 | static inline int cfg80211_testmode_reply(struct sk_buff *skb) |
4009 | { | ||
4010 | return cfg80211_vendor_cmd_reply(skb); | ||
4011 | } | ||
3897 | 4012 | ||
3898 | /** | 4013 | /** |
3899 | * cfg80211_testmode_alloc_event_skb - allocate testmode event | 4014 | * cfg80211_testmode_alloc_event_skb - allocate testmode event |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3cd408b326de..531785f5819e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1163,6 +1163,19 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | |||
1163 | } | 1163 | } |
1164 | 1164 | ||
1165 | /** | 1165 | /** |
1166 | * wdev_to_ieee80211_vif - return a vif struct from a wdev | ||
1167 | * @wdev: the wdev to get the vif for | ||
1168 | * | ||
1169 | * This can be used by mac80211 drivers with direct cfg80211 APIs | ||
1170 | * (like the vendor commands) that get a wdev. | ||
1171 | * | ||
1172 | * Note that this function may return %NULL if the given wdev isn't | ||
1173 | * associated with a vif that the driver knows about (e.g. monitor | ||
1174 | * or AP_VLAN interfaces.) | ||
1175 | */ | ||
1176 | struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev); | ||
1177 | |||
1178 | /** | ||
1166 | * enum ieee80211_key_flags - key flags | 1179 | * enum ieee80211_key_flags - key flags |
1167 | * | 1180 | * |
1168 | * These flags are used for communication about keys between the driver | 1181 | * These flags are used for communication about keys between the driver |
@@ -1600,6 +1613,9 @@ enum ieee80211_hw_flags { | |||
1600 | * @extra_tx_headroom: headroom to reserve in each transmit skb | 1613 | * @extra_tx_headroom: headroom to reserve in each transmit skb |
1601 | * for use by the driver (e.g. for transmit headers.) | 1614 | * for use by the driver (e.g. for transmit headers.) |
1602 | * | 1615 | * |
1616 | * @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb. | ||
1617 | * Can be used by drivers to add extra IEs. | ||
1618 | * | ||
1603 | * @channel_change_time: time (in microseconds) it takes to change channels. | 1619 | * @channel_change_time: time (in microseconds) it takes to change channels. |
1604 | * | 1620 | * |
1605 | * @max_signal: Maximum value for signal (rssi) in RX information, used | 1621 | * @max_signal: Maximum value for signal (rssi) in RX information, used |
@@ -1682,6 +1698,7 @@ struct ieee80211_hw { | |||
1682 | void *priv; | 1698 | void *priv; |
1683 | u32 flags; | 1699 | u32 flags; |
1684 | unsigned int extra_tx_headroom; | 1700 | unsigned int extra_tx_headroom; |
1701 | unsigned int extra_beacon_tailroom; | ||
1685 | int channel_change_time; | 1702 | int channel_change_time; |
1686 | int vif_data_size; | 1703 | int vif_data_size; |
1687 | int sta_data_size; | 1704 | int sta_data_size; |
@@ -2398,9 +2415,6 @@ enum ieee80211_roc_type { | |||
2398 | * See the section "Frame filtering" for more information. | 2415 | * See the section "Frame filtering" for more information. |
2399 | * This callback must be implemented and can sleep. | 2416 | * This callback must be implemented and can sleep. |
2400 | * | 2417 | * |
2401 | * @set_multicast_list: Configure the device's interface specific RX multicast | ||
2402 | * filter. This callback is optional. This callback must be atomic. | ||
2403 | * | ||
2404 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit | 2418 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit |
2405 | * must be set or cleared for a given STA. Must be atomic. | 2419 | * must be set or cleared for a given STA. Must be atomic. |
2406 | * | 2420 | * |
@@ -2485,7 +2499,11 @@ enum ieee80211_roc_type { | |||
2485 | * AP, IBSS/WDS/mesh peer etc. This callback can sleep. | 2499 | * AP, IBSS/WDS/mesh peer etc. This callback can sleep. |
2486 | * | 2500 | * |
2487 | * @sta_remove: Notifies low level driver about removal of an associated | 2501 | * @sta_remove: Notifies low level driver about removal of an associated |
2488 | * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep. | 2502 | * station, AP, IBSS/WDS/mesh peer etc. Note that after the callback |
2503 | * returns it isn't safe to use the pointer, not even RCU protected; | ||
2504 | * no RCU grace period is guaranteed between returning here and freeing | ||
2505 | * the station. See @sta_pre_rcu_remove if needed. | ||
2506 | * This callback can sleep. | ||
2489 | * | 2507 | * |
2490 | * @sta_add_debugfs: Drivers can use this callback to add debugfs files | 2508 | * @sta_add_debugfs: Drivers can use this callback to add debugfs files |
2491 | * when a station is added to mac80211's station list. This callback | 2509 | * when a station is added to mac80211's station list. This callback |
@@ -2504,7 +2522,17 @@ enum ieee80211_roc_type { | |||
2504 | * station (which can be the AP, a client, IBSS/WDS/mesh peer etc.) | 2522 | * station (which can be the AP, a client, IBSS/WDS/mesh peer etc.) |
2505 | * This callback is mutually exclusive with @sta_add/@sta_remove. | 2523 | * This callback is mutually exclusive with @sta_add/@sta_remove. |
2506 | * It must not fail for down transitions but may fail for transitions | 2524 | * It must not fail for down transitions but may fail for transitions |
2507 | * up the list of states. | 2525 | * up the list of states. Also note that after the callback returns it |
2526 | * isn't safe to use the pointer, not even RCU protected - no RCU grace | ||
2527 | * period is guaranteed between returning here and freeing the station. | ||
2528 | * See @sta_pre_rcu_remove if needed. | ||
2529 | * The callback can sleep. | ||
2530 | * | ||
2531 | * @sta_pre_rcu_remove: Notify driver about station removal before RCU | ||
2532 | * synchronisation. This is useful if a driver needs to have station | ||
2533 | * pointers protected using RCU, it can then use this call to clear | ||
2534 | * the pointers instead of waiting for an RCU grace period to elapse | ||
2535 | * in @sta_state. | ||
2508 | * The callback can sleep. | 2536 | * The callback can sleep. |
2509 | * | 2537 | * |
2510 | * @sta_rc_update: Notifies the driver of changes to the bitrates that can be | 2538 | * @sta_rc_update: Notifies the driver of changes to the bitrates that can be |
@@ -2764,10 +2792,6 @@ struct ieee80211_ops { | |||
2764 | unsigned int changed_flags, | 2792 | unsigned int changed_flags, |
2765 | unsigned int *total_flags, | 2793 | unsigned int *total_flags, |
2766 | u64 multicast); | 2794 | u64 multicast); |
2767 | void (*set_multicast_list)(struct ieee80211_hw *hw, | ||
2768 | struct ieee80211_vif *vif, bool allmulti, | ||
2769 | struct netdev_hw_addr_list *mc_list); | ||
2770 | |||
2771 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 2795 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
2772 | bool set); | 2796 | bool set); |
2773 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2797 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -2821,6 +2845,9 @@ struct ieee80211_ops { | |||
2821 | struct ieee80211_sta *sta, | 2845 | struct ieee80211_sta *sta, |
2822 | enum ieee80211_sta_state old_state, | 2846 | enum ieee80211_sta_state old_state, |
2823 | enum ieee80211_sta_state new_state); | 2847 | enum ieee80211_sta_state new_state); |
2848 | void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw, | ||
2849 | struct ieee80211_vif *vif, | ||
2850 | struct ieee80211_sta *sta); | ||
2824 | void (*sta_rc_update)(struct ieee80211_hw *hw, | 2851 | void (*sta_rc_update)(struct ieee80211_hw *hw, |
2825 | struct ieee80211_vif *vif, | 2852 | struct ieee80211_vif *vif, |
2826 | struct ieee80211_sta *sta, | 2853 | struct ieee80211_sta *sta, |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 129b7b087148..e1307909ecf1 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -693,6 +693,15 @@ | |||
693 | * other station that transmission must be blocked until the channel | 693 | * other station that transmission must be blocked until the channel |
694 | * switch is complete. | 694 | * switch is complete. |
695 | * | 695 | * |
696 | * @NL80211_CMD_VENDOR: Vendor-specified command/event. The command is specified | ||
697 | * by the %NL80211_ATTR_VENDOR_ID attribute and a sub-command in | ||
698 | * %NL80211_ATTR_VENDOR_SUBCMD. Parameter(s) can be transported in | ||
699 | * %NL80211_ATTR_VENDOR_DATA. | ||
700 | * For feature advertisement, the %NL80211_ATTR_VENDOR_DATA attribute is | ||
701 | * used in the wiphy data as a nested attribute containing descriptions | ||
702 | * (&struct nl80211_vendor_cmd_info) of the supported vendor commands. | ||
703 | * This may also be sent as an event with the same attributes. | ||
704 | * | ||
696 | * @NL80211_CMD_MAX: highest used command number | 705 | * @NL80211_CMD_MAX: highest used command number |
697 | * @__NL80211_CMD_AFTER_LAST: internal use | 706 | * @__NL80211_CMD_AFTER_LAST: internal use |
698 | */ | 707 | */ |
@@ -860,6 +869,8 @@ enum nl80211_commands { | |||
860 | 869 | ||
861 | NL80211_CMD_CHANNEL_SWITCH, | 870 | NL80211_CMD_CHANNEL_SWITCH, |
862 | 871 | ||
872 | NL80211_CMD_VENDOR, | ||
873 | |||
863 | /* add new commands above here */ | 874 | /* add new commands above here */ |
864 | 875 | ||
865 | /* used to define NL80211_CMD_MAX below */ | 876 | /* used to define NL80211_CMD_MAX below */ |
@@ -1520,6 +1531,16 @@ enum nl80211_commands { | |||
1520 | * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports | 1531 | * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports |
1521 | * 10 MHz channel bandwidth. | 1532 | * 10 MHz channel bandwidth. |
1522 | * | 1533 | * |
1534 | * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode | ||
1535 | * Notification Element based on association request when used with | ||
1536 | * %NL80211_CMD_NEW_STATION; u8 attribute. | ||
1537 | * | ||
1538 | * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if | ||
1539 | * %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet) | ||
1540 | * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command | ||
1541 | * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this | ||
1542 | * attribute is also used for vendor command feature advertisement | ||
1543 | * | ||
1523 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1544 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1524 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1545 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1525 | */ | 1546 | */ |
@@ -1839,6 +1860,12 @@ enum nl80211_attrs { | |||
1839 | NL80211_ATTR_SUPPORT_5_MHZ, | 1860 | NL80211_ATTR_SUPPORT_5_MHZ, |
1840 | NL80211_ATTR_SUPPORT_10_MHZ, | 1861 | NL80211_ATTR_SUPPORT_10_MHZ, |
1841 | 1862 | ||
1863 | NL80211_ATTR_OPMODE_NOTIF, | ||
1864 | |||
1865 | NL80211_ATTR_VENDOR_ID, | ||
1866 | NL80211_ATTR_VENDOR_SUBCMD, | ||
1867 | NL80211_ATTR_VENDOR_DATA, | ||
1868 | |||
1842 | /* add attributes here, update the policy in nl80211.c */ | 1869 | /* add attributes here, update the policy in nl80211.c */ |
1843 | 1870 | ||
1844 | __NL80211_ATTR_AFTER_LAST, | 1871 | __NL80211_ATTR_AFTER_LAST, |
@@ -3083,21 +3110,35 @@ enum nl80211_key_attributes { | |||
3083 | * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with | 3110 | * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with |
3084 | * 1 = 500 kbps) but without the IE length restriction (at most | 3111 | * 1 = 500 kbps) but without the IE length restriction (at most |
3085 | * %NL80211_MAX_SUPP_RATES in a single array). | 3112 | * %NL80211_MAX_SUPP_RATES in a single array). |
3086 | * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection | 3113 | * @NL80211_TXRATE_HT: HT (MCS) rates allowed for TX rate selection |
3087 | * in an array of MCS numbers. | 3114 | * in an array of MCS numbers. |
3115 | * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, | ||
3116 | * see &struct nl80211_txrate_vht | ||
3088 | * @__NL80211_TXRATE_AFTER_LAST: internal | 3117 | * @__NL80211_TXRATE_AFTER_LAST: internal |
3089 | * @NL80211_TXRATE_MAX: highest TX rate attribute | 3118 | * @NL80211_TXRATE_MAX: highest TX rate attribute |
3090 | */ | 3119 | */ |
3091 | enum nl80211_tx_rate_attributes { | 3120 | enum nl80211_tx_rate_attributes { |
3092 | __NL80211_TXRATE_INVALID, | 3121 | __NL80211_TXRATE_INVALID, |
3093 | NL80211_TXRATE_LEGACY, | 3122 | NL80211_TXRATE_LEGACY, |
3094 | NL80211_TXRATE_MCS, | 3123 | NL80211_TXRATE_HT, |
3124 | NL80211_TXRATE_VHT, | ||
3095 | 3125 | ||
3096 | /* keep last */ | 3126 | /* keep last */ |
3097 | __NL80211_TXRATE_AFTER_LAST, | 3127 | __NL80211_TXRATE_AFTER_LAST, |
3098 | NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 | 3128 | NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 |
3099 | }; | 3129 | }; |
3100 | 3130 | ||
3131 | #define NL80211_TXRATE_MCS NL80211_TXRATE_HT | ||
3132 | #define NL80211_VHT_NSS_MAX 8 | ||
3133 | |||
3134 | /** | ||
3135 | * struct nl80211_txrate_vht - VHT MCS/NSS txrate bitmap | ||
3136 | * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) | ||
3137 | */ | ||
3138 | struct nl80211_txrate_vht { | ||
3139 | __u16 mcs[NL80211_VHT_NSS_MAX]; | ||
3140 | }; | ||
3141 | |||
3101 | /** | 3142 | /** |
3102 | * enum nl80211_band - Frequency band | 3143 | * enum nl80211_band - Frequency band |
3103 | * @NL80211_BAND_2GHZ: 2.4 GHz ISM band | 3144 | * @NL80211_BAND_2GHZ: 2.4 GHz ISM band |
@@ -3959,4 +4000,24 @@ enum nl80211_rxmgmt_flags { | |||
3959 | NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, | 4000 | NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, |
3960 | }; | 4001 | }; |
3961 | 4002 | ||
4003 | /* | ||
4004 | * If this flag is unset, the lower 24 bits are an OUI, if set | ||
4005 | * a Linux nl80211 vendor ID is used (no such IDs are allocated | ||
4006 | * yet, so that's not valid so far) | ||
4007 | */ | ||
4008 | #define NL80211_VENDOR_ID_IS_LINUX 0x80000000 | ||
4009 | |||
4010 | /** | ||
4011 | * struct nl80211_vendor_cmd_info - vendor command data | ||
4012 | * @vendor_id: If the %NL80211_VENDOR_ID_IS_LINUX flag is clear, then the | ||
4013 | * value is a 24-bit OUI; if it is set then a separately allocated ID | ||
4014 | * may be used, but no such IDs are allocated yet. New IDs should be | ||
4015 | * added to this file when needed. | ||
4016 | * @subcmd: sub-command ID for the command | ||
4017 | */ | ||
4018 | struct nl80211_vendor_cmd_info { | ||
4019 | __u32 vendor_id; | ||
4020 | __u32 subcmd; | ||
4021 | }; | ||
4022 | |||
3962 | #endif /* __LINUX_NL80211_H */ | 4023 | #endif /* __LINUX_NL80211_H */ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f80e8c4c6bcd..ac185286842d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -301,9 +301,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
301 | if (!sta) | 301 | if (!sta) |
302 | goto out; | 302 | goto out; |
303 | 303 | ||
304 | if (pairwise) | 304 | if (pairwise && key_idx < NUM_DEFAULT_KEYS) |
305 | key = rcu_dereference(sta->ptk[key_idx]); | 305 | key = rcu_dereference(sta->ptk[key_idx]); |
306 | else if (key_idx < NUM_DEFAULT_KEYS) | 306 | else if (!pairwise && |
307 | key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | ||
307 | key = rcu_dereference(sta->gtk[key_idx]); | 308 | key = rcu_dereference(sta->gtk[key_idx]); |
308 | } else | 309 | } else |
309 | key = rcu_dereference(sdata->keys[key_idx]); | 310 | key = rcu_dereference(sdata->keys[key_idx]); |
@@ -873,8 +874,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
873 | return 0; | 874 | return 0; |
874 | } | 875 | } |
875 | 876 | ||
876 | int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | 877 | static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, |
877 | struct cfg80211_beacon_data *params) | 878 | struct cfg80211_beacon_data *params) |
878 | { | 879 | { |
879 | struct beacon_data *new, *old; | 880 | struct beacon_data *new, *old; |
880 | int new_head_len, new_tail_len; | 881 | int new_head_len, new_tail_len; |
@@ -1097,17 +1098,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1097 | if (old_probe_resp) | 1098 | if (old_probe_resp) |
1098 | kfree_rcu(old_probe_resp, rcu_head); | 1099 | kfree_rcu(old_probe_resp, rcu_head); |
1099 | 1100 | ||
1100 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1101 | __sta_info_flush(sdata, true); |
1101 | sta_info_flush_defer(vlan); | 1102 | ieee80211_free_keys(sdata, true); |
1102 | sta_info_flush_defer(sdata); | ||
1103 | synchronize_net(); | ||
1104 | rcu_barrier(); | ||
1105 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { | ||
1106 | sta_info_flush_cleanup(vlan); | ||
1107 | ieee80211_free_keys(vlan); | ||
1108 | } | ||
1109 | sta_info_flush_cleanup(sdata); | ||
1110 | ieee80211_free_keys(sdata); | ||
1111 | 1103 | ||
1112 | sdata->vif.bss_conf.enable_beacon = false; | 1104 | sdata->vif.bss_conf.enable_beacon = false; |
1113 | sdata->vif.bss_conf.ssid_len = 0; | 1105 | sdata->vif.bss_conf.ssid_len = 0; |
@@ -2587,8 +2579,8 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2587 | int j; | 2579 | int j; |
2588 | 2580 | ||
2589 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; | 2581 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
2590 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, | 2582 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].ht_mcs, |
2591 | sizeof(mask->control[i].mcs)); | 2583 | sizeof(mask->control[i].ht_mcs)); |
2592 | 2584 | ||
2593 | sdata->rc_has_mcs_mask[i] = false; | 2585 | sdata->rc_has_mcs_mask[i] = false; |
2594 | if (!sband) | 2586 | if (!sband) |
@@ -3047,8 +3039,8 @@ unlock: | |||
3047 | sdata_unlock(sdata); | 3039 | sdata_unlock(sdata); |
3048 | } | 3040 | } |
3049 | 3041 | ||
3050 | static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3042 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
3051 | struct cfg80211_csa_settings *params) | 3043 | struct cfg80211_csa_settings *params) |
3052 | { | 3044 | { |
3053 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3045 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3054 | struct ieee80211_local *local = sdata->local; | 3046 | struct ieee80211_local *local = sdata->local; |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 5d03c47c0a4c..ef8b385eff04 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -242,22 +242,6 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | |||
242 | return ret; | 242 | return ret; |
243 | } | 243 | } |
244 | 244 | ||
245 | static inline void drv_set_multicast_list(struct ieee80211_local *local, | ||
246 | struct ieee80211_sub_if_data *sdata, | ||
247 | struct netdev_hw_addr_list *mc_list) | ||
248 | { | ||
249 | bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
250 | |||
251 | trace_drv_set_multicast_list(local, sdata, mc_list->count); | ||
252 | |||
253 | check_sdata_in_driver(sdata); | ||
254 | |||
255 | if (local->ops->set_multicast_list) | ||
256 | local->ops->set_multicast_list(&local->hw, &sdata->vif, | ||
257 | allmulti, mc_list); | ||
258 | trace_drv_return_void(local); | ||
259 | } | ||
260 | |||
261 | static inline void drv_configure_filter(struct ieee80211_local *local, | 245 | static inline void drv_configure_filter(struct ieee80211_local *local, |
262 | unsigned int changed_flags, | 246 | unsigned int changed_flags, |
263 | unsigned int *total_flags, | 247 | unsigned int *total_flags, |
@@ -550,6 +534,22 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, | |||
550 | } | 534 | } |
551 | #endif | 535 | #endif |
552 | 536 | ||
537 | static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local, | ||
538 | struct ieee80211_sub_if_data *sdata, | ||
539 | struct sta_info *sta) | ||
540 | { | ||
541 | might_sleep(); | ||
542 | |||
543 | sdata = get_bss_sdata(sdata); | ||
544 | check_sdata_in_driver(sdata); | ||
545 | |||
546 | trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); | ||
547 | if (local->ops->sta_pre_rcu_remove) | ||
548 | local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif, | ||
549 | &sta->sta); | ||
550 | trace_drv_return_void(local); | ||
551 | } | ||
552 | |||
553 | static inline __must_check | 553 | static inline __must_check |
554 | int drv_sta_state(struct ieee80211_local *local, | 554 | int drv_sta_state(struct ieee80211_local *local, |
555 | struct ieee80211_sub_if_data *sdata, | 555 | struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 2eda7b13124a..d6ba841437b6 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -522,7 +522,7 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
522 | if (csa_settings) | 522 | if (csa_settings) |
523 | ieee80211_send_action_csa(sdata, csa_settings); | 523 | ieee80211_send_action_csa(sdata, csa_settings); |
524 | 524 | ||
525 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 525 | return BSS_CHANGED_BEACON; |
526 | out: | 526 | out: |
527 | return ret; | 527 | return ret; |
528 | } | 528 | } |
@@ -534,7 +534,8 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
534 | int err; | 534 | int err; |
535 | u16 capability; | 535 | u16 capability; |
536 | 536 | ||
537 | sdata_lock(sdata); | 537 | sdata_assert_lock(sdata); |
538 | |||
538 | /* update cfg80211 bss information with the new channel */ | 539 | /* update cfg80211 bss information with the new channel */ |
539 | if (!is_zero_ether_addr(ifibss->bssid)) { | 540 | if (!is_zero_ether_addr(ifibss->bssid)) { |
540 | capability = WLAN_CAPABILITY_IBSS; | 541 | capability = WLAN_CAPABILITY_IBSS; |
@@ -559,10 +560,12 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
559 | 560 | ||
560 | /* generate the beacon */ | 561 | /* generate the beacon */ |
561 | err = ieee80211_ibss_csa_beacon(sdata, NULL); | 562 | err = ieee80211_ibss_csa_beacon(sdata, NULL); |
562 | sdata_unlock(sdata); | ||
563 | if (err < 0) | 563 | if (err < 0) |
564 | return err; | 564 | return err; |
565 | 565 | ||
566 | if (err) | ||
567 | ieee80211_bss_info_change_notify(sdata, err); | ||
568 | |||
566 | return 0; | 569 | return 0; |
567 | } | 570 | } |
568 | 571 | ||
@@ -753,12 +756,16 @@ static void ieee80211_csa_connection_drop_work(struct work_struct *work) | |||
753 | container_of(work, struct ieee80211_sub_if_data, | 756 | container_of(work, struct ieee80211_sub_if_data, |
754 | u.ibss.csa_connection_drop_work); | 757 | u.ibss.csa_connection_drop_work); |
755 | 758 | ||
759 | sdata_lock(sdata); | ||
760 | |||
756 | ieee80211_ibss_disconnect(sdata); | 761 | ieee80211_ibss_disconnect(sdata); |
757 | synchronize_rcu(); | 762 | synchronize_rcu(); |
758 | skb_queue_purge(&sdata->skb_queue); | 763 | skb_queue_purge(&sdata->skb_queue); |
759 | 764 | ||
760 | /* trigger a scan to find another IBSS network to join */ | 765 | /* trigger a scan to find another IBSS network to join */ |
761 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 766 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
767 | |||
768 | sdata_unlock(sdata); | ||
762 | } | 769 | } |
763 | 770 | ||
764 | static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata) | 771 | static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata) |
@@ -784,18 +791,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
784 | struct cfg80211_csa_settings params; | 791 | struct cfg80211_csa_settings params; |
785 | struct ieee80211_csa_ie csa_ie; | 792 | struct ieee80211_csa_ie csa_ie; |
786 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 793 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
787 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
788 | struct ieee80211_chanctx *chanctx; | ||
789 | enum nl80211_channel_type ch_type; | 794 | enum nl80211_channel_type ch_type; |
790 | int err, num_chanctx; | 795 | int err; |
791 | u32 sta_flags; | 796 | u32 sta_flags; |
792 | 797 | ||
793 | if (sdata->vif.csa_active) | ||
794 | return true; | ||
795 | |||
796 | if (!sdata->vif.bss_conf.ibss_joined) | ||
797 | return false; | ||
798 | |||
799 | sta_flags = IEEE80211_STA_DISABLE_VHT; | 798 | sta_flags = IEEE80211_STA_DISABLE_VHT; |
800 | switch (ifibss->chandef.width) { | 799 | switch (ifibss->chandef.width) { |
801 | case NL80211_CHAN_WIDTH_5: | 800 | case NL80211_CHAN_WIDTH_5: |
@@ -830,9 +829,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
830 | params.count = csa_ie.count; | 829 | params.count = csa_ie.count; |
831 | params.chandef = csa_ie.chandef; | 830 | params.chandef = csa_ie.chandef; |
832 | 831 | ||
833 | if (ifibss->chandef.chan->band != params.chandef.chan->band) | ||
834 | goto disconnect; | ||
835 | |||
836 | switch (ifibss->chandef.width) { | 832 | switch (ifibss->chandef.width) { |
837 | case NL80211_CHAN_WIDTH_20_NOHT: | 833 | case NL80211_CHAN_WIDTH_20_NOHT: |
838 | case NL80211_CHAN_WIDTH_20: | 834 | case NL80211_CHAN_WIDTH_20: |
@@ -888,28 +884,12 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
888 | params.radar_required = true; | 884 | params.radar_required = true; |
889 | } | 885 | } |
890 | 886 | ||
891 | rcu_read_lock(); | 887 | if (cfg80211_chandef_identical(¶ms.chandef, |
892 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 888 | &sdata->vif.bss_conf.chandef)) { |
893 | if (!chanctx_conf) { | 889 | ibss_dbg(sdata, |
894 | rcu_read_unlock(); | 890 | "received csa with an identical chandef, ignoring\n"); |
895 | goto disconnect; | 891 | return true; |
896 | } | ||
897 | |||
898 | /* don't handle for multi-VIF cases */ | ||
899 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
900 | if (chanctx->refcount > 1) { | ||
901 | rcu_read_unlock(); | ||
902 | goto disconnect; | ||
903 | } | ||
904 | num_chanctx = 0; | ||
905 | list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) | ||
906 | num_chanctx++; | ||
907 | |||
908 | if (num_chanctx > 1) { | ||
909 | rcu_read_unlock(); | ||
910 | goto disconnect; | ||
911 | } | 892 | } |
912 | rcu_read_unlock(); | ||
913 | 893 | ||
914 | /* all checks done, now perform the channel switch. */ | 894 | /* all checks done, now perform the channel switch. */ |
915 | ibss_dbg(sdata, | 895 | ibss_dbg(sdata, |
@@ -918,19 +898,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
918 | 898 | ||
919 | params.block_tx = !!csa_ie.mode; | 899 | params.block_tx = !!csa_ie.mode; |
920 | 900 | ||
921 | ieee80211_ibss_csa_beacon(sdata, ¶ms); | 901 | if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev, |
922 | sdata->csa_radar_required = params.radar_required; | 902 | ¶ms)) |
923 | 903 | goto disconnect; | |
924 | if (params.block_tx) | ||
925 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
926 | IEEE80211_MAX_QUEUE_MAP, | ||
927 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
928 | |||
929 | sdata->csa_chandef = params.chandef; | ||
930 | sdata->vif.csa_active = true; | ||
931 | |||
932 | ieee80211_bss_info_change_notify(sdata, err); | ||
933 | drv_channel_switch_beacon(sdata, ¶ms.chandef); | ||
934 | 904 | ||
935 | ieee80211_ibss_csa_mark_radar(sdata); | 905 | ieee80211_ibss_csa_mark_radar(sdata); |
936 | 906 | ||
@@ -966,7 +936,8 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata, | |||
966 | if (len < required_len) | 936 | if (len < required_len) |
967 | return; | 937 | return; |
968 | 938 | ||
969 | ieee80211_ibss_process_chanswitch(sdata, elems, false); | 939 | if (!sdata->vif.csa_active) |
940 | ieee80211_ibss_process_chanswitch(sdata, elems, false); | ||
970 | } | 941 | } |
971 | 942 | ||
972 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, | 943 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, |
@@ -1147,7 +1118,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1147 | goto put_bss; | 1118 | goto put_bss; |
1148 | 1119 | ||
1149 | /* process channel switch */ | 1120 | /* process channel switch */ |
1150 | if (ieee80211_ibss_process_chanswitch(sdata, elems, true)) | 1121 | if (sdata->vif.csa_active || |
1122 | ieee80211_ibss_process_chanswitch(sdata, elems, true)) | ||
1151 | goto put_bss; | 1123 | goto put_bss; |
1152 | 1124 | ||
1153 | /* same BSSID */ | 1125 | /* same BSSID */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ed5bf8b4b5c2..fb5dbcb79a12 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -232,6 +232,7 @@ struct ieee80211_rx_data { | |||
232 | struct beacon_data { | 232 | struct beacon_data { |
233 | u8 *head, *tail; | 233 | u8 *head, *tail; |
234 | int head_len, tail_len; | 234 | int head_len, tail_len; |
235 | struct ieee80211_meshconf_ie *meshconf; | ||
235 | struct rcu_head rcu_head; | 236 | struct rcu_head rcu_head; |
236 | }; | 237 | }; |
237 | 238 | ||
@@ -540,7 +541,10 @@ struct ieee80211_mesh_sync_ops { | |||
540 | struct ieee80211_mgmt *mgmt, | 541 | struct ieee80211_mgmt *mgmt, |
541 | struct ieee802_11_elems *elems, | 542 | struct ieee802_11_elems *elems, |
542 | struct ieee80211_rx_status *rx_status); | 543 | struct ieee80211_rx_status *rx_status); |
543 | void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata); | 544 | |
545 | /* should be called with beacon_data under RCU read lock */ | ||
546 | void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata, | ||
547 | struct beacon_data *beacon); | ||
544 | /* add other framework functions here */ | 548 | /* add other framework functions here */ |
545 | }; | 549 | }; |
546 | 550 | ||
@@ -614,6 +618,9 @@ struct ieee80211_if_mesh { | |||
614 | bool chsw_init; | 618 | bool chsw_init; |
615 | u8 chsw_ttl; | 619 | u8 chsw_ttl; |
616 | u16 pre_value; | 620 | u16 pre_value; |
621 | |||
622 | /* offset from skb->data while building IE */ | ||
623 | int meshconf_offset; | ||
617 | }; | 624 | }; |
618 | 625 | ||
619 | #ifdef CONFIG_MAC80211_MESH | 626 | #ifdef CONFIG_MAC80211_MESH |
@@ -776,10 +783,6 @@ struct ieee80211_sub_if_data { | |||
776 | u32 mntr_flags; | 783 | u32 mntr_flags; |
777 | } u; | 784 | } u; |
778 | 785 | ||
779 | spinlock_t cleanup_stations_lock; | ||
780 | struct list_head cleanup_stations; | ||
781 | struct work_struct cleanup_stations_wk; | ||
782 | |||
783 | #ifdef CONFIG_MAC80211_DEBUGFS | 786 | #ifdef CONFIG_MAC80211_DEBUGFS |
784 | struct { | 787 | struct { |
785 | struct dentry *subdir_stations; | 788 | struct dentry *subdir_stations; |
@@ -1117,6 +1120,7 @@ struct ieee80211_local { | |||
1117 | 1120 | ||
1118 | struct work_struct sched_scan_stopped_work; | 1121 | struct work_struct sched_scan_stopped_work; |
1119 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; | 1122 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; |
1123 | struct cfg80211_sched_scan_request *sched_scan_req; | ||
1120 | 1124 | ||
1121 | unsigned long leave_oper_channel_time; | 1125 | unsigned long leave_oper_channel_time; |
1122 | enum mac80211_scan_state next_scan_state; | 1126 | enum mac80211_scan_state next_scan_state; |
@@ -1425,6 +1429,9 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, | |||
1425 | struct ieee80211_bss *bss); | 1429 | struct ieee80211_bss *bss); |
1426 | 1430 | ||
1427 | /* scheduled scan handling */ | 1431 | /* scheduled scan handling */ |
1432 | int | ||
1433 | __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | ||
1434 | struct cfg80211_sched_scan_request *req); | ||
1428 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | 1435 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, |
1429 | struct cfg80211_sched_scan_request *req); | 1436 | struct cfg80211_sched_scan_request *req); |
1430 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); | 1437 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); |
@@ -1443,6 +1450,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | |||
1443 | 1450 | ||
1444 | /* channel switch handling */ | 1451 | /* channel switch handling */ |
1445 | void ieee80211_csa_finalize_work(struct work_struct *work); | 1452 | void ieee80211_csa_finalize_work(struct work_struct *work); |
1453 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | ||
1454 | struct cfg80211_csa_settings *params); | ||
1446 | 1455 | ||
1447 | /* interface handling */ | 1456 | /* interface handling */ |
1448 | int ieee80211_iface_init(void); | 1457 | int ieee80211_iface_init(void); |
@@ -1465,8 +1474,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local); | |||
1465 | 1474 | ||
1466 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); | 1475 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); |
1467 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); | 1476 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); |
1468 | int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | ||
1469 | struct cfg80211_beacon_data *params); | ||
1470 | 1477 | ||
1471 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1478 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1472 | { | 1479 | { |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a4f98123d0bf..d624ed49a7d9 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -786,10 +786,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
786 | * This is relevant only in WDS mode, in all other modes we've | 786 | * This is relevant only in WDS mode, in all other modes we've |
787 | * already removed all stations when disconnecting or similar, | 787 | * already removed all stations when disconnecting or similar, |
788 | * so warn otherwise. | 788 | * so warn otherwise. |
789 | * | ||
790 | * We call sta_info_flush_cleanup() later, to combine RCU waits. | ||
791 | */ | 789 | */ |
792 | flushed = sta_info_flush_defer(sdata); | 790 | flushed = sta_info_flush(sdata); |
793 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 791 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
794 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 792 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); |
795 | 793 | ||
@@ -891,23 +889,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
891 | cancel_work_sync(&sdata->work); | 889 | cancel_work_sync(&sdata->work); |
892 | /* | 890 | /* |
893 | * When we get here, the interface is marked down. | 891 | * When we get here, the interface is marked down. |
892 | * Free the remaining keys, if there are any | ||
893 | * (shouldn't be, except maybe in WDS mode?) | ||
894 | * | 894 | * |
895 | * sta_info_flush_cleanup() requires rcu_barrier() | 895 | * Force the key freeing to always synchronize_net() |
896 | * first to wait for the station call_rcu() calls | 896 | * to wait for the RX path in case it is using this |
897 | * to complete, and we also need synchronize_rcu() | 897 | * interface enqueuing frames * at this very time on |
898 | * to wait for the RX path in case it is using the | ||
899 | * interface and enqueuing frames at this very time on | ||
900 | * another CPU. | 898 | * another CPU. |
901 | */ | 899 | */ |
902 | synchronize_rcu(); | 900 | ieee80211_free_keys(sdata, true); |
903 | rcu_barrier(); | ||
904 | sta_info_flush_cleanup(sdata); | ||
905 | |||
906 | /* | ||
907 | * Free all remaining keys, there shouldn't be any, | ||
908 | * except maybe in WDS mode? | ||
909 | */ | ||
910 | ieee80211_free_keys(sdata); | ||
911 | 901 | ||
912 | /* fall through */ | 902 | /* fall through */ |
913 | case NL80211_IFTYPE_AP: | 903 | case NL80211_IFTYPE_AP: |
@@ -1018,17 +1008,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
1018 | atomic_dec(&local->iff_promiscs); | 1008 | atomic_dec(&local->iff_promiscs); |
1019 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 1009 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
1020 | } | 1010 | } |
1021 | |||
1022 | /* | ||
1023 | * TODO: If somebody needs this on AP interfaces, | ||
1024 | * it can be enabled easily but multicast | ||
1025 | * addresses from VLANs need to be synced. | ||
1026 | */ | ||
1027 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
1028 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
1029 | sdata->vif.type != NL80211_IFTYPE_AP) | ||
1030 | drv_set_multicast_list(local, sdata, &dev->mc); | ||
1031 | |||
1032 | spin_lock_bh(&local->filter_lock); | 1011 | spin_lock_bh(&local->filter_lock); |
1033 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); | 1012 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
1034 | spin_unlock_bh(&local->filter_lock); | 1013 | spin_unlock_bh(&local->filter_lock); |
@@ -1044,7 +1023,7 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) | |||
1044 | int i; | 1023 | int i; |
1045 | 1024 | ||
1046 | /* free extra data */ | 1025 | /* free extra data */ |
1047 | ieee80211_free_keys(sdata); | 1026 | ieee80211_free_keys(sdata, false); |
1048 | 1027 | ||
1049 | ieee80211_debugfs_remove_netdev(sdata); | 1028 | ieee80211_debugfs_remove_netdev(sdata); |
1050 | 1029 | ||
@@ -1578,15 +1557,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1578 | mutex_unlock(&local->iflist_mtx); | 1557 | mutex_unlock(&local->iflist_mtx); |
1579 | } | 1558 | } |
1580 | 1559 | ||
1581 | static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) | ||
1582 | { | ||
1583 | struct ieee80211_sub_if_data *sdata; | ||
1584 | |||
1585 | sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); | ||
1586 | |||
1587 | ieee80211_cleanup_sdata_stas(sdata); | ||
1588 | } | ||
1589 | |||
1590 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1560 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
1591 | struct wireless_dev **new_wdev, enum nl80211_iftype type, | 1561 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1592 | struct vif_params *params) | 1562 | struct vif_params *params) |
@@ -1659,9 +1629,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1659 | 1629 | ||
1660 | INIT_LIST_HEAD(&sdata->key_list); | 1630 | INIT_LIST_HEAD(&sdata->key_list); |
1661 | 1631 | ||
1662 | spin_lock_init(&sdata->cleanup_stations_lock); | ||
1663 | INIT_LIST_HEAD(&sdata->cleanup_stations); | ||
1664 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); | ||
1665 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, | 1632 | INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, |
1666 | ieee80211_dfs_cac_timer_work); | 1633 | ieee80211_dfs_cac_timer_work); |
1667 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, | 1634 | INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk, |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index e568d98167d0..6ff65a1ebaa9 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -589,14 +589,10 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, | |||
589 | } | 589 | } |
590 | EXPORT_SYMBOL(ieee80211_iter_keys); | 590 | EXPORT_SYMBOL(ieee80211_iter_keys); |
591 | 591 | ||
592 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | 592 | static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata, |
593 | struct list_head *keys) | ||
593 | { | 594 | { |
594 | struct ieee80211_key *key, *tmp; | 595 | struct ieee80211_key *key, *tmp; |
595 | LIST_HEAD(keys); | ||
596 | |||
597 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); | ||
598 | |||
599 | mutex_lock(&sdata->local->key_mtx); | ||
600 | 596 | ||
601 | sdata->crypto_tx_tailroom_needed_cnt -= | 597 | sdata->crypto_tx_tailroom_needed_cnt -= |
602 | sdata->crypto_tx_tailroom_pending_dec; | 598 | sdata->crypto_tx_tailroom_pending_dec; |
@@ -608,28 +604,51 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
608 | ieee80211_key_replace(key->sdata, key->sta, | 604 | ieee80211_key_replace(key->sdata, key->sta, |
609 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 605 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
610 | key, NULL); | 606 | key, NULL); |
611 | list_add_tail(&key->list, &keys); | 607 | list_add_tail(&key->list, keys); |
612 | } | 608 | } |
613 | 609 | ||
614 | ieee80211_debugfs_key_update_default(sdata); | 610 | ieee80211_debugfs_key_update_default(sdata); |
611 | } | ||
615 | 612 | ||
616 | if (!list_empty(&keys)) { | 613 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, |
617 | synchronize_net(); | 614 | bool force_synchronize) |
618 | list_for_each_entry_safe(key, tmp, &keys, list) | 615 | { |
619 | __ieee80211_key_destroy(key, false); | 616 | struct ieee80211_local *local = sdata->local; |
617 | struct ieee80211_sub_if_data *vlan; | ||
618 | struct ieee80211_key *key, *tmp; | ||
619 | LIST_HEAD(keys); | ||
620 | |||
621 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); | ||
622 | |||
623 | mutex_lock(&local->key_mtx); | ||
624 | |||
625 | ieee80211_free_keys_iface(sdata, &keys); | ||
626 | |||
627 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
628 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
629 | ieee80211_free_keys_iface(vlan, &keys); | ||
620 | } | 630 | } |
621 | 631 | ||
632 | if (!list_empty(&keys) || force_synchronize) | ||
633 | synchronize_net(); | ||
634 | list_for_each_entry_safe(key, tmp, &keys, list) | ||
635 | __ieee80211_key_destroy(key, false); | ||
636 | |||
622 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || | 637 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || |
623 | sdata->crypto_tx_tailroom_pending_dec); | 638 | sdata->crypto_tx_tailroom_pending_dec); |
639 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
640 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
641 | WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt || | ||
642 | vlan->crypto_tx_tailroom_pending_dec); | ||
643 | } | ||
624 | 644 | ||
625 | mutex_unlock(&sdata->local->key_mtx); | 645 | mutex_unlock(&local->key_mtx); |
626 | } | 646 | } |
627 | 647 | ||
628 | void ieee80211_free_sta_keys(struct ieee80211_local *local, | 648 | void ieee80211_free_sta_keys(struct ieee80211_local *local, |
629 | struct sta_info *sta) | 649 | struct sta_info *sta) |
630 | { | 650 | { |
631 | struct ieee80211_key *key, *tmp; | 651 | struct ieee80211_key *key; |
632 | LIST_HEAD(keys); | ||
633 | int i; | 652 | int i; |
634 | 653 | ||
635 | mutex_lock(&local->key_mtx); | 654 | mutex_lock(&local->key_mtx); |
@@ -640,7 +659,7 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local, | |||
640 | ieee80211_key_replace(key->sdata, key->sta, | 659 | ieee80211_key_replace(key->sdata, key->sta, |
641 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 660 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
642 | key, NULL); | 661 | key, NULL); |
643 | list_add(&key->list, &keys); | 662 | __ieee80211_key_destroy(key, true); |
644 | } | 663 | } |
645 | 664 | ||
646 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | 665 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { |
@@ -650,17 +669,8 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local, | |||
650 | ieee80211_key_replace(key->sdata, key->sta, | 669 | ieee80211_key_replace(key->sdata, key->sta, |
651 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 670 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
652 | key, NULL); | 671 | key, NULL); |
653 | list_add(&key->list, &keys); | ||
654 | } | ||
655 | |||
656 | /* | ||
657 | * NB: the station code relies on this being | ||
658 | * done even if there aren't any keys | ||
659 | */ | ||
660 | synchronize_net(); | ||
661 | |||
662 | list_for_each_entry_safe(key, tmp, &keys, list) | ||
663 | __ieee80211_key_destroy(key, true); | 672 | __ieee80211_key_destroy(key, true); |
673 | } | ||
664 | 674 | ||
665 | mutex_unlock(&local->key_mtx); | 675 | mutex_unlock(&local->key_mtx); |
666 | } | 676 | } |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 0aebb889caba..19db68663d75 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -136,7 +136,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, | |||
136 | bool uni, bool multi); | 136 | bool uni, bool multi); |
137 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 137 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
138 | int idx); | 138 | int idx); |
139 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 139 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, |
140 | bool force_synchronize); | ||
140 | void ieee80211_free_sta_keys(struct ieee80211_local *local, | 141 | void ieee80211_free_sta_keys(struct ieee80211_local *local, |
141 | struct sta_info *sta); | 142 | struct sta_info *sta); |
142 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 143 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index fa34cd2344b9..2bd5b552b2f6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -250,12 +250,8 @@ static void ieee80211_restart_work(struct work_struct *work) | |||
250 | /* wait for scan work complete */ | 250 | /* wait for scan work complete */ |
251 | flush_workqueue(local->workqueue); | 251 | flush_workqueue(local->workqueue); |
252 | 252 | ||
253 | mutex_lock(&local->mtx); | 253 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), |
254 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 254 | "%s called with hardware scan in progress\n", __func__); |
255 | rcu_dereference_protected(local->sched_scan_sdata, | ||
256 | lockdep_is_held(&local->mtx)), | ||
257 | "%s called with hardware scan in progress\n", __func__); | ||
258 | mutex_unlock(&local->mtx); | ||
259 | 255 | ||
260 | rtnl_lock(); | 256 | rtnl_lock(); |
261 | ieee80211_scan_cancel(local); | 257 | ieee80211_scan_cancel(local); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 89df62b2b689..5a74b249ba35 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -259,6 +259,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, | |||
259 | *pos++ = WLAN_EID_MESH_CONFIG; | 259 | *pos++ = WLAN_EID_MESH_CONFIG; |
260 | *pos++ = meshconf_len; | 260 | *pos++ = meshconf_len; |
261 | 261 | ||
262 | /* save a pointer for quick updates in pre-tbtt */ | ||
263 | ifmsh->meshconf_offset = pos - skb->data; | ||
264 | |||
262 | /* Active path selection protocol ID */ | 265 | /* Active path selection protocol ID */ |
263 | *pos++ = ifmsh->mesh_pp_id; | 266 | *pos++ = ifmsh->mesh_pp_id; |
264 | /* Active path selection metric ID */ | 267 | /* Active path selection metric ID */ |
@@ -723,6 +726,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
723 | 726 | ||
724 | bcn->tail_len = skb->len; | 727 | bcn->tail_len = skb->len; |
725 | memcpy(bcn->tail, skb->data, bcn->tail_len); | 728 | memcpy(bcn->tail, skb->data, bcn->tail_len); |
729 | bcn->meshconf = (struct ieee80211_meshconf_ie *) | ||
730 | (bcn->tail + ifmsh->meshconf_offset); | ||
726 | 731 | ||
727 | dev_kfree_skb(skb); | 732 | dev_kfree_skb(skb); |
728 | rcu_assign_pointer(ifmsh->beacon, bcn); | 733 | rcu_assign_pointer(ifmsh->beacon, bcn); |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index d1cf2d553499..2bc5dc25d5ad 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -164,12 +164,15 @@ no_sync: | |||
164 | rcu_read_unlock(); | 164 | rcu_read_unlock(); |
165 | } | 165 | } |
166 | 166 | ||
167 | static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | 167 | static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, |
168 | struct beacon_data *beacon) | ||
168 | { | 169 | { |
169 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 170 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
171 | u8 cap; | ||
170 | 172 | ||
171 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); | 173 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); |
172 | BUG_ON(!rcu_read_lock_held()); | 174 | BUG_ON(!rcu_read_lock_held()); |
175 | cap = beacon->meshconf->meshconf_cap; | ||
173 | 176 | ||
174 | spin_lock_bh(&ifmsh->sync_offset_lock); | 177 | spin_lock_bh(&ifmsh->sync_offset_lock); |
175 | 178 | ||
@@ -194,6 +197,10 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | |||
194 | ifmsh->adjusting_tbtt = false; | 197 | ifmsh->adjusting_tbtt = false; |
195 | } | 198 | } |
196 | spin_unlock_bh(&ifmsh->sync_offset_lock); | 199 | spin_unlock_bh(&ifmsh->sync_offset_lock); |
200 | |||
201 | beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ? | ||
202 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap : | ||
203 | ~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap; | ||
197 | } | 204 | } |
198 | 205 | ||
199 | static const struct sync_method sync_methods[] = { | 206 | static const struct sync_method sync_methods[] = { |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 900ead344f5b..9c2c7ee2cc30 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1698,7 +1698,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1698 | memset(ifmgd->bssid, 0, ETH_ALEN); | 1698 | memset(ifmgd->bssid, 0, ETH_ALEN); |
1699 | 1699 | ||
1700 | /* remove AP and TDLS peers */ | 1700 | /* remove AP and TDLS peers */ |
1701 | sta_info_flush_defer(sdata); | 1701 | sta_info_flush(sdata); |
1702 | 1702 | ||
1703 | /* finally reset all BSS / config parameters */ | 1703 | /* finally reset all BSS / config parameters */ |
1704 | changed |= ieee80211_reset_erp_info(sdata); | 1704 | changed |= ieee80211_reset_erp_info(sdata); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 340126204343..af64fb8e8add 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -37,9 +37,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
37 | IEEE80211_MAX_QUEUE_MAP, | 37 | IEEE80211_MAX_QUEUE_MAP, |
38 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 38 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
39 | 39 | ||
40 | /* flush out all packets and station cleanup call_rcu()s */ | 40 | /* flush out all packets */ |
41 | synchronize_net(); | 41 | synchronize_net(); |
42 | rcu_barrier(); | ||
43 | 42 | ||
44 | ieee80211_flush_queues(local, NULL); | 43 | ieee80211_flush_queues(local, NULL); |
45 | 44 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2dfa75522733..5a2afe9583a8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1963,20 +1963,17 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1963 | } | 1963 | } |
1964 | } | 1964 | } |
1965 | 1965 | ||
1966 | if (skb) { | ||
1967 | int align __maybe_unused; | ||
1968 | |||
1969 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | 1966 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
1970 | /* | 1967 | if (skb) { |
1971 | * 'align' will only take the values 0 or 2 here | 1968 | /* 'align' will only take the values 0 or 2 here since all |
1972 | * since all frames are required to be aligned | 1969 | * frames are required to be aligned to 2-byte boundaries |
1973 | * to 2-byte boundaries when being passed to | 1970 | * when being passed to mac80211; the code here works just |
1974 | * mac80211; the code here works just as well if | 1971 | * as well if that isn't true, but mac80211 assumes it can |
1975 | * that isn't true, but mac80211 assumes it can | 1972 | * access fields as 2-byte aligned (e.g. for ether_addr_equal) |
1976 | * access fields as 2-byte aligned (e.g. for | ||
1977 | * compare_ether_addr) | ||
1978 | */ | 1973 | */ |
1979 | align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; | 1974 | int align; |
1975 | |||
1976 | align = (unsigned long)(skb->data + sizeof(struct ethhdr)) & 3; | ||
1980 | if (align) { | 1977 | if (align) { |
1981 | if (WARN_ON(skb_headroom(skb) < 3)) { | 1978 | if (WARN_ON(skb_headroom(skb) < 3)) { |
1982 | dev_kfree_skb(skb); | 1979 | dev_kfree_skb(skb); |
@@ -1989,14 +1986,14 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1989 | skb_set_tail_pointer(skb, len); | 1986 | skb_set_tail_pointer(skb, len); |
1990 | } | 1987 | } |
1991 | } | 1988 | } |
1989 | } | ||
1992 | #endif | 1990 | #endif |
1993 | 1991 | ||
1994 | if (skb) { | 1992 | if (skb) { |
1995 | /* deliver to local stack */ | 1993 | /* deliver to local stack */ |
1996 | skb->protocol = eth_type_trans(skb, dev); | 1994 | skb->protocol = eth_type_trans(skb, dev); |
1997 | memset(skb->cb, 0, sizeof(skb->cb)); | 1995 | memset(skb->cb, 0, sizeof(skb->cb)); |
1998 | netif_receive_skb(skb); | 1996 | netif_receive_skb(skb); |
1999 | } | ||
2000 | } | 1997 | } |
2001 | 1998 | ||
2002 | if (xmit_skb) { | 1999 | if (xmit_skb) { |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 4d73c46df862..88c81616f8f7 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -271,10 +271,11 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
271 | return true; | 271 | return true; |
272 | } | 272 | } |
273 | 273 | ||
274 | static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | 274 | static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
275 | bool was_hw_scan) | ||
276 | { | 275 | { |
277 | struct ieee80211_local *local = hw_to_local(hw); | 276 | struct ieee80211_local *local = hw_to_local(hw); |
277 | bool hw_scan = local->ops->hw_scan; | ||
278 | bool was_scanning = local->scanning; | ||
278 | 279 | ||
279 | lockdep_assert_held(&local->mtx); | 280 | lockdep_assert_held(&local->mtx); |
280 | 281 | ||
@@ -290,7 +291,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
290 | if (WARN_ON(!local->scan_req)) | 291 | if (WARN_ON(!local->scan_req)) |
291 | return; | 292 | return; |
292 | 293 | ||
293 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 294 | if (hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
294 | int rc; | 295 | int rc; |
295 | 296 | ||
296 | rc = drv_hw_scan(local, | 297 | rc = drv_hw_scan(local, |
@@ -316,7 +317,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
316 | /* Set power back to normal operating levels. */ | 317 | /* Set power back to normal operating levels. */ |
317 | ieee80211_hw_config(local, 0); | 318 | ieee80211_hw_config(local, 0); |
318 | 319 | ||
319 | if (!was_hw_scan) { | 320 | if (!hw_scan) { |
320 | ieee80211_configure_filter(local); | 321 | ieee80211_configure_filter(local); |
321 | drv_sw_scan_complete(local); | 322 | drv_sw_scan_complete(local); |
322 | ieee80211_offchannel_return(local); | 323 | ieee80211_offchannel_return(local); |
@@ -327,7 +328,8 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
327 | ieee80211_mlme_notify_scan_completed(local); | 328 | ieee80211_mlme_notify_scan_completed(local); |
328 | ieee80211_ibss_notify_scan_completed(local); | 329 | ieee80211_ibss_notify_scan_completed(local); |
329 | ieee80211_mesh_notify_scan_completed(local); | 330 | ieee80211_mesh_notify_scan_completed(local); |
330 | ieee80211_start_next_roc(local); | 331 | if (was_scanning) |
332 | ieee80211_start_next_roc(local); | ||
331 | } | 333 | } |
332 | 334 | ||
333 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 335 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
@@ -747,7 +749,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
747 | container_of(work, struct ieee80211_local, scan_work.work); | 749 | container_of(work, struct ieee80211_local, scan_work.work); |
748 | struct ieee80211_sub_if_data *sdata; | 750 | struct ieee80211_sub_if_data *sdata; |
749 | unsigned long next_delay = 0; | 751 | unsigned long next_delay = 0; |
750 | bool aborted, hw_scan; | 752 | bool aborted; |
751 | 753 | ||
752 | mutex_lock(&local->mtx); | 754 | mutex_lock(&local->mtx); |
753 | 755 | ||
@@ -786,14 +788,6 @@ void ieee80211_scan_work(struct work_struct *work) | |||
786 | } | 788 | } |
787 | 789 | ||
788 | /* | 790 | /* |
789 | * Avoid re-scheduling when the sdata is going away. | ||
790 | */ | ||
791 | if (!ieee80211_sdata_running(sdata)) { | ||
792 | aborted = true; | ||
793 | goto out_complete; | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * as long as no delay is required advance immediately | 791 | * as long as no delay is required advance immediately |
798 | * without scheduling a new work | 792 | * without scheduling a new work |
799 | */ | 793 | */ |
@@ -834,8 +828,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
834 | goto out; | 828 | goto out; |
835 | 829 | ||
836 | out_complete: | 830 | out_complete: |
837 | hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); | 831 | __ieee80211_scan_completed(&local->hw, aborted); |
838 | __ieee80211_scan_completed(&local->hw, aborted, hw_scan); | ||
839 | out: | 832 | out: |
840 | mutex_unlock(&local->mtx); | 833 | mutex_unlock(&local->mtx); |
841 | } | 834 | } |
@@ -973,13 +966,13 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
973 | */ | 966 | */ |
974 | cancel_delayed_work(&local->scan_work); | 967 | cancel_delayed_work(&local->scan_work); |
975 | /* and clean up */ | 968 | /* and clean up */ |
976 | __ieee80211_scan_completed(&local->hw, true, false); | 969 | __ieee80211_scan_completed(&local->hw, true); |
977 | out: | 970 | out: |
978 | mutex_unlock(&local->mtx); | 971 | mutex_unlock(&local->mtx); |
979 | } | 972 | } |
980 | 973 | ||
981 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | 974 | int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, |
982 | struct cfg80211_sched_scan_request *req) | 975 | struct cfg80211_sched_scan_request *req) |
983 | { | 976 | { |
984 | struct ieee80211_local *local = sdata->local; | 977 | struct ieee80211_local *local = sdata->local; |
985 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; | 978 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; |
@@ -989,17 +982,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
989 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + | 982 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + |
990 | local->scan_ies_len + req->ie_len; | 983 | local->scan_ies_len + req->ie_len; |
991 | 984 | ||
992 | mutex_lock(&local->mtx); | 985 | lockdep_assert_held(&local->mtx); |
993 | |||
994 | if (rcu_access_pointer(local->sched_scan_sdata)) { | ||
995 | ret = -EBUSY; | ||
996 | goto out; | ||
997 | } | ||
998 | 986 | ||
999 | if (!local->ops->sched_scan_start) { | 987 | if (!local->ops->sched_scan_start) |
1000 | ret = -ENOTSUPP; | 988 | return -ENOTSUPP; |
1001 | goto out; | ||
1002 | } | ||
1003 | 989 | ||
1004 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 990 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1005 | if (!local->hw.wiphy->bands[i]) | 991 | if (!local->hw.wiphy->bands[i]) |
@@ -1020,13 +1006,39 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1020 | } | 1006 | } |
1021 | 1007 | ||
1022 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 1008 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
1023 | if (ret == 0) | 1009 | if (ret == 0) { |
1024 | rcu_assign_pointer(local->sched_scan_sdata, sdata); | 1010 | rcu_assign_pointer(local->sched_scan_sdata, sdata); |
1011 | local->sched_scan_req = req; | ||
1012 | } | ||
1025 | 1013 | ||
1026 | out_free: | 1014 | out_free: |
1027 | while (i > 0) | 1015 | while (i > 0) |
1028 | kfree(sched_scan_ies.ie[--i]); | 1016 | kfree(sched_scan_ies.ie[--i]); |
1029 | out: | 1017 | |
1018 | if (ret) { | ||
1019 | /* Clean in case of failure after HW restart or upon resume. */ | ||
1020 | rcu_assign_pointer(local->sched_scan_sdata, NULL); | ||
1021 | local->sched_scan_req = NULL; | ||
1022 | } | ||
1023 | |||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
1027 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | ||
1028 | struct cfg80211_sched_scan_request *req) | ||
1029 | { | ||
1030 | struct ieee80211_local *local = sdata->local; | ||
1031 | int ret; | ||
1032 | |||
1033 | mutex_lock(&local->mtx); | ||
1034 | |||
1035 | if (rcu_access_pointer(local->sched_scan_sdata)) { | ||
1036 | mutex_unlock(&local->mtx); | ||
1037 | return -EBUSY; | ||
1038 | } | ||
1039 | |||
1040 | ret = __ieee80211_request_sched_scan_start(sdata, req); | ||
1041 | |||
1030 | mutex_unlock(&local->mtx); | 1042 | mutex_unlock(&local->mtx); |
1031 | return ret; | 1043 | return ret; |
1032 | } | 1044 | } |
@@ -1043,6 +1055,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
1043 | goto out; | 1055 | goto out; |
1044 | } | 1056 | } |
1045 | 1057 | ||
1058 | /* We don't want to restart sched scan anymore. */ | ||
1059 | local->sched_scan_req = NULL; | ||
1060 | |||
1046 | if (rcu_access_pointer(local->sched_scan_sdata)) | 1061 | if (rcu_access_pointer(local->sched_scan_sdata)) |
1047 | drv_sched_scan_stop(local, sdata); | 1062 | drv_sched_scan_stop(local, sdata); |
1048 | 1063 | ||
@@ -1077,6 +1092,9 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
1077 | 1092 | ||
1078 | rcu_assign_pointer(local->sched_scan_sdata, NULL); | 1093 | rcu_assign_pointer(local->sched_scan_sdata, NULL); |
1079 | 1094 | ||
1095 | /* If sched scan was aborted by the driver. */ | ||
1096 | local->sched_scan_req = NULL; | ||
1097 | |||
1080 | mutex_unlock(&local->mtx); | 1098 | mutex_unlock(&local->mtx); |
1081 | 1099 | ||
1082 | cfg80211_sched_scan_stopped(local->hw.wiphy); | 1100 | cfg80211_sched_scan_stopped(local->hw.wiphy); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8ed97f76c3cf..4576ba0ff221 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -99,23 +99,6 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
99 | struct ieee80211_local *local = sdata->local; | 99 | struct ieee80211_local *local = sdata->local; |
100 | struct ps_data *ps; | 100 | struct ps_data *ps; |
101 | 101 | ||
102 | /* | ||
103 | * At this point, when being called as call_rcu callback, | ||
104 | * neither mac80211 nor the driver can reference this | ||
105 | * sta struct any more except by still existing timers | ||
106 | * associated with this station that we clean up below. | ||
107 | * | ||
108 | * Note though that this still uses the sdata and even | ||
109 | * calls the driver in AP and mesh mode, so interfaces | ||
110 | * of those types mush use call sta_info_flush_cleanup() | ||
111 | * (typically via sta_info_flush()) before deconfiguring | ||
112 | * the driver. | ||
113 | * | ||
114 | * In station mode, nothing happens here so it doesn't | ||
115 | * have to (and doesn't) do that, this is intentional to | ||
116 | * speed up roaming. | ||
117 | */ | ||
118 | |||
119 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 102 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { |
120 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || | 103 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
121 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 104 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -160,37 +143,6 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
160 | sta_info_free(local, sta); | 143 | sta_info_free(local, sta); |
161 | } | 144 | } |
162 | 145 | ||
163 | void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) | ||
164 | { | ||
165 | struct sta_info *sta; | ||
166 | |||
167 | spin_lock_bh(&sdata->cleanup_stations_lock); | ||
168 | while (!list_empty(&sdata->cleanup_stations)) { | ||
169 | sta = list_first_entry(&sdata->cleanup_stations, | ||
170 | struct sta_info, list); | ||
171 | list_del(&sta->list); | ||
172 | spin_unlock_bh(&sdata->cleanup_stations_lock); | ||
173 | |||
174 | cleanup_single_sta(sta); | ||
175 | |||
176 | spin_lock_bh(&sdata->cleanup_stations_lock); | ||
177 | } | ||
178 | |||
179 | spin_unlock_bh(&sdata->cleanup_stations_lock); | ||
180 | } | ||
181 | |||
182 | static void free_sta_rcu(struct rcu_head *h) | ||
183 | { | ||
184 | struct sta_info *sta = container_of(h, struct sta_info, rcu_head); | ||
185 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
186 | |||
187 | spin_lock(&sdata->cleanup_stations_lock); | ||
188 | list_add_tail(&sta->list, &sdata->cleanup_stations); | ||
189 | spin_unlock(&sdata->cleanup_stations_lock); | ||
190 | |||
191 | ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); | ||
192 | } | ||
193 | |||
194 | /* protected by RCU */ | 146 | /* protected by RCU */ |
195 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | 147 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
196 | const u8 *addr) | 148 | const u8 *addr) |
@@ -842,7 +794,7 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
842 | return have_buffered; | 794 | return have_buffered; |
843 | } | 795 | } |
844 | 796 | ||
845 | int __must_check __sta_info_destroy(struct sta_info *sta) | 797 | static int __must_check __sta_info_destroy_part1(struct sta_info *sta) |
846 | { | 798 | { |
847 | struct ieee80211_local *local; | 799 | struct ieee80211_local *local; |
848 | struct ieee80211_sub_if_data *sdata; | 800 | struct ieee80211_sub_if_data *sdata; |
@@ -868,12 +820,35 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
868 | ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA); | 820 | ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA); |
869 | 821 | ||
870 | ret = sta_info_hash_del(local, sta); | 822 | ret = sta_info_hash_del(local, sta); |
871 | if (ret) | 823 | if (WARN_ON(ret)) |
872 | return ret; | 824 | return ret; |
873 | 825 | ||
874 | list_del_rcu(&sta->list); | 826 | list_del_rcu(&sta->list); |
875 | 827 | ||
876 | /* this always calls synchronize_net() */ | 828 | drv_sta_pre_rcu_remove(local, sta->sdata, sta); |
829 | |||
830 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | ||
831 | rcu_access_pointer(sdata->u.vlan.sta) == sta) | ||
832 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); | ||
833 | |||
834 | return 0; | ||
835 | } | ||
836 | |||
837 | static void __sta_info_destroy_part2(struct sta_info *sta) | ||
838 | { | ||
839 | struct ieee80211_local *local = sta->local; | ||
840 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
841 | int ret; | ||
842 | |||
843 | /* | ||
844 | * NOTE: This assumes at least synchronize_net() was done | ||
845 | * after _part1 and before _part2! | ||
846 | */ | ||
847 | |||
848 | might_sleep(); | ||
849 | lockdep_assert_held(&local->sta_mtx); | ||
850 | |||
851 | /* now keys can no longer be reached */ | ||
877 | ieee80211_free_sta_keys(local, sta); | 852 | ieee80211_free_sta_keys(local, sta); |
878 | 853 | ||
879 | sta->dead = true; | 854 | sta->dead = true; |
@@ -881,9 +856,6 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
881 | local->num_sta--; | 856 | local->num_sta--; |
882 | local->sta_generation++; | 857 | local->sta_generation++; |
883 | 858 | ||
884 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
885 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); | ||
886 | |||
887 | while (sta->sta_state > IEEE80211_STA_NONE) { | 859 | while (sta->sta_state > IEEE80211_STA_NONE) { |
888 | ret = sta_info_move_state(sta, sta->sta_state - 1); | 860 | ret = sta_info_move_state(sta, sta->sta_state - 1); |
889 | if (ret) { | 861 | if (ret) { |
@@ -906,7 +878,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
906 | ieee80211_sta_debugfs_remove(sta); | 878 | ieee80211_sta_debugfs_remove(sta); |
907 | ieee80211_recalc_min_chandef(sdata); | 879 | ieee80211_recalc_min_chandef(sdata); |
908 | 880 | ||
909 | call_rcu(&sta->rcu_head, free_sta_rcu); | 881 | cleanup_single_sta(sta); |
882 | } | ||
883 | |||
884 | int __must_check __sta_info_destroy(struct sta_info *sta) | ||
885 | { | ||
886 | int err = __sta_info_destroy_part1(sta); | ||
887 | |||
888 | if (err) | ||
889 | return err; | ||
890 | |||
891 | synchronize_net(); | ||
892 | |||
893 | __sta_info_destroy_part2(sta); | ||
910 | 894 | ||
911 | return 0; | 895 | return 0; |
912 | } | 896 | } |
@@ -976,32 +960,38 @@ void sta_info_stop(struct ieee80211_local *local) | |||
976 | } | 960 | } |
977 | 961 | ||
978 | 962 | ||
979 | int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata) | 963 | int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans) |
980 | { | 964 | { |
981 | struct ieee80211_local *local = sdata->local; | 965 | struct ieee80211_local *local = sdata->local; |
982 | struct sta_info *sta, *tmp; | 966 | struct sta_info *sta, *tmp; |
967 | LIST_HEAD(free_list); | ||
983 | int ret = 0; | 968 | int ret = 0; |
984 | 969 | ||
985 | might_sleep(); | 970 | might_sleep(); |
986 | 971 | ||
972 | WARN_ON(vlans && sdata->vif.type != NL80211_IFTYPE_AP); | ||
973 | WARN_ON(vlans && !sdata->bss); | ||
974 | |||
987 | mutex_lock(&local->sta_mtx); | 975 | mutex_lock(&local->sta_mtx); |
988 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 976 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
989 | if (sdata == sta->sdata) { | 977 | if (sdata == sta->sdata || |
990 | WARN_ON(__sta_info_destroy(sta)); | 978 | (vlans && sdata->bss == sta->sdata->bss)) { |
979 | if (!WARN_ON(__sta_info_destroy_part1(sta))) | ||
980 | list_add(&sta->free_list, &free_list); | ||
991 | ret++; | 981 | ret++; |
992 | } | 982 | } |
993 | } | 983 | } |
984 | |||
985 | if (!list_empty(&free_list)) { | ||
986 | synchronize_net(); | ||
987 | list_for_each_entry_safe(sta, tmp, &free_list, free_list) | ||
988 | __sta_info_destroy_part2(sta); | ||
989 | } | ||
994 | mutex_unlock(&local->sta_mtx); | 990 | mutex_unlock(&local->sta_mtx); |
995 | 991 | ||
996 | return ret; | 992 | return ret; |
997 | } | 993 | } |
998 | 994 | ||
999 | void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata) | ||
1000 | { | ||
1001 | ieee80211_cleanup_sdata_stas(sdata); | ||
1002 | cancel_work_sync(&sdata->cleanup_stations_wk); | ||
1003 | } | ||
1004 | |||
1005 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 995 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
1006 | unsigned long exp_time) | 996 | unsigned long exp_time) |
1007 | { | 997 | { |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 0218caf5c14a..d77ff7090630 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -247,6 +247,7 @@ struct ieee80211_tx_latency_stat { | |||
247 | * mac80211 is communicating with. | 247 | * mac80211 is communicating with. |
248 | * | 248 | * |
249 | * @list: global linked list entry | 249 | * @list: global linked list entry |
250 | * @free_list: list entry for keeping track of stations to free | ||
250 | * @hnext: hash table linked list pointer | 251 | * @hnext: hash table linked list pointer |
251 | * @local: pointer to the global information | 252 | * @local: pointer to the global information |
252 | * @sdata: virtual interface this station belongs to | 253 | * @sdata: virtual interface this station belongs to |
@@ -329,7 +330,7 @@ struct ieee80211_tx_latency_stat { | |||
329 | */ | 330 | */ |
330 | struct sta_info { | 331 | struct sta_info { |
331 | /* General information, mostly static */ | 332 | /* General information, mostly static */ |
332 | struct list_head list; | 333 | struct list_head list, free_list; |
333 | struct rcu_head rcu_head; | 334 | struct rcu_head rcu_head; |
334 | struct sta_info __rcu *hnext; | 335 | struct sta_info __rcu *hnext; |
335 | struct ieee80211_local *local; | 336 | struct ieee80211_local *local; |
@@ -605,21 +606,6 @@ void sta_info_recalc_tim(struct sta_info *sta); | |||
605 | 606 | ||
606 | void sta_info_init(struct ieee80211_local *local); | 607 | void sta_info_init(struct ieee80211_local *local); |
607 | void sta_info_stop(struct ieee80211_local *local); | 608 | void sta_info_stop(struct ieee80211_local *local); |
608 | int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata); | ||
609 | |||
610 | /** | ||
611 | * sta_info_flush_cleanup - flush the sta_info cleanup queue | ||
612 | * @sdata: the interface | ||
613 | * | ||
614 | * Flushes the sta_info cleanup queue for a given interface; | ||
615 | * this is necessary before the interface is removed or, for | ||
616 | * AP/mesh interfaces, before it is deconfigured. | ||
617 | * | ||
618 | * Note an rcu_barrier() must precede the function, after all | ||
619 | * stations have been flushed/removed to ensure the call_rcu() | ||
620 | * calls that add stations to the cleanup queue have completed. | ||
621 | */ | ||
622 | void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata); | ||
623 | 609 | ||
624 | /** | 610 | /** |
625 | * sta_info_flush - flush matching STA entries from the STA table | 611 | * sta_info_flush - flush matching STA entries from the STA table |
@@ -627,15 +613,13 @@ void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata); | |||
627 | * Returns the number of removed STA entries. | 613 | * Returns the number of removed STA entries. |
628 | * | 614 | * |
629 | * @sdata: sdata to remove all stations from | 615 | * @sdata: sdata to remove all stations from |
616 | * @vlans: if the given interface is an AP interface, also flush VLANs | ||
630 | */ | 617 | */ |
618 | int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans); | ||
619 | |||
631 | static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata) | 620 | static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata) |
632 | { | 621 | { |
633 | int ret = sta_info_flush_defer(sdata); | 622 | return __sta_info_flush(sdata, false); |
634 | |||
635 | rcu_barrier(); | ||
636 | sta_info_flush_cleanup(sdata); | ||
637 | |||
638 | return ret; | ||
639 | } | 623 | } |
640 | 624 | ||
641 | void sta_set_rate_info_tx(struct sta_info *sta, | 625 | void sta_set_rate_info_tx(struct sta_info *sta, |
@@ -651,6 +635,4 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); | |||
651 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); | 635 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); |
652 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); | 636 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); |
653 | 637 | ||
654 | void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata); | ||
655 | |||
656 | #endif /* STA_INFO_H */ | 638 | #endif /* STA_INFO_H */ |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index e9ccf22f6dd9..3a669d7ec7ad 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -443,30 +443,6 @@ TRACE_EVENT(drv_prepare_multicast, | |||
443 | ) | 443 | ) |
444 | ); | 444 | ); |
445 | 445 | ||
446 | TRACE_EVENT(drv_set_multicast_list, | ||
447 | TP_PROTO(struct ieee80211_local *local, | ||
448 | struct ieee80211_sub_if_data *sdata, int mc_count), | ||
449 | |||
450 | TP_ARGS(local, sdata, mc_count), | ||
451 | |||
452 | TP_STRUCT__entry( | ||
453 | LOCAL_ENTRY | ||
454 | __field(bool, allmulti) | ||
455 | __field(int, mc_count) | ||
456 | ), | ||
457 | |||
458 | TP_fast_assign( | ||
459 | LOCAL_ASSIGN; | ||
460 | __entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
461 | __entry->mc_count = mc_count; | ||
462 | ), | ||
463 | |||
464 | TP_printk( | ||
465 | LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d", | ||
466 | LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti | ||
467 | ) | ||
468 | ); | ||
469 | |||
470 | TRACE_EVENT(drv_configure_filter, | 446 | TRACE_EVENT(drv_configure_filter, |
471 | TP_PROTO(struct ieee80211_local *local, | 447 | TP_PROTO(struct ieee80211_local *local, |
472 | unsigned int changed_flags, | 448 | unsigned int changed_flags, |
@@ -790,7 +766,7 @@ TRACE_EVENT(drv_sta_rc_update, | |||
790 | ) | 766 | ) |
791 | ); | 767 | ); |
792 | 768 | ||
793 | TRACE_EVENT(drv_sta_add, | 769 | DECLARE_EVENT_CLASS(sta_event, |
794 | TP_PROTO(struct ieee80211_local *local, | 770 | TP_PROTO(struct ieee80211_local *local, |
795 | struct ieee80211_sub_if_data *sdata, | 771 | struct ieee80211_sub_if_data *sdata, |
796 | struct ieee80211_sta *sta), | 772 | struct ieee80211_sta *sta), |
@@ -815,29 +791,25 @@ TRACE_EVENT(drv_sta_add, | |||
815 | ) | 791 | ) |
816 | ); | 792 | ); |
817 | 793 | ||
818 | TRACE_EVENT(drv_sta_remove, | 794 | DEFINE_EVENT(sta_event, drv_sta_add, |
819 | TP_PROTO(struct ieee80211_local *local, | 795 | TP_PROTO(struct ieee80211_local *local, |
820 | struct ieee80211_sub_if_data *sdata, | 796 | struct ieee80211_sub_if_data *sdata, |
821 | struct ieee80211_sta *sta), | 797 | struct ieee80211_sta *sta), |
798 | TP_ARGS(local, sdata, sta) | ||
799 | ); | ||
822 | 800 | ||
823 | TP_ARGS(local, sdata, sta), | 801 | DEFINE_EVENT(sta_event, drv_sta_remove, |
824 | 802 | TP_PROTO(struct ieee80211_local *local, | |
825 | TP_STRUCT__entry( | 803 | struct ieee80211_sub_if_data *sdata, |
826 | LOCAL_ENTRY | 804 | struct ieee80211_sta *sta), |
827 | VIF_ENTRY | 805 | TP_ARGS(local, sdata, sta) |
828 | STA_ENTRY | 806 | ); |
829 | ), | ||
830 | |||
831 | TP_fast_assign( | ||
832 | LOCAL_ASSIGN; | ||
833 | VIF_ASSIGN; | ||
834 | STA_ASSIGN; | ||
835 | ), | ||
836 | 807 | ||
837 | TP_printk( | 808 | DEFINE_EVENT(sta_event, drv_sta_pre_rcu_remove, |
838 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, | 809 | TP_PROTO(struct ieee80211_local *local, |
839 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG | 810 | struct ieee80211_sub_if_data *sdata, |
840 | ) | 811 | struct ieee80211_sta *sta), |
812 | TP_ARGS(local, sdata, sta) | ||
841 | ); | 813 | ); |
842 | 814 | ||
843 | TRACE_EVENT(drv_conf_tx, | 815 | TRACE_EVENT(drv_conf_tx, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6d59e21cdb9f..2f0e176e7989 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2549,7 +2549,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2549 | */ | 2549 | */ |
2550 | skb = dev_alloc_skb(local->tx_headroom + | 2550 | skb = dev_alloc_skb(local->tx_headroom + |
2551 | beacon->head_len + | 2551 | beacon->head_len + |
2552 | beacon->tail_len + 256); | 2552 | beacon->tail_len + 256 + |
2553 | local->hw.extra_beacon_tailroom); | ||
2553 | if (!skb) | 2554 | if (!skb) |
2554 | goto out; | 2555 | goto out; |
2555 | 2556 | ||
@@ -2581,7 +2582,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2581 | ieee80211_update_csa(sdata, presp); | 2582 | ieee80211_update_csa(sdata, presp); |
2582 | 2583 | ||
2583 | 2584 | ||
2584 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len); | 2585 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len + |
2586 | local->hw.extra_beacon_tailroom); | ||
2585 | if (!skb) | 2587 | if (!skb) |
2586 | goto out; | 2588 | goto out; |
2587 | skb_reserve(skb, local->tx_headroom); | 2589 | skb_reserve(skb, local->tx_headroom); |
@@ -2602,13 +2604,13 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2602 | ieee80211_update_csa(sdata, bcn); | 2604 | ieee80211_update_csa(sdata, bcn); |
2603 | 2605 | ||
2604 | if (ifmsh->sync_ops) | 2606 | if (ifmsh->sync_ops) |
2605 | ifmsh->sync_ops->adjust_tbtt( | 2607 | ifmsh->sync_ops->adjust_tbtt(sdata, bcn); |
2606 | sdata); | ||
2607 | 2608 | ||
2608 | skb = dev_alloc_skb(local->tx_headroom + | 2609 | skb = dev_alloc_skb(local->tx_headroom + |
2609 | bcn->head_len + | 2610 | bcn->head_len + |
2610 | 256 + /* TIM IE */ | 2611 | 256 + /* TIM IE */ |
2611 | bcn->tail_len); | 2612 | bcn->tail_len + |
2613 | local->hw.extra_beacon_tailroom); | ||
2612 | if (!skb) | 2614 | if (!skb) |
2613 | goto out; | 2615 | goto out; |
2614 | skb_reserve(skb, local->tx_headroom); | 2616 | skb_reserve(skb, local->tx_headroom); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 875e172c001c..591b46b72462 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -642,6 +642,17 @@ void ieee80211_iterate_active_interfaces_rtnl( | |||
642 | } | 642 | } |
643 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); | 643 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); |
644 | 644 | ||
645 | struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev) | ||
646 | { | ||
647 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
648 | |||
649 | if (!ieee80211_sdata_running(sdata) || | ||
650 | !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
651 | return NULL; | ||
652 | return &sdata->vif; | ||
653 | } | ||
654 | EXPORT_SYMBOL_GPL(wdev_to_ieee80211_vif); | ||
655 | |||
645 | /* | 656 | /* |
646 | * Nothing should have been stuffed into the workqueue during | 657 | * Nothing should have been stuffed into the workqueue during |
647 | * the suspend->resume cycle. If this WARN is seen then there | 658 | * the suspend->resume cycle. If this WARN is seen then there |
@@ -1451,6 +1462,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1451 | struct sta_info *sta; | 1462 | struct sta_info *sta; |
1452 | int res, i; | 1463 | int res, i; |
1453 | bool reconfig_due_to_wowlan = false; | 1464 | bool reconfig_due_to_wowlan = false; |
1465 | struct ieee80211_sub_if_data *sched_scan_sdata; | ||
1466 | bool sched_scan_stopped = false; | ||
1454 | 1467 | ||
1455 | #ifdef CONFIG_PM | 1468 | #ifdef CONFIG_PM |
1456 | if (local->suspended) | 1469 | if (local->suspended) |
@@ -1754,6 +1767,27 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1754 | #else | 1767 | #else |
1755 | WARN_ON(1); | 1768 | WARN_ON(1); |
1756 | #endif | 1769 | #endif |
1770 | |||
1771 | /* | ||
1772 | * Reconfigure sched scan if it was interrupted by FW restart or | ||
1773 | * suspend. | ||
1774 | */ | ||
1775 | mutex_lock(&local->mtx); | ||
1776 | sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata, | ||
1777 | lockdep_is_held(&local->mtx)); | ||
1778 | if (sched_scan_sdata && local->sched_scan_req) | ||
1779 | /* | ||
1780 | * Sched scan stopped, but we don't want to report it. Instead, | ||
1781 | * we're trying to reschedule. | ||
1782 | */ | ||
1783 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, | ||
1784 | local->sched_scan_req)) | ||
1785 | sched_scan_stopped = true; | ||
1786 | mutex_unlock(&local->mtx); | ||
1787 | |||
1788 | if (sched_scan_stopped) | ||
1789 | cfg80211_sched_scan_stopped(local->hw.wiphy); | ||
1790 | |||
1757 | return 0; | 1791 | return 0; |
1758 | } | 1792 | } |
1759 | 1793 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 06db6eb5258a..d89dee2259b5 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -203,17 +203,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | |||
203 | 203 | ||
204 | rdev->opencount--; | 204 | rdev->opencount--; |
205 | 205 | ||
206 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { | 206 | WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && |
207 | /* | 207 | !rdev->scan_req->notified); |
208 | * If the scan request wasn't notified as done, set it | ||
209 | * to aborted and leak it after a warning. The driver | ||
210 | * should have notified us that it ended at the latest | ||
211 | * during rdev_stop_p2p_device(). | ||
212 | */ | ||
213 | if (WARN_ON(!rdev->scan_req->notified)) | ||
214 | rdev->scan_req->aborted = true; | ||
215 | ___cfg80211_scan_done(rdev, !rdev->scan_req->notified); | ||
216 | } | ||
217 | } | 208 | } |
218 | 209 | ||
219 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 210 | static int cfg80211_rfkill_set_block(void *data, bool blocked) |
@@ -765,13 +756,16 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
765 | { | 756 | { |
766 | struct net_device *dev = wdev->netdev; | 757 | struct net_device *dev = wdev->netdev; |
767 | 758 | ||
759 | ASSERT_RTNL(); | ||
760 | |||
768 | switch (wdev->iftype) { | 761 | switch (wdev->iftype) { |
769 | case NL80211_IFTYPE_ADHOC: | 762 | case NL80211_IFTYPE_ADHOC: |
770 | cfg80211_leave_ibss(rdev, dev, true); | 763 | cfg80211_leave_ibss(rdev, dev, true); |
771 | break; | 764 | break; |
772 | case NL80211_IFTYPE_P2P_CLIENT: | 765 | case NL80211_IFTYPE_P2P_CLIENT: |
773 | case NL80211_IFTYPE_STATION: | 766 | case NL80211_IFTYPE_STATION: |
774 | __cfg80211_stop_sched_scan(rdev, false); | 767 | if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev) |
768 | __cfg80211_stop_sched_scan(rdev, false); | ||
775 | 769 | ||
776 | wdev_lock(wdev); | 770 | wdev_lock(wdev); |
777 | #ifdef CONFIG_CFG80211_WEXT | 771 | #ifdef CONFIG_CFG80211_WEXT |
@@ -865,11 +859,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
865 | break; | 859 | break; |
866 | case NETDEV_DOWN: | 860 | case NETDEV_DOWN: |
867 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); | 861 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); |
868 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { | 862 | WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && |
869 | if (WARN_ON(!rdev->scan_req->notified)) | 863 | !rdev->scan_req->notified); |
870 | rdev->scan_req->aborted = true; | ||
871 | ___cfg80211_scan_done(rdev, true); | ||
872 | } | ||
873 | 864 | ||
874 | if (WARN_ON(rdev->sched_scan_req && | 865 | if (WARN_ON(rdev->sched_scan_req && |
875 | rdev->sched_scan_req->dev == wdev->netdev)) { | 866 | rdev->sched_scan_req->dev == wdev->netdev)) { |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 0a277c33bb02..37ec16d7bb1a 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -67,9 +67,7 @@ struct cfg80211_registered_device { | |||
67 | struct work_struct scan_done_wk; | 67 | struct work_struct scan_done_wk; |
68 | struct work_struct sched_scan_results_wk; | 68 | struct work_struct sched_scan_results_wk; |
69 | 69 | ||
70 | #ifdef CONFIG_NL80211_TESTMODE | 70 | struct genl_info *cur_cmd_info; |
71 | struct genl_info *testmode_info; | ||
72 | #endif | ||
73 | 71 | ||
74 | struct work_struct conn_work; | 72 | struct work_struct conn_work; |
75 | struct work_struct event_work; | 73 | struct work_struct event_work; |
@@ -363,7 +361,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | |||
363 | struct key_params *params, int key_idx, | 361 | struct key_params *params, int key_idx, |
364 | bool pairwise, const u8 *mac_addr); | 362 | bool pairwise, const u8 *mac_addr); |
365 | void __cfg80211_scan_done(struct work_struct *wk); | 363 | void __cfg80211_scan_done(struct work_struct *wk); |
366 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); | 364 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); |
367 | void __cfg80211_sched_scan_results(struct work_struct *wk); | 365 | void __cfg80211_sched_scan_results(struct work_struct *wk); |
368 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 366 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, |
369 | bool driver_initiated); | 367 | bool driver_initiated); |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index b0e1869de7de..9c7a11ae7936 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -99,6 +99,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
99 | const struct mesh_config *conf) | 99 | const struct mesh_config *conf) |
100 | { | 100 | { |
101 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 101 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
102 | u8 radar_detect_width = 0; | ||
102 | int err; | 103 | int err; |
103 | 104 | ||
104 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); | 105 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); |
@@ -177,8 +178,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
177 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) | 178 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) |
178 | return -EINVAL; | 179 | return -EINVAL; |
179 | 180 | ||
180 | err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan, | 181 | err = cfg80211_chandef_dfs_required(wdev->wiphy, &setup->chandef); |
181 | CHAN_MODE_SHARED); | 182 | if (err < 0) |
183 | return err; | ||
184 | if (err) | ||
185 | radar_detect_width = BIT(setup->chandef.width); | ||
186 | |||
187 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | ||
188 | setup->chandef.chan, | ||
189 | CHAN_MODE_SHARED, | ||
190 | radar_detect_width); | ||
182 | if (err) | 191 | if (err) |
183 | return err; | 192 | return err; |
184 | 193 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a693f86e5970..04681a46eda8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -376,6 +376,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
376 | [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, | 376 | [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, |
377 | [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, | 377 | [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, |
378 | [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, | 378 | [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, |
379 | [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 }, | ||
380 | [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 }, | ||
381 | [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 }, | ||
382 | [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, | ||
379 | }; | 383 | }; |
380 | 384 | ||
381 | /* policy for the key attributes */ | 385 | /* policy for the key attributes */ |
@@ -1184,6 +1188,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1184 | struct nlattr *nl_bands, *nl_band; | 1188 | struct nlattr *nl_bands, *nl_band; |
1185 | struct nlattr *nl_freqs, *nl_freq; | 1189 | struct nlattr *nl_freqs, *nl_freq; |
1186 | struct nlattr *nl_cmds; | 1190 | struct nlattr *nl_cmds; |
1191 | struct nlattr *nl_vendor_cmds; | ||
1187 | enum ieee80211_band band; | 1192 | enum ieee80211_band band; |
1188 | struct ieee80211_channel *chan; | 1193 | struct ieee80211_channel *chan; |
1189 | int i; | 1194 | int i; |
@@ -1579,6 +1584,19 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1579 | (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || | 1584 | (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || |
1580 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) | 1585 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) |
1581 | goto nla_put_failure; | 1586 | goto nla_put_failure; |
1587 | state->split_start++; | ||
1588 | break; | ||
1589 | case 11: | ||
1590 | nl_vendor_cmds = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); | ||
1591 | if (!nl_vendor_cmds) | ||
1592 | goto nla_put_failure; | ||
1593 | |||
1594 | for (i = 0; i < dev->wiphy.n_vendor_commands; i++) | ||
1595 | if (nla_put(msg, i + 1, | ||
1596 | sizeof(struct nl80211_vendor_cmd_info), | ||
1597 | &dev->wiphy.vendor_commands[i].info)) | ||
1598 | goto nla_put_failure; | ||
1599 | nla_nest_end(msg, nl_vendor_cmds); | ||
1582 | 1600 | ||
1583 | /* done */ | 1601 | /* done */ |
1584 | state->split_start = 0; | 1602 | state->split_start = 0; |
@@ -4151,6 +4169,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
4151 | params.vht_capa = | 4169 | params.vht_capa = |
4152 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); | 4170 | nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); |
4153 | 4171 | ||
4172 | if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) { | ||
4173 | params.opmode_notif_used = true; | ||
4174 | params.opmode_notif = | ||
4175 | nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]); | ||
4176 | } | ||
4177 | |||
4154 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { | 4178 | if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) { |
4155 | params.plink_action = | 4179 | params.plink_action = |
4156 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 4180 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
@@ -5667,8 +5691,13 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5667 | struct net_device *dev = info->user_ptr[1]; | 5691 | struct net_device *dev = info->user_ptr[1]; |
5668 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 5692 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
5669 | struct cfg80211_chan_def chandef; | 5693 | struct cfg80211_chan_def chandef; |
5694 | enum nl80211_dfs_regions dfs_region; | ||
5670 | int err; | 5695 | int err; |
5671 | 5696 | ||
5697 | dfs_region = reg_get_dfs_region(wdev->wiphy); | ||
5698 | if (dfs_region == NL80211_DFS_UNSET) | ||
5699 | return -EINVAL; | ||
5700 | |||
5672 | err = nl80211_parse_chandef(rdev, info, &chandef); | 5701 | err = nl80211_parse_chandef(rdev, info, &chandef); |
5673 | if (err) | 5702 | if (err) |
5674 | return err; | 5703 | return err; |
@@ -6693,6 +6722,40 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info) | |||
6693 | return err; | 6722 | return err; |
6694 | } | 6723 | } |
6695 | 6724 | ||
6725 | static struct sk_buff * | ||
6726 | __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev, | ||
6727 | int approxlen, u32 portid, u32 seq, | ||
6728 | enum nl80211_commands cmd, | ||
6729 | enum nl80211_attrs attr, gfp_t gfp) | ||
6730 | { | ||
6731 | struct sk_buff *skb; | ||
6732 | void *hdr; | ||
6733 | struct nlattr *data; | ||
6734 | |||
6735 | skb = nlmsg_new(approxlen + 100, gfp); | ||
6736 | if (!skb) | ||
6737 | return NULL; | ||
6738 | |||
6739 | hdr = nl80211hdr_put(skb, portid, seq, 0, cmd); | ||
6740 | if (!hdr) { | ||
6741 | kfree_skb(skb); | ||
6742 | return NULL; | ||
6743 | } | ||
6744 | |||
6745 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) | ||
6746 | goto nla_put_failure; | ||
6747 | data = nla_nest_start(skb, attr); | ||
6748 | |||
6749 | ((void **)skb->cb)[0] = rdev; | ||
6750 | ((void **)skb->cb)[1] = hdr; | ||
6751 | ((void **)skb->cb)[2] = data; | ||
6752 | |||
6753 | return skb; | ||
6754 | |||
6755 | nla_put_failure: | ||
6756 | kfree_skb(skb); | ||
6757 | return NULL; | ||
6758 | } | ||
6696 | 6759 | ||
6697 | #ifdef CONFIG_NL80211_TESTMODE | 6760 | #ifdef CONFIG_NL80211_TESTMODE |
6698 | static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | 6761 | static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) |
@@ -6717,11 +6780,11 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) | |||
6717 | if (!info->attrs[NL80211_ATTR_TESTDATA]) | 6780 | if (!info->attrs[NL80211_ATTR_TESTDATA]) |
6718 | return -EINVAL; | 6781 | return -EINVAL; |
6719 | 6782 | ||
6720 | rdev->testmode_info = info; | 6783 | rdev->cur_cmd_info = info; |
6721 | err = rdev_testmode_cmd(rdev, wdev, | 6784 | err = rdev_testmode_cmd(rdev, wdev, |
6722 | nla_data(info->attrs[NL80211_ATTR_TESTDATA]), | 6785 | nla_data(info->attrs[NL80211_ATTR_TESTDATA]), |
6723 | nla_len(info->attrs[NL80211_ATTR_TESTDATA])); | 6786 | nla_len(info->attrs[NL80211_ATTR_TESTDATA])); |
6724 | rdev->testmode_info = NULL; | 6787 | rdev->cur_cmd_info = NULL; |
6725 | 6788 | ||
6726 | return err; | 6789 | return err; |
6727 | } | 6790 | } |
@@ -6821,77 +6884,14 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6821 | return err; | 6884 | return err; |
6822 | } | 6885 | } |
6823 | 6886 | ||
6824 | static struct sk_buff * | ||
6825 | __cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev, | ||
6826 | int approxlen, u32 portid, u32 seq, gfp_t gfp) | ||
6827 | { | ||
6828 | struct sk_buff *skb; | ||
6829 | void *hdr; | ||
6830 | struct nlattr *data; | ||
6831 | |||
6832 | skb = nlmsg_new(approxlen + 100, gfp); | ||
6833 | if (!skb) | ||
6834 | return NULL; | ||
6835 | |||
6836 | hdr = nl80211hdr_put(skb, portid, seq, 0, NL80211_CMD_TESTMODE); | ||
6837 | if (!hdr) { | ||
6838 | kfree_skb(skb); | ||
6839 | return NULL; | ||
6840 | } | ||
6841 | |||
6842 | if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx)) | ||
6843 | goto nla_put_failure; | ||
6844 | data = nla_nest_start(skb, NL80211_ATTR_TESTDATA); | ||
6845 | |||
6846 | ((void **)skb->cb)[0] = rdev; | ||
6847 | ((void **)skb->cb)[1] = hdr; | ||
6848 | ((void **)skb->cb)[2] = data; | ||
6849 | |||
6850 | return skb; | ||
6851 | |||
6852 | nla_put_failure: | ||
6853 | kfree_skb(skb); | ||
6854 | return NULL; | ||
6855 | } | ||
6856 | |||
6857 | struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, | ||
6858 | int approxlen) | ||
6859 | { | ||
6860 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
6861 | |||
6862 | if (WARN_ON(!rdev->testmode_info)) | ||
6863 | return NULL; | ||
6864 | |||
6865 | return __cfg80211_testmode_alloc_skb(rdev, approxlen, | ||
6866 | rdev->testmode_info->snd_portid, | ||
6867 | rdev->testmode_info->snd_seq, | ||
6868 | GFP_KERNEL); | ||
6869 | } | ||
6870 | EXPORT_SYMBOL(cfg80211_testmode_alloc_reply_skb); | ||
6871 | |||
6872 | int cfg80211_testmode_reply(struct sk_buff *skb) | ||
6873 | { | ||
6874 | struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0]; | ||
6875 | void *hdr = ((void **)skb->cb)[1]; | ||
6876 | struct nlattr *data = ((void **)skb->cb)[2]; | ||
6877 | |||
6878 | if (WARN_ON(!rdev->testmode_info)) { | ||
6879 | kfree_skb(skb); | ||
6880 | return -EINVAL; | ||
6881 | } | ||
6882 | |||
6883 | nla_nest_end(skb, data); | ||
6884 | genlmsg_end(skb, hdr); | ||
6885 | return genlmsg_reply(skb, rdev->testmode_info); | ||
6886 | } | ||
6887 | EXPORT_SYMBOL(cfg80211_testmode_reply); | ||
6888 | |||
6889 | struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, | 6887 | struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, |
6890 | int approxlen, gfp_t gfp) | 6888 | int approxlen, gfp_t gfp) |
6891 | { | 6889 | { |
6892 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 6890 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
6893 | 6891 | ||
6894 | return __cfg80211_testmode_alloc_skb(rdev, approxlen, 0, 0, gfp); | 6892 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, 0, 0, |
6893 | NL80211_CMD_TESTMODE, | ||
6894 | NL80211_ATTR_TESTDATA, gfp); | ||
6895 | } | 6895 | } |
6896 | EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb); | 6896 | EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb); |
6897 | 6897 | ||
@@ -7328,11 +7328,72 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, | |||
7328 | return true; | 7328 | return true; |
7329 | } | 7329 | } |
7330 | 7330 | ||
7331 | static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map) | ||
7332 | { | ||
7333 | u16 mcs_mask = 0; | ||
7334 | |||
7335 | switch (vht_mcs_map) { | ||
7336 | case IEEE80211_VHT_MCS_NOT_SUPPORTED: | ||
7337 | break; | ||
7338 | case IEEE80211_VHT_MCS_SUPPORT_0_7: | ||
7339 | mcs_mask = 0x00FF; | ||
7340 | break; | ||
7341 | case IEEE80211_VHT_MCS_SUPPORT_0_8: | ||
7342 | mcs_mask = 0x01FF; | ||
7343 | break; | ||
7344 | case IEEE80211_VHT_MCS_SUPPORT_0_9: | ||
7345 | mcs_mask = 0x03FF; | ||
7346 | break; | ||
7347 | default: | ||
7348 | break; | ||
7349 | } | ||
7350 | |||
7351 | return mcs_mask; | ||
7352 | } | ||
7353 | |||
7354 | static void vht_build_mcs_mask(u16 vht_mcs_map, | ||
7355 | u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) | ||
7356 | { | ||
7357 | u8 nss; | ||
7358 | |||
7359 | for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) { | ||
7360 | vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03); | ||
7361 | vht_mcs_map >>= 2; | ||
7362 | } | ||
7363 | } | ||
7364 | |||
7365 | static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband, | ||
7366 | struct nl80211_txrate_vht *txrate, | ||
7367 | u16 mcs[NL80211_VHT_NSS_MAX]) | ||
7368 | { | ||
7369 | u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); | ||
7370 | u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {}; | ||
7371 | u8 i; | ||
7372 | |||
7373 | if (!sband->vht_cap.vht_supported) | ||
7374 | return false; | ||
7375 | |||
7376 | memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX); | ||
7377 | |||
7378 | /* Build vht_mcs_mask from VHT capabilities */ | ||
7379 | vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask); | ||
7380 | |||
7381 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) { | ||
7382 | if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i]) | ||
7383 | mcs[i] = txrate->mcs[i]; | ||
7384 | else | ||
7385 | return false; | ||
7386 | } | ||
7387 | |||
7388 | return true; | ||
7389 | } | ||
7390 | |||
7331 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { | 7391 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { |
7332 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, | 7392 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, |
7333 | .len = NL80211_MAX_SUPP_RATES }, | 7393 | .len = NL80211_MAX_SUPP_RATES }, |
7334 | [NL80211_TXRATE_MCS] = { .type = NLA_BINARY, | 7394 | [NL80211_TXRATE_HT] = { .type = NLA_BINARY, |
7335 | .len = NL80211_MAX_SUPP_HT_RATES }, | 7395 | .len = NL80211_MAX_SUPP_HT_RATES }, |
7396 | [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)}, | ||
7336 | }; | 7397 | }; |
7337 | 7398 | ||
7338 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | 7399 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, |
@@ -7345,9 +7406,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7345 | struct net_device *dev = info->user_ptr[1]; | 7406 | struct net_device *dev = info->user_ptr[1]; |
7346 | struct nlattr *tx_rates; | 7407 | struct nlattr *tx_rates; |
7347 | struct ieee80211_supported_band *sband; | 7408 | struct ieee80211_supported_band *sband; |
7348 | 7409 | u16 vht_tx_mcs_map; | |
7349 | if (info->attrs[NL80211_ATTR_TX_RATES] == NULL) | ||
7350 | return -EINVAL; | ||
7351 | 7410 | ||
7352 | if (!rdev->ops->set_bitrate_mask) | 7411 | if (!rdev->ops->set_bitrate_mask) |
7353 | return -EOPNOTSUPP; | 7412 | return -EOPNOTSUPP; |
@@ -7356,17 +7415,26 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7356 | /* Default to all rates enabled */ | 7415 | /* Default to all rates enabled */ |
7357 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 7416 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
7358 | sband = rdev->wiphy.bands[i]; | 7417 | sband = rdev->wiphy.bands[i]; |
7359 | mask.control[i].legacy = | 7418 | |
7360 | sband ? (1 << sband->n_bitrates) - 1 : 0; | 7419 | if (!sband) |
7361 | if (sband) | 7420 | continue; |
7362 | memcpy(mask.control[i].mcs, | 7421 | |
7363 | sband->ht_cap.mcs.rx_mask, | 7422 | mask.control[i].legacy = (1 << sband->n_bitrates) - 1; |
7364 | sizeof(mask.control[i].mcs)); | 7423 | memcpy(mask.control[i].ht_mcs, |
7365 | else | 7424 | sband->ht_cap.mcs.rx_mask, |
7366 | memset(mask.control[i].mcs, 0, | 7425 | sizeof(mask.control[i].ht_mcs)); |
7367 | sizeof(mask.control[i].mcs)); | 7426 | |
7427 | if (!sband->vht_cap.vht_supported) | ||
7428 | continue; | ||
7429 | |||
7430 | vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); | ||
7431 | vht_build_mcs_mask(vht_tx_mcs_map, mask.control[i].vht_mcs); | ||
7368 | } | 7432 | } |
7369 | 7433 | ||
7434 | /* if no rates are given set it back to the defaults */ | ||
7435 | if (!info->attrs[NL80211_ATTR_TX_RATES]) | ||
7436 | goto out; | ||
7437 | |||
7370 | /* | 7438 | /* |
7371 | * The nested attribute uses enum nl80211_band as the index. This maps | 7439 | * The nested attribute uses enum nl80211_band as the index. This maps |
7372 | * directly to the enum ieee80211_band values used in cfg80211. | 7440 | * directly to the enum ieee80211_band values used in cfg80211. |
@@ -7391,31 +7459,44 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7391 | nla_len(tb[NL80211_TXRATE_LEGACY])) | 7459 | nla_len(tb[NL80211_TXRATE_LEGACY])) |
7392 | return -EINVAL; | 7460 | return -EINVAL; |
7393 | } | 7461 | } |
7394 | if (tb[NL80211_TXRATE_MCS]) { | 7462 | if (tb[NL80211_TXRATE_HT]) { |
7395 | if (!ht_rateset_to_mask( | 7463 | if (!ht_rateset_to_mask( |
7396 | sband, | 7464 | sband, |
7397 | nla_data(tb[NL80211_TXRATE_MCS]), | 7465 | nla_data(tb[NL80211_TXRATE_HT]), |
7398 | nla_len(tb[NL80211_TXRATE_MCS]), | 7466 | nla_len(tb[NL80211_TXRATE_HT]), |
7399 | mask.control[band].mcs)) | 7467 | mask.control[band].ht_mcs)) |
7468 | return -EINVAL; | ||
7469 | } | ||
7470 | if (tb[NL80211_TXRATE_VHT]) { | ||
7471 | if (!vht_set_mcs_mask( | ||
7472 | sband, | ||
7473 | nla_data(tb[NL80211_TXRATE_VHT]), | ||
7474 | mask.control[band].vht_mcs)) | ||
7400 | return -EINVAL; | 7475 | return -EINVAL; |
7401 | } | 7476 | } |
7402 | 7477 | ||
7403 | if (mask.control[band].legacy == 0) { | 7478 | if (mask.control[band].legacy == 0) { |
7404 | /* don't allow empty legacy rates if HT | 7479 | /* don't allow empty legacy rates if HT or VHT |
7405 | * is not even supported. */ | 7480 | * are not even supported. |
7406 | if (!rdev->wiphy.bands[band]->ht_cap.ht_supported) | 7481 | */ |
7482 | if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported || | ||
7483 | rdev->wiphy.bands[band]->vht_cap.vht_supported)) | ||
7407 | return -EINVAL; | 7484 | return -EINVAL; |
7408 | 7485 | ||
7409 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | 7486 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) |
7410 | if (mask.control[band].mcs[i]) | 7487 | if (mask.control[band].ht_mcs[i]) |
7411 | break; | 7488 | goto out; |
7489 | |||
7490 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) | ||
7491 | if (mask.control[band].vht_mcs[i]) | ||
7492 | goto out; | ||
7412 | 7493 | ||
7413 | /* legacy and mcs rates may not be both empty */ | 7494 | /* legacy and mcs rates may not be both empty */ |
7414 | if (i == IEEE80211_HT_MCS_MASK_LEN) | 7495 | return -EINVAL; |
7415 | return -EINVAL; | ||
7416 | } | 7496 | } |
7417 | } | 7497 | } |
7418 | 7498 | ||
7499 | out: | ||
7419 | return rdev_set_bitrate_mask(rdev, dev, NULL, &mask); | 7500 | return rdev_set_bitrate_mask(rdev, dev, NULL, &mask); |
7420 | } | 7501 | } |
7421 | 7502 | ||
@@ -8875,6 +8956,111 @@ static int nl80211_crit_protocol_stop(struct sk_buff *skb, | |||
8875 | return 0; | 8956 | return 0; |
8876 | } | 8957 | } |
8877 | 8958 | ||
8959 | static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info) | ||
8960 | { | ||
8961 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
8962 | struct wireless_dev *wdev = | ||
8963 | __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs); | ||
8964 | int i, err; | ||
8965 | u32 vid, subcmd; | ||
8966 | |||
8967 | if (!rdev->wiphy.vendor_commands) | ||
8968 | return -EOPNOTSUPP; | ||
8969 | |||
8970 | if (IS_ERR(wdev)) { | ||
8971 | err = PTR_ERR(wdev); | ||
8972 | if (err != -EINVAL) | ||
8973 | return err; | ||
8974 | wdev = NULL; | ||
8975 | } else if (wdev->wiphy != &rdev->wiphy) { | ||
8976 | return -EINVAL; | ||
8977 | } | ||
8978 | |||
8979 | if (!info->attrs[NL80211_ATTR_VENDOR_ID] || | ||
8980 | !info->attrs[NL80211_ATTR_VENDOR_SUBCMD]) | ||
8981 | return -EINVAL; | ||
8982 | |||
8983 | vid = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_ID]); | ||
8984 | subcmd = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_SUBCMD]); | ||
8985 | for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) { | ||
8986 | const struct wiphy_vendor_command *vcmd; | ||
8987 | void *data = NULL; | ||
8988 | int len = 0; | ||
8989 | |||
8990 | vcmd = &rdev->wiphy.vendor_commands[i]; | ||
8991 | |||
8992 | if (vcmd->info.vendor_id != vid || vcmd->info.subcmd != subcmd) | ||
8993 | continue; | ||
8994 | |||
8995 | if (vcmd->flags & (WIPHY_VENDOR_CMD_NEED_WDEV | | ||
8996 | WIPHY_VENDOR_CMD_NEED_NETDEV)) { | ||
8997 | if (!wdev) | ||
8998 | return -EINVAL; | ||
8999 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_NETDEV && | ||
9000 | !wdev->netdev) | ||
9001 | return -EINVAL; | ||
9002 | |||
9003 | if (vcmd->flags & WIPHY_VENDOR_CMD_NEED_RUNNING) { | ||
9004 | if (wdev->netdev && | ||
9005 | !netif_running(wdev->netdev)) | ||
9006 | return -ENETDOWN; | ||
9007 | if (!wdev->netdev && !wdev->p2p_started) | ||
9008 | return -ENETDOWN; | ||
9009 | } | ||
9010 | } else { | ||
9011 | wdev = NULL; | ||
9012 | } | ||
9013 | |||
9014 | if (info->attrs[NL80211_ATTR_VENDOR_DATA]) { | ||
9015 | data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]); | ||
9016 | len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]); | ||
9017 | } | ||
9018 | |||
9019 | rdev->cur_cmd_info = info; | ||
9020 | err = rdev->wiphy.vendor_commands[i].doit(&rdev->wiphy, wdev, | ||
9021 | data, len); | ||
9022 | rdev->cur_cmd_info = NULL; | ||
9023 | return err; | ||
9024 | } | ||
9025 | |||
9026 | return -EOPNOTSUPP; | ||
9027 | } | ||
9028 | |||
9029 | struct sk_buff *__cfg80211_alloc_reply_skb(struct wiphy *wiphy, | ||
9030 | enum nl80211_commands cmd, | ||
9031 | enum nl80211_attrs attr, | ||
9032 | int approxlen) | ||
9033 | { | ||
9034 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
9035 | |||
9036 | if (WARN_ON(!rdev->cur_cmd_info)) | ||
9037 | return NULL; | ||
9038 | |||
9039 | return __cfg80211_alloc_vendor_skb(rdev, approxlen, | ||
9040 | rdev->cur_cmd_info->snd_portid, | ||
9041 | rdev->cur_cmd_info->snd_seq, | ||
9042 | cmd, attr, GFP_KERNEL); | ||
9043 | } | ||
9044 | EXPORT_SYMBOL(__cfg80211_alloc_reply_skb); | ||
9045 | |||
9046 | int cfg80211_vendor_cmd_reply(struct sk_buff *skb) | ||
9047 | { | ||
9048 | struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0]; | ||
9049 | void *hdr = ((void **)skb->cb)[1]; | ||
9050 | struct nlattr *data = ((void **)skb->cb)[2]; | ||
9051 | |||
9052 | if (WARN_ON(!rdev->cur_cmd_info)) { | ||
9053 | kfree_skb(skb); | ||
9054 | return -EINVAL; | ||
9055 | } | ||
9056 | |||
9057 | nla_nest_end(skb, data); | ||
9058 | genlmsg_end(skb, hdr); | ||
9059 | return genlmsg_reply(skb, rdev->cur_cmd_info); | ||
9060 | } | ||
9061 | EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply); | ||
9062 | |||
9063 | |||
8878 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 9064 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
8879 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 9065 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
8880 | #define NL80211_FLAG_NEED_RTNL 0x04 | 9066 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -9599,6 +9785,14 @@ static const struct genl_ops nl80211_ops[] = { | |||
9599 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 9785 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
9600 | NL80211_FLAG_NEED_RTNL, | 9786 | NL80211_FLAG_NEED_RTNL, |
9601 | }, | 9787 | }, |
9788 | { | ||
9789 | .cmd = NL80211_CMD_VENDOR, | ||
9790 | .doit = nl80211_vendor_cmd, | ||
9791 | .policy = nl80211_policy, | ||
9792 | .flags = GENL_ADMIN_PERM, | ||
9793 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
9794 | NL80211_FLAG_NEED_RTNL, | ||
9795 | }, | ||
9602 | }; | 9796 | }; |
9603 | 9797 | ||
9604 | /* notification functions */ | 9798 | /* notification functions */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ec54e1aac8e2..7d20d844ca60 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -135,6 +135,33 @@ static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region) | |||
135 | return "Unknown"; | 135 | return "Unknown"; |
136 | } | 136 | } |
137 | 137 | ||
138 | enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy) | ||
139 | { | ||
140 | const struct ieee80211_regdomain *regd = NULL; | ||
141 | const struct ieee80211_regdomain *wiphy_regd = NULL; | ||
142 | |||
143 | regd = get_cfg80211_regdom(); | ||
144 | if (!wiphy) | ||
145 | goto out; | ||
146 | |||
147 | wiphy_regd = get_wiphy_regdom(wiphy); | ||
148 | if (!wiphy_regd) | ||
149 | goto out; | ||
150 | |||
151 | if (wiphy_regd->dfs_region == regd->dfs_region) | ||
152 | goto out; | ||
153 | |||
154 | REG_DBG_PRINT("%s: device specific dfs_region " | ||
155 | "(%s) disagrees with cfg80211's " | ||
156 | "central dfs_region (%s)\n", | ||
157 | dev_name(&wiphy->dev), | ||
158 | reg_dfs_region_str(wiphy_regd->dfs_region), | ||
159 | reg_dfs_region_str(regd->dfs_region)); | ||
160 | |||
161 | out: | ||
162 | return regd->dfs_region; | ||
163 | } | ||
164 | |||
138 | static void rcu_free_regdom(const struct ieee80211_regdomain *r) | 165 | static void rcu_free_regdom(const struct ieee80211_regdomain *r) |
139 | { | 166 | { |
140 | if (!r) | 167 | if (!r) |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index cc4c2c0a6723..02bd8f4b0921 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -21,6 +21,7 @@ extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; | |||
21 | bool reg_is_valid_request(const char *alpha2); | 21 | bool reg_is_valid_request(const char *alpha2); |
22 | bool is_world_regdom(const char *alpha2); | 22 | bool is_world_regdom(const char *alpha2); |
23 | bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region); | 23 | bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region); |
24 | enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy); | ||
24 | 25 | ||
25 | int regulatory_hint_user(const char *alpha2, | 26 | int regulatory_hint_user(const char *alpha2, |
26 | enum nl80211_user_reg_hint_type user_reg_hint_type); | 27 | enum nl80211_user_reg_hint_type user_reg_hint_type); |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d4397eba5408..a32d52a04c27 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -161,7 +161,7 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, | |||
161 | dev->bss_generation++; | 161 | dev->bss_generation++; |
162 | } | 162 | } |
163 | 163 | ||
164 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | 164 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) |
165 | { | 165 | { |
166 | struct cfg80211_scan_request *request; | 166 | struct cfg80211_scan_request *request; |
167 | struct wireless_dev *wdev; | 167 | struct wireless_dev *wdev; |
@@ -210,17 +210,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | |||
210 | dev_put(wdev->netdev); | 210 | dev_put(wdev->netdev); |
211 | 211 | ||
212 | rdev->scan_req = NULL; | 212 | rdev->scan_req = NULL; |
213 | 213 | kfree(request); | |
214 | /* | ||
215 | * OK. If this is invoked with "leak" then we can't | ||
216 | * free this ... but we've cleaned it up anyway. The | ||
217 | * driver failed to call the scan_done callback, so | ||
218 | * all bets are off, it might still be trying to use | ||
219 | * the scan request or not ... if it accesses the dev | ||
220 | * in there (it shouldn't anyway) then it may crash. | ||
221 | */ | ||
222 | if (!leak) | ||
223 | kfree(request); | ||
224 | } | 214 | } |
225 | 215 | ||
226 | void __cfg80211_scan_done(struct work_struct *wk) | 216 | void __cfg80211_scan_done(struct work_struct *wk) |
@@ -231,7 +221,7 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
231 | scan_done_wk); | 221 | scan_done_wk); |
232 | 222 | ||
233 | rtnl_lock(); | 223 | rtnl_lock(); |
234 | ___cfg80211_scan_done(rdev, false); | 224 | ___cfg80211_scan_done(rdev); |
235 | rtnl_unlock(); | 225 | rtnl_unlock(); |
236 | } | 226 | } |
237 | 227 | ||