diff options
author | David S. Miller <davem@davemloft.net> | 2015-02-09 15:07:20 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-09 15:13:58 -0500 |
commit | c8ac18f2006b2926ce375c01646b2f487d1c33b2 (patch) | |
tree | 29e53fe6b19cf0cae4372353624a1dd8f0589824 | |
parent | 93c1af6ca94c1e763efba76a127b5c135e3d23a6 (diff) | |
parent | d53071143aa5a7cb37cf7db8101042e700b5413f (diff) |
Merge tag 'wireless-drivers-next-for-davem-2015-02-07' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Major changes:
iwlwifi:
* more work for new devices (4165 / 8260)
* cleanups / improvemnts in rate control
* fixes for TDLS
* major statistics work from Johannes - more to come
* improvements for the fw error dump infrastructure
* usual amount of small fixes here and there (scan, D0i3 etc...)
* add support for beamforming
* enable stuck queue detection for iwlmvm
* a few fixes for EBS scan
* fixes for various failure paths
* improvements for TDLS Offchannel
wil6210:
* performance tuning
* some AP features
brcm80211:
* rework some code in SDIO part of the brcmfmac driver related to
suspend/resume that were found doing stress testing
* in PCIe part scheduling of worker thread needed to be relaxed
* minor fixes and exposing firmware revision information to
user-space, ie. ethtool.
mwifiex:
* enhancements for change virtual interface handling
* remove coupling between netdev and FW supported interface
combination, now conversion from any type of supported interface
types to any other type is possible
* DFS support in AP mode
ath9k:
* fix calibration issues on some boards
* Wake-on-WLAN improvements
ath10k:
* add support for qca6174 hardware
* enable RX batching to reduce CPU load
Conflicts:
drivers/net/wireless/rtlwifi/pci.c
Conflict resolution is to get rid of the 'end' label and keep
the rest.
Signed-off-by: David S. Miller <davem@davemloft.net>
173 files changed, 6463 insertions, 2183 deletions
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 3f314c98d089..ac6c5fca906d 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -107,6 +107,14 @@ extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc); | |||
107 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 107 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE |
108 | bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); | 108 | bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); |
109 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | 109 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); |
110 | #else | ||
111 | static inline bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) | ||
112 | { | ||
113 | return false; | ||
114 | } | ||
115 | static inline void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | ||
116 | { | ||
117 | } | ||
110 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 118 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ |
111 | 119 | ||
112 | #ifdef CONFIG_BCMA_DRIVER_GPIO | 120 | #ifdef CONFIG_BCMA_DRIVER_GPIO |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 84d4a95e6caf..b7c8a8d4e6d1 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -178,7 +178,6 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |||
178 | u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) | 178 | u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) |
179 | { | 179 | { |
180 | u32 maxt; | 180 | u32 maxt; |
181 | enum bcma_clkmode clkmode; | ||
182 | 181 | ||
183 | maxt = bcma_chipco_watchdog_get_max_timer(cc); | 182 | maxt = bcma_chipco_watchdog_get_max_timer(cc); |
184 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | 183 | if (cc->capabilities & BCMA_CC_CAP_PMU) { |
@@ -188,8 +187,13 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) | |||
188 | ticks = maxt; | 187 | ticks = maxt; |
189 | bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); | 188 | bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); |
190 | } else { | 189 | } else { |
191 | clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC; | 190 | struct bcma_bus *bus = cc->core->bus; |
192 | bcma_core_set_clockmode(cc->core, clkmode); | 191 | |
192 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 && | ||
193 | bus->chipinfo.id != BCMA_CHIP_ID_BCM53018) | ||
194 | bcma_core_set_clockmode(cc->core, | ||
195 | ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC); | ||
196 | |||
193 | if (ticks > maxt) | 197 | if (ticks > maxt) |
194 | ticks = maxt; | 198 | ticks = maxt; |
195 | /* instant NMI */ | 199 | /* instant NMI */ |
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 50329d1057ed..786666488a2d 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c | |||
@@ -145,6 +145,47 @@ static u16 bcma_pcie_mdio_writeread(struct bcma_drv_pci *pc, u16 device, | |||
145 | } | 145 | } |
146 | 146 | ||
147 | /************************************************** | 147 | /************************************************** |
148 | * Early init. | ||
149 | **************************************************/ | ||
150 | |||
151 | static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) | ||
152 | { | ||
153 | struct bcma_device *core = pc->core; | ||
154 | u16 val16, core_index; | ||
155 | uint regoff; | ||
156 | |||
157 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); | ||
158 | core_index = (u16)core->core_index; | ||
159 | |||
160 | val16 = pcicore_read16(pc, regoff); | ||
161 | if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) | ||
162 | != core_index) { | ||
163 | val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | | ||
164 | (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); | ||
165 | pcicore_write16(pc, regoff, val16); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Apply some early fixes required before accessing SPROM. | ||
171 | * See also si_pci_fixcfg. | ||
172 | */ | ||
173 | void bcma_core_pci_early_init(struct bcma_drv_pci *pc) | ||
174 | { | ||
175 | if (pc->early_setup_done) | ||
176 | return; | ||
177 | |||
178 | pc->hostmode = bcma_core_pci_is_in_hostmode(pc); | ||
179 | if (pc->hostmode) | ||
180 | goto out; | ||
181 | |||
182 | bcma_core_pci_fixcfg(pc); | ||
183 | |||
184 | out: | ||
185 | pc->early_setup_done = true; | ||
186 | } | ||
187 | |||
188 | /************************************************** | ||
148 | * Workarounds. | 189 | * Workarounds. |
149 | **************************************************/ | 190 | **************************************************/ |
150 | 191 | ||
@@ -175,24 +216,6 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) | |||
175 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); | 216 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); |
176 | } | 217 | } |
177 | 218 | ||
178 | static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) | ||
179 | { | ||
180 | struct bcma_device *core = pc->core; | ||
181 | u16 val16, core_index; | ||
182 | uint regoff; | ||
183 | |||
184 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); | ||
185 | core_index = (u16)core->core_index; | ||
186 | |||
187 | val16 = pcicore_read16(pc, regoff); | ||
188 | if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) | ||
189 | != core_index) { | ||
190 | val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | | ||
191 | (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); | ||
192 | pcicore_write16(pc, regoff, val16); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ | 219 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ |
197 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | 220 | /* Needs to happen when coming out of 'standby'/'hibernate' */ |
198 | static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) | 221 | static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) |
@@ -216,7 +239,6 @@ static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) | |||
216 | 239 | ||
217 | static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) | 240 | static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) |
218 | { | 241 | { |
219 | bcma_core_pci_fixcfg(pc); | ||
220 | bcma_pcicore_serdes_workaround(pc); | 242 | bcma_pcicore_serdes_workaround(pc); |
221 | bcma_core_pci_config_fixup(pc); | 243 | bcma_core_pci_config_fixup(pc); |
222 | } | 244 | } |
@@ -226,13 +248,11 @@ void bcma_core_pci_init(struct bcma_drv_pci *pc) | |||
226 | if (pc->setup_done) | 248 | if (pc->setup_done) |
227 | return; | 249 | return; |
228 | 250 | ||
229 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 251 | bcma_core_pci_early_init(pc); |
230 | pc->hostmode = bcma_core_pci_is_in_hostmode(pc); | 252 | |
231 | if (pc->hostmode) | 253 | if (pc->hostmode) |
232 | bcma_core_pci_hostmode_init(pc); | 254 | bcma_core_pci_hostmode_init(pc); |
233 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 255 | else |
234 | |||
235 | if (!pc->hostmode) | ||
236 | bcma_core_pci_clientmode_init(pc); | 256 | bcma_core_pci_clientmode_init(pc); |
237 | } | 257 | } |
238 | 258 | ||
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index cd9161a8b3a1..53c6a8a58859 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -13,10 +13,12 @@ | |||
13 | 13 | ||
14 | static void bcma_host_pci_switch_core(struct bcma_device *core) | 14 | static void bcma_host_pci_switch_core(struct bcma_device *core) |
15 | { | 15 | { |
16 | int win2 = core->bus->host_is_pcie2 ? | ||
17 | BCMA_PCIE2_BAR0_WIN2 : BCMA_PCI_BAR0_WIN2; | ||
18 | |||
16 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, | 19 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, |
17 | core->addr); | 20 | core->addr); |
18 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, | 21 | pci_write_config_dword(core->bus->host_pci, win2, core->wrap); |
19 | core->wrap); | ||
20 | core->bus->mapped_core = core; | 22 | core->bus->mapped_core = core; |
21 | bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); | 23 | bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); |
22 | } | 24 | } |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index c3c5e0a2d5be..38bde6eab8a4 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -368,12 +368,19 @@ static void bcma_unregister_cores(struct bcma_bus *bus) | |||
368 | struct bcma_device *core, *tmp; | 368 | struct bcma_device *core, *tmp; |
369 | 369 | ||
370 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { | 370 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { |
371 | if (!core->dev_registered) | ||
372 | continue; | ||
371 | list_del(&core->list); | 373 | list_del(&core->list); |
372 | if (core->dev_registered) | 374 | device_unregister(&core->dev); |
373 | device_unregister(&core->dev); | ||
374 | } | 375 | } |
375 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | 376 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) |
376 | platform_device_unregister(bus->drv_cc.watchdog); | 377 | platform_device_unregister(bus->drv_cc.watchdog); |
378 | |||
379 | /* Now noone uses internally-handled cores, we can free them */ | ||
380 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { | ||
381 | list_del(&core->list); | ||
382 | kfree(core); | ||
383 | } | ||
377 | } | 384 | } |
378 | 385 | ||
379 | int bcma_bus_register(struct bcma_bus *bus) | 386 | int bcma_bus_register(struct bcma_bus *bus) |
@@ -395,6 +402,13 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
395 | bcma_core_chipcommon_early_init(&bus->drv_cc); | 402 | bcma_core_chipcommon_early_init(&bus->drv_cc); |
396 | } | 403 | } |
397 | 404 | ||
405 | /* Early init PCIE core */ | ||
406 | core = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
407 | if (core) { | ||
408 | bus->drv_pci[0].core = core; | ||
409 | bcma_core_pci_early_init(&bus->drv_pci[0]); | ||
410 | } | ||
411 | |||
398 | /* Cores providing flash access go before SPROM init */ | 412 | /* Cores providing flash access go before SPROM init */ |
399 | list_for_each_entry(core, &bus->cores, list) { | 413 | list_for_each_entry(core, &bus->cores, list) { |
400 | if (bcma_is_core_needed_early(core->id.id)) | 414 | if (bcma_is_core_needed_early(core->id.id)) |
@@ -467,7 +481,6 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
467 | 481 | ||
468 | void bcma_bus_unregister(struct bcma_bus *bus) | 482 | void bcma_bus_unregister(struct bcma_bus *bus) |
469 | { | 483 | { |
470 | struct bcma_device *cores[3]; | ||
471 | int err; | 484 | int err; |
472 | 485 | ||
473 | err = bcma_gpio_unregister(&bus->drv_cc); | 486 | err = bcma_gpio_unregister(&bus->drv_cc); |
@@ -478,15 +491,7 @@ void bcma_bus_unregister(struct bcma_bus *bus) | |||
478 | 491 | ||
479 | bcma_core_chipcommon_b_free(&bus->drv_cc_b); | 492 | bcma_core_chipcommon_b_free(&bus->drv_cc_b); |
480 | 493 | ||
481 | cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | ||
482 | cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
483 | cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); | ||
484 | |||
485 | bcma_unregister_cores(bus); | 494 | bcma_unregister_cores(bus); |
486 | |||
487 | kfree(cores[2]); | ||
488 | kfree(cores[1]); | ||
489 | kfree(cores[0]); | ||
490 | } | 495 | } |
491 | 496 | ||
492 | /* | 497 | /* |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index efb037f9c98a..206edd3ba668 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -579,7 +579,8 @@ int bcma_sprom_get(struct bcma_bus *bus) | |||
579 | u16 offset = BCMA_CC_SPROM; | 579 | u16 offset = BCMA_CC_SPROM; |
580 | u16 *sprom; | 580 | u16 *sprom; |
581 | size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, | 581 | size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, |
582 | SSB_SPROMSIZE_WORDS_R10, }; | 582 | SSB_SPROMSIZE_WORDS_R10, |
583 | SSB_SPROMSIZE_WORDS_R11, }; | ||
583 | int i, err = 0; | 584 | int i, err = 0; |
584 | 585 | ||
585 | if (!bus->drv_cc.core) | 586 | if (!bus->drv_cc.core) |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index ccba4fea7269..1eebe2ea3dfb 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -64,6 +64,7 @@ enum ath_op_flags { | |||
64 | ATH_OP_HW_RESET, | 64 | ATH_OP_HW_RESET, |
65 | ATH_OP_SCANNING, | 65 | ATH_OP_SCANNING, |
66 | ATH_OP_MULTI_CHANNEL, | 66 | ATH_OP_MULTI_CHANNEL, |
67 | ATH_OP_WOW_ENABLED, | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | enum ath_bus_type { | 70 | enum ath_bus_type { |
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index ffa3b1a8745f..f4dbb3e93bf8 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile | |||
@@ -9,12 +9,14 @@ ath10k_core-y += mac.o \ | |||
9 | txrx.o \ | 9 | txrx.o \ |
10 | wmi.o \ | 10 | wmi.o \ |
11 | wmi-tlv.o \ | 11 | wmi-tlv.o \ |
12 | bmi.o | 12 | bmi.o \ |
13 | hw.o | ||
13 | 14 | ||
14 | ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o | 15 | ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o |
15 | ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o | 16 | ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o |
16 | ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o | 17 | ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o |
17 | ath10k_core-$(CONFIG_THERMAL) += thermal.o | 18 | ath10k_core-$(CONFIG_THERMAL) += thermal.o |
19 | ath10k_core-$(CONFIG_MAC80211_DEBUGFS) += debugfs_sta.o | ||
18 | 20 | ||
19 | obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o | 21 | obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o |
20 | ath10k_pci-y += pci.o \ | 22 | ath10k_pci-y += pci.o \ |
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 42ec79327943..e508c65b6ba8 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
@@ -803,7 +803,7 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar) | |||
803 | int ce_id; | 803 | int ce_id; |
804 | 804 | ||
805 | for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { | 805 | for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { |
806 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); | 806 | u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id); |
807 | 807 | ||
808 | ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); | 808 | ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); |
809 | ath10k_ce_error_intr_disable(ar, ctrl_addr); | 809 | ath10k_ce_error_intr_disable(ar, ctrl_addr); |
@@ -832,7 +832,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
832 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 832 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
833 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; | 833 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
834 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 834 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
835 | u32 nentries, ctrl_addr = ath10k_ce_base_address(ce_id); | 835 | u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); |
836 | 836 | ||
837 | nentries = roundup_pow_of_two(attr->src_nentries); | 837 | nentries = roundup_pow_of_two(attr->src_nentries); |
838 | 838 | ||
@@ -869,7 +869,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, | |||
869 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 869 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
870 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; | 870 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
871 | struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; | 871 | struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; |
872 | u32 nentries, ctrl_addr = ath10k_ce_base_address(ce_id); | 872 | u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); |
873 | 873 | ||
874 | nentries = roundup_pow_of_two(attr->dest_nentries); | 874 | nentries = roundup_pow_of_two(attr->dest_nentries); |
875 | 875 | ||
@@ -1051,7 +1051,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, | |||
1051 | 1051 | ||
1052 | static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id) | 1052 | static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id) |
1053 | { | 1053 | { |
1054 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); | 1054 | u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id); |
1055 | 1055 | ||
1056 | ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, 0); | 1056 | ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, 0); |
1057 | ath10k_ce_src_ring_size_set(ar, ctrl_addr, 0); | 1057 | ath10k_ce_src_ring_size_set(ar, ctrl_addr, 0); |
@@ -1061,7 +1061,7 @@ static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id) | |||
1061 | 1061 | ||
1062 | static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id) | 1062 | static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id) |
1063 | { | 1063 | { |
1064 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); | 1064 | u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id); |
1065 | 1065 | ||
1066 | ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, 0); | 1066 | ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, 0); |
1067 | ath10k_ce_dest_ring_size_set(ar, ctrl_addr, 0); | 1067 | ath10k_ce_dest_ring_size_set(ar, ctrl_addr, 0); |
@@ -1098,7 +1098,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, | |||
1098 | 1098 | ||
1099 | ce_state->ar = ar; | 1099 | ce_state->ar = ar; |
1100 | ce_state->id = ce_id; | 1100 | ce_state->id = ce_id; |
1101 | ce_state->ctrl_addr = ath10k_ce_base_address(ce_id); | 1101 | ce_state->ctrl_addr = ath10k_ce_base_address(ar, ce_id); |
1102 | ce_state->attr_flags = attr->flags; | 1102 | ce_state->attr_flags = attr->flags; |
1103 | ce_state->src_sz_max = attr->src_sz_max; | 1103 | ce_state->src_sz_max = attr->src_sz_max; |
1104 | 1104 | ||
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 617a151e8ce4..c18647b87f71 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h | |||
@@ -394,7 +394,7 @@ struct ce_attr { | |||
394 | #define DST_WATERMARK_HIGH_RESET 0 | 394 | #define DST_WATERMARK_HIGH_RESET 0 |
395 | #define DST_WATERMARK_ADDRESS 0x0050 | 395 | #define DST_WATERMARK_ADDRESS 0x0050 |
396 | 396 | ||
397 | static inline u32 ath10k_ce_base_address(unsigned int ce_id) | 397 | static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) |
398 | { | 398 | { |
399 | return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; | 399 | return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; |
400 | } | 400 | } |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2d0671ebcf2b..310e12bc078a 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -57,6 +57,49 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { | |||
57 | .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, | 57 | .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, |
58 | }, | 58 | }, |
59 | }, | 59 | }, |
60 | { | ||
61 | .id = QCA6174_HW_2_1_VERSION, | ||
62 | .name = "qca6174 hw2.1", | ||
63 | .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, | ||
64 | .uart_pin = 6, | ||
65 | .fw = { | ||
66 | .dir = QCA6174_HW_2_1_FW_DIR, | ||
67 | .fw = QCA6174_HW_2_1_FW_FILE, | ||
68 | .otp = QCA6174_HW_2_1_OTP_FILE, | ||
69 | .board = QCA6174_HW_2_1_BOARD_DATA_FILE, | ||
70 | .board_size = QCA6174_BOARD_DATA_SZ, | ||
71 | .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, | ||
72 | }, | ||
73 | }, | ||
74 | { | ||
75 | .id = QCA6174_HW_3_0_VERSION, | ||
76 | .name = "qca6174 hw3.0", | ||
77 | .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, | ||
78 | .uart_pin = 6, | ||
79 | .fw = { | ||
80 | .dir = QCA6174_HW_3_0_FW_DIR, | ||
81 | .fw = QCA6174_HW_3_0_FW_FILE, | ||
82 | .otp = QCA6174_HW_3_0_OTP_FILE, | ||
83 | .board = QCA6174_HW_3_0_BOARD_DATA_FILE, | ||
84 | .board_size = QCA6174_BOARD_DATA_SZ, | ||
85 | .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, | ||
86 | }, | ||
87 | }, | ||
88 | { | ||
89 | .id = QCA6174_HW_3_2_VERSION, | ||
90 | .name = "qca6174 hw3.2", | ||
91 | .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, | ||
92 | .uart_pin = 6, | ||
93 | .fw = { | ||
94 | /* uses same binaries as hw3.0 */ | ||
95 | .dir = QCA6174_HW_3_0_FW_DIR, | ||
96 | .fw = QCA6174_HW_3_0_FW_FILE, | ||
97 | .otp = QCA6174_HW_3_0_OTP_FILE, | ||
98 | .board = QCA6174_HW_3_0_BOARD_DATA_FILE, | ||
99 | .board_size = QCA6174_BOARD_DATA_SZ, | ||
100 | .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, | ||
101 | }, | ||
102 | }, | ||
60 | }; | 103 | }; |
61 | 104 | ||
62 | static void ath10k_send_suspend_complete(struct ath10k *ar) | 105 | static void ath10k_send_suspend_complete(struct ath10k *ar) |
@@ -927,6 +970,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) | |||
927 | case ATH10K_FW_WMI_OP_VERSION_TLV: | 970 | case ATH10K_FW_WMI_OP_VERSION_TLV: |
928 | ar->max_num_peers = TARGET_TLV_NUM_PEERS; | 971 | ar->max_num_peers = TARGET_TLV_NUM_PEERS; |
929 | ar->max_num_stations = TARGET_TLV_NUM_STATIONS; | 972 | ar->max_num_stations = TARGET_TLV_NUM_STATIONS; |
973 | ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS; | ||
930 | ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; | 974 | ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; |
931 | break; | 975 | break; |
932 | case ATH10K_FW_WMI_OP_VERSION_UNSET: | 976 | case ATH10K_FW_WMI_OP_VERSION_UNSET: |
@@ -1060,6 +1104,18 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
1060 | goto err_hif_stop; | 1104 | goto err_hif_stop; |
1061 | } | 1105 | } |
1062 | 1106 | ||
1107 | /* If firmware indicates Full Rx Reorder support it must be used in a | ||
1108 | * slightly different manner. Let HTT code know. | ||
1109 | */ | ||
1110 | ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER, | ||
1111 | ar->wmi.svc_map)); | ||
1112 | |||
1113 | status = ath10k_htt_rx_ring_refill(ar); | ||
1114 | if (status) { | ||
1115 | ath10k_err(ar, "failed to refill htt rx ring: %d\n", status); | ||
1116 | goto err_hif_stop; | ||
1117 | } | ||
1118 | |||
1063 | /* we don't care about HTT in UTF mode */ | 1119 | /* we don't care about HTT in UTF mode */ |
1064 | if (mode == ATH10K_FIRMWARE_MODE_NORMAL) { | 1120 | if (mode == ATH10K_FIRMWARE_MODE_NORMAL) { |
1065 | status = ath10k_htt_setup(&ar->htt); | 1121 | status = ath10k_htt_setup(&ar->htt); |
@@ -1295,6 +1351,7 @@ EXPORT_SYMBOL(ath10k_core_unregister); | |||
1295 | 1351 | ||
1296 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | 1352 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, |
1297 | enum ath10k_bus bus, | 1353 | enum ath10k_bus bus, |
1354 | enum ath10k_hw_rev hw_rev, | ||
1298 | const struct ath10k_hif_ops *hif_ops) | 1355 | const struct ath10k_hif_ops *hif_ops) |
1299 | { | 1356 | { |
1300 | struct ath10k *ar; | 1357 | struct ath10k *ar; |
@@ -1307,9 +1364,24 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | |||
1307 | ar->ath_common.priv = ar; | 1364 | ar->ath_common.priv = ar; |
1308 | ar->ath_common.hw = ar->hw; | 1365 | ar->ath_common.hw = ar->hw; |
1309 | ar->dev = dev; | 1366 | ar->dev = dev; |
1367 | ar->hw_rev = hw_rev; | ||
1310 | ar->hif.ops = hif_ops; | 1368 | ar->hif.ops = hif_ops; |
1311 | ar->hif.bus = bus; | 1369 | ar->hif.bus = bus; |
1312 | 1370 | ||
1371 | switch (hw_rev) { | ||
1372 | case ATH10K_HW_QCA988X: | ||
1373 | ar->regs = &qca988x_regs; | ||
1374 | break; | ||
1375 | case ATH10K_HW_QCA6174: | ||
1376 | ar->regs = &qca6174_regs; | ||
1377 | break; | ||
1378 | default: | ||
1379 | ath10k_err(ar, "unsupported core hardware revision %d\n", | ||
1380 | hw_rev); | ||
1381 | ret = -ENOTSUPP; | ||
1382 | goto err_free_mac; | ||
1383 | } | ||
1384 | |||
1313 | init_completion(&ar->scan.started); | 1385 | init_completion(&ar->scan.started); |
1314 | init_completion(&ar->scan.completed); | 1386 | init_completion(&ar->scan.completed); |
1315 | init_completion(&ar->scan.on_channel); | 1387 | init_completion(&ar->scan.on_channel); |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7b6d9e4567a3..d60e46fe6d19 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -97,6 +97,11 @@ struct ath10k_skb_cb { | |||
97 | } bcn; | 97 | } bcn; |
98 | } __packed; | 98 | } __packed; |
99 | 99 | ||
100 | struct ath10k_skb_rxcb { | ||
101 | dma_addr_t paddr; | ||
102 | struct hlist_node hlist; | ||
103 | }; | ||
104 | |||
100 | static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) | 105 | static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) |
101 | { | 106 | { |
102 | BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) > | 107 | BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) > |
@@ -104,6 +109,15 @@ static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) | |||
104 | return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data; | 109 | return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data; |
105 | } | 110 | } |
106 | 111 | ||
112 | static inline struct ath10k_skb_rxcb *ATH10K_SKB_RXCB(struct sk_buff *skb) | ||
113 | { | ||
114 | BUILD_BUG_ON(sizeof(struct ath10k_skb_rxcb) > sizeof(skb->cb)); | ||
115 | return (struct ath10k_skb_rxcb *)skb->cb; | ||
116 | } | ||
117 | |||
118 | #define ATH10K_RXCB_SKB(rxcb) \ | ||
119 | container_of((void *)rxcb, struct sk_buff, cb) | ||
120 | |||
107 | static inline u32 host_interest_item_address(u32 item_offset) | 121 | static inline u32 host_interest_item_address(u32 item_offset) |
108 | { | 122 | { |
109 | return QCA988X_HOST_INTEREST_ADDRESS + item_offset; | 123 | return QCA988X_HOST_INTEREST_ADDRESS + item_offset; |
@@ -239,10 +253,21 @@ struct ath10k_sta { | |||
239 | u32 smps; | 253 | u32 smps; |
240 | 254 | ||
241 | struct work_struct update_wk; | 255 | struct work_struct update_wk; |
256 | |||
257 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
258 | /* protected by conf_mutex */ | ||
259 | bool aggr_mode; | ||
260 | #endif | ||
242 | }; | 261 | }; |
243 | 262 | ||
244 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) | 263 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) |
245 | 264 | ||
265 | enum ath10k_beacon_state { | ||
266 | ATH10K_BEACON_SCHEDULED = 0, | ||
267 | ATH10K_BEACON_SENDING, | ||
268 | ATH10K_BEACON_SENT, | ||
269 | }; | ||
270 | |||
246 | struct ath10k_vif { | 271 | struct ath10k_vif { |
247 | struct list_head list; | 272 | struct list_head list; |
248 | 273 | ||
@@ -253,7 +278,7 @@ struct ath10k_vif { | |||
253 | u32 dtim_period; | 278 | u32 dtim_period; |
254 | struct sk_buff *beacon; | 279 | struct sk_buff *beacon; |
255 | /* protected by data_lock */ | 280 | /* protected by data_lock */ |
256 | bool beacon_sent; | 281 | enum ath10k_beacon_state beacon_state; |
257 | void *beacon_buf; | 282 | void *beacon_buf; |
258 | dma_addr_t beacon_paddr; | 283 | dma_addr_t beacon_paddr; |
259 | 284 | ||
@@ -266,10 +291,8 @@ struct ath10k_vif { | |||
266 | u32 aid; | 291 | u32 aid; |
267 | u8 bssid[ETH_ALEN]; | 292 | u8 bssid[ETH_ALEN]; |
268 | 293 | ||
269 | struct work_struct wep_key_work; | ||
270 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; | 294 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; |
271 | u8 def_wep_key_idx; | 295 | s8 def_wep_key_idx; |
272 | u8 def_wep_key_newidx; | ||
273 | 296 | ||
274 | u16 tx_seq_no; | 297 | u16 tx_seq_no; |
275 | 298 | ||
@@ -296,6 +319,7 @@ struct ath10k_vif { | |||
296 | bool use_cts_prot; | 319 | bool use_cts_prot; |
297 | int num_legacy_stations; | 320 | int num_legacy_stations; |
298 | int txpower; | 321 | int txpower; |
322 | struct wmi_wmm_params_all_arg wmm_params; | ||
299 | }; | 323 | }; |
300 | 324 | ||
301 | struct ath10k_vif_iter { | 325 | struct ath10k_vif_iter { |
@@ -326,6 +350,7 @@ struct ath10k_debug { | |||
326 | 350 | ||
327 | /* protected by conf_mutex */ | 351 | /* protected by conf_mutex */ |
328 | u32 fw_dbglog_mask; | 352 | u32 fw_dbglog_mask; |
353 | u32 fw_dbglog_level; | ||
329 | u32 pktlog_filter; | 354 | u32 pktlog_filter; |
330 | u32 reg_addr; | 355 | u32 reg_addr; |
331 | u32 nf_cal_period; | 356 | u32 nf_cal_period; |
@@ -452,6 +477,7 @@ struct ath10k { | |||
452 | struct device *dev; | 477 | struct device *dev; |
453 | u8 mac_addr[ETH_ALEN]; | 478 | u8 mac_addr[ETH_ALEN]; |
454 | 479 | ||
480 | enum ath10k_hw_rev hw_rev; | ||
455 | u32 chip_id; | 481 | u32 chip_id; |
456 | u32 target_version; | 482 | u32 target_version; |
457 | u8 fw_version_major; | 483 | u8 fw_version_major; |
@@ -467,9 +493,6 @@ struct ath10k { | |||
467 | 493 | ||
468 | DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); | 494 | DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); |
469 | 495 | ||
470 | struct targetdef *targetdef; | ||
471 | struct hostdef *hostdef; | ||
472 | |||
473 | bool p2p; | 496 | bool p2p; |
474 | 497 | ||
475 | struct { | 498 | struct { |
@@ -479,6 +502,7 @@ struct ath10k { | |||
479 | 502 | ||
480 | struct completion target_suspend; | 503 | struct completion target_suspend; |
481 | 504 | ||
505 | const struct ath10k_hw_regs *regs; | ||
482 | struct ath10k_bmi bmi; | 506 | struct ath10k_bmi bmi; |
483 | struct ath10k_wmi wmi; | 507 | struct ath10k_wmi wmi; |
484 | struct ath10k_htc htc; | 508 | struct ath10k_htc htc; |
@@ -559,7 +583,6 @@ struct ath10k { | |||
559 | u8 cfg_tx_chainmask; | 583 | u8 cfg_tx_chainmask; |
560 | u8 cfg_rx_chainmask; | 584 | u8 cfg_rx_chainmask; |
561 | 585 | ||
562 | struct wmi_pdev_set_wmm_params_arg wmm_params; | ||
563 | struct completion install_key_done; | 586 | struct completion install_key_done; |
564 | 587 | ||
565 | struct completion vdev_setup_done; | 588 | struct completion vdev_setup_done; |
@@ -643,6 +666,7 @@ struct ath10k { | |||
643 | 666 | ||
644 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | 667 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, |
645 | enum ath10k_bus bus, | 668 | enum ath10k_bus bus, |
669 | enum ath10k_hw_rev hw_rev, | ||
646 | const struct ath10k_hif_ops *hif_ops); | 670 | const struct ath10k_hif_ops *hif_ops); |
647 | void ath10k_core_destroy(struct ath10k *ar); | 671 | void ath10k_core_destroy(struct ath10k *ar); |
648 | 672 | ||
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 6ca24427e184..d2281e5c2ffe 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -371,7 +371,7 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar) | |||
371 | 371 | ||
372 | ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete, | 372 | ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete, |
373 | 1*HZ); | 373 | 1*HZ); |
374 | if (ret <= 0) | 374 | if (ret == 0) |
375 | return -ETIMEDOUT; | 375 | return -ETIMEDOUT; |
376 | 376 | ||
377 | spin_lock_bh(&ar->data_lock); | 377 | spin_lock_bh(&ar->data_lock); |
@@ -1318,10 +1318,10 @@ static ssize_t ath10k_read_fw_dbglog(struct file *file, | |||
1318 | { | 1318 | { |
1319 | struct ath10k *ar = file->private_data; | 1319 | struct ath10k *ar = file->private_data; |
1320 | unsigned int len; | 1320 | unsigned int len; |
1321 | char buf[32]; | 1321 | char buf[64]; |
1322 | 1322 | ||
1323 | len = scnprintf(buf, sizeof(buf), "0x%08x\n", | 1323 | len = scnprintf(buf, sizeof(buf), "0x%08x %u\n", |
1324 | ar->debug.fw_dbglog_mask); | 1324 | ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level); |
1325 | 1325 | ||
1326 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 1326 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
1327 | } | 1327 | } |
@@ -1331,19 +1331,32 @@ static ssize_t ath10k_write_fw_dbglog(struct file *file, | |||
1331 | size_t count, loff_t *ppos) | 1331 | size_t count, loff_t *ppos) |
1332 | { | 1332 | { |
1333 | struct ath10k *ar = file->private_data; | 1333 | struct ath10k *ar = file->private_data; |
1334 | unsigned long mask; | ||
1335 | int ret; | 1334 | int ret; |
1335 | char buf[64]; | ||
1336 | unsigned int log_level, mask; | ||
1336 | 1337 | ||
1337 | ret = kstrtoul_from_user(user_buf, count, 0, &mask); | 1338 | simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); |
1338 | if (ret) | 1339 | |
1339 | return ret; | 1340 | /* make sure that buf is null terminated */ |
1341 | buf[sizeof(buf) - 1] = 0; | ||
1342 | |||
1343 | ret = sscanf(buf, "%x %u", &mask, &log_level); | ||
1344 | |||
1345 | if (!ret) | ||
1346 | return -EINVAL; | ||
1347 | |||
1348 | if (ret == 1) | ||
1349 | /* default if user did not specify */ | ||
1350 | log_level = ATH10K_DBGLOG_LEVEL_WARN; | ||
1340 | 1351 | ||
1341 | mutex_lock(&ar->conf_mutex); | 1352 | mutex_lock(&ar->conf_mutex); |
1342 | 1353 | ||
1343 | ar->debug.fw_dbglog_mask = mask; | 1354 | ar->debug.fw_dbglog_mask = mask; |
1355 | ar->debug.fw_dbglog_level = log_level; | ||
1344 | 1356 | ||
1345 | if (ar->state == ATH10K_STATE_ON) { | 1357 | if (ar->state == ATH10K_STATE_ON) { |
1346 | ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); | 1358 | ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask, |
1359 | ar->debug.fw_dbglog_level); | ||
1347 | if (ret) { | 1360 | if (ret) { |
1348 | ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n", | 1361 | ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n", |
1349 | ret); | 1362 | ret); |
@@ -1685,7 +1698,8 @@ int ath10k_debug_start(struct ath10k *ar) | |||
1685 | ret); | 1698 | ret); |
1686 | 1699 | ||
1687 | if (ar->debug.fw_dbglog_mask) { | 1700 | if (ar->debug.fw_dbglog_mask) { |
1688 | ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); | 1701 | ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask, |
1702 | ATH10K_DBGLOG_LEVEL_WARN); | ||
1689 | if (ret) | 1703 | if (ret) |
1690 | /* not serious */ | 1704 | /* not serious */ |
1691 | ath10k_warn(ar, "failed to enable dbglog during start: %d", | 1705 | ath10k_warn(ar, "failed to enable dbglog during start: %d", |
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 1b87a5dbec53..a12b8323f9f1 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h | |||
@@ -48,6 +48,12 @@ enum ath10k_pktlog_filter { | |||
48 | ATH10K_PKTLOG_ANY = 0x00000001f, | 48 | ATH10K_PKTLOG_ANY = 0x00000001f, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | enum ath10k_dbg_aggr_mode { | ||
52 | ATH10K_DBG_AGGR_MODE_AUTO, | ||
53 | ATH10K_DBG_AGGR_MODE_MANUAL, | ||
54 | ATH10K_DBG_AGGR_MODE_MAX, | ||
55 | }; | ||
56 | |||
51 | extern unsigned int ath10k_debug_mask; | 57 | extern unsigned int ath10k_debug_mask; |
52 | 58 | ||
53 | __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); | 59 | __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); |
@@ -77,7 +83,6 @@ int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw, | |||
77 | void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, | 83 | void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, |
78 | struct ieee80211_vif *vif, | 84 | struct ieee80211_vif *vif, |
79 | struct ethtool_stats *stats, u64 *data); | 85 | struct ethtool_stats *stats, u64 *data); |
80 | |||
81 | #else | 86 | #else |
82 | static inline int ath10k_debug_start(struct ath10k *ar) | 87 | static inline int ath10k_debug_start(struct ath10k *ar) |
83 | { | 88 | { |
@@ -129,6 +134,10 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) | |||
129 | #define ath10k_debug_get_et_stats NULL | 134 | #define ath10k_debug_get_et_stats NULL |
130 | 135 | ||
131 | #endif /* CONFIG_ATH10K_DEBUGFS */ | 136 | #endif /* CONFIG_ATH10K_DEBUGFS */ |
137 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
138 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
139 | struct ieee80211_sta *sta, struct dentry *dir); | ||
140 | #endif /* CONFIG_MAC80211_DEBUGFS */ | ||
132 | 141 | ||
133 | #ifdef CONFIG_ATH10K_DEBUG | 142 | #ifdef CONFIG_ATH10K_DEBUG |
134 | __printf(3, 4) void ath10k_dbg(struct ath10k *ar, | 143 | __printf(3, 4) void ath10k_dbg(struct ath10k *ar, |
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c new file mode 100644 index 000000000000..95b5c49374e0 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 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 "core.h" | ||
18 | #include "wmi-ops.h" | ||
19 | #include "debug.h" | ||
20 | |||
21 | static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, | ||
22 | char __user *user_buf, | ||
23 | size_t count, loff_t *ppos) | ||
24 | { | ||
25 | struct ieee80211_sta *sta = file->private_data; | ||
26 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
27 | struct ath10k *ar = arsta->arvif->ar; | ||
28 | char buf[32]; | ||
29 | int len = 0; | ||
30 | |||
31 | mutex_lock(&ar->conf_mutex); | ||
32 | len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n", | ||
33 | (arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ? | ||
34 | "auto" : "manual"); | ||
35 | mutex_unlock(&ar->conf_mutex); | ||
36 | |||
37 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
38 | } | ||
39 | |||
40 | static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file, | ||
41 | const char __user *user_buf, | ||
42 | size_t count, loff_t *ppos) | ||
43 | { | ||
44 | struct ieee80211_sta *sta = file->private_data; | ||
45 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
46 | struct ath10k *ar = arsta->arvif->ar; | ||
47 | u32 aggr_mode; | ||
48 | int ret; | ||
49 | |||
50 | if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode)) | ||
51 | return -EINVAL; | ||
52 | |||
53 | if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX) | ||
54 | return -EINVAL; | ||
55 | |||
56 | mutex_lock(&ar->conf_mutex); | ||
57 | if ((ar->state != ATH10K_STATE_ON) || | ||
58 | (aggr_mode == arsta->aggr_mode)) { | ||
59 | ret = count; | ||
60 | goto out; | ||
61 | } | ||
62 | |||
63 | ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr); | ||
64 | if (ret) { | ||
65 | ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret); | ||
66 | goto out; | ||
67 | } | ||
68 | |||
69 | arsta->aggr_mode = aggr_mode; | ||
70 | out: | ||
71 | mutex_unlock(&ar->conf_mutex); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | static const struct file_operations fops_aggr_mode = { | ||
76 | .read = ath10k_dbg_sta_read_aggr_mode, | ||
77 | .write = ath10k_dbg_sta_write_aggr_mode, | ||
78 | .open = simple_open, | ||
79 | .owner = THIS_MODULE, | ||
80 | .llseek = default_llseek, | ||
81 | }; | ||
82 | |||
83 | static ssize_t ath10k_dbg_sta_write_addba(struct file *file, | ||
84 | const char __user *user_buf, | ||
85 | size_t count, loff_t *ppos) | ||
86 | { | ||
87 | struct ieee80211_sta *sta = file->private_data; | ||
88 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
89 | struct ath10k *ar = arsta->arvif->ar; | ||
90 | u32 tid, buf_size; | ||
91 | int ret; | ||
92 | char buf[64]; | ||
93 | |||
94 | simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); | ||
95 | |||
96 | /* make sure that buf is null terminated */ | ||
97 | buf[sizeof(buf) - 1] = '\0'; | ||
98 | |||
99 | ret = sscanf(buf, "%u %u", &tid, &buf_size); | ||
100 | if (ret != 2) | ||
101 | return -EINVAL; | ||
102 | |||
103 | /* Valid TID values are 0 through 15 */ | ||
104 | if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) | ||
105 | return -EINVAL; | ||
106 | |||
107 | mutex_lock(&ar->conf_mutex); | ||
108 | if ((ar->state != ATH10K_STATE_ON) || | ||
109 | (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { | ||
110 | ret = count; | ||
111 | goto out; | ||
112 | } | ||
113 | |||
114 | ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr, | ||
115 | tid, buf_size); | ||
116 | if (ret) { | ||
117 | ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n", | ||
118 | arsta->arvif->vdev_id, sta->addr, tid, buf_size); | ||
119 | } | ||
120 | |||
121 | ret = count; | ||
122 | out: | ||
123 | mutex_unlock(&ar->conf_mutex); | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | static const struct file_operations fops_addba = { | ||
128 | .write = ath10k_dbg_sta_write_addba, | ||
129 | .open = simple_open, | ||
130 | .owner = THIS_MODULE, | ||
131 | .llseek = default_llseek, | ||
132 | }; | ||
133 | |||
134 | static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file, | ||
135 | const char __user *user_buf, | ||
136 | size_t count, loff_t *ppos) | ||
137 | { | ||
138 | struct ieee80211_sta *sta = file->private_data; | ||
139 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
140 | struct ath10k *ar = arsta->arvif->ar; | ||
141 | u32 tid, status; | ||
142 | int ret; | ||
143 | char buf[64]; | ||
144 | |||
145 | simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); | ||
146 | |||
147 | /* make sure that buf is null terminated */ | ||
148 | buf[sizeof(buf) - 1] = '\0'; | ||
149 | |||
150 | ret = sscanf(buf, "%u %u", &tid, &status); | ||
151 | if (ret != 2) | ||
152 | return -EINVAL; | ||
153 | |||
154 | /* Valid TID values are 0 through 15 */ | ||
155 | if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) | ||
156 | return -EINVAL; | ||
157 | |||
158 | mutex_lock(&ar->conf_mutex); | ||
159 | if ((ar->state != ATH10K_STATE_ON) || | ||
160 | (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { | ||
161 | ret = count; | ||
162 | goto out; | ||
163 | } | ||
164 | |||
165 | ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr, | ||
166 | tid, status); | ||
167 | if (ret) { | ||
168 | ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n", | ||
169 | arsta->arvif->vdev_id, sta->addr, tid, status); | ||
170 | } | ||
171 | ret = count; | ||
172 | out: | ||
173 | mutex_unlock(&ar->conf_mutex); | ||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | static const struct file_operations fops_addba_resp = { | ||
178 | .write = ath10k_dbg_sta_write_addba_resp, | ||
179 | .open = simple_open, | ||
180 | .owner = THIS_MODULE, | ||
181 | .llseek = default_llseek, | ||
182 | }; | ||
183 | |||
184 | static ssize_t ath10k_dbg_sta_write_delba(struct file *file, | ||
185 | const char __user *user_buf, | ||
186 | size_t count, loff_t *ppos) | ||
187 | { | ||
188 | struct ieee80211_sta *sta = file->private_data; | ||
189 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
190 | struct ath10k *ar = arsta->arvif->ar; | ||
191 | u32 tid, initiator, reason; | ||
192 | int ret; | ||
193 | char buf[64]; | ||
194 | |||
195 | simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); | ||
196 | |||
197 | /* make sure that buf is null terminated */ | ||
198 | buf[sizeof(buf) - 1] = '\0'; | ||
199 | |||
200 | ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason); | ||
201 | if (ret != 3) | ||
202 | return -EINVAL; | ||
203 | |||
204 | /* Valid TID values are 0 through 15 */ | ||
205 | if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) | ||
206 | return -EINVAL; | ||
207 | |||
208 | mutex_lock(&ar->conf_mutex); | ||
209 | if ((ar->state != ATH10K_STATE_ON) || | ||
210 | (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { | ||
211 | ret = count; | ||
212 | goto out; | ||
213 | } | ||
214 | |||
215 | ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr, | ||
216 | tid, initiator, reason); | ||
217 | if (ret) { | ||
218 | ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n", | ||
219 | arsta->arvif->vdev_id, sta->addr, tid, initiator, | ||
220 | reason); | ||
221 | } | ||
222 | ret = count; | ||
223 | out: | ||
224 | mutex_unlock(&ar->conf_mutex); | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static const struct file_operations fops_delba = { | ||
229 | .write = ath10k_dbg_sta_write_delba, | ||
230 | .open = simple_open, | ||
231 | .owner = THIS_MODULE, | ||
232 | .llseek = default_llseek, | ||
233 | }; | ||
234 | |||
235 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
236 | struct ieee80211_sta *sta, struct dentry *dir) | ||
237 | { | ||
238 | debugfs_create_file("aggr_mode", S_IRUGO | S_IWUSR, dir, sta, | ||
239 | &fops_aggr_mode); | ||
240 | debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba); | ||
241 | debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp); | ||
242 | debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba); | ||
243 | } | ||
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index f1946a6be442..2fd9e180272b 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c | |||
@@ -703,11 +703,9 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, | |||
703 | /* wait for response */ | 703 | /* wait for response */ |
704 | status = wait_for_completion_timeout(&htc->ctl_resp, | 704 | status = wait_for_completion_timeout(&htc->ctl_resp, |
705 | ATH10K_HTC_CONN_SVC_TIMEOUT_HZ); | 705 | ATH10K_HTC_CONN_SVC_TIMEOUT_HZ); |
706 | if (status <= 0) { | 706 | if (status == 0) { |
707 | if (status == 0) | ||
708 | status = -ETIMEDOUT; | ||
709 | ath10k_err(ar, "Service connect timeout: %d\n", status); | 707 | ath10k_err(ar, "Service connect timeout: %d\n", status); |
710 | return status; | 708 | return -ETIMEDOUT; |
711 | } | 709 | } |
712 | 710 | ||
713 | /* we controlled the buffer creation, it's aligned */ | 711 | /* we controlled the buffer creation, it's aligned */ |
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 56cb4aceb383..4f59ab923e48 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c | |||
@@ -53,7 +53,6 @@ int ath10k_htt_init(struct ath10k *ar) | |||
53 | struct ath10k_htt *htt = &ar->htt; | 53 | struct ath10k_htt *htt = &ar->htt; |
54 | 54 | ||
55 | htt->ar = ar; | 55 | htt->ar = ar; |
56 | htt->max_throughput_mbps = 800; | ||
57 | 56 | ||
58 | /* | 57 | /* |
59 | * Prefetch enough data to satisfy target | 58 | * Prefetch enough data to satisfy target |
@@ -102,7 +101,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt) | |||
102 | 101 | ||
103 | status = wait_for_completion_timeout(&htt->target_version_received, | 102 | status = wait_for_completion_timeout(&htt->target_version_received, |
104 | HTT_TARGET_VERSION_TIMEOUT_HZ); | 103 | HTT_TARGET_VERSION_TIMEOUT_HZ); |
105 | if (status <= 0) { | 104 | if (status == 0) { |
106 | ath10k_warn(ar, "htt version request timed out\n"); | 105 | ath10k_warn(ar, "htt version request timed out\n"); |
107 | return -ETIMEDOUT; | 106 | return -ETIMEDOUT; |
108 | } | 107 | } |
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 1bd5545af903..874bf44ff7a2 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/bug.h> | 21 | #include <linux/bug.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/dmapool.h> | 23 | #include <linux/dmapool.h> |
24 | #include <linux/hashtable.h> | ||
24 | #include <net/mac80211.h> | 25 | #include <net/mac80211.h> |
25 | 26 | ||
26 | #include "htc.h" | 27 | #include "htc.h" |
@@ -286,7 +287,19 @@ enum htt_t2h_msg_type { | |||
286 | HTT_T2H_MSG_TYPE_RC_UPDATE_IND = 0xc, | 287 | HTT_T2H_MSG_TYPE_RC_UPDATE_IND = 0xc, |
287 | HTT_T2H_MSG_TYPE_TX_INSPECT_IND = 0xd, | 288 | HTT_T2H_MSG_TYPE_TX_INSPECT_IND = 0xd, |
288 | HTT_T2H_MSG_TYPE_MGMT_TX_COMPLETION = 0xe, | 289 | HTT_T2H_MSG_TYPE_MGMT_TX_COMPLETION = 0xe, |
290 | HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND = 0xf, | ||
291 | HTT_T2H_MSG_TYPE_RX_PN_IND = 0x10, | ||
292 | HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND = 0x11, | ||
293 | HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND = 0x12, | ||
294 | /* 0x13 reservd */ | ||
295 | HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE = 0x14, | ||
296 | |||
297 | /* FIXME: Do not depend on this event id. Numbering of this event id is | ||
298 | * broken across different firmware revisions and HTT version fails to | ||
299 | * indicate this. | ||
300 | */ | ||
289 | HTT_T2H_MSG_TYPE_TEST, | 301 | HTT_T2H_MSG_TYPE_TEST, |
302 | |||
290 | /* keep this last */ | 303 | /* keep this last */ |
291 | HTT_T2H_NUM_MSGS | 304 | HTT_T2H_NUM_MSGS |
292 | }; | 305 | }; |
@@ -655,6 +668,53 @@ struct htt_rx_fragment_indication { | |||
655 | #define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_MASK 0x00000FC0 | 668 | #define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_MASK 0x00000FC0 |
656 | #define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_LSB 6 | 669 | #define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_LSB 6 |
657 | 670 | ||
671 | struct htt_rx_pn_ind { | ||
672 | __le16 peer_id; | ||
673 | u8 tid; | ||
674 | u8 seqno_start; | ||
675 | u8 seqno_end; | ||
676 | u8 pn_ie_count; | ||
677 | u8 reserved; | ||
678 | u8 pn_ies[0]; | ||
679 | } __packed; | ||
680 | |||
681 | struct htt_rx_offload_msdu { | ||
682 | __le16 msdu_len; | ||
683 | __le16 peer_id; | ||
684 | u8 vdev_id; | ||
685 | u8 tid; | ||
686 | u8 fw_desc; | ||
687 | u8 payload[0]; | ||
688 | } __packed; | ||
689 | |||
690 | struct htt_rx_offload_ind { | ||
691 | u8 reserved; | ||
692 | __le16 msdu_count; | ||
693 | } __packed; | ||
694 | |||
695 | struct htt_rx_in_ord_msdu_desc { | ||
696 | __le32 msdu_paddr; | ||
697 | __le16 msdu_len; | ||
698 | u8 fw_desc; | ||
699 | u8 reserved; | ||
700 | } __packed; | ||
701 | |||
702 | struct htt_rx_in_ord_ind { | ||
703 | u8 info; | ||
704 | __le16 peer_id; | ||
705 | u8 vdev_id; | ||
706 | u8 reserved; | ||
707 | __le16 msdu_count; | ||
708 | struct htt_rx_in_ord_msdu_desc msdu_descs[0]; | ||
709 | } __packed; | ||
710 | |||
711 | #define HTT_RX_IN_ORD_IND_INFO_TID_MASK 0x0000001f | ||
712 | #define HTT_RX_IN_ORD_IND_INFO_TID_LSB 0 | ||
713 | #define HTT_RX_IN_ORD_IND_INFO_OFFLOAD_MASK 0x00000020 | ||
714 | #define HTT_RX_IN_ORD_IND_INFO_OFFLOAD_LSB 5 | ||
715 | #define HTT_RX_IN_ORD_IND_INFO_FRAG_MASK 0x00000040 | ||
716 | #define HTT_RX_IN_ORD_IND_INFO_FRAG_LSB 6 | ||
717 | |||
658 | /* | 718 | /* |
659 | * target -> host test message definition | 719 | * target -> host test message definition |
660 | * | 720 | * |
@@ -1150,6 +1210,9 @@ struct htt_resp { | |||
1150 | struct htt_rx_test rx_test; | 1210 | struct htt_rx_test rx_test; |
1151 | struct htt_pktlog_msg pktlog_msg; | 1211 | struct htt_pktlog_msg pktlog_msg; |
1152 | struct htt_stats_conf stats_conf; | 1212 | struct htt_stats_conf stats_conf; |
1213 | struct htt_rx_pn_ind rx_pn_ind; | ||
1214 | struct htt_rx_offload_ind rx_offload_ind; | ||
1215 | struct htt_rx_in_ord_ind rx_in_ord_ind; | ||
1153 | }; | 1216 | }; |
1154 | } __packed; | 1217 | } __packed; |
1155 | 1218 | ||
@@ -1182,7 +1245,6 @@ struct ath10k_htt { | |||
1182 | struct ath10k *ar; | 1245 | struct ath10k *ar; |
1183 | enum ath10k_htc_ep_id eid; | 1246 | enum ath10k_htc_ep_id eid; |
1184 | 1247 | ||
1185 | int max_throughput_mbps; | ||
1186 | u8 target_version_major; | 1248 | u8 target_version_major; |
1187 | u8 target_version_minor; | 1249 | u8 target_version_minor; |
1188 | struct completion target_version_received; | 1250 | struct completion target_version_received; |
@@ -1198,6 +1260,20 @@ struct ath10k_htt { | |||
1198 | * filled. | 1260 | * filled. |
1199 | */ | 1261 | */ |
1200 | struct sk_buff **netbufs_ring; | 1262 | struct sk_buff **netbufs_ring; |
1263 | |||
1264 | /* This is used only with firmware supporting IN_ORD_IND. | ||
1265 | * | ||
1266 | * With Full Rx Reorder the HTT Rx Ring is more of a temporary | ||
1267 | * buffer ring from which buffer addresses are copied by the | ||
1268 | * firmware to MAC Rx ring. Firmware then delivers IN_ORD_IND | ||
1269 | * pointing to specific (re-ordered) buffers. | ||
1270 | * | ||
1271 | * FIXME: With kernel generic hashing functions there's a lot | ||
1272 | * of hash collisions for sk_buffs. | ||
1273 | */ | ||
1274 | bool in_ord_rx; | ||
1275 | DECLARE_HASHTABLE(skb_table, 4); | ||
1276 | |||
1201 | /* | 1277 | /* |
1202 | * Ring of buffer addresses - | 1278 | * Ring of buffer addresses - |
1203 | * This ring holds the "physical" device address of the | 1279 | * This ring holds the "physical" device address of the |
@@ -1252,12 +1328,11 @@ struct ath10k_htt { | |||
1252 | 1328 | ||
1253 | unsigned int prefetch_len; | 1329 | unsigned int prefetch_len; |
1254 | 1330 | ||
1255 | /* Protects access to %pending_tx, %used_msdu_ids */ | 1331 | /* Protects access to pending_tx, num_pending_tx */ |
1256 | spinlock_t tx_lock; | 1332 | spinlock_t tx_lock; |
1257 | int max_num_pending_tx; | 1333 | int max_num_pending_tx; |
1258 | int num_pending_tx; | 1334 | int num_pending_tx; |
1259 | struct sk_buff **pending_tx; | 1335 | struct idr pending_tx; |
1260 | unsigned long *used_msdu_ids; /* bitmap */ | ||
1261 | wait_queue_head_t empty_tx_wq; | 1336 | wait_queue_head_t empty_tx_wq; |
1262 | struct dma_pool *tx_pool; | 1337 | struct dma_pool *tx_pool; |
1263 | 1338 | ||
@@ -1271,6 +1346,7 @@ struct ath10k_htt { | |||
1271 | struct tasklet_struct txrx_compl_task; | 1346 | struct tasklet_struct txrx_compl_task; |
1272 | struct sk_buff_head tx_compl_q; | 1347 | struct sk_buff_head tx_compl_q; |
1273 | struct sk_buff_head rx_compl_q; | 1348 | struct sk_buff_head rx_compl_q; |
1349 | struct sk_buff_head rx_in_ord_compl_q; | ||
1274 | 1350 | ||
1275 | /* rx_status template */ | 1351 | /* rx_status template */ |
1276 | struct ieee80211_rx_status rx_status; | 1352 | struct ieee80211_rx_status rx_status; |
@@ -1334,6 +1410,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt); | |||
1334 | void ath10k_htt_tx_free(struct ath10k_htt *htt); | 1410 | void ath10k_htt_tx_free(struct ath10k_htt *htt); |
1335 | 1411 | ||
1336 | int ath10k_htt_rx_alloc(struct ath10k_htt *htt); | 1412 | int ath10k_htt_rx_alloc(struct ath10k_htt *htt); |
1413 | int ath10k_htt_rx_ring_refill(struct ath10k *ar); | ||
1337 | void ath10k_htt_rx_free(struct ath10k_htt *htt); | 1414 | void ath10k_htt_rx_free(struct ath10k_htt *htt); |
1338 | 1415 | ||
1339 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); | 1416 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); |
@@ -1346,7 +1423,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, | |||
1346 | u8 max_subfrms_amsdu); | 1423 | u8 max_subfrms_amsdu); |
1347 | 1424 | ||
1348 | void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); | 1425 | void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); |
1349 | int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); | 1426 | int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); |
1350 | void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); | 1427 | void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); |
1351 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); | 1428 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); |
1352 | int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *); | 1429 | int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *); |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 9c782a42665e..c1da44f65a4d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -25,8 +25,8 @@ | |||
25 | 25 | ||
26 | #include <linux/log2.h> | 26 | #include <linux/log2.h> |
27 | 27 | ||
28 | #define HTT_RX_RING_SIZE 1024 | 28 | #define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX |
29 | #define HTT_RX_RING_FILL_LEVEL 1000 | 29 | #define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1) |
30 | 30 | ||
31 | /* when under memory pressure rx ring refill may fail and needs a retry */ | 31 | /* when under memory pressure rx ring refill may fail and needs a retry */ |
32 | #define HTT_RX_RING_REFILL_RETRY_MS 50 | 32 | #define HTT_RX_RING_REFILL_RETRY_MS 50 |
@@ -34,31 +34,70 @@ | |||
34 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); | 34 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); |
35 | static void ath10k_htt_txrx_compl_task(unsigned long ptr); | 35 | static void ath10k_htt_txrx_compl_task(unsigned long ptr); |
36 | 36 | ||
37 | static struct sk_buff * | ||
38 | ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u32 paddr) | ||
39 | { | ||
40 | struct ath10k_skb_rxcb *rxcb; | ||
41 | |||
42 | hash_for_each_possible(ar->htt.rx_ring.skb_table, rxcb, hlist, paddr) | ||
43 | if (rxcb->paddr == paddr) | ||
44 | return ATH10K_RXCB_SKB(rxcb); | ||
45 | |||
46 | WARN_ON_ONCE(1); | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
37 | static void ath10k_htt_rx_ring_free(struct ath10k_htt *htt) | 50 | static void ath10k_htt_rx_ring_free(struct ath10k_htt *htt) |
38 | { | 51 | { |
39 | struct sk_buff *skb; | 52 | struct sk_buff *skb; |
40 | struct ath10k_skb_cb *cb; | 53 | struct ath10k_skb_rxcb *rxcb; |
54 | struct hlist_node *n; | ||
41 | int i; | 55 | int i; |
42 | 56 | ||
43 | for (i = 0; i < htt->rx_ring.fill_cnt; i++) { | 57 | if (htt->rx_ring.in_ord_rx) { |
44 | skb = htt->rx_ring.netbufs_ring[i]; | 58 | hash_for_each_safe(htt->rx_ring.skb_table, i, n, rxcb, hlist) { |
45 | cb = ATH10K_SKB_CB(skb); | 59 | skb = ATH10K_RXCB_SKB(rxcb); |
46 | dma_unmap_single(htt->ar->dev, cb->paddr, | 60 | dma_unmap_single(htt->ar->dev, rxcb->paddr, |
47 | skb->len + skb_tailroom(skb), | 61 | skb->len + skb_tailroom(skb), |
48 | DMA_FROM_DEVICE); | 62 | DMA_FROM_DEVICE); |
49 | dev_kfree_skb_any(skb); | 63 | hash_del(&rxcb->hlist); |
64 | dev_kfree_skb_any(skb); | ||
65 | } | ||
66 | } else { | ||
67 | for (i = 0; i < htt->rx_ring.size; i++) { | ||
68 | skb = htt->rx_ring.netbufs_ring[i]; | ||
69 | if (!skb) | ||
70 | continue; | ||
71 | |||
72 | rxcb = ATH10K_SKB_RXCB(skb); | ||
73 | dma_unmap_single(htt->ar->dev, rxcb->paddr, | ||
74 | skb->len + skb_tailroom(skb), | ||
75 | DMA_FROM_DEVICE); | ||
76 | dev_kfree_skb_any(skb); | ||
77 | } | ||
50 | } | 78 | } |
51 | 79 | ||
52 | htt->rx_ring.fill_cnt = 0; | 80 | htt->rx_ring.fill_cnt = 0; |
81 | hash_init(htt->rx_ring.skb_table); | ||
82 | memset(htt->rx_ring.netbufs_ring, 0, | ||
83 | htt->rx_ring.size * sizeof(htt->rx_ring.netbufs_ring[0])); | ||
53 | } | 84 | } |
54 | 85 | ||
55 | static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) | 86 | static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) |
56 | { | 87 | { |
57 | struct htt_rx_desc *rx_desc; | 88 | struct htt_rx_desc *rx_desc; |
89 | struct ath10k_skb_rxcb *rxcb; | ||
58 | struct sk_buff *skb; | 90 | struct sk_buff *skb; |
59 | dma_addr_t paddr; | 91 | dma_addr_t paddr; |
60 | int ret = 0, idx; | 92 | int ret = 0, idx; |
61 | 93 | ||
94 | /* The Full Rx Reorder firmware has no way of telling the host | ||
95 | * implicitly when it copied HTT Rx Ring buffers to MAC Rx Ring. | ||
96 | * To keep things simple make sure ring is always half empty. This | ||
97 | * guarantees there'll be no replenishment overruns possible. | ||
98 | */ | ||
99 | BUILD_BUG_ON(HTT_RX_RING_FILL_LEVEL >= HTT_RX_RING_SIZE / 2); | ||
100 | |||
62 | idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr); | 101 | idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr); |
63 | while (num > 0) { | 102 | while (num > 0) { |
64 | skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN); | 103 | skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN); |
@@ -86,17 +125,29 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) | |||
86 | goto fail; | 125 | goto fail; |
87 | } | 126 | } |
88 | 127 | ||
89 | ATH10K_SKB_CB(skb)->paddr = paddr; | 128 | rxcb = ATH10K_SKB_RXCB(skb); |
129 | rxcb->paddr = paddr; | ||
90 | htt->rx_ring.netbufs_ring[idx] = skb; | 130 | htt->rx_ring.netbufs_ring[idx] = skb; |
91 | htt->rx_ring.paddrs_ring[idx] = __cpu_to_le32(paddr); | 131 | htt->rx_ring.paddrs_ring[idx] = __cpu_to_le32(paddr); |
92 | htt->rx_ring.fill_cnt++; | 132 | htt->rx_ring.fill_cnt++; |
93 | 133 | ||
134 | if (htt->rx_ring.in_ord_rx) { | ||
135 | hash_add(htt->rx_ring.skb_table, | ||
136 | &ATH10K_SKB_RXCB(skb)->hlist, | ||
137 | (u32)paddr); | ||
138 | } | ||
139 | |||
94 | num--; | 140 | num--; |
95 | idx++; | 141 | idx++; |
96 | idx &= htt->rx_ring.size_mask; | 142 | idx &= htt->rx_ring.size_mask; |
97 | } | 143 | } |
98 | 144 | ||
99 | fail: | 145 | fail: |
146 | /* | ||
147 | * Make sure the rx buffer is updated before available buffer | ||
148 | * index to avoid any potential rx ring corruption. | ||
149 | */ | ||
150 | mb(); | ||
100 | *htt->rx_ring.alloc_idx.vaddr = __cpu_to_le32(idx); | 151 | *htt->rx_ring.alloc_idx.vaddr = __cpu_to_le32(idx); |
101 | return ret; | 152 | return ret; |
102 | } | 153 | } |
@@ -153,22 +204,20 @@ static void ath10k_htt_rx_ring_refill_retry(unsigned long arg) | |||
153 | ath10k_htt_rx_msdu_buff_replenish(htt); | 204 | ath10k_htt_rx_msdu_buff_replenish(htt); |
154 | } | 205 | } |
155 | 206 | ||
156 | static void ath10k_htt_rx_ring_clean_up(struct ath10k_htt *htt) | 207 | int ath10k_htt_rx_ring_refill(struct ath10k *ar) |
157 | { | 208 | { |
158 | struct sk_buff *skb; | 209 | struct ath10k_htt *htt = &ar->htt; |
159 | int i; | 210 | int ret; |
160 | 211 | ||
161 | for (i = 0; i < htt->rx_ring.size; i++) { | 212 | spin_lock_bh(&htt->rx_ring.lock); |
162 | skb = htt->rx_ring.netbufs_ring[i]; | 213 | ret = ath10k_htt_rx_ring_fill_n(htt, (htt->rx_ring.fill_level - |
163 | if (!skb) | 214 | htt->rx_ring.fill_cnt)); |
164 | continue; | 215 | spin_unlock_bh(&htt->rx_ring.lock); |
165 | 216 | ||
166 | dma_unmap_single(htt->ar->dev, ATH10K_SKB_CB(skb)->paddr, | 217 | if (ret) |
167 | skb->len + skb_tailroom(skb), | 218 | ath10k_htt_rx_ring_free(htt); |
168 | DMA_FROM_DEVICE); | 219 | |
169 | dev_kfree_skb_any(skb); | 220 | return ret; |
170 | htt->rx_ring.netbufs_ring[i] = NULL; | ||
171 | } | ||
172 | } | 221 | } |
173 | 222 | ||
174 | void ath10k_htt_rx_free(struct ath10k_htt *htt) | 223 | void ath10k_htt_rx_free(struct ath10k_htt *htt) |
@@ -179,8 +228,9 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) | |||
179 | 228 | ||
180 | skb_queue_purge(&htt->tx_compl_q); | 229 | skb_queue_purge(&htt->tx_compl_q); |
181 | skb_queue_purge(&htt->rx_compl_q); | 230 | skb_queue_purge(&htt->rx_compl_q); |
231 | skb_queue_purge(&htt->rx_in_ord_compl_q); | ||
182 | 232 | ||
183 | ath10k_htt_rx_ring_clean_up(htt); | 233 | ath10k_htt_rx_ring_free(htt); |
184 | 234 | ||
185 | dma_free_coherent(htt->ar->dev, | 235 | dma_free_coherent(htt->ar->dev, |
186 | (htt->rx_ring.size * | 236 | (htt->rx_ring.size * |
@@ -212,6 +262,7 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) | |||
212 | idx = htt->rx_ring.sw_rd_idx.msdu_payld; | 262 | idx = htt->rx_ring.sw_rd_idx.msdu_payld; |
213 | msdu = htt->rx_ring.netbufs_ring[idx]; | 263 | msdu = htt->rx_ring.netbufs_ring[idx]; |
214 | htt->rx_ring.netbufs_ring[idx] = NULL; | 264 | htt->rx_ring.netbufs_ring[idx] = NULL; |
265 | htt->rx_ring.paddrs_ring[idx] = 0; | ||
215 | 266 | ||
216 | idx++; | 267 | idx++; |
217 | idx &= htt->rx_ring.size_mask; | 268 | idx &= htt->rx_ring.size_mask; |
@@ -219,7 +270,7 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) | |||
219 | htt->rx_ring.fill_cnt--; | 270 | htt->rx_ring.fill_cnt--; |
220 | 271 | ||
221 | dma_unmap_single(htt->ar->dev, | 272 | dma_unmap_single(htt->ar->dev, |
222 | ATH10K_SKB_CB(msdu)->paddr, | 273 | ATH10K_SKB_RXCB(msdu)->paddr, |
223 | msdu->len + skb_tailroom(msdu), | 274 | msdu->len + skb_tailroom(msdu), |
224 | DMA_FROM_DEVICE); | 275 | DMA_FROM_DEVICE); |
225 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ", | 276 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ", |
@@ -379,6 +430,82 @@ static void ath10k_htt_rx_replenish_task(unsigned long ptr) | |||
379 | ath10k_htt_rx_msdu_buff_replenish(htt); | 430 | ath10k_htt_rx_msdu_buff_replenish(htt); |
380 | } | 431 | } |
381 | 432 | ||
433 | static struct sk_buff *ath10k_htt_rx_pop_paddr(struct ath10k_htt *htt, | ||
434 | u32 paddr) | ||
435 | { | ||
436 | struct ath10k *ar = htt->ar; | ||
437 | struct ath10k_skb_rxcb *rxcb; | ||
438 | struct sk_buff *msdu; | ||
439 | |||
440 | lockdep_assert_held(&htt->rx_ring.lock); | ||
441 | |||
442 | msdu = ath10k_htt_rx_find_skb_paddr(ar, paddr); | ||
443 | if (!msdu) | ||
444 | return NULL; | ||
445 | |||
446 | rxcb = ATH10K_SKB_RXCB(msdu); | ||
447 | hash_del(&rxcb->hlist); | ||
448 | htt->rx_ring.fill_cnt--; | ||
449 | |||
450 | dma_unmap_single(htt->ar->dev, rxcb->paddr, | ||
451 | msdu->len + skb_tailroom(msdu), | ||
452 | DMA_FROM_DEVICE); | ||
453 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ", | ||
454 | msdu->data, msdu->len + skb_tailroom(msdu)); | ||
455 | |||
456 | return msdu; | ||
457 | } | ||
458 | |||
459 | static int ath10k_htt_rx_pop_paddr_list(struct ath10k_htt *htt, | ||
460 | struct htt_rx_in_ord_ind *ev, | ||
461 | struct sk_buff_head *list) | ||
462 | { | ||
463 | struct ath10k *ar = htt->ar; | ||
464 | struct htt_rx_in_ord_msdu_desc *msdu_desc = ev->msdu_descs; | ||
465 | struct htt_rx_desc *rxd; | ||
466 | struct sk_buff *msdu; | ||
467 | int msdu_count; | ||
468 | bool is_offload; | ||
469 | u32 paddr; | ||
470 | |||
471 | lockdep_assert_held(&htt->rx_ring.lock); | ||
472 | |||
473 | msdu_count = __le16_to_cpu(ev->msdu_count); | ||
474 | is_offload = !!(ev->info & HTT_RX_IN_ORD_IND_INFO_OFFLOAD_MASK); | ||
475 | |||
476 | while (msdu_count--) { | ||
477 | paddr = __le32_to_cpu(msdu_desc->msdu_paddr); | ||
478 | |||
479 | msdu = ath10k_htt_rx_pop_paddr(htt, paddr); | ||
480 | if (!msdu) { | ||
481 | __skb_queue_purge(list); | ||
482 | return -ENOENT; | ||
483 | } | ||
484 | |||
485 | __skb_queue_tail(list, msdu); | ||
486 | |||
487 | if (!is_offload) { | ||
488 | rxd = (void *)msdu->data; | ||
489 | |||
490 | trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd)); | ||
491 | |||
492 | skb_put(msdu, sizeof(*rxd)); | ||
493 | skb_pull(msdu, sizeof(*rxd)); | ||
494 | skb_put(msdu, __le16_to_cpu(msdu_desc->msdu_len)); | ||
495 | |||
496 | if (!(__le32_to_cpu(rxd->attention.flags) & | ||
497 | RX_ATTENTION_FLAGS_MSDU_DONE)) { | ||
498 | ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n"); | ||
499 | return -EIO; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | msdu_desc++; | ||
504 | } | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
382 | int ath10k_htt_rx_alloc(struct ath10k_htt *htt) | 509 | int ath10k_htt_rx_alloc(struct ath10k_htt *htt) |
383 | { | 510 | { |
384 | struct ath10k *ar = htt->ar; | 511 | struct ath10k *ar = htt->ar; |
@@ -424,7 +551,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) | |||
424 | 551 | ||
425 | htt->rx_ring.alloc_idx.vaddr = vaddr; | 552 | htt->rx_ring.alloc_idx.vaddr = vaddr; |
426 | htt->rx_ring.alloc_idx.paddr = paddr; | 553 | htt->rx_ring.alloc_idx.paddr = paddr; |
427 | htt->rx_ring.sw_rd_idx.msdu_payld = 0; | 554 | htt->rx_ring.sw_rd_idx.msdu_payld = htt->rx_ring.size_mask; |
428 | *htt->rx_ring.alloc_idx.vaddr = 0; | 555 | *htt->rx_ring.alloc_idx.vaddr = 0; |
429 | 556 | ||
430 | /* Initialize the Rx refill retry timer */ | 557 | /* Initialize the Rx refill retry timer */ |
@@ -433,14 +560,15 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) | |||
433 | spin_lock_init(&htt->rx_ring.lock); | 560 | spin_lock_init(&htt->rx_ring.lock); |
434 | 561 | ||
435 | htt->rx_ring.fill_cnt = 0; | 562 | htt->rx_ring.fill_cnt = 0; |
436 | if (__ath10k_htt_rx_ring_fill_n(htt, htt->rx_ring.fill_level)) | 563 | htt->rx_ring.sw_rd_idx.msdu_payld = 0; |
437 | goto err_fill_ring; | 564 | hash_init(htt->rx_ring.skb_table); |
438 | 565 | ||
439 | tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task, | 566 | tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task, |
440 | (unsigned long)htt); | 567 | (unsigned long)htt); |
441 | 568 | ||
442 | skb_queue_head_init(&htt->tx_compl_q); | 569 | skb_queue_head_init(&htt->tx_compl_q); |
443 | skb_queue_head_init(&htt->rx_compl_q); | 570 | skb_queue_head_init(&htt->rx_compl_q); |
571 | skb_queue_head_init(&htt->rx_in_ord_compl_q); | ||
444 | 572 | ||
445 | tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task, | 573 | tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task, |
446 | (unsigned long)htt); | 574 | (unsigned long)htt); |
@@ -449,12 +577,6 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) | |||
449 | htt->rx_ring.size, htt->rx_ring.fill_level); | 577 | htt->rx_ring.size, htt->rx_ring.fill_level); |
450 | return 0; | 578 | return 0; |
451 | 579 | ||
452 | err_fill_ring: | ||
453 | ath10k_htt_rx_ring_free(htt); | ||
454 | dma_free_coherent(htt->ar->dev, | ||
455 | sizeof(*htt->rx_ring.alloc_idx.vaddr), | ||
456 | htt->rx_ring.alloc_idx.vaddr, | ||
457 | htt->rx_ring.alloc_idx.paddr); | ||
458 | err_dma_idx: | 580 | err_dma_idx: |
459 | dma_free_coherent(htt->ar->dev, | 581 | dma_free_coherent(htt->ar->dev, |
460 | (htt->rx_ring.size * | 582 | (htt->rx_ring.size * |
@@ -691,7 +813,7 @@ static void ath10k_htt_rx_h_mactime(struct ath10k *ar, | |||
691 | * | 813 | * |
692 | * FIXME: Can we get/compute 64bit TSF? | 814 | * FIXME: Can we get/compute 64bit TSF? |
693 | */ | 815 | */ |
694 | status->mactime = __le32_to_cpu(rxd->ppdu_end.tsf_timestamp); | 816 | status->mactime = __le32_to_cpu(rxd->ppdu_end.common.tsf_timestamp); |
695 | status->flag |= RX_FLAG_MACTIME_END; | 817 | status->flag |= RX_FLAG_MACTIME_END; |
696 | } | 818 | } |
697 | 819 | ||
@@ -1578,6 +1700,194 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp) | |||
1578 | spin_unlock_bh(&ar->data_lock); | 1700 | spin_unlock_bh(&ar->data_lock); |
1579 | } | 1701 | } |
1580 | 1702 | ||
1703 | static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list, | ||
1704 | struct sk_buff_head *amsdu) | ||
1705 | { | ||
1706 | struct sk_buff *msdu; | ||
1707 | struct htt_rx_desc *rxd; | ||
1708 | |||
1709 | if (skb_queue_empty(list)) | ||
1710 | return -ENOBUFS; | ||
1711 | |||
1712 | if (WARN_ON(!skb_queue_empty(amsdu))) | ||
1713 | return -EINVAL; | ||
1714 | |||
1715 | while ((msdu = __skb_dequeue(list))) { | ||
1716 | __skb_queue_tail(amsdu, msdu); | ||
1717 | |||
1718 | rxd = (void *)msdu->data - sizeof(*rxd); | ||
1719 | if (rxd->msdu_end.info0 & | ||
1720 | __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)) | ||
1721 | break; | ||
1722 | } | ||
1723 | |||
1724 | msdu = skb_peek_tail(amsdu); | ||
1725 | rxd = (void *)msdu->data - sizeof(*rxd); | ||
1726 | if (!(rxd->msdu_end.info0 & | ||
1727 | __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))) { | ||
1728 | skb_queue_splice_init(amsdu, list); | ||
1729 | return -EAGAIN; | ||
1730 | } | ||
1731 | |||
1732 | return 0; | ||
1733 | } | ||
1734 | |||
1735 | static void ath10k_htt_rx_h_rx_offload_prot(struct ieee80211_rx_status *status, | ||
1736 | struct sk_buff *skb) | ||
1737 | { | ||
1738 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1739 | |||
1740 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
1741 | return; | ||
1742 | |||
1743 | /* Offloaded frames are already decrypted but firmware insists they are | ||
1744 | * protected in the 802.11 header. Strip the flag. Otherwise mac80211 | ||
1745 | * will drop the frame. | ||
1746 | */ | ||
1747 | |||
1748 | hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
1749 | status->flag |= RX_FLAG_DECRYPTED | | ||
1750 | RX_FLAG_IV_STRIPPED | | ||
1751 | RX_FLAG_MMIC_STRIPPED; | ||
1752 | } | ||
1753 | |||
1754 | static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar, | ||
1755 | struct sk_buff_head *list) | ||
1756 | { | ||
1757 | struct ath10k_htt *htt = &ar->htt; | ||
1758 | struct ieee80211_rx_status *status = &htt->rx_status; | ||
1759 | struct htt_rx_offload_msdu *rx; | ||
1760 | struct sk_buff *msdu; | ||
1761 | size_t offset; | ||
1762 | |||
1763 | while ((msdu = __skb_dequeue(list))) { | ||
1764 | /* Offloaded frames don't have Rx descriptor. Instead they have | ||
1765 | * a short meta information header. | ||
1766 | */ | ||
1767 | |||
1768 | rx = (void *)msdu->data; | ||
1769 | |||
1770 | skb_put(msdu, sizeof(*rx)); | ||
1771 | skb_pull(msdu, sizeof(*rx)); | ||
1772 | |||
1773 | if (skb_tailroom(msdu) < __le16_to_cpu(rx->msdu_len)) { | ||
1774 | ath10k_warn(ar, "dropping frame: offloaded rx msdu is too long!\n"); | ||
1775 | dev_kfree_skb_any(msdu); | ||
1776 | continue; | ||
1777 | } | ||
1778 | |||
1779 | skb_put(msdu, __le16_to_cpu(rx->msdu_len)); | ||
1780 | |||
1781 | /* Offloaded rx header length isn't multiple of 2 nor 4 so the | ||
1782 | * actual payload is unaligned. Align the frame. Otherwise | ||
1783 | * mac80211 complains. This shouldn't reduce performance much | ||
1784 | * because these offloaded frames are rare. | ||
1785 | */ | ||
1786 | offset = 4 - ((unsigned long)msdu->data & 3); | ||
1787 | skb_put(msdu, offset); | ||
1788 | memmove(msdu->data + offset, msdu->data, msdu->len); | ||
1789 | skb_pull(msdu, offset); | ||
1790 | |||
1791 | /* FIXME: The frame is NWifi. Re-construct QoS Control | ||
1792 | * if possible later. | ||
1793 | */ | ||
1794 | |||
1795 | memset(status, 0, sizeof(*status)); | ||
1796 | status->flag |= RX_FLAG_NO_SIGNAL_VAL; | ||
1797 | |||
1798 | ath10k_htt_rx_h_rx_offload_prot(status, msdu); | ||
1799 | ath10k_htt_rx_h_channel(ar, status); | ||
1800 | ath10k_process_rx(ar, status, msdu); | ||
1801 | } | ||
1802 | } | ||
1803 | |||
1804 | static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) | ||
1805 | { | ||
1806 | struct ath10k_htt *htt = &ar->htt; | ||
1807 | struct htt_resp *resp = (void *)skb->data; | ||
1808 | struct ieee80211_rx_status *status = &htt->rx_status; | ||
1809 | struct sk_buff_head list; | ||
1810 | struct sk_buff_head amsdu; | ||
1811 | u16 peer_id; | ||
1812 | u16 msdu_count; | ||
1813 | u8 vdev_id; | ||
1814 | u8 tid; | ||
1815 | bool offload; | ||
1816 | bool frag; | ||
1817 | int ret; | ||
1818 | |||
1819 | lockdep_assert_held(&htt->rx_ring.lock); | ||
1820 | |||
1821 | if (htt->rx_confused) | ||
1822 | return; | ||
1823 | |||
1824 | skb_pull(skb, sizeof(resp->hdr)); | ||
1825 | skb_pull(skb, sizeof(resp->rx_in_ord_ind)); | ||
1826 | |||
1827 | peer_id = __le16_to_cpu(resp->rx_in_ord_ind.peer_id); | ||
1828 | msdu_count = __le16_to_cpu(resp->rx_in_ord_ind.msdu_count); | ||
1829 | vdev_id = resp->rx_in_ord_ind.vdev_id; | ||
1830 | tid = SM(resp->rx_in_ord_ind.info, HTT_RX_IN_ORD_IND_INFO_TID); | ||
1831 | offload = !!(resp->rx_in_ord_ind.info & | ||
1832 | HTT_RX_IN_ORD_IND_INFO_OFFLOAD_MASK); | ||
1833 | frag = !!(resp->rx_in_ord_ind.info & HTT_RX_IN_ORD_IND_INFO_FRAG_MASK); | ||
1834 | |||
1835 | ath10k_dbg(ar, ATH10K_DBG_HTT, | ||
1836 | "htt rx in ord vdev %i peer %i tid %i offload %i frag %i msdu count %i\n", | ||
1837 | vdev_id, peer_id, tid, offload, frag, msdu_count); | ||
1838 | |||
1839 | if (skb->len < msdu_count * sizeof(*resp->rx_in_ord_ind.msdu_descs)) { | ||
1840 | ath10k_warn(ar, "dropping invalid in order rx indication\n"); | ||
1841 | return; | ||
1842 | } | ||
1843 | |||
1844 | /* The event can deliver more than 1 A-MSDU. Each A-MSDU is later | ||
1845 | * extracted and processed. | ||
1846 | */ | ||
1847 | __skb_queue_head_init(&list); | ||
1848 | ret = ath10k_htt_rx_pop_paddr_list(htt, &resp->rx_in_ord_ind, &list); | ||
1849 | if (ret < 0) { | ||
1850 | ath10k_warn(ar, "failed to pop paddr list: %d\n", ret); | ||
1851 | htt->rx_confused = true; | ||
1852 | return; | ||
1853 | } | ||
1854 | |||
1855 | /* Offloaded frames are very different and need to be handled | ||
1856 | * separately. | ||
1857 | */ | ||
1858 | if (offload) | ||
1859 | ath10k_htt_rx_h_rx_offload(ar, &list); | ||
1860 | |||
1861 | while (!skb_queue_empty(&list)) { | ||
1862 | __skb_queue_head_init(&amsdu); | ||
1863 | ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu); | ||
1864 | switch (ret) { | ||
1865 | case 0: | ||
1866 | /* Note: The in-order indication may report interleaved | ||
1867 | * frames from different PPDUs meaning reported rx rate | ||
1868 | * to mac80211 isn't accurate/reliable. It's still | ||
1869 | * better to report something than nothing though. This | ||
1870 | * should still give an idea about rx rate to the user. | ||
1871 | */ | ||
1872 | ath10k_htt_rx_h_ppdu(ar, &amsdu, status); | ||
1873 | ath10k_htt_rx_h_filter(ar, &amsdu, status); | ||
1874 | ath10k_htt_rx_h_mpdu(ar, &amsdu, status); | ||
1875 | ath10k_htt_rx_h_deliver(ar, &amsdu, status); | ||
1876 | break; | ||
1877 | case -EAGAIN: | ||
1878 | /* fall through */ | ||
1879 | default: | ||
1880 | /* Should not happen. */ | ||
1881 | ath10k_warn(ar, "failed to extract amsdu: %d\n", ret); | ||
1882 | htt->rx_confused = true; | ||
1883 | __skb_queue_purge(&list); | ||
1884 | return; | ||
1885 | } | ||
1886 | } | ||
1887 | |||
1888 | tasklet_schedule(&htt->rx_replenish_task); | ||
1889 | } | ||
1890 | |||
1581 | void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | 1891 | void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) |
1582 | { | 1892 | { |
1583 | struct ath10k_htt *htt = &ar->htt; | 1893 | struct ath10k_htt *htt = &ar->htt; |
@@ -1700,6 +2010,20 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1700 | */ | 2010 | */ |
1701 | break; | 2011 | break; |
1702 | } | 2012 | } |
2013 | case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: { | ||
2014 | spin_lock_bh(&htt->rx_ring.lock); | ||
2015 | __skb_queue_tail(&htt->rx_in_ord_compl_q, skb); | ||
2016 | spin_unlock_bh(&htt->rx_ring.lock); | ||
2017 | tasklet_schedule(&htt->txrx_compl_task); | ||
2018 | return; | ||
2019 | } | ||
2020 | case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: | ||
2021 | /* FIXME: This WMI-TLV event is overlapping with 10.2 | ||
2022 | * CHAN_CHANGE - both being 0xF. Neither is being used in | ||
2023 | * practice so no immediate action is necessary. Nevertheless | ||
2024 | * HTT may need an abstraction layer like WMI has one day. | ||
2025 | */ | ||
2026 | break; | ||
1703 | default: | 2027 | default: |
1704 | ath10k_warn(ar, "htt event (%d) not handled\n", | 2028 | ath10k_warn(ar, "htt event (%d) not handled\n", |
1705 | resp->hdr.msg_type); | 2029 | resp->hdr.msg_type); |
@@ -1715,6 +2039,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1715 | static void ath10k_htt_txrx_compl_task(unsigned long ptr) | 2039 | static void ath10k_htt_txrx_compl_task(unsigned long ptr) |
1716 | { | 2040 | { |
1717 | struct ath10k_htt *htt = (struct ath10k_htt *)ptr; | 2041 | struct ath10k_htt *htt = (struct ath10k_htt *)ptr; |
2042 | struct ath10k *ar = htt->ar; | ||
1718 | struct htt_resp *resp; | 2043 | struct htt_resp *resp; |
1719 | struct sk_buff *skb; | 2044 | struct sk_buff *skb; |
1720 | 2045 | ||
@@ -1731,5 +2056,10 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) | |||
1731 | ath10k_htt_rx_handler(htt, &resp->rx_ind); | 2056 | ath10k_htt_rx_handler(htt, &resp->rx_ind); |
1732 | dev_kfree_skb_any(skb); | 2057 | dev_kfree_skb_any(skb); |
1733 | } | 2058 | } |
2059 | |||
2060 | while ((skb = __skb_dequeue(&htt->rx_in_ord_compl_q))) { | ||
2061 | ath10k_htt_rx_in_ord_ind(ar, skb); | ||
2062 | dev_kfree_skb_any(skb); | ||
2063 | } | ||
1734 | spin_unlock_bh(&htt->rx_ring.lock); | 2064 | spin_unlock_bh(&htt->rx_ring.lock); |
1735 | } | 2065 | } |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index a1bda41fb543..cbd2bc9e6202 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -56,21 +56,18 @@ exit: | |||
56 | return ret; | 56 | return ret; |
57 | } | 57 | } |
58 | 58 | ||
59 | int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt) | 59 | int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb) |
60 | { | 60 | { |
61 | struct ath10k *ar = htt->ar; | 61 | struct ath10k *ar = htt->ar; |
62 | int msdu_id; | 62 | int ret; |
63 | 63 | ||
64 | lockdep_assert_held(&htt->tx_lock); | 64 | lockdep_assert_held(&htt->tx_lock); |
65 | 65 | ||
66 | msdu_id = find_first_zero_bit(htt->used_msdu_ids, | 66 | ret = idr_alloc(&htt->pending_tx, skb, 0, 0x10000, GFP_ATOMIC); |
67 | htt->max_num_pending_tx); | 67 | |
68 | if (msdu_id == htt->max_num_pending_tx) | 68 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", ret); |
69 | return -ENOBUFS; | ||
70 | 69 | ||
71 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", msdu_id); | 70 | return ret; |
72 | __set_bit(msdu_id, htt->used_msdu_ids); | ||
73 | return msdu_id; | ||
74 | } | 71 | } |
75 | 72 | ||
76 | void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) | 73 | void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) |
@@ -79,74 +76,53 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) | |||
79 | 76 | ||
80 | lockdep_assert_held(&htt->tx_lock); | 77 | lockdep_assert_held(&htt->tx_lock); |
81 | 78 | ||
82 | if (!test_bit(msdu_id, htt->used_msdu_ids)) | ||
83 | ath10k_warn(ar, "trying to free unallocated msdu_id %d\n", | ||
84 | msdu_id); | ||
85 | |||
86 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx free msdu_id %hu\n", msdu_id); | 79 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx free msdu_id %hu\n", msdu_id); |
87 | __clear_bit(msdu_id, htt->used_msdu_ids); | 80 | |
81 | idr_remove(&htt->pending_tx, msdu_id); | ||
88 | } | 82 | } |
89 | 83 | ||
90 | int ath10k_htt_tx_alloc(struct ath10k_htt *htt) | 84 | int ath10k_htt_tx_alloc(struct ath10k_htt *htt) |
91 | { | 85 | { |
92 | struct ath10k *ar = htt->ar; | 86 | struct ath10k *ar = htt->ar; |
93 | 87 | ||
94 | spin_lock_init(&htt->tx_lock); | ||
95 | |||
96 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", | 88 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", |
97 | htt->max_num_pending_tx); | 89 | htt->max_num_pending_tx); |
98 | 90 | ||
99 | htt->pending_tx = kzalloc(sizeof(*htt->pending_tx) * | 91 | spin_lock_init(&htt->tx_lock); |
100 | htt->max_num_pending_tx, GFP_KERNEL); | 92 | idr_init(&htt->pending_tx); |
101 | if (!htt->pending_tx) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | htt->used_msdu_ids = kzalloc(sizeof(unsigned long) * | ||
105 | BITS_TO_LONGS(htt->max_num_pending_tx), | ||
106 | GFP_KERNEL); | ||
107 | if (!htt->used_msdu_ids) { | ||
108 | kfree(htt->pending_tx); | ||
109 | return -ENOMEM; | ||
110 | } | ||
111 | 93 | ||
112 | htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev, | 94 | htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev, |
113 | sizeof(struct ath10k_htt_txbuf), 4, 0); | 95 | sizeof(struct ath10k_htt_txbuf), 4, 0); |
114 | if (!htt->tx_pool) { | 96 | if (!htt->tx_pool) { |
115 | kfree(htt->used_msdu_ids); | 97 | idr_destroy(&htt->pending_tx); |
116 | kfree(htt->pending_tx); | ||
117 | return -ENOMEM; | 98 | return -ENOMEM; |
118 | } | 99 | } |
119 | 100 | ||
120 | return 0; | 101 | return 0; |
121 | } | 102 | } |
122 | 103 | ||
123 | static void ath10k_htt_tx_free_pending(struct ath10k_htt *htt) | 104 | static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx) |
124 | { | 105 | { |
125 | struct ath10k *ar = htt->ar; | 106 | struct ath10k *ar = ctx; |
107 | struct ath10k_htt *htt = &ar->htt; | ||
126 | struct htt_tx_done tx_done = {0}; | 108 | struct htt_tx_done tx_done = {0}; |
127 | int msdu_id; | ||
128 | |||
129 | spin_lock_bh(&htt->tx_lock); | ||
130 | for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) { | ||
131 | if (!test_bit(msdu_id, htt->used_msdu_ids)) | ||
132 | continue; | ||
133 | 109 | ||
134 | ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", | 110 | ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", msdu_id); |
135 | msdu_id); | ||
136 | 111 | ||
137 | tx_done.discard = 1; | 112 | tx_done.discard = 1; |
138 | tx_done.msdu_id = msdu_id; | 113 | tx_done.msdu_id = msdu_id; |
139 | 114 | ||
140 | ath10k_txrx_tx_unref(htt, &tx_done); | 115 | spin_lock_bh(&htt->tx_lock); |
141 | } | 116 | ath10k_txrx_tx_unref(htt, &tx_done); |
142 | spin_unlock_bh(&htt->tx_lock); | 117 | spin_unlock_bh(&htt->tx_lock); |
118 | |||
119 | return 0; | ||
143 | } | 120 | } |
144 | 121 | ||
145 | void ath10k_htt_tx_free(struct ath10k_htt *htt) | 122 | void ath10k_htt_tx_free(struct ath10k_htt *htt) |
146 | { | 123 | { |
147 | ath10k_htt_tx_free_pending(htt); | 124 | idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); |
148 | kfree(htt->pending_tx); | 125 | idr_destroy(&htt->pending_tx); |
149 | kfree(htt->used_msdu_ids); | ||
150 | dma_pool_destroy(htt->tx_pool); | 126 | dma_pool_destroy(htt->tx_pool); |
151 | } | 127 | } |
152 | 128 | ||
@@ -378,13 +354,12 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
378 | len += sizeof(cmd->mgmt_tx); | 354 | len += sizeof(cmd->mgmt_tx); |
379 | 355 | ||
380 | spin_lock_bh(&htt->tx_lock); | 356 | spin_lock_bh(&htt->tx_lock); |
381 | res = ath10k_htt_tx_alloc_msdu_id(htt); | 357 | res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); |
382 | if (res < 0) { | 358 | if (res < 0) { |
383 | spin_unlock_bh(&htt->tx_lock); | 359 | spin_unlock_bh(&htt->tx_lock); |
384 | goto err_tx_dec; | 360 | goto err_tx_dec; |
385 | } | 361 | } |
386 | msdu_id = res; | 362 | msdu_id = res; |
387 | htt->pending_tx[msdu_id] = msdu; | ||
388 | spin_unlock_bh(&htt->tx_lock); | 363 | spin_unlock_bh(&htt->tx_lock); |
389 | 364 | ||
390 | txdesc = ath10k_htc_alloc_skb(ar, len); | 365 | txdesc = ath10k_htc_alloc_skb(ar, len); |
@@ -423,7 +398,6 @@ err_free_txdesc: | |||
423 | dev_kfree_skb_any(txdesc); | 398 | dev_kfree_skb_any(txdesc); |
424 | err_free_msdu_id: | 399 | err_free_msdu_id: |
425 | spin_lock_bh(&htt->tx_lock); | 400 | spin_lock_bh(&htt->tx_lock); |
426 | htt->pending_tx[msdu_id] = NULL; | ||
427 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); | 401 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); |
428 | spin_unlock_bh(&htt->tx_lock); | 402 | spin_unlock_bh(&htt->tx_lock); |
429 | err_tx_dec: | 403 | err_tx_dec: |
@@ -455,13 +429,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
455 | goto err; | 429 | goto err; |
456 | 430 | ||
457 | spin_lock_bh(&htt->tx_lock); | 431 | spin_lock_bh(&htt->tx_lock); |
458 | res = ath10k_htt_tx_alloc_msdu_id(htt); | 432 | res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); |
459 | if (res < 0) { | 433 | if (res < 0) { |
460 | spin_unlock_bh(&htt->tx_lock); | 434 | spin_unlock_bh(&htt->tx_lock); |
461 | goto err_tx_dec; | 435 | goto err_tx_dec; |
462 | } | 436 | } |
463 | msdu_id = res; | 437 | msdu_id = res; |
464 | htt->pending_tx[msdu_id] = msdu; | ||
465 | spin_unlock_bh(&htt->tx_lock); | 438 | spin_unlock_bh(&htt->tx_lock); |
466 | 439 | ||
467 | prefetch_len = min(htt->prefetch_len, msdu->len); | 440 | prefetch_len = min(htt->prefetch_len, msdu->len); |
@@ -475,10 +448,18 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
475 | 448 | ||
476 | skb_cb->htt.txbuf = dma_pool_alloc(htt->tx_pool, GFP_ATOMIC, | 449 | skb_cb->htt.txbuf = dma_pool_alloc(htt->tx_pool, GFP_ATOMIC, |
477 | &paddr); | 450 | &paddr); |
478 | if (!skb_cb->htt.txbuf) | 451 | if (!skb_cb->htt.txbuf) { |
452 | res = -ENOMEM; | ||
479 | goto err_free_msdu_id; | 453 | goto err_free_msdu_id; |
454 | } | ||
480 | skb_cb->htt.txbuf_paddr = paddr; | 455 | skb_cb->htt.txbuf_paddr = paddr; |
481 | 456 | ||
457 | if ((ieee80211_is_action(hdr->frame_control) || | ||
458 | ieee80211_is_deauth(hdr->frame_control) || | ||
459 | ieee80211_is_disassoc(hdr->frame_control)) && | ||
460 | ieee80211_has_protected(hdr->frame_control)) | ||
461 | skb_put(msdu, IEEE80211_CCMP_MIC_LEN); | ||
462 | |||
482 | skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, | 463 | skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, |
483 | DMA_TO_DEVICE); | 464 | DMA_TO_DEVICE); |
484 | res = dma_mapping_error(dev, skb_cb->paddr); | 465 | res = dma_mapping_error(dev, skb_cb->paddr); |
@@ -534,8 +515,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
534 | 515 | ||
535 | flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); | 516 | flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); |
536 | flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID); | 517 | flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID); |
537 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD; | 518 | if (msdu->ip_summed == CHECKSUM_PARTIAL) { |
538 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD; | 519 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD; |
520 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD; | ||
521 | } | ||
539 | 522 | ||
540 | /* Prevent firmware from sending up tx inspection requests. There's | 523 | /* Prevent firmware from sending up tx inspection requests. There's |
541 | * nothing ath10k can do with frames requested for inspection so force | 524 | * nothing ath10k can do with frames requested for inspection so force |
@@ -593,7 +576,6 @@ err_free_txbuf: | |||
593 | skb_cb->htt.txbuf_paddr); | 576 | skb_cb->htt.txbuf_paddr); |
594 | err_free_msdu_id: | 577 | err_free_msdu_id: |
595 | spin_lock_bh(&htt->tx_lock); | 578 | spin_lock_bh(&htt->tx_lock); |
596 | htt->pending_tx[msdu_id] = NULL; | ||
597 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); | 579 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); |
598 | spin_unlock_bh(&htt->tx_lock); | 580 | spin_unlock_bh(&htt->tx_lock); |
599 | err_tx_dec: | 581 | err_tx_dec: |
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c new file mode 100644 index 000000000000..839a8791fb9e --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/hw.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014-2015 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/types.h> | ||
18 | #include "hw.h" | ||
19 | |||
20 | const struct ath10k_hw_regs qca988x_regs = { | ||
21 | .rtc_state_cold_reset_mask = 0x00000400, | ||
22 | .rtc_soc_base_address = 0x00004000, | ||
23 | .rtc_wmac_base_address = 0x00005000, | ||
24 | .soc_core_base_address = 0x00009000, | ||
25 | .ce_wrapper_base_address = 0x00057000, | ||
26 | .ce0_base_address = 0x00057400, | ||
27 | .ce1_base_address = 0x00057800, | ||
28 | .ce2_base_address = 0x00057c00, | ||
29 | .ce3_base_address = 0x00058000, | ||
30 | .ce4_base_address = 0x00058400, | ||
31 | .ce5_base_address = 0x00058800, | ||
32 | .ce6_base_address = 0x00058c00, | ||
33 | .ce7_base_address = 0x00059000, | ||
34 | .soc_reset_control_si0_rst_mask = 0x00000001, | ||
35 | .soc_reset_control_ce_rst_mask = 0x00040000, | ||
36 | .soc_chip_id_address = 0x00ec, | ||
37 | .scratch_3_address = 0x0030, | ||
38 | }; | ||
39 | |||
40 | const struct ath10k_hw_regs qca6174_regs = { | ||
41 | .rtc_state_cold_reset_mask = 0x00002000, | ||
42 | .rtc_soc_base_address = 0x00000800, | ||
43 | .rtc_wmac_base_address = 0x00001000, | ||
44 | .soc_core_base_address = 0x0003a000, | ||
45 | .ce_wrapper_base_address = 0x00034000, | ||
46 | .ce0_base_address = 0x00034400, | ||
47 | .ce1_base_address = 0x00034800, | ||
48 | .ce2_base_address = 0x00034c00, | ||
49 | .ce3_base_address = 0x00035000, | ||
50 | .ce4_base_address = 0x00035400, | ||
51 | .ce5_base_address = 0x00035800, | ||
52 | .ce6_base_address = 0x00035c00, | ||
53 | .ce7_base_address = 0x00036000, | ||
54 | .soc_reset_control_si0_rst_mask = 0x00000000, | ||
55 | .soc_reset_control_ce_rst_mask = 0x00000001, | ||
56 | .soc_chip_id_address = 0x000f0, | ||
57 | .scratch_3_address = 0x0028, | ||
58 | }; | ||
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 5729901923ac..460771fcfe9e 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
@@ -34,6 +34,44 @@ | |||
34 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" | 34 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" |
35 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 | 35 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 |
36 | 36 | ||
37 | /* QCA6174 target BMI version signatures */ | ||
38 | #define QCA6174_HW_1_0_VERSION 0x05000000 | ||
39 | #define QCA6174_HW_1_1_VERSION 0x05000001 | ||
40 | #define QCA6174_HW_1_3_VERSION 0x05000003 | ||
41 | #define QCA6174_HW_2_1_VERSION 0x05010000 | ||
42 | #define QCA6174_HW_3_0_VERSION 0x05020000 | ||
43 | #define QCA6174_HW_3_2_VERSION 0x05030000 | ||
44 | |||
45 | enum qca6174_pci_rev { | ||
46 | QCA6174_PCI_REV_1_1 = 0x11, | ||
47 | QCA6174_PCI_REV_1_3 = 0x13, | ||
48 | QCA6174_PCI_REV_2_0 = 0x20, | ||
49 | QCA6174_PCI_REV_3_0 = 0x30, | ||
50 | }; | ||
51 | |||
52 | enum qca6174_chip_id_rev { | ||
53 | QCA6174_HW_1_0_CHIP_ID_REV = 0, | ||
54 | QCA6174_HW_1_1_CHIP_ID_REV = 1, | ||
55 | QCA6174_HW_1_3_CHIP_ID_REV = 2, | ||
56 | QCA6174_HW_2_1_CHIP_ID_REV = 4, | ||
57 | QCA6174_HW_2_2_CHIP_ID_REV = 5, | ||
58 | QCA6174_HW_3_0_CHIP_ID_REV = 8, | ||
59 | QCA6174_HW_3_1_CHIP_ID_REV = 9, | ||
60 | QCA6174_HW_3_2_CHIP_ID_REV = 10, | ||
61 | }; | ||
62 | |||
63 | #define QCA6174_HW_2_1_FW_DIR "ath10k/QCA6174/hw2.1" | ||
64 | #define QCA6174_HW_2_1_FW_FILE "firmware.bin" | ||
65 | #define QCA6174_HW_2_1_OTP_FILE "otp.bin" | ||
66 | #define QCA6174_HW_2_1_BOARD_DATA_FILE "board.bin" | ||
67 | #define QCA6174_HW_2_1_PATCH_LOAD_ADDR 0x1234 | ||
68 | |||
69 | #define QCA6174_HW_3_0_FW_DIR "ath10k/QCA6174/hw3.0" | ||
70 | #define QCA6174_HW_3_0_FW_FILE "firmware.bin" | ||
71 | #define QCA6174_HW_3_0_OTP_FILE "otp.bin" | ||
72 | #define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin" | ||
73 | #define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234 | ||
74 | |||
37 | #define ATH10K_FW_API2_FILE "firmware-2.bin" | 75 | #define ATH10K_FW_API2_FILE "firmware-2.bin" |
38 | #define ATH10K_FW_API3_FILE "firmware-3.bin" | 76 | #define ATH10K_FW_API3_FILE "firmware-3.bin" |
39 | 77 | ||
@@ -81,6 +119,37 @@ enum ath10k_fw_wmi_op_version { | |||
81 | ATH10K_FW_WMI_OP_VERSION_MAX, | 119 | ATH10K_FW_WMI_OP_VERSION_MAX, |
82 | }; | 120 | }; |
83 | 121 | ||
122 | enum ath10k_hw_rev { | ||
123 | ATH10K_HW_QCA988X, | ||
124 | ATH10K_HW_QCA6174, | ||
125 | }; | ||
126 | |||
127 | struct ath10k_hw_regs { | ||
128 | u32 rtc_state_cold_reset_mask; | ||
129 | u32 rtc_soc_base_address; | ||
130 | u32 rtc_wmac_base_address; | ||
131 | u32 soc_core_base_address; | ||
132 | u32 ce_wrapper_base_address; | ||
133 | u32 ce0_base_address; | ||
134 | u32 ce1_base_address; | ||
135 | u32 ce2_base_address; | ||
136 | u32 ce3_base_address; | ||
137 | u32 ce4_base_address; | ||
138 | u32 ce5_base_address; | ||
139 | u32 ce6_base_address; | ||
140 | u32 ce7_base_address; | ||
141 | u32 soc_reset_control_si0_rst_mask; | ||
142 | u32 soc_reset_control_ce_rst_mask; | ||
143 | u32 soc_chip_id_address; | ||
144 | u32 scratch_3_address; | ||
145 | }; | ||
146 | |||
147 | extern const struct ath10k_hw_regs qca988x_regs; | ||
148 | extern const struct ath10k_hw_regs qca6174_regs; | ||
149 | |||
150 | #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) | ||
151 | #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) | ||
152 | |||
84 | /* Known pecularities: | 153 | /* Known pecularities: |
85 | * - current FW doesn't support raw rx mode (last tested v599) | 154 | * - current FW doesn't support raw rx mode (last tested v599) |
86 | * - current FW dumps upon raw tx mode (last tested v599) | 155 | * - current FW dumps upon raw tx mode (last tested v599) |
@@ -183,6 +252,9 @@ struct ath10k_pktlog_hdr { | |||
183 | #define TARGET_10X_NUM_MSDU_DESC (1024 + 400) | 252 | #define TARGET_10X_NUM_MSDU_DESC (1024 + 400) |
184 | #define TARGET_10X_MAX_FRAG_ENTRIES 0 | 253 | #define TARGET_10X_MAX_FRAG_ENTRIES 0 |
185 | 254 | ||
255 | /* 10.2 parameters */ | ||
256 | #define TARGET_10_2_DMA_BURST_SIZE 1 | ||
257 | |||
186 | /* Target specific defines for WMI-TLV firmware */ | 258 | /* Target specific defines for WMI-TLV firmware */ |
187 | #define TARGET_TLV_NUM_VDEVS 3 | 259 | #define TARGET_TLV_NUM_VDEVS 3 |
188 | #define TARGET_TLV_NUM_STATIONS 32 | 260 | #define TARGET_TLV_NUM_STATIONS 32 |
@@ -222,7 +294,7 @@ struct ath10k_pktlog_hdr { | |||
222 | /* as of IP3.7.1 */ | 294 | /* as of IP3.7.1 */ |
223 | #define RTC_STATE_V_ON 3 | 295 | #define RTC_STATE_V_ON 3 |
224 | 296 | ||
225 | #define RTC_STATE_COLD_RESET_MASK 0x00000400 | 297 | #define RTC_STATE_COLD_RESET_MASK ar->regs->rtc_state_cold_reset_mask |
226 | #define RTC_STATE_V_LSB 0 | 298 | #define RTC_STATE_V_LSB 0 |
227 | #define RTC_STATE_V_MASK 0x00000007 | 299 | #define RTC_STATE_V_MASK 0x00000007 |
228 | #define RTC_STATE_ADDRESS 0x0000 | 300 | #define RTC_STATE_ADDRESS 0x0000 |
@@ -231,12 +303,12 @@ struct ath10k_pktlog_hdr { | |||
231 | #define PCIE_SOC_WAKE_RESET 0x00000000 | 303 | #define PCIE_SOC_WAKE_RESET 0x00000000 |
232 | #define SOC_GLOBAL_RESET_ADDRESS 0x0008 | 304 | #define SOC_GLOBAL_RESET_ADDRESS 0x0008 |
233 | 305 | ||
234 | #define RTC_SOC_BASE_ADDRESS 0x00004000 | 306 | #define RTC_SOC_BASE_ADDRESS ar->regs->rtc_soc_base_address |
235 | #define RTC_WMAC_BASE_ADDRESS 0x00005000 | 307 | #define RTC_WMAC_BASE_ADDRESS ar->regs->rtc_wmac_base_address |
236 | #define MAC_COEX_BASE_ADDRESS 0x00006000 | 308 | #define MAC_COEX_BASE_ADDRESS 0x00006000 |
237 | #define BT_COEX_BASE_ADDRESS 0x00007000 | 309 | #define BT_COEX_BASE_ADDRESS 0x00007000 |
238 | #define SOC_PCIE_BASE_ADDRESS 0x00008000 | 310 | #define SOC_PCIE_BASE_ADDRESS 0x00008000 |
239 | #define SOC_CORE_BASE_ADDRESS 0x00009000 | 311 | #define SOC_CORE_BASE_ADDRESS ar->regs->soc_core_base_address |
240 | #define WLAN_UART_BASE_ADDRESS 0x0000c000 | 312 | #define WLAN_UART_BASE_ADDRESS 0x0000c000 |
241 | #define WLAN_SI_BASE_ADDRESS 0x00010000 | 313 | #define WLAN_SI_BASE_ADDRESS 0x00010000 |
242 | #define WLAN_GPIO_BASE_ADDRESS 0x00014000 | 314 | #define WLAN_GPIO_BASE_ADDRESS 0x00014000 |
@@ -245,23 +317,23 @@ struct ath10k_pktlog_hdr { | |||
245 | #define EFUSE_BASE_ADDRESS 0x00030000 | 317 | #define EFUSE_BASE_ADDRESS 0x00030000 |
246 | #define FPGA_REG_BASE_ADDRESS 0x00039000 | 318 | #define FPGA_REG_BASE_ADDRESS 0x00039000 |
247 | #define WLAN_UART2_BASE_ADDRESS 0x00054c00 | 319 | #define WLAN_UART2_BASE_ADDRESS 0x00054c00 |
248 | #define CE_WRAPPER_BASE_ADDRESS 0x00057000 | 320 | #define CE_WRAPPER_BASE_ADDRESS ar->regs->ce_wrapper_base_address |
249 | #define CE0_BASE_ADDRESS 0x00057400 | 321 | #define CE0_BASE_ADDRESS ar->regs->ce0_base_address |
250 | #define CE1_BASE_ADDRESS 0x00057800 | 322 | #define CE1_BASE_ADDRESS ar->regs->ce1_base_address |
251 | #define CE2_BASE_ADDRESS 0x00057c00 | 323 | #define CE2_BASE_ADDRESS ar->regs->ce2_base_address |
252 | #define CE3_BASE_ADDRESS 0x00058000 | 324 | #define CE3_BASE_ADDRESS ar->regs->ce3_base_address |
253 | #define CE4_BASE_ADDRESS 0x00058400 | 325 | #define CE4_BASE_ADDRESS ar->regs->ce4_base_address |
254 | #define CE5_BASE_ADDRESS 0x00058800 | 326 | #define CE5_BASE_ADDRESS ar->regs->ce5_base_address |
255 | #define CE6_BASE_ADDRESS 0x00058c00 | 327 | #define CE6_BASE_ADDRESS ar->regs->ce6_base_address |
256 | #define CE7_BASE_ADDRESS 0x00059000 | 328 | #define CE7_BASE_ADDRESS ar->regs->ce7_base_address |
257 | #define DBI_BASE_ADDRESS 0x00060000 | 329 | #define DBI_BASE_ADDRESS 0x00060000 |
258 | #define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 | 330 | #define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS 0x0006c000 |
259 | #define PCIE_LOCAL_BASE_ADDRESS 0x00080000 | 331 | #define PCIE_LOCAL_BASE_ADDRESS 0x00080000 |
260 | 332 | ||
261 | #define SOC_RESET_CONTROL_ADDRESS 0x00000000 | 333 | #define SOC_RESET_CONTROL_ADDRESS 0x00000000 |
262 | #define SOC_RESET_CONTROL_OFFSET 0x00000000 | 334 | #define SOC_RESET_CONTROL_OFFSET 0x00000000 |
263 | #define SOC_RESET_CONTROL_SI0_RST_MASK 0x00000001 | 335 | #define SOC_RESET_CONTROL_SI0_RST_MASK ar->regs->soc_reset_control_si0_rst_mask |
264 | #define SOC_RESET_CONTROL_CE_RST_MASK 0x00040000 | 336 | #define SOC_RESET_CONTROL_CE_RST_MASK ar->regs->soc_reset_control_ce_rst_mask |
265 | #define SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 | 337 | #define SOC_RESET_CONTROL_CPU_WARM_RST_MASK 0x00000040 |
266 | #define SOC_CPU_CLOCK_OFFSET 0x00000020 | 338 | #define SOC_CPU_CLOCK_OFFSET 0x00000020 |
267 | #define SOC_CPU_CLOCK_STANDARD_LSB 0 | 339 | #define SOC_CPU_CLOCK_STANDARD_LSB 0 |
@@ -275,7 +347,7 @@ struct ath10k_pktlog_hdr { | |||
275 | #define SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 | 347 | #define SOC_LF_TIMER_CONTROL0_ADDRESS 0x00000050 |
276 | #define SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 | 348 | #define SOC_LF_TIMER_CONTROL0_ENABLE_MASK 0x00000004 |
277 | 349 | ||
278 | #define SOC_CHIP_ID_ADDRESS 0x000000ec | 350 | #define SOC_CHIP_ID_ADDRESS ar->regs->soc_chip_id_address |
279 | #define SOC_CHIP_ID_REV_LSB 8 | 351 | #define SOC_CHIP_ID_REV_LSB 8 |
280 | #define SOC_CHIP_ID_REV_MASK 0x00000f00 | 352 | #define SOC_CHIP_ID_REV_MASK 0x00000f00 |
281 | 353 | ||
@@ -331,7 +403,7 @@ struct ath10k_pktlog_hdr { | |||
331 | #define PCIE_INTR_ENABLE_ADDRESS 0x0008 | 403 | #define PCIE_INTR_ENABLE_ADDRESS 0x0008 |
332 | #define PCIE_INTR_CAUSE_ADDRESS 0x000c | 404 | #define PCIE_INTR_CAUSE_ADDRESS 0x000c |
333 | #define PCIE_INTR_CLR_ADDRESS 0x0014 | 405 | #define PCIE_INTR_CLR_ADDRESS 0x0014 |
334 | #define SCRATCH_3_ADDRESS 0x0030 | 406 | #define SCRATCH_3_ADDRESS ar->regs->scratch_3_address |
335 | #define CPU_INTR_ADDRESS 0x0010 | 407 | #define CPU_INTR_ADDRESS 0x0010 |
336 | 408 | ||
337 | /* Firmware indications to the Host via SCRATCH_3 register. */ | 409 | /* Firmware indications to the Host via SCRATCH_3 register. */ |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 60a524b73207..d6d2f0f00caa 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -37,7 +37,7 @@ | |||
37 | static int ath10k_send_key(struct ath10k_vif *arvif, | 37 | static int ath10k_send_key(struct ath10k_vif *arvif, |
38 | struct ieee80211_key_conf *key, | 38 | struct ieee80211_key_conf *key, |
39 | enum set_key_cmd cmd, | 39 | enum set_key_cmd cmd, |
40 | const u8 *macaddr) | 40 | const u8 *macaddr, bool def_idx) |
41 | { | 41 | { |
42 | struct ath10k *ar = arvif->ar; | 42 | struct ath10k *ar = arvif->ar; |
43 | struct wmi_vdev_install_key_arg arg = { | 43 | struct wmi_vdev_install_key_arg arg = { |
@@ -58,10 +58,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif, | |||
58 | switch (key->cipher) { | 58 | switch (key->cipher) { |
59 | case WLAN_CIPHER_SUITE_CCMP: | 59 | case WLAN_CIPHER_SUITE_CCMP: |
60 | arg.key_cipher = WMI_CIPHER_AES_CCM; | 60 | arg.key_cipher = WMI_CIPHER_AES_CCM; |
61 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) | 61 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT; |
62 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT; | ||
63 | else | ||
64 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | ||
65 | break; | 62 | break; |
66 | case WLAN_CIPHER_SUITE_TKIP: | 63 | case WLAN_CIPHER_SUITE_TKIP: |
67 | arg.key_cipher = WMI_CIPHER_TKIP; | 64 | arg.key_cipher = WMI_CIPHER_TKIP; |
@@ -75,6 +72,9 @@ static int ath10k_send_key(struct ath10k_vif *arvif, | |||
75 | * Otherwise pairwise key must be set */ | 72 | * Otherwise pairwise key must be set */ |
76 | if (memcmp(macaddr, arvif->vif->addr, ETH_ALEN)) | 73 | if (memcmp(macaddr, arvif->vif->addr, ETH_ALEN)) |
77 | arg.key_flags = WMI_KEY_PAIRWISE; | 74 | arg.key_flags = WMI_KEY_PAIRWISE; |
75 | |||
76 | if (def_idx) | ||
77 | arg.key_flags |= WMI_KEY_TX_USAGE; | ||
78 | break; | 78 | break; |
79 | case WLAN_CIPHER_SUITE_AES_CMAC: | 79 | case WLAN_CIPHER_SUITE_AES_CMAC: |
80 | /* this one needs to be done in software */ | 80 | /* this one needs to be done in software */ |
@@ -95,7 +95,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif, | |||
95 | static int ath10k_install_key(struct ath10k_vif *arvif, | 95 | static int ath10k_install_key(struct ath10k_vif *arvif, |
96 | struct ieee80211_key_conf *key, | 96 | struct ieee80211_key_conf *key, |
97 | enum set_key_cmd cmd, | 97 | enum set_key_cmd cmd, |
98 | const u8 *macaddr) | 98 | const u8 *macaddr, bool def_idx) |
99 | { | 99 | { |
100 | struct ath10k *ar = arvif->ar; | 100 | struct ath10k *ar = arvif->ar; |
101 | int ret; | 101 | int ret; |
@@ -104,7 +104,7 @@ static int ath10k_install_key(struct ath10k_vif *arvif, | |||
104 | 104 | ||
105 | reinit_completion(&ar->install_key_done); | 105 | reinit_completion(&ar->install_key_done); |
106 | 106 | ||
107 | ret = ath10k_send_key(arvif, key, cmd, macaddr); | 107 | ret = ath10k_send_key(arvif, key, cmd, macaddr, def_idx); |
108 | if (ret) | 108 | if (ret) |
109 | return ret; | 109 | return ret; |
110 | 110 | ||
@@ -122,6 +122,7 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif, | |||
122 | struct ath10k_peer *peer; | 122 | struct ath10k_peer *peer; |
123 | int ret; | 123 | int ret; |
124 | int i; | 124 | int i; |
125 | bool def_idx; | ||
125 | 126 | ||
126 | lockdep_assert_held(&ar->conf_mutex); | 127 | lockdep_assert_held(&ar->conf_mutex); |
127 | 128 | ||
@@ -135,9 +136,14 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif, | |||
135 | for (i = 0; i < ARRAY_SIZE(arvif->wep_keys); i++) { | 136 | for (i = 0; i < ARRAY_SIZE(arvif->wep_keys); i++) { |
136 | if (arvif->wep_keys[i] == NULL) | 137 | if (arvif->wep_keys[i] == NULL) |
137 | continue; | 138 | continue; |
139 | /* set TX_USAGE flag for default key id */ | ||
140 | if (arvif->def_wep_key_idx == i) | ||
141 | def_idx = true; | ||
142 | else | ||
143 | def_idx = false; | ||
138 | 144 | ||
139 | ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY, | 145 | ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY, |
140 | addr); | 146 | addr, def_idx); |
141 | if (ret) | 147 | if (ret) |
142 | return ret; | 148 | return ret; |
143 | 149 | ||
@@ -171,8 +177,9 @@ static int ath10k_clear_peer_keys(struct ath10k_vif *arvif, | |||
171 | if (peer->keys[i] == NULL) | 177 | if (peer->keys[i] == NULL) |
172 | continue; | 178 | continue; |
173 | 179 | ||
180 | /* key flags are not required to delete the key */ | ||
174 | ret = ath10k_install_key(arvif, peer->keys[i], | 181 | ret = ath10k_install_key(arvif, peer->keys[i], |
175 | DISABLE_KEY, addr); | 182 | DISABLE_KEY, addr, false); |
176 | if (ret && first_errno == 0) | 183 | if (ret && first_errno == 0) |
177 | first_errno = ret; | 184 | first_errno = ret; |
178 | 185 | ||
@@ -246,8 +253,8 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif, | |||
246 | 253 | ||
247 | if (i == ARRAY_SIZE(peer->keys)) | 254 | if (i == ARRAY_SIZE(peer->keys)) |
248 | break; | 255 | break; |
249 | 256 | /* key flags are not required to delete the key */ | |
250 | ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr); | 257 | ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr, false); |
251 | if (ret && first_errno == 0) | 258 | if (ret && first_errno == 0) |
252 | first_errno = ret; | 259 | first_errno = ret; |
253 | 260 | ||
@@ -527,10 +534,14 @@ void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif) | |||
527 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr, | 534 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr, |
528 | arvif->beacon->len, DMA_TO_DEVICE); | 535 | arvif->beacon->len, DMA_TO_DEVICE); |
529 | 536 | ||
537 | if (WARN_ON(arvif->beacon_state != ATH10K_BEACON_SCHEDULED && | ||
538 | arvif->beacon_state != ATH10K_BEACON_SENT)) | ||
539 | return; | ||
540 | |||
530 | dev_kfree_skb_any(arvif->beacon); | 541 | dev_kfree_skb_any(arvif->beacon); |
531 | 542 | ||
532 | arvif->beacon = NULL; | 543 | arvif->beacon = NULL; |
533 | arvif->beacon_sent = false; | 544 | arvif->beacon_state = ATH10K_BEACON_SCHEDULED; |
534 | } | 545 | } |
535 | 546 | ||
536 | static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif) | 547 | static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif) |
@@ -970,6 +981,143 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif) | |||
970 | return ret; | 981 | return ret; |
971 | } | 982 | } |
972 | 983 | ||
984 | static int ath10k_mac_setup_bcn_p2p_ie(struct ath10k_vif *arvif, | ||
985 | struct sk_buff *bcn) | ||
986 | { | ||
987 | struct ath10k *ar = arvif->ar; | ||
988 | struct ieee80211_mgmt *mgmt; | ||
989 | const u8 *p2p_ie; | ||
990 | int ret; | ||
991 | |||
992 | if (arvif->vdev_type != WMI_VDEV_TYPE_AP) | ||
993 | return 0; | ||
994 | |||
995 | if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) | ||
996 | return 0; | ||
997 | |||
998 | mgmt = (void *)bcn->data; | ||
999 | p2p_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, | ||
1000 | mgmt->u.beacon.variable, | ||
1001 | bcn->len - (mgmt->u.beacon.variable - | ||
1002 | bcn->data)); | ||
1003 | if (!p2p_ie) | ||
1004 | return -ENOENT; | ||
1005 | |||
1006 | ret = ath10k_wmi_p2p_go_bcn_ie(ar, arvif->vdev_id, p2p_ie); | ||
1007 | if (ret) { | ||
1008 | ath10k_warn(ar, "failed to submit p2p go bcn ie for vdev %i: %d\n", | ||
1009 | arvif->vdev_id, ret); | ||
1010 | return ret; | ||
1011 | } | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static int ath10k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui, | ||
1017 | u8 oui_type, size_t ie_offset) | ||
1018 | { | ||
1019 | size_t len; | ||
1020 | const u8 *next; | ||
1021 | const u8 *end; | ||
1022 | u8 *ie; | ||
1023 | |||
1024 | if (WARN_ON(skb->len < ie_offset)) | ||
1025 | return -EINVAL; | ||
1026 | |||
1027 | ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type, | ||
1028 | skb->data + ie_offset, | ||
1029 | skb->len - ie_offset); | ||
1030 | if (!ie) | ||
1031 | return -ENOENT; | ||
1032 | |||
1033 | len = ie[1] + 2; | ||
1034 | end = skb->data + skb->len; | ||
1035 | next = ie + len; | ||
1036 | |||
1037 | if (WARN_ON(next > end)) | ||
1038 | return -EINVAL; | ||
1039 | |||
1040 | memmove(ie, next, end - next); | ||
1041 | skb_trim(skb, skb->len - len); | ||
1042 | |||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | static int ath10k_mac_setup_bcn_tmpl(struct ath10k_vif *arvif) | ||
1047 | { | ||
1048 | struct ath10k *ar = arvif->ar; | ||
1049 | struct ieee80211_hw *hw = ar->hw; | ||
1050 | struct ieee80211_vif *vif = arvif->vif; | ||
1051 | struct ieee80211_mutable_offsets offs = {}; | ||
1052 | struct sk_buff *bcn; | ||
1053 | int ret; | ||
1054 | |||
1055 | if (!test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map)) | ||
1056 | return 0; | ||
1057 | |||
1058 | bcn = ieee80211_beacon_get_template(hw, vif, &offs); | ||
1059 | if (!bcn) { | ||
1060 | ath10k_warn(ar, "failed to get beacon template from mac80211\n"); | ||
1061 | return -EPERM; | ||
1062 | } | ||
1063 | |||
1064 | ret = ath10k_mac_setup_bcn_p2p_ie(arvif, bcn); | ||
1065 | if (ret) { | ||
1066 | ath10k_warn(ar, "failed to setup p2p go bcn ie: %d\n", ret); | ||
1067 | kfree_skb(bcn); | ||
1068 | return ret; | ||
1069 | } | ||
1070 | |||
1071 | /* P2P IE is inserted by firmware automatically (as configured above) | ||
1072 | * so remove it from the base beacon template to avoid duplicate P2P | ||
1073 | * IEs in beacon frames. | ||
1074 | */ | ||
1075 | ath10k_mac_remove_vendor_ie(bcn, WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, | ||
1076 | offsetof(struct ieee80211_mgmt, | ||
1077 | u.beacon.variable)); | ||
1078 | |||
1079 | ret = ath10k_wmi_bcn_tmpl(ar, arvif->vdev_id, offs.tim_offset, bcn, 0, | ||
1080 | 0, NULL, 0); | ||
1081 | kfree_skb(bcn); | ||
1082 | |||
1083 | if (ret) { | ||
1084 | ath10k_warn(ar, "failed to submit beacon template command: %d\n", | ||
1085 | ret); | ||
1086 | return ret; | ||
1087 | } | ||
1088 | |||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | static int ath10k_mac_setup_prb_tmpl(struct ath10k_vif *arvif) | ||
1093 | { | ||
1094 | struct ath10k *ar = arvif->ar; | ||
1095 | struct ieee80211_hw *hw = ar->hw; | ||
1096 | struct ieee80211_vif *vif = arvif->vif; | ||
1097 | struct sk_buff *prb; | ||
1098 | int ret; | ||
1099 | |||
1100 | if (!test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map)) | ||
1101 | return 0; | ||
1102 | |||
1103 | prb = ieee80211_proberesp_get(hw, vif); | ||
1104 | if (!prb) { | ||
1105 | ath10k_warn(ar, "failed to get probe resp template from mac80211\n"); | ||
1106 | return -EPERM; | ||
1107 | } | ||
1108 | |||
1109 | ret = ath10k_wmi_prb_tmpl(ar, arvif->vdev_id, prb); | ||
1110 | kfree_skb(prb); | ||
1111 | |||
1112 | if (ret) { | ||
1113 | ath10k_warn(ar, "failed to submit probe resp template command: %d\n", | ||
1114 | ret); | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
973 | static void ath10k_control_beaconing(struct ath10k_vif *arvif, | 1121 | static void ath10k_control_beaconing(struct ath10k_vif *arvif, |
974 | struct ieee80211_bss_conf *info) | 1122 | struct ieee80211_bss_conf *info) |
975 | { | 1123 | { |
@@ -1155,6 +1303,38 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) | |||
1155 | return 0; | 1303 | return 0; |
1156 | } | 1304 | } |
1157 | 1305 | ||
1306 | static int ath10k_mac_vif_disable_keepalive(struct ath10k_vif *arvif) | ||
1307 | { | ||
1308 | struct ath10k *ar = arvif->ar; | ||
1309 | struct wmi_sta_keepalive_arg arg = {}; | ||
1310 | int ret; | ||
1311 | |||
1312 | lockdep_assert_held(&arvif->ar->conf_mutex); | ||
1313 | |||
1314 | if (arvif->vdev_type != WMI_VDEV_TYPE_STA) | ||
1315 | return 0; | ||
1316 | |||
1317 | if (!test_bit(WMI_SERVICE_STA_KEEP_ALIVE, ar->wmi.svc_map)) | ||
1318 | return 0; | ||
1319 | |||
1320 | /* Some firmware revisions have a bug and ignore the `enabled` field. | ||
1321 | * Instead use the interval to disable the keepalive. | ||
1322 | */ | ||
1323 | arg.vdev_id = arvif->vdev_id; | ||
1324 | arg.enabled = 1; | ||
1325 | arg.method = WMI_STA_KEEPALIVE_METHOD_NULL_FRAME; | ||
1326 | arg.interval = WMI_STA_KEEPALIVE_INTERVAL_DISABLE; | ||
1327 | |||
1328 | ret = ath10k_wmi_sta_keepalive(ar, &arg); | ||
1329 | if (ret) { | ||
1330 | ath10k_warn(ar, "failed to submit keepalive on vdev %i: %d\n", | ||
1331 | arvif->vdev_id, ret); | ||
1332 | return ret; | ||
1333 | } | ||
1334 | |||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
1158 | /**********************/ | 1338 | /**********************/ |
1159 | /* Station management */ | 1339 | /* Station management */ |
1160 | /**********************/ | 1340 | /**********************/ |
@@ -1423,6 +1603,10 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, | |||
1423 | return; | 1603 | return; |
1424 | 1604 | ||
1425 | arg->peer_flags |= WMI_PEER_VHT; | 1605 | arg->peer_flags |= WMI_PEER_VHT; |
1606 | |||
1607 | if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) | ||
1608 | arg->peer_flags |= WMI_PEER_VHT_2G; | ||
1609 | |||
1426 | arg->peer_vht_caps = vht_cap->cap; | 1610 | arg->peer_vht_caps = vht_cap->cap; |
1427 | 1611 | ||
1428 | ampdu_factor = (vht_cap->cap & | 1612 | ampdu_factor = (vht_cap->cap & |
@@ -1501,7 +1685,12 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | |||
1501 | 1685 | ||
1502 | switch (ar->hw->conf.chandef.chan->band) { | 1686 | switch (ar->hw->conf.chandef.chan->band) { |
1503 | case IEEE80211_BAND_2GHZ: | 1687 | case IEEE80211_BAND_2GHZ: |
1504 | if (sta->ht_cap.ht_supported) { | 1688 | if (sta->vht_cap.vht_supported) { |
1689 | if (sta->bandwidth == IEEE80211_STA_RX_BW_40) | ||
1690 | phymode = MODE_11AC_VHT40; | ||
1691 | else | ||
1692 | phymode = MODE_11AC_VHT20; | ||
1693 | } else if (sta->ht_cap.ht_supported) { | ||
1505 | if (sta->bandwidth == IEEE80211_STA_RX_BW_40) | 1694 | if (sta->bandwidth == IEEE80211_STA_RX_BW_40) |
1506 | phymode = MODE_11NG_HT40; | 1695 | phymode = MODE_11NG_HT40; |
1507 | else | 1696 | else |
@@ -1683,7 +1872,8 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | |||
1683 | ath10k_warn(ar, "faield to down vdev %i: %d\n", | 1872 | ath10k_warn(ar, "faield to down vdev %i: %d\n", |
1684 | arvif->vdev_id, ret); | 1873 | arvif->vdev_id, ret); |
1685 | 1874 | ||
1686 | arvif->def_wep_key_idx = 0; | 1875 | arvif->def_wep_key_idx = -1; |
1876 | |||
1687 | arvif->is_up = false; | 1877 | arvif->is_up = false; |
1688 | } | 1878 | } |
1689 | 1879 | ||
@@ -1742,11 +1932,14 @@ static int ath10k_station_assoc(struct ath10k *ar, | |||
1742 | } | 1932 | } |
1743 | } | 1933 | } |
1744 | 1934 | ||
1745 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); | 1935 | /* Plumb cached keys only for static WEP */ |
1746 | if (ret) { | 1936 | if (arvif->def_wep_key_idx != -1) { |
1747 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", | 1937 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); |
1748 | arvif->vdev_id, ret); | 1938 | if (ret) { |
1749 | return ret; | 1939 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", |
1940 | arvif->vdev_id, ret); | ||
1941 | return ret; | ||
1942 | } | ||
1750 | } | 1943 | } |
1751 | } | 1944 | } |
1752 | 1945 | ||
@@ -2011,75 +2204,13 @@ static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2011 | * used only for CQM purposes (e.g. hostapd station keepalive ping) so | 2204 | * used only for CQM purposes (e.g. hostapd station keepalive ping) so |
2012 | * it is safe to downgrade to NullFunc. | 2205 | * it is safe to downgrade to NullFunc. |
2013 | */ | 2206 | */ |
2207 | hdr = (void *)skb->data; | ||
2014 | if (ieee80211_is_qos_nullfunc(hdr->frame_control)) { | 2208 | if (ieee80211_is_qos_nullfunc(hdr->frame_control)) { |
2015 | hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | 2209 | hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
2016 | cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; | 2210 | cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; |
2017 | } | 2211 | } |
2018 | } | 2212 | } |
2019 | 2213 | ||
2020 | static void ath10k_tx_wep_key_work(struct work_struct *work) | ||
2021 | { | ||
2022 | struct ath10k_vif *arvif = container_of(work, struct ath10k_vif, | ||
2023 | wep_key_work); | ||
2024 | struct ath10k *ar = arvif->ar; | ||
2025 | int ret, keyidx = arvif->def_wep_key_newidx; | ||
2026 | |||
2027 | mutex_lock(&arvif->ar->conf_mutex); | ||
2028 | |||
2029 | if (arvif->ar->state != ATH10K_STATE_ON) | ||
2030 | goto unlock; | ||
2031 | |||
2032 | if (arvif->def_wep_key_idx == keyidx) | ||
2033 | goto unlock; | ||
2034 | |||
2035 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n", | ||
2036 | arvif->vdev_id, keyidx); | ||
2037 | |||
2038 | ret = ath10k_wmi_vdev_set_param(arvif->ar, | ||
2039 | arvif->vdev_id, | ||
2040 | arvif->ar->wmi.vdev_param->def_keyid, | ||
2041 | keyidx); | ||
2042 | if (ret) { | ||
2043 | ath10k_warn(ar, "failed to update wep key index for vdev %d: %d\n", | ||
2044 | arvif->vdev_id, | ||
2045 | ret); | ||
2046 | goto unlock; | ||
2047 | } | ||
2048 | |||
2049 | arvif->def_wep_key_idx = keyidx; | ||
2050 | |||
2051 | unlock: | ||
2052 | mutex_unlock(&arvif->ar->conf_mutex); | ||
2053 | } | ||
2054 | |||
2055 | static void ath10k_tx_h_update_wep_key(struct ieee80211_vif *vif, | ||
2056 | struct ieee80211_key_conf *key, | ||
2057 | struct sk_buff *skb) | ||
2058 | { | ||
2059 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
2060 | struct ath10k *ar = arvif->ar; | ||
2061 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
2062 | |||
2063 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
2064 | return; | ||
2065 | |||
2066 | if (!key) | ||
2067 | return; | ||
2068 | |||
2069 | if (key->cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
2070 | key->cipher != WLAN_CIPHER_SUITE_WEP104) | ||
2071 | return; | ||
2072 | |||
2073 | if (key->keyidx == arvif->def_wep_key_idx) | ||
2074 | return; | ||
2075 | |||
2076 | /* FIXME: Most likely a few frames will be TXed with an old key. Simply | ||
2077 | * queueing frames until key index is updated is not an option because | ||
2078 | * sk_buff may need more processing to be done, e.g. offchannel */ | ||
2079 | arvif->def_wep_key_newidx = key->keyidx; | ||
2080 | ieee80211_queue_work(ar->hw, &arvif->wep_key_work); | ||
2081 | } | ||
2082 | |||
2083 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, | 2214 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, |
2084 | struct ieee80211_vif *vif, | 2215 | struct ieee80211_vif *vif, |
2085 | struct sk_buff *skb) | 2216 | struct sk_buff *skb) |
@@ -2231,7 +2362,7 @@ void ath10k_offchan_tx_work(struct work_struct *work) | |||
2231 | 2362 | ||
2232 | ret = wait_for_completion_timeout(&ar->offchan_tx_completed, | 2363 | ret = wait_for_completion_timeout(&ar->offchan_tx_completed, |
2233 | 3 * HZ); | 2364 | 3 * HZ); |
2234 | if (ret <= 0) | 2365 | if (ret == 0) |
2235 | ath10k_warn(ar, "timed out waiting for offchannel skb %p\n", | 2366 | ath10k_warn(ar, "timed out waiting for offchannel skb %p\n", |
2236 | skb); | 2367 | skb); |
2237 | 2368 | ||
@@ -2293,6 +2424,7 @@ void __ath10k_scan_finish(struct ath10k *ar) | |||
2293 | case ATH10K_SCAN_RUNNING: | 2424 | case ATH10K_SCAN_RUNNING: |
2294 | if (ar->scan.is_roc) | 2425 | if (ar->scan.is_roc) |
2295 | ieee80211_remain_on_channel_expired(ar->hw); | 2426 | ieee80211_remain_on_channel_expired(ar->hw); |
2427 | /* fall through */ | ||
2296 | case ATH10K_SCAN_ABORTING: | 2428 | case ATH10K_SCAN_ABORTING: |
2297 | if (!ar->scan.is_roc) | 2429 | if (!ar->scan.is_roc) |
2298 | ieee80211_scan_completed(ar->hw, | 2430 | ieee80211_scan_completed(ar->hw, |
@@ -2439,7 +2571,6 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
2439 | struct ath10k *ar = hw->priv; | 2571 | struct ath10k *ar = hw->priv; |
2440 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2572 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2441 | struct ieee80211_vif *vif = info->control.vif; | 2573 | struct ieee80211_vif *vif = info->control.vif; |
2442 | struct ieee80211_key_conf *key = info->control.hw_key; | ||
2443 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2574 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2444 | 2575 | ||
2445 | /* We should disable CCK RATE due to P2P */ | 2576 | /* We should disable CCK RATE due to P2P */ |
@@ -2453,7 +2584,6 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
2453 | /* it makes no sense to process injected frames like that */ | 2584 | /* it makes no sense to process injected frames like that */ |
2454 | if (vif && vif->type != NL80211_IFTYPE_MONITOR) { | 2585 | if (vif && vif->type != NL80211_IFTYPE_MONITOR) { |
2455 | ath10k_tx_h_nwifi(hw, skb); | 2586 | ath10k_tx_h_nwifi(hw, skb); |
2456 | ath10k_tx_h_update_wep_key(vif, key, skb); | ||
2457 | ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb); | 2587 | ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb); |
2458 | ath10k_tx_h_seq_no(vif, skb); | 2588 | ath10k_tx_h_seq_no(vif, skb); |
2459 | } | 2589 | } |
@@ -2960,7 +3090,6 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2960 | arvif->ar = ar; | 3090 | arvif->ar = ar; |
2961 | arvif->vif = vif; | 3091 | arvif->vif = vif; |
2962 | 3092 | ||
2963 | INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work); | ||
2964 | INIT_LIST_HEAD(&arvif->list); | 3093 | INIT_LIST_HEAD(&arvif->list); |
2965 | 3094 | ||
2966 | if (ar->free_vdev_map == 0) { | 3095 | if (ar->free_vdev_map == 0) { |
@@ -3049,15 +3178,18 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
3049 | ar->free_vdev_map &= ~(1LL << arvif->vdev_id); | 3178 | ar->free_vdev_map &= ~(1LL << arvif->vdev_id); |
3050 | list_add(&arvif->list, &ar->arvifs); | 3179 | list_add(&arvif->list, &ar->arvifs); |
3051 | 3180 | ||
3052 | vdev_param = ar->wmi.vdev_param->def_keyid; | 3181 | /* It makes no sense to have firmware do keepalives. mac80211 already |
3053 | ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, | 3182 | * takes care of this with idle connection polling. |
3054 | arvif->def_wep_key_idx); | 3183 | */ |
3184 | ret = ath10k_mac_vif_disable_keepalive(arvif); | ||
3055 | if (ret) { | 3185 | if (ret) { |
3056 | ath10k_warn(ar, "failed to set vdev %i default key id: %d\n", | 3186 | ath10k_warn(ar, "failed to disable keepalive on vdev %i: %d\n", |
3057 | arvif->vdev_id, ret); | 3187 | arvif->vdev_id, ret); |
3058 | goto err_vdev_delete; | 3188 | goto err_vdev_delete; |
3059 | } | 3189 | } |
3060 | 3190 | ||
3191 | arvif->def_wep_key_idx = -1; | ||
3192 | |||
3061 | vdev_param = ar->wmi.vdev_param->tx_encap_type; | 3193 | vdev_param = ar->wmi.vdev_param->tx_encap_type; |
3062 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | 3194 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
3063 | ATH10K_HW_TXRX_NATIVE_WIFI); | 3195 | ATH10K_HW_TXRX_NATIVE_WIFI); |
@@ -3176,8 +3308,6 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
3176 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 3308 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
3177 | int ret; | 3309 | int ret; |
3178 | 3310 | ||
3179 | cancel_work_sync(&arvif->wep_key_work); | ||
3180 | |||
3181 | mutex_lock(&ar->conf_mutex); | 3311 | mutex_lock(&ar->conf_mutex); |
3182 | 3312 | ||
3183 | spin_lock_bh(&ar->data_lock); | 3313 | spin_lock_bh(&ar->data_lock); |
@@ -3288,9 +3418,21 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
3288 | if (ret) | 3418 | if (ret) |
3289 | ath10k_warn(ar, "failed to set beacon mode for vdev %d: %i\n", | 3419 | ath10k_warn(ar, "failed to set beacon mode for vdev %d: %i\n", |
3290 | arvif->vdev_id, ret); | 3420 | arvif->vdev_id, ret); |
3421 | |||
3422 | ret = ath10k_mac_setup_bcn_tmpl(arvif); | ||
3423 | if (ret) | ||
3424 | ath10k_warn(ar, "failed to update beacon template: %d\n", | ||
3425 | ret); | ||
3426 | } | ||
3427 | |||
3428 | if (changed & BSS_CHANGED_AP_PROBE_RESP) { | ||
3429 | ret = ath10k_mac_setup_prb_tmpl(arvif); | ||
3430 | if (ret) | ||
3431 | ath10k_warn(ar, "failed to setup probe resp template on vdev %i: %d\n", | ||
3432 | arvif->vdev_id, ret); | ||
3291 | } | 3433 | } |
3292 | 3434 | ||
3293 | if (changed & BSS_CHANGED_BEACON_INFO) { | 3435 | if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) { |
3294 | arvif->dtim_period = info->dtim_period; | 3436 | arvif->dtim_period = info->dtim_period; |
3295 | 3437 | ||
3296 | ath10k_dbg(ar, ATH10K_DBG_MAC, | 3438 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
@@ -3537,6 +3679,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3537 | const u8 *peer_addr; | 3679 | const u8 *peer_addr; |
3538 | bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 || | 3680 | bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
3539 | key->cipher == WLAN_CIPHER_SUITE_WEP104; | 3681 | key->cipher == WLAN_CIPHER_SUITE_WEP104; |
3682 | bool def_idx = false; | ||
3540 | int ret = 0; | 3683 | int ret = 0; |
3541 | 3684 | ||
3542 | if (key->keyidx > WMI_MAX_KEY_INDEX) | 3685 | if (key->keyidx > WMI_MAX_KEY_INDEX) |
@@ -3582,7 +3725,14 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3582 | ath10k_clear_vdev_key(arvif, key); | 3725 | ath10k_clear_vdev_key(arvif, key); |
3583 | } | 3726 | } |
3584 | 3727 | ||
3585 | ret = ath10k_install_key(arvif, key, cmd, peer_addr); | 3728 | /* set TX_USAGE flag for all the keys incase of dot1x-WEP. For |
3729 | * static WEP, do not set this flag for the keys whose key id | ||
3730 | * is greater than default key id. | ||
3731 | */ | ||
3732 | if (arvif->def_wep_key_idx == -1) | ||
3733 | def_idx = true; | ||
3734 | |||
3735 | ret = ath10k_install_key(arvif, key, cmd, peer_addr, def_idx); | ||
3586 | if (ret) { | 3736 | if (ret) { |
3587 | ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n", | 3737 | ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n", |
3588 | arvif->vdev_id, peer_addr, ret); | 3738 | arvif->vdev_id, peer_addr, ret); |
@@ -3607,6 +3757,39 @@ exit: | |||
3607 | return ret; | 3757 | return ret; |
3608 | } | 3758 | } |
3609 | 3759 | ||
3760 | static void ath10k_set_default_unicast_key(struct ieee80211_hw *hw, | ||
3761 | struct ieee80211_vif *vif, | ||
3762 | int keyidx) | ||
3763 | { | ||
3764 | struct ath10k *ar = hw->priv; | ||
3765 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
3766 | int ret; | ||
3767 | |||
3768 | mutex_lock(&arvif->ar->conf_mutex); | ||
3769 | |||
3770 | if (arvif->ar->state != ATH10K_STATE_ON) | ||
3771 | goto unlock; | ||
3772 | |||
3773 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n", | ||
3774 | arvif->vdev_id, keyidx); | ||
3775 | |||
3776 | ret = ath10k_wmi_vdev_set_param(arvif->ar, | ||
3777 | arvif->vdev_id, | ||
3778 | arvif->ar->wmi.vdev_param->def_keyid, | ||
3779 | keyidx); | ||
3780 | |||
3781 | if (ret) { | ||
3782 | ath10k_warn(ar, "failed to update wep key index for vdev %d: %d\n", | ||
3783 | arvif->vdev_id, | ||
3784 | ret); | ||
3785 | goto unlock; | ||
3786 | } | ||
3787 | |||
3788 | arvif->def_wep_key_idx = keyidx; | ||
3789 | unlock: | ||
3790 | mutex_unlock(&arvif->ar->conf_mutex); | ||
3791 | } | ||
3792 | |||
3610 | static void ath10k_sta_rc_update_wk(struct work_struct *wk) | 3793 | static void ath10k_sta_rc_update_wk(struct work_struct *wk) |
3611 | { | 3794 | { |
3612 | struct ath10k *ar; | 3795 | struct ath10k *ar; |
@@ -3842,6 +4025,8 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif, | |||
3842 | u16 ac, bool enable) | 4025 | u16 ac, bool enable) |
3843 | { | 4026 | { |
3844 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 4027 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
4028 | struct wmi_sta_uapsd_auto_trig_arg arg = {}; | ||
4029 | u32 prio = 0, acc = 0; | ||
3845 | u32 value = 0; | 4030 | u32 value = 0; |
3846 | int ret = 0; | 4031 | int ret = 0; |
3847 | 4032 | ||
@@ -3854,18 +4039,26 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif, | |||
3854 | case IEEE80211_AC_VO: | 4039 | case IEEE80211_AC_VO: |
3855 | value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN | | 4040 | value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN | |
3856 | WMI_STA_PS_UAPSD_AC3_TRIGGER_EN; | 4041 | WMI_STA_PS_UAPSD_AC3_TRIGGER_EN; |
4042 | prio = 7; | ||
4043 | acc = 3; | ||
3857 | break; | 4044 | break; |
3858 | case IEEE80211_AC_VI: | 4045 | case IEEE80211_AC_VI: |
3859 | value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN | | 4046 | value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN | |
3860 | WMI_STA_PS_UAPSD_AC2_TRIGGER_EN; | 4047 | WMI_STA_PS_UAPSD_AC2_TRIGGER_EN; |
4048 | prio = 5; | ||
4049 | acc = 2; | ||
3861 | break; | 4050 | break; |
3862 | case IEEE80211_AC_BE: | 4051 | case IEEE80211_AC_BE: |
3863 | value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN | | 4052 | value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN | |
3864 | WMI_STA_PS_UAPSD_AC1_TRIGGER_EN; | 4053 | WMI_STA_PS_UAPSD_AC1_TRIGGER_EN; |
4054 | prio = 2; | ||
4055 | acc = 1; | ||
3865 | break; | 4056 | break; |
3866 | case IEEE80211_AC_BK: | 4057 | case IEEE80211_AC_BK: |
3867 | value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN | | 4058 | value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN | |
3868 | WMI_STA_PS_UAPSD_AC0_TRIGGER_EN; | 4059 | WMI_STA_PS_UAPSD_AC0_TRIGGER_EN; |
4060 | prio = 0; | ||
4061 | acc = 0; | ||
3869 | break; | 4062 | break; |
3870 | } | 4063 | } |
3871 | 4064 | ||
@@ -3907,6 +4100,29 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif, | |||
3907 | return ret; | 4100 | return ret; |
3908 | } | 4101 | } |
3909 | 4102 | ||
4103 | if (test_bit(WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG, ar->wmi.svc_map) || | ||
4104 | test_bit(WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG, ar->wmi.svc_map)) { | ||
4105 | /* Only userspace can make an educated decision when to send | ||
4106 | * trigger frame. The following effectively disables u-UAPSD | ||
4107 | * autotrigger in firmware (which is enabled by default | ||
4108 | * provided the autotrigger service is available). | ||
4109 | */ | ||
4110 | |||
4111 | arg.wmm_ac = acc; | ||
4112 | arg.user_priority = prio; | ||
4113 | arg.service_interval = 0; | ||
4114 | arg.suspend_interval = WMI_STA_UAPSD_MAX_INTERVAL_MSEC; | ||
4115 | arg.delay_interval = WMI_STA_UAPSD_MAX_INTERVAL_MSEC; | ||
4116 | |||
4117 | ret = ath10k_wmi_vdev_sta_uapsd(ar, arvif->vdev_id, | ||
4118 | arvif->bssid, &arg, 1); | ||
4119 | if (ret) { | ||
4120 | ath10k_warn(ar, "failed to set uapsd auto trigger %d\n", | ||
4121 | ret); | ||
4122 | return ret; | ||
4123 | } | ||
4124 | } | ||
4125 | |||
3910 | exit: | 4126 | exit: |
3911 | return ret; | 4127 | return ret; |
3912 | } | 4128 | } |
@@ -3916,6 +4132,7 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw, | |||
3916 | const struct ieee80211_tx_queue_params *params) | 4132 | const struct ieee80211_tx_queue_params *params) |
3917 | { | 4133 | { |
3918 | struct ath10k *ar = hw->priv; | 4134 | struct ath10k *ar = hw->priv; |
4135 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
3919 | struct wmi_wmm_params_arg *p = NULL; | 4136 | struct wmi_wmm_params_arg *p = NULL; |
3920 | int ret; | 4137 | int ret; |
3921 | 4138 | ||
@@ -3923,16 +4140,16 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw, | |||
3923 | 4140 | ||
3924 | switch (ac) { | 4141 | switch (ac) { |
3925 | case IEEE80211_AC_VO: | 4142 | case IEEE80211_AC_VO: |
3926 | p = &ar->wmm_params.ac_vo; | 4143 | p = &arvif->wmm_params.ac_vo; |
3927 | break; | 4144 | break; |
3928 | case IEEE80211_AC_VI: | 4145 | case IEEE80211_AC_VI: |
3929 | p = &ar->wmm_params.ac_vi; | 4146 | p = &arvif->wmm_params.ac_vi; |
3930 | break; | 4147 | break; |
3931 | case IEEE80211_AC_BE: | 4148 | case IEEE80211_AC_BE: |
3932 | p = &ar->wmm_params.ac_be; | 4149 | p = &arvif->wmm_params.ac_be; |
3933 | break; | 4150 | break; |
3934 | case IEEE80211_AC_BK: | 4151 | case IEEE80211_AC_BK: |
3935 | p = &ar->wmm_params.ac_bk; | 4152 | p = &arvif->wmm_params.ac_bk; |
3936 | break; | 4153 | break; |
3937 | } | 4154 | } |
3938 | 4155 | ||
@@ -3952,11 +4169,23 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw, | |||
3952 | */ | 4169 | */ |
3953 | p->txop = params->txop * 32; | 4170 | p->txop = params->txop * 32; |
3954 | 4171 | ||
3955 | /* FIXME: FW accepts wmm params per hw, not per vif */ | 4172 | if (ar->wmi.ops->gen_vdev_wmm_conf) { |
3956 | ret = ath10k_wmi_pdev_set_wmm_params(ar, &ar->wmm_params); | 4173 | ret = ath10k_wmi_vdev_wmm_conf(ar, arvif->vdev_id, |
3957 | if (ret) { | 4174 | &arvif->wmm_params); |
3958 | ath10k_warn(ar, "failed to set wmm params: %d\n", ret); | 4175 | if (ret) { |
3959 | goto exit; | 4176 | ath10k_warn(ar, "failed to set vdev wmm params on vdev %i: %d\n", |
4177 | arvif->vdev_id, ret); | ||
4178 | goto exit; | ||
4179 | } | ||
4180 | } else { | ||
4181 | /* This won't work well with multi-interface cases but it's | ||
4182 | * better than nothing. | ||
4183 | */ | ||
4184 | ret = ath10k_wmi_pdev_set_wmm_params(ar, &arvif->wmm_params); | ||
4185 | if (ret) { | ||
4186 | ath10k_warn(ar, "failed to set wmm params: %d\n", ret); | ||
4187 | goto exit; | ||
4188 | } | ||
3960 | } | 4189 | } |
3961 | 4190 | ||
3962 | ret = ath10k_conf_tx_uapsd(ar, vif, ac, params->uapsd); | 4191 | ret = ath10k_conf_tx_uapsd(ar, vif, ac, params->uapsd); |
@@ -4726,6 +4955,7 @@ static const struct ieee80211_ops ath10k_ops = { | |||
4726 | .hw_scan = ath10k_hw_scan, | 4955 | .hw_scan = ath10k_hw_scan, |
4727 | .cancel_hw_scan = ath10k_cancel_hw_scan, | 4956 | .cancel_hw_scan = ath10k_cancel_hw_scan, |
4728 | .set_key = ath10k_set_key, | 4957 | .set_key = ath10k_set_key, |
4958 | .set_default_unicast_key = ath10k_set_default_unicast_key, | ||
4729 | .sta_state = ath10k_sta_state, | 4959 | .sta_state = ath10k_sta_state, |
4730 | .conf_tx = ath10k_conf_tx, | 4960 | .conf_tx = ath10k_conf_tx, |
4731 | .remain_on_channel = ath10k_remain_on_channel, | 4961 | .remain_on_channel = ath10k_remain_on_channel, |
@@ -4751,6 +4981,9 @@ static const struct ieee80211_ops ath10k_ops = { | |||
4751 | .suspend = ath10k_suspend, | 4981 | .suspend = ath10k_suspend, |
4752 | .resume = ath10k_resume, | 4982 | .resume = ath10k_resume, |
4753 | #endif | 4983 | #endif |
4984 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
4985 | .sta_add_debugfs = ath10k_sta_add_debugfs, | ||
4986 | #endif | ||
4754 | }; | 4987 | }; |
4755 | 4988 | ||
4756 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | 4989 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ |
@@ -5074,7 +5307,8 @@ int ath10k_mac_register(struct ath10k *ar) | |||
5074 | band->bitrates = ath10k_g_rates; | 5307 | band->bitrates = ath10k_g_rates; |
5075 | band->ht_cap = ht_cap; | 5308 | band->ht_cap = ht_cap; |
5076 | 5309 | ||
5077 | /* vht is not supported in 2.4 GHz */ | 5310 | /* Enable the VHT support at 2.4 GHz */ |
5311 | band->vht_cap = vht_cap; | ||
5078 | 5312 | ||
5079 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; | 5313 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; |
5080 | } | 5314 | } |
@@ -5139,6 +5373,19 @@ int ath10k_mac_register(struct ath10k *ar) | |||
5139 | 5373 | ||
5140 | ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; | 5374 | ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; |
5141 | 5375 | ||
5376 | if (test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map)) { | ||
5377 | ar->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
5378 | |||
5379 | /* Firmware delivers WPS/P2P Probe Requests frames to driver so | ||
5380 | * that userspace (e.g. wpa_supplicant/hostapd) can generate | ||
5381 | * correct Probe Responses. This is more of a hack advert.. | ||
5382 | */ | ||
5383 | ar->hw->wiphy->probe_resp_offload |= | ||
5384 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
5385 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
5386 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | ||
5387 | } | ||
5388 | |||
5142 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 5389 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
5143 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; | 5390 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; |
5144 | ar->hw->wiphy->max_remain_on_channel_duration = 5000; | 5391 | ar->hw->wiphy->max_remain_on_channel_duration = 5000; |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 5e50214246f8..e6972b09333e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -58,9 +58,11 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)"); | |||
58 | #define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3 | 58 | #define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3 |
59 | 59 | ||
60 | #define QCA988X_2_0_DEVICE_ID (0x003c) | 60 | #define QCA988X_2_0_DEVICE_ID (0x003c) |
61 | #define QCA6174_2_1_DEVICE_ID (0x003e) | ||
61 | 62 | ||
62 | static const struct pci_device_id ath10k_pci_id_table[] = { | 63 | static const struct pci_device_id ath10k_pci_id_table[] = { |
63 | { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ | 64 | { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ |
65 | { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */ | ||
64 | {0} | 66 | {0} |
65 | }; | 67 | }; |
66 | 68 | ||
@@ -70,6 +72,11 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { | |||
70 | * because of that. | 72 | * because of that. |
71 | */ | 73 | */ |
72 | { QCA988X_2_0_DEVICE_ID, QCA988X_HW_2_0_CHIP_ID_REV }, | 74 | { QCA988X_2_0_DEVICE_ID, QCA988X_HW_2_0_CHIP_ID_REV }, |
75 | { QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_1_CHIP_ID_REV }, | ||
76 | { QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_2_CHIP_ID_REV }, | ||
77 | { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_0_CHIP_ID_REV }, | ||
78 | { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_1_CHIP_ID_REV }, | ||
79 | { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV }, | ||
73 | }; | 80 | }; |
74 | 81 | ||
75 | static void ath10k_pci_buffer_cleanup(struct ath10k *ar); | 82 | static void ath10k_pci_buffer_cleanup(struct ath10k *ar); |
@@ -403,7 +410,7 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) | |||
403 | return -EIO; | 410 | return -EIO; |
404 | } | 411 | } |
405 | 412 | ||
406 | ATH10K_SKB_CB(skb)->paddr = paddr; | 413 | ATH10K_SKB_RXCB(skb)->paddr = paddr; |
407 | 414 | ||
408 | ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr); | 415 | ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr); |
409 | if (ret) { | 416 | if (ret) { |
@@ -872,7 +879,7 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) | |||
872 | &flags) == 0) { | 879 | &flags) == 0) { |
873 | skb = transfer_context; | 880 | skb = transfer_context; |
874 | max_nbytes = skb->len + skb_tailroom(skb); | 881 | max_nbytes = skb->len + skb_tailroom(skb); |
875 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, | 882 | dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr, |
876 | max_nbytes, DMA_FROM_DEVICE); | 883 | max_nbytes, DMA_FROM_DEVICE); |
877 | 884 | ||
878 | if (unlikely(max_nbytes < nbytes)) { | 885 | if (unlikely(max_nbytes < nbytes)) { |
@@ -1238,7 +1245,7 @@ static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) | |||
1238 | 1245 | ||
1239 | ce_ring->per_transfer_context[i] = NULL; | 1246 | ce_ring->per_transfer_context[i] = NULL; |
1240 | 1247 | ||
1241 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, | 1248 | dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr, |
1242 | skb->len + skb_tailroom(skb), | 1249 | skb->len + skb_tailroom(skb), |
1243 | DMA_FROM_DEVICE); | 1250 | DMA_FROM_DEVICE); |
1244 | dev_kfree_skb_any(skb); | 1251 | dev_kfree_skb_any(skb); |
@@ -1506,6 +1513,35 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar) | |||
1506 | return 0; | 1513 | return 0; |
1507 | } | 1514 | } |
1508 | 1515 | ||
1516 | static int ath10k_pci_get_num_banks(struct ath10k *ar) | ||
1517 | { | ||
1518 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
1519 | |||
1520 | switch (ar_pci->pdev->device) { | ||
1521 | case QCA988X_2_0_DEVICE_ID: | ||
1522 | return 1; | ||
1523 | case QCA6174_2_1_DEVICE_ID: | ||
1524 | switch (MS(ar->chip_id, SOC_CHIP_ID_REV)) { | ||
1525 | case QCA6174_HW_1_0_CHIP_ID_REV: | ||
1526 | case QCA6174_HW_1_1_CHIP_ID_REV: | ||
1527 | return 3; | ||
1528 | case QCA6174_HW_1_3_CHIP_ID_REV: | ||
1529 | return 2; | ||
1530 | case QCA6174_HW_2_1_CHIP_ID_REV: | ||
1531 | case QCA6174_HW_2_2_CHIP_ID_REV: | ||
1532 | return 6; | ||
1533 | case QCA6174_HW_3_0_CHIP_ID_REV: | ||
1534 | case QCA6174_HW_3_1_CHIP_ID_REV: | ||
1535 | case QCA6174_HW_3_2_CHIP_ID_REV: | ||
1536 | return 9; | ||
1537 | } | ||
1538 | break; | ||
1539 | } | ||
1540 | |||
1541 | ath10k_warn(ar, "unknown number of banks, assuming 1\n"); | ||
1542 | return 1; | ||
1543 | } | ||
1544 | |||
1509 | static int ath10k_pci_init_config(struct ath10k *ar) | 1545 | static int ath10k_pci_init_config(struct ath10k *ar) |
1510 | { | 1546 | { |
1511 | u32 interconnect_targ_addr; | 1547 | u32 interconnect_targ_addr; |
@@ -1616,7 +1652,8 @@ static int ath10k_pci_init_config(struct ath10k *ar) | |||
1616 | /* first bank is switched to IRAM */ | 1652 | /* first bank is switched to IRAM */ |
1617 | ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & | 1653 | ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & |
1618 | HI_EARLY_ALLOC_MAGIC_MASK); | 1654 | HI_EARLY_ALLOC_MAGIC_MASK); |
1619 | ealloc_value |= ((1 << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & | 1655 | ealloc_value |= ((ath10k_pci_get_num_banks(ar) << |
1656 | HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & | ||
1620 | HI_EARLY_ALLOC_IRAM_BANKS_MASK); | 1657 | HI_EARLY_ALLOC_IRAM_BANKS_MASK); |
1621 | 1658 | ||
1622 | ret = ath10k_pci_diag_write32(ar, ealloc_targ_addr, ealloc_value); | 1659 | ret = ath10k_pci_diag_write32(ar, ealloc_targ_addr, ealloc_value); |
@@ -1812,12 +1849,12 @@ static int ath10k_pci_warm_reset(struct ath10k *ar) | |||
1812 | return 0; | 1849 | return 0; |
1813 | } | 1850 | } |
1814 | 1851 | ||
1815 | static int ath10k_pci_chip_reset(struct ath10k *ar) | 1852 | static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar) |
1816 | { | 1853 | { |
1817 | int i, ret; | 1854 | int i, ret; |
1818 | u32 val; | 1855 | u32 val; |
1819 | 1856 | ||
1820 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset\n"); | 1857 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot 988x chip reset\n"); |
1821 | 1858 | ||
1822 | /* Some hardware revisions (e.g. CUS223v2) has issues with cold reset. | 1859 | /* Some hardware revisions (e.g. CUS223v2) has issues with cold reset. |
1823 | * It is thus preferred to use warm reset which is safer but may not be | 1860 | * It is thus preferred to use warm reset which is safer but may not be |
@@ -1881,11 +1918,53 @@ static int ath10k_pci_chip_reset(struct ath10k *ar) | |||
1881 | return ret; | 1918 | return ret; |
1882 | } | 1919 | } |
1883 | 1920 | ||
1884 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (cold)\n"); | 1921 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca988x chip reset complete (cold)\n"); |
1885 | 1922 | ||
1886 | return 0; | 1923 | return 0; |
1887 | } | 1924 | } |
1888 | 1925 | ||
1926 | static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar) | ||
1927 | { | ||
1928 | int ret; | ||
1929 | |||
1930 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca6174 chip reset\n"); | ||
1931 | |||
1932 | /* FIXME: QCA6174 requires cold + warm reset to work. */ | ||
1933 | |||
1934 | ret = ath10k_pci_cold_reset(ar); | ||
1935 | if (ret) { | ||
1936 | ath10k_warn(ar, "failed to cold reset: %d\n", ret); | ||
1937 | return ret; | ||
1938 | } | ||
1939 | |||
1940 | ret = ath10k_pci_wait_for_target_init(ar); | ||
1941 | if (ret) { | ||
1942 | ath10k_warn(ar, "failed to wait for target after cold reset: %d\n", | ||
1943 | ret); | ||
1944 | return ret; | ||
1945 | } | ||
1946 | |||
1947 | ret = ath10k_pci_warm_reset(ar); | ||
1948 | if (ret) { | ||
1949 | ath10k_warn(ar, "failed to warm reset: %d\n", ret); | ||
1950 | return ret; | ||
1951 | } | ||
1952 | |||
1953 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca6174 chip reset complete (cold)\n"); | ||
1954 | |||
1955 | return 0; | ||
1956 | } | ||
1957 | |||
1958 | static int ath10k_pci_chip_reset(struct ath10k *ar) | ||
1959 | { | ||
1960 | if (QCA_REV_988X(ar)) | ||
1961 | return ath10k_pci_qca988x_chip_reset(ar); | ||
1962 | else if (QCA_REV_6174(ar)) | ||
1963 | return ath10k_pci_qca6174_chip_reset(ar); | ||
1964 | else | ||
1965 | return -ENOTSUPP; | ||
1966 | } | ||
1967 | |||
1889 | static int ath10k_pci_hif_power_up(struct ath10k *ar) | 1968 | static int ath10k_pci_hif_power_up(struct ath10k *ar) |
1890 | { | 1969 | { |
1891 | int ret; | 1970 | int ret; |
@@ -1910,6 +1989,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) | |||
1910 | */ | 1989 | */ |
1911 | ret = ath10k_pci_chip_reset(ar); | 1990 | ret = ath10k_pci_chip_reset(ar); |
1912 | if (ret) { | 1991 | if (ret) { |
1992 | if (ath10k_pci_has_fw_crashed(ar)) { | ||
1993 | ath10k_warn(ar, "firmware crashed during chip reset\n"); | ||
1994 | ath10k_pci_fw_crashed_clear(ar); | ||
1995 | ath10k_pci_fw_crashed_dump(ar); | ||
1996 | } | ||
1997 | |||
1913 | ath10k_err(ar, "failed to reset chip: %d\n", ret); | 1998 | ath10k_err(ar, "failed to reset chip: %d\n", ret); |
1914 | goto err_sleep; | 1999 | goto err_sleep; |
1915 | } | 2000 | } |
@@ -2041,6 +2126,7 @@ static void ath10k_msi_err_tasklet(unsigned long data) | |||
2041 | return; | 2126 | return; |
2042 | } | 2127 | } |
2043 | 2128 | ||
2129 | ath10k_pci_irq_disable(ar); | ||
2044 | ath10k_pci_fw_crashed_clear(ar); | 2130 | ath10k_pci_fw_crashed_clear(ar); |
2045 | ath10k_pci_fw_crashed_dump(ar); | 2131 | ath10k_pci_fw_crashed_dump(ar); |
2046 | } | 2132 | } |
@@ -2110,6 +2196,7 @@ static void ath10k_pci_tasklet(unsigned long data) | |||
2110 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 2196 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
2111 | 2197 | ||
2112 | if (ath10k_pci_has_fw_crashed(ar)) { | 2198 | if (ath10k_pci_has_fw_crashed(ar)) { |
2199 | ath10k_pci_irq_disable(ar); | ||
2113 | ath10k_pci_fw_crashed_clear(ar); | 2200 | ath10k_pci_fw_crashed_clear(ar); |
2114 | ath10k_pci_fw_crashed_dump(ar); | 2201 | ath10k_pci_fw_crashed_dump(ar); |
2115 | return; | 2202 | return; |
@@ -2352,8 +2439,6 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) | |||
2352 | 2439 | ||
2353 | if (val & FW_IND_EVENT_PENDING) { | 2440 | if (val & FW_IND_EVENT_PENDING) { |
2354 | ath10k_warn(ar, "device has crashed during init\n"); | 2441 | ath10k_warn(ar, "device has crashed during init\n"); |
2355 | ath10k_pci_fw_crashed_clear(ar); | ||
2356 | ath10k_pci_fw_crashed_dump(ar); | ||
2357 | return -ECOMM; | 2442 | return -ECOMM; |
2358 | } | 2443 | } |
2359 | 2444 | ||
@@ -2507,11 +2592,23 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2507 | int ret = 0; | 2592 | int ret = 0; |
2508 | struct ath10k *ar; | 2593 | struct ath10k *ar; |
2509 | struct ath10k_pci *ar_pci; | 2594 | struct ath10k_pci *ar_pci; |
2595 | enum ath10k_hw_rev hw_rev; | ||
2510 | u32 chip_id; | 2596 | u32 chip_id; |
2511 | 2597 | ||
2512 | ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, | 2598 | switch (pci_dev->device) { |
2513 | ATH10K_BUS_PCI, | 2599 | case QCA988X_2_0_DEVICE_ID: |
2514 | &ath10k_pci_hif_ops); | 2600 | hw_rev = ATH10K_HW_QCA988X; |
2601 | break; | ||
2602 | case QCA6174_2_1_DEVICE_ID: | ||
2603 | hw_rev = ATH10K_HW_QCA6174; | ||
2604 | break; | ||
2605 | default: | ||
2606 | WARN_ON(1); | ||
2607 | return -ENOTSUPP; | ||
2608 | } | ||
2609 | |||
2610 | ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, ATH10K_BUS_PCI, | ||
2611 | hw_rev, &ath10k_pci_hif_ops); | ||
2515 | if (!ar) { | 2612 | if (!ar) { |
2516 | dev_err(&pdev->dev, "failed to allocate core\n"); | 2613 | dev_err(&pdev->dev, "failed to allocate core\n"); |
2517 | return -ENOMEM; | 2614 | return -ENOMEM; |
@@ -2540,18 +2637,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2540 | goto err_release; | 2637 | goto err_release; |
2541 | } | 2638 | } |
2542 | 2639 | ||
2543 | chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); | ||
2544 | if (chip_id == 0xffffffff) { | ||
2545 | ath10k_err(ar, "failed to get chip id\n"); | ||
2546 | goto err_sleep; | ||
2547 | } | ||
2548 | |||
2549 | if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) { | ||
2550 | ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", | ||
2551 | pdev->device, chip_id); | ||
2552 | goto err_sleep; | ||
2553 | } | ||
2554 | |||
2555 | ret = ath10k_pci_alloc_pipes(ar); | 2640 | ret = ath10k_pci_alloc_pipes(ar); |
2556 | if (ret) { | 2641 | if (ret) { |
2557 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", | 2642 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", |
@@ -2578,6 +2663,24 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2578 | goto err_deinit_irq; | 2663 | goto err_deinit_irq; |
2579 | } | 2664 | } |
2580 | 2665 | ||
2666 | ret = ath10k_pci_chip_reset(ar); | ||
2667 | if (ret) { | ||
2668 | ath10k_err(ar, "failed to reset chip: %d\n", ret); | ||
2669 | goto err_free_irq; | ||
2670 | } | ||
2671 | |||
2672 | chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); | ||
2673 | if (chip_id == 0xffffffff) { | ||
2674 | ath10k_err(ar, "failed to get chip id\n"); | ||
2675 | goto err_free_irq; | ||
2676 | } | ||
2677 | |||
2678 | if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) { | ||
2679 | ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n", | ||
2680 | pdev->device, chip_id); | ||
2681 | goto err_sleep; | ||
2682 | } | ||
2683 | |||
2581 | ath10k_pci_sleep(ar); | 2684 | ath10k_pci_sleep(ar); |
2582 | 2685 | ||
2583 | ret = ath10k_core_register(ar, chip_id); | 2686 | ret = ath10k_core_register(ar, chip_id); |
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index ce4a1ef89961..bddf54320160 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h | |||
@@ -194,7 +194,7 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) | |||
194 | 194 | ||
195 | #define ATH10K_PCI_RX_POST_RETRY_MS 50 | 195 | #define ATH10K_PCI_RX_POST_RETRY_MS 50 |
196 | #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ | 196 | #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ |
197 | #define PCIE_WAKE_TIMEOUT 5000 /* 5ms */ | 197 | #define PCIE_WAKE_TIMEOUT 10000 /* 10ms */ |
198 | 198 | ||
199 | #define BAR_NUM 0 | 199 | #define BAR_NUM 0 |
200 | 200 | ||
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index e1ffdd57a18c..e9cc7787bf5f 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h | |||
@@ -850,7 +850,7 @@ struct rx_ppdu_start { | |||
850 | 850 | ||
851 | #define RX_PPDU_END_INFO1_PPDU_DONE (1 << 15) | 851 | #define RX_PPDU_END_INFO1_PPDU_DONE (1 << 15) |
852 | 852 | ||
853 | struct rx_ppdu_end { | 853 | struct rx_ppdu_end_common { |
854 | __le32 evm_p0; | 854 | __le32 evm_p0; |
855 | __le32 evm_p1; | 855 | __le32 evm_p1; |
856 | __le32 evm_p2; | 856 | __le32 evm_p2; |
@@ -873,10 +873,33 @@ struct rx_ppdu_end { | |||
873 | u8 phy_err_code; | 873 | u8 phy_err_code; |
874 | __le16 flags; /* %RX_PPDU_END_FLAGS_ */ | 874 | __le16 flags; /* %RX_PPDU_END_FLAGS_ */ |
875 | __le32 info0; /* %RX_PPDU_END_INFO0_ */ | 875 | __le32 info0; /* %RX_PPDU_END_INFO0_ */ |
876 | } __packed; | ||
877 | |||
878 | struct rx_ppdu_end_qca988x { | ||
876 | __le16 bb_length; | 879 | __le16 bb_length; |
877 | __le16 info1; /* %RX_PPDU_END_INFO1_ */ | 880 | __le16 info1; /* %RX_PPDU_END_INFO1_ */ |
878 | } __packed; | 881 | } __packed; |
879 | 882 | ||
883 | #define RX_PPDU_END_RTT_CORRELATION_VALUE_MASK 0x00ffffff | ||
884 | #define RX_PPDU_END_RTT_CORRELATION_VALUE_LSB 0 | ||
885 | #define RX_PPDU_END_RTT_UNUSED_MASK 0x7f000000 | ||
886 | #define RX_PPDU_END_RTT_UNUSED_LSB 24 | ||
887 | #define RX_PPDU_END_RTT_NORMAL_MODE BIT(31) | ||
888 | |||
889 | struct rx_ppdu_end_qca6174 { | ||
890 | __le32 rtt; /* %RX_PPDU_END_RTT_ */ | ||
891 | __le16 bb_length; | ||
892 | __le16 info1; /* %RX_PPDU_END_INFO1_ */ | ||
893 | } __packed; | ||
894 | |||
895 | struct rx_ppdu_end { | ||
896 | struct rx_ppdu_end_common common; | ||
897 | union { | ||
898 | struct rx_ppdu_end_qca988x qca988x; | ||
899 | struct rx_ppdu_end_qca6174 qca6174; | ||
900 | } __packed; | ||
901 | } __packed; | ||
902 | |||
880 | /* | 903 | /* |
881 | * evm_p0 | 904 | * evm_p0 |
882 | * EVM for pilot 0. Contain EVM for streams: 0, 1, 2 and 3. | 905 | * EVM for pilot 0. Contain EVM for streams: 0, 1, 2 and 3. |
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 9d0ae30f9ff1..a417aae52623 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #ifndef __TARGADDRS_H__ | 18 | #ifndef __TARGADDRS_H__ |
19 | #define __TARGADDRS_H__ | 19 | #define __TARGADDRS_H__ |
20 | 20 | ||
21 | #include "hw.h" | ||
22 | |||
21 | /* | 23 | /* |
22 | * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the | 24 | * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the |
23 | * host_interest structure. It must match the address of the _host_interest | 25 | * host_interest structure. It must match the address of the _host_interest |
@@ -445,4 +447,7 @@ Fw Mode/SubMode Mask | |||
445 | #define QCA988X_BOARD_DATA_SZ 7168 | 447 | #define QCA988X_BOARD_DATA_SZ 7168 |
446 | #define QCA988X_BOARD_EXT_DATA_SZ 0 | 448 | #define QCA988X_BOARD_EXT_DATA_SZ 0 |
447 | 449 | ||
450 | #define QCA6174_BOARD_DATA_SZ 8192 | ||
451 | #define QCA6174_BOARD_EXT_DATA_SZ 0 | ||
452 | |||
448 | #endif /* __TARGADDRS_H__ */ | 453 | #endif /* __TARGADDRS_H__ */ |
diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c index b14ae8d135f6..aede750809fe 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.c +++ b/drivers/net/wireless/ath/ath10k/thermal.c | |||
@@ -98,7 +98,7 @@ static int ath10k_thermal_set_cur_dutycycle(struct thermal_cooling_device *cdev, | |||
98 | } | 98 | } |
99 | period = max(ATH10K_QUIET_PERIOD_MIN, | 99 | period = max(ATH10K_QUIET_PERIOD_MIN, |
100 | (ATH10K_QUIET_PERIOD_DEFAULT / num_bss)); | 100 | (ATH10K_QUIET_PERIOD_DEFAULT / num_bss)); |
101 | duration = period * (duty_cycle / 100); | 101 | duration = (period * duty_cycle) / 100; |
102 | enabled = duration ? 1 : 0; | 102 | enabled = duration ? 1 : 0; |
103 | 103 | ||
104 | ret = ath10k_wmi_pdev_set_quiet_mode(ar, period, duration, | 104 | ret = ath10k_wmi_pdev_set_quiet_mode(ar, period, duration, |
@@ -160,7 +160,8 @@ static ssize_t ath10k_thermal_show_temp(struct device *dev, | |||
160 | temperature = ar->thermal.temperature; | 160 | temperature = ar->thermal.temperature; |
161 | spin_unlock_bh(&ar->data_lock); | 161 | spin_unlock_bh(&ar->data_lock); |
162 | 162 | ||
163 | ret = snprintf(buf, PAGE_SIZE, "%d", temperature); | 163 | /* display in millidegree celcius */ |
164 | ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000); | ||
164 | out: | 165 | out: |
165 | mutex_unlock(&ar->conf_mutex); | 166 | mutex_unlock(&ar->conf_mutex); |
166 | return ret; | 167 | return ret; |
@@ -215,7 +216,7 @@ int ath10k_thermal_register(struct ath10k *ar) | |||
215 | 216 | ||
216 | /* Avoid linking error on devm_hwmon_device_register_with_groups, I | 217 | /* Avoid linking error on devm_hwmon_device_register_with_groups, I |
217 | * guess linux/hwmon.h is missing proper stubs. */ | 218 | * guess linux/hwmon.h is missing proper stubs. */ |
218 | if (!config_enabled(HWMON)) | 219 | if (!config_enabled(CONFIG_HWMON)) |
219 | return 0; | 220 | return 0; |
220 | 221 | ||
221 | hwmon_dev = devm_hwmon_device_register_with_groups(ar->dev, | 222 | hwmon_dev = devm_hwmon_device_register_with_groups(ar->dev, |
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index b289378b6e3e..5407887380ab 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
@@ -453,6 +453,74 @@ TRACE_EVENT(ath10k_htt_rx_desc, | |||
453 | ) | 453 | ) |
454 | ); | 454 | ); |
455 | 455 | ||
456 | TRACE_EVENT(ath10k_wmi_diag_container, | ||
457 | TP_PROTO(struct ath10k *ar, | ||
458 | u8 type, | ||
459 | u32 timestamp, | ||
460 | u32 code, | ||
461 | u16 len, | ||
462 | const void *data), | ||
463 | |||
464 | TP_ARGS(ar, type, timestamp, code, len, data), | ||
465 | |||
466 | TP_STRUCT__entry( | ||
467 | __string(device, dev_name(ar->dev)) | ||
468 | __string(driver, dev_driver_string(ar->dev)) | ||
469 | __field(u8, type) | ||
470 | __field(u32, timestamp) | ||
471 | __field(u32, code) | ||
472 | __field(u16, len) | ||
473 | __dynamic_array(u8, data, len) | ||
474 | ), | ||
475 | |||
476 | TP_fast_assign( | ||
477 | __assign_str(device, dev_name(ar->dev)); | ||
478 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
479 | __entry->type = type; | ||
480 | __entry->timestamp = timestamp; | ||
481 | __entry->code = code; | ||
482 | __entry->len = len; | ||
483 | memcpy(__get_dynamic_array(data), data, len); | ||
484 | ), | ||
485 | |||
486 | TP_printk( | ||
487 | "%s %s diag container type %hhu timestamp %u code %u len %d", | ||
488 | __get_str(driver), | ||
489 | __get_str(device), | ||
490 | __entry->type, | ||
491 | __entry->timestamp, | ||
492 | __entry->code, | ||
493 | __entry->len | ||
494 | ) | ||
495 | ); | ||
496 | |||
497 | TRACE_EVENT(ath10k_wmi_diag, | ||
498 | TP_PROTO(struct ath10k *ar, const void *data, size_t len), | ||
499 | |||
500 | TP_ARGS(ar, data, len), | ||
501 | |||
502 | TP_STRUCT__entry( | ||
503 | __string(device, dev_name(ar->dev)) | ||
504 | __string(driver, dev_driver_string(ar->dev)) | ||
505 | __field(u16, len) | ||
506 | __dynamic_array(u8, data, len) | ||
507 | ), | ||
508 | |||
509 | TP_fast_assign( | ||
510 | __assign_str(device, dev_name(ar->dev)); | ||
511 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
512 | __entry->len = len; | ||
513 | memcpy(__get_dynamic_array(data), data, len); | ||
514 | ), | ||
515 | |||
516 | TP_printk( | ||
517 | "%s %s tlv diag len %d", | ||
518 | __get_str(driver), | ||
519 | __get_str(device), | ||
520 | __entry->len | ||
521 | ) | ||
522 | ); | ||
523 | |||
456 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ | 524 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ |
457 | 525 | ||
458 | /* we don't want to use include/trace/events */ | 526 | /* we don't want to use include/trace/events */ |
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 7579de8e7a8c..3f00cec8aef5 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
@@ -64,7 +64,13 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
64 | return; | 64 | return; |
65 | } | 65 | } |
66 | 66 | ||
67 | msdu = htt->pending_tx[tx_done->msdu_id]; | 67 | msdu = idr_find(&htt->pending_tx, tx_done->msdu_id); |
68 | if (!msdu) { | ||
69 | ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n", | ||
70 | tx_done->msdu_id); | ||
71 | return; | ||
72 | } | ||
73 | |||
68 | skb_cb = ATH10K_SKB_CB(msdu); | 74 | skb_cb = ATH10K_SKB_CB(msdu); |
69 | 75 | ||
70 | dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); | 76 | dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
@@ -95,7 +101,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
95 | /* we do not own the msdu anymore */ | 101 | /* we do not own the msdu anymore */ |
96 | 102 | ||
97 | exit: | 103 | exit: |
98 | htt->pending_tx[tx_done->msdu_id] = NULL; | ||
99 | ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); | 104 | ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); |
100 | __ath10k_htt_tx_dec_pending(htt); | 105 | __ath10k_htt_tx_dec_pending(htt); |
101 | if (htt->num_pending_tx == 0) | 106 | if (htt->num_pending_tx == 0) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 20e2c3002bb5..04dc4b9db04e 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h | |||
@@ -78,6 +78,8 @@ struct wmi_ops { | |||
78 | const struct wmi_vdev_spectral_conf_arg *arg); | 78 | const struct wmi_vdev_spectral_conf_arg *arg); |
79 | struct sk_buff *(*gen_vdev_spectral_enable)(struct ath10k *ar, u32 vdev_id, | 79 | struct sk_buff *(*gen_vdev_spectral_enable)(struct ath10k *ar, u32 vdev_id, |
80 | u32 trigger, u32 enable); | 80 | u32 trigger, u32 enable); |
81 | struct sk_buff *(*gen_vdev_wmm_conf)(struct ath10k *ar, u32 vdev_id, | ||
82 | const struct wmi_wmm_params_all_arg *arg); | ||
81 | struct sk_buff *(*gen_peer_create)(struct ath10k *ar, u32 vdev_id, | 83 | struct sk_buff *(*gen_peer_create)(struct ath10k *ar, u32 vdev_id, |
82 | const u8 peer_addr[ETH_ALEN]); | 84 | const u8 peer_addr[ETH_ALEN]); |
83 | struct sk_buff *(*gen_peer_delete)(struct ath10k *ar, u32 vdev_id, | 85 | struct sk_buff *(*gen_peer_delete)(struct ath10k *ar, u32 vdev_id, |
@@ -102,16 +104,20 @@ struct wmi_ops { | |||
102 | u32 value); | 104 | u32 value); |
103 | struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar, | 105 | struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar, |
104 | const struct wmi_scan_chan_list_arg *arg); | 106 | const struct wmi_scan_chan_list_arg *arg); |
105 | struct sk_buff *(*gen_beacon_dma)(struct ath10k_vif *arvif); | 107 | struct sk_buff *(*gen_beacon_dma)(struct ath10k *ar, u32 vdev_id, |
108 | const void *bcn, size_t bcn_len, | ||
109 | u32 bcn_paddr, bool dtim_zero, | ||
110 | bool deliver_cab); | ||
106 | struct sk_buff *(*gen_pdev_set_wmm)(struct ath10k *ar, | 111 | struct sk_buff *(*gen_pdev_set_wmm)(struct ath10k *ar, |
107 | const struct wmi_pdev_set_wmm_params_arg *arg); | 112 | const struct wmi_wmm_params_all_arg *arg); |
108 | struct sk_buff *(*gen_request_stats)(struct ath10k *ar, | 113 | struct sk_buff *(*gen_request_stats)(struct ath10k *ar, |
109 | enum wmi_stats_id stats_id); | 114 | enum wmi_stats_id stats_id); |
110 | struct sk_buff *(*gen_force_fw_hang)(struct ath10k *ar, | 115 | struct sk_buff *(*gen_force_fw_hang)(struct ath10k *ar, |
111 | enum wmi_force_fw_hang_type type, | 116 | enum wmi_force_fw_hang_type type, |
112 | u32 delay_ms); | 117 | u32 delay_ms); |
113 | struct sk_buff *(*gen_mgmt_tx)(struct ath10k *ar, struct sk_buff *skb); | 118 | struct sk_buff *(*gen_mgmt_tx)(struct ath10k *ar, struct sk_buff *skb); |
114 | struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u32 module_enable); | 119 | struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u32 module_enable, |
120 | u32 log_level); | ||
115 | struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter); | 121 | struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter); |
116 | struct sk_buff *(*gen_pktlog_disable)(struct ath10k *ar); | 122 | struct sk_buff *(*gen_pktlog_disable)(struct ath10k *ar); |
117 | struct sk_buff *(*gen_pdev_set_quiet_mode)(struct ath10k *ar, | 123 | struct sk_buff *(*gen_pdev_set_quiet_mode)(struct ath10k *ar, |
@@ -119,6 +125,30 @@ struct wmi_ops { | |||
119 | u32 next_offset, | 125 | u32 next_offset, |
120 | u32 enabled); | 126 | u32 enabled); |
121 | struct sk_buff *(*gen_pdev_get_temperature)(struct ath10k *ar); | 127 | struct sk_buff *(*gen_pdev_get_temperature)(struct ath10k *ar); |
128 | struct sk_buff *(*gen_addba_clear_resp)(struct ath10k *ar, u32 vdev_id, | ||
129 | const u8 *mac); | ||
130 | struct sk_buff *(*gen_addba_send)(struct ath10k *ar, u32 vdev_id, | ||
131 | const u8 *mac, u32 tid, u32 buf_size); | ||
132 | struct sk_buff *(*gen_addba_set_resp)(struct ath10k *ar, u32 vdev_id, | ||
133 | const u8 *mac, u32 tid, | ||
134 | u32 status); | ||
135 | struct sk_buff *(*gen_delba_send)(struct ath10k *ar, u32 vdev_id, | ||
136 | const u8 *mac, u32 tid, u32 initiator, | ||
137 | u32 reason); | ||
138 | struct sk_buff *(*gen_bcn_tmpl)(struct ath10k *ar, u32 vdev_id, | ||
139 | u32 tim_ie_offset, struct sk_buff *bcn, | ||
140 | u32 prb_caps, u32 prb_erp, | ||
141 | void *prb_ies, size_t prb_ies_len); | ||
142 | struct sk_buff *(*gen_prb_tmpl)(struct ath10k *ar, u32 vdev_id, | ||
143 | struct sk_buff *bcn); | ||
144 | struct sk_buff *(*gen_p2p_go_bcn_ie)(struct ath10k *ar, u32 vdev_id, | ||
145 | const u8 *p2p_ie); | ||
146 | struct sk_buff *(*gen_vdev_sta_uapsd)(struct ath10k *ar, u32 vdev_id, | ||
147 | const u8 peer_addr[ETH_ALEN], | ||
148 | const struct wmi_sta_uapsd_auto_trig_arg *args, | ||
149 | u32 num_ac); | ||
150 | struct sk_buff *(*gen_sta_keepalive)(struct ath10k *ar, | ||
151 | const struct wmi_sta_keepalive_arg *arg); | ||
122 | }; | 152 | }; |
123 | 153 | ||
124 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); | 154 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); |
@@ -558,6 +588,42 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger, | |||
558 | } | 588 | } |
559 | 589 | ||
560 | static inline int | 590 | static inline int |
591 | ath10k_wmi_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id, | ||
592 | const u8 peer_addr[ETH_ALEN], | ||
593 | const struct wmi_sta_uapsd_auto_trig_arg *args, | ||
594 | u32 num_ac) | ||
595 | { | ||
596 | struct sk_buff *skb; | ||
597 | u32 cmd_id; | ||
598 | |||
599 | if (!ar->wmi.ops->gen_vdev_sta_uapsd) | ||
600 | return -EOPNOTSUPP; | ||
601 | |||
602 | skb = ar->wmi.ops->gen_vdev_sta_uapsd(ar, vdev_id, peer_addr, args, | ||
603 | num_ac); | ||
604 | if (IS_ERR(skb)) | ||
605 | return PTR_ERR(skb); | ||
606 | |||
607 | cmd_id = ar->wmi.cmd->sta_uapsd_auto_trig_cmdid; | ||
608 | return ath10k_wmi_cmd_send(ar, skb, cmd_id); | ||
609 | } | ||
610 | |||
611 | static inline int | ||
612 | ath10k_wmi_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id, | ||
613 | const struct wmi_wmm_params_all_arg *arg) | ||
614 | { | ||
615 | struct sk_buff *skb; | ||
616 | u32 cmd_id; | ||
617 | |||
618 | skb = ar->wmi.ops->gen_vdev_wmm_conf(ar, vdev_id, arg); | ||
619 | if (IS_ERR(skb)) | ||
620 | return PTR_ERR(skb); | ||
621 | |||
622 | cmd_id = ar->wmi.cmd->vdev_set_wmm_params_cmdid; | ||
623 | return ath10k_wmi_cmd_send(ar, skb, cmd_id); | ||
624 | } | ||
625 | |||
626 | static inline int | ||
561 | ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, | 627 | ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, |
562 | const u8 peer_addr[ETH_ALEN]) | 628 | const u8 peer_addr[ETH_ALEN]) |
563 | { | 629 | { |
@@ -706,16 +772,19 @@ ath10k_wmi_peer_assoc(struct ath10k *ar, | |||
706 | } | 772 | } |
707 | 773 | ||
708 | static inline int | 774 | static inline int |
709 | ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif) | 775 | ath10k_wmi_beacon_send_ref_nowait(struct ath10k *ar, u32 vdev_id, |
776 | const void *bcn, size_t bcn_len, | ||
777 | u32 bcn_paddr, bool dtim_zero, | ||
778 | bool deliver_cab) | ||
710 | { | 779 | { |
711 | struct ath10k *ar = arvif->ar; | ||
712 | struct sk_buff *skb; | 780 | struct sk_buff *skb; |
713 | int ret; | 781 | int ret; |
714 | 782 | ||
715 | if (!ar->wmi.ops->gen_beacon_dma) | 783 | if (!ar->wmi.ops->gen_beacon_dma) |
716 | return -EOPNOTSUPP; | 784 | return -EOPNOTSUPP; |
717 | 785 | ||
718 | skb = ar->wmi.ops->gen_beacon_dma(arvif); | 786 | skb = ar->wmi.ops->gen_beacon_dma(ar, vdev_id, bcn, bcn_len, bcn_paddr, |
787 | dtim_zero, deliver_cab); | ||
719 | if (IS_ERR(skb)) | 788 | if (IS_ERR(skb)) |
720 | return PTR_ERR(skb); | 789 | return PTR_ERR(skb); |
721 | 790 | ||
@@ -731,7 +800,7 @@ ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif) | |||
731 | 800 | ||
732 | static inline int | 801 | static inline int |
733 | ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, | 802 | ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, |
734 | const struct wmi_pdev_set_wmm_params_arg *arg) | 803 | const struct wmi_wmm_params_all_arg *arg) |
735 | { | 804 | { |
736 | struct sk_buff *skb; | 805 | struct sk_buff *skb; |
737 | 806 | ||
@@ -778,14 +847,14 @@ ath10k_wmi_force_fw_hang(struct ath10k *ar, | |||
778 | } | 847 | } |
779 | 848 | ||
780 | static inline int | 849 | static inline int |
781 | ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable) | 850 | ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable, u32 log_level) |
782 | { | 851 | { |
783 | struct sk_buff *skb; | 852 | struct sk_buff *skb; |
784 | 853 | ||
785 | if (!ar->wmi.ops->gen_dbglog_cfg) | 854 | if (!ar->wmi.ops->gen_dbglog_cfg) |
786 | return -EOPNOTSUPP; | 855 | return -EOPNOTSUPP; |
787 | 856 | ||
788 | skb = ar->wmi.ops->gen_dbglog_cfg(ar, module_enable); | 857 | skb = ar->wmi.ops->gen_dbglog_cfg(ar, module_enable, log_level); |
789 | if (IS_ERR(skb)) | 858 | if (IS_ERR(skb)) |
790 | return PTR_ERR(skb); | 859 | return PTR_ERR(skb); |
791 | 860 | ||
@@ -857,4 +926,139 @@ ath10k_wmi_pdev_get_temperature(struct ath10k *ar) | |||
857 | ar->wmi.cmd->pdev_get_temperature_cmdid); | 926 | ar->wmi.cmd->pdev_get_temperature_cmdid); |
858 | } | 927 | } |
859 | 928 | ||
929 | static inline int | ||
930 | ath10k_wmi_addba_clear_resp(struct ath10k *ar, u32 vdev_id, const u8 *mac) | ||
931 | { | ||
932 | struct sk_buff *skb; | ||
933 | |||
934 | if (!ar->wmi.ops->gen_addba_clear_resp) | ||
935 | return -EOPNOTSUPP; | ||
936 | |||
937 | skb = ar->wmi.ops->gen_addba_clear_resp(ar, vdev_id, mac); | ||
938 | if (IS_ERR(skb)) | ||
939 | return PTR_ERR(skb); | ||
940 | |||
941 | return ath10k_wmi_cmd_send(ar, skb, | ||
942 | ar->wmi.cmd->addba_clear_resp_cmdid); | ||
943 | } | ||
944 | |||
945 | static inline int | ||
946 | ath10k_wmi_addba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac, | ||
947 | u32 tid, u32 buf_size) | ||
948 | { | ||
949 | struct sk_buff *skb; | ||
950 | |||
951 | if (!ar->wmi.ops->gen_addba_send) | ||
952 | return -EOPNOTSUPP; | ||
953 | |||
954 | skb = ar->wmi.ops->gen_addba_send(ar, vdev_id, mac, tid, buf_size); | ||
955 | if (IS_ERR(skb)) | ||
956 | return PTR_ERR(skb); | ||
957 | |||
958 | return ath10k_wmi_cmd_send(ar, skb, | ||
959 | ar->wmi.cmd->addba_send_cmdid); | ||
960 | } | ||
961 | |||
962 | static inline int | ||
963 | ath10k_wmi_addba_set_resp(struct ath10k *ar, u32 vdev_id, const u8 *mac, | ||
964 | u32 tid, u32 status) | ||
965 | { | ||
966 | struct sk_buff *skb; | ||
967 | |||
968 | if (!ar->wmi.ops->gen_addba_set_resp) | ||
969 | return -EOPNOTSUPP; | ||
970 | |||
971 | skb = ar->wmi.ops->gen_addba_set_resp(ar, vdev_id, mac, tid, status); | ||
972 | if (IS_ERR(skb)) | ||
973 | return PTR_ERR(skb); | ||
974 | |||
975 | return ath10k_wmi_cmd_send(ar, skb, | ||
976 | ar->wmi.cmd->addba_set_resp_cmdid); | ||
977 | } | ||
978 | |||
979 | static inline int | ||
980 | ath10k_wmi_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac, | ||
981 | u32 tid, u32 initiator, u32 reason) | ||
982 | { | ||
983 | struct sk_buff *skb; | ||
984 | |||
985 | if (!ar->wmi.ops->gen_delba_send) | ||
986 | return -EOPNOTSUPP; | ||
987 | |||
988 | skb = ar->wmi.ops->gen_delba_send(ar, vdev_id, mac, tid, initiator, | ||
989 | reason); | ||
990 | if (IS_ERR(skb)) | ||
991 | return PTR_ERR(skb); | ||
992 | |||
993 | return ath10k_wmi_cmd_send(ar, skb, | ||
994 | ar->wmi.cmd->delba_send_cmdid); | ||
995 | } | ||
996 | |||
997 | static inline int | ||
998 | ath10k_wmi_bcn_tmpl(struct ath10k *ar, u32 vdev_id, u32 tim_ie_offset, | ||
999 | struct sk_buff *bcn, u32 prb_caps, u32 prb_erp, | ||
1000 | void *prb_ies, size_t prb_ies_len) | ||
1001 | { | ||
1002 | struct sk_buff *skb; | ||
1003 | |||
1004 | if (!ar->wmi.ops->gen_bcn_tmpl) | ||
1005 | return -EOPNOTSUPP; | ||
1006 | |||
1007 | skb = ar->wmi.ops->gen_bcn_tmpl(ar, vdev_id, tim_ie_offset, bcn, | ||
1008 | prb_caps, prb_erp, prb_ies, | ||
1009 | prb_ies_len); | ||
1010 | if (IS_ERR(skb)) | ||
1011 | return PTR_ERR(skb); | ||
1012 | |||
1013 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->bcn_tmpl_cmdid); | ||
1014 | } | ||
1015 | |||
1016 | static inline int | ||
1017 | ath10k_wmi_prb_tmpl(struct ath10k *ar, u32 vdev_id, struct sk_buff *prb) | ||
1018 | { | ||
1019 | struct sk_buff *skb; | ||
1020 | |||
1021 | if (!ar->wmi.ops->gen_prb_tmpl) | ||
1022 | return -EOPNOTSUPP; | ||
1023 | |||
1024 | skb = ar->wmi.ops->gen_prb_tmpl(ar, vdev_id, prb); | ||
1025 | if (IS_ERR(skb)) | ||
1026 | return PTR_ERR(skb); | ||
1027 | |||
1028 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->prb_tmpl_cmdid); | ||
1029 | } | ||
1030 | |||
1031 | static inline int | ||
1032 | ath10k_wmi_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id, const u8 *p2p_ie) | ||
1033 | { | ||
1034 | struct sk_buff *skb; | ||
1035 | |||
1036 | if (!ar->wmi.ops->gen_p2p_go_bcn_ie) | ||
1037 | return -EOPNOTSUPP; | ||
1038 | |||
1039 | skb = ar->wmi.ops->gen_p2p_go_bcn_ie(ar, vdev_id, p2p_ie); | ||
1040 | if (IS_ERR(skb)) | ||
1041 | return PTR_ERR(skb); | ||
1042 | |||
1043 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->p2p_go_set_beacon_ie); | ||
1044 | } | ||
1045 | |||
1046 | static inline int | ||
1047 | ath10k_wmi_sta_keepalive(struct ath10k *ar, | ||
1048 | const struct wmi_sta_keepalive_arg *arg) | ||
1049 | { | ||
1050 | struct sk_buff *skb; | ||
1051 | u32 cmd_id; | ||
1052 | |||
1053 | if (!ar->wmi.ops->gen_sta_keepalive) | ||
1054 | return -EOPNOTSUPP; | ||
1055 | |||
1056 | skb = ar->wmi.ops->gen_sta_keepalive(ar, arg); | ||
1057 | if (IS_ERR(skb)) | ||
1058 | return PTR_ERR(skb); | ||
1059 | |||
1060 | cmd_id = ar->wmi.cmd->sta_keepalive_cmd; | ||
1061 | return ath10k_wmi_cmd_send(ar, skb, cmd_id); | ||
1062 | } | ||
1063 | |||
860 | #endif | 1064 | #endif |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 4c050cec3966..71614ba1b145 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c | |||
@@ -58,6 +58,10 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = { | |||
58 | = { .min_len = sizeof(struct wlan_host_mem_req) }, | 58 | = { .min_len = sizeof(struct wlan_host_mem_req) }, |
59 | [WMI_TLV_TAG_STRUCT_READY_EVENT] | 59 | [WMI_TLV_TAG_STRUCT_READY_EVENT] |
60 | = { .min_len = sizeof(struct wmi_tlv_rdy_ev) }, | 60 | = { .min_len = sizeof(struct wmi_tlv_rdy_ev) }, |
61 | [WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT] | ||
62 | = { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) }, | ||
63 | [WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT] | ||
64 | = { .min_len = sizeof(struct wmi_tlv_diag_data_ev) }, | ||
61 | }; | 65 | }; |
62 | 66 | ||
63 | static int | 67 | static int |
@@ -156,6 +160,142 @@ static u16 ath10k_wmi_tlv_len(const void *ptr) | |||
156 | return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len); | 160 | return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len); |
157 | } | 161 | } |
158 | 162 | ||
163 | /**************/ | ||
164 | /* TLV events */ | ||
165 | /**************/ | ||
166 | static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar, | ||
167 | struct sk_buff *skb) | ||
168 | { | ||
169 | const void **tb; | ||
170 | const struct wmi_tlv_bcn_tx_status_ev *ev; | ||
171 | u32 vdev_id, tx_status; | ||
172 | int ret; | ||
173 | |||
174 | tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); | ||
175 | if (IS_ERR(tb)) { | ||
176 | ret = PTR_ERR(tb); | ||
177 | ath10k_warn(ar, "failed to parse tlv: %d\n", ret); | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]; | ||
182 | if (!ev) { | ||
183 | kfree(tb); | ||
184 | return -EPROTO; | ||
185 | } | ||
186 | |||
187 | tx_status = __le32_to_cpu(ev->tx_status); | ||
188 | vdev_id = __le32_to_cpu(ev->vdev_id); | ||
189 | |||
190 | switch (tx_status) { | ||
191 | case WMI_TLV_BCN_TX_STATUS_OK: | ||
192 | break; | ||
193 | case WMI_TLV_BCN_TX_STATUS_XRETRY: | ||
194 | case WMI_TLV_BCN_TX_STATUS_DROP: | ||
195 | case WMI_TLV_BCN_TX_STATUS_FILTERED: | ||
196 | /* FIXME: It's probably worth telling mac80211 to stop the | ||
197 | * interface as it is crippled. | ||
198 | */ | ||
199 | ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d", | ||
200 | vdev_id, tx_status); | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | kfree(tb); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar, | ||
209 | struct sk_buff *skb) | ||
210 | { | ||
211 | const void **tb; | ||
212 | const struct wmi_tlv_diag_data_ev *ev; | ||
213 | const struct wmi_tlv_diag_item *item; | ||
214 | const void *data; | ||
215 | int ret, num_items, len; | ||
216 | |||
217 | tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); | ||
218 | if (IS_ERR(tb)) { | ||
219 | ret = PTR_ERR(tb); | ||
220 | ath10k_warn(ar, "failed to parse tlv: %d\n", ret); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]; | ||
225 | data = tb[WMI_TLV_TAG_ARRAY_BYTE]; | ||
226 | if (!ev || !data) { | ||
227 | kfree(tb); | ||
228 | return -EPROTO; | ||
229 | } | ||
230 | |||
231 | num_items = __le32_to_cpu(ev->num_items); | ||
232 | len = ath10k_wmi_tlv_len(data); | ||
233 | |||
234 | while (num_items--) { | ||
235 | if (len == 0) | ||
236 | break; | ||
237 | if (len < sizeof(*item)) { | ||
238 | ath10k_warn(ar, "failed to parse diag data: can't fit item header\n"); | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | item = data; | ||
243 | |||
244 | if (len < sizeof(*item) + __le16_to_cpu(item->len)) { | ||
245 | ath10k_warn(ar, "failed to parse diag data: item is too long\n"); | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | trace_ath10k_wmi_diag_container(ar, | ||
250 | item->type, | ||
251 | __le32_to_cpu(item->timestamp), | ||
252 | __le32_to_cpu(item->code), | ||
253 | __le16_to_cpu(item->len), | ||
254 | item->payload); | ||
255 | |||
256 | len -= sizeof(*item); | ||
257 | len -= roundup(__le16_to_cpu(item->len), 4); | ||
258 | |||
259 | data += sizeof(*item); | ||
260 | data += roundup(__le16_to_cpu(item->len), 4); | ||
261 | } | ||
262 | |||
263 | if (num_items != -1 || len != 0) | ||
264 | ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n", | ||
265 | num_items, len); | ||
266 | |||
267 | kfree(tb); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int ath10k_wmi_tlv_event_diag(struct ath10k *ar, | ||
272 | struct sk_buff *skb) | ||
273 | { | ||
274 | const void **tb; | ||
275 | const void *data; | ||
276 | int ret, len; | ||
277 | |||
278 | tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); | ||
279 | if (IS_ERR(tb)) { | ||
280 | ret = PTR_ERR(tb); | ||
281 | ath10k_warn(ar, "failed to parse tlv: %d\n", ret); | ||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | data = tb[WMI_TLV_TAG_ARRAY_BYTE]; | ||
286 | if (!data) { | ||
287 | kfree(tb); | ||
288 | return -EPROTO; | ||
289 | } | ||
290 | len = ath10k_wmi_tlv_len(data); | ||
291 | |||
292 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len); | ||
293 | trace_ath10k_wmi_diag(ar, data, len); | ||
294 | |||
295 | kfree(tb); | ||
296 | return 0; | ||
297 | } | ||
298 | |||
159 | /***********/ | 299 | /***********/ |
160 | /* TLV ops */ | 300 | /* TLV ops */ |
161 | /***********/ | 301 | /***********/ |
@@ -268,6 +408,15 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
268 | case WMI_TLV_READY_EVENTID: | 408 | case WMI_TLV_READY_EVENTID: |
269 | ath10k_wmi_event_ready(ar, skb); | 409 | ath10k_wmi_event_ready(ar, skb); |
270 | break; | 410 | break; |
411 | case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID: | ||
412 | ath10k_wmi_tlv_event_bcn_tx_status(ar, skb); | ||
413 | break; | ||
414 | case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID: | ||
415 | ath10k_wmi_tlv_event_diag_data(ar, skb); | ||
416 | break; | ||
417 | case WMI_TLV_DIAG_EVENTID: | ||
418 | ath10k_wmi_tlv_event_diag(ar, skb); | ||
419 | break; | ||
271 | default: | 420 | default: |
272 | ath10k_warn(ar, "Unknown eventid: %d\n", id); | 421 | ath10k_warn(ar, "Unknown eventid: %d\n", id); |
273 | break; | 422 | break; |
@@ -903,8 +1052,15 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) | |||
903 | 1052 | ||
904 | cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); | 1053 | cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); |
905 | cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS); | 1054 | cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS); |
906 | cfg->num_offload_peers = __cpu_to_le32(0); | 1055 | |
907 | cfg->num_offload_reorder_bufs = __cpu_to_le32(0); | 1056 | if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) { |
1057 | cfg->num_offload_peers = __cpu_to_le32(3); | ||
1058 | cfg->num_offload_reorder_bufs = __cpu_to_le32(3); | ||
1059 | } else { | ||
1060 | cfg->num_offload_peers = __cpu_to_le32(0); | ||
1061 | cfg->num_offload_reorder_bufs = __cpu_to_le32(0); | ||
1062 | } | ||
1063 | |||
908 | cfg->num_peer_keys = __cpu_to_le32(2); | 1064 | cfg->num_peer_keys = __cpu_to_le32(2); |
909 | cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS); | 1065 | cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS); |
910 | cfg->ast_skid_limit = __cpu_to_le32(0x10); | 1066 | cfg->ast_skid_limit = __cpu_to_le32(0x10); |
@@ -1356,6 +1512,173 @@ ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar, | |||
1356 | return skb; | 1512 | return skb; |
1357 | } | 1513 | } |
1358 | 1514 | ||
1515 | static void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr, | ||
1516 | const struct wmi_sta_uapsd_auto_trig_arg *arg) | ||
1517 | { | ||
1518 | struct wmi_sta_uapsd_auto_trig_param *ac; | ||
1519 | struct wmi_tlv *tlv; | ||
1520 | |||
1521 | tlv = ptr; | ||
1522 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM); | ||
1523 | tlv->len = __cpu_to_le16(sizeof(*ac)); | ||
1524 | ac = (void *)tlv->value; | ||
1525 | |||
1526 | ac->wmm_ac = __cpu_to_le32(arg->wmm_ac); | ||
1527 | ac->user_priority = __cpu_to_le32(arg->user_priority); | ||
1528 | ac->service_interval = __cpu_to_le32(arg->service_interval); | ||
1529 | ac->suspend_interval = __cpu_to_le32(arg->suspend_interval); | ||
1530 | ac->delay_interval = __cpu_to_le32(arg->delay_interval); | ||
1531 | |||
1532 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
1533 | "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n", | ||
1534 | ac->wmm_ac, ac->user_priority, ac->service_interval, | ||
1535 | ac->suspend_interval, ac->delay_interval); | ||
1536 | |||
1537 | return ptr + sizeof(*tlv) + sizeof(*ac); | ||
1538 | } | ||
1539 | |||
1540 | static struct sk_buff * | ||
1541 | ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id, | ||
1542 | const u8 peer_addr[ETH_ALEN], | ||
1543 | const struct wmi_sta_uapsd_auto_trig_arg *args, | ||
1544 | u32 num_ac) | ||
1545 | { | ||
1546 | struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd; | ||
1547 | struct wmi_sta_uapsd_auto_trig_param *ac; | ||
1548 | struct wmi_tlv *tlv; | ||
1549 | struct sk_buff *skb; | ||
1550 | size_t len; | ||
1551 | size_t ac_tlv_len; | ||
1552 | void *ptr; | ||
1553 | int i; | ||
1554 | |||
1555 | ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac)); | ||
1556 | len = sizeof(*tlv) + sizeof(*cmd) + | ||
1557 | sizeof(*tlv) + ac_tlv_len; | ||
1558 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
1559 | if (!skb) | ||
1560 | return ERR_PTR(-ENOMEM); | ||
1561 | |||
1562 | ptr = (void *)skb->data; | ||
1563 | tlv = ptr; | ||
1564 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD); | ||
1565 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
1566 | cmd = (void *)tlv->value; | ||
1567 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
1568 | cmd->num_ac = __cpu_to_le32(num_ac); | ||
1569 | ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); | ||
1570 | |||
1571 | ptr += sizeof(*tlv); | ||
1572 | ptr += sizeof(*cmd); | ||
1573 | |||
1574 | tlv = ptr; | ||
1575 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT); | ||
1576 | tlv->len = __cpu_to_le16(ac_tlv_len); | ||
1577 | ac = (void *)tlv->value; | ||
1578 | |||
1579 | ptr += sizeof(*tlv); | ||
1580 | for (i = 0; i < num_ac; i++) | ||
1581 | ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]); | ||
1582 | |||
1583 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n"); | ||
1584 | return skb; | ||
1585 | } | ||
1586 | |||
1587 | static void *ath10k_wmi_tlv_put_wmm(void *ptr, | ||
1588 | const struct wmi_wmm_params_arg *arg) | ||
1589 | { | ||
1590 | struct wmi_wmm_params *wmm; | ||
1591 | struct wmi_tlv *tlv; | ||
1592 | |||
1593 | tlv = ptr; | ||
1594 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS); | ||
1595 | tlv->len = __cpu_to_le16(sizeof(*wmm)); | ||
1596 | wmm = (void *)tlv->value; | ||
1597 | ath10k_wmi_set_wmm_param(wmm, arg); | ||
1598 | |||
1599 | return ptr + sizeof(*tlv) + sizeof(*wmm); | ||
1600 | } | ||
1601 | |||
1602 | static struct sk_buff * | ||
1603 | ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id, | ||
1604 | const struct wmi_wmm_params_all_arg *arg) | ||
1605 | { | ||
1606 | struct wmi_tlv_vdev_set_wmm_cmd *cmd; | ||
1607 | struct wmi_wmm_params *wmm; | ||
1608 | struct wmi_tlv *tlv; | ||
1609 | struct sk_buff *skb; | ||
1610 | size_t len; | ||
1611 | void *ptr; | ||
1612 | |||
1613 | len = (sizeof(*tlv) + sizeof(*cmd)) + | ||
1614 | (4 * (sizeof(*tlv) + sizeof(*wmm))); | ||
1615 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
1616 | if (!skb) | ||
1617 | return ERR_PTR(-ENOMEM); | ||
1618 | |||
1619 | ptr = (void *)skb->data; | ||
1620 | tlv = ptr; | ||
1621 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD); | ||
1622 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
1623 | cmd = (void *)tlv->value; | ||
1624 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
1625 | |||
1626 | ptr += sizeof(*tlv); | ||
1627 | ptr += sizeof(*cmd); | ||
1628 | |||
1629 | ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be); | ||
1630 | ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk); | ||
1631 | ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi); | ||
1632 | ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo); | ||
1633 | |||
1634 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n"); | ||
1635 | return skb; | ||
1636 | } | ||
1637 | |||
1638 | static struct sk_buff * | ||
1639 | ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar, | ||
1640 | const struct wmi_sta_keepalive_arg *arg) | ||
1641 | { | ||
1642 | struct wmi_tlv_sta_keepalive_cmd *cmd; | ||
1643 | struct wmi_sta_keepalive_arp_resp *arp; | ||
1644 | struct sk_buff *skb; | ||
1645 | struct wmi_tlv *tlv; | ||
1646 | void *ptr; | ||
1647 | size_t len; | ||
1648 | |||
1649 | len = sizeof(*tlv) + sizeof(*cmd) + | ||
1650 | sizeof(*tlv) + sizeof(*arp); | ||
1651 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
1652 | if (!skb) | ||
1653 | return ERR_PTR(-ENOMEM); | ||
1654 | |||
1655 | ptr = (void *)skb->data; | ||
1656 | tlv = ptr; | ||
1657 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD); | ||
1658 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
1659 | cmd = (void *)tlv->value; | ||
1660 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); | ||
1661 | cmd->enabled = __cpu_to_le32(arg->enabled); | ||
1662 | cmd->method = __cpu_to_le32(arg->method); | ||
1663 | cmd->interval = __cpu_to_le32(arg->interval); | ||
1664 | |||
1665 | ptr += sizeof(*tlv); | ||
1666 | ptr += sizeof(*cmd); | ||
1667 | |||
1668 | tlv = ptr; | ||
1669 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE); | ||
1670 | tlv->len = __cpu_to_le16(sizeof(*arp)); | ||
1671 | arp = (void *)tlv->value; | ||
1672 | |||
1673 | arp->src_ip4_addr = arg->src_ip4_addr; | ||
1674 | arp->dest_ip4_addr = arg->dest_ip4_addr; | ||
1675 | ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr); | ||
1676 | |||
1677 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d inverval %d\n", | ||
1678 | arg->vdev_id, arg->enabled, arg->method, arg->interval); | ||
1679 | return skb; | ||
1680 | } | ||
1681 | |||
1359 | static struct sk_buff * | 1682 | static struct sk_buff * |
1360 | ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id, | 1683 | ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id, |
1361 | const u8 peer_addr[ETH_ALEN]) | 1684 | const u8 peer_addr[ETH_ALEN]) |
@@ -1678,13 +2001,15 @@ ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar, | |||
1678 | } | 2001 | } |
1679 | 2002 | ||
1680 | static struct sk_buff * | 2003 | static struct sk_buff * |
1681 | ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k_vif *arvif) | 2004 | ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, |
2005 | const void *bcn, size_t bcn_len, | ||
2006 | u32 bcn_paddr, bool dtim_zero, | ||
2007 | bool deliver_cab) | ||
2008 | |||
1682 | { | 2009 | { |
1683 | struct ath10k *ar = arvif->ar; | ||
1684 | struct wmi_bcn_tx_ref_cmd *cmd; | 2010 | struct wmi_bcn_tx_ref_cmd *cmd; |
1685 | struct wmi_tlv *tlv; | 2011 | struct wmi_tlv *tlv; |
1686 | struct sk_buff *skb; | 2012 | struct sk_buff *skb; |
1687 | struct sk_buff *beacon = arvif->beacon; | ||
1688 | struct ieee80211_hdr *hdr; | 2013 | struct ieee80211_hdr *hdr; |
1689 | u16 fc; | 2014 | u16 fc; |
1690 | 2015 | ||
@@ -1692,48 +2017,33 @@ ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k_vif *arvif) | |||
1692 | if (!skb) | 2017 | if (!skb) |
1693 | return ERR_PTR(-ENOMEM); | 2018 | return ERR_PTR(-ENOMEM); |
1694 | 2019 | ||
1695 | hdr = (struct ieee80211_hdr *)beacon->data; | 2020 | hdr = (struct ieee80211_hdr *)bcn; |
1696 | fc = le16_to_cpu(hdr->frame_control); | 2021 | fc = le16_to_cpu(hdr->frame_control); |
1697 | 2022 | ||
1698 | tlv = (void *)skb->data; | 2023 | tlv = (void *)skb->data; |
1699 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD); | 2024 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD); |
1700 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | 2025 | tlv->len = __cpu_to_le16(sizeof(*cmd)); |
1701 | cmd = (void *)tlv->value; | 2026 | cmd = (void *)tlv->value; |
1702 | cmd->vdev_id = __cpu_to_le32(arvif->vdev_id); | 2027 | cmd->vdev_id = __cpu_to_le32(vdev_id); |
1703 | cmd->data_len = __cpu_to_le32(beacon->len); | 2028 | cmd->data_len = __cpu_to_le32(bcn_len); |
1704 | cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr); | 2029 | cmd->data_ptr = __cpu_to_le32(bcn_paddr); |
1705 | cmd->msdu_id = 0; | 2030 | cmd->msdu_id = 0; |
1706 | cmd->frame_control = __cpu_to_le32(fc); | 2031 | cmd->frame_control = __cpu_to_le32(fc); |
1707 | cmd->flags = 0; | 2032 | cmd->flags = 0; |
1708 | 2033 | ||
1709 | if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero) | 2034 | if (dtim_zero) |
1710 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO); | 2035 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO); |
1711 | 2036 | ||
1712 | if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab) | 2037 | if (deliver_cab) |
1713 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB); | 2038 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB); |
1714 | 2039 | ||
1715 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n"); | 2040 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n"); |
1716 | return skb; | 2041 | return skb; |
1717 | } | 2042 | } |
1718 | 2043 | ||
1719 | static void *ath10k_wmi_tlv_put_wmm(void *ptr, | ||
1720 | const struct wmi_wmm_params_arg *arg) | ||
1721 | { | ||
1722 | struct wmi_wmm_params *wmm; | ||
1723 | struct wmi_tlv *tlv; | ||
1724 | |||
1725 | tlv = ptr; | ||
1726 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS); | ||
1727 | tlv->len = __cpu_to_le16(sizeof(*wmm)); | ||
1728 | wmm = (void *)tlv->value; | ||
1729 | ath10k_wmi_pdev_set_wmm_param(wmm, arg); | ||
1730 | |||
1731 | return ptr + sizeof(*tlv) + sizeof(*wmm); | ||
1732 | } | ||
1733 | |||
1734 | static struct sk_buff * | 2044 | static struct sk_buff * |
1735 | ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar, | 2045 | ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar, |
1736 | const struct wmi_pdev_set_wmm_params_arg *arg) | 2046 | const struct wmi_wmm_params_all_arg *arg) |
1737 | { | 2047 | { |
1738 | struct wmi_tlv_pdev_set_wmm_cmd *cmd; | 2048 | struct wmi_tlv_pdev_set_wmm_cmd *cmd; |
1739 | struct wmi_wmm_params *wmm; | 2049 | struct wmi_wmm_params *wmm; |
@@ -1816,8 +2126,8 @@ ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar, | |||
1816 | } | 2126 | } |
1817 | 2127 | ||
1818 | static struct sk_buff * | 2128 | static struct sk_buff * |
1819 | ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable) | 2129 | ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable, |
1820 | { | 2130 | u32 log_level) { |
1821 | struct wmi_tlv_dbglog_cmd *cmd; | 2131 | struct wmi_tlv_dbglog_cmd *cmd; |
1822 | struct wmi_tlv *tlv; | 2132 | struct wmi_tlv *tlv; |
1823 | struct sk_buff *skb; | 2133 | struct sk_buff *skb; |
@@ -1922,6 +2232,159 @@ ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar) | |||
1922 | return skb; | 2232 | return skb; |
1923 | } | 2233 | } |
1924 | 2234 | ||
2235 | static struct sk_buff * | ||
2236 | ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id, | ||
2237 | u32 tim_ie_offset, struct sk_buff *bcn, | ||
2238 | u32 prb_caps, u32 prb_erp, void *prb_ies, | ||
2239 | size_t prb_ies_len) | ||
2240 | { | ||
2241 | struct wmi_tlv_bcn_tmpl_cmd *cmd; | ||
2242 | struct wmi_tlv_bcn_prb_info *info; | ||
2243 | struct wmi_tlv *tlv; | ||
2244 | struct sk_buff *skb; | ||
2245 | void *ptr; | ||
2246 | size_t len; | ||
2247 | |||
2248 | if (WARN_ON(prb_ies_len > 0 && !prb_ies)) | ||
2249 | return ERR_PTR(-EINVAL); | ||
2250 | |||
2251 | len = sizeof(*tlv) + sizeof(*cmd) + | ||
2252 | sizeof(*tlv) + sizeof(*info) + prb_ies_len + | ||
2253 | sizeof(*tlv) + roundup(bcn->len, 4); | ||
2254 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
2255 | if (!skb) | ||
2256 | return ERR_PTR(-ENOMEM); | ||
2257 | |||
2258 | ptr = (void *)skb->data; | ||
2259 | tlv = ptr; | ||
2260 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD); | ||
2261 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
2262 | cmd = (void *)tlv->value; | ||
2263 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
2264 | cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset); | ||
2265 | cmd->buf_len = __cpu_to_le32(bcn->len); | ||
2266 | |||
2267 | ptr += sizeof(*tlv); | ||
2268 | ptr += sizeof(*cmd); | ||
2269 | |||
2270 | /* FIXME: prb_ies_len should be probably aligned to 4byte boundary but | ||
2271 | * then it is then impossible to pass original ie len. | ||
2272 | * This chunk is not used yet so if setting probe resp template yields | ||
2273 | * problems with beaconing or crashes firmware look here. | ||
2274 | */ | ||
2275 | tlv = ptr; | ||
2276 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO); | ||
2277 | tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len); | ||
2278 | info = (void *)tlv->value; | ||
2279 | info->caps = __cpu_to_le32(prb_caps); | ||
2280 | info->erp = __cpu_to_le32(prb_erp); | ||
2281 | memcpy(info->ies, prb_ies, prb_ies_len); | ||
2282 | |||
2283 | ptr += sizeof(*tlv); | ||
2284 | ptr += sizeof(*info); | ||
2285 | ptr += prb_ies_len; | ||
2286 | |||
2287 | tlv = ptr; | ||
2288 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); | ||
2289 | tlv->len = __cpu_to_le16(roundup(bcn->len, 4)); | ||
2290 | memcpy(tlv->value, bcn->data, bcn->len); | ||
2291 | |||
2292 | /* FIXME: Adjust TSF? */ | ||
2293 | |||
2294 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n", | ||
2295 | vdev_id); | ||
2296 | return skb; | ||
2297 | } | ||
2298 | |||
2299 | static struct sk_buff * | ||
2300 | ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id, | ||
2301 | struct sk_buff *prb) | ||
2302 | { | ||
2303 | struct wmi_tlv_prb_tmpl_cmd *cmd; | ||
2304 | struct wmi_tlv_bcn_prb_info *info; | ||
2305 | struct wmi_tlv *tlv; | ||
2306 | struct sk_buff *skb; | ||
2307 | void *ptr; | ||
2308 | size_t len; | ||
2309 | |||
2310 | len = sizeof(*tlv) + sizeof(*cmd) + | ||
2311 | sizeof(*tlv) + sizeof(*info) + | ||
2312 | sizeof(*tlv) + roundup(prb->len, 4); | ||
2313 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
2314 | if (!skb) | ||
2315 | return ERR_PTR(-ENOMEM); | ||
2316 | |||
2317 | ptr = (void *)skb->data; | ||
2318 | tlv = ptr; | ||
2319 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD); | ||
2320 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
2321 | cmd = (void *)tlv->value; | ||
2322 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
2323 | cmd->buf_len = __cpu_to_le32(prb->len); | ||
2324 | |||
2325 | ptr += sizeof(*tlv); | ||
2326 | ptr += sizeof(*cmd); | ||
2327 | |||
2328 | tlv = ptr; | ||
2329 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO); | ||
2330 | tlv->len = __cpu_to_le16(sizeof(*info)); | ||
2331 | info = (void *)tlv->value; | ||
2332 | info->caps = 0; | ||
2333 | info->erp = 0; | ||
2334 | |||
2335 | ptr += sizeof(*tlv); | ||
2336 | ptr += sizeof(*info); | ||
2337 | |||
2338 | tlv = ptr; | ||
2339 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); | ||
2340 | tlv->len = __cpu_to_le16(roundup(prb->len, 4)); | ||
2341 | memcpy(tlv->value, prb->data, prb->len); | ||
2342 | |||
2343 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n", | ||
2344 | vdev_id); | ||
2345 | return skb; | ||
2346 | } | ||
2347 | |||
2348 | static struct sk_buff * | ||
2349 | ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id, | ||
2350 | const u8 *p2p_ie) | ||
2351 | { | ||
2352 | struct wmi_tlv_p2p_go_bcn_ie *cmd; | ||
2353 | struct wmi_tlv *tlv; | ||
2354 | struct sk_buff *skb; | ||
2355 | void *ptr; | ||
2356 | size_t len; | ||
2357 | |||
2358 | len = sizeof(*tlv) + sizeof(*cmd) + | ||
2359 | sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4); | ||
2360 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
2361 | if (!skb) | ||
2362 | return ERR_PTR(-ENOMEM); | ||
2363 | |||
2364 | ptr = (void *)skb->data; | ||
2365 | tlv = ptr; | ||
2366 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE); | ||
2367 | tlv->len = __cpu_to_le16(sizeof(*cmd)); | ||
2368 | cmd = (void *)tlv->value; | ||
2369 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
2370 | cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2); | ||
2371 | |||
2372 | ptr += sizeof(*tlv); | ||
2373 | ptr += sizeof(*cmd); | ||
2374 | |||
2375 | tlv = ptr; | ||
2376 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); | ||
2377 | tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4)); | ||
2378 | memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2); | ||
2379 | |||
2380 | ptr += sizeof(*tlv); | ||
2381 | ptr += roundup(p2p_ie[1] + 2, 4); | ||
2382 | |||
2383 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n", | ||
2384 | vdev_id); | ||
2385 | return skb; | ||
2386 | } | ||
2387 | |||
1925 | /****************/ | 2388 | /****************/ |
1926 | /* TLV mappings */ | 2389 | /* TLV mappings */ |
1927 | /****************/ | 2390 | /****************/ |
@@ -2045,6 +2508,7 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = { | |||
2045 | .gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID, | 2508 | .gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID, |
2046 | .gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID, | 2509 | .gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID, |
2047 | .pdev_get_temperature_cmdid = WMI_TLV_CMD_UNSUPPORTED, | 2510 | .pdev_get_temperature_cmdid = WMI_TLV_CMD_UNSUPPORTED, |
2511 | .vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID, | ||
2048 | }; | 2512 | }; |
2049 | 2513 | ||
2050 | static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = { | 2514 | static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = { |
@@ -2188,6 +2652,7 @@ static const struct wmi_ops wmi_tlv_ops = { | |||
2188 | .gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down, | 2652 | .gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down, |
2189 | .gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param, | 2653 | .gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param, |
2190 | .gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key, | 2654 | .gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key, |
2655 | .gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf, | ||
2191 | .gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create, | 2656 | .gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create, |
2192 | .gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete, | 2657 | .gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete, |
2193 | .gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush, | 2658 | .gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush, |
@@ -2207,6 +2672,15 @@ static const struct wmi_ops wmi_tlv_ops = { | |||
2207 | .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable, | 2672 | .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable, |
2208 | /* .gen_pdev_set_quiet_mode not implemented */ | 2673 | /* .gen_pdev_set_quiet_mode not implemented */ |
2209 | /* .gen_pdev_get_temperature not implemented */ | 2674 | /* .gen_pdev_get_temperature not implemented */ |
2675 | /* .gen_addba_clear_resp not implemented */ | ||
2676 | /* .gen_addba_send not implemented */ | ||
2677 | /* .gen_addba_set_resp not implemented */ | ||
2678 | /* .gen_delba_send not implemented */ | ||
2679 | .gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl, | ||
2680 | .gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl, | ||
2681 | .gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie, | ||
2682 | .gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd, | ||
2683 | .gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive, | ||
2210 | }; | 2684 | }; |
2211 | 2685 | ||
2212 | /************/ | 2686 | /************/ |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 54ffa120cd60..de68fe76eae6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h | |||
@@ -1302,6 +1302,10 @@ struct wmi_tlv_pdev_set_wmm_cmd { | |||
1302 | __le32 dg_type; /* no idea.. */ | 1302 | __le32 dg_type; /* no idea.. */ |
1303 | } __packed; | 1303 | } __packed; |
1304 | 1304 | ||
1305 | struct wmi_tlv_vdev_set_wmm_cmd { | ||
1306 | __le32 vdev_id; | ||
1307 | } __packed; | ||
1308 | |||
1305 | struct wmi_tlv_phyerr_ev { | 1309 | struct wmi_tlv_phyerr_ev { |
1306 | __le32 num_phyerrs; | 1310 | __le32 num_phyerrs; |
1307 | __le32 tsf_l32; | 1311 | __le32 tsf_l32; |
@@ -1375,6 +1379,66 @@ struct wmi_tlv_pktlog_disable { | |||
1375 | __le32 reserved; | 1379 | __le32 reserved; |
1376 | } __packed; | 1380 | } __packed; |
1377 | 1381 | ||
1382 | enum wmi_tlv_bcn_tx_status { | ||
1383 | WMI_TLV_BCN_TX_STATUS_OK, | ||
1384 | WMI_TLV_BCN_TX_STATUS_XRETRY, | ||
1385 | WMI_TLV_BCN_TX_STATUS_DROP, | ||
1386 | WMI_TLV_BCN_TX_STATUS_FILTERED, | ||
1387 | }; | ||
1388 | |||
1389 | struct wmi_tlv_bcn_tx_status_ev { | ||
1390 | __le32 vdev_id; | ||
1391 | __le32 tx_status; | ||
1392 | } __packed; | ||
1393 | |||
1394 | struct wmi_tlv_bcn_prb_info { | ||
1395 | __le32 caps; | ||
1396 | __le32 erp; | ||
1397 | u8 ies[0]; | ||
1398 | } __packed; | ||
1399 | |||
1400 | struct wmi_tlv_bcn_tmpl_cmd { | ||
1401 | __le32 vdev_id; | ||
1402 | __le32 tim_ie_offset; | ||
1403 | __le32 buf_len; | ||
1404 | } __packed; | ||
1405 | |||
1406 | struct wmi_tlv_prb_tmpl_cmd { | ||
1407 | __le32 vdev_id; | ||
1408 | __le32 buf_len; | ||
1409 | } __packed; | ||
1410 | |||
1411 | struct wmi_tlv_p2p_go_bcn_ie { | ||
1412 | __le32 vdev_id; | ||
1413 | __le32 ie_len; | ||
1414 | } __packed; | ||
1415 | |||
1416 | enum wmi_tlv_diag_item_type { | ||
1417 | WMI_TLV_DIAG_ITEM_TYPE_FW_EVENT, | ||
1418 | WMI_TLV_DIAG_ITEM_TYPE_FW_LOG, | ||
1419 | WMI_TLV_DIAG_ITEM_TYPE_FW_DEBUG_MSG, | ||
1420 | }; | ||
1421 | |||
1422 | struct wmi_tlv_diag_item { | ||
1423 | u8 type; | ||
1424 | u8 reserved; | ||
1425 | __le16 len; | ||
1426 | __le32 timestamp; | ||
1427 | __le32 code; | ||
1428 | u8 payload[0]; | ||
1429 | } __packed; | ||
1430 | |||
1431 | struct wmi_tlv_diag_data_ev { | ||
1432 | __le32 num_items; | ||
1433 | } __packed; | ||
1434 | |||
1435 | struct wmi_tlv_sta_keepalive_cmd { | ||
1436 | __le32 vdev_id; | ||
1437 | __le32 enabled; | ||
1438 | __le32 method; /* WMI_STA_KEEPALIVE_METHOD_ */ | ||
1439 | __le32 interval; /* in seconds */ | ||
1440 | } __packed; | ||
1441 | |||
1378 | void ath10k_wmi_tlv_attach(struct ath10k *ar); | 1442 | void ath10k_wmi_tlv_attach(struct ath10k *ar); |
1379 | 1443 | ||
1380 | #endif | 1444 | #endif |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 23eca8bc85d1..aeea1c793943 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -956,23 +956,45 @@ err_pull: | |||
956 | 956 | ||
957 | static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) | 957 | static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) |
958 | { | 958 | { |
959 | struct ath10k *ar = arvif->ar; | ||
960 | struct ath10k_skb_cb *cb; | ||
961 | struct sk_buff *bcn; | ||
959 | int ret; | 962 | int ret; |
960 | 963 | ||
961 | lockdep_assert_held(&arvif->ar->data_lock); | 964 | spin_lock_bh(&ar->data_lock); |
962 | 965 | ||
963 | if (arvif->beacon == NULL) | 966 | bcn = arvif->beacon; |
964 | return; | ||
965 | 967 | ||
966 | if (arvif->beacon_sent) | 968 | if (!bcn) |
967 | return; | 969 | goto unlock; |
968 | 970 | ||
969 | ret = ath10k_wmi_beacon_send_ref_nowait(arvif); | 971 | cb = ATH10K_SKB_CB(bcn); |
970 | if (ret) | 972 | |
971 | return; | 973 | switch (arvif->beacon_state) { |
974 | case ATH10K_BEACON_SENDING: | ||
975 | case ATH10K_BEACON_SENT: | ||
976 | break; | ||
977 | case ATH10K_BEACON_SCHEDULED: | ||
978 | arvif->beacon_state = ATH10K_BEACON_SENDING; | ||
979 | spin_unlock_bh(&ar->data_lock); | ||
980 | |||
981 | ret = ath10k_wmi_beacon_send_ref_nowait(arvif->ar, | ||
982 | arvif->vdev_id, | ||
983 | bcn->data, bcn->len, | ||
984 | cb->paddr, | ||
985 | cb->bcn.dtim_zero, | ||
986 | cb->bcn.deliver_cab); | ||
987 | |||
988 | spin_lock_bh(&ar->data_lock); | ||
989 | |||
990 | if (ret == 0) | ||
991 | arvif->beacon_state = ATH10K_BEACON_SENT; | ||
992 | else | ||
993 | arvif->beacon_state = ATH10K_BEACON_SCHEDULED; | ||
994 | } | ||
972 | 995 | ||
973 | /* We need to retain the arvif->beacon reference for DMA unmapping and | 996 | unlock: |
974 | * freeing the skbuff later. */ | 997 | spin_unlock_bh(&ar->data_lock); |
975 | arvif->beacon_sent = true; | ||
976 | } | 998 | } |
977 | 999 | ||
978 | static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, | 1000 | static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, |
@@ -985,12 +1007,10 @@ static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, | |||
985 | 1007 | ||
986 | static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar) | 1008 | static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar) |
987 | { | 1009 | { |
988 | spin_lock_bh(&ar->data_lock); | ||
989 | ieee80211_iterate_active_interfaces_atomic(ar->hw, | 1010 | ieee80211_iterate_active_interfaces_atomic(ar->hw, |
990 | IEEE80211_IFACE_ITER_NORMAL, | 1011 | IEEE80211_IFACE_ITER_NORMAL, |
991 | ath10k_wmi_tx_beacons_iter, | 1012 | ath10k_wmi_tx_beacons_iter, |
992 | NULL); | 1013 | NULL); |
993 | spin_unlock_bh(&ar->data_lock); | ||
994 | } | 1014 | } |
995 | 1015 | ||
996 | static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) | 1016 | static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) |
@@ -1680,12 +1700,9 @@ int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) | |||
1680 | return 0; | 1700 | return 0; |
1681 | } | 1701 | } |
1682 | 1702 | ||
1683 | void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src, | 1703 | void ath10k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src, |
1684 | struct ath10k_fw_stats_pdev *dst) | 1704 | struct ath10k_fw_stats_pdev *dst) |
1685 | { | 1705 | { |
1686 | const struct wal_dbg_tx_stats *tx = &src->wal.tx; | ||
1687 | const struct wal_dbg_rx_stats *rx = &src->wal.rx; | ||
1688 | |||
1689 | dst->ch_noise_floor = __le32_to_cpu(src->chan_nf); | 1706 | dst->ch_noise_floor = __le32_to_cpu(src->chan_nf); |
1690 | dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count); | 1707 | dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count); |
1691 | dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count); | 1708 | dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count); |
@@ -1693,44 +1710,63 @@ void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src, | |||
1693 | dst->cycle_count = __le32_to_cpu(src->cycle_count); | 1710 | dst->cycle_count = __le32_to_cpu(src->cycle_count); |
1694 | dst->phy_err_count = __le32_to_cpu(src->phy_err_count); | 1711 | dst->phy_err_count = __le32_to_cpu(src->phy_err_count); |
1695 | dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr); | 1712 | dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr); |
1713 | } | ||
1696 | 1714 | ||
1697 | dst->comp_queued = __le32_to_cpu(tx->comp_queued); | 1715 | void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src, |
1698 | dst->comp_delivered = __le32_to_cpu(tx->comp_delivered); | 1716 | struct ath10k_fw_stats_pdev *dst) |
1699 | dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued); | 1717 | { |
1700 | dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued); | 1718 | dst->comp_queued = __le32_to_cpu(src->comp_queued); |
1701 | dst->wmm_drop = __le32_to_cpu(tx->wmm_drop); | 1719 | dst->comp_delivered = __le32_to_cpu(src->comp_delivered); |
1702 | dst->local_enqued = __le32_to_cpu(tx->local_enqued); | 1720 | dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued); |
1703 | dst->local_freed = __le32_to_cpu(tx->local_freed); | 1721 | dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued); |
1704 | dst->hw_queued = __le32_to_cpu(tx->hw_queued); | 1722 | dst->wmm_drop = __le32_to_cpu(src->wmm_drop); |
1705 | dst->hw_reaped = __le32_to_cpu(tx->hw_reaped); | 1723 | dst->local_enqued = __le32_to_cpu(src->local_enqued); |
1706 | dst->underrun = __le32_to_cpu(tx->underrun); | 1724 | dst->local_freed = __le32_to_cpu(src->local_freed); |
1707 | dst->tx_abort = __le32_to_cpu(tx->tx_abort); | 1725 | dst->hw_queued = __le32_to_cpu(src->hw_queued); |
1708 | dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed); | 1726 | dst->hw_reaped = __le32_to_cpu(src->hw_reaped); |
1709 | dst->tx_ko = __le32_to_cpu(tx->tx_ko); | 1727 | dst->underrun = __le32_to_cpu(src->underrun); |
1710 | dst->data_rc = __le32_to_cpu(tx->data_rc); | 1728 | dst->tx_abort = __le32_to_cpu(src->tx_abort); |
1711 | dst->self_triggers = __le32_to_cpu(tx->self_triggers); | 1729 | dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed); |
1712 | dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure); | 1730 | dst->tx_ko = __le32_to_cpu(src->tx_ko); |
1713 | dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err); | 1731 | dst->data_rc = __le32_to_cpu(src->data_rc); |
1714 | dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry); | 1732 | dst->self_triggers = __le32_to_cpu(src->self_triggers); |
1715 | dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout); | 1733 | dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure); |
1716 | dst->pdev_resets = __le32_to_cpu(tx->pdev_resets); | 1734 | dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err); |
1717 | dst->phy_underrun = __le32_to_cpu(tx->phy_underrun); | 1735 | dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry); |
1718 | dst->txop_ovf = __le32_to_cpu(tx->txop_ovf); | 1736 | dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout); |
1719 | 1737 | dst->pdev_resets = __le32_to_cpu(src->pdev_resets); | |
1720 | dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change); | 1738 | dst->phy_underrun = __le32_to_cpu(src->phy_underrun); |
1721 | dst->status_rcvd = __le32_to_cpu(rx->status_rcvd); | 1739 | dst->txop_ovf = __le32_to_cpu(src->txop_ovf); |
1722 | dst->r0_frags = __le32_to_cpu(rx->r0_frags); | 1740 | } |
1723 | dst->r1_frags = __le32_to_cpu(rx->r1_frags); | 1741 | |
1724 | dst->r2_frags = __le32_to_cpu(rx->r2_frags); | 1742 | void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src, |
1725 | dst->r3_frags = __le32_to_cpu(rx->r3_frags); | 1743 | struct ath10k_fw_stats_pdev *dst) |
1726 | dst->htt_msdus = __le32_to_cpu(rx->htt_msdus); | 1744 | { |
1727 | dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus); | 1745 | dst->mid_ppdu_route_change = __le32_to_cpu(src->mid_ppdu_route_change); |
1728 | dst->loc_msdus = __le32_to_cpu(rx->loc_msdus); | 1746 | dst->status_rcvd = __le32_to_cpu(src->status_rcvd); |
1729 | dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus); | 1747 | dst->r0_frags = __le32_to_cpu(src->r0_frags); |
1730 | dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu); | 1748 | dst->r1_frags = __le32_to_cpu(src->r1_frags); |
1731 | dst->phy_errs = __le32_to_cpu(rx->phy_errs); | 1749 | dst->r2_frags = __le32_to_cpu(src->r2_frags); |
1732 | dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop); | 1750 | dst->r3_frags = __le32_to_cpu(src->r3_frags); |
1733 | dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs); | 1751 | dst->htt_msdus = __le32_to_cpu(src->htt_msdus); |
1752 | dst->htt_mpdus = __le32_to_cpu(src->htt_mpdus); | ||
1753 | dst->loc_msdus = __le32_to_cpu(src->loc_msdus); | ||
1754 | dst->loc_mpdus = __le32_to_cpu(src->loc_mpdus); | ||
1755 | dst->oversize_amsdu = __le32_to_cpu(src->oversize_amsdu); | ||
1756 | dst->phy_errs = __le32_to_cpu(src->phy_errs); | ||
1757 | dst->phy_err_drop = __le32_to_cpu(src->phy_err_drop); | ||
1758 | dst->mpdu_errs = __le32_to_cpu(src->mpdu_errs); | ||
1759 | } | ||
1760 | |||
1761 | void ath10k_wmi_pull_pdev_stats_extra(const struct wmi_pdev_stats_extra *src, | ||
1762 | struct ath10k_fw_stats_pdev *dst) | ||
1763 | { | ||
1764 | dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad); | ||
1765 | dst->rts_bad = __le32_to_cpu(src->rts_bad); | ||
1766 | dst->rts_good = __le32_to_cpu(src->rts_good); | ||
1767 | dst->fcs_bad = __le32_to_cpu(src->fcs_bad); | ||
1768 | dst->no_beacons = __le32_to_cpu(src->no_beacons); | ||
1769 | dst->mib_int_count = __le32_to_cpu(src->mib_int_count); | ||
1734 | } | 1770 | } |
1735 | 1771 | ||
1736 | void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, | 1772 | void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, |
@@ -1768,7 +1804,10 @@ static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar, | |||
1768 | if (!dst) | 1804 | if (!dst) |
1769 | continue; | 1805 | continue; |
1770 | 1806 | ||
1771 | ath10k_wmi_pull_pdev_stats(src, dst); | 1807 | ath10k_wmi_pull_pdev_stats_base(&src->base, dst); |
1808 | ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst); | ||
1809 | ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); | ||
1810 | |||
1772 | list_add_tail(&dst->list, &stats->pdevs); | 1811 | list_add_tail(&dst->list, &stats->pdevs); |
1773 | } | 1812 | } |
1774 | 1813 | ||
@@ -1820,14 +1859,10 @@ static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar, | |||
1820 | if (!dst) | 1859 | if (!dst) |
1821 | continue; | 1860 | continue; |
1822 | 1861 | ||
1823 | ath10k_wmi_pull_pdev_stats(&src->old, dst); | 1862 | ath10k_wmi_pull_pdev_stats_base(&src->base, dst); |
1824 | 1863 | ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst); | |
1825 | dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad); | 1864 | ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); |
1826 | dst->rts_bad = __le32_to_cpu(src->rts_bad); | 1865 | ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst); |
1827 | dst->rts_good = __le32_to_cpu(src->rts_good); | ||
1828 | dst->fcs_bad = __le32_to_cpu(src->fcs_bad); | ||
1829 | dst->no_beacons = __le32_to_cpu(src->no_beacons); | ||
1830 | dst->mib_int_count = __le32_to_cpu(src->mib_int_count); | ||
1831 | 1866 | ||
1832 | list_add_tail(&dst->list, &stats->pdevs); | 1867 | list_add_tail(&dst->list, &stats->pdevs); |
1833 | } | 1868 | } |
@@ -1856,6 +1891,164 @@ static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar, | |||
1856 | return 0; | 1891 | return 0; |
1857 | } | 1892 | } |
1858 | 1893 | ||
1894 | static int ath10k_wmi_10_2_op_pull_fw_stats(struct ath10k *ar, | ||
1895 | struct sk_buff *skb, | ||
1896 | struct ath10k_fw_stats *stats) | ||
1897 | { | ||
1898 | const struct wmi_10_2_stats_event *ev = (void *)skb->data; | ||
1899 | u32 num_pdev_stats; | ||
1900 | u32 num_pdev_ext_stats; | ||
1901 | u32 num_vdev_stats; | ||
1902 | u32 num_peer_stats; | ||
1903 | int i; | ||
1904 | |||
1905 | if (!skb_pull(skb, sizeof(*ev))) | ||
1906 | return -EPROTO; | ||
1907 | |||
1908 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); | ||
1909 | num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); | ||
1910 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); | ||
1911 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | ||
1912 | |||
1913 | for (i = 0; i < num_pdev_stats; i++) { | ||
1914 | const struct wmi_10_2_pdev_stats *src; | ||
1915 | struct ath10k_fw_stats_pdev *dst; | ||
1916 | |||
1917 | src = (void *)skb->data; | ||
1918 | if (!skb_pull(skb, sizeof(*src))) | ||
1919 | return -EPROTO; | ||
1920 | |||
1921 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1922 | if (!dst) | ||
1923 | continue; | ||
1924 | |||
1925 | ath10k_wmi_pull_pdev_stats_base(&src->base, dst); | ||
1926 | ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst); | ||
1927 | ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); | ||
1928 | ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst); | ||
1929 | /* FIXME: expose 10.2 specific values */ | ||
1930 | |||
1931 | list_add_tail(&dst->list, &stats->pdevs); | ||
1932 | } | ||
1933 | |||
1934 | for (i = 0; i < num_pdev_ext_stats; i++) { | ||
1935 | const struct wmi_10_2_pdev_ext_stats *src; | ||
1936 | |||
1937 | src = (void *)skb->data; | ||
1938 | if (!skb_pull(skb, sizeof(*src))) | ||
1939 | return -EPROTO; | ||
1940 | |||
1941 | /* FIXME: expose values to userspace | ||
1942 | * | ||
1943 | * Note: Even though this loop seems to do nothing it is | ||
1944 | * required to parse following sub-structures properly. | ||
1945 | */ | ||
1946 | } | ||
1947 | |||
1948 | /* fw doesn't implement vdev stats */ | ||
1949 | |||
1950 | for (i = 0; i < num_peer_stats; i++) { | ||
1951 | const struct wmi_10_2_peer_stats *src; | ||
1952 | struct ath10k_fw_stats_peer *dst; | ||
1953 | |||
1954 | src = (void *)skb->data; | ||
1955 | if (!skb_pull(skb, sizeof(*src))) | ||
1956 | return -EPROTO; | ||
1957 | |||
1958 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1959 | if (!dst) | ||
1960 | continue; | ||
1961 | |||
1962 | ath10k_wmi_pull_peer_stats(&src->old, dst); | ||
1963 | |||
1964 | dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); | ||
1965 | /* FIXME: expose 10.2 specific values */ | ||
1966 | |||
1967 | list_add_tail(&dst->list, &stats->peers); | ||
1968 | } | ||
1969 | |||
1970 | return 0; | ||
1971 | } | ||
1972 | |||
1973 | static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, | ||
1974 | struct sk_buff *skb, | ||
1975 | struct ath10k_fw_stats *stats) | ||
1976 | { | ||
1977 | const struct wmi_10_2_stats_event *ev = (void *)skb->data; | ||
1978 | u32 num_pdev_stats; | ||
1979 | u32 num_pdev_ext_stats; | ||
1980 | u32 num_vdev_stats; | ||
1981 | u32 num_peer_stats; | ||
1982 | int i; | ||
1983 | |||
1984 | if (!skb_pull(skb, sizeof(*ev))) | ||
1985 | return -EPROTO; | ||
1986 | |||
1987 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); | ||
1988 | num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); | ||
1989 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); | ||
1990 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | ||
1991 | |||
1992 | for (i = 0; i < num_pdev_stats; i++) { | ||
1993 | const struct wmi_10_2_pdev_stats *src; | ||
1994 | struct ath10k_fw_stats_pdev *dst; | ||
1995 | |||
1996 | src = (void *)skb->data; | ||
1997 | if (!skb_pull(skb, sizeof(*src))) | ||
1998 | return -EPROTO; | ||
1999 | |||
2000 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
2001 | if (!dst) | ||
2002 | continue; | ||
2003 | |||
2004 | ath10k_wmi_pull_pdev_stats_base(&src->base, dst); | ||
2005 | ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst); | ||
2006 | ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); | ||
2007 | ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst); | ||
2008 | /* FIXME: expose 10.2 specific values */ | ||
2009 | |||
2010 | list_add_tail(&dst->list, &stats->pdevs); | ||
2011 | } | ||
2012 | |||
2013 | for (i = 0; i < num_pdev_ext_stats; i++) { | ||
2014 | const struct wmi_10_2_pdev_ext_stats *src; | ||
2015 | |||
2016 | src = (void *)skb->data; | ||
2017 | if (!skb_pull(skb, sizeof(*src))) | ||
2018 | return -EPROTO; | ||
2019 | |||
2020 | /* FIXME: expose values to userspace | ||
2021 | * | ||
2022 | * Note: Even though this loop seems to do nothing it is | ||
2023 | * required to parse following sub-structures properly. | ||
2024 | */ | ||
2025 | } | ||
2026 | |||
2027 | /* fw doesn't implement vdev stats */ | ||
2028 | |||
2029 | for (i = 0; i < num_peer_stats; i++) { | ||
2030 | const struct wmi_10_2_4_peer_stats *src; | ||
2031 | struct ath10k_fw_stats_peer *dst; | ||
2032 | |||
2033 | src = (void *)skb->data; | ||
2034 | if (!skb_pull(skb, sizeof(*src))) | ||
2035 | return -EPROTO; | ||
2036 | |||
2037 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
2038 | if (!dst) | ||
2039 | continue; | ||
2040 | |||
2041 | ath10k_wmi_pull_peer_stats(&src->common.old, dst); | ||
2042 | |||
2043 | dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate); | ||
2044 | /* FIXME: expose 10.2 specific values */ | ||
2045 | |||
2046 | list_add_tail(&dst->list, &stats->peers); | ||
2047 | } | ||
2048 | |||
2049 | return 0; | ||
2050 | } | ||
2051 | |||
1859 | void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) | 2052 | void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) |
1860 | { | 2053 | { |
1861 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); | 2054 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); |
@@ -2279,9 +2472,19 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
2279 | spin_lock_bh(&ar->data_lock); | 2472 | spin_lock_bh(&ar->data_lock); |
2280 | 2473 | ||
2281 | if (arvif->beacon) { | 2474 | if (arvif->beacon) { |
2282 | if (!arvif->beacon_sent) | 2475 | switch (arvif->beacon_state) { |
2283 | ath10k_warn(ar, "SWBA overrun on vdev %d\n", | 2476 | case ATH10K_BEACON_SENT: |
2477 | break; | ||
2478 | case ATH10K_BEACON_SCHEDULED: | ||
2479 | ath10k_warn(ar, "SWBA overrun on vdev %d, skipped old beacon\n", | ||
2480 | arvif->vdev_id); | ||
2481 | break; | ||
2482 | case ATH10K_BEACON_SENDING: | ||
2483 | ath10k_warn(ar, "SWBA overrun on vdev %d, skipped new beacon\n", | ||
2284 | arvif->vdev_id); | 2484 | arvif->vdev_id); |
2485 | dev_kfree_skb(bcn); | ||
2486 | goto skip; | ||
2487 | } | ||
2285 | 2488 | ||
2286 | ath10k_mac_vif_beacon_free(arvif); | 2489 | ath10k_mac_vif_beacon_free(arvif); |
2287 | } | 2490 | } |
@@ -2309,15 +2512,16 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
2309 | } | 2512 | } |
2310 | 2513 | ||
2311 | arvif->beacon = bcn; | 2514 | arvif->beacon = bcn; |
2312 | arvif->beacon_sent = false; | 2515 | arvif->beacon_state = ATH10K_BEACON_SCHEDULED; |
2313 | 2516 | ||
2314 | trace_ath10k_tx_hdr(ar, bcn->data, bcn->len); | 2517 | trace_ath10k_tx_hdr(ar, bcn->data, bcn->len); |
2315 | trace_ath10k_tx_payload(ar, bcn->data, bcn->len); | 2518 | trace_ath10k_tx_payload(ar, bcn->data, bcn->len); |
2316 | 2519 | ||
2317 | ath10k_wmi_tx_beacon_nowait(arvif); | ||
2318 | skip: | 2520 | skip: |
2319 | spin_unlock_bh(&ar->data_lock); | 2521 | spin_unlock_bh(&ar->data_lock); |
2320 | } | 2522 | } |
2523 | |||
2524 | ath10k_wmi_tx_beacons_nowait(ar); | ||
2321 | } | 2525 | } |
2322 | 2526 | ||
2323 | void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb) | 2527 | void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb) |
@@ -3710,7 +3914,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) | |||
3710 | struct wmi_init_cmd_10_2 *cmd; | 3914 | struct wmi_init_cmd_10_2 *cmd; |
3711 | struct sk_buff *buf; | 3915 | struct sk_buff *buf; |
3712 | struct wmi_resource_config_10x config = {}; | 3916 | struct wmi_resource_config_10x config = {}; |
3713 | u32 len, val; | 3917 | u32 len, val, features; |
3714 | 3918 | ||
3715 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | 3919 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); |
3716 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | 3920 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); |
@@ -3744,7 +3948,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) | |||
3744 | config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE); | 3948 | config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE); |
3745 | config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE); | 3949 | config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE); |
3746 | config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES); | 3950 | config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES); |
3747 | config.dma_burst_size = __cpu_to_le32(TARGET_10X_DMA_BURST_SIZE); | 3951 | config.dma_burst_size = __cpu_to_le32(TARGET_10_2_DMA_BURST_SIZE); |
3748 | config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM); | 3952 | config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM); |
3749 | 3953 | ||
3750 | val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; | 3954 | val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; |
@@ -3764,6 +3968,9 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) | |||
3764 | 3968 | ||
3765 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; | 3969 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; |
3766 | 3970 | ||
3971 | features = WMI_10_2_RX_BATCH_MODE; | ||
3972 | cmd->resource_config.feature_mask = __cpu_to_le32(features); | ||
3973 | |||
3767 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); | 3974 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); |
3768 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); | 3975 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); |
3769 | 3976 | ||
@@ -4680,12 +4887,12 @@ ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar) | |||
4680 | 4887 | ||
4681 | /* This function assumes the beacon is already DMA mapped */ | 4888 | /* This function assumes the beacon is already DMA mapped */ |
4682 | static struct sk_buff * | 4889 | static struct sk_buff * |
4683 | ath10k_wmi_op_gen_beacon_dma(struct ath10k_vif *arvif) | 4890 | ath10k_wmi_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, const void *bcn, |
4891 | size_t bcn_len, u32 bcn_paddr, bool dtim_zero, | ||
4892 | bool deliver_cab) | ||
4684 | { | 4893 | { |
4685 | struct ath10k *ar = arvif->ar; | ||
4686 | struct wmi_bcn_tx_ref_cmd *cmd; | 4894 | struct wmi_bcn_tx_ref_cmd *cmd; |
4687 | struct sk_buff *skb; | 4895 | struct sk_buff *skb; |
4688 | struct sk_buff *beacon = arvif->beacon; | ||
4689 | struct ieee80211_hdr *hdr; | 4896 | struct ieee80211_hdr *hdr; |
4690 | u16 fc; | 4897 | u16 fc; |
4691 | 4898 | ||
@@ -4693,29 +4900,29 @@ ath10k_wmi_op_gen_beacon_dma(struct ath10k_vif *arvif) | |||
4693 | if (!skb) | 4900 | if (!skb) |
4694 | return ERR_PTR(-ENOMEM); | 4901 | return ERR_PTR(-ENOMEM); |
4695 | 4902 | ||
4696 | hdr = (struct ieee80211_hdr *)beacon->data; | 4903 | hdr = (struct ieee80211_hdr *)bcn; |
4697 | fc = le16_to_cpu(hdr->frame_control); | 4904 | fc = le16_to_cpu(hdr->frame_control); |
4698 | 4905 | ||
4699 | cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data; | 4906 | cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data; |
4700 | cmd->vdev_id = __cpu_to_le32(arvif->vdev_id); | 4907 | cmd->vdev_id = __cpu_to_le32(vdev_id); |
4701 | cmd->data_len = __cpu_to_le32(beacon->len); | 4908 | cmd->data_len = __cpu_to_le32(bcn_len); |
4702 | cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr); | 4909 | cmd->data_ptr = __cpu_to_le32(bcn_paddr); |
4703 | cmd->msdu_id = 0; | 4910 | cmd->msdu_id = 0; |
4704 | cmd->frame_control = __cpu_to_le32(fc); | 4911 | cmd->frame_control = __cpu_to_le32(fc); |
4705 | cmd->flags = 0; | 4912 | cmd->flags = 0; |
4706 | cmd->antenna_mask = __cpu_to_le32(WMI_BCN_TX_REF_DEF_ANTENNA); | 4913 | cmd->antenna_mask = __cpu_to_le32(WMI_BCN_TX_REF_DEF_ANTENNA); |
4707 | 4914 | ||
4708 | if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero) | 4915 | if (dtim_zero) |
4709 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO); | 4916 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO); |
4710 | 4917 | ||
4711 | if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab) | 4918 | if (deliver_cab) |
4712 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB); | 4919 | cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB); |
4713 | 4920 | ||
4714 | return skb; | 4921 | return skb; |
4715 | } | 4922 | } |
4716 | 4923 | ||
4717 | void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, | 4924 | void ath10k_wmi_set_wmm_param(struct wmi_wmm_params *params, |
4718 | const struct wmi_wmm_params_arg *arg) | 4925 | const struct wmi_wmm_params_arg *arg) |
4719 | { | 4926 | { |
4720 | params->cwmin = __cpu_to_le32(arg->cwmin); | 4927 | params->cwmin = __cpu_to_le32(arg->cwmin); |
4721 | params->cwmax = __cpu_to_le32(arg->cwmax); | 4928 | params->cwmax = __cpu_to_le32(arg->cwmax); |
@@ -4727,7 +4934,7 @@ void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, | |||
4727 | 4934 | ||
4728 | static struct sk_buff * | 4935 | static struct sk_buff * |
4729 | ath10k_wmi_op_gen_pdev_set_wmm(struct ath10k *ar, | 4936 | ath10k_wmi_op_gen_pdev_set_wmm(struct ath10k *ar, |
4730 | const struct wmi_pdev_set_wmm_params_arg *arg) | 4937 | const struct wmi_wmm_params_all_arg *arg) |
4731 | { | 4938 | { |
4732 | struct wmi_pdev_set_wmm_params *cmd; | 4939 | struct wmi_pdev_set_wmm_params *cmd; |
4733 | struct sk_buff *skb; | 4940 | struct sk_buff *skb; |
@@ -4737,10 +4944,10 @@ ath10k_wmi_op_gen_pdev_set_wmm(struct ath10k *ar, | |||
4737 | return ERR_PTR(-ENOMEM); | 4944 | return ERR_PTR(-ENOMEM); |
4738 | 4945 | ||
4739 | cmd = (struct wmi_pdev_set_wmm_params *)skb->data; | 4946 | cmd = (struct wmi_pdev_set_wmm_params *)skb->data; |
4740 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_be, &arg->ac_be); | 4947 | ath10k_wmi_set_wmm_param(&cmd->ac_be, &arg->ac_be); |
4741 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_bk, &arg->ac_bk); | 4948 | ath10k_wmi_set_wmm_param(&cmd->ac_bk, &arg->ac_bk); |
4742 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vi, &arg->ac_vi); | 4949 | ath10k_wmi_set_wmm_param(&cmd->ac_vi, &arg->ac_vi); |
4743 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); | 4950 | ath10k_wmi_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); |
4744 | 4951 | ||
4745 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); | 4952 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); |
4746 | return skb; | 4953 | return skb; |
@@ -4784,7 +4991,8 @@ ath10k_wmi_op_gen_force_fw_hang(struct ath10k *ar, | |||
4784 | } | 4991 | } |
4785 | 4992 | ||
4786 | static struct sk_buff * | 4993 | static struct sk_buff * |
4787 | ath10k_wmi_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable) | 4994 | ath10k_wmi_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable, |
4995 | u32 log_level) | ||
4788 | { | 4996 | { |
4789 | struct wmi_dbglog_cfg_cmd *cmd; | 4997 | struct wmi_dbglog_cfg_cmd *cmd; |
4790 | struct sk_buff *skb; | 4998 | struct sk_buff *skb; |
@@ -4797,7 +5005,7 @@ ath10k_wmi_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable) | |||
4797 | cmd = (struct wmi_dbglog_cfg_cmd *)skb->data; | 5005 | cmd = (struct wmi_dbglog_cfg_cmd *)skb->data; |
4798 | 5006 | ||
4799 | if (module_enable) { | 5007 | if (module_enable) { |
4800 | cfg = SM(ATH10K_DBGLOG_LEVEL_VERBOSE, | 5008 | cfg = SM(log_level, |
4801 | ATH10K_DBGLOG_CFG_LOG_LVL); | 5009 | ATH10K_DBGLOG_CFG_LOG_LVL); |
4802 | } else { | 5010 | } else { |
4803 | /* set back defaults, all modules with WARN level */ | 5011 | /* set back defaults, all modules with WARN level */ |
@@ -4877,6 +5085,109 @@ ath10k_wmi_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period, | |||
4877 | return skb; | 5085 | return skb; |
4878 | } | 5086 | } |
4879 | 5087 | ||
5088 | static struct sk_buff * | ||
5089 | ath10k_wmi_op_gen_addba_clear_resp(struct ath10k *ar, u32 vdev_id, | ||
5090 | const u8 *mac) | ||
5091 | { | ||
5092 | struct wmi_addba_clear_resp_cmd *cmd; | ||
5093 | struct sk_buff *skb; | ||
5094 | |||
5095 | if (!mac) | ||
5096 | return ERR_PTR(-EINVAL); | ||
5097 | |||
5098 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
5099 | if (!skb) | ||
5100 | return ERR_PTR(-ENOMEM); | ||
5101 | |||
5102 | cmd = (struct wmi_addba_clear_resp_cmd *)skb->data; | ||
5103 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
5104 | ether_addr_copy(cmd->peer_macaddr.addr, mac); | ||
5105 | |||
5106 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
5107 | "wmi addba clear resp vdev_id 0x%X mac_addr %pM\n", | ||
5108 | vdev_id, mac); | ||
5109 | return skb; | ||
5110 | } | ||
5111 | |||
5112 | static struct sk_buff * | ||
5113 | ath10k_wmi_op_gen_addba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac, | ||
5114 | u32 tid, u32 buf_size) | ||
5115 | { | ||
5116 | struct wmi_addba_send_cmd *cmd; | ||
5117 | struct sk_buff *skb; | ||
5118 | |||
5119 | if (!mac) | ||
5120 | return ERR_PTR(-EINVAL); | ||
5121 | |||
5122 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
5123 | if (!skb) | ||
5124 | return ERR_PTR(-ENOMEM); | ||
5125 | |||
5126 | cmd = (struct wmi_addba_send_cmd *)skb->data; | ||
5127 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
5128 | ether_addr_copy(cmd->peer_macaddr.addr, mac); | ||
5129 | cmd->tid = __cpu_to_le32(tid); | ||
5130 | cmd->buffersize = __cpu_to_le32(buf_size); | ||
5131 | |||
5132 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
5133 | "wmi addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n", | ||
5134 | vdev_id, mac, tid, buf_size); | ||
5135 | return skb; | ||
5136 | } | ||
5137 | |||
5138 | static struct sk_buff * | ||
5139 | ath10k_wmi_op_gen_addba_set_resp(struct ath10k *ar, u32 vdev_id, const u8 *mac, | ||
5140 | u32 tid, u32 status) | ||
5141 | { | ||
5142 | struct wmi_addba_setresponse_cmd *cmd; | ||
5143 | struct sk_buff *skb; | ||
5144 | |||
5145 | if (!mac) | ||
5146 | return ERR_PTR(-EINVAL); | ||
5147 | |||
5148 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
5149 | if (!skb) | ||
5150 | return ERR_PTR(-ENOMEM); | ||
5151 | |||
5152 | cmd = (struct wmi_addba_setresponse_cmd *)skb->data; | ||
5153 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
5154 | ether_addr_copy(cmd->peer_macaddr.addr, mac); | ||
5155 | cmd->tid = __cpu_to_le32(tid); | ||
5156 | cmd->statuscode = __cpu_to_le32(status); | ||
5157 | |||
5158 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
5159 | "wmi addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n", | ||
5160 | vdev_id, mac, tid, status); | ||
5161 | return skb; | ||
5162 | } | ||
5163 | |||
5164 | static struct sk_buff * | ||
5165 | ath10k_wmi_op_gen_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac, | ||
5166 | u32 tid, u32 initiator, u32 reason) | ||
5167 | { | ||
5168 | struct wmi_delba_send_cmd *cmd; | ||
5169 | struct sk_buff *skb; | ||
5170 | |||
5171 | if (!mac) | ||
5172 | return ERR_PTR(-EINVAL); | ||
5173 | |||
5174 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
5175 | if (!skb) | ||
5176 | return ERR_PTR(-ENOMEM); | ||
5177 | |||
5178 | cmd = (struct wmi_delba_send_cmd *)skb->data; | ||
5179 | cmd->vdev_id = __cpu_to_le32(vdev_id); | ||
5180 | ether_addr_copy(cmd->peer_macaddr.addr, mac); | ||
5181 | cmd->tid = __cpu_to_le32(tid); | ||
5182 | cmd->initiator = __cpu_to_le32(initiator); | ||
5183 | cmd->reasoncode = __cpu_to_le32(reason); | ||
5184 | |||
5185 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
5186 | "wmi delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n", | ||
5187 | vdev_id, mac, tid, initiator, reason); | ||
5188 | return skb; | ||
5189 | } | ||
5190 | |||
4880 | static const struct wmi_ops wmi_ops = { | 5191 | static const struct wmi_ops wmi_ops = { |
4881 | .rx = ath10k_wmi_op_rx, | 5192 | .rx = ath10k_wmi_op_rx, |
4882 | .map_svc = wmi_main_svc_map, | 5193 | .map_svc = wmi_main_svc_map, |
@@ -4909,6 +5220,7 @@ static const struct wmi_ops wmi_ops = { | |||
4909 | .gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key, | 5220 | .gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key, |
4910 | .gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf, | 5221 | .gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf, |
4911 | .gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable, | 5222 | .gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable, |
5223 | /* .gen_vdev_wmm_conf not implemented */ | ||
4912 | .gen_peer_create = ath10k_wmi_op_gen_peer_create, | 5224 | .gen_peer_create = ath10k_wmi_op_gen_peer_create, |
4913 | .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, | 5225 | .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, |
4914 | .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, | 5226 | .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, |
@@ -4928,6 +5240,13 @@ static const struct wmi_ops wmi_ops = { | |||
4928 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, | 5240 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, |
4929 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, | 5241 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, |
4930 | /* .gen_pdev_get_temperature not implemented */ | 5242 | /* .gen_pdev_get_temperature not implemented */ |
5243 | .gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp, | ||
5244 | .gen_addba_send = ath10k_wmi_op_gen_addba_send, | ||
5245 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | ||
5246 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | ||
5247 | /* .gen_bcn_tmpl not implemented */ | ||
5248 | /* .gen_prb_tmpl not implemented */ | ||
5249 | /* .gen_p2p_go_bcn_ie not implemented */ | ||
4931 | }; | 5250 | }; |
4932 | 5251 | ||
4933 | static const struct wmi_ops wmi_10_1_ops = { | 5252 | static const struct wmi_ops wmi_10_1_ops = { |
@@ -4965,6 +5284,7 @@ static const struct wmi_ops wmi_10_1_ops = { | |||
4965 | .gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key, | 5284 | .gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key, |
4966 | .gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf, | 5285 | .gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf, |
4967 | .gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable, | 5286 | .gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable, |
5287 | /* .gen_vdev_wmm_conf not implemented */ | ||
4968 | .gen_peer_create = ath10k_wmi_op_gen_peer_create, | 5288 | .gen_peer_create = ath10k_wmi_op_gen_peer_create, |
4969 | .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, | 5289 | .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, |
4970 | .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, | 5290 | .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, |
@@ -4982,10 +5302,18 @@ static const struct wmi_ops wmi_10_1_ops = { | |||
4982 | .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable, | 5302 | .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable, |
4983 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, | 5303 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, |
4984 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, | 5304 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, |
5305 | .gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp, | ||
5306 | .gen_addba_send = ath10k_wmi_op_gen_addba_send, | ||
5307 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | ||
5308 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | ||
5309 | /* .gen_bcn_tmpl not implemented */ | ||
5310 | /* .gen_prb_tmpl not implemented */ | ||
5311 | /* .gen_p2p_go_bcn_ie not implemented */ | ||
4985 | }; | 5312 | }; |
4986 | 5313 | ||
4987 | static const struct wmi_ops wmi_10_2_ops = { | 5314 | static const struct wmi_ops wmi_10_2_ops = { |
4988 | .rx = ath10k_wmi_10_2_op_rx, | 5315 | .rx = ath10k_wmi_10_2_op_rx, |
5316 | .pull_fw_stats = ath10k_wmi_10_2_op_pull_fw_stats, | ||
4989 | .gen_init = ath10k_wmi_10_2_op_gen_init, | 5317 | .gen_init = ath10k_wmi_10_2_op_gen_init, |
4990 | .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, | 5318 | .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, |
4991 | /* .gen_pdev_get_temperature not implemented */ | 5319 | /* .gen_pdev_get_temperature not implemented */ |
@@ -4993,7 +5321,6 @@ static const struct wmi_ops wmi_10_2_ops = { | |||
4993 | /* shared with 10.1 */ | 5321 | /* shared with 10.1 */ |
4994 | .map_svc = wmi_10x_svc_map, | 5322 | .map_svc = wmi_10x_svc_map, |
4995 | .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev, | 5323 | .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev, |
4996 | .pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats, | ||
4997 | .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd, | 5324 | .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd, |
4998 | .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan, | 5325 | .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan, |
4999 | 5326 | ||
@@ -5020,6 +5347,7 @@ static const struct wmi_ops wmi_10_2_ops = { | |||
5020 | .gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key, | 5347 | .gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key, |
5021 | .gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf, | 5348 | .gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf, |
5022 | .gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable, | 5349 | .gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable, |
5350 | /* .gen_vdev_wmm_conf not implemented */ | ||
5023 | .gen_peer_create = ath10k_wmi_op_gen_peer_create, | 5351 | .gen_peer_create = ath10k_wmi_op_gen_peer_create, |
5024 | .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, | 5352 | .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, |
5025 | .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, | 5353 | .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, |
@@ -5037,10 +5365,15 @@ static const struct wmi_ops wmi_10_2_ops = { | |||
5037 | .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable, | 5365 | .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable, |
5038 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, | 5366 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, |
5039 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, | 5367 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, |
5368 | .gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp, | ||
5369 | .gen_addba_send = ath10k_wmi_op_gen_addba_send, | ||
5370 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | ||
5371 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | ||
5040 | }; | 5372 | }; |
5041 | 5373 | ||
5042 | static const struct wmi_ops wmi_10_2_4_ops = { | 5374 | static const struct wmi_ops wmi_10_2_4_ops = { |
5043 | .rx = ath10k_wmi_10_2_op_rx, | 5375 | .rx = ath10k_wmi_10_2_op_rx, |
5376 | .pull_fw_stats = ath10k_wmi_10_2_4_op_pull_fw_stats, | ||
5044 | .gen_init = ath10k_wmi_10_2_op_gen_init, | 5377 | .gen_init = ath10k_wmi_10_2_op_gen_init, |
5045 | .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, | 5378 | .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, |
5046 | .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, | 5379 | .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, |
@@ -5048,7 +5381,6 @@ static const struct wmi_ops wmi_10_2_4_ops = { | |||
5048 | /* shared with 10.1 */ | 5381 | /* shared with 10.1 */ |
5049 | .map_svc = wmi_10x_svc_map, | 5382 | .map_svc = wmi_10x_svc_map, |
5050 | .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev, | 5383 | .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev, |
5051 | .pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats, | ||
5052 | .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd, | 5384 | .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd, |
5053 | .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan, | 5385 | .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan, |
5054 | 5386 | ||
@@ -5092,6 +5424,13 @@ static const struct wmi_ops wmi_10_2_4_ops = { | |||
5092 | .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable, | 5424 | .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable, |
5093 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, | 5425 | .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable, |
5094 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, | 5426 | .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode, |
5427 | .gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp, | ||
5428 | .gen_addba_send = ath10k_wmi_op_gen_addba_send, | ||
5429 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | ||
5430 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | ||
5431 | /* .gen_bcn_tmpl not implemented */ | ||
5432 | /* .gen_prb_tmpl not implemented */ | ||
5433 | /* .gen_p2p_go_bcn_ie not implemented */ | ||
5095 | }; | 5434 | }; |
5096 | 5435 | ||
5097 | int ath10k_wmi_attach(struct ath10k *ar) | 5436 | int ath10k_wmi_attach(struct ath10k *ar) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index bd7f29a3a122..20ce3603e64b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -551,6 +551,7 @@ struct wmi_cmd_map { | |||
551 | u32 gpio_config_cmdid; | 551 | u32 gpio_config_cmdid; |
552 | u32 gpio_output_cmdid; | 552 | u32 gpio_output_cmdid; |
553 | u32 pdev_get_temperature_cmdid; | 553 | u32 pdev_get_temperature_cmdid; |
554 | u32 vdev_set_wmm_params_cmdid; | ||
554 | }; | 555 | }; |
555 | 556 | ||
556 | /* | 557 | /* |
@@ -2939,14 +2940,14 @@ struct wmi_wmm_params_arg { | |||
2939 | u32 no_ack; | 2940 | u32 no_ack; |
2940 | }; | 2941 | }; |
2941 | 2942 | ||
2942 | struct wmi_pdev_set_wmm_params_arg { | 2943 | struct wmi_wmm_params_all_arg { |
2943 | struct wmi_wmm_params_arg ac_be; | 2944 | struct wmi_wmm_params_arg ac_be; |
2944 | struct wmi_wmm_params_arg ac_bk; | 2945 | struct wmi_wmm_params_arg ac_bk; |
2945 | struct wmi_wmm_params_arg ac_vi; | 2946 | struct wmi_wmm_params_arg ac_vi; |
2946 | struct wmi_wmm_params_arg ac_vo; | 2947 | struct wmi_wmm_params_arg ac_vo; |
2947 | }; | 2948 | }; |
2948 | 2949 | ||
2949 | struct wal_dbg_tx_stats { | 2950 | struct wmi_pdev_stats_tx { |
2950 | /* Num HTT cookies queued to dispatch list */ | 2951 | /* Num HTT cookies queued to dispatch list */ |
2951 | __le32 comp_queued; | 2952 | __le32 comp_queued; |
2952 | 2953 | ||
@@ -3016,7 +3017,7 @@ struct wal_dbg_tx_stats { | |||
3016 | __le32 txop_ovf; | 3017 | __le32 txop_ovf; |
3017 | } __packed; | 3018 | } __packed; |
3018 | 3019 | ||
3019 | struct wal_dbg_rx_stats { | 3020 | struct wmi_pdev_stats_rx { |
3020 | /* Cnts any change in ring routing mid-ppdu */ | 3021 | /* Cnts any change in ring routing mid-ppdu */ |
3021 | __le32 mid_ppdu_route_change; | 3022 | __le32 mid_ppdu_route_change; |
3022 | 3023 | ||
@@ -3050,17 +3051,11 @@ struct wal_dbg_rx_stats { | |||
3050 | __le32 mpdu_errs; | 3051 | __le32 mpdu_errs; |
3051 | } __packed; | 3052 | } __packed; |
3052 | 3053 | ||
3053 | struct wal_dbg_peer_stats { | 3054 | struct wmi_pdev_stats_peer { |
3054 | /* REMOVE THIS ONCE REAL PEER STAT COUNTERS ARE ADDED */ | 3055 | /* REMOVE THIS ONCE REAL PEER STAT COUNTERS ARE ADDED */ |
3055 | __le32 dummy; | 3056 | __le32 dummy; |
3056 | } __packed; | 3057 | } __packed; |
3057 | 3058 | ||
3058 | struct wal_dbg_stats { | ||
3059 | struct wal_dbg_tx_stats tx; | ||
3060 | struct wal_dbg_rx_stats rx; | ||
3061 | struct wal_dbg_peer_stats peer; | ||
3062 | } __packed; | ||
3063 | |||
3064 | enum wmi_stats_id { | 3059 | enum wmi_stats_id { |
3065 | WMI_REQUEST_PEER_STAT = 0x01, | 3060 | WMI_REQUEST_PEER_STAT = 0x01, |
3066 | WMI_REQUEST_AP_STAT = 0x02 | 3061 | WMI_REQUEST_AP_STAT = 0x02 |
@@ -3127,23 +3122,38 @@ struct wmi_stats_event { | |||
3127 | u8 data[0]; | 3122 | u8 data[0]; |
3128 | } __packed; | 3123 | } __packed; |
3129 | 3124 | ||
3125 | struct wmi_10_2_stats_event { | ||
3126 | __le32 stats_id; /* %WMI_REQUEST_ */ | ||
3127 | __le32 num_pdev_stats; | ||
3128 | __le32 num_pdev_ext_stats; | ||
3129 | __le32 num_vdev_stats; | ||
3130 | __le32 num_peer_stats; | ||
3131 | __le32 num_bcnflt_stats; | ||
3132 | u8 data[0]; | ||
3133 | } __packed; | ||
3134 | |||
3130 | /* | 3135 | /* |
3131 | * PDEV statistics | 3136 | * PDEV statistics |
3132 | * TODO: add all PDEV stats here | 3137 | * TODO: add all PDEV stats here |
3133 | */ | 3138 | */ |
3139 | struct wmi_pdev_stats_base { | ||
3140 | __le32 chan_nf; | ||
3141 | __le32 tx_frame_count; | ||
3142 | __le32 rx_frame_count; | ||
3143 | __le32 rx_clear_count; | ||
3144 | __le32 cycle_count; | ||
3145 | __le32 phy_err_count; | ||
3146 | __le32 chan_tx_pwr; | ||
3147 | } __packed; | ||
3148 | |||
3134 | struct wmi_pdev_stats { | 3149 | struct wmi_pdev_stats { |
3135 | __le32 chan_nf; /* Channel noise floor */ | 3150 | struct wmi_pdev_stats_base base; |
3136 | __le32 tx_frame_count; /* TX frame count */ | 3151 | struct wmi_pdev_stats_tx tx; |
3137 | __le32 rx_frame_count; /* RX frame count */ | 3152 | struct wmi_pdev_stats_rx rx; |
3138 | __le32 rx_clear_count; /* rx clear count */ | 3153 | struct wmi_pdev_stats_peer peer; |
3139 | __le32 cycle_count; /* cycle count */ | ||
3140 | __le32 phy_err_count; /* Phy error count */ | ||
3141 | __le32 chan_tx_pwr; /* channel tx power */ | ||
3142 | struct wal_dbg_stats wal; /* WAL dbg stats */ | ||
3143 | } __packed; | 3154 | } __packed; |
3144 | 3155 | ||
3145 | struct wmi_10x_pdev_stats { | 3156 | struct wmi_pdev_stats_extra { |
3146 | struct wmi_pdev_stats old; | ||
3147 | __le32 ack_rx_bad; | 3157 | __le32 ack_rx_bad; |
3148 | __le32 rts_bad; | 3158 | __le32 rts_bad; |
3149 | __le32 rts_good; | 3159 | __le32 rts_good; |
@@ -3152,6 +3162,30 @@ struct wmi_10x_pdev_stats { | |||
3152 | __le32 mib_int_count; | 3162 | __le32 mib_int_count; |
3153 | } __packed; | 3163 | } __packed; |
3154 | 3164 | ||
3165 | struct wmi_10x_pdev_stats { | ||
3166 | struct wmi_pdev_stats_base base; | ||
3167 | struct wmi_pdev_stats_tx tx; | ||
3168 | struct wmi_pdev_stats_rx rx; | ||
3169 | struct wmi_pdev_stats_peer peer; | ||
3170 | struct wmi_pdev_stats_extra extra; | ||
3171 | } __packed; | ||
3172 | |||
3173 | struct wmi_pdev_stats_mem { | ||
3174 | __le32 dram_free; | ||
3175 | __le32 iram_free; | ||
3176 | } __packed; | ||
3177 | |||
3178 | struct wmi_10_2_pdev_stats { | ||
3179 | struct wmi_pdev_stats_base base; | ||
3180 | struct wmi_pdev_stats_tx tx; | ||
3181 | __le32 mc_drop; | ||
3182 | struct wmi_pdev_stats_rx rx; | ||
3183 | __le32 pdev_rx_timeout; | ||
3184 | struct wmi_pdev_stats_mem mem; | ||
3185 | struct wmi_pdev_stats_peer peer; | ||
3186 | struct wmi_pdev_stats_extra extra; | ||
3187 | } __packed; | ||
3188 | |||
3155 | /* | 3189 | /* |
3156 | * VDEV statistics | 3190 | * VDEV statistics |
3157 | * TODO: add all VDEV stats here | 3191 | * TODO: add all VDEV stats here |
@@ -3175,6 +3209,32 @@ struct wmi_10x_peer_stats { | |||
3175 | __le32 peer_rx_rate; | 3209 | __le32 peer_rx_rate; |
3176 | } __packed; | 3210 | } __packed; |
3177 | 3211 | ||
3212 | struct wmi_10_2_peer_stats { | ||
3213 | struct wmi_peer_stats old; | ||
3214 | __le32 peer_rx_rate; | ||
3215 | __le32 current_per; | ||
3216 | __le32 retries; | ||
3217 | __le32 tx_rate_count; | ||
3218 | __le32 max_4ms_frame_len; | ||
3219 | __le32 total_sub_frames; | ||
3220 | __le32 tx_bytes; | ||
3221 | __le32 num_pkt_loss_overflow[4]; | ||
3222 | __le32 num_pkt_loss_excess_retry[4]; | ||
3223 | } __packed; | ||
3224 | |||
3225 | struct wmi_10_2_4_peer_stats { | ||
3226 | struct wmi_10_2_peer_stats common; | ||
3227 | __le32 unknown_value; /* FIXME: what is this word? */ | ||
3228 | } __packed; | ||
3229 | |||
3230 | struct wmi_10_2_pdev_ext_stats { | ||
3231 | __le32 rx_rssi_comb; | ||
3232 | __le32 rx_rssi[4]; | ||
3233 | __le32 rx_mcs[10]; | ||
3234 | __le32 tx_mcs[10]; | ||
3235 | __le32 ack_rssi; | ||
3236 | } __packed; | ||
3237 | |||
3178 | struct wmi_vdev_create_cmd { | 3238 | struct wmi_vdev_create_cmd { |
3179 | __le32 vdev_id; | 3239 | __le32 vdev_id; |
3180 | __le32 vdev_type; | 3240 | __le32 vdev_type; |
@@ -4060,6 +4120,30 @@ enum wmi_sta_ps_param_uapsd { | |||
4060 | WMI_STA_PS_UAPSD_AC3_TRIGGER_EN = (1 << 7), | 4120 | WMI_STA_PS_UAPSD_AC3_TRIGGER_EN = (1 << 7), |
4061 | }; | 4121 | }; |
4062 | 4122 | ||
4123 | #define WMI_STA_UAPSD_MAX_INTERVAL_MSEC UINT_MAX | ||
4124 | |||
4125 | struct wmi_sta_uapsd_auto_trig_param { | ||
4126 | __le32 wmm_ac; | ||
4127 | __le32 user_priority; | ||
4128 | __le32 service_interval; | ||
4129 | __le32 suspend_interval; | ||
4130 | __le32 delay_interval; | ||
4131 | }; | ||
4132 | |||
4133 | struct wmi_sta_uapsd_auto_trig_cmd_fixed_param { | ||
4134 | __le32 vdev_id; | ||
4135 | struct wmi_mac_addr peer_macaddr; | ||
4136 | __le32 num_ac; | ||
4137 | }; | ||
4138 | |||
4139 | struct wmi_sta_uapsd_auto_trig_arg { | ||
4140 | u32 wmm_ac; | ||
4141 | u32 user_priority; | ||
4142 | u32 service_interval; | ||
4143 | u32 suspend_interval; | ||
4144 | u32 delay_interval; | ||
4145 | }; | ||
4146 | |||
4063 | enum wmi_sta_powersave_param { | 4147 | enum wmi_sta_powersave_param { |
4064 | /* | 4148 | /* |
4065 | * Controls how frames are retrievd from AP while STA is sleeping | 4149 | * Controls how frames are retrievd from AP while STA is sleeping |
@@ -4430,7 +4514,7 @@ struct wmi_peer_set_q_empty_callback_cmd { | |||
4430 | #define WMI_PEER_SPATIAL_MUX 0x00200000 | 4514 | #define WMI_PEER_SPATIAL_MUX 0x00200000 |
4431 | #define WMI_PEER_VHT 0x02000000 | 4515 | #define WMI_PEER_VHT 0x02000000 |
4432 | #define WMI_PEER_80MHZ 0x04000000 | 4516 | #define WMI_PEER_80MHZ 0x04000000 |
4433 | #define WMI_PEER_PMF 0x08000000 | 4517 | #define WMI_PEER_VHT_2G 0x08000000 |
4434 | 4518 | ||
4435 | /* | 4519 | /* |
4436 | * Peer rate capabilities. | 4520 | * Peer rate capabilities. |
@@ -4581,6 +4665,11 @@ enum wmi_sta_keepalive_method { | |||
4581 | WMI_STA_KEEPALIVE_METHOD_UNSOLICITATED_ARP_RESPONSE = 2, | 4665 | WMI_STA_KEEPALIVE_METHOD_UNSOLICITATED_ARP_RESPONSE = 2, |
4582 | }; | 4666 | }; |
4583 | 4667 | ||
4668 | #define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 | ||
4669 | |||
4670 | /* Firmware crashes if keepalive interval exceeds this limit */ | ||
4671 | #define WMI_STA_KEEPALIVE_INTERVAL_MAX_SECONDS 0xffff | ||
4672 | |||
4584 | /* note: ip4 addresses are in network byte order, i.e. big endian */ | 4673 | /* note: ip4 addresses are in network byte order, i.e. big endian */ |
4585 | struct wmi_sta_keepalive_arp_resp { | 4674 | struct wmi_sta_keepalive_arp_resp { |
4586 | __be32 src_ip4_addr; | 4675 | __be32 src_ip4_addr; |
@@ -4596,6 +4685,16 @@ struct wmi_sta_keepalive_cmd { | |||
4596 | struct wmi_sta_keepalive_arp_resp arp_resp; | 4685 | struct wmi_sta_keepalive_arp_resp arp_resp; |
4597 | } __packed; | 4686 | } __packed; |
4598 | 4687 | ||
4688 | struct wmi_sta_keepalive_arg { | ||
4689 | u32 vdev_id; | ||
4690 | u32 enabled; | ||
4691 | u32 method; | ||
4692 | u32 interval; | ||
4693 | __be32 src_ip4_addr; | ||
4694 | __be32 dest_ip4_addr; | ||
4695 | const u8 dest_mac_addr[ETH_ALEN]; | ||
4696 | }; | ||
4697 | |||
4599 | enum wmi_force_fw_hang_type { | 4698 | enum wmi_force_fw_hang_type { |
4600 | WMI_FORCE_FW_HANG_ASSERT = 1, | 4699 | WMI_FORCE_FW_HANG_ASSERT = 1, |
4601 | WMI_FORCE_FW_HANG_NO_DETECT, | 4700 | WMI_FORCE_FW_HANG_NO_DETECT, |
@@ -4772,16 +4871,22 @@ int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, | |||
4772 | u32 cmd_id); | 4871 | u32 cmd_id); |
4773 | void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); | 4872 | void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); |
4774 | 4873 | ||
4775 | void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src, | 4874 | void ath10k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src, |
4776 | struct ath10k_fw_stats_pdev *dst); | 4875 | struct ath10k_fw_stats_pdev *dst); |
4876 | void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src, | ||
4877 | struct ath10k_fw_stats_pdev *dst); | ||
4878 | void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src, | ||
4879 | struct ath10k_fw_stats_pdev *dst); | ||
4880 | void ath10k_wmi_pull_pdev_stats_extra(const struct wmi_pdev_stats_extra *src, | ||
4881 | struct ath10k_fw_stats_pdev *dst); | ||
4777 | void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, | 4882 | void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, |
4778 | struct ath10k_fw_stats_peer *dst); | 4883 | struct ath10k_fw_stats_peer *dst); |
4779 | void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar, | 4884 | void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar, |
4780 | struct wmi_host_mem_chunks *chunks); | 4885 | struct wmi_host_mem_chunks *chunks); |
4781 | void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn, | 4886 | void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn, |
4782 | const struct wmi_start_scan_arg *arg); | 4887 | const struct wmi_start_scan_arg *arg); |
4783 | void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, | 4888 | void ath10k_wmi_set_wmm_param(struct wmi_wmm_params *params, |
4784 | const struct wmi_wmm_params_arg *arg); | 4889 | const struct wmi_wmm_params_arg *arg); |
4785 | void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, | 4890 | void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, |
4786 | const struct wmi_channel_arg *arg); | 4891 | const struct wmi_channel_arg *arg); |
4787 | int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg); | 4892 | int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg); |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index a3399c4f13a9..b9b651ea9851 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -478,7 +478,7 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | |||
478 | regval = ioread32(reg); | 478 | regval = ioread32(reg); |
479 | iowrite32(regval | val, reg); | 479 | iowrite32(regval | val, reg); |
480 | regval = ioread32(reg); | 480 | regval = ioread32(reg); |
481 | usleep_range(100, 150); | 481 | udelay(100); /* NB: should be atomic */ |
482 | 482 | ||
483 | /* Bring BB/MAC out of reset */ | 483 | /* Bring BB/MAC out of reset */ |
484 | iowrite32(regval & ~val, reg); | 484 | iowrite32(regval & ~val, reg); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 06ab71db6e80..174442beb952 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -1203,24 +1203,41 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) | |||
1203 | static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | 1203 | static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) |
1204 | { | 1204 | { |
1205 | int offset[8] = {0}, total = 0, test; | 1205 | int offset[8] = {0}, total = 0, test; |
1206 | int agc_out, i; | 1206 | int agc_out, i, peak_detect_threshold; |
1207 | 1207 | ||
1208 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) | ||
1209 | peak_detect_threshold = 8; | ||
1210 | else | ||
1211 | peak_detect_threshold = 0; | ||
1212 | |||
1213 | /* | ||
1214 | * Turn off LNA/SW. | ||
1215 | */ | ||
1208 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | 1216 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), |
1209 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1); | 1217 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1); |
1210 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | 1218 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), |
1211 | AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0); | 1219 | AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0); |
1212 | if (is_2g) | ||
1213 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
1214 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0); | ||
1215 | else | ||
1216 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
1217 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0); | ||
1218 | 1220 | ||
1221 | if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9330_11(ah)) { | ||
1222 | if (is_2g) | ||
1223 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
1224 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0); | ||
1225 | else | ||
1226 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
1227 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0); | ||
1228 | } | ||
1229 | |||
1230 | /* | ||
1231 | * Turn off RXON. | ||
1232 | */ | ||
1219 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), | 1233 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), |
1220 | AR_PHY_65NM_RXTX2_RXON_OVR, 0x1); | 1234 | AR_PHY_65NM_RXTX2_RXON_OVR, 0x1); |
1221 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), | 1235 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), |
1222 | AR_PHY_65NM_RXTX2_RXON, 0x0); | 1236 | AR_PHY_65NM_RXTX2_RXON, 0x0); |
1223 | 1237 | ||
1238 | /* | ||
1239 | * Turn on AGC for cal. | ||
1240 | */ | ||
1224 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1241 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
1225 | AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1); | 1242 | AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1); |
1226 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1243 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
@@ -1228,16 +1245,19 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | |||
1228 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1245 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
1229 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1); | 1246 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1); |
1230 | 1247 | ||
1231 | if (AR_SREV_9330_11(ah)) { | 1248 | if (AR_SREV_9330_11(ah)) |
1232 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1249 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
1233 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); | 1250 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); |
1234 | } else { | 1251 | |
1252 | if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | ||
1235 | if (is_2g) | 1253 | if (is_2g) |
1236 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1254 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
1237 | AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0); | 1255 | AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, |
1256 | peak_detect_threshold); | ||
1238 | else | 1257 | else |
1239 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1258 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
1240 | AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0); | 1259 | AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, |
1260 | peak_detect_threshold); | ||
1241 | } | 1261 | } |
1242 | 1262 | ||
1243 | for (i = 6; i > 0; i--) { | 1263 | for (i = 6; i > 0; i--) { |
@@ -1266,10 +1286,19 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | |||
1266 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1286 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
1267 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total); | 1287 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total); |
1268 | 1288 | ||
1289 | /* | ||
1290 | * Turn on LNA. | ||
1291 | */ | ||
1269 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | 1292 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), |
1270 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0); | 1293 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0); |
1294 | /* | ||
1295 | * Turn off RXON. | ||
1296 | */ | ||
1271 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), | 1297 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), |
1272 | AR_PHY_65NM_RXTX2_RXON_OVR, 0); | 1298 | AR_PHY_65NM_RXTX2_RXON_OVR, 0); |
1299 | /* | ||
1300 | * Turn off peak detect calibration. | ||
1301 | */ | ||
1273 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1302 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
1274 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); | 1303 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); |
1275 | } | 1304 | } |
@@ -1611,8 +1640,14 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, | |||
1611 | 1640 | ||
1612 | skip_tx_iqcal: | 1641 | skip_tx_iqcal: |
1613 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { | 1642 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { |
1614 | if (AR_SREV_9330_11(ah)) | 1643 | if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { |
1615 | ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); | 1644 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
1645 | if (!(ah->rxchainmask & (1 << i))) | ||
1646 | continue; | ||
1647 | ar9003_hw_manual_peak_cal(ah, i, | ||
1648 | IS_CHAN_2GHZ(chan)); | ||
1649 | } | ||
1650 | } | ||
1616 | 1651 | ||
1617 | /* | 1652 | /* |
1618 | * For non-AR9550 chips, we just trigger AGC calibration | 1653 | * For non-AR9550 chips, we just trigger AGC calibration |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c index 81c88dd606dc..86bfc9604dca 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c | |||
@@ -17,23 +17,9 @@ | |||
17 | #include <linux/export.h> | 17 | #include <linux/export.h> |
18 | #include "ath9k.h" | 18 | #include "ath9k.h" |
19 | #include "reg.h" | 19 | #include "reg.h" |
20 | #include "reg_wow.h" | ||
20 | #include "hw-ops.h" | 21 | #include "hw-ops.h" |
21 | 22 | ||
22 | const char *ath9k_hw_wow_event_to_string(u32 wow_event) | ||
23 | { | ||
24 | if (wow_event & AH_WOW_MAGIC_PATTERN_EN) | ||
25 | return "Magic pattern"; | ||
26 | if (wow_event & AH_WOW_USER_PATTERN_EN) | ||
27 | return "User pattern"; | ||
28 | if (wow_event & AH_WOW_LINK_CHANGE) | ||
29 | return "Link change"; | ||
30 | if (wow_event & AH_WOW_BEACON_MISS) | ||
31 | return "Beacon miss"; | ||
32 | |||
33 | return "unknown reason"; | ||
34 | } | ||
35 | EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); | ||
36 | |||
37 | static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) | 23 | static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) |
38 | { | 24 | { |
39 | struct ath_common *common = ath9k_hw_common(ah); | 25 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -49,6 +35,15 @@ static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) | |||
49 | return; | 35 | return; |
50 | } | 36 | } |
51 | 37 | ||
38 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
39 | if (!REG_READ(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL)) | ||
40 | REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE); | ||
41 | } else if (AR_SREV_9485(ah)){ | ||
42 | if (!(REG_READ(ah, AR_NDP2_TIMER_MODE) & | ||
43 | AR_GEN_TIMERS2_MODE_ENABLE_MASK)) | ||
44 | REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE); | ||
45 | } | ||
46 | |||
52 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); | 47 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); |
53 | } | 48 | } |
54 | 49 | ||
@@ -67,11 +62,15 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) | |||
67 | /* set the transmit buffer */ | 62 | /* set the transmit buffer */ |
68 | ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); | 63 | ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); |
69 | ctl[1] = 0; | 64 | ctl[1] = 0; |
70 | ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ | ||
71 | ctl[4] = 0; | 65 | ctl[4] = 0; |
72 | ctl[7] = (ah->txchainmask) << 2; | 66 | ctl[7] = (ah->txchainmask) << 2; |
73 | ctl[2] = 0xf << 16; /* tx_tries 0 */ | 67 | ctl[2] = 0xf << 16; /* tx_tries 0 */ |
74 | 68 | ||
69 | if (IS_CHAN_2GHZ(ah->curchan)) | ||
70 | ctl[3] = 0x1b; /* CCK_1M */ | ||
71 | else | ||
72 | ctl[3] = 0xb; /* OFDM_6M */ | ||
73 | |||
75 | for (i = 0; i < KAL_NUM_DESC_WORDS; i++) | 74 | for (i = 0; i < KAL_NUM_DESC_WORDS; i++) |
76 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); | 75 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); |
77 | 76 | ||
@@ -103,21 +102,22 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) | |||
103 | 102 | ||
104 | } | 103 | } |
105 | 104 | ||
106 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | 105 | int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, |
107 | u8 *user_mask, int pattern_count, | 106 | u8 *user_mask, int pattern_count, |
108 | int pattern_len) | 107 | int pattern_len) |
109 | { | 108 | { |
110 | int i; | 109 | int i; |
111 | u32 pattern_val, mask_val; | 110 | u32 pattern_val, mask_val; |
112 | u32 set, clr; | 111 | u32 set, clr; |
113 | 112 | ||
114 | /* FIXME: should check count by querying the hardware capability */ | 113 | if (pattern_count >= ah->wow.max_patterns) |
115 | if (pattern_count >= MAX_NUM_PATTERN) | 114 | return -ENOSPC; |
116 | return; | ||
117 | 115 | ||
118 | REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); | 116 | if (pattern_count < MAX_NUM_PATTERN_LEGACY) |
117 | REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); | ||
118 | else | ||
119 | REG_SET_BIT(ah, AR_MAC_PCU_WOW4, BIT(pattern_count - 8)); | ||
119 | 120 | ||
120 | /* set the registers for pattern */ | ||
121 | for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { | 121 | for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { |
122 | memcpy(&pattern_val, user_pattern, 4); | 122 | memcpy(&pattern_val, user_pattern, 4); |
123 | REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), | 123 | REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), |
@@ -125,49 +125,42 @@ void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | |||
125 | user_pattern += 4; | 125 | user_pattern += 4; |
126 | } | 126 | } |
127 | 127 | ||
128 | /* set the registers for mask */ | ||
129 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { | 128 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { |
130 | memcpy(&mask_val, user_mask, 4); | 129 | memcpy(&mask_val, user_mask, 4); |
131 | REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); | 130 | REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); |
132 | user_mask += 4; | 131 | user_mask += 4; |
133 | } | 132 | } |
134 | 133 | ||
135 | /* set the pattern length to be matched | 134 | if (pattern_count < MAX_NUM_PATTERN_LEGACY) |
136 | * | 135 | ah->wow.wow_event_mask |= |
137 | * AR_WOW_LENGTH1_REG1 | 136 | BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); |
138 | * bit 31:24 pattern 0 length | 137 | else |
139 | * bit 23:16 pattern 1 length | 138 | ah->wow.wow_event_mask2 |= |
140 | * bit 15:8 pattern 2 length | 139 | BIT((pattern_count - 8) + AR_WOW_PAT_FOUND_SHIFT); |
141 | * bit 7:0 pattern 3 length | ||
142 | * | ||
143 | * AR_WOW_LENGTH1_REG2 | ||
144 | * bit 31:24 pattern 4 length | ||
145 | * bit 23:16 pattern 5 length | ||
146 | * bit 15:8 pattern 6 length | ||
147 | * bit 7:0 pattern 7 length | ||
148 | * | ||
149 | * the below logic writes out the new | ||
150 | * pattern length for the corresponding | ||
151 | * pattern_count, while masking out the | ||
152 | * other fields | ||
153 | */ | ||
154 | |||
155 | ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); | ||
156 | 140 | ||
157 | if (pattern_count < 4) { | 141 | if (pattern_count < 4) { |
158 | /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ | ||
159 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | 142 | set = (pattern_len & AR_WOW_LENGTH_MAX) << |
160 | AR_WOW_LEN1_SHIFT(pattern_count); | 143 | AR_WOW_LEN1_SHIFT(pattern_count); |
161 | clr = AR_WOW_LENGTH1_MASK(pattern_count); | 144 | clr = AR_WOW_LENGTH1_MASK(pattern_count); |
162 | REG_RMW(ah, AR_WOW_LENGTH1, set, clr); | 145 | REG_RMW(ah, AR_WOW_LENGTH1, set, clr); |
163 | } else { | 146 | } else if (pattern_count < 8) { |
164 | /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ | ||
165 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | 147 | set = (pattern_len & AR_WOW_LENGTH_MAX) << |
166 | AR_WOW_LEN2_SHIFT(pattern_count); | 148 | AR_WOW_LEN2_SHIFT(pattern_count); |
167 | clr = AR_WOW_LENGTH2_MASK(pattern_count); | 149 | clr = AR_WOW_LENGTH2_MASK(pattern_count); |
168 | REG_RMW(ah, AR_WOW_LENGTH2, set, clr); | 150 | REG_RMW(ah, AR_WOW_LENGTH2, set, clr); |
151 | } else if (pattern_count < 12) { | ||
152 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
153 | AR_WOW_LEN3_SHIFT(pattern_count); | ||
154 | clr = AR_WOW_LENGTH3_MASK(pattern_count); | ||
155 | REG_RMW(ah, AR_WOW_LENGTH3, set, clr); | ||
156 | } else if (pattern_count < MAX_NUM_PATTERN) { | ||
157 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
158 | AR_WOW_LEN4_SHIFT(pattern_count); | ||
159 | clr = AR_WOW_LENGTH4_MASK(pattern_count); | ||
160 | REG_RMW(ah, AR_WOW_LENGTH4, set, clr); | ||
169 | } | 161 | } |
170 | 162 | ||
163 | return 0; | ||
171 | } | 164 | } |
172 | EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); | 165 | EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); |
173 | 166 | ||
@@ -189,7 +182,7 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | |||
189 | * register. This mask will clean it up. | 182 | * register. This mask will clean it up. |
190 | */ | 183 | */ |
191 | 184 | ||
192 | val &= ah->wow_event_mask; | 185 | val &= ah->wow.wow_event_mask; |
193 | 186 | ||
194 | if (val) { | 187 | if (val) { |
195 | if (val & AR_WOW_MAGIC_PAT_FOUND) | 188 | if (val & AR_WOW_MAGIC_PAT_FOUND) |
@@ -233,190 +226,192 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | |||
233 | if (ah->is_pciexpress) | 226 | if (ah->is_pciexpress) |
234 | ath9k_hw_configpcipowersave(ah, false); | 227 | ath9k_hw_configpcipowersave(ah, false); |
235 | 228 | ||
236 | ah->wow_event_mask = 0; | 229 | ah->wow.wow_event_mask = 0; |
237 | 230 | ||
238 | return wow_status; | 231 | return wow_status; |
239 | } | 232 | } |
240 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); | 233 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); |
241 | 234 | ||
242 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) | 235 | static void ath9k_hw_wow_set_arwr_reg(struct ath_hw *ah) |
243 | { | 236 | { |
244 | u32 wow_event_mask; | 237 | u32 wa_reg; |
245 | u32 set, clr; | ||
246 | 238 | ||
247 | /* | 239 | if (!ah->is_pciexpress) |
248 | * wow_event_mask is a mask to the AR_WOW_PATTERN register to | 240 | return; |
249 | * indicate which WoW events we have enabled. The WoW events | ||
250 | * are from the 'pattern_enable' in this function and | ||
251 | * 'pattern_count' of ath9k_hw_wow_apply_pattern() | ||
252 | */ | ||
253 | wow_event_mask = ah->wow_event_mask; | ||
254 | 241 | ||
255 | /* | 242 | /* |
256 | * Untie Power-on-Reset from the PCI-E-Reset. When we are in | 243 | * We need to untie the internal POR (power-on-reset) |
257 | * WOW sleep, we do want the Reset from the PCI-E to disturb | 244 | * to the external PCI-E reset. We also need to tie |
258 | * our hw state | 245 | * the PCI-E Phy reset to the PCI-E reset. |
259 | */ | 246 | */ |
260 | if (ah->is_pciexpress) { | 247 | wa_reg = REG_READ(ah, AR_WA); |
261 | /* | 248 | wa_reg &= ~AR_WA_UNTIE_RESET_EN; |
262 | * we need to untie the internal POR (power-on-reset) | 249 | wa_reg |= AR_WA_RESET_EN; |
263 | * to the external PCI-E reset. We also need to tie | 250 | wa_reg |= AR_WA_POR_SHORT; |
264 | * the PCI-E Phy reset to the PCI-E reset. | ||
265 | */ | ||
266 | set = AR_WA_RESET_EN | AR_WA_POR_SHORT; | ||
267 | clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; | ||
268 | REG_RMW(ah, AR_WA, set, clr); | ||
269 | } | ||
270 | 251 | ||
271 | /* | 252 | REG_WRITE(ah, AR_WA, wa_reg); |
272 | * set the power states appropriately and enable PME | 253 | } |
273 | */ | 254 | |
274 | set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | | 255 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) |
275 | AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; | 256 | { |
257 | u32 wow_event_mask; | ||
258 | u32 keep_alive, magic_pattern, host_pm_ctrl; | ||
259 | |||
260 | wow_event_mask = ah->wow.wow_event_mask; | ||
276 | 261 | ||
277 | /* | 262 | /* |
278 | * set and clear WOW_PME_CLEAR registers for the chip | 263 | * AR_PMCTRL_HOST_PME_EN - Override PME enable in configuration |
264 | * space and allow MAC to generate WoW anyway. | ||
265 | * | ||
266 | * AR_PMCTRL_PWR_PM_CTRL_ENA - ??? | ||
267 | * | ||
268 | * AR_PMCTRL_AUX_PWR_DET - PCI core SYS_AUX_PWR_DET signal, | ||
269 | * needs to be set for WoW in PCI mode. | ||
270 | * | ||
271 | * AR_PMCTRL_WOW_PME_CLR - WoW Clear Signal going to the MAC. | ||
272 | * | ||
273 | * Set the power states appropriately and enable PME. | ||
274 | * | ||
275 | * Set and clear WOW_PME_CLEAR for the chip | ||
279 | * to generate next wow signal. | 276 | * to generate next wow signal. |
280 | */ | 277 | */ |
281 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | 278 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_HOST_PME_EN | |
282 | clr = AR_PMCTRL_WOW_PME_CLR; | 279 | AR_PMCTRL_PWR_PM_CTRL_ENA | |
283 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | 280 | AR_PMCTRL_AUX_PWR_DET | |
281 | AR_PMCTRL_WOW_PME_CLR); | ||
282 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR); | ||
284 | 283 | ||
285 | /* | 284 | /* |
286 | * Setup for: | 285 | * Random Backoff. |
287 | * - beacon misses | 286 | * |
288 | * - magic pattern | 287 | * 31:28 in AR_WOW_PATTERN : Indicates the number of bits used in the |
289 | * - keep alive timeout | 288 | * contention window. For value N, |
290 | * - pattern matching | 289 | * the random backoff will be selected between |
290 | * 0 and (2 ^ N) - 1. | ||
291 | */ | 291 | */ |
292 | REG_SET_BIT(ah, AR_WOW_PATTERN, | ||
293 | AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF)); | ||
292 | 294 | ||
293 | /* | 295 | /* |
294 | * Program default values for pattern backoff, aifs/slot/KAL count, | 296 | * AIFS time, Slot time, Keep Alive count. |
295 | * beacon miss timeout, KAL timeout, etc. | 297 | */ |
298 | REG_SET_BIT(ah, AR_WOW_COUNT, AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | | ||
299 | AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | | ||
300 | AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT)); | ||
301 | /* | ||
302 | * Beacon timeout. | ||
296 | */ | 303 | */ |
297 | set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); | ||
298 | REG_SET_BIT(ah, AR_WOW_PATTERN, set); | ||
299 | |||
300 | set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | | ||
301 | AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | | ||
302 | AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); | ||
303 | REG_SET_BIT(ah, AR_WOW_COUNT, set); | ||
304 | |||
305 | if (pattern_enable & AH_WOW_BEACON_MISS) | 304 | if (pattern_enable & AH_WOW_BEACON_MISS) |
306 | set = AR_WOW_BEACON_TIMO; | 305 | REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO); |
307 | /* We are not using beacon miss, program a large value */ | ||
308 | else | 306 | else |
309 | set = AR_WOW_BEACON_TIMO_MAX; | 307 | REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO_MAX); |
310 | |||
311 | REG_WRITE(ah, AR_WOW_BCN_TIMO, set); | ||
312 | 308 | ||
313 | /* | 309 | /* |
314 | * Keep alive timo in ms except AR9280 | 310 | * Keep alive timeout in ms. |
315 | */ | 311 | */ |
316 | if (!pattern_enable) | 312 | if (!pattern_enable) |
317 | set = AR_WOW_KEEP_ALIVE_NEVER; | 313 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, AR_WOW_KEEP_ALIVE_NEVER); |
318 | else | 314 | else |
319 | set = KAL_TIMEOUT * 32; | 315 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, KAL_TIMEOUT * 32); |
320 | |||
321 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); | ||
322 | 316 | ||
323 | /* | 317 | /* |
324 | * Keep alive delay in us. based on 'power on clock', | 318 | * Keep alive delay in us. |
325 | * therefore in usec | ||
326 | */ | 319 | */ |
327 | set = KAL_DELAY * 1000; | 320 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, KAL_DELAY * 1000); |
328 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); | ||
329 | 321 | ||
330 | /* | 322 | /* |
331 | * Create keep alive pattern to respond to beacons | 323 | * Create keep alive pattern to respond to beacons. |
332 | */ | 324 | */ |
333 | ath9k_wow_create_keep_alive_pattern(ah); | 325 | ath9k_wow_create_keep_alive_pattern(ah); |
334 | 326 | ||
335 | /* | 327 | /* |
336 | * Configure MAC WoW Registers | 328 | * Configure keep alive register. |
337 | */ | 329 | */ |
338 | set = 0; | 330 | keep_alive = REG_READ(ah, AR_WOW_KEEP_ALIVE); |
331 | |||
339 | /* Send keep alive timeouts anyway */ | 332 | /* Send keep alive timeouts anyway */ |
340 | clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; | 333 | keep_alive &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS; |
341 | 334 | ||
342 | if (pattern_enable & AH_WOW_LINK_CHANGE) | 335 | if (pattern_enable & AH_WOW_LINK_CHANGE) { |
336 | keep_alive &= ~AR_WOW_KEEP_ALIVE_FAIL_DIS; | ||
343 | wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; | 337 | wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; |
344 | else | 338 | } else { |
345 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | 339 | keep_alive |= AR_WOW_KEEP_ALIVE_FAIL_DIS; |
340 | } | ||
346 | 341 | ||
347 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | 342 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE, keep_alive); |
348 | REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); | ||
349 | 343 | ||
350 | /* | 344 | /* |
351 | * we are relying on a bmiss failure. ensure we have | 345 | * We are relying on a bmiss failure, ensure we have |
352 | * enough threshold to prevent false positives | 346 | * enough threshold to prevent false positives. |
353 | */ | 347 | */ |
354 | REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, | 348 | REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, |
355 | AR_WOW_BMISSTHRESHOLD); | 349 | AR_WOW_BMISSTHRESHOLD); |
356 | 350 | ||
357 | set = 0; | ||
358 | clr = 0; | ||
359 | |||
360 | if (pattern_enable & AH_WOW_BEACON_MISS) { | 351 | if (pattern_enable & AH_WOW_BEACON_MISS) { |
361 | set = AR_WOW_BEACON_FAIL_EN; | ||
362 | wow_event_mask |= AR_WOW_BEACON_FAIL; | 352 | wow_event_mask |= AR_WOW_BEACON_FAIL; |
353 | REG_SET_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN); | ||
363 | } else { | 354 | } else { |
364 | clr = AR_WOW_BEACON_FAIL_EN; | 355 | REG_CLR_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN); |
365 | } | 356 | } |
366 | 357 | ||
367 | REG_RMW(ah, AR_WOW_BCN_EN, set, clr); | ||
368 | |||
369 | set = 0; | ||
370 | clr = 0; | ||
371 | /* | 358 | /* |
372 | * Enable the magic packet registers | 359 | * Enable the magic packet registers. |
373 | */ | 360 | */ |
361 | magic_pattern = REG_READ(ah, AR_WOW_PATTERN); | ||
362 | magic_pattern |= AR_WOW_MAC_INTR_EN; | ||
363 | |||
374 | if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { | 364 | if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { |
375 | set = AR_WOW_MAGIC_EN; | 365 | magic_pattern |= AR_WOW_MAGIC_EN; |
376 | wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; | 366 | wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; |
377 | } else { | 367 | } else { |
378 | clr = AR_WOW_MAGIC_EN; | 368 | magic_pattern &= ~AR_WOW_MAGIC_EN; |
379 | } | 369 | } |
380 | set |= AR_WOW_MAC_INTR_EN; | ||
381 | REG_RMW(ah, AR_WOW_PATTERN, set, clr); | ||
382 | 370 | ||
371 | REG_WRITE(ah, AR_WOW_PATTERN, magic_pattern); | ||
372 | |||
373 | /* | ||
374 | * Enable pattern matching for packets which are less | ||
375 | * than 256 bytes. | ||
376 | */ | ||
383 | REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, | 377 | REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, |
384 | AR_WOW_PATTERN_SUPPORTED); | 378 | AR_WOW_PATTERN_SUPPORTED); |
385 | 379 | ||
386 | /* | 380 | /* |
387 | * Set the power states appropriately and enable PME | 381 | * Set the power states appropriately and enable PME. |
388 | */ | 382 | */ |
389 | clr = 0; | 383 | host_pm_ctrl = REG_READ(ah, AR_PCIE_PM_CTRL); |
390 | set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | | 384 | host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3 | |
391 | AR_PMCTRL_PWR_PM_CTRL_ENA; | 385 | AR_PMCTRL_HOST_PME_EN | |
386 | AR_PMCTRL_PWR_PM_CTRL_ENA; | ||
387 | host_pm_ctrl &= ~AR_PCIE_PM_CTRL_ENA; | ||
392 | 388 | ||
393 | clr = AR_PCIE_PM_CTRL_ENA; | 389 | if (AR_SREV_9462(ah)) { |
394 | REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); | 390 | /* |
391 | * This is needed to prevent the chip waking up | ||
392 | * the host within 3-4 seconds with certain | ||
393 | * platform/BIOS. | ||
394 | */ | ||
395 | host_pm_ctrl &= ~AR_PMCTRL_PWR_STATE_D1D3; | ||
396 | host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3_REAL; | ||
397 | } | ||
398 | |||
399 | REG_WRITE(ah, AR_PCIE_PM_CTRL, host_pm_ctrl); | ||
395 | 400 | ||
396 | /* | 401 | /* |
397 | * this is needed to prevent the chip waking up | 402 | * Enable sequence number generation when asleep. |
398 | * the host within 3-4 seconds with certain | ||
399 | * platform/BIOS. The fix is to enable | ||
400 | * D1 & D3 to match original definition and | ||
401 | * also match the OTP value. Anyway this | ||
402 | * is more related to SW WOW. | ||
403 | */ | 403 | */ |
404 | clr = AR_PMCTRL_PWR_STATE_D1D3; | 404 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); |
405 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | ||
406 | 405 | ||
407 | set = AR_PMCTRL_PWR_STATE_D1D3_REAL; | 406 | /* To bring down WOW power low margin */ |
408 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | 407 | REG_SET_BIT(ah, AR_PCIE_PHY_REG3, BIT(13)); |
409 | 408 | ||
410 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); | 409 | ath9k_hw_wow_set_arwr_reg(ah); |
411 | 410 | ||
412 | /* to bring down WOW power low margin */ | ||
413 | set = BIT(13); | ||
414 | REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); | ||
415 | /* HW WoW */ | 411 | /* HW WoW */ |
416 | clr = BIT(5); | 412 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, BIT(5)); |
417 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); | ||
418 | 413 | ||
419 | ath9k_hw_set_powermode_wow_sleep(ah); | 414 | ath9k_hw_set_powermode_wow_sleep(ah); |
420 | ah->wow_event_mask = wow_event_mask; | 415 | ah->wow.wow_event_mask = wow_event_mask; |
421 | } | 416 | } |
422 | EXPORT_SYMBOL(ath9k_hw_wow_enable); | 417 | EXPORT_SYMBOL(ath9k_hw_wow_enable); |
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 159cc6fd2362..6fc0d07e5ec6 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h | |||
@@ -358,7 +358,7 @@ static const u32 qca953x_1p0_baseband_postamble[][5] = { | |||
358 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 358 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
359 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 359 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
360 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 360 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
361 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, | 361 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10820, 0xcfa10820}, |
362 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | 362 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, |
363 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 363 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
364 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 364 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
@@ -378,7 +378,7 @@ static const u32 qca953x_1p0_baseband_postamble[][5] = { | |||
378 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | 378 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, |
379 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 379 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, |
380 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 380 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, |
381 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 381 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, |
382 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, | 382 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, |
383 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, | 383 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, |
384 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 384 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h index fd6a84ccd49e..148562addd38 100644 --- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h | |||
@@ -63,7 +63,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = { | |||
63 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 63 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
64 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 64 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
65 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 65 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
66 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, | 66 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10820, 0xcfa10820}, |
67 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | 67 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, |
68 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 68 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
69 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 69 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
@@ -83,7 +83,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = { | |||
83 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | 83 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, |
84 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 84 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, |
85 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 85 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, |
86 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 86 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, |
87 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, | 87 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, |
88 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, | 88 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, |
89 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 89 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1a9fe0983a6b..0f8e9464e4ab 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -34,7 +34,7 @@ struct ath_vif; | |||
34 | 34 | ||
35 | extern struct ieee80211_ops ath9k_ops; | 35 | extern struct ieee80211_ops ath9k_ops; |
36 | extern int ath9k_modparam_nohwcrypt; | 36 | extern int ath9k_modparam_nohwcrypt; |
37 | extern int led_blink; | 37 | extern int ath9k_led_blink; |
38 | extern bool is_ath9k_unloaded; | 38 | extern bool is_ath9k_unloaded; |
39 | extern int ath9k_use_chanctx; | 39 | extern int ath9k_use_chanctx; |
40 | 40 | ||
@@ -830,14 +830,9 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) | |||
830 | /* Wake on Wireless LAN */ | 830 | /* Wake on Wireless LAN */ |
831 | /************************/ | 831 | /************************/ |
832 | 832 | ||
833 | struct ath9k_wow_pattern { | ||
834 | u8 pattern_bytes[MAX_PATTERN_SIZE]; | ||
835 | u8 mask_bytes[MAX_PATTERN_SIZE]; | ||
836 | u32 pattern_len; | ||
837 | }; | ||
838 | |||
839 | #ifdef CONFIG_ATH9K_WOW | 833 | #ifdef CONFIG_ATH9K_WOW |
840 | void ath9k_init_wow(struct ieee80211_hw *hw); | 834 | void ath9k_init_wow(struct ieee80211_hw *hw); |
835 | void ath9k_deinit_wow(struct ieee80211_hw *hw); | ||
841 | int ath9k_suspend(struct ieee80211_hw *hw, | 836 | int ath9k_suspend(struct ieee80211_hw *hw, |
842 | struct cfg80211_wowlan *wowlan); | 837 | struct cfg80211_wowlan *wowlan); |
843 | int ath9k_resume(struct ieee80211_hw *hw); | 838 | int ath9k_resume(struct ieee80211_hw *hw); |
@@ -846,6 +841,9 @@ void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled); | |||
846 | static inline void ath9k_init_wow(struct ieee80211_hw *hw) | 841 | static inline void ath9k_init_wow(struct ieee80211_hw *hw) |
847 | { | 842 | { |
848 | } | 843 | } |
844 | static inline void ath9k_deinit_wow(struct ieee80211_hw *hw) | ||
845 | { | ||
846 | } | ||
849 | static inline int ath9k_suspend(struct ieee80211_hw *hw, | 847 | static inline int ath9k_suspend(struct ieee80211_hw *hw, |
850 | struct cfg80211_wowlan *wowlan) | 848 | struct cfg80211_wowlan *wowlan) |
851 | { | 849 | { |
@@ -1039,9 +1037,8 @@ struct ath_softc { | |||
1039 | s16 tx99_power; | 1037 | s16 tx99_power; |
1040 | 1038 | ||
1041 | #ifdef CONFIG_ATH9K_WOW | 1039 | #ifdef CONFIG_ATH9K_WOW |
1042 | atomic_t wow_got_bmiss_intr; | ||
1043 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ | ||
1044 | u32 wow_intr_before_sleep; | 1040 | u32 wow_intr_before_sleep; |
1041 | bool force_wow; | ||
1045 | #endif | 1042 | #endif |
1046 | }; | 1043 | }; |
1047 | 1044 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index ec93ddf0863a..5cee231cca1f 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c | |||
@@ -582,7 +582,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = { | |||
582 | 582 | ||
583 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) | 583 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) |
584 | { | 584 | { |
585 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { | 585 | if (config_enabled(CONFIG_ATH9K_DEBUGFS)) { |
586 | relay_close(spec_priv->rfs_chan_spec_scan); | 586 | relay_close(spec_priv->rfs_chan_spec_scan); |
587 | spec_priv->rfs_chan_spec_scan = NULL; | 587 | spec_priv->rfs_chan_spec_scan = NULL; |
588 | } | 588 | } |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index dd5d3914799b..50a2e0ac3b8b 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -1043,6 +1043,69 @@ static const struct file_operations fops_ackto = { | |||
1043 | }; | 1043 | }; |
1044 | #endif | 1044 | #endif |
1045 | 1045 | ||
1046 | #ifdef CONFIG_ATH9K_WOW | ||
1047 | |||
1048 | static ssize_t read_file_wow(struct file *file, char __user *user_buf, | ||
1049 | size_t count, loff_t *ppos) | ||
1050 | { | ||
1051 | struct ath_softc *sc = file->private_data; | ||
1052 | unsigned int len = 0, size = 32; | ||
1053 | ssize_t retval; | ||
1054 | char *buf; | ||
1055 | |||
1056 | buf = kzalloc(size, GFP_KERNEL); | ||
1057 | if (!buf) | ||
1058 | return -ENOMEM; | ||
1059 | |||
1060 | len += scnprintf(buf + len, size - len, "WOW: %s\n", | ||
1061 | sc->force_wow ? "ENABLED" : "DISABLED"); | ||
1062 | |||
1063 | if (len > size) | ||
1064 | len = size; | ||
1065 | |||
1066 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1067 | kfree(buf); | ||
1068 | |||
1069 | return retval; | ||
1070 | } | ||
1071 | |||
1072 | static ssize_t write_file_wow(struct file *file, const char __user *user_buf, | ||
1073 | size_t count, loff_t *ppos) | ||
1074 | { | ||
1075 | struct ath_softc *sc = file->private_data; | ||
1076 | unsigned long val; | ||
1077 | char buf[32]; | ||
1078 | ssize_t len; | ||
1079 | |||
1080 | len = min(count, sizeof(buf) - 1); | ||
1081 | if (copy_from_user(buf, user_buf, len)) | ||
1082 | return -EFAULT; | ||
1083 | |||
1084 | buf[len] = '\0'; | ||
1085 | if (kstrtoul(buf, 0, &val)) | ||
1086 | return -EINVAL; | ||
1087 | |||
1088 | if (val != 1) | ||
1089 | return -EINVAL; | ||
1090 | |||
1091 | if (!sc->force_wow) { | ||
1092 | sc->force_wow = true; | ||
1093 | ath9k_init_wow(sc->hw); | ||
1094 | } | ||
1095 | |||
1096 | return count; | ||
1097 | } | ||
1098 | |||
1099 | static const struct file_operations fops_wow = { | ||
1100 | .read = read_file_wow, | ||
1101 | .write = write_file_wow, | ||
1102 | .open = simple_open, | ||
1103 | .owner = THIS_MODULE, | ||
1104 | .llseek = default_llseek, | ||
1105 | }; | ||
1106 | |||
1107 | #endif | ||
1108 | |||
1046 | static ssize_t read_file_tpc(struct file *file, char __user *user_buf, | 1109 | static ssize_t read_file_tpc(struct file *file, char __user *user_buf, |
1047 | size_t count, loff_t *ppos) | 1110 | size_t count, loff_t *ppos) |
1048 | { | 1111 | { |
@@ -1313,6 +1376,11 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1313 | &fops_btcoex); | 1376 | &fops_btcoex); |
1314 | #endif | 1377 | #endif |
1315 | 1378 | ||
1379 | #ifdef CONFIG_ATH9K_WOW | ||
1380 | debugfs_create_file("wow", S_IRUSR | S_IWUSR, | ||
1381 | sc->debug.debugfs_phy, sc, &fops_wow); | ||
1382 | #endif | ||
1383 | |||
1316 | #ifdef CONFIG_ATH9K_DYNACK | 1384 | #ifdef CONFIG_ATH9K_DYNACK |
1317 | debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1385 | debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
1318 | sc, &fops_ackto); | 1386 | sc, &fops_ackto); |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 2fef7a480fec..da344b27326c 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -49,7 +49,7 @@ void ath_init_leds(struct ath_softc *sc) | |||
49 | if (AR_SREV_9100(sc->sc_ah)) | 49 | if (AR_SREV_9100(sc->sc_ah)) |
50 | return; | 50 | return; |
51 | 51 | ||
52 | if (!led_blink) | 52 | if (!ath9k_led_blink) |
53 | sc->led_cdev.default_trigger = | 53 | sc->led_cdev.default_trigger = |
54 | ieee80211_get_radio_led_name(sc->hw); | 54 | ieee80211_get_radio_led_name(sc->hw); |
55 | 55 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index c43fec51b8ec..300d3671d0ef 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -45,7 +45,7 @@ | |||
45 | extern struct ieee80211_ops ath9k_htc_ops; | 45 | extern struct ieee80211_ops ath9k_htc_ops; |
46 | extern int htc_modparam_nohwcrypt; | 46 | extern int htc_modparam_nohwcrypt; |
47 | #ifdef CONFIG_MAC80211_LEDS | 47 | #ifdef CONFIG_MAC80211_LEDS |
48 | extern int led_blink; | 48 | extern int ath9k_htc_led_blink; |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | enum htc_phymode { | 51 | enum htc_phymode { |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 998b558d4126..2aabcbdaba4e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -279,7 +279,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) | |||
279 | else | 279 | else |
280 | priv->ah->led_pin = ATH_LED_PIN_DEF; | 280 | priv->ah->led_pin = ATH_LED_PIN_DEF; |
281 | 281 | ||
282 | if (!led_blink) | 282 | if (!ath9k_htc_led_blink) |
283 | priv->led_cdev.default_trigger = | 283 | priv->led_cdev.default_trigger = |
284 | ieee80211_get_radio_led_name(priv->hw); | 284 | ieee80211_get_radio_led_name(priv->hw); |
285 | 285 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 947012757f81..fd229409f676 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -39,8 +39,8 @@ module_param_named(ps_enable, ath9k_ps_enable, int, 0444); | |||
39 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); | 39 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); |
40 | 40 | ||
41 | #ifdef CONFIG_MAC80211_LEDS | 41 | #ifdef CONFIG_MAC80211_LEDS |
42 | int led_blink = 1; | 42 | int ath9k_htc_led_blink = 1; |
43 | module_param_named(blink, led_blink, int, 0444); | 43 | module_param_named(blink, ath9k_htc_led_blink, int, 0444); |
44 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | 44 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); |
45 | 45 | ||
46 | static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { | 46 | static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 82d8f32a3461..60aa8d71e753 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2544,13 +2544,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2544 | pCap->hw_caps |= ATH9K_HW_CAP_RTT; | 2544 | pCap->hw_caps |= ATH9K_HW_CAP_RTT; |
2545 | } | 2545 | } |
2546 | 2546 | ||
2547 | if (AR_SREV_9462(ah)) | ||
2548 | pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE; | ||
2549 | |||
2550 | if (AR_SREV_9300_20_OR_LATER(ah) && | 2547 | if (AR_SREV_9300_20_OR_LATER(ah) && |
2551 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | 2548 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) |
2552 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; | 2549 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; |
2553 | 2550 | ||
2551 | #ifdef CONFIG_ATH9K_WOW | ||
2552 | if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah)) | ||
2553 | ah->wow.max_patterns = MAX_NUM_PATTERN; | ||
2554 | else | ||
2555 | ah->wow.max_patterns = MAX_NUM_PATTERN_LEGACY; | ||
2556 | #endif | ||
2557 | |||
2554 | return 0; | 2558 | return 0; |
2555 | } | 2559 | } |
2556 | 2560 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 450704e49f03..e82e570de330 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -199,12 +199,13 @@ | |||
199 | #define KAL_NUM_DESC_WORDS 12 | 199 | #define KAL_NUM_DESC_WORDS 12 |
200 | #define KAL_ANTENNA_MODE 1 | 200 | #define KAL_ANTENNA_MODE 1 |
201 | #define KAL_TO_DS 1 | 201 | #define KAL_TO_DS 1 |
202 | #define KAL_DELAY 4 /*delay of 4ms between 2 KAL frames */ | 202 | #define KAL_DELAY 4 /* delay of 4ms between 2 KAL frames */ |
203 | #define KAL_TIMEOUT 900 | 203 | #define KAL_TIMEOUT 900 |
204 | 204 | ||
205 | #define MAX_PATTERN_SIZE 256 | 205 | #define MAX_PATTERN_SIZE 256 |
206 | #define MAX_PATTERN_MASK_SIZE 32 | 206 | #define MAX_PATTERN_MASK_SIZE 32 |
207 | #define MAX_NUM_PATTERN 8 | 207 | #define MAX_NUM_PATTERN 16 |
208 | #define MAX_NUM_PATTERN_LEGACY 8 | ||
208 | #define MAX_NUM_USER_PATTERN 6 /* deducting the disassociate and | 209 | #define MAX_NUM_USER_PATTERN 6 /* deducting the disassociate and |
209 | deauthenticate packets */ | 210 | deauthenticate packets */ |
210 | 211 | ||
@@ -248,12 +249,10 @@ enum ath9k_hw_caps { | |||
248 | #ifdef CONFIG_ATH9K_PCOEM | 249 | #ifdef CONFIG_ATH9K_PCOEM |
249 | ATH9K_HW_CAP_RTT = BIT(14), | 250 | ATH9K_HW_CAP_RTT = BIT(14), |
250 | ATH9K_HW_CAP_MCI = BIT(15), | 251 | ATH9K_HW_CAP_MCI = BIT(15), |
251 | ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16), | ||
252 | ATH9K_HW_CAP_BT_ANT_DIV = BIT(17), | 252 | ATH9K_HW_CAP_BT_ANT_DIV = BIT(17), |
253 | #else | 253 | #else |
254 | ATH9K_HW_CAP_RTT = 0, | 254 | ATH9K_HW_CAP_RTT = 0, |
255 | ATH9K_HW_CAP_MCI = 0, | 255 | ATH9K_HW_CAP_MCI = 0, |
256 | ATH9K_HW_WOW_DEVICE_CAPABLE = 0, | ||
257 | ATH9K_HW_CAP_BT_ANT_DIV = 0, | 256 | ATH9K_HW_CAP_BT_ANT_DIV = 0, |
258 | #endif | 257 | #endif |
259 | ATH9K_HW_CAP_DFS = BIT(18), | 258 | ATH9K_HW_CAP_DFS = BIT(18), |
@@ -272,6 +271,12 @@ enum ath9k_hw_caps { | |||
272 | * of those types. | 271 | * of those types. |
273 | */ | 272 | */ |
274 | 273 | ||
274 | struct ath9k_hw_wow { | ||
275 | u32 wow_event_mask; | ||
276 | u32 wow_event_mask2; | ||
277 | u8 max_patterns; | ||
278 | }; | ||
279 | |||
275 | struct ath9k_hw_capabilities { | 280 | struct ath9k_hw_capabilities { |
276 | u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ | 281 | u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ |
277 | u16 rts_aggr_limit; | 282 | u16 rts_aggr_limit; |
@@ -930,7 +935,7 @@ struct ath_hw { | |||
930 | u32 ent_mode; | 935 | u32 ent_mode; |
931 | 936 | ||
932 | #ifdef CONFIG_ATH9K_WOW | 937 | #ifdef CONFIG_ATH9K_WOW |
933 | u32 wow_event_mask; | 938 | struct ath9k_hw_wow wow; |
934 | #endif | 939 | #endif |
935 | bool is_clk_25mhz; | 940 | bool is_clk_25mhz; |
936 | int (*get_mac_revision)(void); | 941 | int (*get_mac_revision)(void); |
@@ -1148,23 +1153,19 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) | |||
1148 | 1153 | ||
1149 | 1154 | ||
1150 | #ifdef CONFIG_ATH9K_WOW | 1155 | #ifdef CONFIG_ATH9K_WOW |
1151 | const char *ath9k_hw_wow_event_to_string(u32 wow_event); | 1156 | int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, |
1152 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | 1157 | u8 *user_mask, int pattern_count, |
1153 | u8 *user_mask, int pattern_count, | 1158 | int pattern_len); |
1154 | int pattern_len); | ||
1155 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah); | 1159 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah); |
1156 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable); | 1160 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable); |
1157 | #else | 1161 | #else |
1158 | static inline const char *ath9k_hw_wow_event_to_string(u32 wow_event) | 1162 | static inline int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, |
1159 | { | 1163 | u8 *user_pattern, |
1160 | return NULL; | 1164 | u8 *user_mask, |
1161 | } | 1165 | int pattern_count, |
1162 | static inline void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, | 1166 | int pattern_len) |
1163 | u8 *user_pattern, | ||
1164 | u8 *user_mask, | ||
1165 | int pattern_count, | ||
1166 | int pattern_len) | ||
1167 | { | 1167 | { |
1168 | return 0; | ||
1168 | } | 1169 | } |
1169 | static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | 1170 | static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) |
1170 | { | 1171 | { |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d1c39346b264..6c6e88495394 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -45,8 +45,8 @@ int ath9k_modparam_nohwcrypt; | |||
45 | module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); | 45 | module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); |
46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | 46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); |
47 | 47 | ||
48 | int led_blink; | 48 | int ath9k_led_blink; |
49 | module_param_named(blink, led_blink, int, 0444); | 49 | module_param_named(blink, ath9k_led_blink, int, 0444); |
50 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | 50 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); |
51 | 51 | ||
52 | static int ath9k_btcoex_enable; | 52 | static int ath9k_btcoex_enable; |
@@ -996,6 +996,7 @@ void ath9k_deinit_device(struct ath_softc *sc) | |||
996 | ath9k_ps_restore(sc); | 996 | ath9k_ps_restore(sc); |
997 | 997 | ||
998 | ath9k_deinit_debug(sc); | 998 | ath9k_deinit_debug(sc); |
999 | ath9k_deinit_wow(hw); | ||
999 | ieee80211_unregister_hw(hw); | 1000 | ieee80211_unregister_hw(hw); |
1000 | ath_rx_cleanup(sc); | 1001 | ath_rx_cleanup(sc); |
1001 | ath9k_deinit_softc(sc); | 1002 | ath9k_deinit_softc(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 62b0bf4fdf6b..9ede991b8d76 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -555,15 +555,6 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
555 | (status & ATH9K_INT_BB_WATCHDOG)) | 555 | (status & ATH9K_INT_BB_WATCHDOG)) |
556 | goto chip_reset; | 556 | goto chip_reset; |
557 | 557 | ||
558 | #ifdef CONFIG_ATH9K_WOW | ||
559 | if (status & ATH9K_INT_BMISS) { | ||
560 | if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { | ||
561 | atomic_inc(&sc->wow_got_bmiss_intr); | ||
562 | atomic_dec(&sc->wow_sleep_proc_intr); | ||
563 | } | ||
564 | } | ||
565 | #endif | ||
566 | |||
567 | if (status & ATH9K_INT_SWBA) | 558 | if (status & ATH9K_INT_SWBA) |
568 | tasklet_schedule(&sc->bcon_tasklet); | 559 | tasklet_schedule(&sc->bcon_tasklet); |
569 | 560 | ||
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index cc5c6810f32e..e6fef1be9977 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -998,9 +998,12 @@ static int ath_pci_suspend(struct device *device) | |||
998 | struct pci_dev *pdev = to_pci_dev(device); | 998 | struct pci_dev *pdev = to_pci_dev(device); |
999 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 999 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
1000 | struct ath_softc *sc = hw->priv; | 1000 | struct ath_softc *sc = hw->priv; |
1001 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1001 | 1002 | ||
1002 | if (sc->wow_enabled) | 1003 | if (test_bit(ATH_OP_WOW_ENABLED, &common->op_flags)) { |
1004 | dev_info(&pdev->dev, "WOW is enabled, bypassing PCI suspend\n"); | ||
1003 | return 0; | 1005 | return 0; |
1006 | } | ||
1004 | 1007 | ||
1005 | /* The device has to be moved to FULLSLEEP forcibly. | 1008 | /* The device has to be moved to FULLSLEEP forcibly. |
1006 | * Otherwise the chip never moved to full sleep, | 1009 | * Otherwise the chip never moved to full sleep, |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index eb2bb0db297f..9587ec655680 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -900,10 +900,13 @@ | |||
900 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) | 900 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) |
901 | #define AR_SREV_9565(_ah) \ | 901 | #define AR_SREV_9565(_ah) \ |
902 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) | 902 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) |
903 | #define AR_SREV_9003_PCOEM(_ah) \ | ||
904 | (AR_SREV_9462(_ah) || AR_SREV_9485(_ah) || AR_SREV_9565(_ah)) | ||
903 | #else | 905 | #else |
904 | #define AR_SREV_9462(_ah) 0 | 906 | #define AR_SREV_9462(_ah) 0 |
905 | #define AR_SREV_9485(_ah) 0 | 907 | #define AR_SREV_9485(_ah) 0 |
906 | #define AR_SREV_9565(_ah) 0 | 908 | #define AR_SREV_9565(_ah) 0 |
909 | #define AR_SREV_9003_PCOEM(_ah) 0 | ||
907 | #endif | 910 | #endif |
908 | 911 | ||
909 | #define AR_SREV_9485_11_OR_LATER(_ah) \ | 912 | #define AR_SREV_9485_11_OR_LATER(_ah) \ |
@@ -1880,6 +1883,7 @@ enum { | |||
1880 | #define AR_FIRST_NDP_TIMER 7 | 1883 | #define AR_FIRST_NDP_TIMER 7 |
1881 | #define AR_NDP2_PERIOD 0x81a0 | 1884 | #define AR_NDP2_PERIOD 0x81a0 |
1882 | #define AR_NDP2_TIMER_MODE 0x81c0 | 1885 | #define AR_NDP2_TIMER_MODE 0x81c0 |
1886 | #define AR_GEN_TIMERS2_MODE_ENABLE_MASK 0x000000FF | ||
1883 | 1887 | ||
1884 | #define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2)) | 1888 | #define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2)) |
1885 | #define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0) | 1889 | #define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0) |
@@ -1975,6 +1979,7 @@ enum { | |||
1975 | 1979 | ||
1976 | #define AR_DIRECT_CONNECT 0x83a0 | 1980 | #define AR_DIRECT_CONNECT 0x83a0 |
1977 | #define AR_DC_AP_STA_EN 0x00000001 | 1981 | #define AR_DC_AP_STA_EN 0x00000001 |
1982 | #define AR_DC_TSF2_ENABLE 0x00000001 | ||
1978 | 1983 | ||
1979 | #define AR_AES_MUTE_MASK0 0x805c | 1984 | #define AR_AES_MUTE_MASK0 0x805c |
1980 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF | 1985 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF |
@@ -2007,126 +2012,6 @@ enum { | |||
2007 | 2012 | ||
2008 | #define AR_WOW_BEACON_TIMO_MAX 0xffffffff | 2013 | #define AR_WOW_BEACON_TIMO_MAX 0xffffffff |
2009 | 2014 | ||
2010 | /* | ||
2011 | * MAC WoW Registers | ||
2012 | */ | ||
2013 | |||
2014 | #define AR_WOW_PATTERN 0x825C | ||
2015 | #define AR_WOW_COUNT 0x8260 | ||
2016 | #define AR_WOW_BCN_EN 0x8270 | ||
2017 | #define AR_WOW_BCN_TIMO 0x8274 | ||
2018 | #define AR_WOW_KEEP_ALIVE_TIMO 0x8278 | ||
2019 | #define AR_WOW_KEEP_ALIVE 0x827c | ||
2020 | #define AR_WOW_US_SCALAR 0x8284 | ||
2021 | #define AR_WOW_KEEP_ALIVE_DELAY 0x8288 | ||
2022 | #define AR_WOW_PATTERN_MATCH 0x828c | ||
2023 | #define AR_WOW_PATTERN_OFF1 0x8290 /* pattern bytes 0 -> 3 */ | ||
2024 | #define AR_WOW_PATTERN_OFF2 0x8294 /* pattern bytes 4 -> 7 */ | ||
2025 | |||
2026 | /* for AR9285 or later version of chips */ | ||
2027 | #define AR_WOW_EXACT 0x829c | ||
2028 | #define AR_WOW_LENGTH1 0x8360 | ||
2029 | #define AR_WOW_LENGTH2 0X8364 | ||
2030 | /* register to enable match for less than 256 bytes packets */ | ||
2031 | #define AR_WOW_PATTERN_MATCH_LT_256B 0x8368 | ||
2032 | |||
2033 | #define AR_SW_WOW_CONTROL 0x20018 | ||
2034 | #define AR_SW_WOW_ENABLE 0x1 | ||
2035 | #define AR_SWITCH_TO_REFCLK 0x2 | ||
2036 | #define AR_RESET_CONTROL 0x4 | ||
2037 | #define AR_RESET_VALUE_MASK 0x8 | ||
2038 | #define AR_HW_WOW_DISABLE 0x10 | ||
2039 | #define AR_CLR_MAC_INTERRUPT 0x20 | ||
2040 | #define AR_CLR_KA_INTERRUPT 0x40 | ||
2041 | |||
2042 | /* AR_WOW_PATTERN register values */ | ||
2043 | #define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 28) /* in usecs */ | ||
2044 | #define AR_WOW_MAC_INTR_EN 0x00040000 | ||
2045 | #define AR_WOW_MAGIC_EN 0x00010000 | ||
2046 | #define AR_WOW_PATTERN_EN(x) (x & 0xff) | ||
2047 | #define AR_WOW_PAT_FOUND_SHIFT 8 | ||
2048 | #define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT)) | ||
2049 | #define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT) | ||
2050 | #define AR_WOW_MAGIC_PAT_FOUND 0x00020000 | ||
2051 | #define AR_WOW_MAC_INTR 0x00080000 | ||
2052 | #define AR_WOW_KEEP_ALIVE_FAIL 0x00100000 | ||
2053 | #define AR_WOW_BEACON_FAIL 0x00200000 | ||
2054 | |||
2055 | #define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | \ | ||
2056 | AR_WOW_MAGIC_PAT_FOUND | \ | ||
2057 | AR_WOW_KEEP_ALIVE_FAIL | \ | ||
2058 | AR_WOW_BEACON_FAIL)) | ||
2059 | #define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \ | ||
2060 | AR_WOW_MAGIC_EN | \ | ||
2061 | AR_WOW_MAC_INTR_EN | \ | ||
2062 | AR_WOW_BEACON_FAIL | \ | ||
2063 | AR_WOW_KEEP_ALIVE_FAIL)) | ||
2064 | |||
2065 | /* AR_WOW_COUNT register values */ | ||
2066 | #define AR_WOW_AIFS_CNT(x) (x & 0xff) | ||
2067 | #define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8) | ||
2068 | #define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16) | ||
2069 | |||
2070 | /* AR_WOW_BCN_EN register */ | ||
2071 | #define AR_WOW_BEACON_FAIL_EN 0x00000001 | ||
2072 | |||
2073 | /* AR_WOW_BCN_TIMO rgister */ | ||
2074 | #define AR_WOW_BEACON_TIMO 0x40000000 /* valid if BCN_EN is set */ | ||
2075 | |||
2076 | /* AR_WOW_KEEP_ALIVE_TIMO register */ | ||
2077 | #define AR_WOW_KEEP_ALIVE_TIMO_VALUE | ||
2078 | #define AR_WOW_KEEP_ALIVE_NEVER 0xffffffff | ||
2079 | |||
2080 | /* AR_WOW_KEEP_ALIVE register */ | ||
2081 | #define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001 | ||
2082 | #define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002 | ||
2083 | |||
2084 | /* AR_WOW_KEEP_ALIVE_DELAY register */ | ||
2085 | #define AR_WOW_KEEP_ALIVE_DELAY_VALUE 0x000003e8 /* 1 msec */ | ||
2086 | |||
2087 | |||
2088 | /* | ||
2089 | * keep it long for beacon workaround - ensure no false alarm | ||
2090 | */ | ||
2091 | #define AR_WOW_BMISSTHRESHOLD 0x20 | ||
2092 | |||
2093 | /* AR_WOW_PATTERN_MATCH register */ | ||
2094 | #define AR_WOW_PAT_END_OF_PKT(x) (x & 0xf) | ||
2095 | #define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8) | ||
2096 | |||
2097 | /* | ||
2098 | * default values for Wow Configuration for backoff, aifs, slot, keep-alive | ||
2099 | * to be programmed into various registers. | ||
2100 | */ | ||
2101 | #define AR_WOW_PAT_BACKOFF 0x00000004 /* AR_WOW_PATTERN_REG */ | ||
2102 | #define AR_WOW_CNT_AIFS_CNT 0x00000022 /* AR_WOW_COUNT_REG */ | ||
2103 | #define AR_WOW_CNT_SLOT_CNT 0x00000009 /* AR_WOW_COUNT_REG */ | ||
2104 | /* | ||
2105 | * Keepalive count applicable for AR9280 2.0 and above. | ||
2106 | */ | ||
2107 | #define AR_WOW_CNT_KA_CNT 0x00000008 /* AR_WOW_COUNT register */ | ||
2108 | |||
2109 | /* WoW - Transmit buffer for keep alive frames */ | ||
2110 | #define AR_WOW_TRANSMIT_BUFFER 0xe000 /* E000 - EFFC */ | ||
2111 | |||
2112 | #define AR_WOW_TXBUF(i) (AR_WOW_TRANSMIT_BUFFER + ((i) << 2)) | ||
2113 | |||
2114 | #define AR_WOW_KA_DESC_WORD2 0xe000 | ||
2115 | |||
2116 | #define AR_WOW_KA_DATA_WORD0 0xe030 | ||
2117 | |||
2118 | /* WoW Transmit Buffer for patterns */ | ||
2119 | #define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8)) | ||
2120 | #define AR_WOW_TB_MASK(i) (0xec00 + (i << 5)) | ||
2121 | |||
2122 | /* Currently Pattern 0-7 are supported - so bit 0-7 are set */ | ||
2123 | #define AR_WOW_PATTERN_SUPPORTED 0xff | ||
2124 | #define AR_WOW_LENGTH_MAX 0xff | ||
2125 | #define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3) | ||
2126 | #define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i)) | ||
2127 | #define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3) | ||
2128 | #define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i)) | ||
2129 | |||
2130 | #define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ | 2015 | #define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ |
2131 | #define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ | 2016 | #define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ |
2132 | 2017 | ||
diff --git a/drivers/net/wireless/ath/ath9k/reg_wow.h b/drivers/net/wireless/ath/ath9k/reg_wow.h new file mode 100644 index 000000000000..3abfca56ca58 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/reg_wow.h | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 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 REG_WOW_H | ||
18 | #define REG_WOW_H | ||
19 | |||
20 | #define AR_WOW_PATTERN 0x825C | ||
21 | #define AR_WOW_COUNT 0x8260 | ||
22 | #define AR_WOW_BCN_EN 0x8270 | ||
23 | #define AR_WOW_BCN_TIMO 0x8274 | ||
24 | #define AR_WOW_KEEP_ALIVE_TIMO 0x8278 | ||
25 | #define AR_WOW_KEEP_ALIVE 0x827c | ||
26 | #define AR_WOW_KEEP_ALIVE_DELAY 0x8288 | ||
27 | #define AR_WOW_PATTERN_MATCH 0x828c | ||
28 | |||
29 | /* | ||
30 | * AR_WOW_LENGTH1 | ||
31 | * bit 31:24 pattern 0 length | ||
32 | * bit 23:16 pattern 1 length | ||
33 | * bit 15:8 pattern 2 length | ||
34 | * bit 7:0 pattern 3 length | ||
35 | * | ||
36 | * AR_WOW_LENGTH2 | ||
37 | * bit 31:24 pattern 4 length | ||
38 | * bit 23:16 pattern 5 length | ||
39 | * bit 15:8 pattern 6 length | ||
40 | * bit 7:0 pattern 7 length | ||
41 | * | ||
42 | * AR_WOW_LENGTH3 | ||
43 | * bit 31:24 pattern 8 length | ||
44 | * bit 23:16 pattern 9 length | ||
45 | * bit 15:8 pattern 10 length | ||
46 | * bit 7:0 pattern 11 length | ||
47 | * | ||
48 | * AR_WOW_LENGTH4 | ||
49 | * bit 31:24 pattern 12 length | ||
50 | * bit 23:16 pattern 13 length | ||
51 | * bit 15:8 pattern 14 length | ||
52 | * bit 7:0 pattern 15 length | ||
53 | */ | ||
54 | #define AR_WOW_LENGTH1 0x8360 | ||
55 | #define AR_WOW_LENGTH2 0X8364 | ||
56 | #define AR_WOW_LENGTH3 0X8380 | ||
57 | #define AR_WOW_LENGTH4 0X8384 | ||
58 | |||
59 | #define AR_WOW_PATTERN_MATCH_LT_256B 0x8368 | ||
60 | #define AR_MAC_PCU_WOW4 0x8370 | ||
61 | |||
62 | #define AR_SW_WOW_CONTROL 0x20018 | ||
63 | #define AR_SW_WOW_ENABLE 0x1 | ||
64 | #define AR_SWITCH_TO_REFCLK 0x2 | ||
65 | #define AR_RESET_CONTROL 0x4 | ||
66 | #define AR_RESET_VALUE_MASK 0x8 | ||
67 | #define AR_HW_WOW_DISABLE 0x10 | ||
68 | #define AR_CLR_MAC_INTERRUPT 0x20 | ||
69 | #define AR_CLR_KA_INTERRUPT 0x40 | ||
70 | |||
71 | #define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 27) /* in usecs */ | ||
72 | #define AR_WOW_MAC_INTR_EN 0x00040000 | ||
73 | #define AR_WOW_MAGIC_EN 0x00010000 | ||
74 | #define AR_WOW_PATTERN_EN(x) (x & 0xff) | ||
75 | #define AR_WOW_PAT_FOUND_SHIFT 8 | ||
76 | #define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT)) | ||
77 | #define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT) | ||
78 | #define AR_WOW_MAGIC_PAT_FOUND 0x00020000 | ||
79 | #define AR_WOW_MAC_INTR 0x00080000 | ||
80 | #define AR_WOW_KEEP_ALIVE_FAIL 0x00100000 | ||
81 | #define AR_WOW_BEACON_FAIL 0x00200000 | ||
82 | |||
83 | #define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | \ | ||
84 | AR_WOW_MAGIC_PAT_FOUND | \ | ||
85 | AR_WOW_KEEP_ALIVE_FAIL | \ | ||
86 | AR_WOW_BEACON_FAIL)) | ||
87 | #define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \ | ||
88 | AR_WOW_MAGIC_EN | \ | ||
89 | AR_WOW_MAC_INTR_EN | \ | ||
90 | AR_WOW_BEACON_FAIL | \ | ||
91 | AR_WOW_KEEP_ALIVE_FAIL)) | ||
92 | |||
93 | #define AR_WOW_AIFS_CNT(x) (x & 0xff) | ||
94 | #define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8) | ||
95 | #define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16) | ||
96 | |||
97 | #define AR_WOW_BEACON_FAIL_EN 0x00000001 | ||
98 | #define AR_WOW_BEACON_TIMO 0x40000000 | ||
99 | #define AR_WOW_KEEP_ALIVE_NEVER 0xffffffff | ||
100 | #define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001 | ||
101 | #define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002 | ||
102 | #define AR_WOW_KEEP_ALIVE_DELAY_VALUE 0x000003e8 /* 1 msec */ | ||
103 | #define AR_WOW_BMISSTHRESHOLD 0x20 | ||
104 | #define AR_WOW_PAT_END_OF_PKT(x) (x & 0xf) | ||
105 | #define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8) | ||
106 | #define AR_WOW_PAT_BACKOFF 0x00000004 | ||
107 | #define AR_WOW_CNT_AIFS_CNT 0x00000022 | ||
108 | #define AR_WOW_CNT_SLOT_CNT 0x00000009 | ||
109 | #define AR_WOW_CNT_KA_CNT 0x00000008 | ||
110 | |||
111 | #define AR_WOW_TRANSMIT_BUFFER 0xe000 | ||
112 | #define AR_WOW_TXBUF(i) (AR_WOW_TRANSMIT_BUFFER + ((i) << 2)) | ||
113 | #define AR_WOW_KA_DESC_WORD2 0xe000 | ||
114 | #define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8)) | ||
115 | #define AR_WOW_TB_MASK(i) (0xec00 + (i << 5)) | ||
116 | #define AR_WOW_PATTERN_SUPPORTED_LEGACY 0xff | ||
117 | #define AR_WOW_PATTERN_SUPPORTED 0xffff | ||
118 | #define AR_WOW_LENGTH_MAX 0xff | ||
119 | #define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3) | ||
120 | #define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i)) | ||
121 | #define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3) | ||
122 | #define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i)) | ||
123 | #define AR_WOW_LEN3_SHIFT(_i) ((0xb - ((_i) & 0xb)) << 0x3) | ||
124 | #define AR_WOW_LENGTH3_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN3_SHIFT(_i)) | ||
125 | #define AR_WOW_LEN4_SHIFT(_i) ((0xf - ((_i) & 0xf)) << 0x3) | ||
126 | #define AR_WOW_LENGTH4_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN4_SHIFT(_i)) | ||
127 | |||
128 | #endif /* REG_WOW_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index 5f30e580d942..8d0b1730a9d5 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c | |||
@@ -16,36 +16,43 @@ | |||
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "ath9k.h" |
18 | 18 | ||
19 | static const struct wiphy_wowlan_support ath9k_wowlan_support = { | 19 | static const struct wiphy_wowlan_support ath9k_wowlan_support_legacy = { |
20 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, | 20 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, |
21 | .n_patterns = MAX_NUM_USER_PATTERN, | 21 | .n_patterns = MAX_NUM_USER_PATTERN, |
22 | .pattern_min_len = 1, | 22 | .pattern_min_len = 1, |
23 | .pattern_max_len = MAX_PATTERN_SIZE, | 23 | .pattern_max_len = MAX_PATTERN_SIZE, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | static void ath9k_wow_map_triggers(struct ath_softc *sc, | 26 | static const struct wiphy_wowlan_support ath9k_wowlan_support = { |
27 | struct cfg80211_wowlan *wowlan, | 27 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, |
28 | u32 *wow_triggers) | 28 | .n_patterns = MAX_NUM_PATTERN - 2, |
29 | .pattern_min_len = 1, | ||
30 | .pattern_max_len = MAX_PATTERN_SIZE, | ||
31 | }; | ||
32 | |||
33 | static u8 ath9k_wow_map_triggers(struct ath_softc *sc, | ||
34 | struct cfg80211_wowlan *wowlan) | ||
29 | { | 35 | { |
36 | u8 wow_triggers = 0; | ||
37 | |||
30 | if (wowlan->disconnect) | 38 | if (wowlan->disconnect) |
31 | *wow_triggers |= AH_WOW_LINK_CHANGE | | 39 | wow_triggers |= AH_WOW_LINK_CHANGE | |
32 | AH_WOW_BEACON_MISS; | 40 | AH_WOW_BEACON_MISS; |
33 | if (wowlan->magic_pkt) | 41 | if (wowlan->magic_pkt) |
34 | *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; | 42 | wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; |
35 | 43 | ||
36 | if (wowlan->n_patterns) | 44 | if (wowlan->n_patterns) |
37 | *wow_triggers |= AH_WOW_USER_PATTERN_EN; | 45 | wow_triggers |= AH_WOW_USER_PATTERN_EN; |
38 | |||
39 | sc->wow_enabled = *wow_triggers; | ||
40 | 46 | ||
47 | return wow_triggers; | ||
41 | } | 48 | } |
42 | 49 | ||
43 | static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | 50 | static int ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) |
44 | { | 51 | { |
45 | struct ath_hw *ah = sc->sc_ah; | 52 | struct ath_hw *ah = sc->sc_ah; |
46 | struct ath_common *common = ath9k_hw_common(ah); | 53 | struct ath_common *common = ath9k_hw_common(ah); |
47 | int pattern_count = 0; | 54 | int pattern_count = 0; |
48 | int i, byte_cnt; | 55 | int ret, i, byte_cnt = 0; |
49 | u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; | 56 | u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; |
50 | u8 dis_deauth_mask[MAX_PATTERN_SIZE]; | 57 | u8 dis_deauth_mask[MAX_PATTERN_SIZE]; |
51 | 58 | ||
@@ -80,12 +87,7 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | |||
80 | * | x:x:x:x:x:x -- 22 bytes | 87 | * | x:x:x:x:x:x -- 22 bytes |
81 | */ | 88 | */ |
82 | 89 | ||
83 | /* Create Disassociate Pattern first */ | ||
84 | |||
85 | byte_cnt = 0; | ||
86 | |||
87 | /* Fill out the mask with all FF's */ | 90 | /* Fill out the mask with all FF's */ |
88 | |||
89 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) | 91 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) |
90 | dis_deauth_mask[i] = 0xff; | 92 | dis_deauth_mask[i] = 0xff; |
91 | 93 | ||
@@ -108,19 +110,17 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | |||
108 | byte_cnt += 6; | 110 | byte_cnt += 6; |
109 | 111 | ||
110 | /* copy the bssid, its same as the source mac address */ | 112 | /* copy the bssid, its same as the source mac address */ |
111 | |||
112 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); | 113 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); |
113 | 114 | ||
114 | /* Create Disassociate pattern mask */ | 115 | /* Create Disassociate pattern mask */ |
115 | |||
116 | dis_deauth_mask[0] = 0xfe; | 116 | dis_deauth_mask[0] = 0xfe; |
117 | dis_deauth_mask[1] = 0x03; | 117 | dis_deauth_mask[1] = 0x03; |
118 | dis_deauth_mask[2] = 0xc0; | 118 | dis_deauth_mask[2] = 0xc0; |
119 | 119 | ||
120 | ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); | 120 | ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, |
121 | 121 | pattern_count, byte_cnt); | |
122 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, | 122 | if (ret) |
123 | pattern_count, byte_cnt); | 123 | goto exit; |
124 | 124 | ||
125 | pattern_count++; | 125 | pattern_count++; |
126 | /* | 126 | /* |
@@ -129,59 +129,39 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | |||
129 | */ | 129 | */ |
130 | dis_deauth_pattern[0] = 0xC0; | 130 | dis_deauth_pattern[0] = 0xC0; |
131 | 131 | ||
132 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, | 132 | ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, |
133 | pattern_count, byte_cnt); | 133 | pattern_count, byte_cnt); |
134 | 134 | exit: | |
135 | return ret; | ||
135 | } | 136 | } |
136 | 137 | ||
137 | static void ath9k_wow_add_pattern(struct ath_softc *sc, | 138 | static int ath9k_wow_add_pattern(struct ath_softc *sc, |
138 | struct cfg80211_wowlan *wowlan) | 139 | struct cfg80211_wowlan *wowlan) |
139 | { | 140 | { |
140 | struct ath_hw *ah = sc->sc_ah; | 141 | struct ath_hw *ah = sc->sc_ah; |
141 | struct ath9k_wow_pattern *wow_pattern = NULL; | ||
142 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; | 142 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; |
143 | int mask_len; | 143 | u8 wow_pattern[MAX_PATTERN_SIZE]; |
144 | u8 wow_mask[MAX_PATTERN_SIZE]; | ||
145 | int mask_len, ret = 0; | ||
144 | s8 i = 0; | 146 | s8 i = 0; |
145 | 147 | ||
146 | if (!wowlan->n_patterns) | ||
147 | return; | ||
148 | |||
149 | /* | ||
150 | * Add the new user configured patterns | ||
151 | */ | ||
152 | for (i = 0; i < wowlan->n_patterns; i++) { | 148 | for (i = 0; i < wowlan->n_patterns; i++) { |
153 | 149 | mask_len = DIV_ROUND_UP(patterns[i].pattern_len, 8); | |
154 | wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); | 150 | memset(wow_pattern, 0, MAX_PATTERN_SIZE); |
155 | 151 | memset(wow_mask, 0, MAX_PATTERN_SIZE); | |
156 | if (!wow_pattern) | 152 | memcpy(wow_pattern, patterns[i].pattern, patterns[i].pattern_len); |
157 | return; | 153 | memcpy(wow_mask, patterns[i].mask, mask_len); |
158 | 154 | ||
159 | /* | 155 | ret = ath9k_hw_wow_apply_pattern(ah, |
160 | * TODO: convert the generic user space pattern to | 156 | wow_pattern, |
161 | * appropriate chip specific/802.11 pattern. | 157 | wow_mask, |
162 | */ | 158 | i + 2, |
163 | 159 | patterns[i].pattern_len); | |
164 | mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); | 160 | if (ret) |
165 | memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); | 161 | break; |
166 | memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); | ||
167 | memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, | ||
168 | patterns[i].pattern_len); | ||
169 | memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); | ||
170 | wow_pattern->pattern_len = patterns[i].pattern_len; | ||
171 | |||
172 | /* | ||
173 | * just need to take care of deauth and disssoc pattern, | ||
174 | * make sure we don't overwrite them. | ||
175 | */ | ||
176 | |||
177 | ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, | ||
178 | wow_pattern->mask_bytes, | ||
179 | i + 2, | ||
180 | wow_pattern->pattern_len); | ||
181 | kfree(wow_pattern); | ||
182 | |||
183 | } | 162 | } |
184 | 163 | ||
164 | return ret; | ||
185 | } | 165 | } |
186 | 166 | ||
187 | int ath9k_suspend(struct ieee80211_hw *hw, | 167 | int ath9k_suspend(struct ieee80211_hw *hw, |
@@ -190,41 +170,39 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
190 | struct ath_softc *sc = hw->priv; | 170 | struct ath_softc *sc = hw->priv; |
191 | struct ath_hw *ah = sc->sc_ah; | 171 | struct ath_hw *ah = sc->sc_ah; |
192 | struct ath_common *common = ath9k_hw_common(ah); | 172 | struct ath_common *common = ath9k_hw_common(ah); |
193 | u32 wow_triggers_enabled = 0; | 173 | u8 triggers; |
194 | int ret = 0; | 174 | int ret = 0; |
195 | 175 | ||
196 | ath9k_deinit_channel_context(sc); | 176 | ath9k_deinit_channel_context(sc); |
197 | 177 | ||
198 | mutex_lock(&sc->mutex); | 178 | mutex_lock(&sc->mutex); |
199 | 179 | ||
200 | ath_cancel_work(sc); | ||
201 | ath_stop_ani(sc); | ||
202 | |||
203 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { | 180 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
204 | ath_dbg(common, ANY, "Device not present\n"); | 181 | ath_err(common, "Device not present\n"); |
205 | ret = -EINVAL; | 182 | ret = -ENODEV; |
206 | goto fail_wow; | 183 | goto fail_wow; |
207 | } | 184 | } |
208 | 185 | ||
209 | if (WARN_ON(!wowlan)) { | 186 | if (WARN_ON(!wowlan)) { |
210 | ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); | 187 | ath_err(common, "None of the WoW triggers enabled\n"); |
211 | ret = -EINVAL; | 188 | ret = -EINVAL; |
212 | goto fail_wow; | 189 | goto fail_wow; |
213 | } | 190 | } |
214 | 191 | ||
215 | if (!device_can_wakeup(sc->dev)) { | 192 | if (sc->cur_chan->nvifs > 1) { |
216 | ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); | 193 | ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); |
217 | ret = 1; | 194 | ret = 1; |
218 | goto fail_wow; | 195 | goto fail_wow; |
219 | } | 196 | } |
220 | 197 | ||
221 | /* | 198 | if (ath9k_is_chanctx_enabled()) { |
222 | * none of the sta vifs are associated | 199 | if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) { |
223 | * and we are not currently handling multivif | 200 | ath_dbg(common, WOW, |
224 | * cases, for instance we have to seperately | 201 | "Multi-channel WOW is not supported\n"); |
225 | * configure 'keep alive frame' for each | 202 | ret = 1; |
226 | * STA. | 203 | goto fail_wow; |
227 | */ | 204 | } |
205 | } | ||
228 | 206 | ||
229 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { | 207 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { |
230 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); | 208 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); |
@@ -232,16 +210,15 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
232 | goto fail_wow; | 210 | goto fail_wow; |
233 | } | 211 | } |
234 | 212 | ||
235 | if (sc->cur_chan->nvifs > 1) { | 213 | triggers = ath9k_wow_map_triggers(sc, wowlan); |
236 | ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); | 214 | if (!triggers) { |
215 | ath_dbg(common, WOW, "No valid WoW triggers\n"); | ||
237 | ret = 1; | 216 | ret = 1; |
238 | goto fail_wow; | 217 | goto fail_wow; |
239 | } | 218 | } |
240 | 219 | ||
241 | ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); | 220 | ath_cancel_work(sc); |
242 | 221 | ath_stop_ani(sc); | |
243 | ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", | ||
244 | wow_triggers_enabled); | ||
245 | 222 | ||
246 | ath9k_ps_wakeup(sc); | 223 | ath9k_ps_wakeup(sc); |
247 | 224 | ||
@@ -251,10 +228,21 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
251 | * Enable wake up on recieving disassoc/deauth | 228 | * Enable wake up on recieving disassoc/deauth |
252 | * frame by default. | 229 | * frame by default. |
253 | */ | 230 | */ |
254 | ath9k_wow_add_disassoc_deauth_pattern(sc); | 231 | ret = ath9k_wow_add_disassoc_deauth_pattern(sc); |
232 | if (ret) { | ||
233 | ath_err(common, | ||
234 | "Unable to add disassoc/deauth pattern: %d\n", ret); | ||
235 | goto fail_wow; | ||
236 | } | ||
255 | 237 | ||
256 | if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) | 238 | if (triggers & AH_WOW_USER_PATTERN_EN) { |
257 | ath9k_wow_add_pattern(sc, wowlan); | 239 | ret = ath9k_wow_add_pattern(sc, wowlan); |
240 | if (ret) { | ||
241 | ath_err(common, | ||
242 | "Unable to add user pattern: %d\n", ret); | ||
243 | goto fail_wow; | ||
244 | } | ||
245 | } | ||
258 | 246 | ||
259 | spin_lock_bh(&sc->sc_pcu_lock); | 247 | spin_lock_bh(&sc->sc_pcu_lock); |
260 | /* | 248 | /* |
@@ -278,12 +266,12 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
278 | synchronize_irq(sc->irq); | 266 | synchronize_irq(sc->irq); |
279 | tasklet_kill(&sc->intr_tq); | 267 | tasklet_kill(&sc->intr_tq); |
280 | 268 | ||
281 | ath9k_hw_wow_enable(ah, wow_triggers_enabled); | 269 | ath9k_hw_wow_enable(ah, triggers); |
282 | 270 | ||
283 | ath9k_ps_restore(sc); | 271 | ath9k_ps_restore(sc); |
284 | ath_dbg(common, ANY, "WoW enabled in ath9k\n"); | 272 | ath_dbg(common, WOW, "Suspend with WoW triggers: 0x%x\n", triggers); |
285 | atomic_inc(&sc->wow_sleep_proc_intr); | ||
286 | 273 | ||
274 | set_bit(ATH_OP_WOW_ENABLED, &common->op_flags); | ||
287 | fail_wow: | 275 | fail_wow: |
288 | mutex_unlock(&sc->mutex); | 276 | mutex_unlock(&sc->mutex); |
289 | return ret; | 277 | return ret; |
@@ -294,7 +282,7 @@ int ath9k_resume(struct ieee80211_hw *hw) | |||
294 | struct ath_softc *sc = hw->priv; | 282 | struct ath_softc *sc = hw->priv; |
295 | struct ath_hw *ah = sc->sc_ah; | 283 | struct ath_hw *ah = sc->sc_ah; |
296 | struct ath_common *common = ath9k_hw_common(ah); | 284 | struct ath_common *common = ath9k_hw_common(ah); |
297 | u32 wow_status; | 285 | u8 status; |
298 | 286 | ||
299 | mutex_lock(&sc->mutex); | 287 | mutex_lock(&sc->mutex); |
300 | 288 | ||
@@ -309,29 +297,14 @@ int ath9k_resume(struct ieee80211_hw *hw) | |||
309 | 297 | ||
310 | spin_unlock_bh(&sc->sc_pcu_lock); | 298 | spin_unlock_bh(&sc->sc_pcu_lock); |
311 | 299 | ||
312 | wow_status = ath9k_hw_wow_wakeup(ah); | 300 | status = ath9k_hw_wow_wakeup(ah); |
313 | 301 | ath_dbg(common, WOW, "Resume with WoW status: 0x%x\n", status); | |
314 | if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { | ||
315 | /* | ||
316 | * some devices may not pick beacon miss | ||
317 | * as the reason they woke up so we add | ||
318 | * that here for that shortcoming. | ||
319 | */ | ||
320 | wow_status |= AH_WOW_BEACON_MISS; | ||
321 | atomic_dec(&sc->wow_got_bmiss_intr); | ||
322 | ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); | ||
323 | } | ||
324 | |||
325 | atomic_dec(&sc->wow_sleep_proc_intr); | ||
326 | |||
327 | if (wow_status) { | ||
328 | ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", | ||
329 | ath9k_hw_wow_event_to_string(wow_status), wow_status); | ||
330 | } | ||
331 | 302 | ||
332 | ath_restart_work(sc); | 303 | ath_restart_work(sc); |
333 | ath9k_start_btcoex(sc); | 304 | ath9k_start_btcoex(sc); |
334 | 305 | ||
306 | clear_bit(ATH_OP_WOW_ENABLED, &common->op_flags); | ||
307 | |||
335 | ath9k_ps_restore(sc); | 308 | ath9k_ps_restore(sc); |
336 | mutex_unlock(&sc->mutex); | 309 | mutex_unlock(&sc->mutex); |
337 | 310 | ||
@@ -341,22 +314,35 @@ int ath9k_resume(struct ieee80211_hw *hw) | |||
341 | void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) | 314 | void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) |
342 | { | 315 | { |
343 | struct ath_softc *sc = hw->priv; | 316 | struct ath_softc *sc = hw->priv; |
317 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
344 | 318 | ||
345 | mutex_lock(&sc->mutex); | 319 | mutex_lock(&sc->mutex); |
346 | device_init_wakeup(sc->dev, 1); | ||
347 | device_set_wakeup_enable(sc->dev, enabled); | 320 | device_set_wakeup_enable(sc->dev, enabled); |
348 | mutex_unlock(&sc->mutex); | 321 | mutex_unlock(&sc->mutex); |
322 | |||
323 | ath_dbg(common, WOW, "WoW wakeup source is %s\n", | ||
324 | (enabled) ? "enabled" : "disabled"); | ||
349 | } | 325 | } |
350 | 326 | ||
351 | void ath9k_init_wow(struct ieee80211_hw *hw) | 327 | void ath9k_init_wow(struct ieee80211_hw *hw) |
352 | { | 328 | { |
353 | struct ath_softc *sc = hw->priv; | 329 | struct ath_softc *sc = hw->priv; |
330 | struct ath_hw *ah = sc->sc_ah; | ||
331 | |||
332 | if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) { | ||
333 | if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah)) | ||
334 | hw->wiphy->wowlan = &ath9k_wowlan_support; | ||
335 | else | ||
336 | hw->wiphy->wowlan = &ath9k_wowlan_support_legacy; | ||
354 | 337 | ||
355 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && | 338 | device_init_wakeup(sc->dev, 1); |
356 | (sc->driver_data & ATH9K_PCI_WOW) && | 339 | } |
357 | device_can_wakeup(sc->dev)) | 340 | } |
358 | hw->wiphy->wowlan = &ath9k_wowlan_support; | 341 | |
342 | void ath9k_deinit_wow(struct ieee80211_hw *hw) | ||
343 | { | ||
344 | struct ath_softc *sc = hw->priv; | ||
359 | 345 | ||
360 | atomic_set(&sc->wow_sleep_proc_intr, -1); | 346 | if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) |
361 | atomic_set(&sc->wow_got_bmiss_intr, -1); | 347 | device_init_wakeup(sc->dev, 0); |
362 | } | 348 | } |
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index 481680a3aa55..ce8c0381825e 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig | |||
@@ -39,12 +39,3 @@ config WIL6210_TRACING | |||
39 | option if you are interested in debugging the driver. | 39 | option if you are interested in debugging the driver. |
40 | 40 | ||
41 | If unsure, say Y to make it easier to debug problems. | 41 | If unsure, say Y to make it easier to debug problems. |
42 | |||
43 | config WIL6210_PLATFORM_MSM | ||
44 | bool "wil6210 MSM platform specific support" | ||
45 | depends on WIL6210 | ||
46 | depends on ARCH_MSM | ||
47 | default y | ||
48 | ---help--- | ||
49 | Say Y here to enable wil6210 driver support for MSM | ||
50 | platform specific features | ||
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index 8ad4b5f97e04..caa717bf52f3 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile | |||
@@ -14,7 +14,6 @@ wil6210-y += ioctl.o | |||
14 | wil6210-y += fw.o | 14 | wil6210-y += fw.o |
15 | wil6210-$(CONFIG_WIL6210_TRACING) += trace.o | 15 | wil6210-$(CONFIG_WIL6210_TRACING) += trace.o |
16 | wil6210-y += wil_platform.o | 16 | wil6210-y += wil_platform.o |
17 | wil6210-$(CONFIG_WIL6210_PLATFORM_MSM) += wil_platform_msm.o | ||
18 | wil6210-y += ethtool.o | 17 | wil6210-y += ethtool.o |
19 | 18 | ||
20 | # for tracing framework to find trace.h | 19 | # for tracing framework to find trace.h |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index bd013fdb86dc..2d5ea21be47e 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -334,6 +334,30 @@ out: | |||
334 | return rc; | 334 | return rc; |
335 | } | 335 | } |
336 | 336 | ||
337 | static void wil_print_crypto(struct wil6210_priv *wil, | ||
338 | struct cfg80211_crypto_settings *c) | ||
339 | { | ||
340 | int i, n; | ||
341 | |||
342 | wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n", | ||
343 | c->wpa_versions, c->cipher_group); | ||
344 | wil_dbg_misc(wil, "Pairwise ciphers [%d] {\n", c->n_ciphers_pairwise); | ||
345 | n = min_t(int, c->n_ciphers_pairwise, ARRAY_SIZE(c->ciphers_pairwise)); | ||
346 | for (i = 0; i < n; i++) | ||
347 | wil_dbg_misc(wil, " [%d] = 0x%08x\n", i, | ||
348 | c->ciphers_pairwise[i]); | ||
349 | wil_dbg_misc(wil, "}\n"); | ||
350 | wil_dbg_misc(wil, "AKM suites [%d] {\n", c->n_akm_suites); | ||
351 | n = min_t(int, c->n_akm_suites, ARRAY_SIZE(c->akm_suites)); | ||
352 | for (i = 0; i < n; i++) | ||
353 | wil_dbg_misc(wil, " [%d] = 0x%08x\n", i, | ||
354 | c->akm_suites[i]); | ||
355 | wil_dbg_misc(wil, "}\n"); | ||
356 | wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n", | ||
357 | c->control_port, be16_to_cpu(c->control_port_ethertype), | ||
358 | c->control_port_no_encrypt); | ||
359 | } | ||
360 | |||
337 | static void wil_print_connect_params(struct wil6210_priv *wil, | 361 | static void wil_print_connect_params(struct wil6210_priv *wil, |
338 | struct cfg80211_connect_params *sme) | 362 | struct cfg80211_connect_params *sme) |
339 | { | 363 | { |
@@ -348,6 +372,7 @@ static void wil_print_connect_params(struct wil6210_priv *wil, | |||
348 | print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, | 372 | print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, |
349 | 16, 1, sme->ssid, sme->ssid_len, true); | 373 | 16, 1, sme->ssid, sme->ssid_len, true); |
350 | wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); | 374 | wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); |
375 | wil_print_crypto(wil, &sme->crypto); | ||
351 | } | 376 | } |
352 | 377 | ||
353 | static int wil_cfg80211_connect(struct wiphy *wiphy, | 378 | static int wil_cfg80211_connect(struct wiphy *wiphy, |
@@ -454,6 +479,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
454 | 479 | ||
455 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); | 480 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); |
456 | if (rc == 0) { | 481 | if (rc == 0) { |
482 | netif_carrier_on(ndev); | ||
457 | /* Connect can take lots of time */ | 483 | /* Connect can take lots of time */ |
458 | mod_timer(&wil->connect_timer, | 484 | mod_timer(&wil->connect_timer, |
459 | jiffies + msecs_to_jiffies(2000)); | 485 | jiffies + msecs_to_jiffies(2000)); |
@@ -618,18 +644,6 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) | |||
618 | b->assocresp_ies, b->assocresp_ies_len); | 644 | b->assocresp_ies, b->assocresp_ies_len); |
619 | } | 645 | } |
620 | 646 | ||
621 | static void wil_print_crypto(struct wil6210_priv *wil, | ||
622 | struct cfg80211_crypto_settings *c) | ||
623 | { | ||
624 | wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n", | ||
625 | c->wpa_versions, c->cipher_group); | ||
626 | wil_dbg_misc(wil, "Pairwise ciphers [%d]\n", c->n_ciphers_pairwise); | ||
627 | wil_dbg_misc(wil, "AKM suites [%d]\n", c->n_akm_suites); | ||
628 | wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n", | ||
629 | c->control_port, be16_to_cpu(c->control_port_ethertype), | ||
630 | c->control_port_no_encrypt); | ||
631 | } | ||
632 | |||
633 | static int wil_fix_bcon(struct wil6210_priv *wil, | 647 | static int wil_fix_bcon(struct wil6210_priv *wil, |
634 | struct cfg80211_beacon_data *bcon) | 648 | struct cfg80211_beacon_data *bcon) |
635 | { | 649 | { |
@@ -757,12 +771,12 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
757 | 771 | ||
758 | wil->secure_pcp = info->privacy; | 772 | wil->secure_pcp = info->privacy; |
759 | 773 | ||
774 | netif_carrier_on(ndev); | ||
775 | |||
760 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, | 776 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, |
761 | channel->hw_value); | 777 | channel->hw_value); |
762 | if (rc) | 778 | if (rc) |
763 | goto out; | 779 | netif_carrier_off(ndev); |
764 | |||
765 | netif_carrier_on(ndev); | ||
766 | 780 | ||
767 | out: | 781 | out: |
768 | mutex_unlock(&wil->mutex); | 782 | mutex_unlock(&wil->mutex); |
@@ -772,23 +786,26 @@ out: | |||
772 | static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | 786 | static int wil_cfg80211_stop_ap(struct wiphy *wiphy, |
773 | struct net_device *ndev) | 787 | struct net_device *ndev) |
774 | { | 788 | { |
775 | int rc, rc1; | ||
776 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 789 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
777 | 790 | ||
778 | wil_dbg_misc(wil, "%s()\n", __func__); | 791 | wil_dbg_misc(wil, "%s()\n", __func__); |
779 | 792 | ||
793 | netif_carrier_off(ndev); | ||
780 | wil_set_recovery_state(wil, fw_recovery_idle); | 794 | wil_set_recovery_state(wil, fw_recovery_idle); |
781 | 795 | ||
782 | mutex_lock(&wil->mutex); | 796 | mutex_lock(&wil->mutex); |
783 | 797 | ||
784 | rc = wmi_pcp_stop(wil); | 798 | wmi_pcp_stop(wil); |
785 | 799 | ||
786 | __wil_down(wil); | 800 | __wil_down(wil); |
787 | rc1 = __wil_up(wil); | 801 | __wil_up(wil); |
788 | 802 | ||
789 | mutex_unlock(&wil->mutex); | 803 | mutex_unlock(&wil->mutex); |
790 | 804 | ||
791 | return min(rc, rc1); | 805 | /* some functions above might fail (e.g. __wil_up). Nevertheless, we |
806 | * return success because AP has stopped | ||
807 | */ | ||
808 | return 0; | ||
792 | } | 809 | } |
793 | 810 | ||
794 | static int wil_cfg80211_del_station(struct wiphy *wiphy, | 811 | static int wil_cfg80211_del_station(struct wiphy *wiphy, |
@@ -804,6 +821,96 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, | |||
804 | return 0; | 821 | return 0; |
805 | } | 822 | } |
806 | 823 | ||
824 | /* probe_client handling */ | ||
825 | static void wil_probe_client_handle(struct wil6210_priv *wil, | ||
826 | struct wil_probe_client_req *req) | ||
827 | { | ||
828 | struct net_device *ndev = wil_to_ndev(wil); | ||
829 | struct wil_sta_info *sta = &wil->sta[req->cid]; | ||
830 | /* assume STA is alive if it is still connected, | ||
831 | * else FW will disconnect it | ||
832 | */ | ||
833 | bool alive = (sta->status == wil_sta_connected); | ||
834 | |||
835 | cfg80211_probe_status(ndev, sta->addr, req->cookie, alive, GFP_KERNEL); | ||
836 | } | ||
837 | |||
838 | static struct list_head *next_probe_client(struct wil6210_priv *wil) | ||
839 | { | ||
840 | struct list_head *ret = NULL; | ||
841 | |||
842 | mutex_lock(&wil->probe_client_mutex); | ||
843 | |||
844 | if (!list_empty(&wil->probe_client_pending)) { | ||
845 | ret = wil->probe_client_pending.next; | ||
846 | list_del(ret); | ||
847 | } | ||
848 | |||
849 | mutex_unlock(&wil->probe_client_mutex); | ||
850 | |||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | void wil_probe_client_worker(struct work_struct *work) | ||
855 | { | ||
856 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
857 | probe_client_worker); | ||
858 | struct wil_probe_client_req *req; | ||
859 | struct list_head *lh; | ||
860 | |||
861 | while ((lh = next_probe_client(wil)) != NULL) { | ||
862 | req = list_entry(lh, struct wil_probe_client_req, list); | ||
863 | |||
864 | wil_probe_client_handle(wil, req); | ||
865 | kfree(req); | ||
866 | } | ||
867 | } | ||
868 | |||
869 | void wil_probe_client_flush(struct wil6210_priv *wil) | ||
870 | { | ||
871 | struct wil_probe_client_req *req, *t; | ||
872 | |||
873 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
874 | |||
875 | mutex_lock(&wil->probe_client_mutex); | ||
876 | |||
877 | list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) { | ||
878 | list_del(&req->list); | ||
879 | kfree(req); | ||
880 | } | ||
881 | |||
882 | mutex_unlock(&wil->probe_client_mutex); | ||
883 | } | ||
884 | |||
885 | static int wil_cfg80211_probe_client(struct wiphy *wiphy, | ||
886 | struct net_device *dev, | ||
887 | const u8 *peer, u64 *cookie) | ||
888 | { | ||
889 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
890 | struct wil_probe_client_req *req; | ||
891 | int cid = wil_find_cid(wil, peer); | ||
892 | |||
893 | wil_dbg_misc(wil, "%s(%pM => CID %d)\n", __func__, peer, cid); | ||
894 | |||
895 | if (cid < 0) | ||
896 | return -ENOLINK; | ||
897 | |||
898 | req = kzalloc(sizeof(*req), GFP_KERNEL); | ||
899 | if (!req) | ||
900 | return -ENOMEM; | ||
901 | |||
902 | req->cid = cid; | ||
903 | req->cookie = cid; | ||
904 | |||
905 | mutex_lock(&wil->probe_client_mutex); | ||
906 | list_add_tail(&req->list, &wil->probe_client_pending); | ||
907 | mutex_unlock(&wil->probe_client_mutex); | ||
908 | |||
909 | *cookie = req->cookie; | ||
910 | queue_work(wil->wq_service, &wil->probe_client_worker); | ||
911 | return 0; | ||
912 | } | ||
913 | |||
807 | static struct cfg80211_ops wil_cfg80211_ops = { | 914 | static struct cfg80211_ops wil_cfg80211_ops = { |
808 | .scan = wil_cfg80211_scan, | 915 | .scan = wil_cfg80211_scan, |
809 | .connect = wil_cfg80211_connect, | 916 | .connect = wil_cfg80211_connect, |
@@ -823,6 +930,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { | |||
823 | .start_ap = wil_cfg80211_start_ap, | 930 | .start_ap = wil_cfg80211_start_ap, |
824 | .stop_ap = wil_cfg80211_stop_ap, | 931 | .stop_ap = wil_cfg80211_stop_ap, |
825 | .del_station = wil_cfg80211_del_station, | 932 | .del_station = wil_cfg80211_del_station, |
933 | .probe_client = wil_cfg80211_probe_client, | ||
826 | }; | 934 | }; |
827 | 935 | ||
828 | static void wil_wiphy_init(struct wiphy *wiphy) | 936 | static void wil_wiphy_init(struct wiphy *wiphy) |
@@ -854,6 +962,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) | |||
854 | wiphy->cipher_suites = wil_cipher_suites; | 962 | wiphy->cipher_suites = wil_cipher_suites; |
855 | wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); | 963 | wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); |
856 | wiphy->mgmt_stypes = wil_mgmt_stypes; | 964 | wiphy->mgmt_stypes = wil_mgmt_stypes; |
965 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS; | ||
857 | } | 966 | } |
858 | 967 | ||
859 | struct wireless_dev *wil_cfg80211_init(struct device *dev) | 968 | struct wireless_dev *wil_cfg80211_init(struct device *dev) |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 62dc24189bd3..b04e0afdcb21 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -33,34 +33,6 @@ static bool no_fw_load = true; | |||
33 | module_param(no_fw_load, bool, S_IRUGO | S_IWUSR); | 33 | module_param(no_fw_load, bool, S_IRUGO | S_IWUSR); |
34 | MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash."); | 34 | MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash."); |
35 | 35 | ||
36 | static unsigned int tx_interframe_timeout = | ||
37 | WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT; | ||
38 | |||
39 | module_param(tx_interframe_timeout, uint, S_IRUGO); | ||
40 | MODULE_PARM_DESC(tx_interframe_timeout, | ||
41 | " Interrupt moderation TX interframe timeout, usecs."); | ||
42 | |||
43 | static unsigned int rx_interframe_timeout = | ||
44 | WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT; | ||
45 | |||
46 | module_param(rx_interframe_timeout, uint, S_IRUGO); | ||
47 | MODULE_PARM_DESC(rx_interframe_timeout, | ||
48 | " Interrupt moderation RX interframe timeout, usecs."); | ||
49 | |||
50 | static unsigned int tx_max_burst_duration = | ||
51 | WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT; | ||
52 | |||
53 | module_param(tx_max_burst_duration, uint, S_IRUGO); | ||
54 | MODULE_PARM_DESC(tx_max_burst_duration, | ||
55 | " Interrupt moderation TX max burst duration, usecs."); | ||
56 | |||
57 | static unsigned int rx_max_burst_duration = | ||
58 | WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT; | ||
59 | |||
60 | module_param(rx_max_burst_duration, uint, S_IRUGO); | ||
61 | MODULE_PARM_DESC(rx_max_burst_duration, | ||
62 | " Interrupt moderation RX max burst duration, usecs."); | ||
63 | |||
64 | /* if not set via modparam, will be set to default value of 1/8 of | 36 | /* if not set via modparam, will be set to default value of 1/8 of |
65 | * rx ring size during init flow | 37 | * rx ring size during init flow |
66 | */ | 38 | */ |
@@ -248,7 +220,9 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
248 | switch (wdev->iftype) { | 220 | switch (wdev->iftype) { |
249 | case NL80211_IFTYPE_STATION: | 221 | case NL80211_IFTYPE_STATION: |
250 | case NL80211_IFTYPE_P2P_CLIENT: | 222 | case NL80211_IFTYPE_P2P_CLIENT: |
251 | wil_link_off(wil); | 223 | netif_tx_stop_all_queues(ndev); |
224 | netif_carrier_off(ndev); | ||
225 | |||
252 | if (test_bit(wil_status_fwconnected, wil->status)) { | 226 | if (test_bit(wil_status_fwconnected, wil->status)) { |
253 | clear_bit(wil_status_fwconnected, wil->status); | 227 | clear_bit(wil_status_fwconnected, wil->status); |
254 | cfg80211_disconnected(ndev, reason_code, | 228 | cfg80211_disconnected(ndev, reason_code, |
@@ -395,6 +369,8 @@ static void wil_connect_worker(struct work_struct *work) | |||
395 | int rc; | 369 | int rc; |
396 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | 370 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, |
397 | connect_worker); | 371 | connect_worker); |
372 | struct net_device *ndev = wil_to_ndev(wil); | ||
373 | |||
398 | int cid = wil->pending_connect_cid; | 374 | int cid = wil->pending_connect_cid; |
399 | int ringid = wil_find_free_vring(wil); | 375 | int ringid = wil_find_free_vring(wil); |
400 | 376 | ||
@@ -409,7 +385,7 @@ static void wil_connect_worker(struct work_struct *work) | |||
409 | wil->pending_connect_cid = -1; | 385 | wil->pending_connect_cid = -1; |
410 | if (rc == 0) { | 386 | if (rc == 0) { |
411 | wil->sta[cid].status = wil_sta_connected; | 387 | wil->sta[cid].status = wil_sta_connected; |
412 | wil_link_on(wil); | 388 | netif_tx_wake_all_queues(ndev); |
413 | } else { | 389 | } else { |
414 | wil->sta[cid].status = wil_sta_unused; | 390 | wil->sta[cid].status = wil_sta_unused; |
415 | } | 391 | } |
@@ -429,6 +405,7 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
429 | mutex_init(&wil->wmi_mutex); | 405 | mutex_init(&wil->wmi_mutex); |
430 | mutex_init(&wil->back_rx_mutex); | 406 | mutex_init(&wil->back_rx_mutex); |
431 | mutex_init(&wil->back_tx_mutex); | 407 | mutex_init(&wil->back_tx_mutex); |
408 | mutex_init(&wil->probe_client_mutex); | ||
432 | 409 | ||
433 | init_completion(&wil->wmi_ready); | 410 | init_completion(&wil->wmi_ready); |
434 | init_completion(&wil->wmi_call); | 411 | init_completion(&wil->wmi_call); |
@@ -443,10 +420,12 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
443 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); | 420 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); |
444 | INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker); | 421 | INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker); |
445 | INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker); | 422 | INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker); |
423 | INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); | ||
446 | 424 | ||
447 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | 425 | INIT_LIST_HEAD(&wil->pending_wmi_ev); |
448 | INIT_LIST_HEAD(&wil->back_rx_pending); | 426 | INIT_LIST_HEAD(&wil->back_rx_pending); |
449 | INIT_LIST_HEAD(&wil->back_tx_pending); | 427 | INIT_LIST_HEAD(&wil->back_tx_pending); |
428 | INIT_LIST_HEAD(&wil->probe_client_pending); | ||
450 | spin_lock_init(&wil->wmi_ev_lock); | 429 | spin_lock_init(&wil->wmi_ev_lock); |
451 | init_waitqueue_head(&wil->wq); | 430 | init_waitqueue_head(&wil->wq); |
452 | 431 | ||
@@ -459,10 +438,10 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
459 | goto out_wmi_wq; | 438 | goto out_wmi_wq; |
460 | 439 | ||
461 | wil->last_fw_recovery = jiffies; | 440 | wil->last_fw_recovery = jiffies; |
462 | wil->tx_interframe_timeout = tx_interframe_timeout; | 441 | wil->tx_interframe_timeout = WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT; |
463 | wil->rx_interframe_timeout = rx_interframe_timeout; | 442 | wil->rx_interframe_timeout = WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT; |
464 | wil->tx_max_burst_duration = tx_max_burst_duration; | 443 | wil->tx_max_burst_duration = WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT; |
465 | wil->rx_max_burst_duration = rx_max_burst_duration; | 444 | wil->rx_max_burst_duration = WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT; |
466 | 445 | ||
467 | if (rx_ring_overflow_thrsh == WIL6210_RX_HIGH_TRSH_INIT) | 446 | if (rx_ring_overflow_thrsh == WIL6210_RX_HIGH_TRSH_INIT) |
468 | rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_DEFAULT; | 447 | rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_DEFAULT; |
@@ -509,6 +488,8 @@ void wil_priv_deinit(struct wil6210_priv *wil) | |||
509 | cancel_work_sync(&wil->back_rx_worker); | 488 | cancel_work_sync(&wil->back_rx_worker); |
510 | wil_back_tx_flush(wil); | 489 | wil_back_tx_flush(wil); |
511 | cancel_work_sync(&wil->back_tx_worker); | 490 | cancel_work_sync(&wil->back_tx_worker); |
491 | wil_probe_client_flush(wil); | ||
492 | cancel_work_sync(&wil->probe_client_worker); | ||
512 | destroy_workqueue(wil->wq_service); | 493 | destroy_workqueue(wil->wq_service); |
513 | destroy_workqueue(wil->wmi_wq); | 494 | destroy_workqueue(wil->wmi_wq); |
514 | } | 495 | } |
@@ -741,28 +722,6 @@ void wil_fw_error_recovery(struct wil6210_priv *wil) | |||
741 | schedule_work(&wil->fw_error_worker); | 722 | schedule_work(&wil->fw_error_worker); |
742 | } | 723 | } |
743 | 724 | ||
744 | void wil_link_on(struct wil6210_priv *wil) | ||
745 | { | ||
746 | struct net_device *ndev = wil_to_ndev(wil); | ||
747 | |||
748 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
749 | |||
750 | netif_carrier_on(ndev); | ||
751 | wil_dbg_misc(wil, "netif_tx_wake : link on\n"); | ||
752 | netif_tx_wake_all_queues(ndev); | ||
753 | } | ||
754 | |||
755 | void wil_link_off(struct wil6210_priv *wil) | ||
756 | { | ||
757 | struct net_device *ndev = wil_to_ndev(wil); | ||
758 | |||
759 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
760 | |||
761 | netif_tx_stop_all_queues(ndev); | ||
762 | wil_dbg_misc(wil, "netif_tx_stop : link off\n"); | ||
763 | netif_carrier_off(ndev); | ||
764 | } | ||
765 | |||
766 | int __wil_up(struct wil6210_priv *wil) | 725 | int __wil_up(struct wil6210_priv *wil) |
767 | { | 726 | { |
768 | struct net_device *ndev = wil_to_ndev(wil); | 727 | struct net_device *ndev = wil_to_ndev(wil); |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index e81703ca7701..ace30c1b5c64 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
18 | |||
19 | #include "wil6210.h" | 18 | #include "wil6210.h" |
20 | #include "txrx.h" | 19 | #include "txrx.h" |
21 | 20 | ||
@@ -122,6 +121,12 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) | |||
122 | return min(tx_done, budget); | 121 | return min(tx_done, budget); |
123 | } | 122 | } |
124 | 123 | ||
124 | static void wil_dev_setup(struct net_device *dev) | ||
125 | { | ||
126 | ether_setup(dev); | ||
127 | dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; | ||
128 | } | ||
129 | |||
125 | void *wil_if_alloc(struct device *dev, void __iomem *csr) | 130 | void *wil_if_alloc(struct device *dev, void __iomem *csr) |
126 | { | 131 | { |
127 | struct net_device *ndev; | 132 | struct net_device *ndev; |
@@ -153,7 +158,7 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) | |||
153 | ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; | 158 | ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; |
154 | cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); | 159 | cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); |
155 | 160 | ||
156 | ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup); | 161 | ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, wil_dev_setup); |
157 | if (!ndev) { | 162 | if (!ndev) { |
158 | dev_err(dev, "alloc_netdev_mqs failed\n"); | 163 | dev_err(dev, "alloc_netdev_mqs failed\n"); |
159 | rc = -ENOMEM; | 164 | rc = -ENOMEM; |
@@ -174,7 +179,7 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) | |||
174 | netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, | 179 | netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, |
175 | WIL6210_NAPI_BUDGET); | 180 | WIL6210_NAPI_BUDGET); |
176 | 181 | ||
177 | wil_link_off(wil); | 182 | netif_tx_stop_all_queues(ndev); |
178 | 183 | ||
179 | return wil; | 184 | return wil; |
180 | 185 | ||
@@ -217,8 +222,6 @@ int wil_if_add(struct wil6210_priv *wil) | |||
217 | return rc; | 222 | return rc; |
218 | } | 223 | } |
219 | 224 | ||
220 | wil_link_off(wil); | ||
221 | |||
222 | return 0; | 225 | return 0; |
223 | } | 226 | } |
224 | 227 | ||
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 552209227de9..ca10dcf0986e 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -292,6 +292,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
292 | u16 agg_timeout = req->ba_timeout; | 292 | u16 agg_timeout = req->ba_timeout; |
293 | u16 status = WLAN_STATUS_SUCCESS; | 293 | u16 status = WLAN_STATUS_SUCCESS; |
294 | u16 ssn = req->ba_seq_ctrl >> 4; | 294 | u16 ssn = req->ba_seq_ctrl >> 4; |
295 | struct wil_tid_ampdu_rx *r; | ||
295 | int rc; | 296 | int rc; |
296 | 297 | ||
297 | might_sleep(); | 298 | might_sleep(); |
@@ -328,11 +329,10 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
328 | return; | 329 | return; |
329 | 330 | ||
330 | /* apply */ | 331 | /* apply */ |
332 | r = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn); | ||
331 | spin_lock_bh(&sta->tid_rx_lock); | 333 | spin_lock_bh(&sta->tid_rx_lock); |
332 | |||
333 | wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]); | 334 | wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]); |
334 | sta->tid_rx[tid] = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn); | 335 | sta->tid_rx[tid] = r; |
335 | |||
336 | spin_unlock_bh(&sta->tid_rx_lock); | 336 | spin_unlock_bh(&sta->tid_rx_lock); |
337 | } | 337 | } |
338 | 338 | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index b58ee52e1860..8439f65db259 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -671,6 +671,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
671 | } | 671 | } |
672 | 672 | ||
673 | memset(txdata, 0, sizeof(*txdata)); | 673 | memset(txdata, 0, sizeof(*txdata)); |
674 | spin_lock_init(&txdata->lock); | ||
674 | vring->size = size; | 675 | vring->size = size; |
675 | rc = wil_vring_alloc(wil, vring); | 676 | rc = wil_vring_alloc(wil, vring); |
676 | if (rc) | 677 | if (rc) |
@@ -718,8 +719,10 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | |||
718 | 719 | ||
719 | wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); | 720 | wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); |
720 | 721 | ||
722 | spin_lock_bh(&txdata->lock); | ||
723 | txdata->enabled = 0; /* no Tx can be in progress or start anew */ | ||
724 | spin_unlock_bh(&txdata->lock); | ||
721 | /* make sure NAPI won't touch this vring */ | 725 | /* make sure NAPI won't touch this vring */ |
722 | wil->vring_tx_data[id].enabled = 0; | ||
723 | if (test_bit(wil_status_napi_en, wil->status)) | 726 | if (test_bit(wil_status_napi_en, wil->status)) |
724 | napi_synchronize(&wil->napi_tx); | 727 | napi_synchronize(&wil->napi_tx); |
725 | 728 | ||
@@ -873,9 +876,6 @@ static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, | |||
873 | d->mac.d[1] = 0; | 876 | d->mac.d[1] = 0; |
874 | d->mac.d[2] = 0; | 877 | d->mac.d[2] = 0; |
875 | d->mac.ucode_cmd = 0; | 878 | d->mac.ucode_cmd = 0; |
876 | /* use dst index 0 */ | ||
877 | d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | | ||
878 | (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); | ||
879 | /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ | 879 | /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ |
880 | d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | | 880 | d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | |
881 | (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); | 881 | (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); |
@@ -938,8 +938,8 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil, | |||
938 | return 0; | 938 | return 0; |
939 | } | 939 | } |
940 | 940 | ||
941 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 941 | static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, |
942 | struct sk_buff *skb) | 942 | struct sk_buff *skb) |
943 | { | 943 | { |
944 | struct device *dev = wil_to_dev(wil); | 944 | struct device *dev = wil_to_dev(wil); |
945 | struct vring_tx_desc dd, *d = ⅆ | 945 | struct vring_tx_desc dd, *d = ⅆ |
@@ -955,18 +955,21 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
955 | 955 | ||
956 | wil_dbg_txrx(wil, "%s()\n", __func__); | 956 | wil_dbg_txrx(wil, "%s()\n", __func__); |
957 | 957 | ||
958 | if (unlikely(!txdata->enabled)) | ||
959 | return -EINVAL; | ||
960 | |||
958 | if (avail < 1 + nr_frags) { | 961 | if (avail < 1 + nr_frags) { |
959 | wil_err_ratelimited(wil, | 962 | wil_err_ratelimited(wil, |
960 | "Tx ring full. No space for %d fragments\n", | 963 | "Tx ring[%2d] full. No space for %d fragments\n", |
961 | 1 + nr_frags); | 964 | vring_index, 1 + nr_frags); |
962 | return -ENOMEM; | 965 | return -ENOMEM; |
963 | } | 966 | } |
964 | _d = &vring->va[i].tx; | 967 | _d = &vring->va[i].tx; |
965 | 968 | ||
966 | pa = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); | 969 | pa = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); |
967 | 970 | ||
968 | wil_dbg_txrx(wil, "Tx skb %d bytes 0x%p -> %pad\n", skb_headlen(skb), | 971 | wil_dbg_txrx(wil, "Tx[%2d] skb %d bytes 0x%p -> %pad\n", vring_index, |
969 | skb->data, &pa); | 972 | skb_headlen(skb), skb->data, &pa); |
970 | wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1, | 973 | wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1, |
971 | skb->data, skb_headlen(skb), false); | 974 | skb->data, skb_headlen(skb), false); |
972 | 975 | ||
@@ -977,15 +980,13 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
977 | wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); | 980 | wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); |
978 | /* Process TCP/UDP checksum offloading */ | 981 | /* Process TCP/UDP checksum offloading */ |
979 | if (wil_tx_desc_offload_cksum_set(wil, d, skb)) { | 982 | if (wil_tx_desc_offload_cksum_set(wil, d, skb)) { |
980 | wil_err(wil, "VRING #%d Failed to set cksum, drop packet\n", | 983 | wil_err(wil, "Tx[%2d] Failed to set cksum, drop packet\n", |
981 | vring_index); | 984 | vring_index); |
982 | goto dma_error; | 985 | goto dma_error; |
983 | } | 986 | } |
984 | 987 | ||
985 | vring->ctx[i].nr_frags = nr_frags; | 988 | vring->ctx[i].nr_frags = nr_frags; |
986 | wil_tx_desc_set_nr_frags(d, nr_frags); | 989 | wil_tx_desc_set_nr_frags(d, nr_frags); |
987 | if (nr_frags) | ||
988 | *_d = *d; | ||
989 | 990 | ||
990 | /* middle segments */ | 991 | /* middle segments */ |
991 | for (; f < nr_frags; f++) { | 992 | for (; f < nr_frags; f++) { |
@@ -993,6 +994,10 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
993 | &skb_shinfo(skb)->frags[f]; | 994 | &skb_shinfo(skb)->frags[f]; |
994 | int len = skb_frag_size(frag); | 995 | int len = skb_frag_size(frag); |
995 | 996 | ||
997 | *_d = *d; | ||
998 | wil_dbg_txrx(wil, "Tx[%2d] desc[%4d]\n", vring_index, i); | ||
999 | wil_hex_dump_txrx("TxD ", DUMP_PREFIX_NONE, 32, 4, | ||
1000 | (const void *)d, sizeof(*d), false); | ||
996 | i = (swhead + f + 1) % vring->size; | 1001 | i = (swhead + f + 1) % vring->size; |
997 | _d = &vring->va[i].tx; | 1002 | _d = &vring->va[i].tx; |
998 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | 1003 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), |
@@ -1006,13 +1011,15 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1006 | * it will succeed here too | 1011 | * it will succeed here too |
1007 | */ | 1012 | */ |
1008 | wil_tx_desc_offload_cksum_set(wil, d, skb); | 1013 | wil_tx_desc_offload_cksum_set(wil, d, skb); |
1009 | *_d = *d; | ||
1010 | } | 1014 | } |
1011 | /* for the last seg only */ | 1015 | /* for the last seg only */ |
1012 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); | 1016 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); |
1013 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS); | 1017 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS); |
1014 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); | 1018 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); |
1015 | *_d = *d; | 1019 | *_d = *d; |
1020 | wil_dbg_txrx(wil, "Tx[%2d] desc[%4d]\n", vring_index, i); | ||
1021 | wil_hex_dump_txrx("TxD ", DUMP_PREFIX_NONE, 32, 4, | ||
1022 | (const void *)d, sizeof(*d), false); | ||
1016 | 1023 | ||
1017 | /* hold reference to skb | 1024 | /* hold reference to skb |
1018 | * to prevent skb release before accounting | 1025 | * to prevent skb release before accounting |
@@ -1020,15 +1027,13 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1020 | */ | 1027 | */ |
1021 | vring->ctx[i].skb = skb_get(skb); | 1028 | vring->ctx[i].skb = skb_get(skb); |
1022 | 1029 | ||
1023 | wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4, | ||
1024 | (const void *)d, sizeof(*d), false); | ||
1025 | |||
1026 | if (wil_vring_is_empty(vring)) /* performance monitoring */ | 1030 | if (wil_vring_is_empty(vring)) /* performance monitoring */ |
1027 | txdata->idle += get_cycles() - txdata->last_idle; | 1031 | txdata->idle += get_cycles() - txdata->last_idle; |
1028 | 1032 | ||
1029 | /* advance swhead */ | 1033 | /* advance swhead */ |
1030 | wil_vring_advance_head(vring, nr_frags + 1); | 1034 | wil_vring_advance_head(vring, nr_frags + 1); |
1031 | wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); | 1035 | wil_dbg_txrx(wil, "Tx[%2d] swhead %d -> %d\n", vring_index, swhead, |
1036 | vring->swhead); | ||
1032 | trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags); | 1037 | trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags); |
1033 | iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); | 1038 | iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); |
1034 | 1039 | ||
@@ -1055,6 +1060,19 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1055 | return -EINVAL; | 1060 | return -EINVAL; |
1056 | } | 1061 | } |
1057 | 1062 | ||
1063 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | ||
1064 | struct sk_buff *skb) | ||
1065 | { | ||
1066 | int vring_index = vring - wil->vring_tx; | ||
1067 | struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; | ||
1068 | int rc; | ||
1069 | |||
1070 | spin_lock(&txdata->lock); | ||
1071 | rc = __wil_tx_vring(wil, vring, skb); | ||
1072 | spin_unlock(&txdata->lock); | ||
1073 | return rc; | ||
1074 | } | ||
1075 | |||
1058 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 1076 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
1059 | { | 1077 | { |
1060 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 1078 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
@@ -1121,6 +1139,22 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
1121 | return NET_XMIT_DROP; | 1139 | return NET_XMIT_DROP; |
1122 | } | 1140 | } |
1123 | 1141 | ||
1142 | static inline bool wil_need_txstat(struct sk_buff *skb) | ||
1143 | { | ||
1144 | struct ethhdr *eth = (void *)skb->data; | ||
1145 | |||
1146 | return is_unicast_ether_addr(eth->h_dest) && skb->sk && | ||
1147 | (skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS); | ||
1148 | } | ||
1149 | |||
1150 | static inline void wil_consume_skb(struct sk_buff *skb, bool acked) | ||
1151 | { | ||
1152 | if (unlikely(wil_need_txstat(skb))) | ||
1153 | skb_complete_wifi_ack(skb, acked); | ||
1154 | else | ||
1155 | acked ? dev_consume_skb_any(skb) : dev_kfree_skb_any(skb); | ||
1156 | } | ||
1157 | |||
1124 | /** | 1158 | /** |
1125 | * Clean up transmitted skb's from the Tx VRING | 1159 | * Clean up transmitted skb's from the Tx VRING |
1126 | * | 1160 | * |
@@ -1181,10 +1215,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
1181 | trace_wil6210_tx_done(ringid, vring->swtail, dmalen, | 1215 | trace_wil6210_tx_done(ringid, vring->swtail, dmalen, |
1182 | d->dma.error); | 1216 | d->dma.error); |
1183 | wil_dbg_txrx(wil, | 1217 | wil_dbg_txrx(wil, |
1184 | "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", | 1218 | "TxC[%2d][%3d] : %d bytes, status 0x%02x err 0x%02x\n", |
1185 | vring->swtail, dmalen, d->dma.status, | 1219 | ringid, vring->swtail, dmalen, |
1186 | d->dma.error); | 1220 | d->dma.status, d->dma.error); |
1187 | wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4, | 1221 | wil_hex_dump_txrx("TxCD ", DUMP_PREFIX_NONE, 32, 4, |
1188 | (const void *)d, sizeof(*d), false); | 1222 | (const void *)d, sizeof(*d), false); |
1189 | 1223 | ||
1190 | wil_txdesc_unmap(dev, d, ctx); | 1224 | wil_txdesc_unmap(dev, d, ctx); |
@@ -1199,8 +1233,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
1199 | ndev->stats.tx_errors++; | 1233 | ndev->stats.tx_errors++; |
1200 | stats->tx_errors++; | 1234 | stats->tx_errors++; |
1201 | } | 1235 | } |
1202 | 1236 | wil_consume_skb(skb, d->dma.error == 0); | |
1203 | dev_kfree_skb_any(skb); | ||
1204 | } | 1237 | } |
1205 | memset(ctx, 0, sizeof(*ctx)); | 1238 | memset(ctx, 0, sizeof(*ctx)); |
1206 | /* There is no need to touch HW descriptor: | 1239 | /* There is no need to touch HW descriptor: |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index da3fe7853d63..94611568fc9a 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -44,8 +44,9 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
44 | 44 | ||
45 | #define WIL6210_MEM_SIZE (2*1024*1024UL) | 45 | #define WIL6210_MEM_SIZE (2*1024*1024UL) |
46 | 46 | ||
47 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (9) | 47 | #define WIL_TX_Q_LEN_DEFAULT (4000) |
48 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (9) | 48 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) |
49 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (10) | ||
49 | /* limit ring size in range [32..32k] */ | 50 | /* limit ring size in range [32..32k] */ |
50 | #define WIL_RING_SIZE_ORDER_MIN (5) | 51 | #define WIL_RING_SIZE_ORDER_MIN (5) |
51 | #define WIL_RING_SIZE_ORDER_MAX (15) | 52 | #define WIL_RING_SIZE_ORDER_MAX (15) |
@@ -77,8 +78,8 @@ static inline u32 wil_mtu2macbuf(u32 mtu) | |||
77 | #define WIL_MAX_ETH_MTU (IEEE80211_MAX_DATA_LEN_DMG - 8) | 78 | #define WIL_MAX_ETH_MTU (IEEE80211_MAX_DATA_LEN_DMG - 8) |
78 | /* Max supported by wil6210 value for interrupt threshold is 5sec. */ | 79 | /* Max supported by wil6210 value for interrupt threshold is 5sec. */ |
79 | #define WIL6210_ITR_TRSH_MAX (5000000) | 80 | #define WIL6210_ITR_TRSH_MAX (5000000) |
80 | #define WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT (15) /* usec */ | 81 | #define WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT (13) /* usec */ |
81 | #define WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT (15) /* usec */ | 82 | #define WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT (13) /* usec */ |
82 | #define WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ | 83 | #define WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ |
83 | #define WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ | 84 | #define WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ |
84 | #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ | 85 | #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ |
@@ -384,6 +385,7 @@ struct vring_tx_data { | |||
384 | u16 agg_timeout; | 385 | u16 agg_timeout; |
385 | u8 agg_amsdu; | 386 | u8 agg_amsdu; |
386 | bool addba_in_progress; /* if set, agg_xxx is for request in progress */ | 387 | bool addba_in_progress; /* if set, agg_xxx is for request in progress */ |
388 | spinlock_t lock; | ||
387 | }; | 389 | }; |
388 | 390 | ||
389 | enum { /* for wil6210_priv.status */ | 391 | enum { /* for wil6210_priv.status */ |
@@ -503,6 +505,12 @@ struct wil_back_tx { | |||
503 | u16 agg_timeout; | 505 | u16 agg_timeout; |
504 | }; | 506 | }; |
505 | 507 | ||
508 | struct wil_probe_client_req { | ||
509 | struct list_head list; | ||
510 | u64 cookie; | ||
511 | u8 cid; | ||
512 | }; | ||
513 | |||
506 | struct wil6210_priv { | 514 | struct wil6210_priv { |
507 | struct pci_dev *pdev; | 515 | struct pci_dev *pdev; |
508 | int n_msi; | 516 | int n_msi; |
@@ -563,6 +571,10 @@ struct wil6210_priv { | |||
563 | struct list_head back_tx_pending; | 571 | struct list_head back_tx_pending; |
564 | struct mutex back_tx_mutex; /* protect @back_tx_pending */ | 572 | struct mutex back_tx_mutex; /* protect @back_tx_pending */ |
565 | struct work_struct back_tx_worker; | 573 | struct work_struct back_tx_worker; |
574 | /* keep alive */ | ||
575 | struct list_head probe_client_pending; | ||
576 | struct mutex probe_client_mutex; /* protect @probe_client_pending */ | ||
577 | struct work_struct probe_client_worker; | ||
566 | /* DMA related */ | 578 | /* DMA related */ |
567 | struct vring vring_rx; | 579 | struct vring vring_rx; |
568 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; | 580 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; |
@@ -649,8 +661,6 @@ void wil_priv_deinit(struct wil6210_priv *wil); | |||
649 | int wil_reset(struct wil6210_priv *wil); | 661 | int wil_reset(struct wil6210_priv *wil); |
650 | void wil_fw_error_recovery(struct wil6210_priv *wil); | 662 | void wil_fw_error_recovery(struct wil6210_priv *wil); |
651 | void wil_set_recovery_state(struct wil6210_priv *wil, int state); | 663 | void wil_set_recovery_state(struct wil6210_priv *wil, int state); |
652 | void wil_link_on(struct wil6210_priv *wil); | ||
653 | void wil_link_off(struct wil6210_priv *wil); | ||
654 | int wil_up(struct wil6210_priv *wil); | 664 | int wil_up(struct wil6210_priv *wil); |
655 | int __wil_up(struct wil6210_priv *wil); | 665 | int __wil_up(struct wil6210_priv *wil); |
656 | int wil_down(struct wil6210_priv *wil); | 666 | int wil_down(struct wil6210_priv *wil); |
@@ -723,6 +733,8 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); | |||
723 | int wmi_pcp_stop(struct wil6210_priv *wil); | 733 | int wmi_pcp_stop(struct wil6210_priv *wil); |
724 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 734 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, |
725 | u16 reason_code, bool from_event); | 735 | u16 reason_code, bool from_event); |
736 | void wil_probe_client_flush(struct wil6210_priv *wil); | ||
737 | void wil_probe_client_worker(struct work_struct *work); | ||
726 | 738 | ||
727 | int wil_rx_init(struct wil6210_priv *wil, u16 size); | 739 | int wil_rx_init(struct wil6210_priv *wil, u16 size); |
728 | void wil_rx_fini(struct wil6210_priv *wil); | 740 | void wil_rx_fini(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.c b/drivers/net/wireless/ath/wil6210/wil_platform.c index 8f1d78f8a74d..976a071ba74e 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.c +++ b/drivers/net/wireless/ath/wil6210/wil_platform.c | |||
@@ -17,10 +17,6 @@ | |||
17 | #include "linux/device.h" | 17 | #include "linux/device.h" |
18 | #include "wil_platform.h" | 18 | #include "wil_platform.h" |
19 | 19 | ||
20 | #ifdef CONFIG_WIL6210_PLATFORM_MSM | ||
21 | #include "wil_platform_msm.h" | ||
22 | #endif | ||
23 | |||
24 | /** | 20 | /** |
25 | * wil_platform_init() - wil6210 platform module init | 21 | * wil_platform_init() - wil6210 platform module init |
26 | * | 22 | * |
@@ -37,13 +33,7 @@ void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops) | |||
37 | return NULL; | 33 | return NULL; |
38 | } | 34 | } |
39 | 35 | ||
40 | #ifdef CONFIG_WIL6210_PLATFORM_MSM | 36 | /* platform specific init functions should be called here */ |
41 | handle = wil_platform_msm_init(dev, ops); | ||
42 | if (handle) | ||
43 | return handle; | ||
44 | #endif | ||
45 | |||
46 | /* other platform specific init functions should be called here */ | ||
47 | 37 | ||
48 | return handle; | 38 | return handle; |
49 | } | 39 | } |
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform_msm.c b/drivers/net/wireless/ath/wil6210/wil_platform_msm.c deleted file mode 100644 index b354a743240d..000000000000 --- a/drivers/net/wireless/ath/wil6210/wil_platform_msm.c +++ /dev/null | |||
@@ -1,257 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 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/of.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/msm-bus.h> | ||
20 | |||
21 | #include "wil_platform.h" | ||
22 | #include "wil_platform_msm.h" | ||
23 | |||
24 | /** | ||
25 | * struct wil_platform_msm - wil6210 msm platform module info | ||
26 | * | ||
27 | * @dev: device object | ||
28 | * @msm_bus_handle: handle for using msm_bus API | ||
29 | * @pdata: bus scale info retrieved from DT | ||
30 | */ | ||
31 | struct wil_platform_msm { | ||
32 | struct device *dev; | ||
33 | uint32_t msm_bus_handle; | ||
34 | struct msm_bus_scale_pdata *pdata; | ||
35 | }; | ||
36 | |||
37 | #define KBTOB(a) (a * 1000ULL) | ||
38 | |||
39 | /** | ||
40 | * wil_platform_get_pdata() - Generate bus client data from device tree | ||
41 | * provided by clients. | ||
42 | * | ||
43 | * dev: device object | ||
44 | * of_node: Device tree node to extract information from | ||
45 | * | ||
46 | * The function returns a valid pointer to the allocated bus-scale-pdata | ||
47 | * if the vectors were correctly read from the client's device node. | ||
48 | * Any error in reading or parsing the device node will return NULL | ||
49 | * to the caller. | ||
50 | */ | ||
51 | static struct msm_bus_scale_pdata *wil_platform_get_pdata( | ||
52 | struct device *dev, | ||
53 | struct device_node *of_node) | ||
54 | { | ||
55 | struct msm_bus_scale_pdata *pdata; | ||
56 | struct msm_bus_paths *usecase; | ||
57 | int i, j, ret, len; | ||
58 | unsigned int num_usecases, num_paths, mem_size; | ||
59 | const uint32_t *vec_arr; | ||
60 | struct msm_bus_vectors *vectors; | ||
61 | |||
62 | /* first read num_usecases and num_paths so we can calculate | ||
63 | * amount of memory to allocate | ||
64 | */ | ||
65 | ret = of_property_read_u32(of_node, "qcom,msm-bus,num-cases", | ||
66 | &num_usecases); | ||
67 | if (ret) { | ||
68 | dev_err(dev, "Error: num-usecases not found\n"); | ||
69 | return NULL; | ||
70 | } | ||
71 | |||
72 | ret = of_property_read_u32(of_node, "qcom,msm-bus,num-paths", | ||
73 | &num_paths); | ||
74 | if (ret) { | ||
75 | dev_err(dev, "Error: num_paths not found\n"); | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | /* pdata memory layout: | ||
80 | * msm_bus_scale_pdata | ||
81 | * msm_bus_paths[num_usecases] | ||
82 | * msm_bus_vectors[num_usecases][num_paths] | ||
83 | */ | ||
84 | mem_size = sizeof(struct msm_bus_scale_pdata) + | ||
85 | sizeof(struct msm_bus_paths) * num_usecases + | ||
86 | sizeof(struct msm_bus_vectors) * num_usecases * num_paths; | ||
87 | |||
88 | pdata = kzalloc(mem_size, GFP_KERNEL); | ||
89 | if (!pdata) | ||
90 | return NULL; | ||
91 | |||
92 | ret = of_property_read_string(of_node, "qcom,msm-bus,name", | ||
93 | &pdata->name); | ||
94 | if (ret) { | ||
95 | dev_err(dev, "Error: Client name not found\n"); | ||
96 | goto err; | ||
97 | } | ||
98 | |||
99 | if (of_property_read_bool(of_node, "qcom,msm-bus,active-only")) { | ||
100 | pdata->active_only = 1; | ||
101 | } else { | ||
102 | dev_info(dev, "active_only flag absent.\n"); | ||
103 | dev_info(dev, "Using dual context by default\n"); | ||
104 | } | ||
105 | |||
106 | pdata->num_usecases = num_usecases; | ||
107 | pdata->usecase = (struct msm_bus_paths *)(pdata + 1); | ||
108 | |||
109 | vec_arr = of_get_property(of_node, "qcom,msm-bus,vectors-KBps", &len); | ||
110 | if (vec_arr == NULL) { | ||
111 | dev_err(dev, "Error: Vector array not found\n"); | ||
112 | goto err; | ||
113 | } | ||
114 | |||
115 | if (len != num_usecases * num_paths * sizeof(uint32_t) * 4) { | ||
116 | dev_err(dev, "Error: Length-error on getting vectors\n"); | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | vectors = (struct msm_bus_vectors *)(pdata->usecase + num_usecases); | ||
121 | for (i = 0; i < num_usecases; i++) { | ||
122 | usecase = &pdata->usecase[i]; | ||
123 | usecase->num_paths = num_paths; | ||
124 | usecase->vectors = &vectors[i]; | ||
125 | |||
126 | for (j = 0; j < num_paths; j++) { | ||
127 | int index = ((i * num_paths) + j) * 4; | ||
128 | |||
129 | usecase->vectors[j].src = be32_to_cpu(vec_arr[index]); | ||
130 | usecase->vectors[j].dst = | ||
131 | be32_to_cpu(vec_arr[index + 1]); | ||
132 | usecase->vectors[j].ab = (uint64_t) | ||
133 | KBTOB(be32_to_cpu(vec_arr[index + 2])); | ||
134 | usecase->vectors[j].ib = (uint64_t) | ||
135 | KBTOB(be32_to_cpu(vec_arr[index + 3])); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | return pdata; | ||
140 | |||
141 | err: | ||
142 | kfree(pdata); | ||
143 | |||
144 | return NULL; | ||
145 | } | ||
146 | |||
147 | /* wil_platform API (callbacks) */ | ||
148 | |||
149 | static int wil_platform_bus_request(void *handle, | ||
150 | uint32_t kbps /* KBytes/Sec */) | ||
151 | { | ||
152 | int rc, i; | ||
153 | struct wil_platform_msm *msm = (struct wil_platform_msm *)handle; | ||
154 | int vote = 0; /* vote 0 in case requested kbps cannot be satisfied */ | ||
155 | struct msm_bus_paths *usecase; | ||
156 | uint32_t usecase_kbps; | ||
157 | uint32_t min_kbps = ~0; | ||
158 | |||
159 | /* find the lowest usecase that is bigger than requested kbps */ | ||
160 | for (i = 0; i < msm->pdata->num_usecases; i++) { | ||
161 | usecase = &msm->pdata->usecase[i]; | ||
162 | /* assume we have single path (vectors[0]). If we ever | ||
163 | * have multiple paths, need to define the behavior */ | ||
164 | usecase_kbps = div64_u64(usecase->vectors[0].ib, 1000); | ||
165 | if (usecase_kbps >= kbps && usecase_kbps < min_kbps) { | ||
166 | min_kbps = usecase_kbps; | ||
167 | vote = i; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | rc = msm_bus_scale_client_update_request(msm->msm_bus_handle, vote); | ||
172 | if (rc) | ||
173 | dev_err(msm->dev, "Failed msm_bus voting. kbps=%d vote=%d, rc=%d\n", | ||
174 | kbps, vote, rc); | ||
175 | else | ||
176 | /* TOOD: remove */ | ||
177 | dev_info(msm->dev, "msm_bus_scale_client_update_request succeeded. kbps=%d vote=%d\n", | ||
178 | kbps, vote); | ||
179 | |||
180 | return rc; | ||
181 | } | ||
182 | |||
183 | static void wil_platform_uninit(void *handle) | ||
184 | { | ||
185 | struct wil_platform_msm *msm = (struct wil_platform_msm *)handle; | ||
186 | |||
187 | dev_info(msm->dev, "wil_platform_uninit\n"); | ||
188 | |||
189 | if (msm->msm_bus_handle) | ||
190 | msm_bus_scale_unregister_client(msm->msm_bus_handle); | ||
191 | |||
192 | kfree(msm->pdata); | ||
193 | kfree(msm); | ||
194 | } | ||
195 | |||
196 | static int wil_platform_msm_bus_register(struct wil_platform_msm *msm, | ||
197 | struct device_node *node) | ||
198 | { | ||
199 | msm->pdata = wil_platform_get_pdata(msm->dev, node); | ||
200 | if (!msm->pdata) { | ||
201 | dev_err(msm->dev, "Failed getting DT info\n"); | ||
202 | return -EINVAL; | ||
203 | } | ||
204 | |||
205 | msm->msm_bus_handle = msm_bus_scale_register_client(msm->pdata); | ||
206 | if (!msm->msm_bus_handle) { | ||
207 | dev_err(msm->dev, "Failed msm_bus registration\n"); | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | dev_info(msm->dev, "msm_bus registration succeeded! handle 0x%x\n", | ||
212 | msm->msm_bus_handle); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * wil_platform_msm_init() - wil6210 msm platform module init | ||
219 | * | ||
220 | * The function must be called before all other functions in this module. | ||
221 | * It returns a handle which is used with the rest of the API | ||
222 | * | ||
223 | */ | ||
224 | void *wil_platform_msm_init(struct device *dev, struct wil_platform_ops *ops) | ||
225 | { | ||
226 | struct device_node *of_node; | ||
227 | struct wil_platform_msm *msm; | ||
228 | int rc; | ||
229 | |||
230 | of_node = of_find_compatible_node(NULL, NULL, "qcom,wil6210"); | ||
231 | if (!of_node) { | ||
232 | /* this could mean non-msm platform */ | ||
233 | dev_err(dev, "DT node not found\n"); | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | msm = kzalloc(sizeof(*msm), GFP_KERNEL); | ||
238 | if (!msm) | ||
239 | return NULL; | ||
240 | |||
241 | msm->dev = dev; | ||
242 | |||
243 | /* register with msm_bus module for scaling requests */ | ||
244 | rc = wil_platform_msm_bus_register(msm, of_node); | ||
245 | if (rc) | ||
246 | goto cleanup; | ||
247 | |||
248 | memset(ops, 0, sizeof(*ops)); | ||
249 | ops->bus_request = wil_platform_bus_request; | ||
250 | ops->uninit = wil_platform_uninit; | ||
251 | |||
252 | return (void *)msm; | ||
253 | |||
254 | cleanup: | ||
255 | kfree(msm); | ||
256 | return NULL; | ||
257 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform_msm.h b/drivers/net/wireless/ath/wil6210/wil_platform_msm.h deleted file mode 100644 index 2f2229edb498..000000000000 --- a/drivers/net/wireless/ath/wil6210/wil_platform_msm.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 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 __WIL_PLATFORM__MSM_H__ | ||
18 | #define __WIL_PLATFORM_MSM_H__ | ||
19 | |||
20 | #include "wil_platform.h" | ||
21 | |||
22 | void *wil_platform_msm_init(struct device *dev, struct wil_platform_ops *ops); | ||
23 | |||
24 | #endif /* __WIL_PLATFORM__MSM_H__ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index b2b0fe1faa96..0f3e4334c8e3 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -566,7 +566,6 @@ static void wil_addba_tx_cid(struct wil6210_priv *wil, u8 cid, u16 wsize) | |||
566 | 566 | ||
567 | static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) | 567 | static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) |
568 | { | 568 | { |
569 | struct net_device *ndev = wil_to_ndev(wil); | ||
570 | struct wmi_data_port_open_event *evt = d; | 569 | struct wmi_data_port_open_event *evt = d; |
571 | u8 cid = evt->cid; | 570 | u8 cid = evt->cid; |
572 | 571 | ||
@@ -580,7 +579,6 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) | |||
580 | wil->sta[cid].data_port_open = true; | 579 | wil->sta[cid].data_port_open = true; |
581 | if (agg_wsize >= 0) | 580 | if (agg_wsize >= 0) |
582 | wil_addba_tx_cid(wil, cid, agg_wsize); | 581 | wil_addba_tx_cid(wil, cid, agg_wsize); |
583 | netif_carrier_on(ndev); | ||
584 | } | 582 | } |
585 | 583 | ||
586 | static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) | 584 | static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) |
@@ -1133,12 +1131,13 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
1133 | return rc; | 1131 | return rc; |
1134 | } | 1132 | } |
1135 | 1133 | ||
1136 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r) | 1134 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) |
1137 | { | 1135 | { |
1138 | int rc; | 1136 | int rc; |
1139 | struct wmi_temp_sense_cmd cmd = { | 1137 | struct wmi_temp_sense_cmd cmd = { |
1140 | .measure_marlon_m_en = cpu_to_le32(!!t_m), | 1138 | .measure_baseband_en = cpu_to_le32(!!t_bb), |
1141 | .measure_marlon_r_en = cpu_to_le32(!!t_r), | 1139 | .measure_rf_en = cpu_to_le32(!!t_rf), |
1140 | .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW), | ||
1142 | }; | 1141 | }; |
1143 | struct { | 1142 | struct { |
1144 | struct wil6210_mbox_hdr_wmi wmi; | 1143 | struct wil6210_mbox_hdr_wmi wmi; |
@@ -1150,10 +1149,10 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r) | |||
1150 | if (rc) | 1149 | if (rc) |
1151 | return rc; | 1150 | return rc; |
1152 | 1151 | ||
1153 | if (t_m) | 1152 | if (t_bb) |
1154 | *t_m = le32_to_cpu(reply.evt.marlon_m_t1000); | 1153 | *t_bb = le32_to_cpu(reply.evt.baseband_t1000); |
1155 | if (t_r) | 1154 | if (t_rf) |
1156 | *t_r = le32_to_cpu(reply.evt.marlon_r_t1000); | 1155 | *t_rf = le32_to_cpu(reply.evt.rf_t1000); |
1157 | 1156 | ||
1158 | return 0; | 1157 | return 0; |
1159 | } | 1158 | } |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index b5102f0b97f4..8a4af613e191 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -29,8 +29,10 @@ | |||
29 | 29 | ||
30 | /* General */ | 30 | /* General */ |
31 | #define WILOCITY_MAX_ASSOC_STA (8) | 31 | #define WILOCITY_MAX_ASSOC_STA (8) |
32 | #define WILOCITY_DEFAULT_ASSOC_STA (1) | ||
32 | #define WMI_MAC_LEN (6) | 33 | #define WMI_MAC_LEN (6) |
33 | #define WMI_PROX_RANGE_NUM (3) | 34 | #define WMI_PROX_RANGE_NUM (3) |
35 | #define WMI_MAX_LOSS_DMG_BEACONS (32) | ||
34 | 36 | ||
35 | /* List of Commands */ | 37 | /* List of Commands */ |
36 | enum wmi_command_id { | 38 | enum wmi_command_id { |
@@ -48,7 +50,7 @@ enum wmi_command_id { | |||
48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, | 50 | WMI_SET_WSC_STATUS_CMDID = 0x0041, |
49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, | 51 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, |
50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, | 52 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, |
51 | WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, | 53 | /* WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, */ |
52 | WMI_MEM_READ_CMDID = 0x0800, | 54 | WMI_MEM_READ_CMDID = 0x0800, |
53 | WMI_MEM_WR_CMDID = 0x0801, | 55 | WMI_MEM_WR_CMDID = 0x0801, |
54 | WMI_ECHO_CMDID = 0x0803, | 56 | WMI_ECHO_CMDID = 0x0803, |
@@ -102,6 +104,8 @@ enum wmi_command_id { | |||
102 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, | 104 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, |
103 | WMI_RS_MGMT_CMDID = 0x0852, | 105 | WMI_RS_MGMT_CMDID = 0x0852, |
104 | WMI_RF_MGMT_CMDID = 0x0853, | 106 | WMI_RF_MGMT_CMDID = 0x0853, |
107 | WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x0854, | ||
108 | WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x0855, | ||
105 | /* Performance monitoring commands */ | 109 | /* Performance monitoring commands */ |
106 | WMI_BF_CTRL_CMDID = 0x0862, | 110 | WMI_BF_CTRL_CMDID = 0x0862, |
107 | WMI_NOTIFY_REQ_CMDID = 0x0863, | 111 | WMI_NOTIFY_REQ_CMDID = 0x0863, |
@@ -136,6 +140,7 @@ enum wmi_command_id { | |||
136 | WMI_EAPOL_TX_CMDID = 0xf04c, | 140 | WMI_EAPOL_TX_CMDID = 0xf04c, |
137 | WMI_MAC_ADDR_REQ_CMDID = 0xf04d, | 141 | WMI_MAC_ADDR_REQ_CMDID = 0xf04d, |
138 | WMI_FW_VER_CMDID = 0xf04e, | 142 | WMI_FW_VER_CMDID = 0xf04e, |
143 | WMI_PMC_CMDID = 0xf04f, | ||
139 | }; | 144 | }; |
140 | 145 | ||
141 | /* | 146 | /* |
@@ -283,8 +288,8 @@ enum wmi_scan_type { | |||
283 | WMI_LONG_SCAN = 0, | 288 | WMI_LONG_SCAN = 0, |
284 | WMI_SHORT_SCAN = 1, | 289 | WMI_SHORT_SCAN = 1, |
285 | WMI_PBC_SCAN = 2, | 290 | WMI_PBC_SCAN = 2, |
286 | WMI_ACTIVE_SCAN = 3, | 291 | WMI_DIRECT_SCAN = 3, |
287 | WMI_DIRECT_SCAN = 4, | 292 | WMI_ACTIVE_SCAN = 4, |
288 | }; | 293 | }; |
289 | 294 | ||
290 | struct wmi_start_scan_cmd { | 295 | struct wmi_start_scan_cmd { |
@@ -375,6 +380,17 @@ struct wmi_rf_mgmt_cmd { | |||
375 | } __packed; | 380 | } __packed; |
376 | 381 | ||
377 | /* | 382 | /* |
383 | * WMI_THERMAL_THROTTLING_CTRL_CMDID | ||
384 | */ | ||
385 | #define THERMAL_THROTTLING_USE_DEFAULT_MAX_TXOP_LENGTH (0xFFFFFFFF) | ||
386 | |||
387 | struct wmi_thermal_throttling_ctrl_cmd { | ||
388 | __le32 time_on_usec; | ||
389 | __le32 time_off_usec; | ||
390 | __le32 max_txop_length_usec; | ||
391 | } __packed; | ||
392 | |||
393 | /* | ||
378 | * WMI_RF_RX_TEST_CMDID | 394 | * WMI_RF_RX_TEST_CMDID |
379 | */ | 395 | */ |
380 | struct wmi_rf_rx_test_cmd { | 396 | struct wmi_rf_rx_test_cmd { |
@@ -648,6 +664,7 @@ enum wmi_cfg_rx_chain_cmd_action { | |||
648 | enum wmi_cfg_rx_chain_cmd_decap_trans_type { | 664 | enum wmi_cfg_rx_chain_cmd_decap_trans_type { |
649 | WMI_DECAP_TYPE_802_3 = 0, | 665 | WMI_DECAP_TYPE_802_3 = 0, |
650 | WMI_DECAP_TYPE_NATIVE_WIFI = 1, | 666 | WMI_DECAP_TYPE_NATIVE_WIFI = 1, |
667 | WMI_DECAP_TYPE_NONE = 2, | ||
651 | }; | 668 | }; |
652 | 669 | ||
653 | enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { | 670 | enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { |
@@ -785,9 +802,17 @@ struct wmi_echo_cmd { | |||
785 | * | 802 | * |
786 | * Measure MAC and radio temperatures | 803 | * Measure MAC and radio temperatures |
787 | */ | 804 | */ |
805 | |||
806 | /* Possible modes for temperature measurement */ | ||
807 | enum wmi_temperature_measure_mode { | ||
808 | TEMPERATURE_USE_OLD_VALUE = 0x1, | ||
809 | TEMPERATURE_MEASURE_NOW = 0x2, | ||
810 | }; | ||
811 | |||
788 | struct wmi_temp_sense_cmd { | 812 | struct wmi_temp_sense_cmd { |
789 | __le32 measure_marlon_m_en; | 813 | __le32 measure_baseband_en; |
790 | __le32 measure_marlon_r_en; | 814 | __le32 measure_rf_en; |
815 | __le32 measure_mode; | ||
791 | } __packed; | 816 | } __packed; |
792 | 817 | ||
793 | /* | 818 | /* |
@@ -843,6 +868,7 @@ enum wmi_event_id { | |||
843 | WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, | 868 | WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, |
844 | WMI_RS_MGMT_DONE_EVENTID = 0x1852, | 869 | WMI_RS_MGMT_DONE_EVENTID = 0x1852, |
845 | WMI_RF_MGMT_STATUS_EVENTID = 0x1853, | 870 | WMI_RF_MGMT_STATUS_EVENTID = 0x1853, |
871 | WMI_THERMAL_THROTTLING_STATUS_EVENTID = 0x1855, | ||
846 | WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, | 872 | WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, |
847 | WMI_RX_MGMT_PACKET_EVENTID = 0x1840, | 873 | WMI_RX_MGMT_PACKET_EVENTID = 0x1840, |
848 | WMI_TX_MGMT_PACKET_EVENTID = 0x1841, | 874 | WMI_TX_MGMT_PACKET_EVENTID = 0x1841, |
@@ -859,6 +885,7 @@ enum wmi_event_id { | |||
859 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, | 885 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, |
860 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, | 886 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, |
861 | /*P2P*/ | 887 | /*P2P*/ |
888 | WMI_P2P_CFG_DONE_EVENTID = 0x1910, | ||
862 | WMI_PORT_ALLOCATED_EVENTID = 0x1911, | 889 | WMI_PORT_ALLOCATED_EVENTID = 0x1911, |
863 | WMI_PORT_DELETED_EVENTID = 0x1912, | 890 | WMI_PORT_DELETED_EVENTID = 0x1912, |
864 | WMI_LISTEN_STARTED_EVENTID = 0x1914, | 891 | WMI_LISTEN_STARTED_EVENTID = 0x1914, |
@@ -899,6 +926,15 @@ struct wmi_rf_mgmt_status_event { | |||
899 | } __packed; | 926 | } __packed; |
900 | 927 | ||
901 | /* | 928 | /* |
929 | * WMI_THERMAL_THROTTLING_STATUS_EVENTID | ||
930 | */ | ||
931 | struct wmi_thermal_throttling_status_event { | ||
932 | __le32 time_on_usec; | ||
933 | __le32 time_off_usec; | ||
934 | __le32 max_txop_length_usec; | ||
935 | } __packed; | ||
936 | |||
937 | /* | ||
902 | * WMI_GET_STATUS_DONE_EVENTID | 938 | * WMI_GET_STATUS_DONE_EVENTID |
903 | */ | 939 | */ |
904 | struct wmi_get_status_done_event { | 940 | struct wmi_get_status_done_event { |
@@ -1155,6 +1191,14 @@ struct wmi_get_pcp_channel_event { | |||
1155 | } __packed; | 1191 | } __packed; |
1156 | 1192 | ||
1157 | /* | 1193 | /* |
1194 | * WMI_P2P_CFG_DONE_EVENTID | ||
1195 | */ | ||
1196 | struct wmi_p2p_cfg_done_event { | ||
1197 | u8 status; /* wmi_fw_status */ | ||
1198 | u8 reserved[3]; | ||
1199 | } __packed; | ||
1200 | |||
1201 | /* | ||
1158 | * WMI_PORT_ALLOCATED_EVENTID | 1202 | * WMI_PORT_ALLOCATED_EVENTID |
1159 | */ | 1203 | */ |
1160 | struct wmi_port_allocated_event { | 1204 | struct wmi_port_allocated_event { |
@@ -1282,8 +1326,8 @@ struct wmi_echo_event { | |||
1282 | * Measure MAC and radio temperatures | 1326 | * Measure MAC and radio temperatures |
1283 | */ | 1327 | */ |
1284 | struct wmi_temp_sense_done_event { | 1328 | struct wmi_temp_sense_done_event { |
1285 | __le32 marlon_m_t1000; | 1329 | __le32 baseband_t1000; |
1286 | __le32 marlon_r_t1000; | 1330 | __le32 rf_t1000; |
1287 | } __packed; | 1331 | } __packed; |
1288 | 1332 | ||
1289 | #endif /* __WILOCITY_WMI_H__ */ | 1333 | #endif /* __WILOCITY_WMI_H__ */ |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 64a5b672e30a..759fb8d41fc9 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -166,6 +166,15 @@ config B43_PHY_LCN | |||
166 | 166 | ||
167 | Say N, this is BROKEN and crashes driver. | 167 | Say N, this is BROKEN and crashes driver. |
168 | 168 | ||
169 | config B43_PHY_AC | ||
170 | bool "Support for AC-PHY (802.11ac) devices (BROKEN)" | ||
171 | depends on B43 && B43_BCMA && BROKEN | ||
172 | ---help--- | ||
173 | This PHY type can be found in the following chipsets: | ||
174 | PCI: BCM4352, BCM4360 | ||
175 | |||
176 | Say N, this is BROKEN and crashes driver. | ||
177 | |||
169 | # This config option automatically enables b43 LEDS support, | 178 | # This config option automatically enables b43 LEDS support, |
170 | # if it's possible. | 179 | # if it's possible. |
171 | config B43_LEDS | 180 | config B43_LEDS |
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 9f7965aae93d..c624d4d90e4f 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
@@ -13,6 +13,7 @@ b43-$(CONFIG_B43_PHY_HT) += phy_ht.o | |||
13 | b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o | 13 | b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o |
14 | b43-$(CONFIG_B43_PHY_HT) += radio_2059.o | 14 | b43-$(CONFIG_B43_PHY_HT) += radio_2059.o |
15 | b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o | 15 | b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o |
16 | b43-$(CONFIG_B43_PHY_AC) += phy_ac.o | ||
16 | b43-y += sysfs.o | 17 | b43-y += sysfs.o |
17 | b43-y += xmit.o | 18 | b43-y += xmit.o |
18 | b43-y += dma.o | 19 | b43-y += dma.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index bb12586cd7cd..036552439816 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -500,6 +500,8 @@ enum { | |||
500 | #define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */ | 500 | #define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */ |
501 | #define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */ | 501 | #define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */ |
502 | #define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */ | 502 | #define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */ |
503 | #define B43_BCMA_IOCTL_PHY_BW_80MHZ 0x000000C0 /* 80 MHz bandwidth */ | ||
504 | #define B43_BCMA_IOCTL_DAC 0x00000300 /* Highspeed DAC mode control field */ | ||
503 | #define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */ | 505 | #define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */ |
504 | 506 | ||
505 | /* BCMA 802.11 core specific IO status (BCMA_IOST) flags */ | 507 | /* BCMA 802.11 core specific IO status (BCMA_IOST) flags */ |
@@ -941,6 +943,7 @@ struct b43_wl { | |||
941 | bool beacon1_uploaded; | 943 | bool beacon1_uploaded; |
942 | bool beacon_templates_virgin; /* Never wrote the templates? */ | 944 | bool beacon_templates_virgin; /* Never wrote the templates? */ |
943 | struct work_struct beacon_update_trigger; | 945 | struct work_struct beacon_update_trigger; |
946 | spinlock_t beacon_lock; | ||
944 | 947 | ||
945 | /* The current QOS parameters for the 4 queues. */ | 948 | /* The current QOS parameters for the 4 queues. */ |
946 | struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM]; | 949 | struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM]; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 58a2e88631fb..2c9088633ec6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1262,6 +1262,23 @@ static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) | |||
1262 | flags |= B43_BCMA_IOCTL_GMODE; | 1262 | flags |= B43_BCMA_IOCTL_GMODE; |
1263 | b43_device_enable(dev, flags); | 1263 | b43_device_enable(dev, flags); |
1264 | 1264 | ||
1265 | if (dev->phy.type == B43_PHYTYPE_AC) { | ||
1266 | u16 tmp; | ||
1267 | |||
1268 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
1269 | tmp &= ~B43_BCMA_IOCTL_DAC; | ||
1270 | tmp |= 0x100; | ||
1271 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
1272 | |||
1273 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
1274 | tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN; | ||
1275 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
1276 | |||
1277 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
1278 | tmp |= B43_BCMA_IOCTL_PHY_CLKEN; | ||
1279 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
1280 | } | ||
1281 | |||
1265 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); | 1282 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); |
1266 | b43_bcma_phy_reset(dev); | 1283 | b43_bcma_phy_reset(dev); |
1267 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); | 1284 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); |
@@ -1601,12 +1618,26 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
1601 | unsigned int rate; | 1618 | unsigned int rate; |
1602 | u16 ctl; | 1619 | u16 ctl; |
1603 | int antenna; | 1620 | int antenna; |
1604 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); | 1621 | struct ieee80211_tx_info *info; |
1622 | unsigned long flags; | ||
1623 | struct sk_buff *beacon_skb; | ||
1605 | 1624 | ||
1606 | bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); | 1625 | spin_lock_irqsave(&dev->wl->beacon_lock, flags); |
1607 | len = min_t(size_t, dev->wl->current_beacon->len, | 1626 | info = IEEE80211_SKB_CB(dev->wl->current_beacon); |
1608 | 0x200 - sizeof(struct b43_plcp_hdr6)); | ||
1609 | rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; | 1627 | rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; |
1628 | /* Clone the beacon, so it cannot go away, while we write it to hw. */ | ||
1629 | beacon_skb = skb_clone(dev->wl->current_beacon, GFP_ATOMIC); | ||
1630 | spin_unlock_irqrestore(&dev->wl->beacon_lock, flags); | ||
1631 | |||
1632 | if (!beacon_skb) { | ||
1633 | b43dbg(dev->wl, "Could not upload beacon. " | ||
1634 | "Failed to clone beacon skb."); | ||
1635 | return; | ||
1636 | } | ||
1637 | |||
1638 | bcn = (const struct ieee80211_mgmt *)(beacon_skb->data); | ||
1639 | len = min_t(size_t, beacon_skb->len, | ||
1640 | 0x200 - sizeof(struct b43_plcp_hdr6)); | ||
1610 | 1641 | ||
1611 | b43_write_template_common(dev, (const u8 *)bcn, | 1642 | b43_write_template_common(dev, (const u8 *)bcn, |
1612 | len, ram_offset, shm_size_offset, rate); | 1643 | len, ram_offset, shm_size_offset, rate); |
@@ -1674,6 +1705,8 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
1674 | B43_SHM_SH_DTIMPER, 0); | 1705 | B43_SHM_SH_DTIMPER, 0); |
1675 | } | 1706 | } |
1676 | b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); | 1707 | b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); |
1708 | |||
1709 | dev_kfree_skb_any(beacon_skb); | ||
1677 | } | 1710 | } |
1678 | 1711 | ||
1679 | static void b43_upload_beacon0(struct b43_wldev *dev) | 1712 | static void b43_upload_beacon0(struct b43_wldev *dev) |
@@ -1790,13 +1823,13 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) | |||
1790 | mutex_unlock(&wl->mutex); | 1823 | mutex_unlock(&wl->mutex); |
1791 | } | 1824 | } |
1792 | 1825 | ||
1793 | /* Asynchronously update the packet templates in template RAM. | 1826 | /* Asynchronously update the packet templates in template RAM. */ |
1794 | * Locking: Requires wl->mutex to be locked. */ | ||
1795 | static void b43_update_templates(struct b43_wl *wl) | 1827 | static void b43_update_templates(struct b43_wl *wl) |
1796 | { | 1828 | { |
1797 | struct sk_buff *beacon; | 1829 | struct sk_buff *beacon, *old_beacon; |
1830 | unsigned long flags; | ||
1798 | 1831 | ||
1799 | /* This is the top half of the ansynchronous beacon update. | 1832 | /* This is the top half of the asynchronous beacon update. |
1800 | * The bottom half is the beacon IRQ. | 1833 | * The bottom half is the beacon IRQ. |
1801 | * Beacon update must be asynchronous to avoid sending an | 1834 | * Beacon update must be asynchronous to avoid sending an |
1802 | * invalid beacon. This can happen for example, if the firmware | 1835 | * invalid beacon. This can happen for example, if the firmware |
@@ -1810,12 +1843,17 @@ static void b43_update_templates(struct b43_wl *wl) | |||
1810 | if (unlikely(!beacon)) | 1843 | if (unlikely(!beacon)) |
1811 | return; | 1844 | return; |
1812 | 1845 | ||
1813 | if (wl->current_beacon) | 1846 | spin_lock_irqsave(&wl->beacon_lock, flags); |
1814 | dev_kfree_skb_any(wl->current_beacon); | 1847 | old_beacon = wl->current_beacon; |
1815 | wl->current_beacon = beacon; | 1848 | wl->current_beacon = beacon; |
1816 | wl->beacon0_uploaded = false; | 1849 | wl->beacon0_uploaded = false; |
1817 | wl->beacon1_uploaded = false; | 1850 | wl->beacon1_uploaded = false; |
1851 | spin_unlock_irqrestore(&wl->beacon_lock, flags); | ||
1852 | |||
1818 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); | 1853 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); |
1854 | |||
1855 | if (old_beacon) | ||
1856 | dev_kfree_skb_any(old_beacon); | ||
1819 | } | 1857 | } |
1820 | 1858 | ||
1821 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) | 1859 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) |
@@ -4506,6 +4544,12 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4506 | unsupported = 1; | 4544 | unsupported = 1; |
4507 | break; | 4545 | break; |
4508 | #endif | 4546 | #endif |
4547 | #ifdef CONFIG_B43_PHY_AC | ||
4548 | case B43_PHYTYPE_AC: | ||
4549 | if (phy_rev > 1) | ||
4550 | unsupported = 1; | ||
4551 | break; | ||
4552 | #endif | ||
4509 | default: | 4553 | default: |
4510 | unsupported = 1; | 4554 | unsupported = 1; |
4511 | } | 4555 | } |
@@ -4602,6 +4646,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4602 | if (radio_id != 0x2064) | 4646 | if (radio_id != 0x2064) |
4603 | unsupported = 1; | 4647 | unsupported = 1; |
4604 | break; | 4648 | break; |
4649 | case B43_PHYTYPE_AC: | ||
4650 | if (radio_id != 0x2069) | ||
4651 | unsupported = 1; | ||
4652 | break; | ||
4605 | default: | 4653 | default: |
4606 | B43_WARN_ON(1); | 4654 | B43_WARN_ON(1); |
4607 | } | 4655 | } |
@@ -5095,7 +5143,6 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, | |||
5095 | { | 5143 | { |
5096 | struct b43_wl *wl = hw_to_b43_wl(hw); | 5144 | struct b43_wl *wl = hw_to_b43_wl(hw); |
5097 | 5145 | ||
5098 | /* FIXME: add locking */ | ||
5099 | b43_update_templates(wl); | 5146 | b43_update_templates(wl); |
5100 | 5147 | ||
5101 | return 0; | 5148 | return 0; |
@@ -5585,6 +5632,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) | |||
5585 | wl->hw = hw; | 5632 | wl->hw = hw; |
5586 | mutex_init(&wl->mutex); | 5633 | mutex_init(&wl->mutex); |
5587 | spin_lock_init(&wl->hardirq_lock); | 5634 | spin_lock_init(&wl->hardirq_lock); |
5635 | spin_lock_init(&wl->beacon_lock); | ||
5588 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); | 5636 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); |
5589 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); | 5637 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); |
5590 | INIT_WORK(&wl->tx_work, b43_tx_work); | 5638 | INIT_WORK(&wl->tx_work, b43_tx_work); |
diff --git a/drivers/net/wireless/b43/phy_ac.c b/drivers/net/wireless/b43/phy_ac.c new file mode 100644 index 000000000000..e75633d67938 --- /dev/null +++ b/drivers/net/wireless/b43/phy_ac.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * Broadcom B43 wireless driver | ||
3 | * IEEE 802.11ac AC-PHY support | ||
4 | * | ||
5 | * Copyright (c) 2015 Rafał Miłecki <zajec5@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include "b43.h" | ||
14 | #include "phy_ac.h" | ||
15 | |||
16 | /************************************************** | ||
17 | * Basic PHY ops | ||
18 | **************************************************/ | ||
19 | |||
20 | static int b43_phy_ac_op_allocate(struct b43_wldev *dev) | ||
21 | { | ||
22 | struct b43_phy_ac *phy_ac; | ||
23 | |||
24 | phy_ac = kzalloc(sizeof(*phy_ac), GFP_KERNEL); | ||
25 | if (!phy_ac) | ||
26 | return -ENOMEM; | ||
27 | dev->phy.ac = phy_ac; | ||
28 | |||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static void b43_phy_ac_op_free(struct b43_wldev *dev) | ||
33 | { | ||
34 | struct b43_phy *phy = &dev->phy; | ||
35 | struct b43_phy_ac *phy_ac = phy->ac; | ||
36 | |||
37 | kfree(phy_ac); | ||
38 | phy->ac = NULL; | ||
39 | } | ||
40 | |||
41 | static void b43_phy_ac_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, | ||
42 | u16 set) | ||
43 | { | ||
44 | b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); | ||
45 | b43_write16(dev, B43_MMIO_PHY_DATA, | ||
46 | (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); | ||
47 | } | ||
48 | |||
49 | static u16 b43_phy_ac_op_radio_read(struct b43_wldev *dev, u16 reg) | ||
50 | { | ||
51 | b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); | ||
52 | return b43_read16(dev, B43_MMIO_RADIO24_DATA); | ||
53 | } | ||
54 | |||
55 | static void b43_phy_ac_op_radio_write(struct b43_wldev *dev, u16 reg, | ||
56 | u16 value) | ||
57 | { | ||
58 | b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); | ||
59 | b43_write16(dev, B43_MMIO_RADIO24_DATA, value); | ||
60 | } | ||
61 | |||
62 | static unsigned int b43_phy_ac_op_get_default_chan(struct b43_wldev *dev) | ||
63 | { | ||
64 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
65 | return 11; | ||
66 | return 36; | ||
67 | } | ||
68 | |||
69 | static enum b43_txpwr_result | ||
70 | b43_phy_ac_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) | ||
71 | { | ||
72 | return B43_TXPWR_RES_DONE; | ||
73 | } | ||
74 | |||
75 | static void b43_phy_ac_op_adjust_txpower(struct b43_wldev *dev) | ||
76 | { | ||
77 | } | ||
78 | |||
79 | /************************************************** | ||
80 | * PHY ops struct | ||
81 | **************************************************/ | ||
82 | |||
83 | const struct b43_phy_operations b43_phyops_ac = { | ||
84 | .allocate = b43_phy_ac_op_allocate, | ||
85 | .free = b43_phy_ac_op_free, | ||
86 | .phy_maskset = b43_phy_ac_op_maskset, | ||
87 | .radio_read = b43_phy_ac_op_radio_read, | ||
88 | .radio_write = b43_phy_ac_op_radio_write, | ||
89 | .get_default_chan = b43_phy_ac_op_get_default_chan, | ||
90 | .recalc_txpower = b43_phy_ac_op_recalc_txpower, | ||
91 | .adjust_txpower = b43_phy_ac_op_adjust_txpower, | ||
92 | }; | ||
diff --git a/drivers/net/wireless/b43/phy_ac.h b/drivers/net/wireless/b43/phy_ac.h new file mode 100644 index 000000000000..d1ca79e0eb24 --- /dev/null +++ b/drivers/net/wireless/b43/phy_ac.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef B43_PHY_AC_H_ | ||
2 | #define B43_PHY_AC_H_ | ||
3 | |||
4 | #include "phy_common.h" | ||
5 | |||
6 | #define B43_PHY_AC_BBCFG 0x001 | ||
7 | #define B43_PHY_AC_BBCFG_RSTCCA 0x4000 /* Reset CCA */ | ||
8 | #define B43_PHY_AC_BANDCTL 0x003 /* Band control */ | ||
9 | #define B43_PHY_AC_BANDCTL_5GHZ 0x0001 | ||
10 | #define B43_PHY_AC_TABLE_ID 0x00d | ||
11 | #define B43_PHY_AC_TABLE_OFFSET 0x00e | ||
12 | #define B43_PHY_AC_TABLE_DATA1 0x00f | ||
13 | #define B43_PHY_AC_TABLE_DATA2 0x010 | ||
14 | #define B43_PHY_AC_TABLE_DATA3 0x011 | ||
15 | #define B43_PHY_AC_CLASSCTL 0x140 /* Classifier control */ | ||
16 | #define B43_PHY_AC_CLASSCTL_CCKEN 0x0001 /* CCK enable */ | ||
17 | #define B43_PHY_AC_CLASSCTL_OFDMEN 0x0002 /* OFDM enable */ | ||
18 | #define B43_PHY_AC_CLASSCTL_WAITEDEN 0x0004 /* Waited enable */ | ||
19 | #define B43_PHY_AC_BW1A 0x371 | ||
20 | #define B43_PHY_AC_BW2 0x372 | ||
21 | #define B43_PHY_AC_BW3 0x373 | ||
22 | #define B43_PHY_AC_BW4 0x374 | ||
23 | #define B43_PHY_AC_BW5 0x375 | ||
24 | #define B43_PHY_AC_BW6 0x376 | ||
25 | #define B43_PHY_AC_RFCTL_CMD 0x408 | ||
26 | #define B43_PHY_AC_C1_CLIP 0x6d4 | ||
27 | #define B43_PHY_AC_C1_CLIP_DIS 0x4000 | ||
28 | #define B43_PHY_AC_C2_CLIP 0x8d4 | ||
29 | #define B43_PHY_AC_C2_CLIP_DIS 0x4000 | ||
30 | #define B43_PHY_AC_C3_CLIP 0xad4 | ||
31 | #define B43_PHY_AC_C3_CLIP_DIS 0x4000 | ||
32 | |||
33 | struct b43_phy_ac { | ||
34 | }; | ||
35 | |||
36 | extern const struct b43_phy_operations b43_phyops_ac; | ||
37 | |||
38 | #endif /* B43_PHY_AC_H_ */ | ||
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index ee27b06074e1..ec2b9c577b90 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "phy_lp.h" | 33 | #include "phy_lp.h" |
34 | #include "phy_ht.h" | 34 | #include "phy_ht.h" |
35 | #include "phy_lcn.h" | 35 | #include "phy_lcn.h" |
36 | #include "phy_ac.h" | ||
36 | #include "b43.h" | 37 | #include "b43.h" |
37 | #include "main.h" | 38 | #include "main.h" |
38 | 39 | ||
@@ -70,6 +71,11 @@ int b43_phy_allocate(struct b43_wldev *dev) | |||
70 | phy->ops = &b43_phyops_lcn; | 71 | phy->ops = &b43_phyops_lcn; |
71 | #endif | 72 | #endif |
72 | break; | 73 | break; |
74 | case B43_PHYTYPE_AC: | ||
75 | #ifdef CONFIG_B43_PHY_AC | ||
76 | phy->ops = &b43_phyops_ac; | ||
77 | #endif | ||
78 | break; | ||
73 | } | 79 | } |
74 | if (B43_WARN_ON(!phy->ops)) | 80 | if (B43_WARN_ON(!phy->ops)) |
75 | return -ENODEV; | 81 | return -ENODEV; |
@@ -572,7 +578,8 @@ void b43_phy_force_clock(struct b43_wldev *dev, bool force) | |||
572 | u32 tmp; | 578 | u32 tmp; |
573 | 579 | ||
574 | WARN_ON(dev->phy.type != B43_PHYTYPE_N && | 580 | WARN_ON(dev->phy.type != B43_PHYTYPE_N && |
575 | dev->phy.type != B43_PHYTYPE_HT); | 581 | dev->phy.type != B43_PHYTYPE_HT && |
582 | dev->phy.type != B43_PHYTYPE_AC); | ||
576 | 583 | ||
577 | switch (dev->dev->bus_type) { | 584 | switch (dev->dev->bus_type) { |
578 | #ifdef CONFIG_B43_BCMA | 585 | #ifdef CONFIG_B43_BCMA |
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 3912274f71e3..78d86526799e 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h | |||
@@ -222,6 +222,8 @@ struct b43_phy { | |||
222 | struct b43_phy_ht *ht; | 222 | struct b43_phy_ht *ht; |
223 | /* LCN-PHY specific information */ | 223 | /* LCN-PHY specific information */ |
224 | struct b43_phy_lcn *lcn; | 224 | struct b43_phy_lcn *lcn; |
225 | /* AC-PHY specific information */ | ||
226 | struct b43_phy_ac *ac; | ||
225 | }; | 227 | }; |
226 | 228 | ||
227 | /* Band support flags. */ | 229 | /* Band support flags. */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 00ba90b89455..7944224e3fc9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -97,25 +97,6 @@ static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func) | |||
97 | { | 97 | { |
98 | } | 98 | } |
99 | 99 | ||
100 | static bool brcmf_sdiod_pm_resume_error(struct brcmf_sdio_dev *sdiodev) | ||
101 | { | ||
102 | bool is_err = false; | ||
103 | #ifdef CONFIG_PM_SLEEP | ||
104 | is_err = atomic_read(&sdiodev->suspend); | ||
105 | #endif | ||
106 | return is_err; | ||
107 | } | ||
108 | |||
109 | static void brcmf_sdiod_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, | ||
110 | wait_queue_head_t *wq) | ||
111 | { | ||
112 | #ifdef CONFIG_PM_SLEEP | ||
113 | int retry = 0; | ||
114 | while (atomic_read(&sdiodev->suspend) && retry++ != 30) | ||
115 | wait_event_timeout(*wq, false, HZ/100); | ||
116 | #endif | ||
117 | } | ||
118 | |||
119 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) | 100 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) |
120 | { | 101 | { |
121 | int ret = 0; | 102 | int ret = 0; |
@@ -244,10 +225,6 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, | |||
244 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | 225 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", |
245 | write, fn, addr, regsz); | 226 | write, fn, addr, regsz); |
246 | 227 | ||
247 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | ||
248 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
249 | return -EIO; | ||
250 | |||
251 | /* only allow byte access on F0 */ | 228 | /* only allow byte access on F0 */ |
252 | if (WARN_ON(regsz > 1 && !fn)) | 229 | if (WARN_ON(regsz > 1 && !fn)) |
253 | return -EINVAL; | 230 | return -EINVAL; |
@@ -292,6 +269,12 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, | |||
292 | return ret; | 269 | return ret; |
293 | } | 270 | } |
294 | 271 | ||
272 | static void brcmf_sdiod_nomedium_state(struct brcmf_sdio_dev *sdiodev) | ||
273 | { | ||
274 | sdiodev->state = BRCMF_STATE_NOMEDIUM; | ||
275 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN); | ||
276 | } | ||
277 | |||
295 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | 278 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
296 | u8 regsz, void *data, bool write) | 279 | u8 regsz, void *data, bool write) |
297 | { | 280 | { |
@@ -299,7 +282,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
299 | s32 retry = 0; | 282 | s32 retry = 0; |
300 | int ret; | 283 | int ret; |
301 | 284 | ||
302 | if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM) | 285 | if (sdiodev->state == BRCMF_STATE_NOMEDIUM) |
303 | return -ENOMEDIUM; | 286 | return -ENOMEDIUM; |
304 | 287 | ||
305 | /* | 288 | /* |
@@ -325,7 +308,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
325 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 308 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
326 | 309 | ||
327 | if (ret == -ENOMEDIUM) | 310 | if (ret == -ENOMEDIUM) |
328 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); | 311 | brcmf_sdiod_nomedium_state(sdiodev); |
329 | else if (ret != 0) { | 312 | else if (ret != 0) { |
330 | /* | 313 | /* |
331 | * SleepCSR register access can fail when | 314 | * SleepCSR register access can fail when |
@@ -348,7 +331,7 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
348 | int err = 0, i; | 331 | int err = 0, i; |
349 | u8 addr[3]; | 332 | u8 addr[3]; |
350 | 333 | ||
351 | if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM) | 334 | if (sdiodev->state == BRCMF_STATE_NOMEDIUM) |
352 | return -ENOMEDIUM; | 335 | return -ENOMEDIUM; |
353 | 336 | ||
354 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; | 337 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; |
@@ -462,10 +445,6 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
462 | unsigned int req_sz; | 445 | unsigned int req_sz; |
463 | int err; | 446 | int err; |
464 | 447 | ||
465 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | ||
466 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
467 | return -EIO; | ||
468 | |||
469 | /* Single skb use the standard mmc interface */ | 448 | /* Single skb use the standard mmc interface */ |
470 | req_sz = pkt->len + 3; | 449 | req_sz = pkt->len + 3; |
471 | req_sz &= (uint)~3; | 450 | req_sz &= (uint)~3; |
@@ -481,7 +460,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
481 | err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, | 460 | err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, |
482 | req_sz); | 461 | req_sz); |
483 | if (err == -ENOMEDIUM) | 462 | if (err == -ENOMEDIUM) |
484 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); | 463 | brcmf_sdiod_nomedium_state(sdiodev); |
485 | return err; | 464 | return err; |
486 | } | 465 | } |
487 | 466 | ||
@@ -516,10 +495,6 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
516 | if (!pktlist->qlen) | 495 | if (!pktlist->qlen) |
517 | return -EINVAL; | 496 | return -EINVAL; |
518 | 497 | ||
519 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | ||
520 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
521 | return -EIO; | ||
522 | |||
523 | target_list = pktlist; | 498 | target_list = pktlist; |
524 | /* for host with broken sg support, prepare a page aligned list */ | 499 | /* for host with broken sg support, prepare a page aligned list */ |
525 | __skb_queue_head_init(&local_list); | 500 | __skb_queue_head_init(&local_list); |
@@ -620,8 +595,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
620 | 595 | ||
621 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; | 596 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; |
622 | if (ret == -ENOMEDIUM) { | 597 | if (ret == -ENOMEDIUM) { |
623 | brcmf_bus_change_state(sdiodev->bus_if, | 598 | brcmf_sdiod_nomedium_state(sdiodev); |
624 | BRCMF_BUS_NOMEDIUM); | ||
625 | break; | 599 | break; |
626 | } else if (ret != 0) { | 600 | } else if (ret != 0) { |
627 | brcmf_err("CMD53 sg block %s failed %d\n", | 601 | brcmf_err("CMD53 sg block %s failed %d\n", |
@@ -1076,9 +1050,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
1076 | bus_if->wowl_supported = true; | 1050 | bus_if->wowl_supported = true; |
1077 | #endif | 1051 | #endif |
1078 | 1052 | ||
1053 | sdiodev->sleeping = false; | ||
1079 | atomic_set(&sdiodev->suspend, false); | 1054 | atomic_set(&sdiodev->suspend, false); |
1080 | init_waitqueue_head(&sdiodev->request_word_wait); | 1055 | init_waitqueue_head(&sdiodev->idle_wait); |
1081 | init_waitqueue_head(&sdiodev->request_buffer_wait); | ||
1082 | 1056 | ||
1083 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); | 1057 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); |
1084 | err = brcmf_sdiod_probe(sdiodev); | 1058 | err = brcmf_sdiod_probe(sdiodev); |
@@ -1140,12 +1114,23 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled) | |||
1140 | #ifdef CONFIG_PM_SLEEP | 1114 | #ifdef CONFIG_PM_SLEEP |
1141 | static int brcmf_ops_sdio_suspend(struct device *dev) | 1115 | static int brcmf_ops_sdio_suspend(struct device *dev) |
1142 | { | 1116 | { |
1143 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 1117 | struct brcmf_bus *bus_if; |
1144 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 1118 | struct brcmf_sdio_dev *sdiodev; |
1145 | mmc_pm_flag_t sdio_flags; | 1119 | mmc_pm_flag_t sdio_flags; |
1146 | 1120 | ||
1147 | brcmf_dbg(SDIO, "Enter\n"); | 1121 | brcmf_dbg(SDIO, "Enter\n"); |
1148 | 1122 | ||
1123 | bus_if = dev_get_drvdata(dev); | ||
1124 | sdiodev = bus_if->bus_priv.sdio; | ||
1125 | |||
1126 | /* wait for watchdog to go idle */ | ||
1127 | if (wait_event_timeout(sdiodev->idle_wait, sdiodev->sleeping, | ||
1128 | msecs_to_jiffies(3 * BRCMF_WD_POLL_MS)) == 0) { | ||
1129 | brcmf_err("bus still active\n"); | ||
1130 | return -EBUSY; | ||
1131 | } | ||
1132 | /* disable watchdog */ | ||
1133 | brcmf_sdio_wd_timer(sdiodev->bus, 0); | ||
1149 | atomic_set(&sdiodev->suspend, true); | 1134 | atomic_set(&sdiodev->suspend, true); |
1150 | 1135 | ||
1151 | if (sdiodev->wowl_enabled) { | 1136 | if (sdiodev->wowl_enabled) { |
@@ -1157,9 +1142,6 @@ static int brcmf_ops_sdio_suspend(struct device *dev) | |||
1157 | if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) | 1142 | if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) |
1158 | brcmf_err("Failed to set pm_flags %x\n", sdio_flags); | 1143 | brcmf_err("Failed to set pm_flags %x\n", sdio_flags); |
1159 | } | 1144 | } |
1160 | |||
1161 | brcmf_sdio_wd_timer(sdiodev->bus, 0); | ||
1162 | |||
1163 | return 0; | 1145 | return 0; |
1164 | } | 1146 | } |
1165 | 1147 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h index ef344e47218a..89e6a4dc105e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h | |||
@@ -33,11 +33,8 @@ | |||
33 | 33 | ||
34 | /* The level of bus communication with the dongle */ | 34 | /* The level of bus communication with the dongle */ |
35 | enum brcmf_bus_state { | 35 | enum brcmf_bus_state { |
36 | BRCMF_BUS_UNKNOWN, /* Not determined yet */ | ||
37 | BRCMF_BUS_NOMEDIUM, /* No medium access to dongle */ | ||
38 | BRCMF_BUS_DOWN, /* Not ready for frame transfers */ | 36 | BRCMF_BUS_DOWN, /* Not ready for frame transfers */ |
39 | BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ | 37 | BRCMF_BUS_UP /* Ready for frame transfers */ |
40 | BRCMF_BUS_DATA /* Ready for frame transfers */ | ||
41 | }; | 38 | }; |
42 | 39 | ||
43 | /* The level of bus communication with the dongle */ | 40 | /* The level of bus communication with the dongle */ |
@@ -188,22 +185,6 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled) | |||
188 | bus->ops->wowl_config(bus->dev, enabled); | 185 | bus->ops->wowl_config(bus->dev, enabled); |
189 | } | 186 | } |
190 | 187 | ||
191 | static inline bool brcmf_bus_ready(struct brcmf_bus *bus) | ||
192 | { | ||
193 | return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA; | ||
194 | } | ||
195 | |||
196 | static inline void brcmf_bus_change_state(struct brcmf_bus *bus, | ||
197 | enum brcmf_bus_state new_state) | ||
198 | { | ||
199 | /* NOMEDIUM is permanent */ | ||
200 | if (bus->state == BRCMF_BUS_NOMEDIUM) | ||
201 | return; | ||
202 | |||
203 | brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state); | ||
204 | bus->state = new_state; | ||
205 | } | ||
206 | |||
207 | /* | 188 | /* |
208 | * interface functions from common layer | 189 | * interface functions from common layer |
209 | */ | 190 | */ |
@@ -226,6 +207,9 @@ void brcmf_txflowblock(struct device *dev, bool state); | |||
226 | /* Notify the bus has transferred the tx packet to firmware */ | 207 | /* Notify the bus has transferred the tx packet to firmware */ |
227 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); | 208 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); |
228 | 209 | ||
210 | /* Configure the "global" bus state used by upper layers */ | ||
211 | void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state); | ||
212 | |||
229 | int brcmf_bus_start(struct device *dev); | 213 | int brcmf_bus_start(struct device *dev); |
230 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len); | 214 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len); |
231 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); | 215 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 5eba81bfc6ed..b59b8c6c42ab 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | |||
@@ -1229,7 +1229,25 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) | |||
1229 | memset(prof, 0, sizeof(*prof)); | 1229 | memset(prof, 0, sizeof(*prof)); |
1230 | } | 1230 | } |
1231 | 1231 | ||
1232 | static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) | 1232 | static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e) |
1233 | { | ||
1234 | u16 reason; | ||
1235 | |||
1236 | switch (e->event_code) { | ||
1237 | case BRCMF_E_DEAUTH: | ||
1238 | case BRCMF_E_DEAUTH_IND: | ||
1239 | case BRCMF_E_DISASSOC_IND: | ||
1240 | reason = e->reason; | ||
1241 | break; | ||
1242 | case BRCMF_E_LINK: | ||
1243 | default: | ||
1244 | reason = 0; | ||
1245 | break; | ||
1246 | } | ||
1247 | return reason; | ||
1248 | } | ||
1249 | |||
1250 | static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) | ||
1233 | { | 1251 | { |
1234 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); | 1252 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); |
1235 | s32 err = 0; | 1253 | s32 err = 0; |
@@ -1244,7 +1262,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) | |||
1244 | brcmf_err("WLC_DISASSOC failed (%d)\n", err); | 1262 | brcmf_err("WLC_DISASSOC failed (%d)\n", err); |
1245 | } | 1263 | } |
1246 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); | 1264 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); |
1247 | cfg80211_disconnected(vif->wdev.netdev, 0, NULL, 0, GFP_KERNEL); | 1265 | cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0, |
1266 | GFP_KERNEL); | ||
1248 | 1267 | ||
1249 | } | 1268 | } |
1250 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); | 1269 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); |
@@ -1414,7 +1433,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) | |||
1414 | if (!check_vif_up(ifp->vif)) | 1433 | if (!check_vif_up(ifp->vif)) |
1415 | return -EIO; | 1434 | return -EIO; |
1416 | 1435 | ||
1417 | brcmf_link_down(ifp->vif); | 1436 | brcmf_link_down(ifp->vif, WLAN_REASON_DEAUTH_LEAVING); |
1418 | 1437 | ||
1419 | brcmf_dbg(TRACE, "Exit\n"); | 1438 | brcmf_dbg(TRACE, "Exit\n"); |
1420 | 1439 | ||
@@ -3041,7 +3060,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, | |||
3041 | * disassociate from AP to save power while system is | 3060 | * disassociate from AP to save power while system is |
3042 | * in suspended state | 3061 | * in suspended state |
3043 | */ | 3062 | */ |
3044 | brcmf_link_down(vif); | 3063 | brcmf_link_down(vif, WLAN_REASON_UNSPECIFIED); |
3045 | /* Make sure WPA_Supplicant receives all the event | 3064 | /* Make sure WPA_Supplicant receives all the event |
3046 | * generated due to DISASSOC call to the fw to keep | 3065 | * generated due to DISASSOC call to the fw to keep |
3047 | * the state fw and WPA_Supplicant state consistent | 3066 | * the state fw and WPA_Supplicant state consistent |
@@ -4927,7 +4946,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4927 | if (!brcmf_is_ibssmode(ifp->vif)) { | 4946 | if (!brcmf_is_ibssmode(ifp->vif)) { |
4928 | brcmf_bss_connect_done(cfg, ndev, e, false); | 4947 | brcmf_bss_connect_done(cfg, ndev, e, false); |
4929 | } | 4948 | } |
4930 | brcmf_link_down(ifp->vif); | 4949 | brcmf_link_down(ifp->vif, brcmf_map_fw_linkdown_reason(e)); |
4931 | brcmf_init_prof(ndev_to_prof(ndev)); | 4950 | brcmf_init_prof(ndev_to_prof(ndev)); |
4932 | if (ndev != cfg_to_ndev(cfg)) | 4951 | if (ndev != cfg_to_ndev(cfg)) |
4933 | complete(&cfg->vif_disabled); | 4952 | complete(&cfg->vif_disabled); |
@@ -5868,7 +5887,7 @@ static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp) | |||
5868 | * from AP to save power | 5887 | * from AP to save power |
5869 | */ | 5888 | */ |
5870 | if (check_vif_up(ifp->vif)) { | 5889 | if (check_vif_up(ifp->vif)) { |
5871 | brcmf_link_down(ifp->vif); | 5890 | brcmf_link_down(ifp->vif, WLAN_REASON_UNSPECIFIED); |
5872 | 5891 | ||
5873 | /* Make sure WPA_Supplicant receives all the event | 5892 | /* Make sure WPA_Supplicant receives all the event |
5874 | generated due to DISASSOC call to the fw to keep | 5893 | generated due to DISASSOC call to the fw to keep |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c index ddf05af13d44..fe54844c75e0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c | |||
@@ -41,6 +41,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
41 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | 41 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; |
42 | u8 buf[BRCMF_DCMD_SMLEN]; | 42 | u8 buf[BRCMF_DCMD_SMLEN]; |
43 | struct brcmf_join_pref_params join_pref_params[2]; | 43 | struct brcmf_join_pref_params join_pref_params[2]; |
44 | struct brcmf_rev_info_le revinfo; | ||
45 | struct brcmf_rev_info *ri; | ||
44 | char *ptr; | 46 | char *ptr; |
45 | s32 err; | 47 | s32 err; |
46 | 48 | ||
@@ -48,12 +50,37 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
48 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | 50 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, |
49 | sizeof(ifp->mac_addr)); | 51 | sizeof(ifp->mac_addr)); |
50 | if (err < 0) { | 52 | if (err < 0) { |
51 | brcmf_err("Retreiving cur_etheraddr failed, %d\n", | 53 | brcmf_err("Retreiving cur_etheraddr failed, %d\n", err); |
52 | err); | ||
53 | goto done; | 54 | goto done; |
54 | } | 55 | } |
55 | memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); | 56 | memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); |
56 | 57 | ||
58 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, | ||
59 | &revinfo, sizeof(revinfo)); | ||
60 | ri = &ifp->drvr->revinfo; | ||
61 | if (err < 0) { | ||
62 | brcmf_err("retrieving revision info failed, %d\n", err); | ||
63 | } else { | ||
64 | ri->vendorid = le32_to_cpu(revinfo.vendorid); | ||
65 | ri->deviceid = le32_to_cpu(revinfo.deviceid); | ||
66 | ri->radiorev = le32_to_cpu(revinfo.radiorev); | ||
67 | ri->chiprev = le32_to_cpu(revinfo.chiprev); | ||
68 | ri->corerev = le32_to_cpu(revinfo.corerev); | ||
69 | ri->boardid = le32_to_cpu(revinfo.boardid); | ||
70 | ri->boardvendor = le32_to_cpu(revinfo.boardvendor); | ||
71 | ri->boardrev = le32_to_cpu(revinfo.boardrev); | ||
72 | ri->driverrev = le32_to_cpu(revinfo.driverrev); | ||
73 | ri->ucoderev = le32_to_cpu(revinfo.ucoderev); | ||
74 | ri->bus = le32_to_cpu(revinfo.bus); | ||
75 | ri->chipnum = le32_to_cpu(revinfo.chipnum); | ||
76 | ri->phytype = le32_to_cpu(revinfo.phytype); | ||
77 | ri->phyrev = le32_to_cpu(revinfo.phyrev); | ||
78 | ri->anarev = le32_to_cpu(revinfo.anarev); | ||
79 | ri->chippkg = le32_to_cpu(revinfo.chippkg); | ||
80 | ri->nvramrev = le32_to_cpu(revinfo.nvramrev); | ||
81 | } | ||
82 | ri->result = err; | ||
83 | |||
57 | /* query for 'ver' to get version info from firmware */ | 84 | /* query for 'ver' to get version info from firmware */ |
58 | memset(buf, 0, sizeof(buf)); | 85 | memset(buf, 0, sizeof(buf)); |
59 | strcpy(buf, "ver"); | 86 | strcpy(buf, "ver"); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h index 002336e35764..3d404016a92e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h | |||
@@ -37,6 +37,8 @@ struct brcmf_commonring { | |||
37 | unsigned long flags; | 37 | unsigned long flags; |
38 | bool inited; | 38 | bool inited; |
39 | bool was_full; | 39 | bool was_full; |
40 | |||
41 | atomic_t outstanding_tx; | ||
40 | }; | 42 | }; |
41 | 43 | ||
42 | 44 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index e2a9e33f71ab..2d6e2cc1b12c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c | |||
@@ -197,7 +197,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
197 | brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); | 197 | brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); |
198 | 198 | ||
199 | /* Can the device send data? */ | 199 | /* Can the device send data? */ |
200 | if (drvr->bus_if->state != BRCMF_BUS_DATA) { | 200 | if (drvr->bus_if->state != BRCMF_BUS_UP) { |
201 | brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state); | 201 | brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state); |
202 | netif_stop_queue(ndev); | 202 | netif_stop_queue(ndev); |
203 | dev_kfree_skb(skb); | 203 | dev_kfree_skb(skb); |
@@ -601,9 +601,12 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, | |||
601 | { | 601 | { |
602 | struct brcmf_if *ifp = netdev_priv(ndev); | 602 | struct brcmf_if *ifp = netdev_priv(ndev); |
603 | struct brcmf_pub *drvr = ifp->drvr; | 603 | struct brcmf_pub *drvr = ifp->drvr; |
604 | char drev[BRCMU_DOTREV_LEN] = "n/a"; | ||
604 | 605 | ||
606 | if (drvr->revinfo.result == 0) | ||
607 | brcmu_dotrev_str(drvr->revinfo.driverrev, drev); | ||
605 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); | 608 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); |
606 | snprintf(info->version, sizeof(info->version), "n/a"); | 609 | strlcpy(info->version, drev, sizeof(info->version)); |
607 | strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version)); | 610 | strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version)); |
608 | strlcpy(info->bus_info, dev_name(drvr->bus_if->dev), | 611 | strlcpy(info->bus_info, dev_name(drvr->bus_if->dev), |
609 | sizeof(info->bus_info)); | 612 | sizeof(info->bus_info)); |
@@ -637,7 +640,7 @@ static int brcmf_netdev_open(struct net_device *ndev) | |||
637 | brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); | 640 | brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); |
638 | 641 | ||
639 | /* If bus is not ready, can't continue */ | 642 | /* If bus is not ready, can't continue */ |
640 | if (bus_if->state != BRCMF_BUS_DATA) { | 643 | if (bus_if->state != BRCMF_BUS_UP) { |
641 | brcmf_err("failed bus is not ready\n"); | 644 | brcmf_err("failed bus is not ready\n"); |
642 | return -EAGAIN; | 645 | return -EAGAIN; |
643 | } | 646 | } |
@@ -964,13 +967,20 @@ int brcmf_bus_start(struct device *dev) | |||
964 | p2p_ifp = NULL; | 967 | p2p_ifp = NULL; |
965 | 968 | ||
966 | /* signal bus ready */ | 969 | /* signal bus ready */ |
967 | brcmf_bus_change_state(bus_if, BRCMF_BUS_DATA); | 970 | brcmf_bus_change_state(bus_if, BRCMF_BUS_UP); |
968 | 971 | ||
969 | /* Bus is ready, do any initialization */ | 972 | /* Bus is ready, do any initialization */ |
970 | ret = brcmf_c_preinit_dcmds(ifp); | 973 | ret = brcmf_c_preinit_dcmds(ifp); |
971 | if (ret < 0) | 974 | if (ret < 0) |
972 | goto fail; | 975 | goto fail; |
973 | 976 | ||
977 | /* assure we have chipid before feature attach */ | ||
978 | if (!bus_if->chip) { | ||
979 | bus_if->chip = drvr->revinfo.chipnum; | ||
980 | bus_if->chiprev = drvr->revinfo.chiprev; | ||
981 | brcmf_dbg(INFO, "firmware revinfo: chip %x (%d) rev %d\n", | ||
982 | bus_if->chip, bus_if->chip, bus_if->chiprev); | ||
983 | } | ||
974 | brcmf_feat_attach(drvr); | 984 | brcmf_feat_attach(drvr); |
975 | 985 | ||
976 | ret = brcmf_fws_init(drvr); | 986 | ret = brcmf_fws_init(drvr); |
@@ -1106,6 +1116,27 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp) | |||
1106 | return !err; | 1116 | return !err; |
1107 | } | 1117 | } |
1108 | 1118 | ||
1119 | void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state) | ||
1120 | { | ||
1121 | struct brcmf_pub *drvr = bus->drvr; | ||
1122 | struct net_device *ndev; | ||
1123 | int ifidx; | ||
1124 | |||
1125 | brcmf_dbg(TRACE, "%d -> %d\n", bus->state, state); | ||
1126 | bus->state = state; | ||
1127 | |||
1128 | if (state == BRCMF_BUS_UP) { | ||
1129 | for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) { | ||
1130 | if ((drvr->iflist[ifidx]) && | ||
1131 | (drvr->iflist[ifidx]->ndev)) { | ||
1132 | ndev = drvr->iflist[ifidx]->ndev; | ||
1133 | if (netif_queue_stopped(ndev)) | ||
1134 | netif_wake_queue(ndev); | ||
1135 | } | ||
1136 | } | ||
1137 | } | ||
1138 | } | ||
1139 | |||
1109 | static void brcmf_driver_register(struct work_struct *work) | 1140 | static void brcmf_driver_register(struct work_struct *work) |
1110 | { | 1141 | { |
1111 | #ifdef CONFIG_BRCMFMAC_SDIO | 1142 | #ifdef CONFIG_BRCMFMAC_SDIO |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index f2f7d3d1a8ef..fd74a9c6e9ac 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h | |||
@@ -71,6 +71,35 @@ struct brcmf_proto; /* device communication protocol info */ | |||
71 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ | 71 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ |
72 | struct brcmf_fws_info; /* firmware signalling info */ | 72 | struct brcmf_fws_info; /* firmware signalling info */ |
73 | 73 | ||
74 | /* | ||
75 | * struct brcmf_rev_info | ||
76 | * | ||
77 | * The result field stores the error code of the | ||
78 | * revision info request from firmware. For the | ||
79 | * other fields see struct brcmf_rev_info_le in | ||
80 | * fwil_types.h | ||
81 | */ | ||
82 | struct brcmf_rev_info { | ||
83 | int result; | ||
84 | u32 vendorid; | ||
85 | u32 deviceid; | ||
86 | u32 radiorev; | ||
87 | u32 chiprev; | ||
88 | u32 corerev; | ||
89 | u32 boardid; | ||
90 | u32 boardvendor; | ||
91 | u32 boardrev; | ||
92 | u32 driverrev; | ||
93 | u32 ucoderev; | ||
94 | u32 bus; | ||
95 | u32 chipnum; | ||
96 | u32 phytype; | ||
97 | u32 phyrev; | ||
98 | u32 anarev; | ||
99 | u32 chippkg; | ||
100 | u32 nvramrev; | ||
101 | }; | ||
102 | |||
74 | /* Common structure for module and instance linkage */ | 103 | /* Common structure for module and instance linkage */ |
75 | struct brcmf_pub { | 104 | struct brcmf_pub { |
76 | /* Linkage ponters */ | 105 | /* Linkage ponters */ |
@@ -104,6 +133,7 @@ struct brcmf_pub { | |||
104 | u32 feat_flags; | 133 | u32 feat_flags; |
105 | u32 chip_quirks; | 134 | u32 chip_quirks; |
106 | 135 | ||
136 | struct brcmf_rev_info revinfo; | ||
107 | #ifdef DEBUG | 137 | #ifdef DEBUG |
108 | struct dentry *dbgfs_dir; | 138 | struct dentry *dbgfs_dir; |
109 | #endif | 139 | #endif |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 1ff787d1a36b..9cb99152ad17 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c | |||
@@ -103,7 +103,11 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) | |||
103 | 103 | ||
104 | c = nvp->fwnv->data[nvp->pos]; | 104 | c = nvp->fwnv->data[nvp->pos]; |
105 | if (c == '=') { | 105 | if (c == '=') { |
106 | st = VALUE; | 106 | /* ignore RAW1 by treating as comment */ |
107 | if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0) | ||
108 | st = COMMENT; | ||
109 | else | ||
110 | st = VALUE; | ||
107 | } else if (!is_nvram_char(c)) { | 111 | } else if (!is_nvram_char(c)) { |
108 | brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", | 112 | brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", |
109 | nvp->line, nvp->column); | 113 | nvp->line, nvp->column); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 03f2c406a17b..dcfa0bb149ce 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -109,7 +109,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | |||
109 | struct brcmf_pub *drvr = ifp->drvr; | 109 | struct brcmf_pub *drvr = ifp->drvr; |
110 | s32 err; | 110 | s32 err; |
111 | 111 | ||
112 | if (drvr->bus_if->state != BRCMF_BUS_DATA) { | 112 | if (drvr->bus_if->state != BRCMF_BUS_UP) { |
113 | brcmf_err("bus is down. we have nothing to do.\n"); | 113 | brcmf_err("bus is down. we have nothing to do.\n"); |
114 | return -EIO; | 114 | return -EIO; |
115 | } | 115 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h index 37345e7b873d..5434dcf64f7d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h | |||
@@ -59,6 +59,7 @@ | |||
59 | #define BRCMF_C_SET_COUNTRY 84 | 59 | #define BRCMF_C_SET_COUNTRY 84 |
60 | #define BRCMF_C_GET_PM 85 | 60 | #define BRCMF_C_GET_PM 85 |
61 | #define BRCMF_C_SET_PM 86 | 61 | #define BRCMF_C_SET_PM 86 |
62 | #define BRCMF_C_GET_REVINFO 98 | ||
62 | #define BRCMF_C_GET_CURR_RATESET 114 | 63 | #define BRCMF_C_GET_CURR_RATESET 114 |
63 | #define BRCMF_C_GET_AP 117 | 64 | #define BRCMF_C_GET_AP 117 |
64 | #define BRCMF_C_SET_AP 118 | 65 | #define BRCMF_C_SET_AP 118 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 619669bbdb83..374920965108 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
@@ -539,4 +539,45 @@ struct brcmf_fil_country_le { | |||
539 | char ccode[BRCMF_COUNTRY_BUF_SZ]; | 539 | char ccode[BRCMF_COUNTRY_BUF_SZ]; |
540 | }; | 540 | }; |
541 | 541 | ||
542 | /** | ||
543 | * struct brcmf_rev_info_le - device revision info. | ||
544 | * | ||
545 | * @vendorid: PCI vendor id. | ||
546 | * @deviceid: device id of chip. | ||
547 | * @radiorev: radio revision. | ||
548 | * @chiprev: chip revision. | ||
549 | * @corerev: core revision. | ||
550 | * @boardid: board identifier (usu. PCI sub-device id). | ||
551 | * @boardvendor: board vendor (usu. PCI sub-vendor id). | ||
552 | * @boardrev: board revision. | ||
553 | * @driverrev: driver version. | ||
554 | * @ucoderev: microcode version. | ||
555 | * @bus: bus type. | ||
556 | * @chipnum: chip number. | ||
557 | * @phytype: phy type. | ||
558 | * @phyrev: phy revision. | ||
559 | * @anarev: anacore rev. | ||
560 | * @chippkg: chip package info. | ||
561 | * @nvramrev: nvram revision number. | ||
562 | */ | ||
563 | struct brcmf_rev_info_le { | ||
564 | __le32 vendorid; | ||
565 | __le32 deviceid; | ||
566 | __le32 radiorev; | ||
567 | __le32 chiprev; | ||
568 | __le32 corerev; | ||
569 | __le32 boardid; | ||
570 | __le32 boardvendor; | ||
571 | __le32 boardrev; | ||
572 | __le32 driverrev; | ||
573 | __le32 ucoderev; | ||
574 | __le32 bus; | ||
575 | __le32 chipnum; | ||
576 | __le32 phytype; | ||
577 | __le32 phyrev; | ||
578 | __le32 anarev; | ||
579 | __le32 chippkg; | ||
580 | __le32 nvramrev; | ||
581 | }; | ||
582 | |||
542 | #endif /* FWIL_TYPES_H_ */ | 583 | #endif /* FWIL_TYPES_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index ee147f5c706a..6262612dec45 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | |||
@@ -73,6 +73,8 @@ | |||
73 | #define BRCMF_MSGBUF_TX_FLUSH_CNT1 32 | 73 | #define BRCMF_MSGBUF_TX_FLUSH_CNT1 32 |
74 | #define BRCMF_MSGBUF_TX_FLUSH_CNT2 96 | 74 | #define BRCMF_MSGBUF_TX_FLUSH_CNT2 96 |
75 | 75 | ||
76 | #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 64 | ||
77 | #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32 | ||
76 | 78 | ||
77 | struct msgbuf_common_hdr { | 79 | struct msgbuf_common_hdr { |
78 | u8 msgtype; | 80 | u8 msgtype; |
@@ -749,6 +751,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid) | |||
749 | tx_msghdr->metadata_buf_len = 0; | 751 | tx_msghdr->metadata_buf_len = 0; |
750 | tx_msghdr->metadata_buf_addr.high_addr = 0; | 752 | tx_msghdr->metadata_buf_addr.high_addr = 0; |
751 | tx_msghdr->metadata_buf_addr.low_addr = 0; | 753 | tx_msghdr->metadata_buf_addr.low_addr = 0; |
754 | atomic_inc(&commonring->outstanding_tx); | ||
752 | if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) { | 755 | if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) { |
753 | brcmf_commonring_write_complete(commonring); | 756 | brcmf_commonring_write_complete(commonring); |
754 | count = 0; | 757 | count = 0; |
@@ -773,10 +776,16 @@ static void brcmf_msgbuf_txflow_worker(struct work_struct *worker) | |||
773 | } | 776 | } |
774 | 777 | ||
775 | 778 | ||
776 | static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid) | 779 | static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid, |
780 | bool force) | ||
777 | { | 781 | { |
782 | struct brcmf_commonring *commonring; | ||
783 | |||
778 | set_bit(flowid, msgbuf->flow_map); | 784 | set_bit(flowid, msgbuf->flow_map); |
779 | queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work); | 785 | commonring = msgbuf->flowrings[flowid]; |
786 | if ((force) || (atomic_read(&commonring->outstanding_tx) < | ||
787 | BRCMF_MSGBUF_DELAY_TXWORKER_THRS)) | ||
788 | queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work); | ||
780 | 789 | ||
781 | return 0; | 790 | return 0; |
782 | } | 791 | } |
@@ -797,7 +806,7 @@ static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx, | |||
797 | return -ENOMEM; | 806 | return -ENOMEM; |
798 | } | 807 | } |
799 | brcmf_flowring_enqueue(flow, flowid, skb); | 808 | brcmf_flowring_enqueue(flow, flowid, skb); |
800 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid); | 809 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false); |
801 | 810 | ||
802 | return 0; | 811 | return 0; |
803 | } | 812 | } |
@@ -854,6 +863,7 @@ brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf) | |||
854 | static void | 863 | static void |
855 | brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) | 864 | brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) |
856 | { | 865 | { |
866 | struct brcmf_commonring *commonring; | ||
857 | struct msgbuf_tx_status *tx_status; | 867 | struct msgbuf_tx_status *tx_status; |
858 | u32 idx; | 868 | u32 idx; |
859 | struct sk_buff *skb; | 869 | struct sk_buff *skb; |
@@ -871,6 +881,8 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) | |||
871 | } | 881 | } |
872 | 882 | ||
873 | set_bit(flowid, msgbuf->txstatus_done_map); | 883 | set_bit(flowid, msgbuf->txstatus_done_map); |
884 | commonring = msgbuf->flowrings[flowid]; | ||
885 | atomic_dec(&commonring->outstanding_tx); | ||
874 | 886 | ||
875 | brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); | 887 | brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); |
876 | } | 888 | } |
@@ -1181,7 +1193,7 @@ brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf, | |||
1181 | 1193 | ||
1182 | brcmf_flowring_open(msgbuf->flow, flowid); | 1194 | brcmf_flowring_open(msgbuf->flow, flowid); |
1183 | 1195 | ||
1184 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid); | 1196 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true); |
1185 | } | 1197 | } |
1186 | 1198 | ||
1187 | 1199 | ||
@@ -1280,8 +1292,10 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) | |||
1280 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 1292 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
1281 | struct brcmf_pub *drvr = bus_if->drvr; | 1293 | struct brcmf_pub *drvr = bus_if->drvr; |
1282 | struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; | 1294 | struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; |
1295 | struct brcmf_commonring *commonring; | ||
1283 | void *buf; | 1296 | void *buf; |
1284 | u32 flowid; | 1297 | u32 flowid; |
1298 | int qlen; | ||
1285 | 1299 | ||
1286 | buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE]; | 1300 | buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE]; |
1287 | brcmf_msgbuf_process_rx(msgbuf, buf); | 1301 | brcmf_msgbuf_process_rx(msgbuf, buf); |
@@ -1293,8 +1307,12 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) | |||
1293 | for_each_set_bit(flowid, msgbuf->txstatus_done_map, | 1307 | for_each_set_bit(flowid, msgbuf->txstatus_done_map, |
1294 | msgbuf->nrof_flowrings) { | 1308 | msgbuf->nrof_flowrings) { |
1295 | clear_bit(flowid, msgbuf->txstatus_done_map); | 1309 | clear_bit(flowid, msgbuf->txstatus_done_map); |
1296 | if (brcmf_flowring_qlen(msgbuf->flow, flowid)) | 1310 | commonring = msgbuf->flowrings[flowid]; |
1297 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid); | 1311 | qlen = brcmf_flowring_qlen(msgbuf->flow, flowid); |
1312 | if ((qlen > BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) || | ||
1313 | ((qlen) && (atomic_read(&commonring->outstanding_tx) < | ||
1314 | BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS))) | ||
1315 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true); | ||
1298 | } | 1316 | } |
1299 | 1317 | ||
1300 | return 0; | 1318 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index e91fa9a2c885..61c053a729be 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c | |||
@@ -1828,7 +1828,7 @@ static int brcmf_pcie_resume(struct pci_dev *pdev) | |||
1828 | goto cleanup; | 1828 | goto cleanup; |
1829 | brcmf_dbg(PCIE, "Hot resume, continue....\n"); | 1829 | brcmf_dbg(PCIE, "Hot resume, continue....\n"); |
1830 | brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); | 1830 | brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); |
1831 | brcmf_bus_change_state(bus, BRCMF_BUS_DATA); | 1831 | brcmf_bus_change_state(bus, BRCMF_BUS_UP); |
1832 | brcmf_pcie_intr_enable(devinfo); | 1832 | brcmf_pcie_intr_enable(devinfo); |
1833 | return 0; | 1833 | return 0; |
1834 | } | 1834 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index 99a37765888d..faec35c899ec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c | |||
@@ -44,7 +44,8 @@ | |||
44 | #include "chip.h" | 44 | #include "chip.h" |
45 | #include "firmware.h" | 45 | #include "firmware.h" |
46 | 46 | ||
47 | #define DCMD_RESP_TIMEOUT 2000 /* In milli second */ | 47 | #define DCMD_RESP_TIMEOUT 2000 /* In milli second */ |
48 | #define CTL_DONE_TIMEOUT 2000 /* In milli second */ | ||
48 | 49 | ||
49 | #ifdef DEBUG | 50 | #ifdef DEBUG |
50 | 51 | ||
@@ -495,9 +496,9 @@ struct brcmf_sdio { | |||
495 | u8 *ctrl_frame_buf; | 496 | u8 *ctrl_frame_buf; |
496 | u16 ctrl_frame_len; | 497 | u16 ctrl_frame_len; |
497 | bool ctrl_frame_stat; | 498 | bool ctrl_frame_stat; |
499 | int ctrl_frame_err; | ||
498 | 500 | ||
499 | spinlock_t txq_lock; /* protect bus->txq */ | 501 | spinlock_t txq_lock; /* protect bus->txq */ |
500 | struct semaphore tx_seq_lock; /* protect bus->tx_seq */ | ||
501 | wait_queue_head_t ctrl_wait; | 502 | wait_queue_head_t ctrl_wait; |
502 | wait_queue_head_t dcmd_resp_wait; | 503 | wait_queue_head_t dcmd_resp_wait; |
503 | 504 | ||
@@ -514,7 +515,6 @@ struct brcmf_sdio { | |||
514 | bool txoff; /* Transmit flow-controlled */ | 515 | bool txoff; /* Transmit flow-controlled */ |
515 | struct brcmf_sdio_count sdcnt; | 516 | struct brcmf_sdio_count sdcnt; |
516 | bool sr_enabled; /* SaveRestore enabled */ | 517 | bool sr_enabled; /* SaveRestore enabled */ |
517 | bool sleeping; /* SDIO bus sleeping */ | ||
518 | 518 | ||
519 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ | 519 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ |
520 | bool txglom; /* host tx glomming enable flag */ | 520 | bool txglom; /* host tx glomming enable flag */ |
@@ -1013,12 +1013,12 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
1013 | 1013 | ||
1014 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", | 1014 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", |
1015 | (sleep ? "SLEEP" : "WAKE"), | 1015 | (sleep ? "SLEEP" : "WAKE"), |
1016 | (bus->sleeping ? "SLEEP" : "WAKE")); | 1016 | (bus->sdiodev->sleeping ? "SLEEP" : "WAKE")); |
1017 | 1017 | ||
1018 | /* If SR is enabled control bus state with KSO */ | 1018 | /* If SR is enabled control bus state with KSO */ |
1019 | if (bus->sr_enabled) { | 1019 | if (bus->sr_enabled) { |
1020 | /* Done if we're already in the requested state */ | 1020 | /* Done if we're already in the requested state */ |
1021 | if (sleep == bus->sleeping) | 1021 | if (sleep == bus->sdiodev->sleeping) |
1022 | goto end; | 1022 | goto end; |
1023 | 1023 | ||
1024 | /* Going to sleep */ | 1024 | /* Going to sleep */ |
@@ -1050,12 +1050,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
1050 | bus->idlecount = 0; | 1050 | bus->idlecount = 0; |
1051 | err = brcmf_sdio_kso_control(bus, true); | 1051 | err = brcmf_sdio_kso_control(bus, true); |
1052 | } | 1052 | } |
1053 | if (!err) { | 1053 | if (err) { |
1054 | /* Change state */ | ||
1055 | bus->sleeping = sleep; | ||
1056 | brcmf_dbg(SDIO, "new state %s\n", | ||
1057 | (sleep ? "SLEEP" : "WAKE")); | ||
1058 | } else { | ||
1059 | brcmf_err("error while changing bus sleep state %d\n", | 1054 | brcmf_err("error while changing bus sleep state %d\n", |
1060 | err); | 1055 | err); |
1061 | goto done; | 1056 | goto done; |
@@ -1070,6 +1065,11 @@ end: | |||
1070 | } else { | 1065 | } else { |
1071 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); | 1066 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); |
1072 | } | 1067 | } |
1068 | bus->sdiodev->sleeping = sleep; | ||
1069 | if (sleep) | ||
1070 | wake_up(&bus->sdiodev->idle_wait); | ||
1071 | brcmf_dbg(SDIO, "new state %s\n", | ||
1072 | (sleep ? "SLEEP" : "WAKE")); | ||
1073 | done: | 1073 | done: |
1074 | brcmf_dbg(SDIO, "Exit: err=%d\n", err); | 1074 | brcmf_dbg(SDIO, "Exit: err=%d\n", err); |
1075 | return err; | 1075 | return err; |
@@ -1909,7 +1909,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1909 | bus->rxpending = true; | 1909 | bus->rxpending = true; |
1910 | 1910 | ||
1911 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; | 1911 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; |
1912 | !bus->rxskip && rxleft && brcmf_bus_ready(bus->sdiodev->bus_if); | 1912 | !bus->rxskip && rxleft && bus->sdiodev->state == BRCMF_STATE_DATA; |
1913 | rd->seq_num++, rxleft--) { | 1913 | rd->seq_num++, rxleft--) { |
1914 | 1914 | ||
1915 | /* Handle glomming separately */ | 1915 | /* Handle glomming separately */ |
@@ -2376,8 +2376,6 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2376 | /* Send frames until the limit or some other event */ | 2376 | /* Send frames until the limit or some other event */ |
2377 | for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { | 2377 | for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { |
2378 | pkt_num = 1; | 2378 | pkt_num = 1; |
2379 | if (down_interruptible(&bus->tx_seq_lock)) | ||
2380 | return cnt; | ||
2381 | if (bus->txglom) | 2379 | if (bus->txglom) |
2382 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, | 2380 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, |
2383 | bus->sdiodev->txglomsz); | 2381 | bus->sdiodev->txglomsz); |
@@ -2393,13 +2391,10 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2393 | __skb_queue_tail(&pktq, pkt); | 2391 | __skb_queue_tail(&pktq, pkt); |
2394 | } | 2392 | } |
2395 | spin_unlock_bh(&bus->txq_lock); | 2393 | spin_unlock_bh(&bus->txq_lock); |
2396 | if (i == 0) { | 2394 | if (i == 0) |
2397 | up(&bus->tx_seq_lock); | ||
2398 | break; | 2395 | break; |
2399 | } | ||
2400 | 2396 | ||
2401 | ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); | 2397 | ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); |
2402 | up(&bus->tx_seq_lock); | ||
2403 | 2398 | ||
2404 | cnt += i; | 2399 | cnt += i; |
2405 | 2400 | ||
@@ -2420,7 +2415,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2420 | } | 2415 | } |
2421 | 2416 | ||
2422 | /* Deflow-control stack if needed */ | 2417 | /* Deflow-control stack if needed */ |
2423 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) && | 2418 | if ((bus->sdiodev->state == BRCMF_STATE_DATA) && |
2424 | bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { | 2419 | bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { |
2425 | bus->txoff = false; | 2420 | bus->txoff = false; |
2426 | brcmf_txflowblock(bus->sdiodev->dev, false); | 2421 | brcmf_txflowblock(bus->sdiodev->dev, false); |
@@ -2508,7 +2503,7 @@ static void brcmf_sdio_bus_stop(struct device *dev) | |||
2508 | bus->watchdog_tsk = NULL; | 2503 | bus->watchdog_tsk = NULL; |
2509 | } | 2504 | } |
2510 | 2505 | ||
2511 | if (bus_if->state == BRCMF_BUS_DOWN) { | 2506 | if (sdiodev->state != BRCMF_STATE_NOMEDIUM) { |
2512 | sdio_claim_host(sdiodev->func[1]); | 2507 | sdio_claim_host(sdiodev->func[1]); |
2513 | 2508 | ||
2514 | /* Enable clock for device interrupts */ | 2509 | /* Enable clock for device interrupts */ |
@@ -2543,8 +2538,7 @@ static void brcmf_sdio_bus_stop(struct device *dev) | |||
2543 | brcmu_pktq_flush(&bus->txq, true, NULL, NULL); | 2538 | brcmu_pktq_flush(&bus->txq, true, NULL, NULL); |
2544 | 2539 | ||
2545 | /* Clear any held glomming stuff */ | 2540 | /* Clear any held glomming stuff */ |
2546 | if (bus->glomd) | 2541 | brcmu_pkt_buf_free_skb(bus->glomd); |
2547 | brcmu_pkt_buf_free_skb(bus->glomd); | ||
2548 | brcmf_sdio_free_glom(bus); | 2542 | brcmf_sdio_free_glom(bus); |
2549 | 2543 | ||
2550 | /* Clear rx control and wake any waiters */ | 2544 | /* Clear rx control and wake any waiters */ |
@@ -2609,6 +2603,21 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | |||
2609 | return ret; | 2603 | return ret; |
2610 | } | 2604 | } |
2611 | 2605 | ||
2606 | static int brcmf_sdio_pm_resume_wait(struct brcmf_sdio_dev *sdiodev) | ||
2607 | { | ||
2608 | #ifdef CONFIG_PM_SLEEP | ||
2609 | int retry; | ||
2610 | |||
2611 | /* Wait for possible resume to complete */ | ||
2612 | retry = 0; | ||
2613 | while ((atomic_read(&sdiodev->suspend)) && (retry++ != 50)) | ||
2614 | msleep(20); | ||
2615 | if (atomic_read(&sdiodev->suspend)) | ||
2616 | return -EIO; | ||
2617 | #endif | ||
2618 | return 0; | ||
2619 | } | ||
2620 | |||
2612 | static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | 2621 | static void brcmf_sdio_dpc(struct brcmf_sdio *bus) |
2613 | { | 2622 | { |
2614 | u32 newstatus = 0; | 2623 | u32 newstatus = 0; |
@@ -2619,6 +2628,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2619 | 2628 | ||
2620 | brcmf_dbg(TRACE, "Enter\n"); | 2629 | brcmf_dbg(TRACE, "Enter\n"); |
2621 | 2630 | ||
2631 | if (brcmf_sdio_pm_resume_wait(bus->sdiodev)) | ||
2632 | return; | ||
2633 | |||
2622 | sdio_claim_host(bus->sdiodev->func[1]); | 2634 | sdio_claim_host(bus->sdiodev->func[1]); |
2623 | 2635 | ||
2624 | /* If waiting for HTAVAIL, check status */ | 2636 | /* If waiting for HTAVAIL, check status */ |
@@ -2725,17 +2737,14 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2725 | brcmf_sdio_clrintr(bus); | 2737 | brcmf_sdio_clrintr(bus); |
2726 | 2738 | ||
2727 | if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && | 2739 | if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && |
2728 | (down_interruptible(&bus->tx_seq_lock) == 0)) { | 2740 | data_ok(bus)) { |
2729 | if (data_ok(bus)) { | 2741 | sdio_claim_host(bus->sdiodev->func[1]); |
2730 | sdio_claim_host(bus->sdiodev->func[1]); | 2742 | err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, |
2731 | err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, | 2743 | bus->ctrl_frame_len); |
2732 | bus->ctrl_frame_len); | 2744 | sdio_release_host(bus->sdiodev->func[1]); |
2733 | sdio_release_host(bus->sdiodev->func[1]); | 2745 | bus->ctrl_frame_err = err; |
2734 | 2746 | bus->ctrl_frame_stat = false; | |
2735 | bus->ctrl_frame_stat = false; | 2747 | brcmf_sdio_wait_event_wakeup(bus); |
2736 | brcmf_sdio_wait_event_wakeup(bus); | ||
2737 | } | ||
2738 | up(&bus->tx_seq_lock); | ||
2739 | } | 2748 | } |
2740 | /* Send queued frames (limit 1 if rx may still be pending) */ | 2749 | /* Send queued frames (limit 1 if rx may still be pending) */ |
2741 | if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && | 2750 | if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && |
@@ -2746,7 +2755,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2746 | brcmf_sdio_sendfromq(bus, framecnt); | 2755 | brcmf_sdio_sendfromq(bus, framecnt); |
2747 | } | 2756 | } |
2748 | 2757 | ||
2749 | if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) { | 2758 | if ((bus->sdiodev->state != BRCMF_STATE_DATA) || (err != 0)) { |
2750 | brcmf_err("failed backplane access over SDIO, halting operation\n"); | 2759 | brcmf_err("failed backplane access over SDIO, halting operation\n"); |
2751 | atomic_set(&bus->intstatus, 0); | 2760 | atomic_set(&bus->intstatus, 0); |
2752 | } else if (atomic_read(&bus->intstatus) || | 2761 | } else if (atomic_read(&bus->intstatus) || |
@@ -2947,43 +2956,30 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2947 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2956 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2948 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2957 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2949 | struct brcmf_sdio *bus = sdiodev->bus; | 2958 | struct brcmf_sdio *bus = sdiodev->bus; |
2950 | int ret = -1; | 2959 | int ret; |
2951 | 2960 | ||
2952 | brcmf_dbg(TRACE, "Enter\n"); | 2961 | brcmf_dbg(TRACE, "Enter\n"); |
2953 | 2962 | ||
2954 | if (down_interruptible(&bus->tx_seq_lock)) | 2963 | /* Send from dpc */ |
2955 | return -EINTR; | 2964 | bus->ctrl_frame_buf = msg; |
2956 | 2965 | bus->ctrl_frame_len = msglen; | |
2957 | if (!data_ok(bus)) { | 2966 | bus->ctrl_frame_stat = true; |
2958 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", | 2967 | if (atomic_read(&bus->dpc_tskcnt) == 0) { |
2959 | bus->tx_max, bus->tx_seq); | 2968 | atomic_inc(&bus->dpc_tskcnt); |
2960 | up(&bus->tx_seq_lock); | 2969 | queue_work(bus->brcmf_wq, &bus->datawork); |
2961 | /* Send from dpc */ | ||
2962 | bus->ctrl_frame_buf = msg; | ||
2963 | bus->ctrl_frame_len = msglen; | ||
2964 | bus->ctrl_frame_stat = true; | ||
2965 | |||
2966 | wait_event_interruptible_timeout(bus->ctrl_wait, | ||
2967 | !bus->ctrl_frame_stat, | ||
2968 | msecs_to_jiffies(2000)); | ||
2969 | |||
2970 | if (!bus->ctrl_frame_stat) { | ||
2971 | brcmf_dbg(SDIO, "ctrl_frame_stat == false\n"); | ||
2972 | ret = 0; | ||
2973 | } else { | ||
2974 | brcmf_dbg(SDIO, "ctrl_frame_stat == true\n"); | ||
2975 | bus->ctrl_frame_stat = false; | ||
2976 | if (down_interruptible(&bus->tx_seq_lock)) | ||
2977 | return -EINTR; | ||
2978 | ret = -1; | ||
2979 | } | ||
2980 | } | 2970 | } |
2981 | if (ret == -1) { | 2971 | |
2982 | sdio_claim_host(bus->sdiodev->func[1]); | 2972 | wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, |
2983 | brcmf_sdio_bus_sleep(bus, false, false); | 2973 | msecs_to_jiffies(CTL_DONE_TIMEOUT)); |
2984 | ret = brcmf_sdio_tx_ctrlframe(bus, msg, msglen); | 2974 | |
2985 | sdio_release_host(bus->sdiodev->func[1]); | 2975 | if (!bus->ctrl_frame_stat) { |
2986 | up(&bus->tx_seq_lock); | 2976 | brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", |
2977 | bus->ctrl_frame_err); | ||
2978 | ret = bus->ctrl_frame_err; | ||
2979 | } else { | ||
2980 | brcmf_dbg(SDIO, "ctrl_frame timeout\n"); | ||
2981 | bus->ctrl_frame_stat = false; | ||
2982 | ret = -ETIMEDOUT; | ||
2987 | } | 2983 | } |
2988 | 2984 | ||
2989 | if (ret) | 2985 | if (ret) |
@@ -2991,7 +2987,7 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2991 | else | 2987 | else |
2992 | bus->sdcnt.tx_ctlpkts++; | 2988 | bus->sdcnt.tx_ctlpkts++; |
2993 | 2989 | ||
2994 | return ret ? -EIO : 0; | 2990 | return ret; |
2995 | } | 2991 | } |
2996 | 2992 | ||
2997 | #ifdef DEBUG | 2993 | #ifdef DEBUG |
@@ -3414,8 +3410,8 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, | |||
3414 | goto err; | 3410 | goto err; |
3415 | } | 3411 | } |
3416 | 3412 | ||
3417 | /* Allow HT Clock now that the ARM is running. */ | 3413 | /* Allow full data communication using DPC from now on. */ |
3418 | brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_LOAD); | 3414 | bus->sdiodev->state = BRCMF_STATE_DATA; |
3419 | bcmerror = 0; | 3415 | bcmerror = 0; |
3420 | 3416 | ||
3421 | err: | 3417 | err: |
@@ -3561,7 +3557,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
3561 | return; | 3557 | return; |
3562 | } | 3558 | } |
3563 | 3559 | ||
3564 | if (!brcmf_bus_ready(bus->sdiodev->bus_if)) { | 3560 | if (bus->sdiodev->state != BRCMF_STATE_DATA) { |
3565 | brcmf_err("bus is down. we have nothing to do\n"); | 3561 | brcmf_err("bus is down. we have nothing to do\n"); |
3566 | return; | 3562 | return; |
3567 | } | 3563 | } |
@@ -3584,10 +3580,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
3584 | 3580 | ||
3585 | static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | 3581 | static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) |
3586 | { | 3582 | { |
3587 | #ifdef DEBUG | ||
3588 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); | ||
3589 | #endif /* DEBUG */ | ||
3590 | |||
3591 | brcmf_dbg(TIMER, "Enter\n"); | 3583 | brcmf_dbg(TIMER, "Enter\n"); |
3592 | 3584 | ||
3593 | /* Poll period: check device if appropriate. */ | 3585 | /* Poll period: check device if appropriate. */ |
@@ -3631,7 +3623,7 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | |||
3631 | } | 3623 | } |
3632 | #ifdef DEBUG | 3624 | #ifdef DEBUG |
3633 | /* Poll for console output periodically */ | 3625 | /* Poll for console output periodically */ |
3634 | if (bus_if && bus_if->state == BRCMF_BUS_DATA && | 3626 | if (bus->sdiodev->state == BRCMF_STATE_DATA && |
3635 | bus->console_interval != 0) { | 3627 | bus->console_interval != 0) { |
3636 | bus->console.count += BRCMF_WD_POLL_MS; | 3628 | bus->console.count += BRCMF_WD_POLL_MS; |
3637 | if (bus->console.count >= bus->console_interval) { | 3629 | if (bus->console.count >= bus->console_interval) { |
@@ -3872,11 +3864,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | |||
3872 | goto fail; | 3864 | goto fail; |
3873 | } | 3865 | } |
3874 | 3866 | ||
3875 | /* SDIO register access works so moving | ||
3876 | * state from UNKNOWN to DOWN. | ||
3877 | */ | ||
3878 | brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN); | ||
3879 | |||
3880 | bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops); | 3867 | bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops); |
3881 | if (IS_ERR(bus->ci)) { | 3868 | if (IS_ERR(bus->ci)) { |
3882 | brcmf_err("brcmf_chip_attach failed!\n"); | 3869 | brcmf_err("brcmf_chip_attach failed!\n"); |
@@ -4010,18 +3997,16 @@ static void brcmf_sdio_firmware_callback(struct device *dev, | |||
4010 | 3997 | ||
4011 | brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev)); | 3998 | brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev)); |
4012 | 3999 | ||
4013 | /* try to download image and nvram to the dongle */ | ||
4014 | if (bus_if->state == BRCMF_BUS_DOWN) { | ||
4015 | bus->alp_only = true; | ||
4016 | err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); | ||
4017 | if (err) | ||
4018 | goto fail; | ||
4019 | bus->alp_only = false; | ||
4020 | } | ||
4021 | |||
4022 | if (!bus_if->drvr) | 4000 | if (!bus_if->drvr) |
4023 | return; | 4001 | return; |
4024 | 4002 | ||
4003 | /* try to download image and nvram to the dongle */ | ||
4004 | bus->alp_only = true; | ||
4005 | err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); | ||
4006 | if (err) | ||
4007 | goto fail; | ||
4008 | bus->alp_only = false; | ||
4009 | |||
4025 | /* Start the watchdog timer */ | 4010 | /* Start the watchdog timer */ |
4026 | bus->sdcnt.tickcnt = 0; | 4011 | bus->sdcnt.tickcnt = 0; |
4027 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); | 4012 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); |
@@ -4147,7 +4132,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4147 | 4132 | ||
4148 | spin_lock_init(&bus->rxctl_lock); | 4133 | spin_lock_init(&bus->rxctl_lock); |
4149 | spin_lock_init(&bus->txq_lock); | 4134 | spin_lock_init(&bus->txq_lock); |
4150 | sema_init(&bus->tx_seq_lock, 1); | ||
4151 | init_waitqueue_head(&bus->ctrl_wait); | 4135 | init_waitqueue_head(&bus->ctrl_wait); |
4152 | init_waitqueue_head(&bus->dcmd_resp_wait); | 4136 | init_waitqueue_head(&bus->dcmd_resp_wait); |
4153 | 4137 | ||
@@ -4218,7 +4202,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4218 | bus->idleclock = BRCMF_IDLE_ACTIVE; | 4202 | bus->idleclock = BRCMF_IDLE_ACTIVE; |
4219 | 4203 | ||
4220 | /* SR state */ | 4204 | /* SR state */ |
4221 | bus->sleeping = false; | ||
4222 | bus->sr_enabled = false; | 4205 | bus->sr_enabled = false; |
4223 | 4206 | ||
4224 | brcmf_sdio_debugfs_create(bus); | 4207 | brcmf_sdio_debugfs_create(bus); |
@@ -4259,7 +4242,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) | |||
4259 | destroy_workqueue(bus->brcmf_wq); | 4242 | destroy_workqueue(bus->brcmf_wq); |
4260 | 4243 | ||
4261 | if (bus->ci) { | 4244 | if (bus->ci) { |
4262 | if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { | 4245 | if (bus->sdiodev->state != BRCMF_STATE_NOMEDIUM) { |
4263 | sdio_claim_host(bus->sdiodev->func[1]); | 4246 | sdio_claim_host(bus->sdiodev->func[1]); |
4264 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | 4247 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
4265 | /* Leave the device in state where it is | 4248 | /* Leave the device in state where it is |
@@ -4294,7 +4277,7 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick) | |||
4294 | } | 4277 | } |
4295 | 4278 | ||
4296 | /* don't start the wd until fw is loaded */ | 4279 | /* don't start the wd until fw is loaded */ |
4297 | if (bus->sdiodev->bus_if->state != BRCMF_BUS_DATA) | 4280 | if (bus->sdiodev->state != BRCMF_STATE_DATA) |
4298 | return; | 4281 | return; |
4299 | 4282 | ||
4300 | if (wdtick) { | 4283 | if (wdtick) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h index 8eb42620129c..ec2586a8425c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h | |||
@@ -155,6 +155,13 @@ | |||
155 | /* watchdog polling interval in ms */ | 155 | /* watchdog polling interval in ms */ |
156 | #define BRCMF_WD_POLL_MS 10 | 156 | #define BRCMF_WD_POLL_MS 10 |
157 | 157 | ||
158 | /* The state of the bus */ | ||
159 | enum brcmf_sdio_state { | ||
160 | BRCMF_STATE_DOWN, /* Device available, still initialising */ | ||
161 | BRCMF_STATE_DATA, /* Ready for data transfers, DPC enabled */ | ||
162 | BRCMF_STATE_NOMEDIUM /* No medium access to dongle possible */ | ||
163 | }; | ||
164 | |||
158 | struct brcmf_sdreg { | 165 | struct brcmf_sdreg { |
159 | int func; | 166 | int func; |
160 | int offset; | 167 | int offset; |
@@ -169,8 +176,8 @@ struct brcmf_sdio_dev { | |||
169 | u32 sbwad; /* Save backplane window address */ | 176 | u32 sbwad; /* Save backplane window address */ |
170 | struct brcmf_sdio *bus; | 177 | struct brcmf_sdio *bus; |
171 | atomic_t suspend; /* suspend flag */ | 178 | atomic_t suspend; /* suspend flag */ |
172 | wait_queue_head_t request_word_wait; | 179 | bool sleeping; |
173 | wait_queue_head_t request_buffer_wait; | 180 | wait_queue_head_t idle_wait; |
174 | struct device *dev; | 181 | struct device *dev; |
175 | struct brcmf_bus *bus_if; | 182 | struct brcmf_bus *bus_if; |
176 | struct brcmfmac_sdio_platform_data *pdata; | 183 | struct brcmfmac_sdio_platform_data *pdata; |
@@ -187,6 +194,7 @@ struct brcmf_sdio_dev { | |||
187 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 194 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
188 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 195 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
189 | bool wowl_enabled; | 196 | bool wowl_enabled; |
197 | enum brcmf_sdio_state state; | ||
190 | }; | 198 | }; |
191 | 199 | ||
192 | /* sdio core registers */ | 200 | /* sdio core registers */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 4572defc280f..5df6aa72cc2d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -421,7 +421,7 @@ fail: | |||
421 | brcmf_err("fail!\n"); | 421 | brcmf_err("fail!\n"); |
422 | while (!list_empty(q)) { | 422 | while (!list_empty(q)) { |
423 | req = list_entry(q->next, struct brcmf_usbreq, list); | 423 | req = list_entry(q->next, struct brcmf_usbreq, list); |
424 | if (req && req->urb) | 424 | if (req) |
425 | usb_free_urb(req->urb); | 425 | usb_free_urb(req->urb); |
426 | list_del(q->next); | 426 | list_del(q->next); |
427 | } | 427 | } |
@@ -576,7 +576,7 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) | |||
576 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN); | 576 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN); |
577 | } else if (state == BRCMFMAC_USB_STATE_UP) { | 577 | } else if (state == BRCMFMAC_USB_STATE_UP) { |
578 | brcmf_dbg(USB, "DBUS is up\n"); | 578 | brcmf_dbg(USB, "DBUS is up\n"); |
579 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DATA); | 579 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_UP); |
580 | } else { | 580 | } else { |
581 | brcmf_dbg(USB, "DBUS current state=%d\n", state); | 581 | brcmf_dbg(USB, "DBUS current state=%d\n", state); |
582 | } | 582 | } |
@@ -1263,6 +1263,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) | |||
1263 | ret = brcmf_usb_bus_setup(devinfo); | 1263 | ret = brcmf_usb_bus_setup(devinfo); |
1264 | if (ret) | 1264 | if (ret) |
1265 | goto fail; | 1265 | goto fail; |
1266 | /* we are done */ | ||
1267 | return 0; | ||
1266 | } | 1268 | } |
1267 | bus->chip = bus_pub->devid; | 1269 | bus->chip = bus_pub->devid; |
1268 | bus->chiprev = bus_pub->chiprev; | 1270 | bus->chiprev = bus_pub->chiprev; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c index c9a8b9360ab1..7a1fbb2e3a71 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c | |||
@@ -78,7 +78,7 @@ int brcms_debugfs_hardware_read(struct seq_file *s, void *data) | |||
78 | struct brcms_hardware *hw = drvr->wlc->hw; | 78 | struct brcms_hardware *hw = drvr->wlc->hw; |
79 | struct bcma_device *core = hw->d11core; | 79 | struct bcma_device *core = hw->d11core; |
80 | struct bcma_bus *bus = core->bus; | 80 | struct bcma_bus *bus = core->bus; |
81 | char boardrev[10]; | 81 | char boardrev[BRCMU_BOARDREV_LEN]; |
82 | 82 | ||
83 | seq_printf(s, "chipnum 0x%x\n" | 83 | seq_printf(s, "chipnum 0x%x\n" |
84 | "chiprev 0x%x\n" | 84 | "chiprev 0x%x\n" |
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index 906e89ddf319..0543607002fd 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c | |||
@@ -267,15 +267,43 @@ char *brcmu_boardrev_str(u32 brev, char *buf) | |||
267 | char c; | 267 | char c; |
268 | 268 | ||
269 | if (brev < 0x100) { | 269 | if (brev < 0x100) { |
270 | snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); | 270 | snprintf(buf, BRCMU_BOARDREV_LEN, "%d.%d", |
271 | (brev & 0xf0) >> 4, brev & 0xf); | ||
271 | } else { | 272 | } else { |
272 | c = (brev & 0xf000) == 0x1000 ? 'P' : 'A'; | 273 | c = (brev & 0xf000) == 0x1000 ? 'P' : 'A'; |
273 | snprintf(buf, 8, "%c%03x", c, brev & 0xfff); | 274 | snprintf(buf, BRCMU_BOARDREV_LEN, "%c%03x", c, brev & 0xfff); |
274 | } | 275 | } |
275 | return buf; | 276 | return buf; |
276 | } | 277 | } |
277 | EXPORT_SYMBOL(brcmu_boardrev_str); | 278 | EXPORT_SYMBOL(brcmu_boardrev_str); |
278 | 279 | ||
280 | char *brcmu_dotrev_str(u32 dotrev, char *buf) | ||
281 | { | ||
282 | u8 dotval[4]; | ||
283 | |||
284 | if (!dotrev) { | ||
285 | snprintf(buf, BRCMU_DOTREV_LEN, "unknown"); | ||
286 | return buf; | ||
287 | } | ||
288 | dotval[0] = (dotrev >> 24) & 0xFF; | ||
289 | dotval[1] = (dotrev >> 16) & 0xFF; | ||
290 | dotval[2] = (dotrev >> 8) & 0xFF; | ||
291 | dotval[3] = dotrev & 0xFF; | ||
292 | |||
293 | if (dotval[3]) | ||
294 | snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d.%d", dotval[0], | ||
295 | dotval[1], dotval[2], dotval[3]); | ||
296 | else if (dotval[2]) | ||
297 | snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d", dotval[0], | ||
298 | dotval[1], dotval[2]); | ||
299 | else | ||
300 | snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d", dotval[0], | ||
301 | dotval[1]); | ||
302 | |||
303 | return buf; | ||
304 | } | ||
305 | EXPORT_SYMBOL(brcmu_dotrev_str); | ||
306 | |||
279 | #if defined(DEBUG) | 307 | #if defined(DEBUG) |
280 | /* pretty hex print a pkt buffer chain */ | 308 | /* pretty hex print a pkt buffer chain */ |
281 | void brcmu_prpkt(const char *msg, struct sk_buff *p0) | 309 | void brcmu_prpkt(const char *msg, struct sk_buff *p0) |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h index a043e29f07e2..41969527b459 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h | |||
@@ -218,6 +218,10 @@ void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...) | |||
218 | } | 218 | } |
219 | #endif | 219 | #endif |
220 | 220 | ||
221 | #define BRCMU_BOARDREV_LEN 8 | ||
222 | #define BRCMU_DOTREV_LEN 16 | ||
223 | |||
221 | char *brcmu_boardrev_str(u32 brev, char *buf); | 224 | char *brcmu_boardrev_str(u32 brev, char *buf); |
225 | char *brcmu_dotrev_str(u32 dotrev, char *buf); | ||
222 | 226 | ||
223 | #endif /* _BRCMU_UTILS_H_ */ | 227 | #endif /* _BRCMU_UTILS_H_ */ |
diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c index 6f1b9aace8b3..30e7646d04af 100644 --- a/drivers/net/wireless/cw1200/fwio.c +++ b/drivers/net/wireless/cw1200/fwio.c | |||
@@ -66,25 +66,31 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
66 | do { \ | 66 | do { \ |
67 | ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \ | 67 | ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \ |
68 | if (ret < 0) \ | 68 | if (ret < 0) \ |
69 | goto error; \ | 69 | goto exit; \ |
70 | } while (0) | ||
71 | #define APB_WRITE2(reg, val) \ | ||
72 | do { \ | ||
73 | ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \ | ||
74 | if (ret < 0) \ | ||
75 | goto free_buffer; \ | ||
70 | } while (0) | 76 | } while (0) |
71 | #define APB_READ(reg, val) \ | 77 | #define APB_READ(reg, val) \ |
72 | do { \ | 78 | do { \ |
73 | ret = cw1200_apb_read_32(priv, CW1200_APB(reg), &(val)); \ | 79 | ret = cw1200_apb_read_32(priv, CW1200_APB(reg), &(val)); \ |
74 | if (ret < 0) \ | 80 | if (ret < 0) \ |
75 | goto error; \ | 81 | goto free_buffer; \ |
76 | } while (0) | 82 | } while (0) |
77 | #define REG_WRITE(reg, val) \ | 83 | #define REG_WRITE(reg, val) \ |
78 | do { \ | 84 | do { \ |
79 | ret = cw1200_reg_write_32(priv, (reg), (val)); \ | 85 | ret = cw1200_reg_write_32(priv, (reg), (val)); \ |
80 | if (ret < 0) \ | 86 | if (ret < 0) \ |
81 | goto error; \ | 87 | goto exit; \ |
82 | } while (0) | 88 | } while (0) |
83 | #define REG_READ(reg, val) \ | 89 | #define REG_READ(reg, val) \ |
84 | do { \ | 90 | do { \ |
85 | ret = cw1200_reg_read_32(priv, (reg), &(val)); \ | 91 | ret = cw1200_reg_read_32(priv, (reg), &(val)); \ |
86 | if (ret < 0) \ | 92 | if (ret < 0) \ |
87 | goto error; \ | 93 | goto exit; \ |
88 | } while (0) | 94 | } while (0) |
89 | 95 | ||
90 | switch (priv->hw_revision) { | 96 | switch (priv->hw_revision) { |
@@ -142,14 +148,14 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
142 | ret = request_firmware(&firmware, fw_path, priv->pdev); | 148 | ret = request_firmware(&firmware, fw_path, priv->pdev); |
143 | if (ret) { | 149 | if (ret) { |
144 | pr_err("Can't load firmware file %s.\n", fw_path); | 150 | pr_err("Can't load firmware file %s.\n", fw_path); |
145 | goto error; | 151 | goto exit; |
146 | } | 152 | } |
147 | 153 | ||
148 | buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL | GFP_DMA); | 154 | buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL | GFP_DMA); |
149 | if (!buf) { | 155 | if (!buf) { |
150 | pr_err("Can't allocate firmware load buffer.\n"); | 156 | pr_err("Can't allocate firmware load buffer.\n"); |
151 | ret = -ENOMEM; | 157 | ret = -ENOMEM; |
152 | goto error; | 158 | goto firmware_release; |
153 | } | 159 | } |
154 | 160 | ||
155 | /* Check if the bootloader is ready */ | 161 | /* Check if the bootloader is ready */ |
@@ -163,7 +169,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
163 | if (val32 != DOWNLOAD_I_AM_HERE) { | 169 | if (val32 != DOWNLOAD_I_AM_HERE) { |
164 | pr_err("Bootloader is not ready.\n"); | 170 | pr_err("Bootloader is not ready.\n"); |
165 | ret = -ETIMEDOUT; | 171 | ret = -ETIMEDOUT; |
166 | goto error; | 172 | goto free_buffer; |
167 | } | 173 | } |
168 | 174 | ||
169 | /* Calculcate number of download blocks */ | 175 | /* Calculcate number of download blocks */ |
@@ -171,7 +177,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
171 | 177 | ||
172 | /* Updating the length in Download Ctrl Area */ | 178 | /* Updating the length in Download Ctrl Area */ |
173 | val32 = firmware->size; /* Explicit cast from size_t to u32 */ | 179 | val32 = firmware->size; /* Explicit cast from size_t to u32 */ |
174 | APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, val32); | 180 | APB_WRITE2(DOWNLOAD_IMAGE_SIZE_REG, val32); |
175 | 181 | ||
176 | /* Firmware downloading loop */ | 182 | /* Firmware downloading loop */ |
177 | for (block = 0; block < num_blocks; block++) { | 183 | for (block = 0; block < num_blocks; block++) { |
@@ -183,7 +189,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
183 | if (val32 != DOWNLOAD_PENDING) { | 189 | if (val32 != DOWNLOAD_PENDING) { |
184 | pr_err("Bootloader reported error %d.\n", val32); | 190 | pr_err("Bootloader reported error %d.\n", val32); |
185 | ret = -EIO; | 191 | ret = -EIO; |
186 | goto error; | 192 | goto free_buffer; |
187 | } | 193 | } |
188 | 194 | ||
189 | /* loop until put - get <= 24K */ | 195 | /* loop until put - get <= 24K */ |
@@ -198,7 +204,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
198 | if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) { | 204 | if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) { |
199 | pr_err("Timeout waiting for FIFO.\n"); | 205 | pr_err("Timeout waiting for FIFO.\n"); |
200 | ret = -ETIMEDOUT; | 206 | ret = -ETIMEDOUT; |
201 | goto error; | 207 | goto free_buffer; |
202 | } | 208 | } |
203 | 209 | ||
204 | /* calculate the block size */ | 210 | /* calculate the block size */ |
@@ -220,12 +226,12 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
220 | if (ret < 0) { | 226 | if (ret < 0) { |
221 | pr_err("Can't write firmware block @ %d!\n", | 227 | pr_err("Can't write firmware block @ %d!\n", |
222 | put & (DOWNLOAD_FIFO_SIZE - 1)); | 228 | put & (DOWNLOAD_FIFO_SIZE - 1)); |
223 | goto error; | 229 | goto free_buffer; |
224 | } | 230 | } |
225 | 231 | ||
226 | /* update the put register */ | 232 | /* update the put register */ |
227 | put += block_size; | 233 | put += block_size; |
228 | APB_WRITE(DOWNLOAD_PUT_REG, put); | 234 | APB_WRITE2(DOWNLOAD_PUT_REG, put); |
229 | } /* End of firmware download loop */ | 235 | } /* End of firmware download loop */ |
230 | 236 | ||
231 | /* Wait for the download completion */ | 237 | /* Wait for the download completion */ |
@@ -238,19 +244,21 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
238 | if (val32 != DOWNLOAD_SUCCESS) { | 244 | if (val32 != DOWNLOAD_SUCCESS) { |
239 | pr_err("Wait for download completion failed: 0x%.8X\n", val32); | 245 | pr_err("Wait for download completion failed: 0x%.8X\n", val32); |
240 | ret = -ETIMEDOUT; | 246 | ret = -ETIMEDOUT; |
241 | goto error; | 247 | goto free_buffer; |
242 | } else { | 248 | } else { |
243 | pr_info("Firmware download completed.\n"); | 249 | pr_info("Firmware download completed.\n"); |
244 | ret = 0; | 250 | ret = 0; |
245 | } | 251 | } |
246 | 252 | ||
247 | error: | 253 | free_buffer: |
248 | kfree(buf); | 254 | kfree(buf); |
249 | if (firmware) | 255 | firmware_release: |
250 | release_firmware(firmware); | 256 | release_firmware(firmware); |
257 | exit: | ||
251 | return ret; | 258 | return ret; |
252 | 259 | ||
253 | #undef APB_WRITE | 260 | #undef APB_WRITE |
261 | #undef APB_WRITE2 | ||
254 | #undef APB_READ | 262 | #undef APB_READ |
255 | #undef REG_WRITE | 263 | #undef REG_WRITE |
256 | #undef REG_READ | 264 | #undef REG_READ |
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index f2e276faca70..bff81b8d4164 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c | |||
@@ -39,9 +39,9 @@ static int cw1200_scan_start(struct cw1200_common *priv, struct wsm_scan *scan) | |||
39 | cancel_delayed_work_sync(&priv->clear_recent_scan_work); | 39 | cancel_delayed_work_sync(&priv->clear_recent_scan_work); |
40 | atomic_set(&priv->scan.in_progress, 1); | 40 | atomic_set(&priv->scan.in_progress, 1); |
41 | atomic_set(&priv->recent_scan, 1); | 41 | atomic_set(&priv->recent_scan, 1); |
42 | cw1200_pm_stay_awake(&priv->pm_state, tmo * HZ / 1000); | 42 | cw1200_pm_stay_awake(&priv->pm_state, msecs_to_jiffies(tmo)); |
43 | queue_delayed_work(priv->workqueue, &priv->scan.timeout, | 43 | queue_delayed_work(priv->workqueue, &priv->scan.timeout, |
44 | tmo * HZ / 1000); | 44 | msecs_to_jiffies(tmo)); |
45 | ret = wsm_scan(priv, scan); | 45 | ret = wsm_scan(priv, scan); |
46 | if (ret) { | 46 | if (ret) { |
47 | atomic_set(&priv->scan.in_progress, 0); | 47 | atomic_set(&priv->scan.in_progress, 0); |
@@ -386,8 +386,8 @@ void cw1200_probe_work(struct work_struct *work) | |||
386 | if (down_trylock(&priv->scan.lock)) { | 386 | if (down_trylock(&priv->scan.lock)) { |
387 | /* Scan is already in progress. Requeue self. */ | 387 | /* Scan is already in progress. Requeue self. */ |
388 | schedule(); | 388 | schedule(); |
389 | queue_delayed_work(priv->workqueue, | 389 | queue_delayed_work(priv->workqueue, &priv->scan.probe_work, |
390 | &priv->scan.probe_work, HZ / 10); | 390 | msecs_to_jiffies(100)); |
391 | mutex_unlock(&priv->conf_mutex); | 391 | mutex_unlock(&priv->conf_mutex); |
392 | return; | 392 | return; |
393 | } | 393 | } |
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 596525528f50..fd8d83dd4f62 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
@@ -145,7 +145,7 @@ static void ap_free_sta(struct ap_data *ap, struct sta_info *sta) | |||
145 | if (sta->aid > 0) | 145 | if (sta->aid > 0) |
146 | ap->sta_aid[sta->aid - 1] = NULL; | 146 | ap->sta_aid[sta->aid - 1] = NULL; |
147 | 147 | ||
148 | if (!sta->ap && sta->u.sta.challenge) | 148 | if (!sta->ap) |
149 | kfree(sta->u.sta.challenge); | 149 | kfree(sta->u.sta.challenge); |
150 | del_timer_sync(&sta->timer); | 150 | del_timer_sync(&sta->timer); |
151 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 151 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index de43dd7e170a..c4d6dd7402d9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -1228,11 +1228,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1228 | trans_cfg.no_reclaim_cmds = no_reclaim_cmds; | 1228 | trans_cfg.no_reclaim_cmds = no_reclaim_cmds; |
1229 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); | 1229 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); |
1230 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; | 1230 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; |
1231 | if (!iwlwifi_mod_params.wd_disable) | 1231 | trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED; |
1232 | trans_cfg.queue_watchdog_timeout = | 1232 | |
1233 | priv->cfg->base_params->wd_timeout; | ||
1234 | else | ||
1235 | trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; | ||
1236 | trans_cfg.command_names = iwl_dvm_cmd_strings; | 1233 | trans_cfg.command_names = iwl_dvm_cmd_strings; |
1237 | trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM; | 1234 | trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM; |
1238 | 1235 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index d1ce3ce13591..1e40a12de077 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -715,7 +715,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
715 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; | 715 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; |
716 | 716 | ||
717 | iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, | 717 | iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, |
718 | buf_size, ssn); | 718 | buf_size, ssn, 0); |
719 | 719 | ||
720 | /* | 720 | /* |
721 | * If the limit is 0, then it wasn't initialised yet, | 721 | * If the limit is 0, then it wasn't initialised yet, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index d5cee1530597..4dbef7e58c2e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -267,7 +267,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
267 | for (i = 0; i < n_queues; i++) | 267 | for (i = 0; i < n_queues; i++) |
268 | if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED) | 268 | if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED) |
269 | iwl_trans_ac_txq_enable(priv->trans, i, | 269 | iwl_trans_ac_txq_enable(priv->trans, i, |
270 | queue_to_txf[i]); | 270 | queue_to_txf[i], 0); |
271 | 271 | ||
272 | priv->passive_no_rx = false; | 272 | priv->passive_no_rx = false; |
273 | priv->transport_queue_stop = 0; | 273 | priv->transport_queue_stop = 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 445bff690a63..4b190d98a1ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -126,7 +126,7 @@ enum iwl_led_mode { | |||
126 | 126 | ||
127 | /* TX queue watchdog timeouts in mSecs */ | 127 | /* TX queue watchdog timeouts in mSecs */ |
128 | #define IWL_WATCHDOG_DISABLED 0 | 128 | #define IWL_WATCHDOG_DISABLED 0 |
129 | #define IWL_DEF_WD_TIMEOUT 2000 | 129 | #define IWL_DEF_WD_TIMEOUT 2500 |
130 | #define IWL_LONG_WD_TIMEOUT 10000 | 130 | #define IWL_LONG_WD_TIMEOUT 10000 |
131 | #define IWL_MAX_WD_TIMEOUT 120000 | 131 | #define IWL_MAX_WD_TIMEOUT 120000 |
132 | 132 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index e7c0df6db6ee..996e7f16adf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -1367,7 +1367,6 @@ struct iwl_mod_params iwlwifi_mod_params = { | |||
1367 | .restart_fw = true, | 1367 | .restart_fw = true, |
1368 | .bt_coex_active = true, | 1368 | .bt_coex_active = true, |
1369 | .power_level = IWL_POWER_INDEX_1, | 1369 | .power_level = IWL_POWER_INDEX_1, |
1370 | .wd_disable = true, | ||
1371 | .d0i3_disable = true, | 1370 | .d0i3_disable = true, |
1372 | #ifndef CONFIG_IWLWIFI_UAPSD | 1371 | #ifndef CONFIG_IWLWIFI_UAPSD |
1373 | .uapsd_disable = true, | 1372 | .uapsd_disable = true, |
@@ -1478,10 +1477,6 @@ module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, | |||
1478 | MODULE_PARM_DESC(antenna_coupling, | 1477 | MODULE_PARM_DESC(antenna_coupling, |
1479 | "specify antenna coupling in dB (default: 0 dB)"); | 1478 | "specify antenna coupling in dB (default: 0 dB)"); |
1480 | 1479 | ||
1481 | module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); | ||
1482 | MODULE_PARM_DESC(wd_disable, | ||
1483 | "Disable stuck queue watchdog timer 0=system default, 1=disable (default: 1)"); | ||
1484 | |||
1485 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); | 1480 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); |
1486 | MODULE_PARM_DESC(nvm_file, "NVM file name"); | 1481 | MODULE_PARM_DESC(nvm_file, "NVM file name"); |
1487 | 1482 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index e4f589898eda..016d91384681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -270,6 +270,7 @@ enum iwl_ucode_tlv_api { | |||
270 | * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 | 270 | * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 |
271 | * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory | 271 | * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory |
272 | * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan. | 272 | * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan. |
273 | * @IWL_UCODE_TLV_CAPA_BEAMFORMER: supports Beamformer | ||
273 | * @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality | 274 | * @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality |
274 | * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current | 275 | * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current |
275 | * tx power value into TPC Report action frame and Link Measurement Report | 276 | * tx power value into TPC Report action frame and Link Measurement Report |
@@ -288,6 +289,7 @@ enum iwl_ucode_tlv_capa { | |||
288 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), | 289 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), |
289 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT = BIT(1), | 290 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT = BIT(1), |
290 | IWL_UCODE_TLV_CAPA_UMAC_SCAN = BIT(2), | 291 | IWL_UCODE_TLV_CAPA_UMAC_SCAN = BIT(2), |
292 | IWL_UCODE_TLV_CAPA_BEAMFORMER = BIT(3), | ||
291 | IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = BIT(6), | 293 | IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = BIT(6), |
292 | IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8), | 294 | IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8), |
293 | IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9), | 295 | IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9), |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 2a8cf4b2445c..e8eabd21ccfe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -96,7 +96,6 @@ enum iwl_disable_11n { | |||
96 | * use IWL_[DIS,EN]ABLE_HT_* constants | 96 | * use IWL_[DIS,EN]ABLE_HT_* constants |
97 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 | 97 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 |
98 | * @restart_fw: restart firmware, default = 1 | 98 | * @restart_fw: restart firmware, default = 1 |
99 | * @wd_disable: disable stuck queue check, default = 1 | ||
100 | * @bt_coex_active: enable bt coex, default = true | 99 | * @bt_coex_active: enable bt coex, default = true |
101 | * @led_mode: system default, default = 0 | 100 | * @led_mode: system default, default = 0 |
102 | * @power_save: enable power save, default = false | 101 | * @power_save: enable power save, default = false |
@@ -111,7 +110,6 @@ struct iwl_mod_params { | |||
111 | unsigned int disable_11n; | 110 | unsigned int disable_11n; |
112 | int amsdu_size_8K; | 111 | int amsdu_size_8K; |
113 | bool restart_fw; | 112 | bool restart_fw; |
114 | int wd_disable; | ||
115 | bool bt_coex_active; | 113 | bool bt_coex_active; |
116 | int led_mode; | 114 | int led_mode; |
117 | bool power_save; | 115 | bool power_save; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index b21fcf042b77..6221e4dfc64f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -252,6 +252,7 @@ | |||
252 | #define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) | 252 | #define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) |
253 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) | 253 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) |
254 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) | 254 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) |
255 | #define SCD_GP_CTRL_ENABLE_31_QUEUES BIT(0) | ||
255 | 256 | ||
256 | /* Context Data */ | 257 | /* Context Data */ |
257 | #define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) | 258 | #define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) |
@@ -285,32 +286,9 @@ | |||
285 | #define SCD_CHAINEXT_EN (SCD_BASE + 0x244) | 286 | #define SCD_CHAINEXT_EN (SCD_BASE + 0x244) |
286 | #define SCD_AGGR_SEL (SCD_BASE + 0x248) | 287 | #define SCD_AGGR_SEL (SCD_BASE + 0x248) |
287 | #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) | 288 | #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) |
289 | #define SCD_GP_CTRL (SCD_BASE + 0x1a8) | ||
288 | #define SCD_EN_CTRL (SCD_BASE + 0x254) | 290 | #define SCD_EN_CTRL (SCD_BASE + 0x254) |
289 | 291 | ||
290 | static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl) | ||
291 | { | ||
292 | if (chnl < 20) | ||
293 | return SCD_BASE + 0x18 + chnl * 4; | ||
294 | WARN_ON_ONCE(chnl >= 32); | ||
295 | return SCD_BASE + 0x284 + (chnl - 20) * 4; | ||
296 | } | ||
297 | |||
298 | static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl) | ||
299 | { | ||
300 | if (chnl < 20) | ||
301 | return SCD_BASE + 0x68 + chnl * 4; | ||
302 | WARN_ON_ONCE(chnl >= 32); | ||
303 | return SCD_BASE + 0x2B4 + (chnl - 20) * 4; | ||
304 | } | ||
305 | |||
306 | static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl) | ||
307 | { | ||
308 | if (chnl < 20) | ||
309 | return SCD_BASE + 0x10c + chnl * 4; | ||
310 | WARN_ON_ONCE(chnl >= 32); | ||
311 | return SCD_BASE + 0x384 + (chnl - 20) * 4; | ||
312 | } | ||
313 | |||
314 | /*********************** END TX SCHEDULER *************************************/ | 292 | /*********************** END TX SCHEDULER *************************************/ |
315 | 293 | ||
316 | /* Oscillator clock */ | 294 | /* Oscillator clock */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scd.h b/drivers/net/wireless/iwlwifi/iwl-scd.h index 6c622b21bba7..f2353ebf2666 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scd.h +++ b/drivers/net/wireless/iwlwifi/iwl-scd.h | |||
@@ -69,14 +69,6 @@ | |||
69 | #include "iwl-prph.h" | 69 | #include "iwl-prph.h" |
70 | 70 | ||
71 | 71 | ||
72 | static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans, | ||
73 | u16 txq_id) | ||
74 | { | ||
75 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), | ||
76 | (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
77 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
78 | } | ||
79 | |||
80 | static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans, | 72 | static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans, |
81 | u16 txq_id) | 73 | u16 txq_id) |
82 | { | 74 | { |
@@ -115,4 +107,37 @@ static inline void iwl_scd_enable_set_active(struct iwl_trans *trans, | |||
115 | { | 107 | { |
116 | iwl_write_prph(trans, SCD_EN_CTRL, value); | 108 | iwl_write_prph(trans, SCD_EN_CTRL, value); |
117 | } | 109 | } |
110 | |||
111 | static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl) | ||
112 | { | ||
113 | if (chnl < 20) | ||
114 | return SCD_BASE + 0x18 + chnl * 4; | ||
115 | WARN_ON_ONCE(chnl >= 32); | ||
116 | return SCD_BASE + 0x284 + (chnl - 20) * 4; | ||
117 | } | ||
118 | |||
119 | static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl) | ||
120 | { | ||
121 | if (chnl < 20) | ||
122 | return SCD_BASE + 0x68 + chnl * 4; | ||
123 | WARN_ON_ONCE(chnl >= 32); | ||
124 | return SCD_BASE + 0x2B4 + chnl * 4; | ||
125 | } | ||
126 | |||
127 | static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl) | ||
128 | { | ||
129 | if (chnl < 20) | ||
130 | return SCD_BASE + 0x10c + chnl * 4; | ||
131 | WARN_ON_ONCE(chnl >= 32); | ||
132 | return SCD_BASE + 0x334 + chnl * 4; | ||
133 | } | ||
134 | |||
135 | static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans, | ||
136 | u16 txq_id) | ||
137 | { | ||
138 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), | ||
139 | (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
140 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
141 | } | ||
142 | |||
118 | #endif | 143 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 84d8477432a2..a96bd8db6ceb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -368,6 +368,7 @@ enum iwl_trans_status { | |||
368 | * @cmd_queue: the index of the command queue. | 368 | * @cmd_queue: the index of the command queue. |
369 | * Must be set before start_fw. | 369 | * Must be set before start_fw. |
370 | * @cmd_fifo: the fifo for host commands | 370 | * @cmd_fifo: the fifo for host commands |
371 | * @cmd_q_wdg_timeout: the timeout of the watchdog timer for the command queue. | ||
371 | * @no_reclaim_cmds: Some devices erroneously don't set the | 372 | * @no_reclaim_cmds: Some devices erroneously don't set the |
372 | * SEQ_RX_FRAME bit on some notifications, this is the | 373 | * SEQ_RX_FRAME bit on some notifications, this is the |
373 | * list of such notifications to filter. Max length is | 374 | * list of such notifications to filter. Max length is |
@@ -378,8 +379,6 @@ enum iwl_trans_status { | |||
378 | * @bc_table_dword: set to true if the BC table expects the byte count to be | 379 | * @bc_table_dword: set to true if the BC table expects the byte count to be |
379 | * in DWORD (as opposed to bytes) | 380 | * in DWORD (as opposed to bytes) |
380 | * @scd_set_active: should the transport configure the SCD for HCMD queue | 381 | * @scd_set_active: should the transport configure the SCD for HCMD queue |
381 | * @queue_watchdog_timeout: time (in ms) after which queues | ||
382 | * are considered stuck and will trigger device restart | ||
383 | * @command_names: array of command names, must be 256 entries | 382 | * @command_names: array of command names, must be 256 entries |
384 | * (one for each command); for debugging only | 383 | * (one for each command); for debugging only |
385 | * @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until | 384 | * @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until |
@@ -390,13 +389,13 @@ struct iwl_trans_config { | |||
390 | 389 | ||
391 | u8 cmd_queue; | 390 | u8 cmd_queue; |
392 | u8 cmd_fifo; | 391 | u8 cmd_fifo; |
392 | unsigned int cmd_q_wdg_timeout; | ||
393 | const u8 *no_reclaim_cmds; | 393 | const u8 *no_reclaim_cmds; |
394 | unsigned int n_no_reclaim_cmds; | 394 | unsigned int n_no_reclaim_cmds; |
395 | 395 | ||
396 | bool rx_buf_size_8k; | 396 | bool rx_buf_size_8k; |
397 | bool bc_table_dword; | 397 | bool bc_table_dword; |
398 | bool scd_set_active; | 398 | bool scd_set_active; |
399 | unsigned int queue_watchdog_timeout; | ||
400 | const char *const *command_names; | 399 | const char *const *command_names; |
401 | 400 | ||
402 | u32 sdio_adma_addr; | 401 | u32 sdio_adma_addr; |
@@ -511,7 +510,8 @@ struct iwl_trans_ops { | |||
511 | struct sk_buff_head *skbs); | 510 | struct sk_buff_head *skbs); |
512 | 511 | ||
513 | void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, | 512 | void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, |
514 | const struct iwl_trans_txq_scd_cfg *cfg); | 513 | const struct iwl_trans_txq_scd_cfg *cfg, |
514 | unsigned int queue_wdg_timeout); | ||
515 | void (*txq_disable)(struct iwl_trans *trans, int queue, | 515 | void (*txq_disable)(struct iwl_trans *trans, int queue, |
516 | bool configure_scd); | 516 | bool configure_scd); |
517 | 517 | ||
@@ -829,19 +829,21 @@ static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue, | |||
829 | 829 | ||
830 | static inline void | 830 | static inline void |
831 | iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn, | 831 | iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn, |
832 | const struct iwl_trans_txq_scd_cfg *cfg) | 832 | const struct iwl_trans_txq_scd_cfg *cfg, |
833 | unsigned int queue_wdg_timeout) | ||
833 | { | 834 | { |
834 | might_sleep(); | 835 | might_sleep(); |
835 | 836 | ||
836 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) | 837 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) |
837 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); | 838 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
838 | 839 | ||
839 | trans->ops->txq_enable(trans, queue, ssn, cfg); | 840 | trans->ops->txq_enable(trans, queue, ssn, cfg, queue_wdg_timeout); |
840 | } | 841 | } |
841 | 842 | ||
842 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | 843 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, |
843 | int fifo, int sta_id, int tid, | 844 | int fifo, int sta_id, int tid, |
844 | int frame_limit, u16 ssn) | 845 | int frame_limit, u16 ssn, |
846 | unsigned int queue_wdg_timeout) | ||
845 | { | 847 | { |
846 | struct iwl_trans_txq_scd_cfg cfg = { | 848 | struct iwl_trans_txq_scd_cfg cfg = { |
847 | .fifo = fifo, | 849 | .fifo = fifo, |
@@ -851,11 +853,12 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | |||
851 | .aggregate = sta_id >= 0, | 853 | .aggregate = sta_id >= 0, |
852 | }; | 854 | }; |
853 | 855 | ||
854 | iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg); | 856 | iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg, queue_wdg_timeout); |
855 | } | 857 | } |
856 | 858 | ||
857 | static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | 859 | static inline |
858 | int fifo) | 860 | void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, int fifo, |
861 | unsigned int queue_wdg_timeout) | ||
859 | { | 862 | { |
860 | struct iwl_trans_txq_scd_cfg cfg = { | 863 | struct iwl_trans_txq_scd_cfg cfg = { |
861 | .fifo = fifo, | 864 | .fifo = fifo, |
@@ -865,16 +868,16 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | |||
865 | .aggregate = false, | 868 | .aggregate = false, |
866 | }; | 869 | }; |
867 | 870 | ||
868 | iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg); | 871 | iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg, queue_wdg_timeout); |
869 | } | 872 | } |
870 | 873 | ||
871 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, | 874 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, |
872 | u32 txq_bm) | 875 | u32 txqs) |
873 | { | 876 | { |
874 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | 877 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
875 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); | 878 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
876 | 879 | ||
877 | return trans->ops->wait_tx_queue_empty(trans, txq_bm); | 880 | return trans->ops->wait_tx_queue_empty(trans, txqs); |
878 | } | 881 | } |
879 | 882 | ||
880 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | 883 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index d91c46b0f888..beba375489f1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -99,7 +99,7 @@ | |||
99 | #define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 | 99 | #define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 |
100 | #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 | 100 | #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 |
101 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 | 101 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 |
102 | #define IWL_MVM_QUOTA_THRESHOLD 8 | 102 | #define IWL_MVM_QUOTA_THRESHOLD 4 |
103 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 | 103 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 |
104 | #define IWL_MVM_RS_DISABLE_P2P_MIMO 0 | 104 | #define IWL_MVM_RS_DISABLE_P2P_MIMO 0 |
105 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 | 105 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index 6a2a6b0ab91b..0f1ea80a55ef 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
@@ -308,16 +308,41 @@ enum { | |||
308 | #define LQ_FLAG_DYNAMIC_BW_POS 6 | 308 | #define LQ_FLAG_DYNAMIC_BW_POS 6 |
309 | #define LQ_FLAG_DYNAMIC_BW_MSK (1 << LQ_FLAG_DYNAMIC_BW_POS) | 309 | #define LQ_FLAG_DYNAMIC_BW_MSK (1 << LQ_FLAG_DYNAMIC_BW_POS) |
310 | 310 | ||
311 | /* Single Stream Parameters | 311 | /* Single Stream Tx Parameters (lq_cmd->ss_params) |
312 | * SS_STBC/BFER_ALLOWED - Controls whether STBC or Beamformer (BFER) is allowed | 312 | * Flags to control a smart FW decision about whether BFER/STBC/SISO will be |
313 | * ucode will make a smart decision between SISO/STBC/BFER | 313 | * used for single stream Tx. |
314 | * SS_PARAMS_VALID - if not set ignore the ss_params field. | ||
315 | */ | 314 | */ |
316 | enum { | 315 | |
317 | RS_SS_STBC_ALLOWED = BIT(0), | 316 | /* Bit 0-1: Max STBC streams allowed. Can be 0-3. |
318 | RS_SS_BFER_ALLOWED = BIT(1), | 317 | * (0) - No STBC allowed |
319 | RS_SS_PARAMS_VALID = BIT(31), | 318 | * (1) - 2x1 STBC allowed (HT/VHT) |
320 | }; | 319 | * (2) - 4x2 STBC allowed (HT/VHT) |
320 | * (3) - 3x2 STBC allowed (HT only) | ||
321 | * All our chips are at most 2 antennas so only (1) is valid for now. | ||
322 | */ | ||
323 | #define LQ_SS_STBC_ALLOWED_POS 0 | ||
324 | #define LQ_SS_STBC_ALLOWED_MSK (3 << LQ_SS_STBC_ALLOWED_MSK) | ||
325 | |||
326 | /* 2x1 STBC is allowed */ | ||
327 | #define LQ_SS_STBC_1SS_ALLOWED (1 << LQ_SS_STBC_ALLOWED_POS) | ||
328 | |||
329 | /* Bit 2: Beamformer (VHT only) is allowed */ | ||
330 | #define LQ_SS_BFER_ALLOWED_POS 2 | ||
331 | #define LQ_SS_BFER_ALLOWED (1 << LQ_SS_BFER_ALLOWED_POS) | ||
332 | |||
333 | /* Bit 3: Force BFER or STBC for testing | ||
334 | * If this is set: | ||
335 | * If BFER is allowed then force the ucode to choose BFER else | ||
336 | * If STBC is allowed then force the ucode to choose STBC over SISO | ||
337 | */ | ||
338 | #define LQ_SS_FORCE_POS 3 | ||
339 | #define LQ_SS_FORCE (1 << LQ_SS_FORCE_POS) | ||
340 | |||
341 | /* Bit 31: ss_params field is valid. Used for FW backward compatibility | ||
342 | * with other drivers which don't support the ss_params API yet | ||
343 | */ | ||
344 | #define LQ_SS_PARAMS_VALID_POS 31 | ||
345 | #define LQ_SS_PARAMS_VALID (1 << LQ_SS_PARAMS_VALID_POS) | ||
321 | 346 | ||
322 | /** | 347 | /** |
323 | * struct iwl_lq_cmd - link quality command | 348 | * struct iwl_lq_cmd - link quality command |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index a322a5e3d31b..ca38e9817374 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -575,7 +575,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
575 | goto error; | 575 | goto error; |
576 | } | 576 | } |
577 | 577 | ||
578 | iwl_mvm_get_shared_mem_conf(mvm); | 578 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 10) |
579 | iwl_mvm_get_shared_mem_conf(mvm); | ||
579 | 580 | ||
580 | ret = iwl_mvm_sf_update(mvm, NULL, false); | 581 | ret = iwl_mvm_sf_update(mvm, NULL, false); |
581 | if (ret) | 582 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 8bf78fa8ace0..7bdc6220743f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -462,6 +462,9 @@ exit_fail: | |||
462 | 462 | ||
463 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 463 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
464 | { | 464 | { |
465 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
466 | mvm->cfg->base_params->wd_timeout : | ||
467 | IWL_WATCHDOG_DISABLED; | ||
465 | u32 ac; | 468 | u32 ac; |
466 | int ret; | 469 | int ret; |
467 | 470 | ||
@@ -474,16 +477,17 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
474 | switch (vif->type) { | 477 | switch (vif->type) { |
475 | case NL80211_IFTYPE_P2P_DEVICE: | 478 | case NL80211_IFTYPE_P2P_DEVICE: |
476 | iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, | 479 | iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, |
477 | IWL_MVM_TX_FIFO_VO); | 480 | IWL_MVM_TX_FIFO_VO, wdg_timeout); |
478 | break; | 481 | break; |
479 | case NL80211_IFTYPE_AP: | 482 | case NL80211_IFTYPE_AP: |
480 | iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, | 483 | iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, |
481 | IWL_MVM_TX_FIFO_MCAST); | 484 | IWL_MVM_TX_FIFO_MCAST, wdg_timeout); |
482 | /* fall through */ | 485 | /* fall through */ |
483 | default: | 486 | default: |
484 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 487 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
485 | iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], | 488 | iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], |
486 | iwl_mvm_ac_to_tx_fifo[ac]); | 489 | iwl_mvm_ac_to_tx_fifo[ac], |
490 | wdg_timeout); | ||
487 | break; | 491 | break; |
488 | } | 492 | } |
489 | 493 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index cef6f3373542..1ff7ec08532d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -401,10 +401,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
401 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) | 401 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) |
402 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 402 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
403 | &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; | 403 | &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; |
404 | if (mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels) | 404 | if (mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels) { |
405 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 405 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
406 | &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; | 406 | &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; |
407 | 407 | ||
408 | if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BEAMFORMER) | ||
409 | hw->wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |= | ||
410 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; | ||
411 | } | ||
412 | |||
408 | hw->wiphy->hw_version = mvm->trans->hw_id; | 413 | hw->wiphy->hw_version = mvm->trans->hw_id; |
409 | 414 | ||
410 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) | 415 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) |
@@ -707,9 +712,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, | |||
707 | mvmvif->uploaded = false; | 712 | mvmvif->uploaded = false; |
708 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; | 713 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; |
709 | 714 | ||
710 | /* does this make sense at all? */ | ||
711 | mvmvif->color++; | ||
712 | |||
713 | spin_lock_bh(&mvm->time_event_lock); | 715 | spin_lock_bh(&mvm->time_event_lock); |
714 | iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); | 716 | iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); |
715 | spin_unlock_bh(&mvm->time_event_lock); | 717 | spin_unlock_bh(&mvm->time_event_lock); |
@@ -1353,7 +1355,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
1353 | 1355 | ||
1354 | ret = iwl_mvm_power_update_mac(mvm); | 1356 | ret = iwl_mvm_power_update_mac(mvm); |
1355 | if (ret) | 1357 | if (ret) |
1356 | goto out_release; | 1358 | goto out_remove_mac; |
1357 | 1359 | ||
1358 | /* beacon filtering */ | 1360 | /* beacon filtering */ |
1359 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); | 1361 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 979ac23522f2..6c69d0584f6c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -119,11 +119,13 @@ extern const struct ieee80211_ops iwl_mvm_hw_ops; | |||
119 | * We will register to mac80211 to have testmode working. The NIC must not | 119 | * We will register to mac80211 to have testmode working. The NIC must not |
120 | * be up'ed after the INIT fw asserted. This is useful to be able to use | 120 | * be up'ed after the INIT fw asserted. This is useful to be able to use |
121 | * proprietary tools over testmode to debug the INIT fw. | 121 | * proprietary tools over testmode to debug the INIT fw. |
122 | * @tfd_q_hang_detect: enabled the detection of hung transmit queues | ||
122 | * @power_scheme: CAM(Continuous Active Mode)-1, BPS(Balanced Power | 123 | * @power_scheme: CAM(Continuous Active Mode)-1, BPS(Balanced Power |
123 | * Save)-2(default), LP(Low Power)-3 | 124 | * Save)-2(default), LP(Low Power)-3 |
124 | */ | 125 | */ |
125 | struct iwl_mvm_mod_params { | 126 | struct iwl_mvm_mod_params { |
126 | bool init_dbg; | 127 | bool init_dbg; |
128 | bool tfd_q_hang_detect; | ||
127 | int power_scheme; | 129 | int power_scheme; |
128 | }; | 130 | }; |
129 | extern struct iwl_mvm_mod_params iwlmvm_mod_params; | 131 | extern struct iwl_mvm_mod_params iwlmvm_mod_params; |
@@ -532,6 +534,7 @@ enum { | |||
532 | enum iwl_mvm_tdls_cs_state { | 534 | enum iwl_mvm_tdls_cs_state { |
533 | IWL_MVM_TDLS_SW_IDLE = 0, | 535 | IWL_MVM_TDLS_SW_IDLE = 0, |
534 | IWL_MVM_TDLS_SW_REQ_SENT, | 536 | IWL_MVM_TDLS_SW_REQ_SENT, |
537 | IWL_MVM_TDLS_SW_RESP_RCVD, | ||
535 | IWL_MVM_TDLS_SW_REQ_RCVD, | 538 | IWL_MVM_TDLS_SW_REQ_RCVD, |
536 | IWL_MVM_TDLS_SW_ACTIVE, | 539 | IWL_MVM_TDLS_SW_ACTIVE, |
537 | }; | 540 | }; |
@@ -797,6 +800,9 @@ struct iwl_mvm { | |||
797 | struct cfg80211_chan_def chandef; | 800 | struct cfg80211_chan_def chandef; |
798 | struct sk_buff *skb; /* ch sw template */ | 801 | struct sk_buff *skb; /* ch sw template */ |
799 | u32 ch_sw_tm_ie; | 802 | u32 ch_sw_tm_ie; |
803 | |||
804 | /* timestamp of last ch-sw request sent (GP2 time) */ | ||
805 | u32 sent_timestamp; | ||
800 | } peer; | 806 | } peer; |
801 | } tdls_cs; | 807 | } tdls_cs; |
802 | 808 | ||
@@ -874,7 +880,7 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) | |||
874 | 880 | ||
875 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) | 881 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) |
876 | { | 882 | { |
877 | return mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_API_SCD_CFG; | 883 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SCD_CFG; |
878 | } | 884 | } |
879 | 885 | ||
880 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 886 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
@@ -1312,11 +1318,13 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) | |||
1312 | 1318 | ||
1313 | /* hw scheduler queue config */ | 1319 | /* hw scheduler queue config */ |
1314 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | 1320 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, |
1315 | const struct iwl_trans_txq_scd_cfg *cfg); | 1321 | const struct iwl_trans_txq_scd_cfg *cfg, |
1322 | unsigned int wdg_timeout); | ||
1316 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags); | 1323 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags); |
1317 | 1324 | ||
1318 | static inline void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, | 1325 | static inline |
1319 | u8 fifo) | 1326 | void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, |
1327 | u8 fifo, unsigned int wdg_timeout) | ||
1320 | { | 1328 | { |
1321 | struct iwl_trans_txq_scd_cfg cfg = { | 1329 | struct iwl_trans_txq_scd_cfg cfg = { |
1322 | .fifo = fifo, | 1330 | .fifo = fifo, |
@@ -1325,12 +1333,13 @@ static inline void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, | |||
1325 | .frame_limit = IWL_FRAME_LIMIT, | 1333 | .frame_limit = IWL_FRAME_LIMIT, |
1326 | }; | 1334 | }; |
1327 | 1335 | ||
1328 | iwl_mvm_enable_txq(mvm, queue, 0, &cfg); | 1336 | iwl_mvm_enable_txq(mvm, queue, 0, &cfg, wdg_timeout); |
1329 | } | 1337 | } |
1330 | 1338 | ||
1331 | static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, | 1339 | static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, |
1332 | int fifo, int sta_id, int tid, | 1340 | int fifo, int sta_id, int tid, |
1333 | int frame_limit, u16 ssn) | 1341 | int frame_limit, u16 ssn, |
1342 | unsigned int wdg_timeout) | ||
1334 | { | 1343 | { |
1335 | struct iwl_trans_txq_scd_cfg cfg = { | 1344 | struct iwl_trans_txq_scd_cfg cfg = { |
1336 | .fifo = fifo, | 1345 | .fifo = fifo, |
@@ -1340,7 +1349,7 @@ static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, | |||
1340 | .aggregate = true, | 1349 | .aggregate = true, |
1341 | }; | 1350 | }; |
1342 | 1351 | ||
1343 | iwl_mvm_enable_txq(mvm, queue, ssn, &cfg); | 1352 | iwl_mvm_enable_txq(mvm, queue, ssn, &cfg, wdg_timeout); |
1344 | } | 1353 | } |
1345 | 1354 | ||
1346 | /* Assoc status */ | 1355 | /* Assoc status */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 8bf8c2a29e5e..2dffc3600ed3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -93,6 +93,7 @@ static const struct iwl_op_mode_ops iwl_mvm_ops; | |||
93 | 93 | ||
94 | struct iwl_mvm_mod_params iwlmvm_mod_params = { | 94 | struct iwl_mvm_mod_params iwlmvm_mod_params = { |
95 | .power_scheme = IWL_POWER_SCHEME_BPS, | 95 | .power_scheme = IWL_POWER_SCHEME_BPS, |
96 | .tfd_q_hang_detect = true | ||
96 | /* rest of fields are 0 by default */ | 97 | /* rest of fields are 0 by default */ |
97 | }; | 98 | }; |
98 | 99 | ||
@@ -102,6 +103,10 @@ MODULE_PARM_DESC(init_dbg, | |||
102 | module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, S_IRUGO); | 103 | module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, S_IRUGO); |
103 | MODULE_PARM_DESC(power_scheme, | 104 | MODULE_PARM_DESC(power_scheme, |
104 | "power management scheme: 1-active, 2-balanced, 3-low power, default: 2"); | 105 | "power management scheme: 1-active, 2-balanced, 3-low power, default: 2"); |
106 | module_param_named(tfd_q_hang_detect, iwlmvm_mod_params.tfd_q_hang_detect, | ||
107 | bool, S_IRUGO); | ||
108 | MODULE_PARM_DESC(tfd_q_hang_detect, | ||
109 | "TFD queues hang detection (default: true"); | ||
105 | 110 | ||
106 | /* | 111 | /* |
107 | * module init and exit functions | 112 | * module init and exit functions |
@@ -473,11 +478,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
473 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE) | 478 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE) |
474 | trans_cfg.bc_table_dword = true; | 479 | trans_cfg.bc_table_dword = true; |
475 | 480 | ||
476 | if (!iwlwifi_mod_params.wd_disable) | ||
477 | trans_cfg.queue_watchdog_timeout = cfg->base_params->wd_timeout; | ||
478 | else | ||
479 | trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; | ||
480 | |||
481 | trans_cfg.command_names = iwl_mvm_cmd_strings; | 481 | trans_cfg.command_names = iwl_mvm_cmd_strings; |
482 | 482 | ||
483 | trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE; | 483 | trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE; |
@@ -486,6 +486,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
486 | 486 | ||
487 | trans_cfg.sdio_adma_addr = fw->sdio_adma_addr; | 487 | trans_cfg.sdio_adma_addr = fw->sdio_adma_addr; |
488 | 488 | ||
489 | /* Set a short watchdog for the command queue */ | ||
490 | trans_cfg.cmd_q_wdg_timeout = | ||
491 | iwlmvm_mod_params.tfd_q_hang_detect ? IWL_DEF_WD_TIMEOUT : | ||
492 | IWL_WATCHDOG_DISABLED; | ||
493 | |||
489 | snprintf(mvm->hw->wiphy->fw_version, | 494 | snprintf(mvm->hw->wiphy->fw_version, |
490 | sizeof(mvm->hw->wiphy->fw_version), | 495 | sizeof(mvm->hw->wiphy->fw_version), |
491 | "%s", fw->fw_version); | 496 | "%s", fw->fw_version); |
@@ -563,6 +568,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
563 | if (!mvm->scan_cmd) | 568 | if (!mvm->scan_cmd) |
564 | goto out_free; | 569 | goto out_free; |
565 | 570 | ||
571 | /* Set EBS as successful as long as not stated otherwise by the FW. */ | ||
572 | mvm->last_ebs_successful = true; | ||
573 | |||
566 | err = iwl_mvm_mac_setup_register(mvm); | 574 | err = iwl_mvm_mac_setup_register(mvm); |
567 | if (err) | 575 | if (err) |
568 | goto out_free; | 576 | goto out_free; |
@@ -870,7 +878,10 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) | |||
870 | * If WoWLAN fw asserted, don't restart either, mac80211 | 878 | * If WoWLAN fw asserted, don't restart either, mac80211 |
871 | * can't recover this since we're already half suspended. | 879 | * can't recover this since we're already half suspended. |
872 | */ | 880 | */ |
873 | if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | 881 | if (!mvm->restart_fw && fw_error) { |
882 | schedule_work(&mvm->fw_error_dump_wk); | ||
883 | } else if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, | ||
884 | &mvm->status)) { | ||
874 | struct iwl_mvm_reprobe *reprobe; | 885 | struct iwl_mvm_reprobe *reprobe; |
875 | 886 | ||
876 | IWL_ERR(mvm, | 887 | IWL_ERR(mvm, |
@@ -894,16 +905,13 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) | |||
894 | reprobe->dev = mvm->trans->dev; | 905 | reprobe->dev = mvm->trans->dev; |
895 | INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); | 906 | INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); |
896 | schedule_work(&reprobe->work); | 907 | schedule_work(&reprobe->work); |
897 | } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && | 908 | } else if (mvm->cur_ucode == IWL_UCODE_REGULAR) { |
898 | (!fw_error || mvm->restart_fw)) { | ||
899 | /* don't let the transport/FW power down */ | 909 | /* don't let the transport/FW power down */ |
900 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); | 910 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); |
901 | 911 | ||
902 | if (fw_error && mvm->restart_fw > 0) | 912 | if (fw_error && mvm->restart_fw > 0) |
903 | mvm->restart_fw--; | 913 | mvm->restart_fw--; |
904 | ieee80211_restart_hw(mvm->hw); | 914 | ieee80211_restart_hw(mvm->hw); |
905 | } else if (fw_error) { | ||
906 | schedule_work(&mvm->fw_error_dump_wk); | ||
907 | } | 915 | } |
908 | } | 916 | } |
909 | 917 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 9f32f2db95bd..194bd1f939ca 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "sta.h" | 39 | #include "sta.h" |
40 | #include "iwl-op-mode.h" | 40 | #include "iwl-op-mode.h" |
41 | #include "mvm.h" | 41 | #include "mvm.h" |
42 | #include "debugfs.h" | ||
42 | 43 | ||
43 | #define RS_NAME "iwl-mvm-rs" | 44 | #define RS_NAME "iwl-mvm-rs" |
44 | 45 | ||
@@ -1805,7 +1806,7 @@ static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1805 | /* Our chip supports Tx STBC and the peer is an HT/VHT STA which | 1806 | /* Our chip supports Tx STBC and the peer is an HT/VHT STA which |
1806 | * supports STBC of at least 1*SS | 1807 | * supports STBC of at least 1*SS |
1807 | */ | 1808 | */ |
1808 | if (!lq_sta->stbc) | 1809 | if (!lq_sta->stbc_capable) |
1809 | return false; | 1810 | return false; |
1810 | 1811 | ||
1811 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) | 1812 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) |
@@ -2626,7 +2627,7 @@ static void rs_ht_init(struct iwl_mvm *mvm, | |||
2626 | if (mvm->cfg->ht_params->stbc && | 2627 | if (mvm->cfg->ht_params->stbc && |
2627 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | 2628 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && |
2628 | (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) | 2629 | (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) |
2629 | lq_sta->stbc = true; | 2630 | lq_sta->stbc_capable = true; |
2630 | 2631 | ||
2631 | lq_sta->is_vht = false; | 2632 | lq_sta->is_vht = false; |
2632 | } | 2633 | } |
@@ -2645,7 +2646,12 @@ static void rs_vht_init(struct iwl_mvm *mvm, | |||
2645 | if (mvm->cfg->ht_params->stbc && | 2646 | if (mvm->cfg->ht_params->stbc && |
2646 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | 2647 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && |
2647 | (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)) | 2648 | (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)) |
2648 | lq_sta->stbc = true; | 2649 | lq_sta->stbc_capable = true; |
2650 | |||
2651 | if ((mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BEAMFORMER) && | ||
2652 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | ||
2653 | (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) | ||
2654 | lq_sta->bfer_capable = true; | ||
2649 | 2655 | ||
2650 | lq_sta->is_vht = true; | 2656 | lq_sta->is_vht = true; |
2651 | } | 2657 | } |
@@ -2778,11 +2784,12 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2778 | rs_get_max_rate_from_mask(lq_sta->active_mimo2_rate); | 2784 | rs_get_max_rate_from_mask(lq_sta->active_mimo2_rate); |
2779 | 2785 | ||
2780 | IWL_DEBUG_RATE(mvm, | 2786 | IWL_DEBUG_RATE(mvm, |
2781 | "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC=%d\n", | 2787 | "LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC=%d BFER=%d\n", |
2782 | lq_sta->active_legacy_rate, | 2788 | lq_sta->active_legacy_rate, |
2783 | lq_sta->active_siso_rate, | 2789 | lq_sta->active_siso_rate, |
2784 | lq_sta->active_mimo2_rate, | 2790 | lq_sta->active_mimo2_rate, |
2785 | lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc); | 2791 | lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc_capable, |
2792 | lq_sta->bfer_capable); | ||
2786 | IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", | 2793 | IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", |
2787 | lq_sta->max_legacy_rate_idx, | 2794 | lq_sta->max_legacy_rate_idx, |
2788 | lq_sta->max_siso_rate_idx, | 2795 | lq_sta->max_siso_rate_idx, |
@@ -2916,23 +2923,15 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
2916 | u8 valid_tx_ant = 0; | 2923 | u8 valid_tx_ant = 0; |
2917 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | 2924 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; |
2918 | bool toggle_ant = false; | 2925 | bool toggle_ant = false; |
2919 | bool stbc_allowed = false; | ||
2920 | 2926 | ||
2921 | memcpy(&rate, initial_rate, sizeof(rate)); | 2927 | memcpy(&rate, initial_rate, sizeof(rate)); |
2922 | 2928 | ||
2923 | valid_tx_ant = iwl_mvm_get_valid_tx_ant(mvm); | 2929 | valid_tx_ant = iwl_mvm_get_valid_tx_ant(mvm); |
2924 | 2930 | ||
2925 | stbc_allowed = rs_stbc_allow(mvm, sta, lq_sta); | 2931 | /* TODO: remove old API when min FW API hits 14 */ |
2926 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS) { | 2932 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS) && |
2927 | u32 ss_params = RS_SS_PARAMS_VALID; | 2933 | rs_stbc_allow(mvm, sta, lq_sta)) |
2928 | 2934 | rate.stbc = true; | |
2929 | if (stbc_allowed) | ||
2930 | ss_params |= RS_SS_STBC_ALLOWED; | ||
2931 | lq_cmd->ss_params = cpu_to_le32(ss_params); | ||
2932 | } else { | ||
2933 | /* TODO: remove old API when min FW API hits 14 */ | ||
2934 | rate.stbc = stbc_allowed; | ||
2935 | } | ||
2936 | 2935 | ||
2937 | if (is_siso(&rate)) { | 2936 | if (is_siso(&rate)) { |
2938 | num_rates = IWL_MVM_RS_INITIAL_SISO_NUM_RATES; | 2937 | num_rates = IWL_MVM_RS_INITIAL_SISO_NUM_RATES; |
@@ -2980,6 +2979,142 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
2980 | 2979 | ||
2981 | } | 2980 | } |
2982 | 2981 | ||
2982 | struct rs_bfer_active_iter_data { | ||
2983 | struct ieee80211_sta *exclude_sta; | ||
2984 | struct iwl_mvm_sta *bfer_mvmsta; | ||
2985 | }; | ||
2986 | |||
2987 | static void rs_bfer_active_iter(void *_data, | ||
2988 | struct ieee80211_sta *sta) | ||
2989 | { | ||
2990 | struct rs_bfer_active_iter_data *data = _data; | ||
2991 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
2992 | struct iwl_lq_cmd *lq_cmd = &mvmsta->lq_sta.lq; | ||
2993 | u32 ss_params = le32_to_cpu(lq_cmd->ss_params); | ||
2994 | |||
2995 | if (sta == data->exclude_sta) | ||
2996 | return; | ||
2997 | |||
2998 | /* The current sta has BFER allowed */ | ||
2999 | if (ss_params & LQ_SS_BFER_ALLOWED) { | ||
3000 | WARN_ON_ONCE(data->bfer_mvmsta != NULL); | ||
3001 | |||
3002 | data->bfer_mvmsta = mvmsta; | ||
3003 | } | ||
3004 | } | ||
3005 | |||
3006 | static int rs_bfer_priority(struct iwl_mvm_sta *sta) | ||
3007 | { | ||
3008 | int prio = -1; | ||
3009 | enum nl80211_iftype viftype = ieee80211_vif_type_p2p(sta->vif); | ||
3010 | |||
3011 | switch (viftype) { | ||
3012 | case NL80211_IFTYPE_AP: | ||
3013 | case NL80211_IFTYPE_P2P_GO: | ||
3014 | prio = 3; | ||
3015 | break; | ||
3016 | case NL80211_IFTYPE_P2P_CLIENT: | ||
3017 | prio = 2; | ||
3018 | break; | ||
3019 | case NL80211_IFTYPE_STATION: | ||
3020 | prio = 1; | ||
3021 | break; | ||
3022 | default: | ||
3023 | WARN_ONCE(true, "viftype %d sta_id %d", viftype, sta->sta_id); | ||
3024 | prio = -1; | ||
3025 | } | ||
3026 | |||
3027 | return prio; | ||
3028 | } | ||
3029 | |||
3030 | /* Returns >0 if sta1 has a higher BFER priority compared to sta2 */ | ||
3031 | static int rs_bfer_priority_cmp(struct iwl_mvm_sta *sta1, | ||
3032 | struct iwl_mvm_sta *sta2) | ||
3033 | { | ||
3034 | int prio1 = rs_bfer_priority(sta1); | ||
3035 | int prio2 = rs_bfer_priority(sta2); | ||
3036 | |||
3037 | if (prio1 > prio2) | ||
3038 | return 1; | ||
3039 | if (prio1 < prio2) | ||
3040 | return -1; | ||
3041 | return 0; | ||
3042 | } | ||
3043 | |||
3044 | static void rs_set_lq_ss_params(struct iwl_mvm *mvm, | ||
3045 | struct ieee80211_sta *sta, | ||
3046 | struct iwl_lq_sta *lq_sta, | ||
3047 | const struct rs_rate *initial_rate) | ||
3048 | { | ||
3049 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | ||
3050 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
3051 | struct rs_bfer_active_iter_data data = { | ||
3052 | .exclude_sta = sta, | ||
3053 | .bfer_mvmsta = NULL, | ||
3054 | }; | ||
3055 | struct iwl_mvm_sta *bfer_mvmsta = NULL; | ||
3056 | u32 ss_params = LQ_SS_PARAMS_VALID; | ||
3057 | |||
3058 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) | ||
3059 | goto out; | ||
3060 | |||
3061 | /* Check if forcing the decision is configured. | ||
3062 | * Note that SISO is forced by not allowing STBC or BFER | ||
3063 | */ | ||
3064 | if (lq_sta->ss_force == RS_SS_FORCE_STBC) | ||
3065 | ss_params |= (LQ_SS_STBC_1SS_ALLOWED | LQ_SS_FORCE); | ||
3066 | else if (lq_sta->ss_force == RS_SS_FORCE_BFER) | ||
3067 | ss_params |= (LQ_SS_BFER_ALLOWED | LQ_SS_FORCE); | ||
3068 | |||
3069 | if (lq_sta->ss_force != RS_SS_FORCE_NONE) { | ||
3070 | IWL_DEBUG_RATE(mvm, "Forcing single stream Tx decision %d\n", | ||
3071 | lq_sta->ss_force); | ||
3072 | goto out; | ||
3073 | } | ||
3074 | |||
3075 | if (lq_sta->stbc_capable) | ||
3076 | ss_params |= LQ_SS_STBC_1SS_ALLOWED; | ||
3077 | |||
3078 | if (!lq_sta->bfer_capable) | ||
3079 | goto out; | ||
3080 | |||
3081 | ieee80211_iterate_stations_atomic(mvm->hw, | ||
3082 | rs_bfer_active_iter, | ||
3083 | &data); | ||
3084 | bfer_mvmsta = data.bfer_mvmsta; | ||
3085 | |||
3086 | /* This code is safe as it doesn't run concurrently for different | ||
3087 | * stations. This is guaranteed by the fact that calls to | ||
3088 | * ieee80211_tx_status wouldn't run concurrently for a single HW. | ||
3089 | */ | ||
3090 | if (!bfer_mvmsta) { | ||
3091 | IWL_DEBUG_RATE(mvm, "No sta with BFER allowed found. Allow\n"); | ||
3092 | |||
3093 | ss_params |= LQ_SS_BFER_ALLOWED; | ||
3094 | goto out; | ||
3095 | } | ||
3096 | |||
3097 | IWL_DEBUG_RATE(mvm, "Found existing sta %d with BFER activated\n", | ||
3098 | bfer_mvmsta->sta_id); | ||
3099 | |||
3100 | /* Disallow BFER on another STA if active and we're a higher priority */ | ||
3101 | if (rs_bfer_priority_cmp(mvmsta, bfer_mvmsta) > 0) { | ||
3102 | struct iwl_lq_cmd *bfersta_lq_cmd = &bfer_mvmsta->lq_sta.lq; | ||
3103 | u32 bfersta_ss_params = le32_to_cpu(bfersta_lq_cmd->ss_params); | ||
3104 | |||
3105 | bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED; | ||
3106 | bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params); | ||
3107 | iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd, false); | ||
3108 | |||
3109 | ss_params |= LQ_SS_BFER_ALLOWED; | ||
3110 | IWL_DEBUG_RATE(mvm, | ||
3111 | "Lower priority BFER sta found (%d). Switch BFER\n", | ||
3112 | bfer_mvmsta->sta_id); | ||
3113 | } | ||
3114 | out: | ||
3115 | lq_cmd->ss_params = cpu_to_le32(ss_params); | ||
3116 | } | ||
3117 | |||
2983 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | 3118 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, |
2984 | struct ieee80211_sta *sta, | 3119 | struct ieee80211_sta *sta, |
2985 | struct iwl_lq_sta *lq_sta, | 3120 | struct iwl_lq_sta *lq_sta, |
@@ -3006,6 +3141,9 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | |||
3006 | 3141 | ||
3007 | rs_build_rates_table(mvm, sta, lq_sta, initial_rate); | 3142 | rs_build_rates_table(mvm, sta, lq_sta, initial_rate); |
3008 | 3143 | ||
3144 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS) | ||
3145 | rs_set_lq_ss_params(mvm, sta, lq_sta, initial_rate); | ||
3146 | |||
3009 | if (num_of_ant(initial_rate->ant) == 1) | 3147 | if (num_of_ant(initial_rate->ant) == 1) |
3010 | lq_cmd->single_stream_ant_msk = initial_rate->ant; | 3148 | lq_cmd->single_stream_ant_msk = initial_rate->ant; |
3011 | 3149 | ||
@@ -3379,9 +3517,73 @@ static const struct file_operations rs_sta_dbgfs_drv_tx_stats_ops = { | |||
3379 | .llseek = default_llseek, | 3517 | .llseek = default_llseek, |
3380 | }; | 3518 | }; |
3381 | 3519 | ||
3520 | static ssize_t iwl_dbgfs_ss_force_read(struct file *file, | ||
3521 | char __user *user_buf, | ||
3522 | size_t count, loff_t *ppos) | ||
3523 | { | ||
3524 | struct iwl_lq_sta *lq_sta = file->private_data; | ||
3525 | char buf[12]; | ||
3526 | int bufsz = sizeof(buf); | ||
3527 | int pos = 0; | ||
3528 | static const char * const ss_force_name[] = { | ||
3529 | [RS_SS_FORCE_NONE] = "none", | ||
3530 | [RS_SS_FORCE_STBC] = "stbc", | ||
3531 | [RS_SS_FORCE_BFER] = "bfer", | ||
3532 | [RS_SS_FORCE_SISO] = "siso", | ||
3533 | }; | ||
3534 | |||
3535 | pos += scnprintf(buf+pos, bufsz-pos, "%s\n", | ||
3536 | ss_force_name[lq_sta->ss_force]); | ||
3537 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
3538 | } | ||
3539 | |||
3540 | static ssize_t iwl_dbgfs_ss_force_write(struct iwl_lq_sta *lq_sta, char *buf, | ||
3541 | size_t count, loff_t *ppos) | ||
3542 | { | ||
3543 | struct iwl_mvm *mvm = lq_sta->pers.drv; | ||
3544 | int ret = 0; | ||
3545 | |||
3546 | if (!strncmp("none", buf, 4)) { | ||
3547 | lq_sta->ss_force = RS_SS_FORCE_NONE; | ||
3548 | } else if (!strncmp("siso", buf, 4)) { | ||
3549 | lq_sta->ss_force = RS_SS_FORCE_SISO; | ||
3550 | } else if (!strncmp("stbc", buf, 4)) { | ||
3551 | if (lq_sta->stbc_capable) { | ||
3552 | lq_sta->ss_force = RS_SS_FORCE_STBC; | ||
3553 | } else { | ||
3554 | IWL_ERR(mvm, | ||
3555 | "can't force STBC. peer doesn't support\n"); | ||
3556 | ret = -EINVAL; | ||
3557 | } | ||
3558 | } else if (!strncmp("bfer", buf, 4)) { | ||
3559 | if (lq_sta->bfer_capable) { | ||
3560 | lq_sta->ss_force = RS_SS_FORCE_BFER; | ||
3561 | } else { | ||
3562 | IWL_ERR(mvm, | ||
3563 | "can't force BFER. peer doesn't support\n"); | ||
3564 | ret = -EINVAL; | ||
3565 | } | ||
3566 | } else { | ||
3567 | IWL_ERR(mvm, "valid values none|siso|stbc|bfer\n"); | ||
3568 | ret = -EINVAL; | ||
3569 | } | ||
3570 | return ret ?: count; | ||
3571 | } | ||
3572 | |||
3573 | #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ | ||
3574 | _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_lq_sta) | ||
3575 | #define MVM_DEBUGFS_ADD_FILE_RS(name, parent, mode) do { \ | ||
3576 | if (!debugfs_create_file(#name, mode, parent, lq_sta, \ | ||
3577 | &iwl_dbgfs_##name##_ops)) \ | ||
3578 | goto err; \ | ||
3579 | } while (0) | ||
3580 | |||
3581 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32); | ||
3582 | |||
3382 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | 3583 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) |
3383 | { | 3584 | { |
3384 | struct iwl_lq_sta *lq_sta = mvm_sta; | 3585 | struct iwl_lq_sta *lq_sta = mvm_sta; |
3586 | |||
3385 | debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, | 3587 | debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, |
3386 | lq_sta, &rs_sta_dbgfs_scale_table_ops); | 3588 | lq_sta, &rs_sta_dbgfs_scale_table_ops); |
3387 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, | 3589 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, |
@@ -3392,6 +3594,11 @@ static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | |||
3392 | &lq_sta->tx_agg_tid_en); | 3594 | &lq_sta->tx_agg_tid_en); |
3393 | debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir, | 3595 | debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir, |
3394 | &lq_sta->pers.dbg_fixed_txp_reduction); | 3596 | &lq_sta->pers.dbg_fixed_txp_reduction); |
3597 | |||
3598 | MVM_DEBUGFS_ADD_FILE_RS(ss_force, dir, S_IRUSR | S_IWUSR); | ||
3599 | return; | ||
3600 | err: | ||
3601 | IWL_ERR((struct iwl_mvm *)mvm, "Can't create debugfs entity\n"); | ||
3395 | } | 3602 | } |
3396 | 3603 | ||
3397 | static void rs_remove_debugfs(void *mvm, void *mvm_sta) | 3604 | static void rs_remove_debugfs(void *mvm, void *mvm_sta) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index f8f5bf21cc38..dc4ef3dfafe1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -240,6 +240,13 @@ enum rs_column { | |||
240 | RS_COLUMN_INVALID, | 240 | RS_COLUMN_INVALID, |
241 | }; | 241 | }; |
242 | 242 | ||
243 | enum rs_ss_force_opt { | ||
244 | RS_SS_FORCE_NONE = 0, | ||
245 | RS_SS_FORCE_STBC, | ||
246 | RS_SS_FORCE_BFER, | ||
247 | RS_SS_FORCE_SISO, | ||
248 | }; | ||
249 | |||
243 | /* Packet stats per rate */ | 250 | /* Packet stats per rate */ |
244 | struct rs_rate_stats { | 251 | struct rs_rate_stats { |
245 | u64 success; | 252 | u64 success; |
@@ -293,7 +300,9 @@ struct iwl_lq_sta { | |||
293 | u64 last_tx; | 300 | u64 last_tx; |
294 | bool is_vht; | 301 | bool is_vht; |
295 | bool ldpc; /* LDPC Rx is supported by the STA */ | 302 | bool ldpc; /* LDPC Rx is supported by the STA */ |
296 | bool stbc; /* Tx STBC is supported by chip and Rx by STA */ | 303 | bool stbc_capable; /* Tx STBC is supported by chip and Rx by STA */ |
304 | bool bfer_capable; /* Remote supports beamformee and we BFer */ | ||
305 | |||
297 | enum ieee80211_band band; | 306 | enum ieee80211_band band; |
298 | 307 | ||
299 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 308 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
@@ -322,6 +331,9 @@ struct iwl_lq_sta { | |||
322 | /* tx power reduce for this sta */ | 331 | /* tx power reduce for this sta */ |
323 | int tpc_reduce; | 332 | int tpc_reduce; |
324 | 333 | ||
334 | /* force STBC/BFER/SISO for testing */ | ||
335 | enum rs_ss_force_opt ss_force; | ||
336 | |||
325 | /* persistent fields - initialized only once - keep last! */ | 337 | /* persistent fields - initialized only once - keep last! */ |
326 | struct lq_sta_pers { | 338 | struct lq_sta_pers { |
327 | #ifdef CONFIG_MAC80211_DEBUGFS | 339 | #ifdef CONFIG_MAC80211_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 3bd5f34d3285..7e9aa3cb3254 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -704,7 +704,8 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | |||
704 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 704 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
705 | } | 705 | } |
706 | 706 | ||
707 | mvm->last_ebs_successful = !ebs_status; | 707 | if (ebs_status) |
708 | mvm->last_ebs_successful = false; | ||
708 | 709 | ||
709 | return 0; | 710 | return 0; |
710 | } | 711 | } |
@@ -1682,10 +1683,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) | |||
1682 | 1683 | ||
1683 | band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; | 1684 | band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; |
1684 | for (i = 0; i < band->n_channels; i++, j++) | 1685 | for (i = 0; i < band->n_channels; i++, j++) |
1685 | scan_config->channel_array[j] = band->channels[i].center_freq; | 1686 | scan_config->channel_array[j] = band->channels[i].hw_value; |
1686 | band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; | 1687 | band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; |
1687 | for (i = 0; i < band->n_channels; i++, j++) | 1688 | for (i = 0; i < band->n_channels; i++, j++) |
1688 | scan_config->channel_array[j] = band->channels[i].center_freq; | 1689 | scan_config->channel_array[j] = band->channels[i].hw_value; |
1689 | 1690 | ||
1690 | cmd.data[0] = scan_config; | 1691 | cmd.data[0] = scan_config; |
1691 | cmd.len[0] = cmd_size; | 1692 | cmd.len[0] = cmd_size; |
@@ -1862,6 +1863,13 @@ int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1862 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL; | 1863 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL; |
1863 | 1864 | ||
1864 | cmd->general_flags = cpu_to_le32(flags); | 1865 | cmd->general_flags = cpu_to_le32(flags); |
1866 | |||
1867 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SINGLE_SCAN_EBS && | ||
1868 | mvm->last_ebs_successful) | ||
1869 | cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | | ||
1870 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
1871 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; | ||
1872 | |||
1865 | cmd->n_channels = req->req.n_channels; | 1873 | cmd->n_channels = req->req.n_channels; |
1866 | 1874 | ||
1867 | for (i = 0; i < req->req.n_ssids; i++) | 1875 | for (i = 0; i < req->req.n_ssids; i++) |
@@ -2025,7 +2033,9 @@ int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, | |||
2025 | notif->ebs_status == IWL_SCAN_EBS_SUCCESS ? | 2033 | notif->ebs_status == IWL_SCAN_EBS_SUCCESS ? |
2026 | "success" : "failed"); | 2034 | "success" : "failed"); |
2027 | 2035 | ||
2028 | mvm->last_ebs_successful = !notif->ebs_status; | 2036 | if (notif->ebs_status) |
2037 | mvm->last_ebs_successful = false; | ||
2038 | |||
2029 | mvm->scan_uid[uid_idx] = 0; | 2039 | mvm->scan_uid[uid_idx] = 0; |
2030 | 2040 | ||
2031 | if (!sched) { | 2041 | if (!sched) { |
@@ -2058,10 +2068,14 @@ static bool iwl_scan_umac_done_check(struct iwl_notif_wait_data *notif_wait, | |||
2058 | 2068 | ||
2059 | /* | 2069 | /* |
2060 | * Clear scan uid of scans that was aborted from above and completed | 2070 | * Clear scan uid of scans that was aborted from above and completed |
2061 | * in FW so the RX handler does nothing. | 2071 | * in FW so the RX handler does nothing. Set last_ebs_successful here if |
2072 | * needed. | ||
2062 | */ | 2073 | */ |
2063 | scan_done->mvm->scan_uid[uid_idx] = 0; | 2074 | scan_done->mvm->scan_uid[uid_idx] = 0; |
2064 | 2075 | ||
2076 | if (notif->ebs_status) | ||
2077 | scan_done->mvm->last_ebs_successful = false; | ||
2078 | |||
2065 | return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type); | 2079 | return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type); |
2066 | } | 2080 | } |
2067 | 2081 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 14a848480d04..5c23cddaaae3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -209,6 +209,9 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, | |||
209 | { | 209 | { |
210 | unsigned long used_hw_queues; | 210 | unsigned long used_hw_queues; |
211 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 211 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
212 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
213 | mvm->cfg->base_params->wd_timeout : | ||
214 | IWL_WATCHDOG_DISABLED; | ||
212 | u32 ac; | 215 | u32 ac; |
213 | 216 | ||
214 | lockdep_assert_held(&mvm->mutex); | 217 | lockdep_assert_held(&mvm->mutex); |
@@ -232,7 +235,7 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, | |||
232 | /* Found a place for all queues - enable them */ | 235 | /* Found a place for all queues - enable them */ |
233 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 236 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
234 | iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], | 237 | iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], |
235 | iwl_mvm_ac_to_tx_fifo[ac]); | 238 | iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout); |
236 | mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); | 239 | mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); |
237 | } | 240 | } |
238 | 241 | ||
@@ -626,13 +629,16 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
626 | 629 | ||
627 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) | 630 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) |
628 | { | 631 | { |
632 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
633 | mvm->cfg->base_params->wd_timeout : | ||
634 | IWL_WATCHDOG_DISABLED; | ||
629 | int ret; | 635 | int ret; |
630 | 636 | ||
631 | lockdep_assert_held(&mvm->mutex); | 637 | lockdep_assert_held(&mvm->mutex); |
632 | 638 | ||
633 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ | 639 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ |
634 | iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, | 640 | iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, |
635 | IWL_MVM_TX_FIFO_MCAST); | 641 | IWL_MVM_TX_FIFO_MCAST, wdg_timeout); |
636 | 642 | ||
637 | /* Allocate aux station and assign to it the aux queue */ | 643 | /* Allocate aux station and assign to it the aux queue */ |
638 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), | 644 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), |
@@ -965,6 +971,9 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
965 | { | 971 | { |
966 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 972 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
967 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | 973 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; |
974 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
975 | mvm->cfg->base_params->wd_timeout : | ||
976 | IWL_WATCHDOG_DISABLED; | ||
968 | int queue, fifo, ret; | 977 | int queue, fifo, ret; |
969 | u16 ssn; | 978 | u16 ssn; |
970 | 979 | ||
@@ -988,7 +997,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
988 | return -EIO; | 997 | return -EIO; |
989 | 998 | ||
990 | iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid, | 999 | iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid, |
991 | buf_size, ssn); | 1000 | buf_size, ssn, wdg_timeout); |
992 | 1001 | ||
993 | /* | 1002 | /* |
994 | * Even though in theory the peer could have different | 1003 | * Even though in theory the peer could have different |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tdls.c b/drivers/net/wireless/iwlwifi/mvm/tdls.c index c0e00bae5bd0..a87b506c8c72 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tdls.c +++ b/drivers/net/wireless/iwlwifi/mvm/tdls.c | |||
@@ -64,6 +64,8 @@ | |||
64 | #include <linux/etherdevice.h> | 64 | #include <linux/etherdevice.h> |
65 | #include "mvm.h" | 65 | #include "mvm.h" |
66 | #include "time-event.h" | 66 | #include "time-event.h" |
67 | #include "iwl-io.h" | ||
68 | #include "iwl-prph.h" | ||
67 | 69 | ||
68 | #define TU_TO_US(x) (x * 1024) | 70 | #define TU_TO_US(x) (x * 1024) |
69 | #define TU_TO_MS(x) (TU_TO_US(x) / 1000) | 71 | #define TU_TO_MS(x) (TU_TO_US(x) / 1000) |
@@ -228,6 +230,8 @@ iwl_mvm_tdls_cs_state_str(enum iwl_mvm_tdls_cs_state state) | |||
228 | return "IDLE"; | 230 | return "IDLE"; |
229 | case IWL_MVM_TDLS_SW_REQ_SENT: | 231 | case IWL_MVM_TDLS_SW_REQ_SENT: |
230 | return "REQ SENT"; | 232 | return "REQ SENT"; |
233 | case IWL_MVM_TDLS_SW_RESP_RCVD: | ||
234 | return "RESP RECEIVED"; | ||
231 | case IWL_MVM_TDLS_SW_REQ_RCVD: | 235 | case IWL_MVM_TDLS_SW_REQ_RCVD: |
232 | return "REQ RECEIVED"; | 236 | return "REQ RECEIVED"; |
233 | case IWL_MVM_TDLS_SW_ACTIVE: | 237 | case IWL_MVM_TDLS_SW_ACTIVE: |
@@ -248,6 +252,11 @@ static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm, | |||
248 | iwl_mvm_tdls_cs_state_str(state)); | 252 | iwl_mvm_tdls_cs_state_str(state)); |
249 | mvm->tdls_cs.state = state; | 253 | mvm->tdls_cs.state = state; |
250 | 254 | ||
255 | /* we only send requests to our switching peer - update sent time */ | ||
256 | if (state == IWL_MVM_TDLS_SW_REQ_SENT) | ||
257 | mvm->tdls_cs.peer.sent_timestamp = | ||
258 | iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); | ||
259 | |||
251 | if (state == IWL_MVM_TDLS_SW_IDLE) | 260 | if (state == IWL_MVM_TDLS_SW_IDLE) |
252 | mvm->tdls_cs.cur_sta_id = IWL_MVM_STATION_COUNT; | 261 | mvm->tdls_cs.cur_sta_id = IWL_MVM_STATION_COUNT; |
253 | } | 262 | } |
@@ -300,7 +309,7 @@ out: | |||
300 | static int | 309 | static int |
301 | iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, | 310 | iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, |
302 | enum iwl_tdls_channel_switch_type type, | 311 | enum iwl_tdls_channel_switch_type type, |
303 | const u8 *peer, bool peer_initiator) | 312 | const u8 *peer, bool peer_initiator, u32 timestamp) |
304 | { | 313 | { |
305 | bool same_peer = false; | 314 | bool same_peer = false; |
306 | int ret = 0; | 315 | int ret = 0; |
@@ -325,17 +334,30 @@ iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, | |||
325 | ret = -EINVAL; | 334 | ret = -EINVAL; |
326 | break; | 335 | break; |
327 | case IWL_MVM_TDLS_SW_REQ_SENT: | 336 | case IWL_MVM_TDLS_SW_REQ_SENT: |
337 | /* only allow requests from the same peer */ | ||
338 | if (!same_peer) | ||
339 | ret = -EBUSY; | ||
340 | else if (type == TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH && | ||
341 | !peer_initiator) | ||
342 | /* | ||
343 | * We received a ch-switch request while an outgoing | ||
344 | * one is pending. Allow it if the peer is the link | ||
345 | * initiator. | ||
346 | */ | ||
347 | ret = -EBUSY; | ||
348 | else if (type == TDLS_SEND_CHAN_SW_REQ) | ||
349 | /* wait for idle before sending another request */ | ||
350 | ret = -EBUSY; | ||
351 | else if (timestamp <= mvm->tdls_cs.peer.sent_timestamp) | ||
352 | /* we got a stale response - ignore it */ | ||
353 | ret = -EINVAL; | ||
354 | break; | ||
355 | case IWL_MVM_TDLS_SW_RESP_RCVD: | ||
328 | /* | 356 | /* |
329 | * We received a ch-switch request while an outgoing one is | 357 | * we are waiting for the FW to give an "active" notification, |
330 | * pending. Allow it to proceed if the other peer is the same | 358 | * so ignore requests in the meantime |
331 | * one we sent to, and we are not the link initiator. | ||
332 | */ | 359 | */ |
333 | if (type == TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH) { | 360 | ret = -EBUSY; |
334 | if (!same_peer) | ||
335 | ret = -EBUSY; | ||
336 | else if (!peer_initiator) /* we are the initiator */ | ||
337 | ret = -EBUSY; | ||
338 | } | ||
339 | break; | 361 | break; |
340 | case IWL_MVM_TDLS_SW_REQ_RCVD: | 362 | case IWL_MVM_TDLS_SW_REQ_RCVD: |
341 | /* as above, allow the link initiator to proceed */ | 363 | /* as above, allow the link initiator to proceed */ |
@@ -349,9 +371,12 @@ iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, | |||
349 | } | 371 | } |
350 | break; | 372 | break; |
351 | case IWL_MVM_TDLS_SW_ACTIVE: | 373 | case IWL_MVM_TDLS_SW_ACTIVE: |
352 | /* we don't allow initiations during active channel switch */ | 374 | /* |
353 | if (type == TDLS_SEND_CHAN_SW_REQ) | 375 | * the only valid request when active is a request to return |
354 | ret = -EINVAL; | 376 | * to the base channel by the current off-channel peer |
377 | */ | ||
378 | if (type != TDLS_MOVE_CH || !same_peer) | ||
379 | ret = -EBUSY; | ||
355 | break; | 380 | break; |
356 | } | 381 | } |
357 | 382 | ||
@@ -384,7 +409,8 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, | |||
384 | 409 | ||
385 | lockdep_assert_held(&mvm->mutex); | 410 | lockdep_assert_held(&mvm->mutex); |
386 | 411 | ||
387 | ret = iwl_mvm_tdls_check_action(mvm, type, peer, peer_initiator); | 412 | ret = iwl_mvm_tdls_check_action(mvm, type, peer, peer_initiator, |
413 | timestamp); | ||
388 | if (ret) | 414 | if (ret) |
389 | return ret; | 415 | return ret; |
390 | 416 | ||
@@ -473,6 +499,8 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, | |||
473 | type == TDLS_SEND_CHAN_SW_REQ ? | 499 | type == TDLS_SEND_CHAN_SW_REQ ? |
474 | IWL_MVM_TDLS_SW_REQ_SENT : | 500 | IWL_MVM_TDLS_SW_REQ_SENT : |
475 | IWL_MVM_TDLS_SW_REQ_RCVD); | 501 | IWL_MVM_TDLS_SW_REQ_RCVD); |
502 | } else { | ||
503 | iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_RESP_RCVD); | ||
476 | } | 504 | } |
477 | 505 | ||
478 | out: | 506 | out: |
@@ -657,12 +685,15 @@ iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw, | |||
657 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 685 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
658 | enum iwl_tdls_channel_switch_type type; | 686 | enum iwl_tdls_channel_switch_type type; |
659 | unsigned int delay; | 687 | unsigned int delay; |
688 | const char *action_str = | ||
689 | params->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ? | ||
690 | "REQ" : "RESP"; | ||
660 | 691 | ||
661 | mutex_lock(&mvm->mutex); | 692 | mutex_lock(&mvm->mutex); |
662 | 693 | ||
663 | IWL_DEBUG_TDLS(mvm, | 694 | IWL_DEBUG_TDLS(mvm, |
664 | "Received TDLS ch switch action %d from %pM status %d\n", | 695 | "Received TDLS ch switch action %s from %pM status %d\n", |
665 | params->action_code, params->sta->addr, params->status); | 696 | action_str, params->sta->addr, params->status); |
666 | 697 | ||
667 | /* | 698 | /* |
668 | * we got a non-zero status from a peer we were switching to - move to | 699 | * we got a non-zero status from a peer we were switching to - move to |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 4eb3cad31aa9..8decf9953229 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -432,7 +432,7 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) | |||
432 | mvm->status, table.valid); | 432 | mvm->status, table.valid); |
433 | } | 433 | } |
434 | 434 | ||
435 | IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, | 435 | IWL_ERR(mvm, "0x%08X | %s\n", table.error_id, |
436 | desc_lookup(table.error_id)); | 436 | desc_lookup(table.error_id)); |
437 | IWL_ERR(mvm, "0x%08X | umac branchlink1\n", table.blink1); | 437 | IWL_ERR(mvm, "0x%08X | umac branchlink1\n", table.blink1); |
438 | IWL_ERR(mvm, "0x%08X | umac branchlink2\n", table.blink2); | 438 | IWL_ERR(mvm, "0x%08X | umac branchlink2\n", table.blink2); |
@@ -531,7 +531,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
531 | } | 531 | } |
532 | 532 | ||
533 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | 533 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, |
534 | const struct iwl_trans_txq_scd_cfg *cfg) | 534 | const struct iwl_trans_txq_scd_cfg *cfg, |
535 | unsigned int wdg_timeout) | ||
535 | { | 536 | { |
536 | struct iwl_scd_txq_cfg_cmd cmd = { | 537 | struct iwl_scd_txq_cfg_cmd cmd = { |
537 | .scd_queue = queue, | 538 | .scd_queue = queue, |
@@ -545,11 +546,12 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | |||
545 | }; | 546 | }; |
546 | 547 | ||
547 | if (!iwl_mvm_is_scd_cfg_supported(mvm)) { | 548 | if (!iwl_mvm_is_scd_cfg_supported(mvm)) { |
548 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, cfg); | 549 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, cfg, |
550 | wdg_timeout); | ||
549 | return; | 551 | return; |
550 | } | 552 | } |
551 | 553 | ||
552 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL); | 554 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout); |
553 | WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), | 555 | WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), |
554 | "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); | 556 | "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); |
555 | } | 557 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index e5652d82d79e..cae0eb8835ce 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -216,6 +216,7 @@ struct iwl_pcie_txq_scratch_buf { | |||
216 | * @need_update: indicates need to update read/write index | 216 | * @need_update: indicates need to update read/write index |
217 | * @active: stores if queue is active | 217 | * @active: stores if queue is active |
218 | * @ampdu: true if this queue is an ampdu queue for an specific RA/TID | 218 | * @ampdu: true if this queue is an ampdu queue for an specific RA/TID |
219 | * @wd_timeout: queue watchdog timeout (jiffies) - per queue | ||
219 | * | 220 | * |
220 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame | 221 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame |
221 | * descriptors) and required locking structures. | 222 | * descriptors) and required locking structures. |
@@ -232,6 +233,7 @@ struct iwl_txq { | |||
232 | bool need_update; | 233 | bool need_update; |
233 | u8 active; | 234 | u8 active; |
234 | bool ampdu; | 235 | bool ampdu; |
236 | unsigned long wd_timeout; | ||
235 | }; | 237 | }; |
236 | 238 | ||
237 | static inline dma_addr_t | 239 | static inline dma_addr_t |
@@ -259,7 +261,6 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) | |||
259 | * @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) |
260 | * @scd_set_active: should the transport configure the SCD for HCMD queue | 262 | * @scd_set_active: should the transport configure the SCD for HCMD queue |
261 | * @rx_page_order: page order for receive buffer size | 263 | * @rx_page_order: page order for receive buffer size |
262 | * @wd_timeout: queue watchdog timeout (jiffies) | ||
263 | * @reg_lock: protect hw register access | 264 | * @reg_lock: protect hw register access |
264 | * @cmd_in_flight: true when we have a host command in flight | 265 | * @cmd_in_flight: true when we have a host command in flight |
265 | * @fw_mon_phys: physical address of the buffer for the firmware monitor | 266 | * @fw_mon_phys: physical address of the buffer for the firmware monitor |
@@ -302,6 +303,7 @@ struct iwl_trans_pcie { | |||
302 | 303 | ||
303 | u8 cmd_queue; | 304 | u8 cmd_queue; |
304 | u8 cmd_fifo; | 305 | u8 cmd_fifo; |
306 | unsigned int cmd_q_wdg_timeout; | ||
305 | u8 n_no_reclaim_cmds; | 307 | u8 n_no_reclaim_cmds; |
306 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; | 308 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; |
307 | 309 | ||
@@ -312,9 +314,6 @@ struct iwl_trans_pcie { | |||
312 | 314 | ||
313 | const char *const *command_names; | 315 | const char *const *command_names; |
314 | 316 | ||
315 | /* queue watchdog */ | ||
316 | unsigned long wd_timeout; | ||
317 | |||
318 | /*protect hw register */ | 317 | /*protect hw register */ |
319 | spinlock_t reg_lock; | 318 | spinlock_t reg_lock; |
320 | bool cmd_in_flight; | 319 | bool cmd_in_flight; |
@@ -373,7 +372,8 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr); | |||
373 | int iwl_pcie_tx_stop(struct iwl_trans *trans); | 372 | int iwl_pcie_tx_stop(struct iwl_trans *trans); |
374 | void iwl_pcie_tx_free(struct iwl_trans *trans); | 373 | void iwl_pcie_tx_free(struct iwl_trans *trans); |
375 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn, | 374 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn, |
376 | const struct iwl_trans_txq_scd_cfg *cfg); | 375 | const struct iwl_trans_txq_scd_cfg *cfg, |
376 | unsigned int wdg_timeout); | ||
377 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue, | 377 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue, |
378 | bool configure_scd); | 378 | bool configure_scd); |
379 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | 379 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 1ff87677c3d3..69935aa5a1b3 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #include "iwl-trans.h" | 75 | #include "iwl-trans.h" |
76 | #include "iwl-csr.h" | 76 | #include "iwl-csr.h" |
77 | #include "iwl-prph.h" | 77 | #include "iwl-prph.h" |
78 | #include "iwl-scd.h" | ||
78 | #include "iwl-agn-hw.h" | 79 | #include "iwl-agn-hw.h" |
79 | #include "iwl-fw-error-dump.h" | 80 | #include "iwl-fw-error-dump.h" |
80 | #include "internal.h" | 81 | #include "internal.h" |
@@ -1268,6 +1269,7 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
1268 | 1269 | ||
1269 | trans_pcie->cmd_queue = trans_cfg->cmd_queue; | 1270 | trans_pcie->cmd_queue = trans_cfg->cmd_queue; |
1270 | trans_pcie->cmd_fifo = trans_cfg->cmd_fifo; | 1271 | trans_pcie->cmd_fifo = trans_cfg->cmd_fifo; |
1272 | trans_pcie->cmd_q_wdg_timeout = trans_cfg->cmd_q_wdg_timeout; | ||
1271 | if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) | 1273 | if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) |
1272 | trans_pcie->n_no_reclaim_cmds = 0; | 1274 | trans_pcie->n_no_reclaim_cmds = 0; |
1273 | else | 1275 | else |
@@ -1282,9 +1284,6 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
1282 | else | 1284 | else |
1283 | trans_pcie->rx_page_order = get_order(4 * 1024); | 1285 | trans_pcie->rx_page_order = get_order(4 * 1024); |
1284 | 1286 | ||
1285 | trans_pcie->wd_timeout = | ||
1286 | msecs_to_jiffies(trans_cfg->queue_watchdog_timeout); | ||
1287 | |||
1288 | trans_pcie->command_names = trans_cfg->command_names; | 1287 | trans_pcie->command_names = trans_cfg->command_names; |
1289 | trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; | 1288 | trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; |
1290 | trans_pcie->scd_set_active = trans_cfg->scd_set_active; | 1289 | trans_pcie->scd_set_active = trans_cfg->scd_set_active; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index d40cd4a67d6e..af0bce736358 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -147,7 +147,6 @@ static void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, | |||
147 | static void iwl_pcie_txq_stuck_timer(unsigned long data) | 147 | static void iwl_pcie_txq_stuck_timer(unsigned long data) |
148 | { | 148 | { |
149 | struct iwl_txq *txq = (void *)data; | 149 | struct iwl_txq *txq = (void *)data; |
150 | struct iwl_queue *q = &txq->q; | ||
151 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; | 150 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; |
152 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); | 151 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); |
153 | u32 scd_sram_addr = trans_pcie->scd_base_addr + | 152 | u32 scd_sram_addr = trans_pcie->scd_base_addr + |
@@ -164,7 +163,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
164 | spin_unlock(&txq->lock); | 163 | spin_unlock(&txq->lock); |
165 | 164 | ||
166 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, | 165 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, |
167 | jiffies_to_msecs(trans_pcie->wd_timeout)); | 166 | jiffies_to_msecs(txq->wd_timeout)); |
168 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | 167 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", |
169 | txq->q.read_ptr, txq->q.write_ptr); | 168 | txq->q.read_ptr, txq->q.write_ptr); |
170 | 169 | ||
@@ -198,11 +197,6 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
198 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); | 197 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); |
199 | } | 198 | } |
200 | 199 | ||
201 | for (i = q->read_ptr; i != q->write_ptr; | ||
202 | i = iwl_queue_inc_wrap(i)) | ||
203 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | ||
204 | le32_to_cpu(txq->scratchbufs[i].scratch)); | ||
205 | |||
206 | iwl_force_nmi(trans); | 200 | iwl_force_nmi(trans); |
207 | } | 201 | } |
208 | 202 | ||
@@ -680,7 +674,8 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) | |||
680 | iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); | 674 | iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); |
681 | 675 | ||
682 | iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, | 676 | iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, |
683 | trans_pcie->cmd_fifo); | 677 | trans_pcie->cmd_fifo, |
678 | trans_pcie->cmd_q_wdg_timeout); | ||
684 | 679 | ||
685 | /* Activate all Tx DMA/FIFO channels */ | 680 | /* Activate all Tx DMA/FIFO channels */ |
686 | iwl_scd_activate_fifos(trans); | 681 | iwl_scd_activate_fifos(trans); |
@@ -722,7 +717,12 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) | |||
722 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, | 717 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, |
723 | trans_pcie->kw.dma >> 4); | 718 | trans_pcie->kw.dma >> 4); |
724 | 719 | ||
725 | iwl_pcie_tx_start(trans, trans_pcie->scd_base_addr); | 720 | /* |
721 | * Send 0 as the scd_base_addr since the device may have be reset | ||
722 | * while we were in WoWLAN in which case SCD_SRAM_BASE_ADDR will | ||
723 | * contain garbage. | ||
724 | */ | ||
725 | iwl_pcie_tx_start(trans, 0); | ||
726 | } | 726 | } |
727 | 727 | ||
728 | /* | 728 | /* |
@@ -898,6 +898,10 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) | |||
898 | } | 898 | } |
899 | } | 899 | } |
900 | 900 | ||
901 | if (trans->cfg->base_params->num_of_queues > 20) | ||
902 | iwl_set_bits_prph(trans, SCD_GP_CTRL, | ||
903 | SCD_GP_CTRL_ENABLE_31_QUEUES); | ||
904 | |||
901 | return 0; | 905 | return 0; |
902 | error: | 906 | error: |
903 | /*Upon error, free only if we allocated something */ | 907 | /*Upon error, free only if we allocated something */ |
@@ -906,10 +910,9 @@ error: | |||
906 | return ret; | 910 | return ret; |
907 | } | 911 | } |
908 | 912 | ||
909 | static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie, | 913 | static inline void iwl_pcie_txq_progress(struct iwl_txq *txq) |
910 | struct iwl_txq *txq) | ||
911 | { | 914 | { |
912 | if (!trans_pcie->wd_timeout) | 915 | if (!txq->wd_timeout) |
913 | return; | 916 | return; |
914 | 917 | ||
915 | /* | 918 | /* |
@@ -919,7 +922,7 @@ static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie, | |||
919 | if (txq->q.read_ptr == txq->q.write_ptr) | 922 | if (txq->q.read_ptr == txq->q.write_ptr) |
920 | del_timer(&txq->stuck_timer); | 923 | del_timer(&txq->stuck_timer); |
921 | else | 924 | else |
922 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | 925 | mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); |
923 | } | 926 | } |
924 | 927 | ||
925 | /* Frees buffers until index _not_ inclusive */ | 928 | /* Frees buffers until index _not_ inclusive */ |
@@ -981,7 +984,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
981 | iwl_pcie_txq_free_tfd(trans, txq); | 984 | iwl_pcie_txq_free_tfd(trans, txq); |
982 | } | 985 | } |
983 | 986 | ||
984 | iwl_pcie_txq_progress(trans_pcie, txq); | 987 | iwl_pcie_txq_progress(txq); |
985 | 988 | ||
986 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) | 989 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) |
987 | iwl_wake_queue(trans, txq); | 990 | iwl_wake_queue(trans, txq); |
@@ -1109,7 +1112,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
1109 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | 1112 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); |
1110 | } | 1113 | } |
1111 | 1114 | ||
1112 | iwl_pcie_txq_progress(trans_pcie, txq); | 1115 | iwl_pcie_txq_progress(txq); |
1113 | } | 1116 | } |
1114 | 1117 | ||
1115 | static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, | 1118 | static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, |
@@ -1142,14 +1145,18 @@ static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, | |||
1142 | #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) | 1145 | #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) |
1143 | 1146 | ||
1144 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | 1147 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, |
1145 | const struct iwl_trans_txq_scd_cfg *cfg) | 1148 | const struct iwl_trans_txq_scd_cfg *cfg, |
1149 | unsigned int wdg_timeout) | ||
1146 | { | 1150 | { |
1147 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1151 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1152 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | ||
1148 | int fifo = -1; | 1153 | int fifo = -1; |
1149 | 1154 | ||
1150 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) | 1155 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) |
1151 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); | 1156 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); |
1152 | 1157 | ||
1158 | txq->wd_timeout = msecs_to_jiffies(wdg_timeout); | ||
1159 | |||
1153 | if (cfg) { | 1160 | if (cfg) { |
1154 | fifo = cfg->fifo; | 1161 | fifo = cfg->fifo; |
1155 | 1162 | ||
@@ -1173,7 +1180,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
1173 | 1180 | ||
1174 | /* enable aggregations for the queue */ | 1181 | /* enable aggregations for the queue */ |
1175 | iwl_scd_txq_enable_agg(trans, txq_id); | 1182 | iwl_scd_txq_enable_agg(trans, txq_id); |
1176 | trans_pcie->txq[txq_id].ampdu = true; | 1183 | txq->ampdu = true; |
1177 | } else { | 1184 | } else { |
1178 | /* | 1185 | /* |
1179 | * disable aggregations for the queue, this will also | 1186 | * disable aggregations for the queue, this will also |
@@ -1182,14 +1189,14 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
1182 | */ | 1189 | */ |
1183 | iwl_scd_txq_disable_agg(trans, txq_id); | 1190 | iwl_scd_txq_disable_agg(trans, txq_id); |
1184 | 1191 | ||
1185 | ssn = trans_pcie->txq[txq_id].q.read_ptr; | 1192 | ssn = txq->q.read_ptr; |
1186 | } | 1193 | } |
1187 | } | 1194 | } |
1188 | 1195 | ||
1189 | /* Place first TFD at index corresponding to start sequence number. | 1196 | /* Place first TFD at index corresponding to start sequence number. |
1190 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | 1197 | * Assumes that ssn_idx is valid (!= 0xFFF) */ |
1191 | trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff); | 1198 | txq->q.read_ptr = (ssn & 0xff); |
1192 | trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff); | 1199 | txq->q.write_ptr = (ssn & 0xff); |
1193 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | 1200 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, |
1194 | (ssn & 0xff) | (txq_id << 8)); | 1201 | (ssn & 0xff) | (txq_id << 8)); |
1195 | 1202 | ||
@@ -1230,7 +1237,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
1230 | txq_id, ssn & 0xff); | 1237 | txq_id, ssn & 0xff); |
1231 | } | 1238 | } |
1232 | 1239 | ||
1233 | trans_pcie->txq[txq_id].active = true; | 1240 | txq->active = true; |
1234 | } | 1241 | } |
1235 | 1242 | ||
1236 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, | 1243 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, |
@@ -1495,8 +1502,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1495 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); | 1502 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); |
1496 | 1503 | ||
1497 | /* start timer if queue currently empty */ | 1504 | /* start timer if queue currently empty */ |
1498 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | 1505 | if (q->read_ptr == q->write_ptr && txq->wd_timeout) |
1499 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | 1506 | mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); |
1500 | 1507 | ||
1501 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); | 1508 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); |
1502 | ret = iwl_pcie_set_cmd_in_flight(trans, cmd); | 1509 | ret = iwl_pcie_set_cmd_in_flight(trans, cmd); |
@@ -1846,9 +1853,8 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1846 | 1853 | ||
1847 | /* start timer if queue currently empty */ | 1854 | /* start timer if queue currently empty */ |
1848 | if (q->read_ptr == q->write_ptr) { | 1855 | if (q->read_ptr == q->write_ptr) { |
1849 | if (txq->need_update && trans_pcie->wd_timeout) | 1856 | if (txq->wd_timeout) |
1850 | mod_timer(&txq->stuck_timer, | 1857 | mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); |
1851 | jiffies + trans_pcie->wd_timeout); | ||
1852 | IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id); | 1858 | IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id); |
1853 | iwl_trans_pcie_ref(trans); | 1859 | iwl_trans_pcie_ref(trans); |
1854 | } | 1860 | } |
diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c index 2668e83afbb6..3ab87a855122 100644 --- a/drivers/net/wireless/mwifiex/11h.c +++ b/drivers/net/wireless/mwifiex/11h.c | |||
@@ -21,6 +21,16 @@ | |||
21 | #include "fw.h" | 21 | #include "fw.h" |
22 | 22 | ||
23 | 23 | ||
24 | void mwifiex_init_11h_params(struct mwifiex_private *priv) | ||
25 | { | ||
26 | priv->state_11h.is_11h_enabled = true; | ||
27 | priv->state_11h.is_11h_active = false; | ||
28 | } | ||
29 | |||
30 | inline int mwifiex_is_11h_active(struct mwifiex_private *priv) | ||
31 | { | ||
32 | return priv->state_11h.is_11h_active; | ||
33 | } | ||
24 | /* This function appends 11h info to a buffer while joining an | 34 | /* This function appends 11h info to a buffer while joining an |
25 | * infrastructure BSS | 35 | * infrastructure BSS |
26 | */ | 36 | */ |
@@ -39,7 +49,7 @@ mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer, | |||
39 | return; | 49 | return; |
40 | 50 | ||
41 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); | 51 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); |
42 | sband = priv->wdev->wiphy->bands[radio_type]; | 52 | sband = priv->wdev.wiphy->bands[radio_type]; |
43 | 53 | ||
44 | cap = (struct mwifiex_ie_types_pwr_capability *)*buffer; | 54 | cap = (struct mwifiex_ie_types_pwr_capability *)*buffer; |
45 | cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY); | 55 | cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY); |
@@ -69,10 +79,14 @@ mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer, | |||
69 | } | 79 | } |
70 | 80 | ||
71 | /* Enable or disable the 11h extensions in the firmware */ | 81 | /* Enable or disable the 11h extensions in the firmware */ |
72 | static int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag) | 82 | int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag) |
73 | { | 83 | { |
74 | u32 enable = flag; | 84 | u32 enable = flag; |
75 | 85 | ||
86 | /* enable master mode radar detection on AP interface */ | ||
87 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && enable) | ||
88 | enable |= MWIFIEX_MASTER_RADAR_DET_MASK; | ||
89 | |||
76 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, | 90 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
77 | HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true); | 91 | HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true); |
78 | } | 92 | } |
@@ -91,11 +105,191 @@ void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, | |||
91 | * bit | 105 | * bit |
92 | */ | 106 | */ |
93 | mwifiex_11h_activate(priv, true); | 107 | mwifiex_11h_activate(priv, true); |
108 | priv->state_11h.is_11h_active = true; | ||
94 | bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT; | 109 | bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT; |
95 | mwifiex_11h_process_infra_join(priv, buffer, bss_desc); | 110 | mwifiex_11h_process_infra_join(priv, buffer, bss_desc); |
96 | } else { | 111 | } else { |
97 | /* Deactivate 11h functions in the firmware */ | 112 | /* Deactivate 11h functions in the firmware */ |
98 | mwifiex_11h_activate(priv, false); | 113 | mwifiex_11h_activate(priv, false); |
114 | priv->state_11h.is_11h_active = false; | ||
99 | bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT; | 115 | bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT; |
100 | } | 116 | } |
101 | } | 117 | } |
118 | |||
119 | /* This is DFS CAC work queue function. | ||
120 | * This delayed work emits CAC finished event for cfg80211 if | ||
121 | * CAC was started earlier. | ||
122 | */ | ||
123 | void mwifiex_dfs_cac_work_queue(struct work_struct *work) | ||
124 | { | ||
125 | struct cfg80211_chan_def chandef; | ||
126 | struct delayed_work *delayed_work = | ||
127 | container_of(work, struct delayed_work, work); | ||
128 | struct mwifiex_private *priv = | ||
129 | container_of(delayed_work, struct mwifiex_private, | ||
130 | dfs_cac_work); | ||
131 | |||
132 | if (WARN_ON(!priv)) | ||
133 | return; | ||
134 | |||
135 | chandef = priv->dfs_chandef; | ||
136 | if (priv->wdev.cac_started) { | ||
137 | dev_dbg(priv->adapter->dev, | ||
138 | "CAC timer finished; No radar detected\n"); | ||
139 | cfg80211_cac_event(priv->netdev, &chandef, | ||
140 | NL80211_RADAR_CAC_FINISHED, | ||
141 | GFP_KERNEL); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* This function prepares channel report request command to FW for | ||
146 | * starting radar detection. | ||
147 | */ | ||
148 | int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv, | ||
149 | struct host_cmd_ds_command *cmd, | ||
150 | void *data_buf) | ||
151 | { | ||
152 | struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req; | ||
153 | struct mwifiex_radar_params *radar_params = (void *)data_buf; | ||
154 | |||
155 | cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST); | ||
156 | cmd->size = cpu_to_le16(S_DS_GEN); | ||
157 | le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_chan_rpt_req)); | ||
158 | |||
159 | cr_req->chan_desc.start_freq = cpu_to_le16(MWIFIEX_A_BAND_START_FREQ); | ||
160 | cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value; | ||
161 | cr_req->chan_desc.chan_width = radar_params->chandef->width; | ||
162 | cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms); | ||
163 | |||
164 | dev_dbg(priv->adapter->dev, | ||
165 | "11h: issuing DFS Radar check for channel=%d\n", | ||
166 | radar_params->chandef->chan->hw_value); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | /* This function is to abort ongoing CAC upon stopping AP operations | ||
172 | * or during unload. | ||
173 | */ | ||
174 | void mwifiex_abort_cac(struct mwifiex_private *priv) | ||
175 | { | ||
176 | if (priv->wdev.cac_started) { | ||
177 | dev_dbg(priv->adapter->dev, | ||
178 | "Aborting delayed work for CAC.\n"); | ||
179 | cancel_delayed_work_sync(&priv->dfs_cac_work); | ||
180 | cfg80211_cac_event(priv->netdev, &priv->dfs_chandef, | ||
181 | NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* This function handles channel report event from FW during CAC period. | ||
186 | * If radar is detected during CAC, driver indicates the same to cfg80211 | ||
187 | * and also cancels ongoing delayed work. | ||
188 | */ | ||
189 | int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv, | ||
190 | struct sk_buff *skb) | ||
191 | { | ||
192 | struct host_cmd_ds_chan_rpt_event *rpt_event; | ||
193 | struct mwifiex_ie_types_chan_rpt_data *rpt; | ||
194 | u8 *evt_buf; | ||
195 | u16 event_len, tlv_len; | ||
196 | |||
197 | rpt_event = (void *)(skb->data + sizeof(u32)); | ||
198 | event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event)+ | ||
199 | sizeof(u32)); | ||
200 | |||
201 | if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) { | ||
202 | dev_err(priv->adapter->dev, "Error in channel report event\n"); | ||
203 | return -1; | ||
204 | } | ||
205 | |||
206 | evt_buf = (void *)&rpt_event->tlvbuf; | ||
207 | |||
208 | while (event_len >= sizeof(struct mwifiex_ie_types_header)) { | ||
209 | rpt = (void *)&rpt_event->tlvbuf; | ||
210 | tlv_len = le16_to_cpu(rpt->header.len); | ||
211 | |||
212 | switch (le16_to_cpu(rpt->header.type)) { | ||
213 | case TLV_TYPE_CHANRPT_11H_BASIC: | ||
214 | if (rpt->map.radar) { | ||
215 | dev_notice(priv->adapter->dev, | ||
216 | "RADAR Detected on channel %d!\n", | ||
217 | priv->dfs_chandef.chan->hw_value); | ||
218 | cancel_delayed_work_sync(&priv->dfs_cac_work); | ||
219 | cfg80211_cac_event(priv->netdev, | ||
220 | &priv->dfs_chandef, | ||
221 | NL80211_RADAR_DETECTED, | ||
222 | GFP_KERNEL); | ||
223 | } | ||
224 | break; | ||
225 | default: | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | evt_buf += (tlv_len + sizeof(rpt->header)); | ||
230 | event_len -= (tlv_len + sizeof(rpt->header)); | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | /* Handler for radar detected event from FW.*/ | ||
237 | int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | ||
238 | struct sk_buff *skb) | ||
239 | { | ||
240 | struct mwifiex_radar_det_event *rdr_event; | ||
241 | |||
242 | rdr_event = (void *)(skb->data + sizeof(u32)); | ||
243 | |||
244 | if (le32_to_cpu(rdr_event->passed)) { | ||
245 | dev_notice(priv->adapter->dev, | ||
246 | "radar detected; indicating kernel\n"); | ||
247 | cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef, | ||
248 | GFP_KERNEL); | ||
249 | dev_dbg(priv->adapter->dev, "regdomain: %d\n", | ||
250 | rdr_event->reg_domain); | ||
251 | dev_dbg(priv->adapter->dev, "radar detection type: %d\n", | ||
252 | rdr_event->det_type); | ||
253 | } else { | ||
254 | dev_dbg(priv->adapter->dev, "false radar detection event!\n"); | ||
255 | } | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | /* This is work queue function for channel switch handling. | ||
261 | * This function takes care of updating new channel definitin to | ||
262 | * bss config structure, restart AP and indicate channel switch success | ||
263 | * to cfg80211. | ||
264 | */ | ||
265 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work) | ||
266 | { | ||
267 | struct mwifiex_uap_bss_param *bss_cfg; | ||
268 | struct delayed_work *delayed_work = | ||
269 | container_of(work, struct delayed_work, work); | ||
270 | struct mwifiex_private *priv = | ||
271 | container_of(delayed_work, struct mwifiex_private, | ||
272 | dfs_chan_sw_work); | ||
273 | |||
274 | if (WARN_ON(!priv)) | ||
275 | return; | ||
276 | |||
277 | bss_cfg = &priv->bss_cfg; | ||
278 | if (!bss_cfg->beacon_period) { | ||
279 | dev_err(priv->adapter->dev, | ||
280 | "channel switch: AP already stopped\n"); | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | mwifiex_uap_set_channel(bss_cfg, priv->dfs_chandef); | ||
285 | |||
286 | if (mwifiex_config_start_uap(priv, bss_cfg)) { | ||
287 | dev_dbg(priv->adapter->dev, | ||
288 | "Failed to start AP after channel switch\n"); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | dev_notice(priv->adapter->dev, | ||
293 | "indicating channel switch completion to kernel\n"); | ||
294 | cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef); | ||
295 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index c5c83cf664d8..543148d27b01 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -39,7 +39,7 @@ int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, | |||
39 | { | 39 | { |
40 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info); | 40 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info); |
41 | struct ieee80211_supported_band *sband = | 41 | struct ieee80211_supported_band *sband = |
42 | priv->wdev->wiphy->bands[radio_type]; | 42 | priv->wdev.wiphy->bands[radio_type]; |
43 | 43 | ||
44 | if (WARN_ON_ONCE(!sband)) { | 44 | if (WARN_ON_ONCE(!sband)) { |
45 | dev_err(priv->adapter->dev, "Invalid radio type!\n"); | 45 | dev_err(priv->adapter->dev, "Invalid radio type!\n"); |
@@ -314,7 +314,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
314 | return ret_len; | 314 | return ret_len; |
315 | 315 | ||
316 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); | 316 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); |
317 | sband = priv->wdev->wiphy->bands[radio_type]; | 317 | sband = priv->wdev.wiphy->bands[radio_type]; |
318 | 318 | ||
319 | if (bss_desc->bcn_ht_cap) { | 319 | if (bss_desc->bcn_ht_cap) { |
320 | ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; | 320 | ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index c7ca5b734875..a2e8817b56d8 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, | |||
45 | skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); | 45 | skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); |
46 | 46 | ||
47 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | 47 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, |
48 | priv->wdev->iftype, 0, false); | 48 | priv->wdev.iftype, 0, false); |
49 | 49 | ||
50 | while (!skb_queue_empty(&list)) { | 50 | while (!skb_queue_empty(&list)) { |
51 | rx_skb = __skb_dequeue(&list); | 51 | rx_skb = __skb_dequeue(&list); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 7be1e9b83fd0..41c8e25df954 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -590,77 +590,62 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
590 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | 590 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
591 | struct mwifiex_private *priv; | 591 | struct mwifiex_private *priv; |
592 | struct mwifiex_uap_bss_param *bss_cfg; | 592 | struct mwifiex_uap_bss_param *bss_cfg; |
593 | int ret, bss_started, i; | 593 | int ret; |
594 | |||
595 | for (i = 0; i < adapter->priv_num; i++) { | ||
596 | priv = adapter->priv[i]; | ||
597 | |||
598 | switch (priv->bss_role) { | ||
599 | case MWIFIEX_BSS_ROLE_UAP: | ||
600 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), | ||
601 | GFP_KERNEL); | ||
602 | if (!bss_cfg) | ||
603 | return -ENOMEM; | ||
604 | |||
605 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
606 | |||
607 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) | ||
608 | bss_cfg->rts_threshold = wiphy->rts_threshold; | ||
609 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) | ||
610 | bss_cfg->frag_threshold = wiphy->frag_threshold; | ||
611 | if (changed & WIPHY_PARAM_RETRY_LONG) | ||
612 | bss_cfg->retry_limit = wiphy->retry_long; | ||
613 | |||
614 | bss_started = priv->bss_started; | ||
615 | |||
616 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
617 | HostCmd_ACT_GEN_SET, 0, | ||
618 | NULL, true); | ||
619 | if (ret) { | ||
620 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
621 | kfree(bss_cfg); | ||
622 | return ret; | ||
623 | } | ||
624 | 594 | ||
625 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | 595 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
626 | HostCmd_ACT_GEN_SET, | ||
627 | UAP_BSS_PARAMS_I, bss_cfg, | ||
628 | false); | ||
629 | 596 | ||
630 | kfree(bss_cfg); | 597 | switch (priv->bss_role) { |
598 | case MWIFIEX_BSS_ROLE_UAP: | ||
599 | if (priv->bss_started) { | ||
600 | dev_err(adapter->dev, | ||
601 | "cannot change wiphy params when bss started"); | ||
602 | return -EINVAL; | ||
603 | } | ||
631 | 604 | ||
632 | if (ret) { | 605 | bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL); |
633 | wiphy_err(wiphy, "Failed to set bss config\n"); | 606 | if (!bss_cfg) |
634 | return ret; | 607 | return -ENOMEM; |
635 | } | ||
636 | 608 | ||
637 | if (!bss_started) | 609 | mwifiex_set_sys_config_invalid_data(bss_cfg); |
638 | break; | ||
639 | 610 | ||
640 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, | 611 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) |
641 | HostCmd_ACT_GEN_SET, 0, | 612 | bss_cfg->rts_threshold = wiphy->rts_threshold; |
642 | NULL, false); | 613 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) |
643 | if (ret) { | 614 | bss_cfg->frag_threshold = wiphy->frag_threshold; |
644 | wiphy_err(wiphy, "Failed to start BSS\n"); | 615 | if (changed & WIPHY_PARAM_RETRY_LONG) |
645 | return ret; | 616 | bss_cfg->retry_limit = wiphy->retry_long; |
646 | } | 617 | |
618 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
619 | HostCmd_ACT_GEN_SET, | ||
620 | UAP_BSS_PARAMS_I, bss_cfg, | ||
621 | false); | ||
622 | |||
623 | kfree(bss_cfg); | ||
624 | if (ret) { | ||
625 | wiphy_err(wiphy, "Failed to set wiphy phy params\n"); | ||
626 | return ret; | ||
627 | } | ||
628 | break; | ||
647 | 629 | ||
648 | break; | ||
649 | case MWIFIEX_BSS_ROLE_STA: | 630 | case MWIFIEX_BSS_ROLE_STA: |
650 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 631 | if (priv->media_connected) { |
651 | ret = mwifiex_set_rts(priv, | 632 | dev_err(adapter->dev, |
652 | wiphy->rts_threshold); | 633 | "cannot change wiphy params when connected"); |
653 | if (ret) | 634 | return -EINVAL; |
654 | return ret; | 635 | } |
655 | } | 636 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { |
656 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { | 637 | ret = mwifiex_set_rts(priv, |
657 | ret = mwifiex_set_frag(priv, | 638 | wiphy->rts_threshold); |
658 | wiphy->frag_threshold); | 639 | if (ret) |
659 | if (ret) | 640 | return ret; |
660 | return ret; | 641 | } |
661 | } | 642 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { |
662 | break; | 643 | ret = mwifiex_set_frag(priv, |
644 | wiphy->frag_threshold); | ||
645 | if (ret) | ||
646 | return ret; | ||
663 | } | 647 | } |
648 | break; | ||
664 | } | 649 | } |
665 | 650 | ||
666 | return 0; | 651 | return 0; |
@@ -671,9 +656,6 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) | |||
671 | { | 656 | { |
672 | u16 mode = P2P_MODE_DISABLE; | 657 | u16 mode = P2P_MODE_DISABLE; |
673 | 658 | ||
674 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) | ||
675 | mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA); | ||
676 | |||
677 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, | 659 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, |
678 | HostCmd_ACT_GEN_SET, 0, &mode, true)) | 660 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
679 | return -1; | 661 | return -1; |
@@ -730,12 +712,249 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) | |||
730 | HostCmd_ACT_GEN_SET, 0, &mode, true)) | 712 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
731 | return -1; | 713 | return -1; |
732 | 714 | ||
733 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) | 715 | return 0; |
734 | mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_UAP); | 716 | } |
717 | |||
718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | ||
719 | { | ||
720 | priv->mgmt_frame_mask = 0; | ||
721 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, | ||
722 | HostCmd_ACT_GEN_SET, 0, | ||
723 | &priv->mgmt_frame_mask, false)) { | ||
724 | dev_warn(priv->adapter->dev, | ||
725 | "could not unregister mgmt frame rx\n"); | ||
726 | return -1; | ||
727 | } | ||
728 | |||
729 | mwifiex_deauthenticate(priv, NULL); | ||
730 | mwifiex_free_priv(priv); | ||
731 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
732 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
733 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
735 | 734 | ||
736 | return 0; | 735 | return 0; |
737 | } | 736 | } |
738 | 737 | ||
738 | static int | ||
739 | mwifiex_init_new_priv_params(struct mwifiex_private *priv, | ||
740 | struct net_device *dev, | ||
741 | enum nl80211_iftype type) | ||
742 | { | ||
743 | mwifiex_init_priv(priv); | ||
744 | |||
745 | priv->bss_mode = type; | ||
746 | priv->wdev.iftype = type; | ||
747 | |||
748 | mwifiex_init_priv_params(priv, priv->netdev); | ||
749 | priv->bss_started = 0; | ||
750 | |||
751 | switch (type) { | ||
752 | case NL80211_IFTYPE_STATION: | ||
753 | case NL80211_IFTYPE_ADHOC: | ||
754 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | ||
755 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; | ||
756 | break; | ||
757 | case NL80211_IFTYPE_P2P_CLIENT: | ||
758 | case NL80211_IFTYPE_P2P_GO: | ||
759 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | ||
760 | priv->bss_type = MWIFIEX_BSS_TYPE_P2P; | ||
761 | break; | ||
762 | case NL80211_IFTYPE_AP: | ||
763 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; | ||
764 | priv->bss_role = MWIFIEX_BSS_ROLE_UAP; | ||
765 | break; | ||
766 | default: | ||
767 | dev_err(priv->adapter->dev, | ||
768 | "%s: changing to %d not supported\n", | ||
769 | dev->name, type); | ||
770 | return -EOPNOTSUPP; | ||
771 | } | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static int | ||
777 | mwifiex_change_vif_to_p2p(struct net_device *dev, | ||
778 | enum nl80211_iftype curr_iftype, | ||
779 | enum nl80211_iftype type, u32 *flags, | ||
780 | struct vif_params *params) | ||
781 | { | ||
782 | struct mwifiex_private *priv; | ||
783 | struct mwifiex_adapter *adapter; | ||
784 | |||
785 | priv = mwifiex_netdev_get_priv(dev); | ||
786 | |||
787 | if (!priv) | ||
788 | return -1; | ||
789 | |||
790 | adapter = priv->adapter; | ||
791 | |||
792 | if (adapter->curr_iface_comb.p2p_intf == | ||
793 | adapter->iface_limit.p2p_intf) { | ||
794 | dev_err(adapter->dev, | ||
795 | "cannot create multiple P2P ifaces\n"); | ||
796 | return -1; | ||
797 | } | ||
798 | |||
799 | dev_dbg(priv->adapter->dev, "%s: changing role to p2p\n", dev->name); | ||
800 | |||
801 | if (mwifiex_deinit_priv_params(priv)) | ||
802 | return -1; | ||
803 | if (mwifiex_init_new_priv_params(priv, dev, type)) | ||
804 | return -1; | ||
805 | |||
806 | switch (type) { | ||
807 | case NL80211_IFTYPE_P2P_CLIENT: | ||
808 | if (mwifiex_cfg80211_init_p2p_client(priv)) | ||
809 | return -EFAULT; | ||
810 | break; | ||
811 | case NL80211_IFTYPE_P2P_GO: | ||
812 | if (mwifiex_cfg80211_init_p2p_go(priv)) | ||
813 | return -EFAULT; | ||
814 | break; | ||
815 | default: | ||
816 | dev_err(priv->adapter->dev, | ||
817 | "%s: changing to %d not supported\n", | ||
818 | dev->name, type); | ||
819 | return -EOPNOTSUPP; | ||
820 | } | ||
821 | |||
822 | if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
823 | HostCmd_ACT_GEN_SET, 0, NULL, true)) | ||
824 | return -1; | ||
825 | |||
826 | if (mwifiex_sta_init_cmd(priv, false, false)) | ||
827 | return -1; | ||
828 | |||
829 | switch (curr_iftype) { | ||
830 | case NL80211_IFTYPE_STATION: | ||
831 | case NL80211_IFTYPE_ADHOC: | ||
832 | adapter->curr_iface_comb.sta_intf--; | ||
833 | break; | ||
834 | case NL80211_IFTYPE_AP: | ||
835 | adapter->curr_iface_comb.uap_intf--; | ||
836 | break; | ||
837 | default: | ||
838 | break; | ||
839 | } | ||
840 | |||
841 | adapter->curr_iface_comb.p2p_intf++; | ||
842 | dev->ieee80211_ptr->iftype = type; | ||
843 | |||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | static int | ||
848 | mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, | ||
849 | enum nl80211_iftype curr_iftype, | ||
850 | enum nl80211_iftype type, u32 *flags, | ||
851 | struct vif_params *params) | ||
852 | { | ||
853 | struct mwifiex_private *priv; | ||
854 | struct mwifiex_adapter *adapter; | ||
855 | |||
856 | priv = mwifiex_netdev_get_priv(dev); | ||
857 | |||
858 | if (!priv) | ||
859 | return -1; | ||
860 | |||
861 | adapter = priv->adapter; | ||
862 | |||
863 | if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT && | ||
864 | curr_iftype != NL80211_IFTYPE_P2P_GO) && | ||
865 | (adapter->curr_iface_comb.sta_intf == | ||
866 | adapter->iface_limit.sta_intf)) { | ||
867 | dev_err(adapter->dev, | ||
868 | "cannot create multiple station/adhoc ifaces\n"); | ||
869 | return -1; | ||
870 | } | ||
871 | |||
872 | if (type == NL80211_IFTYPE_STATION) | ||
873 | dev_notice(adapter->dev, | ||
874 | "%s: changing role to station\n", dev->name); | ||
875 | else | ||
876 | dev_notice(adapter->dev, | ||
877 | "%s: changing role to adhoc\n", dev->name); | ||
878 | |||
879 | if (mwifiex_deinit_priv_params(priv)) | ||
880 | return -1; | ||
881 | if (mwifiex_init_new_priv_params(priv, dev, type)) | ||
882 | return -1; | ||
883 | if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
884 | HostCmd_ACT_GEN_SET, 0, NULL, true)) | ||
885 | return -1; | ||
886 | if (mwifiex_sta_init_cmd(priv, false, false)) | ||
887 | return -1; | ||
888 | |||
889 | switch (curr_iftype) { | ||
890 | case NL80211_IFTYPE_P2P_CLIENT: | ||
891 | case NL80211_IFTYPE_P2P_GO: | ||
892 | adapter->curr_iface_comb.p2p_intf--; | ||
893 | break; | ||
894 | case NL80211_IFTYPE_AP: | ||
895 | adapter->curr_iface_comb.uap_intf--; | ||
896 | break; | ||
897 | default: | ||
898 | break; | ||
899 | } | ||
900 | |||
901 | adapter->curr_iface_comb.sta_intf++; | ||
902 | dev->ieee80211_ptr->iftype = type; | ||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static int | ||
907 | mwifiex_change_vif_to_ap(struct net_device *dev, | ||
908 | enum nl80211_iftype curr_iftype, | ||
909 | enum nl80211_iftype type, u32 *flags, | ||
910 | struct vif_params *params) | ||
911 | { | ||
912 | struct mwifiex_private *priv; | ||
913 | struct mwifiex_adapter *adapter; | ||
914 | |||
915 | priv = mwifiex_netdev_get_priv(dev); | ||
916 | |||
917 | if (!priv) | ||
918 | return -1; | ||
919 | |||
920 | adapter = priv->adapter; | ||
921 | |||
922 | if (adapter->curr_iface_comb.uap_intf == | ||
923 | adapter->iface_limit.uap_intf) { | ||
924 | dev_err(adapter->dev, | ||
925 | "cannot create multiple AP ifaces\n"); | ||
926 | return -1; | ||
927 | } | ||
928 | |||
929 | dev_notice(adapter->dev, "%s: changing role to AP\n", dev->name); | ||
930 | |||
931 | if (mwifiex_deinit_priv_params(priv)) | ||
932 | return -1; | ||
933 | if (mwifiex_init_new_priv_params(priv, dev, type)) | ||
934 | return -1; | ||
935 | if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
936 | HostCmd_ACT_GEN_SET, 0, NULL, true)) | ||
937 | return -1; | ||
938 | if (mwifiex_sta_init_cmd(priv, false, false)) | ||
939 | return -1; | ||
940 | |||
941 | switch (curr_iftype) { | ||
942 | case NL80211_IFTYPE_P2P_CLIENT: | ||
943 | case NL80211_IFTYPE_P2P_GO: | ||
944 | adapter->curr_iface_comb.p2p_intf--; | ||
945 | break; | ||
946 | case NL80211_IFTYPE_STATION: | ||
947 | case NL80211_IFTYPE_ADHOC: | ||
948 | adapter->curr_iface_comb.sta_intf--; | ||
949 | break; | ||
950 | default: | ||
951 | break; | ||
952 | } | ||
953 | |||
954 | adapter->curr_iface_comb.uap_intf++; | ||
955 | dev->ieee80211_ptr->iftype = type; | ||
956 | return 0; | ||
957 | } | ||
739 | /* | 958 | /* |
740 | * CFG802.11 operation handler to change interface type. | 959 | * CFG802.11 operation handler to change interface type. |
741 | */ | 960 | */ |
@@ -745,19 +964,32 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
745 | enum nl80211_iftype type, u32 *flags, | 964 | enum nl80211_iftype type, u32 *flags, |
746 | struct vif_params *params) | 965 | struct vif_params *params) |
747 | { | 966 | { |
748 | int ret; | ||
749 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 967 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
968 | enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype; | ||
750 | 969 | ||
751 | switch (dev->ieee80211_ptr->iftype) { | 970 | switch (curr_iftype) { |
752 | case NL80211_IFTYPE_ADHOC: | 971 | case NL80211_IFTYPE_ADHOC: |
753 | switch (type) { | 972 | switch (type) { |
754 | case NL80211_IFTYPE_STATION: | 973 | case NL80211_IFTYPE_STATION: |
755 | break; | 974 | priv->bss_mode = type; |
975 | priv->sec_info.authentication_mode = | ||
976 | NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
977 | dev->ieee80211_ptr->iftype = type; | ||
978 | mwifiex_deauthenticate(priv, NULL); | ||
979 | return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
980 | HostCmd_ACT_GEN_SET, 0, NULL, | ||
981 | true); | ||
982 | case NL80211_IFTYPE_P2P_CLIENT: | ||
983 | case NL80211_IFTYPE_P2P_GO: | ||
984 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, | ||
985 | type, flags, params); | ||
986 | case NL80211_IFTYPE_AP: | ||
987 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, | ||
988 | flags, params); | ||
756 | case NL80211_IFTYPE_UNSPECIFIED: | 989 | case NL80211_IFTYPE_UNSPECIFIED: |
757 | wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); | 990 | wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); |
758 | case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ | 991 | case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ |
759 | return 0; | 992 | return 0; |
760 | case NL80211_IFTYPE_AP: | ||
761 | default: | 993 | default: |
762 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | 994 | wiphy_err(wiphy, "%s: changing to %d not supported\n", |
763 | dev->name, type); | 995 | dev->name, type); |
@@ -767,22 +999,25 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
767 | case NL80211_IFTYPE_STATION: | 999 | case NL80211_IFTYPE_STATION: |
768 | switch (type) { | 1000 | switch (type) { |
769 | case NL80211_IFTYPE_ADHOC: | 1001 | case NL80211_IFTYPE_ADHOC: |
770 | break; | 1002 | priv->bss_mode = type; |
771 | case NL80211_IFTYPE_P2P_CLIENT: | 1003 | priv->sec_info.authentication_mode = |
772 | if (mwifiex_cfg80211_init_p2p_client(priv)) | 1004 | NL80211_AUTHTYPE_OPEN_SYSTEM; |
773 | return -EFAULT; | ||
774 | dev->ieee80211_ptr->iftype = type; | 1005 | dev->ieee80211_ptr->iftype = type; |
775 | return 0; | 1006 | mwifiex_deauthenticate(priv, NULL); |
1007 | return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
1008 | HostCmd_ACT_GEN_SET, 0, NULL, | ||
1009 | true); | ||
1010 | case NL80211_IFTYPE_P2P_CLIENT: | ||
776 | case NL80211_IFTYPE_P2P_GO: | 1011 | case NL80211_IFTYPE_P2P_GO: |
777 | if (mwifiex_cfg80211_init_p2p_go(priv)) | 1012 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, |
778 | return -EFAULT; | 1013 | type, flags, params); |
779 | dev->ieee80211_ptr->iftype = type; | 1014 | case NL80211_IFTYPE_AP: |
780 | return 0; | 1015 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, |
1016 | flags, params); | ||
781 | case NL80211_IFTYPE_UNSPECIFIED: | 1017 | case NL80211_IFTYPE_UNSPECIFIED: |
782 | wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); | 1018 | wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); |
783 | case NL80211_IFTYPE_STATION: /* This shouldn't happen */ | 1019 | case NL80211_IFTYPE_STATION: /* This shouldn't happen */ |
784 | return 0; | 1020 | return 0; |
785 | case NL80211_IFTYPE_AP: | ||
786 | default: | 1021 | default: |
787 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | 1022 | wiphy_err(wiphy, "%s: changing to %d not supported\n", |
788 | dev->name, type); | 1023 | dev->name, type); |
@@ -791,12 +1026,20 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
791 | break; | 1026 | break; |
792 | case NL80211_IFTYPE_AP: | 1027 | case NL80211_IFTYPE_AP: |
793 | switch (type) { | 1028 | switch (type) { |
1029 | case NL80211_IFTYPE_ADHOC: | ||
1030 | case NL80211_IFTYPE_STATION: | ||
1031 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, | ||
1032 | type, flags, | ||
1033 | params); | ||
1034 | break; | ||
1035 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1036 | case NL80211_IFTYPE_P2P_GO: | ||
1037 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, | ||
1038 | type, flags, params); | ||
794 | case NL80211_IFTYPE_UNSPECIFIED: | 1039 | case NL80211_IFTYPE_UNSPECIFIED: |
795 | wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); | 1040 | wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); |
796 | case NL80211_IFTYPE_AP: /* This shouldn't happen */ | 1041 | case NL80211_IFTYPE_AP: /* This shouldn't happen */ |
797 | return 0; | 1042 | return 0; |
798 | case NL80211_IFTYPE_ADHOC: | ||
799 | case NL80211_IFTYPE_STATION: | ||
800 | default: | 1043 | default: |
801 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | 1044 | wiphy_err(wiphy, "%s: changing to %d not supported\n", |
802 | dev->name, type); | 1045 | dev->name, type); |
@@ -807,11 +1050,30 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
807 | case NL80211_IFTYPE_P2P_GO: | 1050 | case NL80211_IFTYPE_P2P_GO: |
808 | switch (type) { | 1051 | switch (type) { |
809 | case NL80211_IFTYPE_STATION: | 1052 | case NL80211_IFTYPE_STATION: |
810 | if (mwifiex_cfg80211_deinit_p2p(priv)) | 1053 | if (mwifiex_cfg80211_init_p2p_client(priv)) |
811 | return -EFAULT; | 1054 | return -EFAULT; |
812 | dev->ieee80211_ptr->iftype = type; | 1055 | dev->ieee80211_ptr->iftype = type; |
1056 | break; | ||
1057 | case NL80211_IFTYPE_ADHOC: | ||
1058 | if (mwifiex_cfg80211_deinit_p2p(priv)) | ||
1059 | return -EFAULT; | ||
1060 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, | ||
1061 | type, flags, | ||
1062 | params); | ||
1063 | break; | ||
1064 | case NL80211_IFTYPE_AP: | ||
1065 | if (mwifiex_cfg80211_deinit_p2p(priv)) | ||
1066 | return -EFAULT; | ||
1067 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, | ||
1068 | flags, params); | ||
1069 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1070 | wiphy_warn(wiphy, "%s: kept type as P2P\n", dev->name); | ||
1071 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1072 | case NL80211_IFTYPE_P2P_GO: | ||
813 | return 0; | 1073 | return 0; |
814 | default: | 1074 | default: |
1075 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
1076 | dev->name, type); | ||
815 | return -EOPNOTSUPP; | 1077 | return -EOPNOTSUPP; |
816 | } | 1078 | } |
817 | break; | 1079 | break; |
@@ -821,16 +1083,8 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
821 | return -EOPNOTSUPP; | 1083 | return -EOPNOTSUPP; |
822 | } | 1084 | } |
823 | 1085 | ||
824 | dev->ieee80211_ptr->iftype = type; | ||
825 | priv->bss_mode = type; | ||
826 | mwifiex_deauthenticate(priv, NULL); | ||
827 | |||
828 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
829 | 1086 | ||
830 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | 1087 | return 0; |
831 | HostCmd_ACT_GEN_SET, 0, NULL, true); | ||
832 | |||
833 | return ret; | ||
834 | } | 1088 | } |
835 | 1089 | ||
836 | static void | 1090 | static void |
@@ -1397,10 +1651,13 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1397 | { | 1651 | { |
1398 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1652 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
1399 | 1653 | ||
1654 | mwifiex_abort_cac(priv); | ||
1655 | |||
1400 | if (mwifiex_del_mgmt_ies(priv)) | 1656 | if (mwifiex_del_mgmt_ies(priv)) |
1401 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); | 1657 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); |
1402 | 1658 | ||
1403 | priv->ap_11n_enabled = 0; | 1659 | priv->ap_11n_enabled = 0; |
1660 | memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg)); | ||
1404 | 1661 | ||
1405 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | 1662 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, |
1406 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | 1663 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { |
@@ -1422,12 +1679,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1422 | { | 1679 | { |
1423 | struct mwifiex_uap_bss_param *bss_cfg; | 1680 | struct mwifiex_uap_bss_param *bss_cfg; |
1424 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1681 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
1425 | u8 config_bands = 0; | ||
1426 | 1682 | ||
1427 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) | 1683 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) |
1428 | return -1; | 1684 | return -1; |
1429 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) | ||
1430 | return -1; | ||
1431 | 1685 | ||
1432 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | 1686 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); |
1433 | if (!bss_cfg) | 1687 | if (!bss_cfg) |
@@ -1444,6 +1698,11 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1444 | memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); | 1698 | memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); |
1445 | bss_cfg->ssid.ssid_len = params->ssid_len; | 1699 | bss_cfg->ssid.ssid_len = params->ssid_len; |
1446 | } | 1700 | } |
1701 | if (params->inactivity_timeout > 0) { | ||
1702 | /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ | ||
1703 | bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout; | ||
1704 | bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; | ||
1705 | } | ||
1447 | 1706 | ||
1448 | switch (params->hidden_ssid) { | 1707 | switch (params->hidden_ssid) { |
1449 | case NL80211_HIDDEN_SSID_NOT_IN_USE: | 1708 | case NL80211_HIDDEN_SSID_NOT_IN_USE: |
@@ -1459,33 +1718,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1459 | return -EINVAL; | 1718 | return -EINVAL; |
1460 | } | 1719 | } |
1461 | 1720 | ||
1462 | bss_cfg->channel = ieee80211_frequency_to_channel( | 1721 | mwifiex_uap_set_channel(bss_cfg, params->chandef); |
1463 | params->chandef.chan->center_freq); | ||
1464 | |||
1465 | /* Set appropriate bands */ | ||
1466 | if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { | ||
1467 | bss_cfg->band_cfg = BAND_CONFIG_BG; | ||
1468 | config_bands = BAND_B | BAND_G; | ||
1469 | |||
1470 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
1471 | config_bands |= BAND_GN; | ||
1472 | } else { | ||
1473 | bss_cfg->band_cfg = BAND_CONFIG_A; | ||
1474 | config_bands = BAND_A; | ||
1475 | |||
1476 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
1477 | config_bands |= BAND_AN; | ||
1478 | |||
1479 | if (params->chandef.width > NL80211_CHAN_WIDTH_40) | ||
1480 | config_bands |= BAND_AAC; | ||
1481 | } | ||
1482 | |||
1483 | if (!((config_bands | priv->adapter->fw_bands) & | ||
1484 | ~priv->adapter->fw_bands)) | ||
1485 | priv->adapter->config_bands = config_bands; | ||
1486 | |||
1487 | mwifiex_set_uap_rates(bss_cfg, params); | 1722 | mwifiex_set_uap_rates(bss_cfg, params); |
1488 | mwifiex_send_domain_info_cmd_fw(wiphy); | ||
1489 | 1723 | ||
1490 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { | 1724 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { |
1491 | kfree(bss_cfg); | 1725 | kfree(bss_cfg); |
@@ -1508,45 +1742,29 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1508 | 1742 | ||
1509 | mwifiex_set_wmm_params(priv, bss_cfg, params); | 1743 | mwifiex_set_wmm_params(priv, bss_cfg, params); |
1510 | 1744 | ||
1511 | if (params->inactivity_timeout > 0) { | 1745 | if (mwifiex_is_11h_active(priv) && |
1512 | /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ | 1746 | !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef, |
1513 | bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout; | 1747 | priv->bss_mode)) { |
1514 | bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; | 1748 | dev_dbg(priv->adapter->dev, "Disable 11h extensions in FW\n"); |
1749 | if (mwifiex_11h_activate(priv, false)) { | ||
1750 | dev_err(priv->adapter->dev, | ||
1751 | "Failed to disable 11h extensions!!"); | ||
1752 | return -1; | ||
1753 | } | ||
1754 | priv->state_11h.is_11h_active = true; | ||
1515 | } | 1755 | } |
1516 | 1756 | ||
1517 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | 1757 | if (mwifiex_config_start_uap(priv, bss_cfg)) { |
1518 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | 1758 | wiphy_err(wiphy, "Failed to start AP\n"); |
1519 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
1520 | kfree(bss_cfg); | 1759 | kfree(bss_cfg); |
1521 | return -1; | 1760 | return -1; |
1522 | } | 1761 | } |
1523 | 1762 | ||
1524 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | 1763 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) |
1525 | HostCmd_ACT_GEN_SET, | ||
1526 | UAP_BSS_PARAMS_I, bss_cfg, false)) { | ||
1527 | wiphy_err(wiphy, "Failed to set the SSID\n"); | ||
1528 | kfree(bss_cfg); | ||
1529 | return -1; | 1764 | return -1; |
1530 | } | ||
1531 | 1765 | ||
1766 | memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); | ||
1532 | kfree(bss_cfg); | 1767 | kfree(bss_cfg); |
1533 | |||
1534 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, | ||
1535 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { | ||
1536 | wiphy_err(wiphy, "Failed to start the BSS\n"); | ||
1537 | return -1; | ||
1538 | } | ||
1539 | |||
1540 | if (priv->sec_info.wep_enabled) | ||
1541 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; | ||
1542 | else | ||
1543 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | ||
1544 | |||
1545 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, | ||
1546 | HostCmd_ACT_GEN_SET, 0, | ||
1547 | &priv->curr_pkt_filter, true)) | ||
1548 | return -1; | ||
1549 | |||
1550 | return 0; | 1768 | return 0; |
1551 | } | 1769 | } |
1552 | 1770 | ||
@@ -1605,15 +1823,15 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
1605 | ie_len = ie_buf[1] + sizeof(struct ieee_types_header); | 1823 | ie_len = ie_buf[1] + sizeof(struct ieee_types_header); |
1606 | 1824 | ||
1607 | band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | 1825 | band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); |
1608 | chan = __ieee80211_get_channel(priv->wdev->wiphy, | 1826 | chan = __ieee80211_get_channel(priv->wdev.wiphy, |
1609 | ieee80211_channel_to_frequency(bss_info.bss_chan, | 1827 | ieee80211_channel_to_frequency(bss_info.bss_chan, |
1610 | band)); | 1828 | band)); |
1611 | 1829 | ||
1612 | bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, | 1830 | bss = cfg80211_inform_bss(priv->wdev.wiphy, chan, |
1613 | CFG80211_BSS_FTYPE_UNKNOWN, | 1831 | CFG80211_BSS_FTYPE_UNKNOWN, |
1614 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, | 1832 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, |
1615 | 0, ie_buf, ie_len, 0, GFP_KERNEL); | 1833 | 0, ie_buf, ie_len, 0, GFP_KERNEL); |
1616 | cfg80211_put_bss(priv->wdev->wiphy, bss); | 1834 | cfg80211_put_bss(priv->wdev.wiphy, bss); |
1617 | memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); | 1835 | memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); |
1618 | 1836 | ||
1619 | return 0; | 1837 | return 0; |
@@ -1734,12 +1952,12 @@ done: | |||
1734 | 1952 | ||
1735 | /* Find the BSS we want using available scan results */ | 1953 | /* Find the BSS we want using available scan results */ |
1736 | if (mode == NL80211_IFTYPE_ADHOC) | 1954 | if (mode == NL80211_IFTYPE_ADHOC) |
1737 | bss = cfg80211_get_bss(priv->wdev->wiphy, channel, | 1955 | bss = cfg80211_get_bss(priv->wdev.wiphy, channel, |
1738 | bssid, ssid, ssid_len, | 1956 | bssid, ssid, ssid_len, |
1739 | WLAN_CAPABILITY_IBSS, | 1957 | WLAN_CAPABILITY_IBSS, |
1740 | WLAN_CAPABILITY_IBSS); | 1958 | WLAN_CAPABILITY_IBSS); |
1741 | else | 1959 | else |
1742 | bss = cfg80211_get_bss(priv->wdev->wiphy, channel, | 1960 | bss = cfg80211_get_bss(priv->wdev.wiphy, channel, |
1743 | bssid, ssid, ssid_len, | 1961 | bssid, ssid, ssid_len, |
1744 | WLAN_CAPABILITY_ESS, | 1962 | WLAN_CAPABILITY_ESS, |
1745 | WLAN_CAPABILITY_ESS); | 1963 | WLAN_CAPABILITY_ESS); |
@@ -1796,7 +2014,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1796 | return -EINVAL; | 2014 | return -EINVAL; |
1797 | } | 2015 | } |
1798 | 2016 | ||
1799 | if (priv->wdev && priv->wdev->current_bss) { | 2017 | if (priv->wdev.current_bss) { |
1800 | wiphy_warn(wiphy, "%s: already connected\n", dev->name); | 2018 | wiphy_warn(wiphy, "%s: already connected\n", dev->name); |
1801 | return -EALREADY; | 2019 | return -EALREADY; |
1802 | } | 2020 | } |
@@ -1854,7 +2072,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1854 | static int mwifiex_set_ibss_params(struct mwifiex_private *priv, | 2072 | static int mwifiex_set_ibss_params(struct mwifiex_private *priv, |
1855 | struct cfg80211_ibss_params *params) | 2073 | struct cfg80211_ibss_params *params) |
1856 | { | 2074 | { |
1857 | struct wiphy *wiphy = priv->wdev->wiphy; | 2075 | struct wiphy *wiphy = priv->wdev.wiphy; |
1858 | struct mwifiex_adapter *adapter = priv->adapter; | 2076 | struct mwifiex_adapter *adapter = priv->adapter; |
1859 | int index = 0, i; | 2077 | int index = 0, i; |
1860 | u8 config_bands = 0; | 2078 | u8 config_bands = 0; |
@@ -2179,6 +2397,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
2179 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 2397 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
2180 | } | 2398 | } |
2181 | 2399 | ||
2400 | #define MWIFIEX_MAX_WQ_LEN 30 | ||
2182 | /* | 2401 | /* |
2183 | * create a new virtual interface with the given name | 2402 | * create a new virtual interface with the given name |
2184 | */ | 2403 | */ |
@@ -2192,7 +2411,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2192 | struct mwifiex_private *priv; | 2411 | struct mwifiex_private *priv; |
2193 | struct net_device *dev; | 2412 | struct net_device *dev; |
2194 | void *mdev_priv; | 2413 | void *mdev_priv; |
2195 | struct wireless_dev *wdev; | 2414 | char dfs_cac_str[MWIFIEX_MAX_WQ_LEN], dfs_chsw_str[MWIFIEX_MAX_WQ_LEN]; |
2196 | 2415 | ||
2197 | if (!adapter) | 2416 | if (!adapter) |
2198 | return ERR_PTR(-EFAULT); | 2417 | return ERR_PTR(-EFAULT); |
@@ -2201,20 +2420,22 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2201 | case NL80211_IFTYPE_UNSPECIFIED: | 2420 | case NL80211_IFTYPE_UNSPECIFIED: |
2202 | case NL80211_IFTYPE_STATION: | 2421 | case NL80211_IFTYPE_STATION: |
2203 | case NL80211_IFTYPE_ADHOC: | 2422 | case NL80211_IFTYPE_ADHOC: |
2204 | priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; | 2423 | if (adapter->curr_iface_comb.sta_intf == |
2205 | if (priv->bss_mode) { | 2424 | adapter->iface_limit.sta_intf) { |
2206 | wiphy_err(wiphy, | 2425 | wiphy_err(wiphy, |
2207 | "cannot create multiple sta/adhoc ifaces\n"); | 2426 | "cannot create multiple sta/adhoc ifaces\n"); |
2208 | return ERR_PTR(-EINVAL); | 2427 | return ERR_PTR(-EINVAL); |
2209 | } | 2428 | } |
2210 | 2429 | ||
2211 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 2430 | priv = mwifiex_get_unused_priv(adapter); |
2212 | if (!wdev) | 2431 | if (!priv) { |
2213 | return ERR_PTR(-ENOMEM); | 2432 | wiphy_err(wiphy, |
2433 | "could not get free private struct\n"); | ||
2434 | return ERR_PTR(-EFAULT); | ||
2435 | } | ||
2214 | 2436 | ||
2215 | wdev->wiphy = wiphy; | 2437 | priv->wdev.wiphy = wiphy; |
2216 | priv->wdev = wdev; | 2438 | priv->wdev.iftype = NL80211_IFTYPE_STATION; |
2217 | wdev->iftype = NL80211_IFTYPE_STATION; | ||
2218 | 2439 | ||
2219 | if (type == NL80211_IFTYPE_UNSPECIFIED) | 2440 | if (type == NL80211_IFTYPE_UNSPECIFIED) |
2220 | priv->bss_mode = NL80211_IFTYPE_STATION; | 2441 | priv->bss_mode = NL80211_IFTYPE_STATION; |
@@ -2229,20 +2450,22 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2229 | 2450 | ||
2230 | break; | 2451 | break; |
2231 | case NL80211_IFTYPE_AP: | 2452 | case NL80211_IFTYPE_AP: |
2232 | priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP]; | 2453 | if (adapter->curr_iface_comb.uap_intf == |
2233 | 2454 | adapter->iface_limit.uap_intf) { | |
2234 | if (priv->bss_mode) { | 2455 | wiphy_err(wiphy, |
2235 | wiphy_err(wiphy, "Can't create multiple AP interfaces"); | 2456 | "cannot create multiple AP ifaces\n"); |
2236 | return ERR_PTR(-EINVAL); | 2457 | return ERR_PTR(-EINVAL); |
2237 | } | 2458 | } |
2238 | 2459 | ||
2239 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 2460 | priv = mwifiex_get_unused_priv(adapter); |
2240 | if (!wdev) | 2461 | if (!priv) { |
2241 | return ERR_PTR(-ENOMEM); | 2462 | wiphy_err(wiphy, |
2463 | "could not get free private struct\n"); | ||
2464 | return ERR_PTR(-EFAULT); | ||
2465 | } | ||
2242 | 2466 | ||
2243 | priv->wdev = wdev; | 2467 | priv->wdev.wiphy = wiphy; |
2244 | wdev->wiphy = wiphy; | 2468 | priv->wdev.iftype = NL80211_IFTYPE_AP; |
2245 | wdev->iftype = NL80211_IFTYPE_AP; | ||
2246 | 2469 | ||
2247 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; | 2470 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; |
2248 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | 2471 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; |
@@ -2254,24 +2477,25 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2254 | 2477 | ||
2255 | break; | 2478 | break; |
2256 | case NL80211_IFTYPE_P2P_CLIENT: | 2479 | case NL80211_IFTYPE_P2P_CLIENT: |
2257 | priv = adapter->priv[MWIFIEX_BSS_TYPE_P2P]; | 2480 | if (adapter->curr_iface_comb.p2p_intf == |
2258 | 2481 | adapter->iface_limit.p2p_intf) { | |
2259 | if (priv->bss_mode) { | 2482 | wiphy_err(wiphy, |
2260 | wiphy_err(wiphy, "Can't create multiple P2P ifaces"); | 2483 | "cannot create multiple P2P ifaces\n"); |
2261 | return ERR_PTR(-EINVAL); | 2484 | return ERR_PTR(-EINVAL); |
2262 | } | 2485 | } |
2263 | 2486 | ||
2264 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 2487 | priv = mwifiex_get_unused_priv(adapter); |
2265 | if (!wdev) | 2488 | if (!priv) { |
2266 | return ERR_PTR(-ENOMEM); | 2489 | wiphy_err(wiphy, |
2267 | 2490 | "could not get free private struct\n"); | |
2268 | priv->wdev = wdev; | 2491 | return ERR_PTR(-EFAULT); |
2269 | wdev->wiphy = wiphy; | 2492 | } |
2270 | 2493 | ||
2494 | priv->wdev.wiphy = wiphy; | ||
2271 | /* At start-up, wpa_supplicant tries to change the interface | 2495 | /* At start-up, wpa_supplicant tries to change the interface |
2272 | * to NL80211_IFTYPE_STATION if it is not managed mode. | 2496 | * to NL80211_IFTYPE_STATION if it is not managed mode. |
2273 | */ | 2497 | */ |
2274 | wdev->iftype = NL80211_IFTYPE_P2P_CLIENT; | 2498 | priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; |
2275 | priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT; | 2499 | priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT; |
2276 | 2500 | ||
2277 | /* Setting bss_type to P2P tells firmware that this interface | 2501 | /* Setting bss_type to P2P tells firmware that this interface |
@@ -2287,8 +2511,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2287 | priv->bss_num = 0; | 2511 | priv->bss_num = 0; |
2288 | 2512 | ||
2289 | if (mwifiex_cfg80211_init_p2p_client(priv)) { | 2513 | if (mwifiex_cfg80211_init_p2p_client(priv)) { |
2290 | wdev = ERR_PTR(-EFAULT); | 2514 | memset(&priv->wdev, 0, sizeof(priv->wdev)); |
2291 | goto done; | 2515 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
2516 | return ERR_PTR(-EFAULT); | ||
2292 | } | 2517 | } |
2293 | 2518 | ||
2294 | break; | 2519 | break; |
@@ -2302,9 +2527,10 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2302 | IEEE80211_NUM_ACS, 1); | 2527 | IEEE80211_NUM_ACS, 1); |
2303 | if (!dev) { | 2528 | if (!dev) { |
2304 | wiphy_err(wiphy, "no memory available for netdevice\n"); | 2529 | wiphy_err(wiphy, "no memory available for netdevice\n"); |
2530 | memset(&priv->wdev, 0, sizeof(priv->wdev)); | ||
2531 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
2305 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 2532 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
2306 | wdev = ERR_PTR(-ENOMEM); | 2533 | return ERR_PTR(-ENOMEM); |
2307 | goto done; | ||
2308 | } | 2534 | } |
2309 | 2535 | ||
2310 | mwifiex_init_priv_params(priv, dev); | 2536 | mwifiex_init_priv_params(priv, dev); |
@@ -2324,7 +2550,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2324 | &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv); | 2550 | &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv); |
2325 | 2551 | ||
2326 | dev_net_set(dev, wiphy_net(wiphy)); | 2552 | dev_net_set(dev, wiphy_net(wiphy)); |
2327 | dev->ieee80211_ptr = priv->wdev; | 2553 | dev->ieee80211_ptr = &priv->wdev; |
2328 | dev->ieee80211_ptr->iftype = priv->bss_mode; | 2554 | dev->ieee80211_ptr->iftype = priv->bss_mode; |
2329 | memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); | 2555 | memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); |
2330 | SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); | 2556 | SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); |
@@ -2345,10 +2571,47 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2345 | free_netdev(dev); | 2571 | free_netdev(dev); |
2346 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 2572 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
2347 | priv->netdev = NULL; | 2573 | priv->netdev = NULL; |
2348 | wdev = ERR_PTR(-EFAULT); | 2574 | memset(&priv->wdev, 0, sizeof(priv->wdev)); |
2349 | goto done; | 2575 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
2576 | return ERR_PTR(-EFAULT); | ||
2577 | } | ||
2578 | |||
2579 | strcpy(dfs_cac_str, "MWIFIEX_DFS_CAC"); | ||
2580 | strcat(dfs_cac_str, name); | ||
2581 | priv->dfs_cac_workqueue = alloc_workqueue(dfs_cac_str, | ||
2582 | WQ_HIGHPRI | | ||
2583 | WQ_MEM_RECLAIM | | ||
2584 | WQ_UNBOUND, 1); | ||
2585 | if (!priv->dfs_cac_workqueue) { | ||
2586 | wiphy_err(wiphy, "cannot register virtual network device\n"); | ||
2587 | free_netdev(dev); | ||
2588 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
2589 | priv->netdev = NULL; | ||
2590 | memset(&priv->wdev, 0, sizeof(priv->wdev)); | ||
2591 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
2592 | return ERR_PTR(-ENOMEM); | ||
2593 | } | ||
2594 | |||
2595 | INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue); | ||
2596 | |||
2597 | strcpy(dfs_chsw_str, "MWIFIEX_DFS_CHSW"); | ||
2598 | strcat(dfs_chsw_str, name); | ||
2599 | priv->dfs_chan_sw_workqueue = alloc_workqueue(dfs_chsw_str, | ||
2600 | WQ_HIGHPRI | WQ_UNBOUND | | ||
2601 | WQ_MEM_RECLAIM, 1); | ||
2602 | if (!priv->dfs_chan_sw_workqueue) { | ||
2603 | wiphy_err(wiphy, "cannot register virtual network device\n"); | ||
2604 | free_netdev(dev); | ||
2605 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
2606 | priv->netdev = NULL; | ||
2607 | memset(&priv->wdev, 0, sizeof(priv->wdev)); | ||
2608 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
2609 | return ERR_PTR(-ENOMEM); | ||
2350 | } | 2610 | } |
2351 | 2611 | ||
2612 | INIT_DELAYED_WORK(&priv->dfs_chan_sw_work, | ||
2613 | mwifiex_dfs_chan_sw_work_queue); | ||
2614 | |||
2352 | sema_init(&priv->async_sem, 1); | 2615 | sema_init(&priv->async_sem, 1); |
2353 | 2616 | ||
2354 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); | 2617 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); |
@@ -2357,13 +2620,24 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2357 | mwifiex_dev_debugfs_init(priv); | 2620 | mwifiex_dev_debugfs_init(priv); |
2358 | #endif | 2621 | #endif |
2359 | 2622 | ||
2360 | done: | 2623 | switch (type) { |
2361 | if (IS_ERR(wdev)) { | 2624 | case NL80211_IFTYPE_UNSPECIFIED: |
2362 | kfree(priv->wdev); | 2625 | case NL80211_IFTYPE_STATION: |
2363 | priv->wdev = NULL; | 2626 | case NL80211_IFTYPE_ADHOC: |
2627 | adapter->curr_iface_comb.sta_intf++; | ||
2628 | break; | ||
2629 | case NL80211_IFTYPE_AP: | ||
2630 | adapter->curr_iface_comb.uap_intf++; | ||
2631 | break; | ||
2632 | case NL80211_IFTYPE_P2P_CLIENT: | ||
2633 | adapter->curr_iface_comb.p2p_intf++; | ||
2634 | break; | ||
2635 | default: | ||
2636 | wiphy_err(wiphy, "type not supported\n"); | ||
2637 | return ERR_PTR(-EINVAL); | ||
2364 | } | 2638 | } |
2365 | 2639 | ||
2366 | return wdev; | 2640 | return &priv->wdev; |
2367 | } | 2641 | } |
2368 | EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); | 2642 | EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); |
2369 | 2643 | ||
@@ -2373,12 +2647,13 @@ EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); | |||
2373 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | 2647 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) |
2374 | { | 2648 | { |
2375 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); | 2649 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); |
2650 | struct mwifiex_adapter *adapter = priv->adapter; | ||
2376 | 2651 | ||
2377 | #ifdef CONFIG_DEBUG_FS | 2652 | #ifdef CONFIG_DEBUG_FS |
2378 | mwifiex_dev_debugfs_remove(priv); | 2653 | mwifiex_dev_debugfs_remove(priv); |
2379 | #endif | 2654 | #endif |
2380 | 2655 | ||
2381 | mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); | 2656 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); |
2382 | 2657 | ||
2383 | if (netif_carrier_ok(priv->netdev)) | 2658 | if (netif_carrier_ok(priv->netdev)) |
2384 | netif_carrier_off(priv->netdev); | 2659 | netif_carrier_off(priv->netdev); |
@@ -2386,14 +2661,42 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2386 | if (wdev->netdev->reg_state == NETREG_REGISTERED) | 2661 | if (wdev->netdev->reg_state == NETREG_REGISTERED) |
2387 | unregister_netdevice(wdev->netdev); | 2662 | unregister_netdevice(wdev->netdev); |
2388 | 2663 | ||
2664 | if (priv->dfs_cac_workqueue) { | ||
2665 | flush_workqueue(priv->dfs_cac_workqueue); | ||
2666 | destroy_workqueue(priv->dfs_cac_workqueue); | ||
2667 | priv->dfs_cac_workqueue = NULL; | ||
2668 | } | ||
2669 | |||
2670 | if (priv->dfs_chan_sw_workqueue) { | ||
2671 | flush_workqueue(priv->dfs_chan_sw_workqueue); | ||
2672 | destroy_workqueue(priv->dfs_chan_sw_workqueue); | ||
2673 | priv->dfs_chan_sw_workqueue = NULL; | ||
2674 | } | ||
2389 | /* Clear the priv in adapter */ | 2675 | /* Clear the priv in adapter */ |
2390 | priv->netdev->ieee80211_ptr = NULL; | 2676 | priv->netdev->ieee80211_ptr = NULL; |
2391 | priv->netdev = NULL; | 2677 | priv->netdev = NULL; |
2392 | kfree(wdev); | 2678 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
2393 | priv->wdev = NULL; | ||
2394 | 2679 | ||
2395 | priv->media_connected = false; | 2680 | priv->media_connected = false; |
2396 | 2681 | ||
2682 | switch (priv->bss_mode) { | ||
2683 | case NL80211_IFTYPE_UNSPECIFIED: | ||
2684 | case NL80211_IFTYPE_STATION: | ||
2685 | case NL80211_IFTYPE_ADHOC: | ||
2686 | adapter->curr_iface_comb.sta_intf++; | ||
2687 | break; | ||
2688 | case NL80211_IFTYPE_AP: | ||
2689 | adapter->curr_iface_comb.uap_intf++; | ||
2690 | break; | ||
2691 | case NL80211_IFTYPE_P2P_CLIENT: | ||
2692 | case NL80211_IFTYPE_P2P_GO: | ||
2693 | adapter->curr_iface_comb.p2p_intf++; | ||
2694 | break; | ||
2695 | default: | ||
2696 | dev_err(adapter->dev, "del_virtual_intf: type not supported\n"); | ||
2697 | break; | ||
2698 | } | ||
2699 | |||
2397 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 2700 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
2398 | 2701 | ||
2399 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || | 2702 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || |
@@ -2848,6 +3151,102 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
2848 | } | 3151 | } |
2849 | 3152 | ||
2850 | static int | 3153 | static int |
3154 | mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | ||
3155 | struct cfg80211_csa_settings *params) | ||
3156 | { | ||
3157 | struct ieee_types_header *chsw_ie; | ||
3158 | struct ieee80211_channel_sw_ie *channel_sw; | ||
3159 | int chsw_msec; | ||
3160 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
3161 | |||
3162 | if (priv->adapter->scan_processing) { | ||
3163 | dev_err(priv->adapter->dev, | ||
3164 | "radar detection: scan in process...\n"); | ||
3165 | return -EBUSY; | ||
3166 | } | ||
3167 | |||
3168 | if (priv->wdev.cac_started) | ||
3169 | return -EBUSY; | ||
3170 | |||
3171 | if (cfg80211_chandef_identical(¶ms->chandef, | ||
3172 | &priv->dfs_chandef)) | ||
3173 | return -EINVAL; | ||
3174 | |||
3175 | chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH, | ||
3176 | params->beacon_csa.tail, | ||
3177 | params->beacon_csa.tail_len); | ||
3178 | if (!chsw_ie) { | ||
3179 | dev_err(priv->adapter->dev, | ||
3180 | "Could not parse channel switch announcement IE\n"); | ||
3181 | return -EINVAL; | ||
3182 | } | ||
3183 | |||
3184 | channel_sw = (void *)(chsw_ie + 1); | ||
3185 | if (channel_sw->mode) { | ||
3186 | if (netif_carrier_ok(priv->netdev)) | ||
3187 | netif_carrier_off(priv->netdev); | ||
3188 | mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); | ||
3189 | } | ||
3190 | |||
3191 | if (mwifiex_del_mgmt_ies(priv)) | ||
3192 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); | ||
3193 | |||
3194 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon_csa)) { | ||
3195 | wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__); | ||
3196 | return -EFAULT; | ||
3197 | } | ||
3198 | |||
3199 | memcpy(&priv->dfs_chandef, ¶ms->chandef, sizeof(priv->dfs_chandef)); | ||
3200 | memcpy(&priv->beacon_after, ¶ms->beacon_after, | ||
3201 | sizeof(priv->beacon_after)); | ||
3202 | |||
3203 | chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100); | ||
3204 | queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work, | ||
3205 | msecs_to_jiffies(chsw_msec)); | ||
3206 | return 0; | ||
3207 | } | ||
3208 | |||
3209 | static int | ||
3210 | mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, | ||
3211 | struct net_device *dev, | ||
3212 | struct cfg80211_chan_def *chandef, | ||
3213 | u32 cac_time_ms) | ||
3214 | { | ||
3215 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
3216 | struct mwifiex_radar_params radar_params; | ||
3217 | |||
3218 | if (priv->adapter->scan_processing) { | ||
3219 | dev_err(priv->adapter->dev, | ||
3220 | "radar detection: scan already in process...\n"); | ||
3221 | return -EBUSY; | ||
3222 | } | ||
3223 | |||
3224 | if (!mwifiex_is_11h_active(priv)) { | ||
3225 | dev_dbg(priv->adapter->dev, "Enable 11h extensions in FW\n"); | ||
3226 | if (mwifiex_11h_activate(priv, true)) { | ||
3227 | dev_err(priv->adapter->dev, | ||
3228 | "Failed to activate 11h extensions!!"); | ||
3229 | return -1; | ||
3230 | } | ||
3231 | priv->state_11h.is_11h_active = true; | ||
3232 | } | ||
3233 | |||
3234 | memset(&radar_params, 0, sizeof(struct mwifiex_radar_params)); | ||
3235 | radar_params.chandef = chandef; | ||
3236 | radar_params.cac_time_ms = cac_time_ms; | ||
3237 | |||
3238 | memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef)); | ||
3239 | |||
3240 | if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST, | ||
3241 | HostCmd_ACT_GEN_SET, 0, &radar_params, true)) | ||
3242 | return -1; | ||
3243 | |||
3244 | queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work, | ||
3245 | msecs_to_jiffies(cac_time_ms)); | ||
3246 | return 0; | ||
3247 | } | ||
3248 | |||
3249 | static int | ||
2851 | mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, | 3250 | mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, |
2852 | const u8 *mac, | 3251 | const u8 *mac, |
2853 | struct station_parameters *params) | 3252 | struct station_parameters *params) |
@@ -2911,6 +3310,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2911 | .tdls_oper = mwifiex_cfg80211_tdls_oper, | 3310 | .tdls_oper = mwifiex_cfg80211_tdls_oper, |
2912 | .add_station = mwifiex_cfg80211_add_station, | 3311 | .add_station = mwifiex_cfg80211_add_station, |
2913 | .change_station = mwifiex_cfg80211_change_station, | 3312 | .change_station = mwifiex_cfg80211_change_station, |
3313 | .start_radar_detection = mwifiex_cfg80211_start_radar_detection, | ||
3314 | .channel_switch = mwifiex_cfg80211_channel_switch, | ||
2914 | }; | 3315 | }; |
2915 | 3316 | ||
2916 | #ifdef CONFIG_PM | 3317 | #ifdef CONFIG_PM |
@@ -3009,12 +3410,13 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
3009 | wiphy->cipher_suites = mwifiex_cipher_suites; | 3410 | wiphy->cipher_suites = mwifiex_cipher_suites; |
3010 | wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); | 3411 | wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); |
3011 | 3412 | ||
3012 | memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); | 3413 | ether_addr_copy(wiphy->perm_addr, adapter->perm_addr); |
3013 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 3414 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
3014 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | 3415 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | |
3015 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | | 3416 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
3016 | WIPHY_FLAG_AP_UAPSD | | 3417 | WIPHY_FLAG_AP_UAPSD | |
3017 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 3418 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
3419 | WIPHY_FLAG_HAS_CHANNEL_SWITCH; | ||
3018 | 3420 | ||
3019 | if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) | 3421 | if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) |
3020 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | 3422 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index f494fc7eeb62..e9df8826f124 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c | |||
@@ -322,9 +322,9 @@ mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq) | |||
322 | return cfp; | 322 | return cfp; |
323 | 323 | ||
324 | if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) | 324 | if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) |
325 | sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; | 325 | sband = priv->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]; |
326 | else | 326 | else |
327 | sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; | 327 | sband = priv->wdev.wiphy->bands[IEEE80211_BAND_5GHZ]; |
328 | 328 | ||
329 | if (!sband) { | 329 | if (!sband) { |
330 | dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d\n", | 330 | dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d\n", |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 946a2f7a172f..c5a14ff7eb82 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -315,22 +315,19 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | |||
315 | adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; | 315 | adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; |
316 | return -1; | 316 | return -1; |
317 | } | 317 | } |
318 | if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) | 318 | |
319 | == MWIFIEX_BSS_ROLE_STA) { | 319 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) |
320 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) | 320 | /* Response is not needed for sleep confirm command */ |
321 | /* Response is not needed for sleep | 321 | adapter->ps_state = PS_STATE_SLEEP; |
322 | confirm command */ | 322 | else |
323 | adapter->ps_state = PS_STATE_SLEEP; | 323 | adapter->ps_state = PS_STATE_SLEEP_CFM; |
324 | else | 324 | |
325 | adapter->ps_state = PS_STATE_SLEEP_CFM; | 325 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && |
326 | 326 | (adapter->is_hs_configured && | |
327 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && | 327 | !adapter->sleep_period.period)) { |
328 | (adapter->is_hs_configured && | 328 | adapter->pm_wakeup_card_req = true; |
329 | !adapter->sleep_period.period)) { | 329 | mwifiex_hs_activated_event(mwifiex_get_priv |
330 | adapter->pm_wakeup_card_req = true; | 330 | (adapter, MWIFIEX_BSS_ROLE_ANY), true); |
331 | mwifiex_hs_activated_event(mwifiex_get_priv | ||
332 | (adapter, MWIFIEX_BSS_ROLE_STA), true); | ||
333 | } | ||
334 | } | 331 | } |
335 | 332 | ||
336 | return ret; | 333 | return ret; |
@@ -450,6 +447,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
450 | EVENT_GET_BSS_TYPE(eventcause)); | 447 | EVENT_GET_BSS_TYPE(eventcause)); |
451 | if (!priv) | 448 | if (!priv) |
452 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 449 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
450 | |||
453 | /* Clear BSS_NO_BITS from event */ | 451 | /* Clear BSS_NO_BITS from event */ |
454 | eventcause &= EVENT_ID_MASK; | 452 | eventcause &= EVENT_ID_MASK; |
455 | adapter->event_cause = eventcause; | 453 | adapter->event_cause = eventcause; |
@@ -462,12 +460,6 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
462 | } | 460 | } |
463 | 461 | ||
464 | dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause); | 462 | dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause); |
465 | if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) { | ||
466 | /* Handle PS_SLEEP/AWAKE events on STA */ | ||
467 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
468 | if (!priv) | ||
469 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
470 | } | ||
471 | 463 | ||
472 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 464 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
473 | ret = mwifiex_process_uap_event(priv); | 465 | ret = mwifiex_process_uap_event(priv); |
@@ -1582,9 +1574,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1582 | le16_to_cpu(hw_spec->hw_if_version), | 1574 | le16_to_cpu(hw_spec->hw_if_version), |
1583 | le16_to_cpu(hw_spec->version)); | 1575 | le16_to_cpu(hw_spec->version)); |
1584 | 1576 | ||
1585 | if (priv->curr_addr[0] == 0xff) | 1577 | ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr); |
1586 | memmove(priv->curr_addr, hw_spec->permanent_addr, ETH_ALEN); | ||
1587 | |||
1588 | adapter->region_code = le16_to_cpu(hw_spec->region_code); | 1578 | adapter->region_code = le16_to_cpu(hw_spec->region_code); |
1589 | 1579 | ||
1590 | for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) | 1580 | for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 7aa988e1dc7a..88d0eade6bb1 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -104,6 +104,12 @@ | |||
104 | /* Rate index for OFDM 0 */ | 104 | /* Rate index for OFDM 0 */ |
105 | #define MWIFIEX_RATE_INDEX_OFDM0 4 | 105 | #define MWIFIEX_RATE_INDEX_OFDM0 4 |
106 | 106 | ||
107 | #define MWIFIEX_MAX_STA_NUM 1 | ||
108 | #define MWIFIEX_MAX_UAP_NUM 1 | ||
109 | #define MWIFIEX_MAX_P2P_NUM 1 | ||
110 | |||
111 | #define MWIFIEX_A_BAND_START_FREQ 5000 | ||
112 | |||
107 | enum mwifiex_bss_type { | 113 | enum mwifiex_bss_type { |
108 | MWIFIEX_BSS_TYPE_STA = 0, | 114 | MWIFIEX_BSS_TYPE_STA = 0, |
109 | MWIFIEX_BSS_TYPE_UAP = 1, | 115 | MWIFIEX_BSS_TYPE_UAP = 1, |
@@ -232,4 +238,19 @@ struct mwifiex_histogram_data { | |||
232 | atomic_t num_samples; | 238 | atomic_t num_samples; |
233 | }; | 239 | }; |
234 | 240 | ||
241 | struct mwifiex_iface_comb { | ||
242 | u8 sta_intf; | ||
243 | u8 uap_intf; | ||
244 | u8 p2p_intf; | ||
245 | }; | ||
246 | |||
247 | struct mwifiex_radar_params { | ||
248 | struct cfg80211_chan_def *chandef; | ||
249 | u32 cac_time_ms; | ||
250 | } __packed; | ||
251 | |||
252 | struct mwifiex_11h_intf_state { | ||
253 | bool is_11h_enabled; | ||
254 | bool is_11h_active; | ||
255 | } __packed; | ||
235 | #endif /* !_MWIFIEX_DECL_H_ */ | 256 | #endif /* !_MWIFIEX_DECL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 15ad776ae08e..df553e86a0ad 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -158,6 +158,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
158 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) | 158 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) |
159 | #define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86) | 159 | #define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86) |
160 | #define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87) | 160 | #define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87) |
161 | #define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91) | ||
161 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) | 162 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) |
162 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) | 163 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) |
163 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) | 164 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) |
@@ -336,6 +337,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
336 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf | 337 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf |
337 | #define HostCmd_CMD_11N_DELBA 0x00d0 | 338 | #define HostCmd_CMD_11N_DELBA 0x00d0 |
338 | #define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 | 339 | #define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 |
340 | #define HostCmd_CMD_CHAN_REPORT_REQUEST 0x00dd | ||
339 | #define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df | 341 | #define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df |
340 | #define HostCmd_CMD_TXPWR_CFG 0x00d1 | 342 | #define HostCmd_CMD_TXPWR_CFG 0x00d1 |
341 | #define HostCmd_CMD_TX_RATE_CFG 0x00d6 | 343 | #define HostCmd_CMD_TX_RATE_CFG 0x00d6 |
@@ -493,6 +495,8 @@ enum P2P_MODES { | |||
493 | #define EVENT_HOSTWAKE_STAIE 0x0000004d | 495 | #define EVENT_HOSTWAKE_STAIE 0x0000004d |
494 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 | 496 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 |
495 | #define EVENT_TDLS_GENERIC_EVENT 0x00000052 | 497 | #define EVENT_TDLS_GENERIC_EVENT 0x00000052 |
498 | #define EVENT_RADAR_DETECTED 0x00000053 | ||
499 | #define EVENT_CHANNEL_REPORT_RDY 0x00000054 | ||
496 | #define EVENT_EXT_SCAN_REPORT 0x00000058 | 500 | #define EVENT_EXT_SCAN_REPORT 0x00000058 |
497 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f | 501 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f |
498 | #define EVENT_TX_STATUS_REPORT 0x00000074 | 502 | #define EVENT_TX_STATUS_REPORT 0x00000074 |
@@ -530,6 +534,8 @@ enum P2P_MODES { | |||
530 | 534 | ||
531 | #define MWIFIEX_FW_V15 15 | 535 | #define MWIFIEX_FW_V15 15 |
532 | 536 | ||
537 | #define MWIFIEX_MASTER_RADAR_DET_MASK BIT(1) | ||
538 | |||
533 | struct mwifiex_ie_types_header { | 539 | struct mwifiex_ie_types_header { |
534 | __le16 type; | 540 | __le16 type; |
535 | __le16 len; | 541 | __le16 len; |
@@ -1216,6 +1222,24 @@ struct host_cmd_ds_tdls_oper { | |||
1216 | u8 peer_mac[ETH_ALEN]; | 1222 | u8 peer_mac[ETH_ALEN]; |
1217 | } __packed; | 1223 | } __packed; |
1218 | 1224 | ||
1225 | struct mwifiex_chan_desc { | ||
1226 | __le16 start_freq; | ||
1227 | u8 chan_width; | ||
1228 | u8 chan_num; | ||
1229 | } __packed; | ||
1230 | |||
1231 | struct host_cmd_ds_chan_rpt_req { | ||
1232 | struct mwifiex_chan_desc chan_desc; | ||
1233 | __le32 msec_dwell_time; | ||
1234 | } __packed; | ||
1235 | |||
1236 | struct host_cmd_ds_chan_rpt_event { | ||
1237 | __le32 result; | ||
1238 | __le64 start_tsf; | ||
1239 | __le32 duration; | ||
1240 | u8 tlvbuf[0]; | ||
1241 | } __packed; | ||
1242 | |||
1219 | struct mwifiex_fixed_bcn_param { | 1243 | struct mwifiex_fixed_bcn_param { |
1220 | __le64 timestamp; | 1244 | __le64 timestamp; |
1221 | __le16 beacon_period; | 1245 | __le16 beacon_period; |
@@ -1792,6 +1816,39 @@ struct mwifiex_ie_types_rssi_threshold { | |||
1792 | u8 evt_freq; | 1816 | u8 evt_freq; |
1793 | } __packed; | 1817 | } __packed; |
1794 | 1818 | ||
1819 | #define MWIFIEX_DFS_REC_HDR_LEN 8 | ||
1820 | #define MWIFIEX_DFS_REC_HDR_NUM 10 | ||
1821 | #define MWIFIEX_BIN_COUNTER_LEN 7 | ||
1822 | |||
1823 | struct mwifiex_radar_det_event { | ||
1824 | __le32 detect_count; | ||
1825 | u8 reg_domain; /*1=fcc, 2=etsi, 3=mic*/ | ||
1826 | u8 det_type; /*0=none, 1=pw(chirp), 2=pri(radar)*/ | ||
1827 | __le16 pw_chirp_type; | ||
1828 | u8 pw_chirp_idx; | ||
1829 | u8 pw_value; | ||
1830 | u8 pri_radar_type; | ||
1831 | u8 pri_bincnt; | ||
1832 | u8 bin_counter[MWIFIEX_BIN_COUNTER_LEN]; | ||
1833 | u8 num_dfs_records; | ||
1834 | u8 dfs_record_hdr[MWIFIEX_DFS_REC_HDR_NUM][MWIFIEX_DFS_REC_HDR_LEN]; | ||
1835 | __le32 passed; | ||
1836 | } __packed; | ||
1837 | |||
1838 | struct meas_rpt_map { | ||
1839 | u8 rssi:3; | ||
1840 | u8 unmeasured:1; | ||
1841 | u8 radar:1; | ||
1842 | u8 unidentified_sig:1; | ||
1843 | u8 ofdm_preamble:1; | ||
1844 | u8 bss:1; | ||
1845 | } __packed; | ||
1846 | |||
1847 | struct mwifiex_ie_types_chan_rpt_data { | ||
1848 | struct mwifiex_ie_types_header header; | ||
1849 | struct meas_rpt_map map; | ||
1850 | } __packed; | ||
1851 | |||
1795 | struct host_cmd_ds_802_11_subsc_evt { | 1852 | struct host_cmd_ds_802_11_subsc_evt { |
1796 | __le16 action; | 1853 | __le16 action; |
1797 | __le16 events; | 1854 | __le16 events; |
@@ -1904,6 +1961,7 @@ struct host_cmd_ds_command { | |||
1904 | struct host_cmd_11ac_vht_cfg vht_cfg; | 1961 | struct host_cmd_11ac_vht_cfg vht_cfg; |
1905 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; | 1962 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; |
1906 | struct host_cmd_ds_tdls_oper tdls_oper; | 1963 | struct host_cmd_ds_tdls_oper tdls_oper; |
1964 | struct host_cmd_ds_chan_rpt_req chan_rpt_req; | ||
1907 | } params; | 1965 | } params; |
1908 | } __packed; | 1966 | } __packed; |
1909 | 1967 | ||
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index b933794758b7..f3b6ed249403 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c | |||
@@ -317,27 +317,27 @@ done: | |||
317 | return ret; | 317 | return ret; |
318 | } | 318 | } |
319 | 319 | ||
320 | /* This function parses different IEs-tail IEs, beacon IEs, probe response IEs, | 320 | /* This function parses head and tail IEs, from cfg80211_beacon_data and sets |
321 | * association response IEs from cfg80211_ap_settings function and sets these IE | 321 | * these IE to FW. |
322 | * to FW. | ||
323 | */ | 322 | */ |
324 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | 323 | static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv, |
325 | struct cfg80211_beacon_data *info) | 324 | struct cfg80211_beacon_data *info) |
326 | { | 325 | { |
327 | struct mwifiex_ie *gen_ie; | 326 | struct mwifiex_ie *gen_ie; |
328 | struct ieee_types_header *rsn_ie, *wpa_ie = NULL; | 327 | struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL; |
329 | u16 rsn_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; | 328 | struct ieee_types_header *chsw_ie = NULL; |
329 | u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; | ||
330 | const u8 *vendor_ie; | 330 | const u8 *vendor_ie; |
331 | 331 | ||
332 | if (info->tail && info->tail_len) { | 332 | gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL); |
333 | gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | 333 | if (!gen_ie) |
334 | if (!gen_ie) | 334 | return -ENOMEM; |
335 | return -ENOMEM; | 335 | gen_ie->ie_index = cpu_to_le16(gen_idx); |
336 | gen_ie->ie_index = cpu_to_le16(rsn_idx); | 336 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | |
337 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | | 337 | MGMT_MASK_PROBE_RESP | |
338 | MGMT_MASK_PROBE_RESP | | 338 | MGMT_MASK_ASSOC_RESP); |
339 | MGMT_MASK_ASSOC_RESP); | ||
340 | 339 | ||
340 | if (info->tail && info->tail_len) { | ||
341 | rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, | 341 | rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, |
342 | info->tail, info->tail_len); | 342 | info->tail, info->tail_len); |
343 | if (rsn_ie) { | 343 | if (rsn_ie) { |
@@ -358,19 +358,41 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
358 | gen_ie->ie_length = cpu_to_le16(ie_len); | 358 | gen_ie->ie_length = cpu_to_le16(ie_len); |
359 | } | 359 | } |
360 | 360 | ||
361 | if (rsn_ie || wpa_ie) { | 361 | chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH, |
362 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx, | 362 | info->tail, info->tail_len); |
363 | NULL, NULL, | 363 | if (chsw_ie) { |
364 | NULL, NULL)) { | 364 | memcpy(gen_ie->ie_buffer + ie_len, |
365 | kfree(gen_ie); | 365 | chsw_ie, chsw_ie->len + 2); |
366 | return -1; | 366 | ie_len += chsw_ie->len + 2; |
367 | } | 367 | gen_ie->ie_length = cpu_to_le16(ie_len); |
368 | priv->rsn_idx = rsn_idx; | ||
369 | } | 368 | } |
369 | } | ||
370 | 370 | ||
371 | kfree(gen_ie); | 371 | if (rsn_ie || wpa_ie || chsw_ie) { |
372 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, | ||
373 | NULL, NULL, NULL)) { | ||
374 | kfree(gen_ie); | ||
375 | return -1; | ||
376 | } | ||
377 | priv->gen_idx = gen_idx; | ||
372 | } | 378 | } |
373 | 379 | ||
380 | kfree(gen_ie); | ||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | /* This function parses different IEs-head & tail IEs, beacon IEs, | ||
385 | * probe response IEs, association response IEs from cfg80211_ap_settings | ||
386 | * function and sets these IE to FW. | ||
387 | */ | ||
388 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
389 | struct cfg80211_beacon_data *info) | ||
390 | { | ||
391 | int ret; | ||
392 | |||
393 | ret = mwifiex_uap_set_head_tail_ies(priv, info); | ||
394 | return ret; | ||
395 | |||
374 | return mwifiex_set_mgmt_beacon_data_ies(priv, info); | 396 | return mwifiex_set_mgmt_beacon_data_ies(priv, info); |
375 | } | 397 | } |
376 | 398 | ||
@@ -378,25 +400,25 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
378 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) | 400 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) |
379 | { | 401 | { |
380 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | 402 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; |
381 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | 403 | struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL; |
382 | int ret = 0; | 404 | int ret = 0; |
383 | 405 | ||
384 | if (priv->rsn_idx != MWIFIEX_AUTO_IDX_MASK) { | 406 | if (priv->gen_idx != MWIFIEX_AUTO_IDX_MASK) { |
385 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | 407 | gen_ie = kmalloc(sizeof(*gen_ie), GFP_KERNEL); |
386 | if (!rsn_ie) | 408 | if (!gen_ie) |
387 | return -ENOMEM; | 409 | return -ENOMEM; |
388 | 410 | ||
389 | rsn_ie->ie_index = cpu_to_le16(priv->rsn_idx); | 411 | gen_ie->ie_index = cpu_to_le16(priv->gen_idx); |
390 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | 412 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); |
391 | rsn_ie->ie_length = 0; | 413 | gen_ie->ie_length = 0; |
392 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &priv->rsn_idx, | 414 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx, |
393 | NULL, &priv->proberesp_idx, | 415 | NULL, &priv->proberesp_idx, |
394 | NULL, &priv->assocresp_idx)) { | 416 | NULL, &priv->assocresp_idx)) { |
395 | ret = -1; | 417 | ret = -1; |
396 | goto done; | 418 | goto done; |
397 | } | 419 | } |
398 | 420 | ||
399 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | 421 | priv->gen_idx = MWIFIEX_AUTO_IDX_MASK; |
400 | } | 422 | } |
401 | 423 | ||
402 | if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) { | 424 | if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) { |
@@ -440,7 +462,6 @@ done: | |||
440 | kfree(beacon_ie); | 462 | kfree(beacon_ie); |
441 | kfree(pr_ie); | 463 | kfree(pr_ie); |
442 | kfree(ar_ie); | 464 | kfree(ar_ie); |
443 | kfree(rsn_ie); | ||
444 | 465 | ||
445 | return ret; | 466 | return ret; |
446 | } | 467 | } |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index b115e0f94dd7..b77ba743e1c4 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -152,6 +152,8 @@ int mwifiex_init_priv(struct mwifiex_private *priv) | |||
152 | priv->check_tdls_tx = false; | 152 | priv->check_tdls_tx = false; |
153 | memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); | 153 | memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); |
154 | 154 | ||
155 | mwifiex_init_11h_params(priv); | ||
156 | |||
155 | return mwifiex_add_bss_prio_tbl(priv); | 157 | return mwifiex_add_bss_prio_tbl(priv); |
156 | } | 158 | } |
157 | 159 | ||
@@ -294,9 +296,13 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
294 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); | 296 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); |
295 | adapter->arp_filter_size = 0; | 297 | adapter->arp_filter_size = 0; |
296 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; | 298 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; |
297 | adapter->ext_scan = true; | 299 | adapter->ext_scan = false; |
298 | adapter->key_api_major_ver = 0; | 300 | adapter->key_api_major_ver = 0; |
299 | adapter->key_api_minor_ver = 0; | 301 | adapter->key_api_minor_ver = 0; |
302 | memset(adapter->perm_addr, 0xff, ETH_ALEN); | ||
303 | adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM; | ||
304 | adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM; | ||
305 | adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM; | ||
300 | 306 | ||
301 | setup_timer(&adapter->wakeup_timer, wakeup_timer_fn, | 307 | setup_timer(&adapter->wakeup_timer, wakeup_timer_fn, |
302 | (unsigned long)adapter); | 308 | (unsigned long)adapter); |
@@ -551,7 +557,8 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter) | |||
551 | 557 | ||
552 | for (i = 0; i < adapter->priv_num; i++) { | 558 | for (i = 0; i < adapter->priv_num; i++) { |
553 | if (adapter->priv[i]) { | 559 | if (adapter->priv[i]) { |
554 | ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); | 560 | ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta, |
561 | true); | ||
555 | if (ret == -1) | 562 | if (ret == -1) |
556 | return -1; | 563 | return -1; |
557 | 564 | ||
@@ -676,6 +683,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
676 | priv = adapter->priv[i]; | 683 | priv = adapter->priv[i]; |
677 | 684 | ||
678 | mwifiex_clean_auto_tdls(priv); | 685 | mwifiex_clean_auto_tdls(priv); |
686 | mwifiex_abort_cac(priv); | ||
679 | mwifiex_clean_txrx(priv); | 687 | mwifiex_clean_txrx(priv); |
680 | mwifiex_delete_bss_prio_tbl(priv); | 688 | mwifiex_delete_bss_prio_tbl(priv); |
681 | } | 689 | } |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d235adb82c94..7e74b4fccddd 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -562,7 +562,8 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) | |||
562 | static int | 562 | static int |
563 | mwifiex_open(struct net_device *dev) | 563 | mwifiex_open(struct net_device *dev) |
564 | { | 564 | { |
565 | netif_tx_start_all_queues(dev); | 565 | netif_carrier_off(dev); |
566 | |||
566 | return 0; | 567 | return 0; |
567 | } | 568 | } |
568 | 569 | ||
@@ -960,21 +961,21 @@ static const struct net_device_ops mwifiex_netdev_ops = { | |||
960 | * In addition, the CFG80211 work queue is also created. | 961 | * In addition, the CFG80211 work queue is also created. |
961 | */ | 962 | */ |
962 | void mwifiex_init_priv_params(struct mwifiex_private *priv, | 963 | void mwifiex_init_priv_params(struct mwifiex_private *priv, |
963 | struct net_device *dev) | 964 | struct net_device *dev) |
964 | { | 965 | { |
965 | dev->netdev_ops = &mwifiex_netdev_ops; | 966 | dev->netdev_ops = &mwifiex_netdev_ops; |
966 | dev->destructor = free_netdev; | 967 | dev->destructor = free_netdev; |
967 | /* Initialize private structure */ | 968 | /* Initialize private structure */ |
968 | priv->current_key_index = 0; | 969 | priv->current_key_index = 0; |
969 | priv->media_connected = false; | 970 | priv->media_connected = false; |
970 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); | ||
971 | memset(priv->mgmt_ie, 0, | 971 | memset(priv->mgmt_ie, 0, |
972 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); | 972 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); |
973 | priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; | 973 | priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; |
974 | priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; | 974 | priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; |
975 | priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; | 975 | priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; |
976 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | 976 | priv->gen_idx = MWIFIEX_AUTO_IDX_MASK; |
977 | priv->num_tx_timeout = 0; | 977 | priv->num_tx_timeout = 0; |
978 | ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr); | ||
978 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); | 979 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); |
979 | 980 | ||
980 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || | 981 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || |
@@ -1203,8 +1204,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) | |||
1203 | continue; | 1204 | continue; |
1204 | 1205 | ||
1205 | rtnl_lock(); | 1206 | rtnl_lock(); |
1206 | if (priv->wdev && priv->netdev) | 1207 | if (priv->netdev && |
1207 | mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); | 1208 | priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) |
1209 | mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev); | ||
1208 | rtnl_unlock(); | 1210 | rtnl_unlock(); |
1209 | } | 1211 | } |
1210 | 1212 | ||
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 55273eefb785..f0a6af179af0 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -547,13 +547,12 @@ struct mwifiex_private { | |||
547 | u32 curr_bcn_size; | 547 | u32 curr_bcn_size; |
548 | /* spin lock for beacon buffer */ | 548 | /* spin lock for beacon buffer */ |
549 | spinlock_t curr_bcn_buf_lock; | 549 | spinlock_t curr_bcn_buf_lock; |
550 | struct wireless_dev *wdev; | 550 | struct wireless_dev wdev; |
551 | struct mwifiex_chan_freq_power cfp; | 551 | struct mwifiex_chan_freq_power cfp; |
552 | char version_str[128]; | 552 | char version_str[128]; |
553 | #ifdef CONFIG_DEBUG_FS | 553 | #ifdef CONFIG_DEBUG_FS |
554 | struct dentry *dfs_dev_dir; | 554 | struct dentry *dfs_dev_dir; |
555 | #endif | 555 | #endif |
556 | u8 nick_name[16]; | ||
557 | u16 current_key_index; | 556 | u16 current_key_index; |
558 | struct semaphore async_sem; | 557 | struct semaphore async_sem; |
559 | struct cfg80211_scan_request *scan_request; | 558 | struct cfg80211_scan_request *scan_request; |
@@ -568,7 +567,7 @@ struct mwifiex_private { | |||
568 | u16 beacon_idx; | 567 | u16 beacon_idx; |
569 | u16 proberesp_idx; | 568 | u16 proberesp_idx; |
570 | u16 assocresp_idx; | 569 | u16 assocresp_idx; |
571 | u16 rsn_idx; | 570 | u16 gen_idx; |
572 | u8 ap_11n_enabled; | 571 | u8 ap_11n_enabled; |
573 | u8 ap_11ac_enabled; | 572 | u8 ap_11ac_enabled; |
574 | u32 mgmt_frame_mask; | 573 | u32 mgmt_frame_mask; |
@@ -578,6 +577,7 @@ struct mwifiex_private { | |||
578 | unsigned long csa_expire_time; | 577 | unsigned long csa_expire_time; |
579 | u8 del_list_idx; | 578 | u8 del_list_idx; |
580 | bool hs2_enabled; | 579 | bool hs2_enabled; |
580 | struct mwifiex_uap_bss_param bss_cfg; | ||
581 | struct station_parameters *sta_params; | 581 | struct station_parameters *sta_params; |
582 | struct sk_buff_head tdls_txq; | 582 | struct sk_buff_head tdls_txq; |
583 | u8 check_tdls_tx; | 583 | u8 check_tdls_tx; |
@@ -588,6 +588,14 @@ struct mwifiex_private { | |||
588 | spinlock_t ack_status_lock; | 588 | spinlock_t ack_status_lock; |
589 | /** rx histogram data */ | 589 | /** rx histogram data */ |
590 | struct mwifiex_histogram_data *hist_data; | 590 | struct mwifiex_histogram_data *hist_data; |
591 | struct cfg80211_chan_def dfs_chandef; | ||
592 | struct workqueue_struct *dfs_cac_workqueue; | ||
593 | struct delayed_work dfs_cac_work; | ||
594 | struct timer_list dfs_chan_switch_timer; | ||
595 | struct workqueue_struct *dfs_chan_sw_workqueue; | ||
596 | struct delayed_work dfs_chan_sw_work; | ||
597 | struct cfg80211_beacon_data beacon_after; | ||
598 | struct mwifiex_11h_intf_state state_11h; | ||
591 | }; | 599 | }; |
592 | 600 | ||
593 | enum mwifiex_ba_status { | 601 | enum mwifiex_ba_status { |
@@ -731,6 +739,8 @@ struct mwifiex_if_ops { | |||
731 | 739 | ||
732 | struct mwifiex_adapter { | 740 | struct mwifiex_adapter { |
733 | u8 iface_type; | 741 | u8 iface_type; |
742 | struct mwifiex_iface_comb iface_limit; | ||
743 | struct mwifiex_iface_comb curr_iface_comb; | ||
734 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; | 744 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; |
735 | u8 priv_num; | 745 | u8 priv_num; |
736 | const struct firmware *firmware; | 746 | const struct firmware *firmware; |
@@ -738,6 +748,7 @@ struct mwifiex_adapter { | |||
738 | int winner; | 748 | int winner; |
739 | struct device *dev; | 749 | struct device *dev; |
740 | struct wiphy *wiphy; | 750 | struct wiphy *wiphy; |
751 | u8 perm_addr[ETH_ALEN]; | ||
741 | bool surprise_removed; | 752 | bool surprise_removed; |
742 | u32 fw_release_number; | 753 | u32 fw_release_number; |
743 | u16 init_wait_q_woken; | 754 | u16 init_wait_q_woken; |
@@ -751,6 +762,8 @@ struct mwifiex_adapter { | |||
751 | struct work_struct main_work; | 762 | struct work_struct main_work; |
752 | struct workqueue_struct *rx_workqueue; | 763 | struct workqueue_struct *rx_workqueue; |
753 | struct work_struct rx_work; | 764 | struct work_struct rx_work; |
765 | struct workqueue_struct *dfs_workqueue; | ||
766 | struct work_struct dfs_work; | ||
754 | bool rx_work_enabled; | 767 | bool rx_work_enabled; |
755 | bool rx_processing; | 768 | bool rx_processing; |
756 | bool delay_main_work; | 769 | bool delay_main_work; |
@@ -989,7 +1002,7 @@ void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, | |||
989 | const u8 *ra_addr); | 1002 | const u8 *ra_addr); |
990 | void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); | 1003 | void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); |
991 | void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); | 1004 | void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); |
992 | int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); | 1005 | int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta, bool init); |
993 | int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, | 1006 | int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, |
994 | struct mwifiex_scan_cmd_config *scan_cfg); | 1007 | struct mwifiex_scan_cmd_config *scan_cfg); |
995 | void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, | 1008 | void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, |
@@ -1150,6 +1163,25 @@ mwifiex_get_priv(struct mwifiex_adapter *adapter, | |||
1150 | } | 1163 | } |
1151 | 1164 | ||
1152 | /* | 1165 | /* |
1166 | * This function returns the first available unused private structure pointer. | ||
1167 | */ | ||
1168 | static inline struct mwifiex_private * | ||
1169 | mwifiex_get_unused_priv(struct mwifiex_adapter *adapter) | ||
1170 | { | ||
1171 | int i; | ||
1172 | |||
1173 | for (i = 0; i < adapter->priv_num; i++) { | ||
1174 | if (adapter->priv[i]) { | ||
1175 | if (adapter->priv[i]->bss_mode == | ||
1176 | NL80211_IFTYPE_UNSPECIFIED) | ||
1177 | break; | ||
1178 | } | ||
1179 | } | ||
1180 | |||
1181 | return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); | ||
1182 | } | ||
1183 | |||
1184 | /* | ||
1153 | * This function returns the driver private structure of a network device. | 1185 | * This function returns the driver private structure of a network device. |
1154 | */ | 1186 | */ |
1155 | static inline struct mwifiex_private * | 1187 | static inline struct mwifiex_private * |
@@ -1240,8 +1272,6 @@ int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, | |||
1240 | struct ieee80211_channel *chan, | 1272 | struct ieee80211_channel *chan, |
1241 | unsigned int duration); | 1273 | unsigned int duration); |
1242 | 1274 | ||
1243 | int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role); | ||
1244 | |||
1245 | int mwifiex_get_stats_info(struct mwifiex_private *priv, | 1275 | int mwifiex_get_stats_info(struct mwifiex_private *priv, |
1246 | struct mwifiex_ds_get_stats *log); | 1276 | struct mwifiex_ds_get_stats *log); |
1247 | 1277 | ||
@@ -1301,9 +1331,17 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
1301 | struct cfg80211_beacon_data *data); | 1331 | struct cfg80211_beacon_data *data); |
1302 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | 1332 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); |
1303 | u8 *mwifiex_11d_code_2_region(u8 code); | 1333 | u8 *mwifiex_11d_code_2_region(u8 code); |
1334 | void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg, | ||
1335 | struct cfg80211_chan_def chandef); | ||
1336 | int mwifiex_config_start_uap(struct mwifiex_private *priv, | ||
1337 | struct mwifiex_uap_bss_param *bss_cfg); | ||
1304 | void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, | 1338 | void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, |
1305 | struct mwifiex_sta_node *node); | 1339 | struct mwifiex_sta_node *node); |
1306 | 1340 | ||
1341 | void mwifiex_init_11h_params(struct mwifiex_private *priv); | ||
1342 | int mwifiex_is_11h_active(struct mwifiex_private *priv); | ||
1343 | int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag); | ||
1344 | |||
1307 | void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, | 1345 | void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, |
1308 | struct mwifiex_bssdescriptor *bss_desc); | 1346 | struct mwifiex_bssdescriptor *bss_desc); |
1309 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); | 1347 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); |
@@ -1352,6 +1390,11 @@ void mwifiex_check_auto_tdls(unsigned long context); | |||
1352 | void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); | 1390 | void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); |
1353 | void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); | 1391 | void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); |
1354 | void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); | 1392 | void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); |
1393 | int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv, | ||
1394 | struct host_cmd_ds_command *cmd, | ||
1395 | void *data_buf); | ||
1396 | int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv, | ||
1397 | struct sk_buff *skb); | ||
1355 | 1398 | ||
1356 | void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, | 1399 | void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, |
1357 | void *event_body); | 1400 | void *event_body); |
@@ -1359,6 +1402,11 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, | |||
1359 | struct sk_buff * | 1402 | struct sk_buff * |
1360 | mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, | 1403 | mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, |
1361 | struct sk_buff *skb, u8 flag, u64 *cookie); | 1404 | struct sk_buff *skb, u8 flag, u64 *cookie); |
1405 | void mwifiex_dfs_cac_work_queue(struct work_struct *work); | ||
1406 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work); | ||
1407 | void mwifiex_abort_cac(struct mwifiex_private *priv); | ||
1408 | int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | ||
1409 | struct sk_buff *skb); | ||
1362 | 1410 | ||
1363 | void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, | 1411 | void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, |
1364 | s8 nflr); | 1412 | s8 nflr); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index a460b0e6a151..a5828da59365 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -204,6 +204,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, | |||
204 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; | 204 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; |
205 | card->pcie.tx_buf_size = data->tx_buf_size; | 205 | card->pcie.tx_buf_size = data->tx_buf_size; |
206 | card->pcie.supports_fw_dump = data->supports_fw_dump; | 206 | card->pcie.supports_fw_dump = data->supports_fw_dump; |
207 | card->pcie.can_ext_scan = data->can_ext_scan; | ||
207 | } | 208 | } |
208 | 209 | ||
209 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, | 210 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, |
@@ -2563,6 +2564,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
2563 | adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; | 2564 | adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; |
2564 | adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); | 2565 | adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); |
2565 | strcpy(adapter->fw_name, card->pcie.firmware); | 2566 | strcpy(adapter->fw_name, card->pcie.firmware); |
2567 | adapter->ext_scan = card->pcie.can_ext_scan; | ||
2566 | 2568 | ||
2567 | return 0; | 2569 | return 0; |
2568 | } | 2570 | } |
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h index 200e8b0cb582..666d40e9dbc3 100644 --- a/drivers/net/wireless/mwifiex/pcie.h +++ b/drivers/net/wireless/mwifiex/pcie.h | |||
@@ -206,6 +206,7 @@ struct mwifiex_pcie_device { | |||
206 | u16 blksz_fw_dl; | 206 | u16 blksz_fw_dl; |
207 | u16 tx_buf_size; | 207 | u16 tx_buf_size; |
208 | bool supports_fw_dump; | 208 | bool supports_fw_dump; |
209 | bool can_ext_scan; | ||
209 | }; | 210 | }; |
210 | 211 | ||
211 | static const struct mwifiex_pcie_device mwifiex_pcie8766 = { | 212 | static const struct mwifiex_pcie_device mwifiex_pcie8766 = { |
@@ -214,6 +215,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8766 = { | |||
214 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, | 215 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, |
215 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | 216 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, |
216 | .supports_fw_dump = false, | 217 | .supports_fw_dump = false, |
218 | .can_ext_scan = true, | ||
217 | }; | 219 | }; |
218 | 220 | ||
219 | static const struct mwifiex_pcie_device mwifiex_pcie8897 = { | 221 | static const struct mwifiex_pcie_device mwifiex_pcie8897 = { |
@@ -222,6 +224,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8897 = { | |||
222 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, | 224 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, |
223 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, | 225 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, |
224 | .supports_fw_dump = true, | 226 | .supports_fw_dump = true, |
227 | .can_ext_scan = true, | ||
225 | }; | 228 | }; |
226 | 229 | ||
227 | struct mwifiex_evt_buf_desc { | 230 | struct mwifiex_evt_buf_desc { |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index e304f0731647..0ffdb7c5afd2 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -496,10 +496,10 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | |||
496 | 496 | ||
497 | for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { | 497 | for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { |
498 | 498 | ||
499 | if (!priv->wdev->wiphy->bands[band]) | 499 | if (!priv->wdev.wiphy->bands[band]) |
500 | continue; | 500 | continue; |
501 | 501 | ||
502 | sband = priv->wdev->wiphy->bands[band]; | 502 | sband = priv->wdev.wiphy->bands[band]; |
503 | 503 | ||
504 | for (i = 0; (i < sband->n_channels) ; i++) { | 504 | for (i = 0; (i < sband->n_channels) ; i++) { |
505 | ch = &sband->channels[i]; | 505 | ch = &sband->channels[i]; |
@@ -1733,10 +1733,10 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, | |||
1733 | 1733 | ||
1734 | freq = cfp ? cfp->freq : 0; | 1734 | freq = cfp ? cfp->freq : 0; |
1735 | 1735 | ||
1736 | chan = ieee80211_get_channel(priv->wdev->wiphy, freq); | 1736 | chan = ieee80211_get_channel(priv->wdev.wiphy, freq); |
1737 | 1737 | ||
1738 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | 1738 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { |
1739 | bss = cfg80211_inform_bss(priv->wdev->wiphy, | 1739 | bss = cfg80211_inform_bss(priv->wdev.wiphy, |
1740 | chan, CFG80211_BSS_FTYPE_UNKNOWN, | 1740 | chan, CFG80211_BSS_FTYPE_UNKNOWN, |
1741 | bssid, timestamp, | 1741 | bssid, timestamp, |
1742 | cap_info_bitmap, beacon_period, | 1742 | cap_info_bitmap, beacon_period, |
@@ -1748,7 +1748,7 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, | |||
1748 | !memcmp(bssid, priv->curr_bss_params.bss_descriptor | 1748 | !memcmp(bssid, priv->curr_bss_params.bss_descriptor |
1749 | .mac_address, ETH_ALEN)) | 1749 | .mac_address, ETH_ALEN)) |
1750 | mwifiex_update_curr_bss_params(priv, bss); | 1750 | mwifiex_update_curr_bss_params(priv, bss); |
1751 | cfg80211_put_bss(priv->wdev->wiphy, bss); | 1751 | cfg80211_put_bss(priv->wdev.wiphy, bss); |
1752 | } | 1752 | } |
1753 | } else { | 1753 | } else { |
1754 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | 1754 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index a70f103359ea..91e36cda9543 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -107,6 +107,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | |||
107 | card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; | 107 | card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; |
108 | card->supports_fw_dump = data->supports_fw_dump; | 108 | card->supports_fw_dump = data->supports_fw_dump; |
109 | card->auto_tdls = data->auto_tdls; | 109 | card->auto_tdls = data->auto_tdls; |
110 | card->can_ext_scan = data->can_ext_scan; | ||
110 | } | 111 | } |
111 | 112 | ||
112 | sdio_claim_host(func); | 113 | sdio_claim_host(func); |
@@ -282,6 +283,9 @@ static int mwifiex_sdio_suspend(struct device *dev) | |||
282 | #define SDIO_DEVICE_ID_MARVELL_8897 (0x912d) | 283 | #define SDIO_DEVICE_ID_MARVELL_8897 (0x912d) |
283 | /* Device ID for SD8887 */ | 284 | /* Device ID for SD8887 */ |
284 | #define SDIO_DEVICE_ID_MARVELL_8887 (0x9135) | 285 | #define SDIO_DEVICE_ID_MARVELL_8887 (0x9135) |
286 | /* Device ID for SD8801 */ | ||
287 | #define SDIO_DEVICE_ID_MARVELL_8801 (0x9139) | ||
288 | |||
285 | 289 | ||
286 | /* WLAN IDs */ | 290 | /* WLAN IDs */ |
287 | static const struct sdio_device_id mwifiex_ids[] = { | 291 | static const struct sdio_device_id mwifiex_ids[] = { |
@@ -295,6 +299,8 @@ static const struct sdio_device_id mwifiex_ids[] = { | |||
295 | .driver_data = (unsigned long) &mwifiex_sdio_sd8897}, | 299 | .driver_data = (unsigned long) &mwifiex_sdio_sd8897}, |
296 | {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887), | 300 | {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887), |
297 | .driver_data = (unsigned long)&mwifiex_sdio_sd8887}, | 301 | .driver_data = (unsigned long)&mwifiex_sdio_sd8887}, |
302 | {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801), | ||
303 | .driver_data = (unsigned long)&mwifiex_sdio_sd8801}, | ||
298 | {}, | 304 | {}, |
299 | }; | 305 | }; |
300 | 306 | ||
@@ -1882,6 +1888,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) | |||
1882 | } | 1888 | } |
1883 | 1889 | ||
1884 | adapter->auto_tdls = card->auto_tdls; | 1890 | adapter->auto_tdls = card->auto_tdls; |
1891 | adapter->ext_scan = card->can_ext_scan; | ||
1885 | return ret; | 1892 | return ret; |
1886 | } | 1893 | } |
1887 | 1894 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 895eea054c9e..957cca246618 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" | 34 | #define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" |
35 | #define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" | 35 | #define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" |
36 | #define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin" | 36 | #define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin" |
37 | #define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin" | ||
37 | 38 | ||
38 | #define BLOCK_MODE 1 | 39 | #define BLOCK_MODE 1 |
39 | #define BYTE_MODE 0 | 40 | #define BYTE_MODE 0 |
@@ -255,6 +256,7 @@ struct sdio_mmc_card { | |||
255 | 256 | ||
256 | u8 *mp_regs; | 257 | u8 *mp_regs; |
257 | u8 auto_tdls; | 258 | u8 auto_tdls; |
259 | bool can_ext_scan; | ||
258 | 260 | ||
259 | struct mwifiex_sdio_mpa_tx mpa_tx; | 261 | struct mwifiex_sdio_mpa_tx mpa_tx; |
260 | struct mwifiex_sdio_mpa_rx mpa_rx; | 262 | struct mwifiex_sdio_mpa_rx mpa_rx; |
@@ -272,6 +274,7 @@ struct mwifiex_sdio_device { | |||
272 | u32 mp_tx_agg_buf_size; | 274 | u32 mp_tx_agg_buf_size; |
273 | u32 mp_rx_agg_buf_size; | 275 | u32 mp_rx_agg_buf_size; |
274 | u8 auto_tdls; | 276 | u8 auto_tdls; |
277 | bool can_ext_scan; | ||
275 | }; | 278 | }; |
276 | 279 | ||
277 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { | 280 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { |
@@ -416,6 +419,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { | |||
416 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 419 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
417 | .supports_fw_dump = false, | 420 | .supports_fw_dump = false, |
418 | .auto_tdls = false, | 421 | .auto_tdls = false, |
422 | .can_ext_scan = false, | ||
419 | }; | 423 | }; |
420 | 424 | ||
421 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | 425 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { |
@@ -430,6 +434,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | |||
430 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 434 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
431 | .supports_fw_dump = false, | 435 | .supports_fw_dump = false, |
432 | .auto_tdls = false, | 436 | .auto_tdls = false, |
437 | .can_ext_scan = true, | ||
433 | }; | 438 | }; |
434 | 439 | ||
435 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | 440 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { |
@@ -444,6 +449,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | |||
444 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 449 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
445 | .supports_fw_dump = false, | 450 | .supports_fw_dump = false, |
446 | .auto_tdls = false, | 451 | .auto_tdls = false, |
452 | .can_ext_scan = true, | ||
447 | }; | 453 | }; |
448 | 454 | ||
449 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | 455 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { |
@@ -458,6 +464,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | |||
458 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 464 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
459 | .supports_fw_dump = true, | 465 | .supports_fw_dump = true, |
460 | .auto_tdls = false, | 466 | .auto_tdls = false, |
467 | .can_ext_scan = true, | ||
461 | }; | 468 | }; |
462 | 469 | ||
463 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { | 470 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { |
@@ -472,6 +479,22 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { | |||
472 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 479 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
473 | .supports_fw_dump = false, | 480 | .supports_fw_dump = false, |
474 | .auto_tdls = true, | 481 | .auto_tdls = true, |
482 | .can_ext_scan = true, | ||
483 | }; | ||
484 | |||
485 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = { | ||
486 | .firmware = SD8801_DEFAULT_FW_NAME, | ||
487 | .reg = &mwifiex_reg_sd87xx, | ||
488 | .max_ports = 16, | ||
489 | .mp_agg_pkt_limit = 8, | ||
490 | .supports_sdio_new_mode = false, | ||
491 | .has_control_mask = true, | ||
492 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | ||
493 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | ||
494 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | ||
495 | .supports_fw_dump = false, | ||
496 | .auto_tdls = false, | ||
497 | .can_ext_scan = true, | ||
475 | }; | 498 | }; |
476 | 499 | ||
477 | /* | 500 | /* |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index f7b920d7a95a..f7d204ffd6e9 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -1897,6 +1897,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1897 | case HostCmd_CMD_TDLS_OPER: | 1897 | case HostCmd_CMD_TDLS_OPER: |
1898 | ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); | 1898 | ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); |
1899 | break; | 1899 | break; |
1900 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | ||
1901 | ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, | ||
1902 | data_buf); | ||
1903 | break; | ||
1900 | default: | 1904 | default: |
1901 | dev_err(priv->adapter->dev, | 1905 | dev_err(priv->adapter->dev, |
1902 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1906 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
@@ -1911,6 +1915,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1911 | * | 1915 | * |
1912 | * This is called after firmware download to bring the card to | 1916 | * This is called after firmware download to bring the card to |
1913 | * working state. | 1917 | * working state. |
1918 | * Function is also called during reinitialization of virtual | ||
1919 | * interfaces. | ||
1914 | * | 1920 | * |
1915 | * The following commands are issued sequentially - | 1921 | * The following commands are issued sequentially - |
1916 | * - Set PCI-Express host buffer configuration (PCIE only) | 1922 | * - Set PCI-Express host buffer configuration (PCIE only) |
@@ -1925,7 +1931,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1925 | * - Set 11d control | 1931 | * - Set 11d control |
1926 | * - Set MAC control (this must be the last command to initialize firmware) | 1932 | * - Set MAC control (this must be the last command to initialize firmware) |
1927 | */ | 1933 | */ |
1928 | int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | 1934 | int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) |
1929 | { | 1935 | { |
1930 | struct mwifiex_adapter *adapter = priv->adapter; | 1936 | struct mwifiex_adapter *adapter = priv->adapter; |
1931 | int ret; | 1937 | int ret; |
@@ -2059,9 +2065,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
2059 | "11D: failed to enable 11D\n"); | 2065 | "11D: failed to enable 11D\n"); |
2060 | } | 2066 | } |
2061 | 2067 | ||
2062 | /* set last_init_cmd before sending the command */ | ||
2063 | priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; | ||
2064 | |||
2065 | /* Send cmd to FW to configure 11n specific configuration | 2068 | /* Send cmd to FW to configure 11n specific configuration |
2066 | * (Short GI, Channel BW, Green field support etc.) for transmit | 2069 | * (Short GI, Channel BW, Green field support etc.) for transmit |
2067 | */ | 2070 | */ |
@@ -2069,7 +2072,11 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
2069 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG, | 2072 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG, |
2070 | HostCmd_ACT_GEN_SET, 0, &tx_cfg, true); | 2073 | HostCmd_ACT_GEN_SET, 0, &tx_cfg, true); |
2071 | 2074 | ||
2072 | ret = -EINPROGRESS; | 2075 | if (init) { |
2076 | /* set last_init_cmd before sending the command */ | ||
2077 | priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; | ||
2078 | ret = -EINPROGRESS; | ||
2079 | } | ||
2073 | 2080 | ||
2074 | return ret; | 2081 | return ret; |
2075 | } | 2082 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 65d10a33eab5..5f8da5924666 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -1105,6 +1105,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
1105 | case HostCmd_CMD_UAP_SYS_CONFIG: | 1105 | case HostCmd_CMD_UAP_SYS_CONFIG: |
1106 | break; | 1106 | break; |
1107 | case HostCmd_CMD_UAP_BSS_START: | 1107 | case HostCmd_CMD_UAP_BSS_START: |
1108 | adapter->tx_lock_flag = false; | ||
1109 | adapter->pps_uapsd_mode = false; | ||
1110 | adapter->delay_null_pkt = false; | ||
1108 | priv->bss_started = 1; | 1111 | priv->bss_started = 1; |
1109 | break; | 1112 | break; |
1110 | case HostCmd_CMD_UAP_BSS_STOP: | 1113 | case HostCmd_CMD_UAP_BSS_STOP: |
@@ -1119,6 +1122,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
1119 | case HostCmd_CMD_TDLS_OPER: | 1122 | case HostCmd_CMD_TDLS_OPER: |
1120 | ret = mwifiex_ret_tdls_oper(priv, resp); | 1123 | ret = mwifiex_ret_tdls_oper(priv, resp); |
1121 | break; | 1124 | break; |
1125 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | ||
1126 | break; | ||
1122 | default: | 1127 | default: |
1123 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 1128 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
1124 | resp->command); | 1129 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 419e35f1dbf3..80ffe7412496 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -312,8 +312,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
312 | adapter->ps_state = PS_STATE_AWAKE; | 312 | adapter->ps_state = PS_STATE_AWAKE; |
313 | adapter->pm_wakeup_card_req = false; | 313 | adapter->pm_wakeup_card_req = false; |
314 | adapter->pm_wakeup_fw_try = false; | 314 | adapter->pm_wakeup_fw_try = false; |
315 | mod_timer(&adapter->wakeup_timer, | 315 | del_timer_sync(&adapter->wakeup_timer); |
316 | jiffies + (HZ*3)); | ||
317 | break; | 316 | break; |
318 | } | 317 | } |
319 | if (!mwifiex_send_null_packet | 318 | if (!mwifiex_send_null_packet |
@@ -487,7 +486,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
487 | 486 | ||
488 | case EVENT_REMAIN_ON_CHAN_EXPIRED: | 487 | case EVENT_REMAIN_ON_CHAN_EXPIRED: |
489 | dev_dbg(adapter->dev, "event: Remain on channel expired\n"); | 488 | dev_dbg(adapter->dev, "event: Remain on channel expired\n"); |
490 | cfg80211_remain_on_channel_expired(priv->wdev, | 489 | cfg80211_remain_on_channel_expired(&priv->wdev, |
491 | priv->roc_cfg.cookie, | 490 | priv->roc_cfg.cookie, |
492 | &priv->roc_cfg.chan, | 491 | &priv->roc_cfg.chan, |
493 | GFP_ATOMIC); | 492 | GFP_ATOMIC); |
@@ -516,6 +515,16 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
516 | mwifiex_parse_tx_status_event(priv, adapter->event_body); | 515 | mwifiex_parse_tx_status_event(priv, adapter->event_body); |
517 | break; | 516 | break; |
518 | 517 | ||
518 | case EVENT_CHANNEL_REPORT_RDY: | ||
519 | dev_dbg(adapter->dev, "event: Channel Report\n"); | ||
520 | ret = mwifiex_11h_handle_chanrpt_ready(priv, | ||
521 | adapter->event_skb); | ||
522 | break; | ||
523 | case EVENT_RADAR_DETECTED: | ||
524 | dev_dbg(adapter->dev, "event: Radar detected\n"); | ||
525 | ret = mwifiex_11h_handle_radar_detected(priv, | ||
526 | adapter->event_skb); | ||
527 | break; | ||
519 | default: | 528 | default: |
520 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 529 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
521 | eventcause); | 530 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index fb9c5fc83e5d..0599e41e253c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -219,7 +219,7 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
219 | 219 | ||
220 | if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { | 220 | if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { |
221 | rcu_read_unlock(); | 221 | rcu_read_unlock(); |
222 | wiphy_dbg(priv->wdev->wiphy, | 222 | wiphy_dbg(priv->wdev.wiphy, |
223 | "11D: skip setting domain info in FW\n"); | 223 | "11D: skip setting domain info in FW\n"); |
224 | return 0; | 224 | return 0; |
225 | } | 225 | } |
@@ -1135,36 +1135,6 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, | |||
1135 | return roc_cfg.status; | 1135 | return roc_cfg.status; |
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | int | ||
1139 | mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role) | ||
1140 | { | ||
1141 | if (GET_BSS_ROLE(priv) == bss_role) { | ||
1142 | dev_dbg(priv->adapter->dev, | ||
1143 | "info: already in the desired role.\n"); | ||
1144 | return 0; | ||
1145 | } | ||
1146 | |||
1147 | mwifiex_free_priv(priv); | ||
1148 | mwifiex_init_priv(priv); | ||
1149 | |||
1150 | priv->bss_role = bss_role; | ||
1151 | switch (bss_role) { | ||
1152 | case MWIFIEX_BSS_ROLE_UAP: | ||
1153 | priv->bss_mode = NL80211_IFTYPE_AP; | ||
1154 | break; | ||
1155 | case MWIFIEX_BSS_ROLE_STA: | ||
1156 | case MWIFIEX_BSS_ROLE_ANY: | ||
1157 | default: | ||
1158 | priv->bss_mode = NL80211_IFTYPE_STATION; | ||
1159 | break; | ||
1160 | } | ||
1161 | |||
1162 | mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
1163 | HostCmd_ACT_GEN_SET, 0, NULL, true); | ||
1164 | |||
1165 | return mwifiex_sta_init_cmd(priv, false); | ||
1166 | } | ||
1167 | |||
1168 | /* | 1138 | /* |
1169 | * Sends IOCTL request to get statistics information. | 1139 | * Sends IOCTL request to get statistics information. |
1170 | * | 1140 | * |
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 1debe76017b1..5ce2d9a4f919 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c | |||
@@ -183,9 +183,13 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
183 | } | 183 | } |
184 | switch (ret) { | 184 | switch (ret) { |
185 | case -EBUSY: | 185 | case -EBUSY: |
186 | adapter->data_sent = true; | 186 | dev_kfree_skb_any(skb); |
187 | /* Fall through FAILURE handling */ | 187 | dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", |
188 | __func__, ret); | ||
189 | adapter->dbg.num_tx_host_to_card_failure++; | ||
190 | break; | ||
188 | case -1: | 191 | case -1: |
192 | adapter->data_sent = false; | ||
189 | dev_kfree_skb_any(skb); | 193 | dev_kfree_skb_any(skb); |
190 | dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", | 194 | dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", |
191 | __func__, ret); | 195 | __func__, ret); |
@@ -198,6 +202,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
198 | adapter->tx_lock_flag = true; | 202 | adapter->tx_lock_flag = true; |
199 | break; | 203 | break; |
200 | case -EINPROGRESS: | 204 | case -EINPROGRESS: |
205 | adapter->tx_lock_flag = true; | ||
201 | break; | 206 | break; |
202 | default: | 207 | default: |
203 | break; | 208 | break; |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 6ae133333363..ac93557cbdc9 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -227,7 +227,7 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, | |||
227 | /* consumes ack_skb */ | 227 | /* consumes ack_skb */ |
228 | skb_complete_wifi_ack(ack_skb, !tx_status->status); | 228 | skb_complete_wifi_ack(ack_skb, !tx_status->status); |
229 | } else { | 229 | } else { |
230 | cfg80211_mgmt_tx_status(priv->wdev, tx_info->cookie, | 230 | cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie, |
231 | ack_skb->data, ack_skb->len, | 231 | ack_skb->data, ack_skb->len, |
232 | !tx_status->status, GFP_ATOMIC); | 232 | !tx_status->status, GFP_ATOMIC); |
233 | dev_kfree_skb_any(ack_skb); | 233 | dev_kfree_skb_any(ack_skb); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 0f347fdefa0a..f5c2af01ba0a 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -761,6 +761,11 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
761 | if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) | 761 | if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) |
762 | return -1; | 762 | return -1; |
763 | break; | 763 | break; |
764 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | ||
765 | if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf, | ||
766 | data_buf)) | ||
767 | return -1; | ||
768 | break; | ||
764 | default: | 769 | default: |
765 | dev_err(priv->adapter->dev, | 770 | dev_err(priv->adapter->dev, |
766 | "PREP_CMD: unknown cmd %#x\n", cmd_no); | 771 | "PREP_CMD: unknown cmd %#x\n", cmd_no); |
@@ -769,3 +774,68 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
769 | 774 | ||
770 | return 0; | 775 | return 0; |
771 | } | 776 | } |
777 | |||
778 | void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg, | ||
779 | struct cfg80211_chan_def chandef) | ||
780 | { | ||
781 | u8 config_bands = 0; | ||
782 | |||
783 | bss_cfg->channel = ieee80211_frequency_to_channel( | ||
784 | chandef.chan->center_freq); | ||
785 | |||
786 | /* Set appropriate bands */ | ||
787 | if (chandef.chan->band == IEEE80211_BAND_2GHZ) { | ||
788 | bss_cfg->band_cfg = BAND_CONFIG_BG; | ||
789 | config_bands = BAND_B | BAND_G; | ||
790 | |||
791 | if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
792 | config_bands |= BAND_GN; | ||
793 | } else { | ||
794 | bss_cfg->band_cfg = BAND_CONFIG_A; | ||
795 | config_bands = BAND_A; | ||
796 | |||
797 | if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
798 | config_bands |= BAND_AN; | ||
799 | |||
800 | if (chandef.width > NL80211_CHAN_WIDTH_40) | ||
801 | config_bands |= BAND_AAC; | ||
802 | } | ||
803 | } | ||
804 | |||
805 | int mwifiex_config_start_uap(struct mwifiex_private *priv, | ||
806 | struct mwifiex_uap_bss_param *bss_cfg) | ||
807 | { | ||
808 | if (mwifiex_del_mgmt_ies(priv)) | ||
809 | dev_err(priv->adapter->dev, "Failed to delete mgmt IEs!\n"); | ||
810 | |||
811 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
812 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | ||
813 | dev_err(priv->adapter->dev, "Failed to stop the BSS\n"); | ||
814 | return -1; | ||
815 | } | ||
816 | |||
817 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
818 | HostCmd_ACT_GEN_SET, | ||
819 | UAP_BSS_PARAMS_I, bss_cfg, false)) { | ||
820 | dev_err(priv->adapter->dev, "Failed to set the SSID\n"); | ||
821 | return -1; | ||
822 | } | ||
823 | |||
824 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, | ||
825 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { | ||
826 | dev_err(priv->adapter->dev, "Failed to start the BSS\n"); | ||
827 | return -1; | ||
828 | } | ||
829 | |||
830 | if (priv->sec_info.wep_enabled) | ||
831 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; | ||
832 | else | ||
833 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | ||
834 | |||
835 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, | ||
836 | HostCmd_ACT_GEN_SET, 0, | ||
837 | &priv->curr_pkt_filter, true)) | ||
838 | return -1; | ||
839 | |||
840 | return 0; | ||
841 | } | ||
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 96ff39722f8f..f4794cdc36d2 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c | |||
@@ -178,6 +178,53 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
178 | dev_dbg(adapter->dev, "event: TX_STATUS Report\n"); | 178 | dev_dbg(adapter->dev, "event: TX_STATUS Report\n"); |
179 | mwifiex_parse_tx_status_event(priv, adapter->event_body); | 179 | mwifiex_parse_tx_status_event(priv, adapter->event_body); |
180 | break; | 180 | break; |
181 | case EVENT_PS_SLEEP: | ||
182 | dev_dbg(adapter->dev, "info: EVENT: SLEEP\n"); | ||
183 | |||
184 | adapter->ps_state = PS_STATE_PRE_SLEEP; | ||
185 | |||
186 | mwifiex_check_ps_cond(adapter); | ||
187 | break; | ||
188 | |||
189 | case EVENT_PS_AWAKE: | ||
190 | dev_dbg(adapter->dev, "info: EVENT: AWAKE\n"); | ||
191 | if (!adapter->pps_uapsd_mode && | ||
192 | priv->media_connected && adapter->sleep_period.period) { | ||
193 | adapter->pps_uapsd_mode = true; | ||
194 | dev_dbg(adapter->dev, | ||
195 | "event: PPS/UAPSD mode activated\n"); | ||
196 | } | ||
197 | adapter->tx_lock_flag = false; | ||
198 | if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { | ||
199 | if (mwifiex_check_last_packet_indication(priv)) { | ||
200 | if (adapter->data_sent) { | ||
201 | adapter->ps_state = PS_STATE_AWAKE; | ||
202 | adapter->pm_wakeup_card_req = false; | ||
203 | adapter->pm_wakeup_fw_try = false; | ||
204 | break; | ||
205 | } | ||
206 | if (!mwifiex_send_null_packet | ||
207 | (priv, | ||
208 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | | ||
209 | MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) | ||
210 | adapter->ps_state = | ||
211 | PS_STATE_SLEEP; | ||
212 | return 0; | ||
213 | } | ||
214 | } | ||
215 | adapter->ps_state = PS_STATE_AWAKE; | ||
216 | adapter->pm_wakeup_card_req = false; | ||
217 | adapter->pm_wakeup_fw_try = false; | ||
218 | break; | ||
219 | |||
220 | case EVENT_CHANNEL_REPORT_RDY: | ||
221 | dev_dbg(adapter->dev, "event: Channel Report\n"); | ||
222 | mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb); | ||
223 | break; | ||
224 | case EVENT_RADAR_DETECTED: | ||
225 | dev_dbg(adapter->dev, "event: Radar detected\n"); | ||
226 | mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); | ||
227 | break; | ||
181 | default: | 228 | default: |
182 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 229 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
183 | eventcause); | 230 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 6c62995028e6..223873022ffe 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -37,6 +37,11 @@ static struct usb_device_id mwifiex_usb_table[] = { | |||
37 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, | 37 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, |
38 | USB_CLASS_VENDOR_SPEC, | 38 | USB_CLASS_VENDOR_SPEC, |
39 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, | 39 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, |
40 | /* 8801 */ | ||
41 | {USB_DEVICE(USB8XXX_VID, USB8801_PID_1)}, | ||
42 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2, | ||
43 | USB_CLASS_VENDOR_SPEC, | ||
44 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, | ||
40 | /* 8897 */ | 45 | /* 8897 */ |
41 | {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)}, | 46 | {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)}, |
42 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2, | 47 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2, |
@@ -361,11 +366,13 @@ static int mwifiex_usb_probe(struct usb_interface *intf, | |||
361 | switch (id_product) { | 366 | switch (id_product) { |
362 | case USB8766_PID_1: | 367 | case USB8766_PID_1: |
363 | case USB8797_PID_1: | 368 | case USB8797_PID_1: |
369 | case USB8801_PID_1: | ||
364 | case USB8897_PID_1: | 370 | case USB8897_PID_1: |
365 | card->usb_boot_state = USB8XXX_FW_DNLD; | 371 | card->usb_boot_state = USB8XXX_FW_DNLD; |
366 | break; | 372 | break; |
367 | case USB8766_PID_2: | 373 | case USB8766_PID_2: |
368 | case USB8797_PID_2: | 374 | case USB8797_PID_2: |
375 | case USB8801_PID_2: | ||
369 | case USB8897_PID_2: | 376 | case USB8897_PID_2: |
370 | card->usb_boot_state = USB8XXX_FW_READY; | 377 | card->usb_boot_state = USB8XXX_FW_READY; |
371 | break; | 378 | break; |
@@ -792,11 +799,19 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
792 | case USB8897_PID_2: | 799 | case USB8897_PID_2: |
793 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; | 800 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; |
794 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); | 801 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); |
802 | adapter->ext_scan = true; | ||
795 | break; | 803 | break; |
796 | case USB8766_PID_1: | 804 | case USB8766_PID_1: |
797 | case USB8766_PID_2: | 805 | case USB8766_PID_2: |
798 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | 806 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; |
799 | strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME); | 807 | strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME); |
808 | adapter->ext_scan = true; | ||
809 | break; | ||
810 | case USB8801_PID_1: | ||
811 | case USB8801_PID_2: | ||
812 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | ||
813 | strcpy(adapter->fw_name, USB8801_DEFAULT_FW_NAME); | ||
814 | adapter->ext_scan = false; | ||
800 | break; | 815 | break; |
801 | case USB8797_PID_1: | 816 | case USB8797_PID_1: |
802 | case USB8797_PID_2: | 817 | case USB8797_PID_2: |
@@ -1083,4 +1098,5 @@ MODULE_VERSION(USB_VERSION); | |||
1083 | MODULE_LICENSE("GPL v2"); | 1098 | MODULE_LICENSE("GPL v2"); |
1084 | MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); | 1099 | MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); |
1085 | MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); | 1100 | MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); |
1101 | MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME); | ||
1086 | MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); | 1102 | MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); |
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index 0ad1bebc3f93..57e1a5736318 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h | |||
@@ -30,6 +30,9 @@ | |||
30 | #define USB8797_PID_2 0x2044 | 30 | #define USB8797_PID_2 0x2044 |
31 | #define USB8897_PID_1 0x2045 | 31 | #define USB8897_PID_1 0x2045 |
32 | #define USB8897_PID_2 0x2046 | 32 | #define USB8897_PID_2 0x2046 |
33 | #define USB8801_PID_1 0x2049 | ||
34 | #define USB8801_PID_2 0x204a | ||
35 | |||
33 | 36 | ||
34 | #define USB8XXX_FW_DNLD 1 | 37 | #define USB8XXX_FW_DNLD 1 |
35 | #define USB8XXX_FW_READY 2 | 38 | #define USB8XXX_FW_READY 2 |
@@ -41,6 +44,7 @@ | |||
41 | 44 | ||
42 | #define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" | 45 | #define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" |
43 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" | 46 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" |
47 | #define USB8801_DEFAULT_FW_NAME "mrvl/usb8801_uapsta.bin" | ||
44 | #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" | 48 | #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" |
45 | 49 | ||
46 | #define FW_DNLD_TX_BUF_SIZE 620 | 50 | #define FW_DNLD_TX_BUF_SIZE 620 |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 707319799942..308550611f22 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -387,7 +387,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |||
387 | pkt_len -= ETH_ALEN + sizeof(pkt_len); | 387 | pkt_len -= ETH_ALEN + sizeof(pkt_len); |
388 | rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); | 388 | rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); |
389 | 389 | ||
390 | cfg80211_rx_mgmt(priv->wdev, priv->roc_cfg.chan.center_freq, | 390 | cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq, |
391 | CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len, | 391 | CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len, |
392 | 0); | 392 | 0); |
393 | 393 | ||
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index ffffd2c5a76e..ef717acec8b7 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -1228,6 +1228,9 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
1228 | case -EINPROGRESS: | 1228 | case -EINPROGRESS: |
1229 | if (adapter->iface_type != MWIFIEX_PCIE) | 1229 | if (adapter->iface_type != MWIFIEX_PCIE) |
1230 | adapter->data_sent = false; | 1230 | adapter->data_sent = false; |
1231 | break; | ||
1232 | case 0: | ||
1233 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
1231 | default: | 1234 | default: |
1232 | break; | 1235 | break; |
1233 | } | 1236 | } |
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 38ec8d19ac29..c410180479e6 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c | |||
@@ -2342,7 +2342,7 @@ void free_orinocodev(struct orinoco_private *priv) | |||
2342 | list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) { | 2342 | list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) { |
2343 | list_del(&sd->list); | 2343 | list_del(&sd->list); |
2344 | 2344 | ||
2345 | if ((sd->len > 0) && sd->buf) | 2345 | if (sd->len > 0) |
2346 | kfree(sd->buf); | 2346 | kfree(sd->buf); |
2347 | kfree(sd); | 2347 | kfree(sd); |
2348 | } | 2348 | } |
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index b6bdad632842..74219d59d7e1 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c | |||
@@ -94,7 +94,7 @@ static int orinoco_pci_cor_reset(struct orinoco_private *priv) | |||
94 | mdelay(HERMES_PCI_COR_OFFT); | 94 | mdelay(HERMES_PCI_COR_OFFT); |
95 | 95 | ||
96 | /* The card is ready when it's no longer busy */ | 96 | /* The card is ready when it's no longer busy */ |
97 | timeout = jiffies + (HERMES_PCI_COR_BUSYT * HZ / 1000); | 97 | timeout = jiffies + msecs_to_jiffies(HERMES_PCI_COR_BUSYT); |
98 | reg = hermes_read_regn(hw, CMD); | 98 | reg = hermes_read_regn(hw, CMD); |
99 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { | 99 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { |
100 | mdelay(1); | 100 | mdelay(1); |
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index b8f6e5c431ae..8b045236b6e0 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c | |||
@@ -121,7 +121,7 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv) | |||
121 | mdelay(1); | 121 | mdelay(1); |
122 | 122 | ||
123 | /* Just in case, wait more until the card is no longer busy */ | 123 | /* Just in case, wait more until the card is no longer busy */ |
124 | timeout = jiffies + (PLX_RESET_TIME * HZ / 1000); | 124 | timeout = jiffies + msecs_to_jiffies(PLX_RESET_TIME); |
125 | reg = hermes_read_regn(hw, CMD); | 125 | reg = hermes_read_regn(hw, CMD); |
126 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { | 126 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { |
127 | mdelay(1); | 127 | mdelay(1); |
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 79d0e33b625e..20ce569b8a43 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c | |||
@@ -71,7 +71,7 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | |||
71 | mdelay(1); | 71 | mdelay(1); |
72 | 72 | ||
73 | /* Just in case, wait more until the card is no longer busy */ | 73 | /* Just in case, wait more until the card is no longer busy */ |
74 | timeout = jiffies + (TMD_RESET_TIME * HZ / 1000); | 74 | timeout = jiffies + msecs_to_jiffies(TMD_RESET_TIME); |
75 | reg = hermes_read_regn(hw, CMD); | 75 | reg = hermes_read_regn(hw, CMD); |
76 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { | 76 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { |
77 | mdelay(1); | 77 | mdelay(1); |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index eb203163ed05..a31a12775f1a 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -1010,6 +1010,16 @@ static int rtl_op_conf_tx(struct ieee80211_hw *hw, | |||
1010 | return 0; | 1010 | return 0; |
1011 | } | 1011 | } |
1012 | 1012 | ||
1013 | static void send_beacon_frame(struct ieee80211_hw *hw, | ||
1014 | struct ieee80211_vif *vif) | ||
1015 | { | ||
1016 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1017 | struct sk_buff *skb = ieee80211_beacon_get(hw, vif); | ||
1018 | |||
1019 | if (skb) | ||
1020 | rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, NULL); | ||
1021 | } | ||
1022 | |||
1013 | static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | 1023 | static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, |
1014 | struct ieee80211_vif *vif, | 1024 | struct ieee80211_vif *vif, |
1015 | struct ieee80211_bss_conf *bss_conf, | 1025 | struct ieee80211_bss_conf *bss_conf, |
@@ -1040,6 +1050,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1040 | 1050 | ||
1041 | if (rtlpriv->cfg->ops->linked_set_reg) | 1051 | if (rtlpriv->cfg->ops->linked_set_reg) |
1042 | rtlpriv->cfg->ops->linked_set_reg(hw); | 1052 | rtlpriv->cfg->ops->linked_set_reg(hw); |
1053 | send_beacon_frame(hw, vif); | ||
1043 | } | 1054 | } |
1044 | } | 1055 | } |
1045 | if ((changed & BSS_CHANGED_BEACON_ENABLED && | 1056 | if ((changed & BSS_CHANGED_BEACON_ENABLED && |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index c70efb9a6e78..ec456f0d972e 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -578,6 +578,13 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
578 | else | 578 | else |
579 | entry = (u8 *)(&ring->desc[ring->idx]); | 579 | entry = (u8 *)(&ring->desc[ring->idx]); |
580 | 580 | ||
581 | if (rtlpriv->cfg->ops->get_available_desc && | ||
582 | rtlpriv->cfg->ops->get_available_desc(hw, prio) <= 1) { | ||
583 | RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_DMESG, | ||
584 | "no available desc!\n"); | ||
585 | return; | ||
586 | } | ||
587 | |||
581 | if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx)) | 588 | if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx)) |
582 | return; | 589 | return; |
583 | ring->idx = (ring->idx + 1) % ring->entries; | 590 | ring->idx = (ring->idx + 1) % ring->entries; |
@@ -641,10 +648,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
641 | 648 | ||
642 | ieee80211_tx_status_irqsafe(hw, skb); | 649 | ieee80211_tx_status_irqsafe(hw, skb); |
643 | 650 | ||
644 | if ((ring->entries - skb_queue_len(&ring->queue)) | 651 | if ((ring->entries - skb_queue_len(&ring->queue)) <= 4) { |
645 | == 2) { | ||
646 | 652 | ||
647 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, | 653 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, |
648 | "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n", | 654 | "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n", |
649 | prio, ring->idx, | 655 | prio, ring->idx, |
650 | skb_queue_len(&ring->queue)); | 656 | skb_queue_len(&ring->queue)); |
@@ -793,7 +799,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
793 | rx_remained_cnt = | 799 | rx_remained_cnt = |
794 | rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw, | 800 | rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw, |
795 | hw_queue); | 801 | hw_queue); |
796 | if (rx_remained_cnt < 1) | 802 | if (rx_remained_cnt == 0) |
797 | return; | 803 | return; |
798 | 804 | ||
799 | } else { /* rx descriptor */ | 805 | } else { /* rx descriptor */ |
@@ -848,18 +854,18 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
848 | else | 854 | else |
849 | skb_reserve(skb, stats.rx_drvinfo_size + | 855 | skb_reserve(skb, stats.rx_drvinfo_size + |
850 | stats.rx_bufshift); | 856 | stats.rx_bufshift); |
851 | |||
852 | } else { | 857 | } else { |
853 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 858 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
854 | "skb->end - skb->tail = %d, len is %d\n", | 859 | "skb->end - skb->tail = %d, len is %d\n", |
855 | skb->end - skb->tail, len); | 860 | skb->end - skb->tail, len); |
856 | break; | 861 | dev_kfree_skb_any(skb); |
862 | goto new_trx_end; | ||
857 | } | 863 | } |
858 | /* handle command packet here */ | 864 | /* handle command packet here */ |
859 | if (rtlpriv->cfg->ops->rx_command_packet && | 865 | if (rtlpriv->cfg->ops->rx_command_packet && |
860 | rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { | 866 | rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { |
861 | dev_kfree_skb_any(skb); | 867 | dev_kfree_skb_any(skb); |
862 | goto end; | 868 | goto new_trx_end; |
863 | } | 869 | } |
864 | 870 | ||
865 | /* | 871 | /* |
@@ -909,6 +915,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
909 | } else { | 915 | } else { |
910 | dev_kfree_skb_any(skb); | 916 | dev_kfree_skb_any(skb); |
911 | } | 917 | } |
918 | new_trx_end: | ||
912 | if (rtlpriv->use_new_trx_flow) { | 919 | if (rtlpriv->use_new_trx_flow) { |
913 | rtlpci->rx_ring[hw_queue].next_rx_rp += 1; | 920 | rtlpci->rx_ring[hw_queue].next_rx_rp += 1; |
914 | rtlpci->rx_ring[hw_queue].next_rx_rp %= | 921 | rtlpci->rx_ring[hw_queue].next_rx_rp %= |
@@ -924,7 +931,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
924 | rtlpriv->enter_ps = false; | 931 | rtlpriv->enter_ps = false; |
925 | schedule_work(&rtlpriv->works.lps_change_work); | 932 | schedule_work(&rtlpriv->works.lps_change_work); |
926 | } | 933 | } |
927 | end: | ||
928 | skb = new_skb; | 934 | skb = new_skb; |
929 | no_new: | 935 | no_new: |
930 | if (rtlpriv->use_new_trx_flow) { | 936 | if (rtlpriv->use_new_trx_flow) { |
@@ -1688,6 +1694,15 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, | |||
1688 | } | 1694 | } |
1689 | } | 1695 | } |
1690 | 1696 | ||
1697 | if (rtlpriv->cfg->ops->get_available_desc && | ||
1698 | rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) { | ||
1699 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1700 | "get_available_desc fail\n"); | ||
1701 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, | ||
1702 | flags); | ||
1703 | return skb->len; | ||
1704 | } | ||
1705 | |||
1691 | if (ieee80211_is_data_qos(fc)) { | 1706 | if (ieee80211_is_data_qos(fc)) { |
1692 | tid = rtl_get_tid(skb); | 1707 | tid = rtl_get_tid(skb); |
1693 | if (sta) { | 1708 | if (sta) { |
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 5e832306dba9..d4567d12e07e 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h | |||
@@ -325,4 +325,11 @@ static inline void pci_write32_async(struct rtl_priv *rtlpriv, | |||
325 | writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); | 325 | writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); |
326 | } | 326 | } |
327 | 327 | ||
328 | static inline u16 calc_fifo_space(u16 rp, u16 wp) | ||
329 | { | ||
330 | if (rp <= wp) | ||
331 | return RTL_PCI_MAX_RX_COUNT - 1 + rp - wp; | ||
332 | return rp - wp - 1; | ||
333 | } | ||
334 | |||
328 | #endif | 335 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 551321728ae0..fe4b699a12f5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -1000,6 +1000,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) | |||
1000 | local_save_flags(flags); | 1000 | local_save_flags(flags); |
1001 | local_irq_enable(); | 1001 | local_irq_enable(); |
1002 | 1002 | ||
1003 | rtlhal->fw_ready = false; | ||
1003 | rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; | 1004 | rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; |
1004 | err = _rtl92cu_init_mac(hw); | 1005 | err = _rtl92cu_init_mac(hw); |
1005 | if (err) { | 1006 | if (err) { |
@@ -1013,6 +1014,8 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) | |||
1013 | err = 1; | 1014 | err = 1; |
1014 | goto exit; | 1015 | goto exit; |
1015 | } | 1016 | } |
1017 | |||
1018 | rtlhal->fw_ready = true; | ||
1016 | rtlhal->last_hmeboxnum = 0; /* h2c */ | 1019 | rtlhal->last_hmeboxnum = 0; /* h2c */ |
1017 | _rtl92cu_phy_param_tab_init(hw); | 1020 | _rtl92cu_phy_param_tab_init(hw); |
1018 | rtl92cu_phy_mac_config(hw); | 1021 | rtl92cu_phy_mac_config(hw); |
@@ -1509,6 +1512,7 @@ void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw) | |||
1509 | /* TODO: Modify later (Find the right parameters) | 1512 | /* TODO: Modify later (Find the right parameters) |
1510 | * NOTE: Fix test chip's bug (about contention windows's randomness) */ | 1513 | * NOTE: Fix test chip's bug (about contention windows's randomness) */ |
1511 | if ((mac->opmode == NL80211_IFTYPE_ADHOC) || | 1514 | if ((mac->opmode == NL80211_IFTYPE_ADHOC) || |
1515 | (mac->opmode == NL80211_IFTYPE_MESH_POINT) || | ||
1512 | (mac->opmode == NL80211_IFTYPE_AP)) { | 1516 | (mac->opmode == NL80211_IFTYPE_AP)) { |
1513 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); | 1517 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); |
1514 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); | 1518 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c index 45c128b91f7f..c5d4b8013cde 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c | |||
@@ -666,7 +666,6 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
666 | struct sk_buff *skb = NULL; | 666 | struct sk_buff *skb = NULL; |
667 | 667 | ||
668 | u32 totalpacketlen; | 668 | u32 totalpacketlen; |
669 | bool rtstatus; | ||
670 | u8 u1rsvdpageloc[5] = { 0 }; | 669 | u8 u1rsvdpageloc[5] = { 0 }; |
671 | bool b_dlok = false; | 670 | bool b_dlok = false; |
672 | 671 | ||
@@ -728,10 +727,7 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
728 | memcpy((u8 *)skb_put(skb, totalpacketlen), | 727 | memcpy((u8 *)skb_put(skb, totalpacketlen), |
729 | &reserved_page_packet, totalpacketlen); | 728 | &reserved_page_packet, totalpacketlen); |
730 | 729 | ||
731 | rtstatus = rtl_cmd_send_packet(hw, skb); | 730 | b_dlok = true; |
732 | |||
733 | if (rtstatus) | ||
734 | b_dlok = true; | ||
735 | 731 | ||
736 | if (b_dlok) { | 732 | if (b_dlok) { |
737 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , | 733 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c index 1a87edca2c3f..b461b3128da5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | |||
@@ -85,29 +85,6 @@ static void _rtl92ee_enable_bcn_sub_func(struct ieee80211_hw *hw) | |||
85 | _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); | 85 | _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); |
86 | } | 86 | } |
87 | 87 | ||
88 | static void _rtl92ee_return_beacon_queue_skb(struct ieee80211_hw *hw) | ||
89 | { | ||
90 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
91 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
92 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
93 | unsigned long flags; | ||
94 | |||
95 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); | ||
96 | while (skb_queue_len(&ring->queue)) { | ||
97 | struct rtl_tx_buffer_desc *entry = | ||
98 | &ring->buffer_desc[ring->idx]; | ||
99 | struct sk_buff *skb = __skb_dequeue(&ring->queue); | ||
100 | |||
101 | pci_unmap_single(rtlpci->pdev, | ||
102 | rtlpriv->cfg->ops->get_desc( | ||
103 | (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), | ||
104 | skb->len, PCI_DMA_TODEVICE); | ||
105 | kfree_skb(skb); | ||
106 | ring->idx = (ring->idx + 1) % ring->entries; | ||
107 | } | ||
108 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); | ||
109 | } | ||
110 | |||
111 | static void _rtl92ee_disable_bcn_sub_func(struct ieee80211_hw *hw) | 88 | static void _rtl92ee_disable_bcn_sub_func(struct ieee80211_hw *hw) |
112 | { | 89 | { |
113 | _rtl92ee_set_bcn_ctrl_reg(hw, BIT(1), 0); | 90 | _rtl92ee_set_bcn_ctrl_reg(hw, BIT(1), 0); |
@@ -403,9 +380,6 @@ static void _rtl92ee_download_rsvd_page(struct ieee80211_hw *hw) | |||
403 | rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, | 380 | rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, |
404 | bcnvalid_reg | BIT(0)); | 381 | bcnvalid_reg | BIT(0)); |
405 | 382 | ||
406 | /* Return Beacon TCB */ | ||
407 | _rtl92ee_return_beacon_queue_skb(hw); | ||
408 | |||
409 | /* download rsvd page */ | 383 | /* download rsvd page */ |
410 | rtl92ee_set_fw_rsvdpagepkt(hw, false); | 384 | rtl92ee_set_fw_rsvdpagepkt(hw, false); |
411 | 385 | ||
@@ -1163,6 +1137,139 @@ void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw) | |||
1163 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); | 1137 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); |
1164 | } | 1138 | } |
1165 | 1139 | ||
1140 | static bool _rtl8192ee_check_pcie_dma_hang(struct rtl_priv *rtlpriv) | ||
1141 | { | ||
1142 | u8 tmp; | ||
1143 | |||
1144 | /* write reg 0x350 Bit[26]=1. Enable debug port. */ | ||
1145 | tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); | ||
1146 | if (!(tmp & BIT(2))) { | ||
1147 | rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3, | ||
1148 | tmp | BIT(2)); | ||
1149 | mdelay(100); /* Suggested by DD Justin_tsai. */ | ||
1150 | } | ||
1151 | |||
1152 | /* read reg 0x350 Bit[25] if 1 : RX hang | ||
1153 | * read reg 0x350 Bit[24] if 1 : TX hang | ||
1154 | */ | ||
1155 | tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); | ||
1156 | if ((tmp & BIT(0)) || (tmp & BIT(1))) { | ||
1157 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1158 | "CheckPcieDMAHang8192EE(): true!!\n"); | ||
1159 | return true; | ||
1160 | } | ||
1161 | return false; | ||
1162 | } | ||
1163 | |||
1164 | static void _rtl8192ee_reset_pcie_interface_dma(struct rtl_priv *rtlpriv, | ||
1165 | bool mac_power_on) | ||
1166 | { | ||
1167 | u8 tmp; | ||
1168 | bool release_mac_rx_pause; | ||
1169 | u8 backup_pcie_dma_pause; | ||
1170 | |||
1171 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1172 | "ResetPcieInterfaceDMA8192EE()\n"); | ||
1173 | |||
1174 | /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03" | ||
1175 | * released by SD1 Alan. | ||
1176 | */ | ||
1177 | |||
1178 | /* 1. disable register write lock | ||
1179 | * write 0x1C bit[1:0] = 2'h0 | ||
1180 | * write 0xCC bit[2] = 1'b1 | ||
1181 | */ | ||
1182 | tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); | ||
1183 | tmp &= ~(BIT(1) | BIT(0)); | ||
1184 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); | ||
1185 | tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); | ||
1186 | tmp |= BIT(2); | ||
1187 | rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); | ||
1188 | |||
1189 | /* 2. Check and pause TRX DMA | ||
1190 | * write 0x284 bit[18] = 1'b1 | ||
1191 | * write 0x301 = 0xFF | ||
1192 | */ | ||
1193 | tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1194 | if (tmp & BIT(2)) { | ||
1195 | /* Already pause before the function for another reason. */ | ||
1196 | release_mac_rx_pause = false; | ||
1197 | } else { | ||
1198 | rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); | ||
1199 | release_mac_rx_pause = true; | ||
1200 | } | ||
1201 | |||
1202 | backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); | ||
1203 | if (backup_pcie_dma_pause != 0xFF) | ||
1204 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); | ||
1205 | |||
1206 | if (mac_power_on) { | ||
1207 | /* 3. reset TRX function | ||
1208 | * write 0x100 = 0x00 | ||
1209 | */ | ||
1210 | rtl_write_byte(rtlpriv, REG_CR, 0); | ||
1211 | } | ||
1212 | |||
1213 | /* 4. Reset PCIe DMA | ||
1214 | * write 0x003 bit[0] = 0 | ||
1215 | */ | ||
1216 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
1217 | tmp &= ~(BIT(0)); | ||
1218 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); | ||
1219 | |||
1220 | /* 5. Enable PCIe DMA | ||
1221 | * write 0x003 bit[0] = 1 | ||
1222 | */ | ||
1223 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
1224 | tmp |= BIT(0); | ||
1225 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); | ||
1226 | |||
1227 | if (mac_power_on) { | ||
1228 | /* 6. enable TRX function | ||
1229 | * write 0x100 = 0xFF | ||
1230 | */ | ||
1231 | rtl_write_byte(rtlpriv, REG_CR, 0xFF); | ||
1232 | |||
1233 | /* We should init LLT & RQPN and | ||
1234 | * prepare Tx/Rx descrptor address later | ||
1235 | * because MAC function is reset. | ||
1236 | */ | ||
1237 | } | ||
1238 | |||
1239 | /* 7. Restore PCIe autoload down bit | ||
1240 | * write 0xF8 bit[17] = 1'b1 | ||
1241 | */ | ||
1242 | tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); | ||
1243 | tmp |= BIT(1); | ||
1244 | rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); | ||
1245 | |||
1246 | /* In MAC power on state, BB and RF maybe in ON state, | ||
1247 | * if we release TRx DMA here | ||
1248 | * it will cause packets to be started to Tx/Rx, | ||
1249 | * so we release Tx/Rx DMA later. | ||
1250 | */ | ||
1251 | if (!mac_power_on) { | ||
1252 | /* 8. release TRX DMA | ||
1253 | * write 0x284 bit[18] = 1'b0 | ||
1254 | * write 0x301 = 0x00 | ||
1255 | */ | ||
1256 | if (release_mac_rx_pause) { | ||
1257 | tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1258 | rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, | ||
1259 | (tmp & (~BIT(2)))); | ||
1260 | } | ||
1261 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, | ||
1262 | backup_pcie_dma_pause); | ||
1263 | } | ||
1264 | |||
1265 | /* 9. lock system register | ||
1266 | * write 0xCC bit[2] = 1'b0 | ||
1267 | */ | ||
1268 | tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); | ||
1269 | tmp &= ~(BIT(2)); | ||
1270 | rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); | ||
1271 | } | ||
1272 | |||
1166 | int rtl92ee_hw_init(struct ieee80211_hw *hw) | 1273 | int rtl92ee_hw_init(struct ieee80211_hw *hw) |
1167 | { | 1274 | { |
1168 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1275 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1188,6 +1295,13 @@ int rtl92ee_hw_init(struct ieee80211_hw *hw) | |||
1188 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; | 1295 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; |
1189 | } | 1296 | } |
1190 | 1297 | ||
1298 | if (_rtl8192ee_check_pcie_dma_hang(rtlpriv)) { | ||
1299 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "92ee dma hang!\n"); | ||
1300 | _rtl8192ee_reset_pcie_interface_dma(rtlpriv, | ||
1301 | rtlhal->mac_func_enable); | ||
1302 | rtlhal->mac_func_enable = false; | ||
1303 | } | ||
1304 | |||
1191 | rtstatus = _rtl92ee_init_mac(hw); | 1305 | rtstatus = _rtl92ee_init_mac(hw); |
1192 | 1306 | ||
1193 | rtl_write_byte(rtlpriv, 0x577, 0x03); | 1307 | rtl_write_byte(rtlpriv, 0x577, 0x03); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h index 3f2a9596e7cd..1eaa1fab550d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h | |||
@@ -77,9 +77,11 @@ | |||
77 | #define REG_HIMRE 0x00B8 | 77 | #define REG_HIMRE 0x00B8 |
78 | #define REG_HISRE 0x00BC | 78 | #define REG_HISRE 0x00BC |
79 | 79 | ||
80 | #define REG_PMC_DBG_CTRL2 0x00CC | ||
80 | #define REG_EFUSE_ACCESS 0x00CF | 81 | #define REG_EFUSE_ACCESS 0x00CF |
81 | #define REG_HPON_FSM 0x00EC | 82 | #define REG_HPON_FSM 0x00EC |
82 | #define REG_SYS_CFG1 0x00F0 | 83 | #define REG_SYS_CFG1 0x00F0 |
84 | #define REG_MAC_PHY_CTRL_NORMAL 0x00F8 | ||
83 | #define REG_SYS_CFG2 0x00FC | 85 | #define REG_SYS_CFG2 0x00FC |
84 | 86 | ||
85 | #define REG_CR 0x0100 | 87 | #define REG_CR 0x0100 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c index 9b5a7d5be121..c31c6bfb536d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c | |||
@@ -113,8 +113,6 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) | |||
113 | RCR_HTC_LOC_CTRL | | 113 | RCR_HTC_LOC_CTRL | |
114 | RCR_AMF | | 114 | RCR_AMF | |
115 | RCR_ACF | | 115 | RCR_ACF | |
116 | RCR_ADF | | ||
117 | RCR_AICV | | ||
118 | RCR_ACRC32 | | 116 | RCR_ACRC32 | |
119 | RCR_AB | | 117 | RCR_AB | |
120 | RCR_AM | | 118 | RCR_AM | |
@@ -241,6 +239,7 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = { | |||
241 | .set_desc = rtl92ee_set_desc, | 239 | .set_desc = rtl92ee_set_desc, |
242 | .get_desc = rtl92ee_get_desc, | 240 | .get_desc = rtl92ee_get_desc, |
243 | .is_tx_desc_closed = rtl92ee_is_tx_desc_closed, | 241 | .is_tx_desc_closed = rtl92ee_is_tx_desc_closed, |
242 | .get_available_desc = rtl92ee_get_available_desc, | ||
244 | .tx_polling = rtl92ee_tx_polling, | 243 | .tx_polling = rtl92ee_tx_polling, |
245 | .enable_hw_sec = rtl92ee_enable_hw_security_config, | 244 | .enable_hw_sec = rtl92ee_enable_hw_security_config, |
246 | .set_key = rtl92ee_set_key, | 245 | .set_key = rtl92ee_set_key, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c index 55d1da5e162b..d39ee67f6113 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c | |||
@@ -354,6 +354,10 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, | |||
354 | struct ieee80211_hdr *hdr; | 354 | struct ieee80211_hdr *hdr; |
355 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); | 355 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); |
356 | 356 | ||
357 | if (GET_RX_STATUS_DESC_RPT_SEL(pdesc) == 0) | ||
358 | status->packet_report_type = NORMAL_RX; | ||
359 | else | ||
360 | status->packet_report_type = C2H_PACKET; | ||
357 | status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); | 361 | status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); |
358 | status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * | 362 | status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * |
359 | RX_DRV_INFO_SIZE_UNIT; | 363 | RX_DRV_INFO_SIZE_UNIT; |
@@ -495,14 +499,7 @@ u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, u8 queue_index) | |||
495 | if (!start_rx) | 499 | if (!start_rx) |
496 | return 0; | 500 | return 0; |
497 | 501 | ||
498 | if ((last_read_point > (RX_DESC_NUM_92E / 2)) && | 502 | remind_cnt = calc_fifo_space(read_point, write_point); |
499 | (read_point <= (RX_DESC_NUM_92E / 2))) { | ||
500 | remind_cnt = RX_DESC_NUM_92E - write_point; | ||
501 | } else { | ||
502 | remind_cnt = (read_point >= write_point) ? | ||
503 | (read_point - write_point) : | ||
504 | (RX_DESC_NUM_92E - write_point + read_point); | ||
505 | } | ||
506 | 503 | ||
507 | if (remind_cnt == 0) | 504 | if (remind_cnt == 0) |
508 | return 0; | 505 | return 0; |
@@ -551,6 +548,26 @@ static u16 get_desc_addr_fr_q_idx(u16 queue_index) | |||
551 | return desc_address; | 548 | return desc_address; |
552 | } | 549 | } |
553 | 550 | ||
551 | u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx) | ||
552 | { | ||
553 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
554 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
555 | u16 point_diff = 0; | ||
556 | u16 current_tx_read_point = 0, current_tx_write_point = 0; | ||
557 | u32 tmp_4byte; | ||
558 | |||
559 | tmp_4byte = rtl_read_dword(rtlpriv, | ||
560 | get_desc_addr_fr_q_idx(q_idx)); | ||
561 | current_tx_read_point = (u16)((tmp_4byte >> 16) & 0x0fff); | ||
562 | current_tx_write_point = (u16)((tmp_4byte) & 0x0fff); | ||
563 | |||
564 | point_diff = calc_fifo_space(current_tx_read_point, | ||
565 | current_tx_write_point); | ||
566 | |||
567 | rtlpci->tx_ring[q_idx].avl_desc = point_diff; | ||
568 | return point_diff; | ||
569 | } | ||
570 | |||
554 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, | 571 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, |
555 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, | 572 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, |
556 | struct sk_buff *skb, dma_addr_t addr) | 573 | struct sk_buff *skb, dma_addr_t addr) |
@@ -1027,8 +1044,7 @@ bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) | |||
1027 | static u8 stop_report_cnt; | 1044 | static u8 stop_report_cnt; |
1028 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; | 1045 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; |
1029 | 1046 | ||
1030 | /*checking Read/Write Point each interrupt wastes CPU */ | 1047 | { |
1031 | if (stop_report_cnt > 15 || !rtlpriv->link_info.busytraffic) { | ||
1032 | u16 point_diff = 0; | 1048 | u16 point_diff = 0; |
1033 | u16 cur_tx_rp, cur_tx_wp; | 1049 | u16 cur_tx_rp, cur_tx_wp; |
1034 | u32 tmpu32 = 0; | 1050 | u32 tmpu32 = 0; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h index 48504c25fffb..8f78ac9e6040 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h | |||
@@ -542,6 +542,8 @@ | |||
542 | LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) | 542 | LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) |
543 | #define GET_RX_DESC_RX_IS_QOS(__pdesc) \ | 543 | #define GET_RX_DESC_RX_IS_QOS(__pdesc) \ |
544 | LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) | 544 | LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) |
545 | #define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ | ||
546 | LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) | ||
545 | 547 | ||
546 | #define GET_RX_DESC_RXMCS(__pdesc) \ | 548 | #define GET_RX_DESC_RXMCS(__pdesc) \ |
547 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) | 549 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) |
@@ -829,6 +831,7 @@ void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc, | |||
829 | u8 queue_index); | 831 | u8 queue_index); |
830 | u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, | 832 | u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, |
831 | u8 queue_index); | 833 | u8 queue_index); |
834 | u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 queue_index); | ||
832 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, | 835 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, |
833 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, | 836 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, |
834 | struct sk_buff *skb, dma_addr_t addr); | 837 | struct sk_buff *skb, dma_addr_t addr); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index b53d9dd7a595..51572912c53d 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -2182,6 +2182,7 @@ struct rtl_hal_ops { | |||
2182 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, | 2182 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, |
2183 | struct rtl_wow_pattern *rtl_pattern, | 2183 | struct rtl_wow_pattern *rtl_pattern, |
2184 | u8 index); | 2184 | u8 index); |
2185 | u16 (*get_available_desc)(struct ieee80211_hw *hw, u8 q_idx); | ||
2185 | }; | 2186 | }; |
2186 | 2187 | ||
2187 | struct rtl_intf_ops { | 2188 | struct rtl_intf_ops { |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 2fead3820849..1e180c400f17 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -90,25 +90,6 @@ found: | |||
90 | } | 90 | } |
91 | #endif /* CONFIG_SSB_PCMCIAHOST */ | 91 | #endif /* CONFIG_SSB_PCMCIAHOST */ |
92 | 92 | ||
93 | #ifdef CONFIG_SSB_SDIOHOST | ||
94 | struct ssb_bus *ssb_sdio_func_to_bus(struct sdio_func *func) | ||
95 | { | ||
96 | struct ssb_bus *bus; | ||
97 | |||
98 | ssb_buses_lock(); | ||
99 | list_for_each_entry(bus, &buses, list) { | ||
100 | if (bus->bustype == SSB_BUSTYPE_SDIO && | ||
101 | bus->host_sdio == func) | ||
102 | goto found; | ||
103 | } | ||
104 | bus = NULL; | ||
105 | found: | ||
106 | ssb_buses_unlock(); | ||
107 | |||
108 | return bus; | ||
109 | } | ||
110 | #endif /* CONFIG_SSB_SDIOHOST */ | ||
111 | |||
112 | int ssb_for_each_bus_call(unsigned long data, | 93 | int ssb_for_each_bus_call(unsigned long data, |
113 | int (*func)(struct ssb_bus *bus, unsigned long data)) | 94 | int (*func)(struct ssb_bus *bus, unsigned long data)) |
114 | { | 95 | { |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index eb1c6a47b67f..994739da827f 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -318,6 +318,7 @@ struct bcma_bus { | |||
318 | const struct bcma_host_ops *ops; | 318 | const struct bcma_host_ops *ops; |
319 | 319 | ||
320 | enum bcma_hosttype hosttype; | 320 | enum bcma_hosttype hosttype; |
321 | bool host_is_pcie2; /* Used for BCMA_HOSTTYPE_PCI only */ | ||
321 | union { | 322 | union { |
322 | /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ | 323 | /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ |
323 | struct pci_dev *host_pci; | 324 | struct pci_dev *host_pci; |
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h index 0333e605ea0d..3f809ae372c4 100644 --- a/include/linux/bcma/bcma_driver_pci.h +++ b/include/linux/bcma/bcma_driver_pci.h | |||
@@ -223,6 +223,7 @@ struct bcma_drv_pci_host { | |||
223 | 223 | ||
224 | struct bcma_drv_pci { | 224 | struct bcma_drv_pci { |
225 | struct bcma_device *core; | 225 | struct bcma_device *core; |
226 | u8 early_setup_done:1; | ||
226 | u8 setup_done:1; | 227 | u8 setup_done:1; |
227 | u8 hostmode:1; | 228 | u8 hostmode:1; |
228 | 229 | ||
@@ -237,6 +238,7 @@ struct bcma_drv_pci { | |||
237 | #define pcicore_write16(pc, offset, val) bcma_write16((pc)->core, offset, val) | 238 | #define pcicore_write16(pc, offset, val) bcma_write16((pc)->core, offset, val) |
238 | #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) | 239 | #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) |
239 | 240 | ||
241 | extern void bcma_core_pci_early_init(struct bcma_drv_pci *pc); | ||
240 | extern void bcma_core_pci_init(struct bcma_drv_pci *pc); | 242 | extern void bcma_core_pci_init(struct bcma_drv_pci *pc); |
241 | extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, | 243 | extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, |
242 | struct bcma_device *core, bool enable); | 244 | struct bcma_device *core, bool enable); |
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index e64ae7bf80a1..ebd5c1fcdea4 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h | |||
@@ -64,6 +64,8 @@ | |||
64 | #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ | 64 | #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ |
65 | #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ | 65 | #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ |
66 | 66 | ||
67 | #define BCMA_PCIE2_BAR0_WIN2 0x70 | ||
68 | |||
67 | /* SiliconBackplane Address Map. | 69 | /* SiliconBackplane Address Map. |
68 | * All regions may not exist on all chips. | 70 | * All regions may not exist on all chips. |
69 | */ | 71 | */ |
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index f7b9100686c3..c0f707ac192b 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -173,6 +173,7 @@ | |||
173 | #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) | 173 | #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) |
174 | #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) | 174 | #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) |
175 | #define SSB_SPROMSIZE_WORDS_R10 230 | 175 | #define SSB_SPROMSIZE_WORDS_R10 230 |
176 | #define SSB_SPROMSIZE_WORDS_R11 234 | ||
176 | #define SSB_SPROM_BASE1 0x1000 | 177 | #define SSB_SPROM_BASE1 0x1000 |
177 | #define SSB_SPROM_BASE31 0x0800 | 178 | #define SSB_SPROM_BASE31 0x0800 |
178 | #define SSB_SPROM_REVISION 0x007E | 179 | #define SSB_SPROM_REVISION 0x007E |