diff options
author | David S. Miller <davem@davemloft.net> | 2016-03-13 15:03:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-13 15:03:34 -0400 |
commit | 00e3d2ef184d005db4e14d64f5870d556183e638 (patch) | |
tree | 25412f18891e3f09e358c436a2251bccc61429af | |
parent | f22f5f6060584ac66a7a43f644788fda8fc7b1f8 (diff) | |
parent | 836856e3bd61d0644e5178a2c1b51d90459e2788 (diff) |
Merge tag 'wireless-drivers-next-for-davem-2016-03-09' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says:
====================
wireless-drivers patches for 4.6
Major changes:
ath10k
* dt: add bindings for ipq4019 wifi block
* start adding support for qca4019 chip
ath9k
* add device ID for Toshiba WLM-20U2/GN-1080
* allow more than one interface on DFS channels
bcma
* move flash detection code to ChipCommon core driver
brcmfmac
* IPv6 Neighbor discovery offload
* driver settings that can be populated from different sources
* country code setting in firmware
* length checks to validate firmware events
* new way to determine device memory size needed for BCM4366
* various offloads during Wake on Wireless LAN (WoWLAN)
* full Management Frame Protection (MFP) support
iwlwifi
* add support for thermal device / cooling device
* improvements in scheduled scan without profiles
* new firmware support (-21.ucode)
* add MSIX support for 9000 devices
* enable MU-MIMO and take care of firmware restart
* add support for large SKBs in mvm to reach A-MSDU
* add support for filtering frames from a BA session
* start implementing the new Rx path for 9000 devices
* enable the new Radio Resource Management (RRM) nl80211 feature flag
* add a new module paramater to disable VHT
* build infrastructure for Dynamic Queue Allocation
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
162 files changed, 6422 insertions, 1819 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt index edefc26c6204..96aae6b4f736 100644 --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt | |||
@@ -1,17 +1,46 @@ | |||
1 | * Qualcomm Atheros ath10k wireless devices | 1 | * Qualcomm Atheros ath10k wireless devices |
2 | 2 | ||
3 | For ath10k devices the calibration data can be provided through Device | ||
4 | Tree. The node is a child node of the PCI controller. | ||
5 | |||
6 | Required properties: | 3 | Required properties: |
7 | -compatible : Should be "qcom,ath10k" | 4 | - compatible: Should be one of the following: |
5 | * "qcom,ath10k" | ||
6 | * "qcom,ipq4019-wifi" | ||
7 | |||
8 | PCI based devices uses compatible string "qcom,ath10k" and takes only | ||
9 | calibration data via "qcom,ath10k-calibration-data". Rest of the properties | ||
10 | are not applicable for PCI based devices. | ||
11 | |||
12 | AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi" | ||
13 | and also uses most of the properties defined in this doc. | ||
8 | 14 | ||
9 | Optional properties: | 15 | Optional properties: |
16 | - reg: Address and length of the register set for the device. | ||
17 | - resets: Must contain an entry for each entry in reset-names. | ||
18 | See ../reset/reseti.txt for details. | ||
19 | - reset-names: Must include the list of following reset names, | ||
20 | "wifi_cpu_init" | ||
21 | "wifi_radio_srif" | ||
22 | "wifi_radio_warm" | ||
23 | "wifi_radio_cold" | ||
24 | "wifi_core_warm" | ||
25 | "wifi_core_cold" | ||
26 | - clocks: List of clock specifiers, must contain an entry for each required | ||
27 | entry in clock-names. | ||
28 | - clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref", | ||
29 | "wifi_wcss_rtc". | ||
30 | - interrupts: List of interrupt lines. Must contain an entry | ||
31 | for each entry in the interrupt-names property. | ||
32 | - interrupt-names: Must include the entries for MSI interrupt | ||
33 | names ("msi0" to "msi15") and legacy interrupt | ||
34 | name ("legacy"), | ||
35 | - qcom,msi_addr: MSI interrupt address. | ||
36 | - qcom,msi_base: Base value to add before writing MSI data into | ||
37 | MSI address register. | ||
10 | - qcom,ath10k-calibration-data : calibration data as an array, the | 38 | - qcom,ath10k-calibration-data : calibration data as an array, the |
11 | length can vary between hw versions | 39 | length can vary between hw versions |
12 | 40 | ||
41 | Example (to supply the calibration data alone): | ||
13 | 42 | ||
14 | Example: | 43 | In this example, the node is defined as child node of the PCI controller. |
15 | 44 | ||
16 | pci { | 45 | pci { |
17 | pcie@0 { | 46 | pcie@0 { |
@@ -28,3 +57,53 @@ pci { | |||
28 | }; | 57 | }; |
29 | }; | 58 | }; |
30 | }; | 59 | }; |
60 | |||
61 | Example (to supply ipq4019 SoC wifi block details): | ||
62 | |||
63 | wifi0: wifi@a000000 { | ||
64 | compatible = "qcom,ipq4019-wifi"; | ||
65 | reg = <0xa000000 0x200000>; | ||
66 | resets = <&gcc WIFI0_CPU_INIT_RESET>, | ||
67 | <&gcc WIFI0_RADIO_SRIF_RESET>, | ||
68 | <&gcc WIFI0_RADIO_WARM_RESET>, | ||
69 | <&gcc WIFI0_RADIO_COLD_RESET>, | ||
70 | <&gcc WIFI0_CORE_WARM_RESET>, | ||
71 | <&gcc WIFI0_CORE_COLD_RESET>; | ||
72 | reset-names = "wifi_cpu_init", | ||
73 | "wifi_radio_srif", | ||
74 | "wifi_radio_warm", | ||
75 | "wifi_radio_cold", | ||
76 | "wifi_core_warm", | ||
77 | "wifi_core_cold"; | ||
78 | clocks = <&gcc GCC_WCSS2G_CLK>, | ||
79 | <&gcc GCC_WCSS2G_REF_CLK>, | ||
80 | <&gcc GCC_WCSS2G_RTC_CLK>; | ||
81 | clock-names = "wifi_wcss_cmd", | ||
82 | "wifi_wcss_ref", | ||
83 | "wifi_wcss_rtc"; | ||
84 | interrupts = <0 0x20 0x1>, | ||
85 | <0 0x21 0x1>, | ||
86 | <0 0x22 0x1>, | ||
87 | <0 0x23 0x1>, | ||
88 | <0 0x24 0x1>, | ||
89 | <0 0x25 0x1>, | ||
90 | <0 0x26 0x1>, | ||
91 | <0 0x27 0x1>, | ||
92 | <0 0x28 0x1>, | ||
93 | <0 0x29 0x1>, | ||
94 | <0 0x2a 0x1>, | ||
95 | <0 0x2b 0x1>, | ||
96 | <0 0x2c 0x1>, | ||
97 | <0 0x2d 0x1>, | ||
98 | <0 0x2e 0x1>, | ||
99 | <0 0x2f 0x1>, | ||
100 | <0 0xa8 0x0>; | ||
101 | interrupt-names = "msi0", "msi1", "msi2", "msi3", | ||
102 | "msi4", "msi5", "msi6", "msi7", | ||
103 | "msi8", "msi9", "msi10", "msi11", | ||
104 | "msi12", "msi13", "msi14", "msi15", | ||
105 | "legacy"; | ||
106 | qcom,msi_addr = <0x0b006040>; | ||
107 | qcom,msi_base = <0x40>; | ||
108 | qcom,ath10k-calibration-data = [ 01 02 03 ... ]; | ||
109 | }; | ||
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index 023d448ed3fa..efdc2ae8441a 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig | |||
@@ -70,6 +70,11 @@ config BCMA_DRIVER_MIPS | |||
70 | 70 | ||
71 | If unsure, say N | 71 | If unsure, say N |
72 | 72 | ||
73 | config BCMA_PFLASH | ||
74 | bool | ||
75 | depends on BCMA_DRIVER_MIPS | ||
76 | default y | ||
77 | |||
73 | config BCMA_SFLASH | 78 | config BCMA_SFLASH |
74 | bool | 79 | bool |
75 | depends on BCMA_DRIVER_MIPS | 80 | depends on BCMA_DRIVER_MIPS |
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile index f32af9b76bcd..087948a1d20d 100644 --- a/drivers/bcma/Makefile +++ b/drivers/bcma/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | bcma-y += main.o scan.o core.o sprom.o | 1 | bcma-y += main.o scan.o core.o sprom.o |
2 | bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o | 2 | bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o |
3 | bcma-y += driver_chipcommon_b.o | 3 | bcma-y += driver_chipcommon_b.o |
4 | bcma-$(CONFIG_BCMA_PFLASH) += driver_chipcommon_pflash.o | ||
4 | bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o | 5 | bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o |
5 | bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o | 6 | bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o |
6 | bcma-$(CONFIG_BCMA_DRIVER_PCI) += driver_pci.o | 7 | bcma-$(CONFIG_BCMA_DRIVER_PCI) += driver_pci.o |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 7e4ddfb076d3..eda09090cb52 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -47,9 +47,6 @@ int bcma_sprom_get(struct bcma_bus *bus); | |||
47 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); | 47 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); |
48 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); | 48 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); |
49 | void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); | 49 | void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); |
50 | #ifdef CONFIG_BCMA_DRIVER_MIPS | ||
51 | extern struct platform_device bcma_pflash_dev; | ||
52 | #endif /* CONFIG_BCMA_DRIVER_MIPS */ | ||
53 | 50 | ||
54 | /* driver_chipcommon_b.c */ | 51 | /* driver_chipcommon_b.c */ |
55 | int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb); | 52 | int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb); |
@@ -61,6 +58,21 @@ void bcma_pmu_init(struct bcma_drv_cc *cc); | |||
61 | u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc); | 58 | u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc); |
62 | u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc); | 59 | u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc); |
63 | 60 | ||
61 | /************************************************** | ||
62 | * driver_chipcommon_sflash.c | ||
63 | **************************************************/ | ||
64 | |||
65 | #ifdef CONFIG_BCMA_PFLASH | ||
66 | extern struct platform_device bcma_pflash_dev; | ||
67 | int bcma_pflash_init(struct bcma_drv_cc *cc); | ||
68 | #else | ||
69 | static inline int bcma_pflash_init(struct bcma_drv_cc *cc) | ||
70 | { | ||
71 | bcma_err(cc->core->bus, "Parallel flash not supported\n"); | ||
72 | return 0; | ||
73 | } | ||
74 | #endif /* CONFIG_BCMA_PFLASH */ | ||
75 | |||
64 | #ifdef CONFIG_BCMA_SFLASH | 76 | #ifdef CONFIG_BCMA_SFLASH |
65 | /* driver_chipcommon_sflash.c */ | 77 | /* driver_chipcommon_sflash.c */ |
66 | int bcma_sflash_init(struct bcma_drv_cc *cc); | 78 | int bcma_sflash_init(struct bcma_drv_cc *cc); |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index b0f44a2937b9..921ce1834673 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -115,6 +115,33 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) | |||
115 | return 0; | 115 | return 0; |
116 | } | 116 | } |
117 | 117 | ||
118 | static void bcma_core_chipcommon_flash_detect(struct bcma_drv_cc *cc) | ||
119 | { | ||
120 | struct bcma_bus *bus = cc->core->bus; | ||
121 | |||
122 | switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | ||
123 | case BCMA_CC_FLASHT_STSER: | ||
124 | case BCMA_CC_FLASHT_ATSER: | ||
125 | bcma_debug(bus, "Found serial flash\n"); | ||
126 | bcma_sflash_init(cc); | ||
127 | break; | ||
128 | case BCMA_CC_FLASHT_PARA: | ||
129 | bcma_debug(bus, "Found parallel flash\n"); | ||
130 | bcma_pflash_init(cc); | ||
131 | break; | ||
132 | default: | ||
133 | bcma_err(bus, "Flash type not supported\n"); | ||
134 | } | ||
135 | |||
136 | if (cc->core->id.rev == 38 || | ||
137 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | ||
138 | if (cc->capabilities & BCMA_CC_CAP_NFLASH) { | ||
139 | bcma_debug(bus, "Found NAND flash\n"); | ||
140 | bcma_nflash_init(cc); | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
118 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) | 145 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) |
119 | { | 146 | { |
120 | struct bcma_bus *bus = cc->core->bus; | 147 | struct bcma_bus *bus = cc->core->bus; |
@@ -136,6 +163,9 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) | |||
136 | if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC) | 163 | if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC) |
137 | bcma_chipco_serial_init(cc); | 164 | bcma_chipco_serial_init(cc); |
138 | 165 | ||
166 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | ||
167 | bcma_core_chipcommon_flash_detect(cc); | ||
168 | |||
139 | cc->early_setup_done = true; | 169 | cc->early_setup_done = true; |
140 | } | 170 | } |
141 | 171 | ||
diff --git a/drivers/bcma/driver_chipcommon_pflash.c b/drivers/bcma/driver_chipcommon_pflash.c new file mode 100644 index 000000000000..3b497c9ee0d4 --- /dev/null +++ b/drivers/bcma/driver_chipcommon_pflash.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * ChipCommon parallel flash | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include "bcma_private.h" | ||
9 | |||
10 | #include <linux/bcma/bcma.h> | ||
11 | #include <linux/mtd/physmap.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | static const char * const part_probes[] = { "bcm47xxpart", NULL }; | ||
15 | |||
16 | static struct physmap_flash_data bcma_pflash_data = { | ||
17 | .part_probe_types = part_probes, | ||
18 | }; | ||
19 | |||
20 | static struct resource bcma_pflash_resource = { | ||
21 | .name = "bcma_pflash", | ||
22 | .flags = IORESOURCE_MEM, | ||
23 | }; | ||
24 | |||
25 | struct platform_device bcma_pflash_dev = { | ||
26 | .name = "physmap-flash", | ||
27 | .dev = { | ||
28 | .platform_data = &bcma_pflash_data, | ||
29 | }, | ||
30 | .resource = &bcma_pflash_resource, | ||
31 | .num_resources = 1, | ||
32 | }; | ||
33 | |||
34 | int bcma_pflash_init(struct bcma_drv_cc *cc) | ||
35 | { | ||
36 | struct bcma_pflash *pflash = &cc->pflash; | ||
37 | |||
38 | pflash->present = true; | ||
39 | |||
40 | if (!(bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & BCMA_CC_FLASH_CFG_DS)) | ||
41 | bcma_pflash_data.width = 1; | ||
42 | else | ||
43 | bcma_pflash_data.width = 2; | ||
44 | |||
45 | bcma_pflash_resource.start = BCMA_SOC_FLASH2; | ||
46 | bcma_pflash_resource.end = BCMA_SOC_FLASH2 + BCMA_SOC_FLASH2_SZ; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index a40a203314db..96f171328200 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c | |||
@@ -14,8 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/bcma/bcma.h> | 15 | #include <linux/bcma/bcma.h> |
16 | 16 | ||
17 | #include <linux/mtd/physmap.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/serial.h> | 17 | #include <linux/serial.h> |
20 | #include <linux/serial_core.h> | 18 | #include <linux/serial_core.h> |
21 | #include <linux/serial_reg.h> | 19 | #include <linux/serial_reg.h> |
@@ -32,26 +30,6 @@ enum bcma_boot_dev { | |||
32 | BCMA_BOOT_DEV_NAND, | 30 | BCMA_BOOT_DEV_NAND, |
33 | }; | 31 | }; |
34 | 32 | ||
35 | static const char * const part_probes[] = { "bcm47xxpart", NULL }; | ||
36 | |||
37 | static struct physmap_flash_data bcma_pflash_data = { | ||
38 | .part_probe_types = part_probes, | ||
39 | }; | ||
40 | |||
41 | static struct resource bcma_pflash_resource = { | ||
42 | .name = "bcma_pflash", | ||
43 | .flags = IORESOURCE_MEM, | ||
44 | }; | ||
45 | |||
46 | struct platform_device bcma_pflash_dev = { | ||
47 | .name = "physmap-flash", | ||
48 | .dev = { | ||
49 | .platform_data = &bcma_pflash_data, | ||
50 | }, | ||
51 | .resource = &bcma_pflash_resource, | ||
52 | .num_resources = 1, | ||
53 | }; | ||
54 | |||
55 | /* The 47162a0 hangs when reading MIPS DMP registers registers */ | 33 | /* The 47162a0 hangs when reading MIPS DMP registers registers */ |
56 | static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) | 34 | static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) |
57 | { | 35 | { |
@@ -272,48 +250,11 @@ static enum bcma_boot_dev bcma_boot_dev(struct bcma_bus *bus) | |||
272 | return BCMA_BOOT_DEV_SERIAL; | 250 | return BCMA_BOOT_DEV_SERIAL; |
273 | } | 251 | } |
274 | 252 | ||
275 | static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) | 253 | static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore) |
276 | { | 254 | { |
277 | struct bcma_bus *bus = mcore->core->bus; | 255 | struct bcma_bus *bus = mcore->core->bus; |
278 | struct bcma_drv_cc *cc = &bus->drv_cc; | ||
279 | struct bcma_pflash *pflash = &cc->pflash; | ||
280 | enum bcma_boot_dev boot_dev; | 256 | enum bcma_boot_dev boot_dev; |
281 | 257 | ||
282 | switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | ||
283 | case BCMA_CC_FLASHT_STSER: | ||
284 | case BCMA_CC_FLASHT_ATSER: | ||
285 | bcma_debug(bus, "Found serial flash\n"); | ||
286 | bcma_sflash_init(cc); | ||
287 | break; | ||
288 | case BCMA_CC_FLASHT_PARA: | ||
289 | bcma_debug(bus, "Found parallel flash\n"); | ||
290 | pflash->present = true; | ||
291 | pflash->window = BCMA_SOC_FLASH2; | ||
292 | pflash->window_size = BCMA_SOC_FLASH2_SZ; | ||
293 | |||
294 | if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & | ||
295 | BCMA_CC_FLASH_CFG_DS) == 0) | ||
296 | pflash->buswidth = 1; | ||
297 | else | ||
298 | pflash->buswidth = 2; | ||
299 | |||
300 | bcma_pflash_data.width = pflash->buswidth; | ||
301 | bcma_pflash_resource.start = pflash->window; | ||
302 | bcma_pflash_resource.end = pflash->window + pflash->window_size; | ||
303 | |||
304 | break; | ||
305 | default: | ||
306 | bcma_err(bus, "Flash type not supported\n"); | ||
307 | } | ||
308 | |||
309 | if (cc->core->id.rev == 38 || | ||
310 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | ||
311 | if (cc->capabilities & BCMA_CC_CAP_NFLASH) { | ||
312 | bcma_debug(bus, "Found NAND flash\n"); | ||
313 | bcma_nflash_init(cc); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | /* Determine flash type this SoC boots from */ | 258 | /* Determine flash type this SoC boots from */ |
318 | boot_dev = bcma_boot_dev(bus); | 259 | boot_dev = bcma_boot_dev(bus); |
319 | switch (boot_dev) { | 260 | switch (boot_dev) { |
@@ -340,7 +281,7 @@ void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) | |||
340 | if (mcore->early_setup_done) | 281 | if (mcore->early_setup_done) |
341 | return; | 282 | return; |
342 | 283 | ||
343 | bcma_core_mips_flash_detect(mcore); | 284 | bcma_core_mips_nvram_init(mcore); |
344 | 285 | ||
345 | mcore->early_setup_done = true; | 286 | mcore->early_setup_done = true; |
346 | } | 287 | } |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index c466f752b067..786be8fed39e 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -350,7 +350,7 @@ static int bcma_register_devices(struct bcma_bus *bus) | |||
350 | bcma_register_core(bus, core); | 350 | bcma_register_core(bus, core); |
351 | } | 351 | } |
352 | 352 | ||
353 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 353 | #ifdef CONFIG_BCMA_PFLASH |
354 | if (bus->drv_cc.pflash.present) { | 354 | if (bus->drv_cc.pflash.present) { |
355 | err = platform_device_register(&bcma_pflash_dev); | 355 | err = platform_device_register(&bcma_pflash_dev); |
356 | if (err) | 356 | if (err) |
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index 03aa35f999a1..db1ca629cbd6 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig | |||
@@ -15,6 +15,12 @@ config ATH10K_PCI | |||
15 | ---help--- | 15 | ---help--- |
16 | This module adds support for PCIE bus | 16 | This module adds support for PCIE bus |
17 | 17 | ||
18 | config ATH10K_AHB | ||
19 | bool "Atheros ath10k AHB support" | ||
20 | depends on ATH10K_PCI && OF && RESET_CONTROLLER | ||
21 | ---help--- | ||
22 | This module adds support for AHB bus | ||
23 | |||
18 | config ATH10K_DEBUG | 24 | config ATH10K_DEBUG |
19 | bool "Atheros ath10k debugging" | 25 | bool "Atheros ath10k debugging" |
20 | depends on ATH10K | 26 | depends on ATH10K |
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index c04fb00e7930..930fadd940d8 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile | |||
@@ -25,5 +25,7 @@ obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o | |||
25 | ath10k_pci-y += pci.o \ | 25 | ath10k_pci-y += pci.o \ |
26 | ce.o | 26 | ce.o |
27 | 27 | ||
28 | ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o | ||
29 | |||
28 | # for tracing framework to find trace.h | 30 | # for tracing framework to find trace.h |
29 | CFLAGS_trace.o := -I$(src) | 31 | CFLAGS_trace.o := -I$(src) |
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c new file mode 100644 index 000000000000..bd62bc19e758 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ahb.c | |||
@@ -0,0 +1,933 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved. | ||
3 | * Copyright (c) 2015 The Linux Foundation. All rights reserved. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_device.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/reset.h> | ||
22 | #include "core.h" | ||
23 | #include "debug.h" | ||
24 | #include "pci.h" | ||
25 | #include "ahb.h" | ||
26 | |||
27 | static const struct of_device_id ath10k_ahb_of_match[] = { | ||
28 | /* TODO: enable this entry once everything in place. | ||
29 | * { .compatible = "qcom,ipq4019-wifi", | ||
30 | * .data = (void *)ATH10K_HW_QCA4019 }, | ||
31 | */ | ||
32 | { } | ||
33 | }; | ||
34 | |||
35 | MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); | ||
36 | |||
37 | static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar) | ||
38 | { | ||
39 | return &((struct ath10k_pci *)ar->drv_priv)->ahb[0]; | ||
40 | } | ||
41 | |||
42 | static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value) | ||
43 | { | ||
44 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
45 | |||
46 | iowrite32(value, ar_ahb->mem + offset); | ||
47 | } | ||
48 | |||
49 | static u32 ath10k_ahb_read32(struct ath10k *ar, u32 offset) | ||
50 | { | ||
51 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
52 | |||
53 | return ioread32(ar_ahb->mem + offset); | ||
54 | } | ||
55 | |||
56 | static u32 ath10k_ahb_gcc_read32(struct ath10k *ar, u32 offset) | ||
57 | { | ||
58 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
59 | |||
60 | return ioread32(ar_ahb->gcc_mem + offset); | ||
61 | } | ||
62 | |||
63 | static void ath10k_ahb_tcsr_write32(struct ath10k *ar, u32 offset, u32 value) | ||
64 | { | ||
65 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
66 | |||
67 | iowrite32(value, ar_ahb->tcsr_mem + offset); | ||
68 | } | ||
69 | |||
70 | static u32 ath10k_ahb_tcsr_read32(struct ath10k *ar, u32 offset) | ||
71 | { | ||
72 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
73 | |||
74 | return ioread32(ar_ahb->tcsr_mem + offset); | ||
75 | } | ||
76 | |||
77 | static u32 ath10k_ahb_soc_read32(struct ath10k *ar, u32 addr) | ||
78 | { | ||
79 | return ath10k_ahb_read32(ar, RTC_SOC_BASE_ADDRESS + addr); | ||
80 | } | ||
81 | |||
82 | static int ath10k_ahb_get_num_banks(struct ath10k *ar) | ||
83 | { | ||
84 | if (ar->hw_rev == ATH10K_HW_QCA4019) | ||
85 | return 1; | ||
86 | |||
87 | ath10k_warn(ar, "unknown number of banks, assuming 1\n"); | ||
88 | return 1; | ||
89 | } | ||
90 | |||
91 | static int ath10k_ahb_clock_init(struct ath10k *ar) | ||
92 | { | ||
93 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
94 | struct device *dev; | ||
95 | int ret; | ||
96 | |||
97 | dev = &ar_ahb->pdev->dev; | ||
98 | |||
99 | ar_ahb->cmd_clk = clk_get(dev, "wifi_wcss_cmd"); | ||
100 | if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) { | ||
101 | ath10k_err(ar, "failed to get cmd clk: %ld\n", | ||
102 | PTR_ERR(ar_ahb->cmd_clk)); | ||
103 | ret = ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV; | ||
104 | goto out; | ||
105 | } | ||
106 | |||
107 | ar_ahb->ref_clk = clk_get(dev, "wifi_wcss_ref"); | ||
108 | if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) { | ||
109 | ath10k_err(ar, "failed to get ref clk: %ld\n", | ||
110 | PTR_ERR(ar_ahb->ref_clk)); | ||
111 | ret = ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV; | ||
112 | goto err_cmd_clk_put; | ||
113 | } | ||
114 | |||
115 | ar_ahb->rtc_clk = clk_get(dev, "wifi_wcss_rtc"); | ||
116 | if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { | ||
117 | ath10k_err(ar, "failed to get rtc clk: %ld\n", | ||
118 | PTR_ERR(ar_ahb->rtc_clk)); | ||
119 | ret = ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV; | ||
120 | goto err_ref_clk_put; | ||
121 | } | ||
122 | |||
123 | return 0; | ||
124 | |||
125 | err_ref_clk_put: | ||
126 | clk_put(ar_ahb->ref_clk); | ||
127 | |||
128 | err_cmd_clk_put: | ||
129 | clk_put(ar_ahb->cmd_clk); | ||
130 | |||
131 | out: | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static void ath10k_ahb_clock_deinit(struct ath10k *ar) | ||
136 | { | ||
137 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
138 | |||
139 | if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk)) | ||
140 | clk_put(ar_ahb->cmd_clk); | ||
141 | |||
142 | if (!IS_ERR_OR_NULL(ar_ahb->ref_clk)) | ||
143 | clk_put(ar_ahb->ref_clk); | ||
144 | |||
145 | if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk)) | ||
146 | clk_put(ar_ahb->rtc_clk); | ||
147 | |||
148 | ar_ahb->cmd_clk = NULL; | ||
149 | ar_ahb->ref_clk = NULL; | ||
150 | ar_ahb->rtc_clk = NULL; | ||
151 | } | ||
152 | |||
153 | static int ath10k_ahb_clock_enable(struct ath10k *ar) | ||
154 | { | ||
155 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
156 | struct device *dev; | ||
157 | int ret; | ||
158 | |||
159 | dev = &ar_ahb->pdev->dev; | ||
160 | |||
161 | if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) || | ||
162 | IS_ERR_OR_NULL(ar_ahb->ref_clk) || | ||
163 | IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { | ||
164 | ath10k_err(ar, "clock(s) is/are not initialized\n"); | ||
165 | ret = -EIO; | ||
166 | goto out; | ||
167 | } | ||
168 | |||
169 | ret = clk_prepare_enable(ar_ahb->cmd_clk); | ||
170 | if (ret) { | ||
171 | ath10k_err(ar, "failed to enable cmd clk: %d\n", ret); | ||
172 | goto out; | ||
173 | } | ||
174 | |||
175 | ret = clk_prepare_enable(ar_ahb->ref_clk); | ||
176 | if (ret) { | ||
177 | ath10k_err(ar, "failed to enable ref clk: %d\n", ret); | ||
178 | goto err_cmd_clk_disable; | ||
179 | } | ||
180 | |||
181 | ret = clk_prepare_enable(ar_ahb->rtc_clk); | ||
182 | if (ret) { | ||
183 | ath10k_err(ar, "failed to enable rtc clk: %d\n", ret); | ||
184 | goto err_ref_clk_disable; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | |||
189 | err_ref_clk_disable: | ||
190 | clk_disable_unprepare(ar_ahb->ref_clk); | ||
191 | |||
192 | err_cmd_clk_disable: | ||
193 | clk_disable_unprepare(ar_ahb->cmd_clk); | ||
194 | |||
195 | out: | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | static void ath10k_ahb_clock_disable(struct ath10k *ar) | ||
200 | { | ||
201 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
202 | |||
203 | if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk)) | ||
204 | clk_disable_unprepare(ar_ahb->cmd_clk); | ||
205 | |||
206 | if (!IS_ERR_OR_NULL(ar_ahb->ref_clk)) | ||
207 | clk_disable_unprepare(ar_ahb->ref_clk); | ||
208 | |||
209 | if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk)) | ||
210 | clk_disable_unprepare(ar_ahb->rtc_clk); | ||
211 | } | ||
212 | |||
213 | static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar) | ||
214 | { | ||
215 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
216 | struct device *dev; | ||
217 | int ret; | ||
218 | |||
219 | dev = &ar_ahb->pdev->dev; | ||
220 | |||
221 | ar_ahb->core_cold_rst = reset_control_get(dev, "wifi_core_cold"); | ||
222 | if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) { | ||
223 | ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n", | ||
224 | PTR_ERR(ar_ahb->core_cold_rst)); | ||
225 | ret = ar_ahb->core_cold_rst ? | ||
226 | PTR_ERR(ar_ahb->core_cold_rst) : -ENODEV; | ||
227 | goto out; | ||
228 | } | ||
229 | |||
230 | ar_ahb->radio_cold_rst = reset_control_get(dev, "wifi_radio_cold"); | ||
231 | if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) { | ||
232 | ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n", | ||
233 | PTR_ERR(ar_ahb->radio_cold_rst)); | ||
234 | ret = ar_ahb->radio_cold_rst ? | ||
235 | PTR_ERR(ar_ahb->radio_cold_rst) : -ENODEV; | ||
236 | goto err_core_cold_rst_put; | ||
237 | } | ||
238 | |||
239 | ar_ahb->radio_warm_rst = reset_control_get(dev, "wifi_radio_warm"); | ||
240 | if (IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) { | ||
241 | ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n", | ||
242 | PTR_ERR(ar_ahb->radio_warm_rst)); | ||
243 | ret = ar_ahb->radio_warm_rst ? | ||
244 | PTR_ERR(ar_ahb->radio_warm_rst) : -ENODEV; | ||
245 | goto err_radio_cold_rst_put; | ||
246 | } | ||
247 | |||
248 | ar_ahb->radio_srif_rst = reset_control_get(dev, "wifi_radio_srif"); | ||
249 | if (IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) { | ||
250 | ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n", | ||
251 | PTR_ERR(ar_ahb->radio_srif_rst)); | ||
252 | ret = ar_ahb->radio_srif_rst ? | ||
253 | PTR_ERR(ar_ahb->radio_srif_rst) : -ENODEV; | ||
254 | goto err_radio_warm_rst_put; | ||
255 | } | ||
256 | |||
257 | ar_ahb->cpu_init_rst = reset_control_get(dev, "wifi_cpu_init"); | ||
258 | if (IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { | ||
259 | ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n", | ||
260 | PTR_ERR(ar_ahb->cpu_init_rst)); | ||
261 | ret = ar_ahb->cpu_init_rst ? | ||
262 | PTR_ERR(ar_ahb->cpu_init_rst) : -ENODEV; | ||
263 | goto err_radio_srif_rst_put; | ||
264 | } | ||
265 | |||
266 | return 0; | ||
267 | |||
268 | err_radio_srif_rst_put: | ||
269 | reset_control_put(ar_ahb->radio_srif_rst); | ||
270 | |||
271 | err_radio_warm_rst_put: | ||
272 | reset_control_put(ar_ahb->radio_warm_rst); | ||
273 | |||
274 | err_radio_cold_rst_put: | ||
275 | reset_control_put(ar_ahb->radio_cold_rst); | ||
276 | |||
277 | err_core_cold_rst_put: | ||
278 | reset_control_put(ar_ahb->core_cold_rst); | ||
279 | |||
280 | out: | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar) | ||
285 | { | ||
286 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
287 | |||
288 | if (!IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) | ||
289 | reset_control_put(ar_ahb->core_cold_rst); | ||
290 | |||
291 | if (!IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) | ||
292 | reset_control_put(ar_ahb->radio_cold_rst); | ||
293 | |||
294 | if (!IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) | ||
295 | reset_control_put(ar_ahb->radio_warm_rst); | ||
296 | |||
297 | if (!IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) | ||
298 | reset_control_put(ar_ahb->radio_srif_rst); | ||
299 | |||
300 | if (!IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) | ||
301 | reset_control_put(ar_ahb->cpu_init_rst); | ||
302 | |||
303 | ar_ahb->core_cold_rst = NULL; | ||
304 | ar_ahb->radio_cold_rst = NULL; | ||
305 | ar_ahb->radio_warm_rst = NULL; | ||
306 | ar_ahb->radio_srif_rst = NULL; | ||
307 | ar_ahb->cpu_init_rst = NULL; | ||
308 | } | ||
309 | |||
310 | static int ath10k_ahb_release_reset(struct ath10k *ar) | ||
311 | { | ||
312 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
313 | int ret; | ||
314 | |||
315 | if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || | ||
316 | IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || | ||
317 | IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || | ||
318 | IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { | ||
319 | ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); | ||
320 | return -EINVAL; | ||
321 | } | ||
322 | |||
323 | ret = reset_control_deassert(ar_ahb->radio_cold_rst); | ||
324 | if (ret) { | ||
325 | ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret); | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | ret = reset_control_deassert(ar_ahb->radio_warm_rst); | ||
330 | if (ret) { | ||
331 | ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | ret = reset_control_deassert(ar_ahb->radio_srif_rst); | ||
336 | if (ret) { | ||
337 | ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | ret = reset_control_deassert(ar_ahb->cpu_init_rst); | ||
342 | if (ret) { | ||
343 | ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret); | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg, | ||
351 | u32 haltack_reg) | ||
352 | { | ||
353 | unsigned long timeout; | ||
354 | u32 val; | ||
355 | |||
356 | /* Issue halt axi bus request */ | ||
357 | val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); | ||
358 | val |= AHB_AXI_BUS_HALT_REQ; | ||
359 | ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); | ||
360 | |||
361 | /* Wait for axi bus halted ack */ | ||
362 | timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT); | ||
363 | do { | ||
364 | val = ath10k_ahb_tcsr_read32(ar, haltack_reg); | ||
365 | if (val & AHB_AXI_BUS_HALT_ACK) | ||
366 | break; | ||
367 | |||
368 | mdelay(1); | ||
369 | } while (time_before(jiffies, timeout)); | ||
370 | |||
371 | if (!(val & AHB_AXI_BUS_HALT_ACK)) { | ||
372 | ath10k_err(ar, "failed to halt axi bus: %d\n", val); | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n"); | ||
377 | } | ||
378 | |||
379 | static void ath10k_ahb_halt_chip(struct ath10k *ar) | ||
380 | { | ||
381 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
382 | u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg; | ||
383 | u32 val; | ||
384 | int ret; | ||
385 | |||
386 | if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) || | ||
387 | IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || | ||
388 | IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || | ||
389 | IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || | ||
390 | IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { | ||
391 | ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG); | ||
396 | |||
397 | switch (core_id) { | ||
398 | case 0: | ||
399 | glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG; | ||
400 | haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ; | ||
401 | haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK; | ||
402 | break; | ||
403 | case 1: | ||
404 | glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG; | ||
405 | haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ; | ||
406 | haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK; | ||
407 | break; | ||
408 | default: | ||
409 | ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n", | ||
410 | core_id); | ||
411 | return; | ||
412 | } | ||
413 | |||
414 | ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg); | ||
415 | |||
416 | val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); | ||
417 | val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; | ||
418 | ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); | ||
419 | |||
420 | ret = reset_control_assert(ar_ahb->core_cold_rst); | ||
421 | if (ret) | ||
422 | ath10k_err(ar, "failed to assert core cold rst: %d\n", ret); | ||
423 | msleep(1); | ||
424 | |||
425 | ret = reset_control_assert(ar_ahb->radio_cold_rst); | ||
426 | if (ret) | ||
427 | ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret); | ||
428 | msleep(1); | ||
429 | |||
430 | ret = reset_control_assert(ar_ahb->radio_warm_rst); | ||
431 | if (ret) | ||
432 | ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret); | ||
433 | msleep(1); | ||
434 | |||
435 | ret = reset_control_assert(ar_ahb->radio_srif_rst); | ||
436 | if (ret) | ||
437 | ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret); | ||
438 | msleep(1); | ||
439 | |||
440 | ret = reset_control_assert(ar_ahb->cpu_init_rst); | ||
441 | if (ret) | ||
442 | ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret); | ||
443 | msleep(10); | ||
444 | |||
445 | /* Clear halt req and core clock disable req before | ||
446 | * deasserting wifi core reset. | ||
447 | */ | ||
448 | val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); | ||
449 | val &= ~AHB_AXI_BUS_HALT_REQ; | ||
450 | ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); | ||
451 | |||
452 | val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); | ||
453 | val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; | ||
454 | ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); | ||
455 | |||
456 | ret = reset_control_deassert(ar_ahb->core_cold_rst); | ||
457 | if (ret) | ||
458 | ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret); | ||
459 | |||
460 | ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id); | ||
461 | } | ||
462 | |||
463 | static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg) | ||
464 | { | ||
465 | struct ath10k *ar = arg; | ||
466 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
467 | |||
468 | if (!ath10k_pci_irq_pending(ar)) | ||
469 | return IRQ_NONE; | ||
470 | |||
471 | ath10k_pci_disable_and_clear_legacy_irq(ar); | ||
472 | tasklet_schedule(&ar_pci->intr_tq); | ||
473 | |||
474 | return IRQ_HANDLED; | ||
475 | } | ||
476 | |||
477 | static int ath10k_ahb_request_irq_legacy(struct ath10k *ar) | ||
478 | { | ||
479 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
480 | int ret; | ||
481 | |||
482 | ret = request_irq(ar_ahb->irq, | ||
483 | ath10k_ahb_interrupt_handler, | ||
484 | IRQF_SHARED, "ath10k_ahb", ar); | ||
485 | if (ret) { | ||
486 | ath10k_warn(ar, "failed to request legacy irq %d: %d\n", | ||
487 | ar_ahb->irq, ret); | ||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static void ath10k_ahb_release_irq_legacy(struct ath10k *ar) | ||
495 | { | ||
496 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
497 | |||
498 | free_irq(ar_ahb->irq, ar); | ||
499 | } | ||
500 | |||
501 | static void ath10k_ahb_irq_disable(struct ath10k *ar) | ||
502 | { | ||
503 | ath10k_ce_disable_interrupts(ar); | ||
504 | ath10k_pci_disable_and_clear_legacy_irq(ar); | ||
505 | } | ||
506 | |||
507 | static int ath10k_ahb_resource_init(struct ath10k *ar) | ||
508 | { | ||
509 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
510 | struct platform_device *pdev; | ||
511 | struct device *dev; | ||
512 | struct resource *res; | ||
513 | int ret; | ||
514 | |||
515 | pdev = ar_ahb->pdev; | ||
516 | dev = &pdev->dev; | ||
517 | |||
518 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
519 | if (!res) { | ||
520 | ath10k_err(ar, "failed to get memory resource\n"); | ||
521 | ret = -ENXIO; | ||
522 | goto out; | ||
523 | } | ||
524 | |||
525 | ar_ahb->mem = devm_ioremap_resource(&pdev->dev, res); | ||
526 | if (IS_ERR(ar_ahb->mem)) { | ||
527 | ath10k_err(ar, "mem ioremap error\n"); | ||
528 | ret = PTR_ERR(ar_ahb->mem); | ||
529 | goto out; | ||
530 | } | ||
531 | |||
532 | ar_ahb->mem_len = resource_size(res); | ||
533 | |||
534 | ar_ahb->gcc_mem = ioremap_nocache(ATH10K_GCC_REG_BASE, | ||
535 | ATH10K_GCC_REG_SIZE); | ||
536 | if (!ar_ahb->gcc_mem) { | ||
537 | ath10k_err(ar, "gcc mem ioremap error\n"); | ||
538 | ret = -ENOMEM; | ||
539 | goto err_mem_unmap; | ||
540 | } | ||
541 | |||
542 | ar_ahb->tcsr_mem = ioremap_nocache(ATH10K_TCSR_REG_BASE, | ||
543 | ATH10K_TCSR_REG_SIZE); | ||
544 | if (!ar_ahb->tcsr_mem) { | ||
545 | ath10k_err(ar, "tcsr mem ioremap error\n"); | ||
546 | ret = -ENOMEM; | ||
547 | goto err_gcc_mem_unmap; | ||
548 | } | ||
549 | |||
550 | ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); | ||
551 | if (ret) { | ||
552 | ath10k_err(ar, "failed to set 32-bit dma mask: %d\n", ret); | ||
553 | goto err_tcsr_mem_unmap; | ||
554 | } | ||
555 | |||
556 | ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); | ||
557 | if (ret) { | ||
558 | ath10k_err(ar, "failed to set 32-bit consistent dma: %d\n", | ||
559 | ret); | ||
560 | goto err_tcsr_mem_unmap; | ||
561 | } | ||
562 | |||
563 | ret = ath10k_ahb_clock_init(ar); | ||
564 | if (ret) | ||
565 | goto err_tcsr_mem_unmap; | ||
566 | |||
567 | ret = ath10k_ahb_rst_ctrl_init(ar); | ||
568 | if (ret) | ||
569 | goto err_clock_deinit; | ||
570 | |||
571 | ar_ahb->irq = platform_get_irq_byname(pdev, "legacy"); | ||
572 | if (ar_ahb->irq < 0) { | ||
573 | ath10k_err(ar, "failed to get irq number: %d\n", ar_ahb->irq); | ||
574 | goto err_clock_deinit; | ||
575 | } | ||
576 | |||
577 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq); | ||
578 | |||
579 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%p mem_len: %lu gcc mem: 0x%p tcsr_mem: 0x%p\n", | ||
580 | ar_ahb->mem, ar_ahb->mem_len, | ||
581 | ar_ahb->gcc_mem, ar_ahb->tcsr_mem); | ||
582 | return 0; | ||
583 | |||
584 | err_clock_deinit: | ||
585 | ath10k_ahb_clock_deinit(ar); | ||
586 | |||
587 | err_tcsr_mem_unmap: | ||
588 | iounmap(ar_ahb->tcsr_mem); | ||
589 | |||
590 | err_gcc_mem_unmap: | ||
591 | ar_ahb->tcsr_mem = NULL; | ||
592 | iounmap(ar_ahb->gcc_mem); | ||
593 | |||
594 | err_mem_unmap: | ||
595 | ar_ahb->gcc_mem = NULL; | ||
596 | devm_iounmap(&pdev->dev, ar_ahb->mem); | ||
597 | |||
598 | out: | ||
599 | ar_ahb->mem = NULL; | ||
600 | return ret; | ||
601 | } | ||
602 | |||
603 | static void ath10k_ahb_resource_deinit(struct ath10k *ar) | ||
604 | { | ||
605 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
606 | struct device *dev; | ||
607 | |||
608 | dev = &ar_ahb->pdev->dev; | ||
609 | |||
610 | if (ar_ahb->mem) | ||
611 | devm_iounmap(dev, ar_ahb->mem); | ||
612 | |||
613 | if (ar_ahb->gcc_mem) | ||
614 | iounmap(ar_ahb->gcc_mem); | ||
615 | |||
616 | if (ar_ahb->tcsr_mem) | ||
617 | iounmap(ar_ahb->tcsr_mem); | ||
618 | |||
619 | ar_ahb->mem = NULL; | ||
620 | ar_ahb->gcc_mem = NULL; | ||
621 | ar_ahb->tcsr_mem = NULL; | ||
622 | |||
623 | ath10k_ahb_clock_deinit(ar); | ||
624 | ath10k_ahb_rst_ctrl_deinit(ar); | ||
625 | } | ||
626 | |||
627 | static int ath10k_ahb_prepare_device(struct ath10k *ar) | ||
628 | { | ||
629 | u32 val; | ||
630 | int ret; | ||
631 | |||
632 | ret = ath10k_ahb_clock_enable(ar); | ||
633 | if (ret) { | ||
634 | ath10k_err(ar, "failed to enable clocks\n"); | ||
635 | return ret; | ||
636 | } | ||
637 | |||
638 | /* Clock for the target is supplied from outside of target (ie, | ||
639 | * external clock module controlled by the host). Target needs | ||
640 | * to know what frequency target cpu is configured which is needed | ||
641 | * for target internal use. Read target cpu frequency info from | ||
642 | * gcc register and write into target's scratch register where | ||
643 | * target expects this information. | ||
644 | */ | ||
645 | val = ath10k_ahb_gcc_read32(ar, ATH10K_AHB_GCC_FEPLL_PLL_DIV); | ||
646 | ath10k_ahb_write32(ar, ATH10K_AHB_WIFI_SCRATCH_5_REG, val); | ||
647 | |||
648 | ret = ath10k_ahb_release_reset(ar); | ||
649 | if (ret) | ||
650 | goto err_clk_disable; | ||
651 | |||
652 | ath10k_ahb_irq_disable(ar); | ||
653 | |||
654 | ath10k_ahb_write32(ar, FW_INDICATOR_ADDRESS, FW_IND_HOST_READY); | ||
655 | |||
656 | ret = ath10k_pci_wait_for_target_init(ar); | ||
657 | if (ret) | ||
658 | goto err_halt_chip; | ||
659 | |||
660 | return 0; | ||
661 | |||
662 | err_halt_chip: | ||
663 | ath10k_ahb_halt_chip(ar); | ||
664 | |||
665 | err_clk_disable: | ||
666 | ath10k_ahb_clock_disable(ar); | ||
667 | |||
668 | return ret; | ||
669 | } | ||
670 | |||
671 | static int ath10k_ahb_chip_reset(struct ath10k *ar) | ||
672 | { | ||
673 | int ret; | ||
674 | |||
675 | ath10k_ahb_halt_chip(ar); | ||
676 | ath10k_ahb_clock_disable(ar); | ||
677 | |||
678 | ret = ath10k_ahb_prepare_device(ar); | ||
679 | if (ret) | ||
680 | return ret; | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static int ath10k_ahb_wake_target_cpu(struct ath10k *ar) | ||
686 | { | ||
687 | u32 addr, val; | ||
688 | |||
689 | addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS; | ||
690 | val = ath10k_ahb_read32(ar, addr); | ||
691 | val |= ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK; | ||
692 | ath10k_ahb_write32(ar, addr, val); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int ath10k_ahb_hif_start(struct ath10k *ar) | ||
698 | { | ||
699 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n"); | ||
700 | |||
701 | ath10k_ce_enable_interrupts(ar); | ||
702 | ath10k_pci_enable_legacy_irq(ar); | ||
703 | |||
704 | ath10k_pci_rx_post(ar); | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | static void ath10k_ahb_hif_stop(struct ath10k *ar) | ||
710 | { | ||
711 | struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); | ||
712 | |||
713 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif stop\n"); | ||
714 | |||
715 | ath10k_ahb_irq_disable(ar); | ||
716 | synchronize_irq(ar_ahb->irq); | ||
717 | |||
718 | ath10k_pci_flush(ar); | ||
719 | } | ||
720 | |||
721 | static int ath10k_ahb_hif_power_up(struct ath10k *ar) | ||
722 | { | ||
723 | int ret; | ||
724 | |||
725 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif power up\n"); | ||
726 | |||
727 | ret = ath10k_ahb_chip_reset(ar); | ||
728 | if (ret) { | ||
729 | ath10k_err(ar, "failed to reset chip: %d\n", ret); | ||
730 | goto out; | ||
731 | } | ||
732 | |||
733 | ret = ath10k_pci_init_pipes(ar); | ||
734 | if (ret) { | ||
735 | ath10k_err(ar, "failed to initialize CE: %d\n", ret); | ||
736 | goto out; | ||
737 | } | ||
738 | |||
739 | ret = ath10k_pci_init_config(ar); | ||
740 | if (ret) { | ||
741 | ath10k_err(ar, "failed to setup init config: %d\n", ret); | ||
742 | goto err_ce_deinit; | ||
743 | } | ||
744 | |||
745 | ret = ath10k_ahb_wake_target_cpu(ar); | ||
746 | if (ret) { | ||
747 | ath10k_err(ar, "could not wake up target CPU: %d\n", ret); | ||
748 | goto err_ce_deinit; | ||
749 | } | ||
750 | |||
751 | return 0; | ||
752 | |||
753 | err_ce_deinit: | ||
754 | ath10k_pci_ce_deinit(ar); | ||
755 | out: | ||
756 | return ret; | ||
757 | } | ||
758 | |||
759 | static const struct ath10k_hif_ops ath10k_ahb_hif_ops = { | ||
760 | .tx_sg = ath10k_pci_hif_tx_sg, | ||
761 | .diag_read = ath10k_pci_hif_diag_read, | ||
762 | .diag_write = ath10k_pci_diag_write_mem, | ||
763 | .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, | ||
764 | .start = ath10k_ahb_hif_start, | ||
765 | .stop = ath10k_ahb_hif_stop, | ||
766 | .map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe, | ||
767 | .get_default_pipe = ath10k_pci_hif_get_default_pipe, | ||
768 | .send_complete_check = ath10k_pci_hif_send_complete_check, | ||
769 | .get_free_queue_number = ath10k_pci_hif_get_free_queue_number, | ||
770 | .power_up = ath10k_ahb_hif_power_up, | ||
771 | .power_down = ath10k_pci_hif_power_down, | ||
772 | .read32 = ath10k_ahb_read32, | ||
773 | .write32 = ath10k_ahb_write32, | ||
774 | }; | ||
775 | |||
776 | static const struct ath10k_bus_ops ath10k_ahb_bus_ops = { | ||
777 | .read32 = ath10k_ahb_read32, | ||
778 | .write32 = ath10k_ahb_write32, | ||
779 | .get_num_banks = ath10k_ahb_get_num_banks, | ||
780 | }; | ||
781 | |||
782 | static int ath10k_ahb_probe(struct platform_device *pdev) | ||
783 | { | ||
784 | struct ath10k *ar; | ||
785 | struct ath10k_ahb *ar_ahb; | ||
786 | struct ath10k_pci *ar_pci; | ||
787 | const struct of_device_id *of_id; | ||
788 | enum ath10k_hw_rev hw_rev; | ||
789 | size_t size; | ||
790 | int ret; | ||
791 | u32 chip_id; | ||
792 | |||
793 | of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); | ||
794 | if (!of_id) { | ||
795 | dev_err(&pdev->dev, "failed to find matching device tree id\n"); | ||
796 | return -EINVAL; | ||
797 | } | ||
798 | |||
799 | hw_rev = (enum ath10k_hw_rev)of_id->data; | ||
800 | |||
801 | size = sizeof(*ar_pci) + sizeof(*ar_ahb); | ||
802 | ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB, | ||
803 | hw_rev, &ath10k_ahb_hif_ops); | ||
804 | if (!ar) { | ||
805 | dev_err(&pdev->dev, "failed to allocate core\n"); | ||
806 | return -ENOMEM; | ||
807 | } | ||
808 | |||
809 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n"); | ||
810 | |||
811 | ar_pci = ath10k_pci_priv(ar); | ||
812 | ar_ahb = ath10k_ahb_priv(ar); | ||
813 | |||
814 | ar_ahb->pdev = pdev; | ||
815 | platform_set_drvdata(pdev, ar); | ||
816 | |||
817 | ret = ath10k_ahb_resource_init(ar); | ||
818 | if (ret) | ||
819 | goto err_core_destroy; | ||
820 | |||
821 | ar->dev_id = 0; | ||
822 | ar_pci->mem = ar_ahb->mem; | ||
823 | ar_pci->mem_len = ar_ahb->mem_len; | ||
824 | ar_pci->ar = ar; | ||
825 | ar_pci->bus_ops = &ath10k_ahb_bus_ops; | ||
826 | |||
827 | ret = ath10k_pci_setup_resource(ar); | ||
828 | if (ret) { | ||
829 | ath10k_err(ar, "failed to setup resource: %d\n", ret); | ||
830 | goto err_resource_deinit; | ||
831 | } | ||
832 | |||
833 | ath10k_pci_init_irq_tasklets(ar); | ||
834 | |||
835 | ret = ath10k_ahb_request_irq_legacy(ar); | ||
836 | if (ret) | ||
837 | goto err_free_pipes; | ||
838 | |||
839 | ret = ath10k_ahb_prepare_device(ar); | ||
840 | if (ret) | ||
841 | goto err_free_irq; | ||
842 | |||
843 | ath10k_pci_ce_deinit(ar); | ||
844 | |||
845 | chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); | ||
846 | if (chip_id == 0xffffffff) { | ||
847 | ath10k_err(ar, "failed to get chip id\n"); | ||
848 | goto err_halt_device; | ||
849 | } | ||
850 | |||
851 | ret = ath10k_core_register(ar, chip_id); | ||
852 | if (ret) { | ||
853 | ath10k_err(ar, "failed to register driver core: %d\n", ret); | ||
854 | goto err_halt_device; | ||
855 | } | ||
856 | |||
857 | return 0; | ||
858 | |||
859 | err_halt_device: | ||
860 | ath10k_ahb_halt_chip(ar); | ||
861 | ath10k_ahb_clock_disable(ar); | ||
862 | |||
863 | err_free_irq: | ||
864 | ath10k_ahb_release_irq_legacy(ar); | ||
865 | |||
866 | err_free_pipes: | ||
867 | ath10k_pci_free_pipes(ar); | ||
868 | |||
869 | err_resource_deinit: | ||
870 | ath10k_ahb_resource_deinit(ar); | ||
871 | |||
872 | err_core_destroy: | ||
873 | ath10k_core_destroy(ar); | ||
874 | platform_set_drvdata(pdev, NULL); | ||
875 | |||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | static int ath10k_ahb_remove(struct platform_device *pdev) | ||
880 | { | ||
881 | struct ath10k *ar = platform_get_drvdata(pdev); | ||
882 | struct ath10k_ahb *ar_ahb; | ||
883 | |||
884 | if (!ar) | ||
885 | return -EINVAL; | ||
886 | |||
887 | ar_ahb = ath10k_ahb_priv(ar); | ||
888 | |||
889 | if (!ar_ahb) | ||
890 | return -EINVAL; | ||
891 | |||
892 | ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n"); | ||
893 | |||
894 | ath10k_core_unregister(ar); | ||
895 | ath10k_ahb_irq_disable(ar); | ||
896 | ath10k_ahb_release_irq_legacy(ar); | ||
897 | ath10k_pci_release_resource(ar); | ||
898 | ath10k_ahb_halt_chip(ar); | ||
899 | ath10k_ahb_clock_disable(ar); | ||
900 | ath10k_ahb_resource_deinit(ar); | ||
901 | ath10k_core_destroy(ar); | ||
902 | |||
903 | platform_set_drvdata(pdev, NULL); | ||
904 | |||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | static struct platform_driver ath10k_ahb_driver = { | ||
909 | .driver = { | ||
910 | .name = "ath10k_ahb", | ||
911 | .of_match_table = ath10k_ahb_of_match, | ||
912 | }, | ||
913 | .probe = ath10k_ahb_probe, | ||
914 | .remove = ath10k_ahb_remove, | ||
915 | }; | ||
916 | |||
917 | int ath10k_ahb_init(void) | ||
918 | { | ||
919 | int ret; | ||
920 | |||
921 | printk(KERN_ERR "AHB support is still work in progress\n"); | ||
922 | |||
923 | ret = platform_driver_register(&ath10k_ahb_driver); | ||
924 | if (ret) | ||
925 | printk(KERN_ERR "failed to register ath10k ahb driver: %d\n", | ||
926 | ret); | ||
927 | return ret; | ||
928 | } | ||
929 | |||
930 | void ath10k_ahb_exit(void) | ||
931 | { | ||
932 | platform_driver_unregister(&ath10k_ahb_driver); | ||
933 | } | ||
diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h new file mode 100644 index 000000000000..d43e375215c8 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ahb.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved. | ||
3 | * Copyright (c) 2015 The Linux Foundation. All rights reserved. | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef _AHB_H_ | ||
19 | #define _AHB_H_ | ||
20 | |||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | struct ath10k_ahb { | ||
24 | struct platform_device *pdev; | ||
25 | void __iomem *mem; | ||
26 | unsigned long mem_len; | ||
27 | void __iomem *gcc_mem; | ||
28 | void __iomem *tcsr_mem; | ||
29 | |||
30 | int irq; | ||
31 | |||
32 | struct clk *cmd_clk; | ||
33 | struct clk *ref_clk; | ||
34 | struct clk *rtc_clk; | ||
35 | |||
36 | struct reset_control *core_cold_rst; | ||
37 | struct reset_control *radio_cold_rst; | ||
38 | struct reset_control *radio_warm_rst; | ||
39 | struct reset_control *radio_srif_rst; | ||
40 | struct reset_control *cpu_init_rst; | ||
41 | }; | ||
42 | |||
43 | #ifdef CONFIG_ATH10K_AHB | ||
44 | |||
45 | #define ATH10K_GCC_REG_BASE 0x1800000 | ||
46 | #define ATH10K_GCC_REG_SIZE 0x60000 | ||
47 | |||
48 | #define ATH10K_TCSR_REG_BASE 0x1900000 | ||
49 | #define ATH10K_TCSR_REG_SIZE 0x80000 | ||
50 | |||
51 | #define ATH10K_AHB_GCC_FEPLL_PLL_DIV 0x2f020 | ||
52 | #define ATH10K_AHB_WIFI_SCRATCH_5_REG 0x4f014 | ||
53 | |||
54 | #define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030 | ||
55 | |||
56 | #define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000 | ||
57 | #define ATH10K_AHB_TCSR_WIFI1_GLB_CFG 0x49004 | ||
58 | #define TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK BIT(25) | ||
59 | |||
60 | #define ATH10K_AHB_TCSR_WCSS0_HALTREQ 0x52000 | ||
61 | #define ATH10K_AHB_TCSR_WCSS1_HALTREQ 0x52010 | ||
62 | #define ATH10K_AHB_TCSR_WCSS0_HALTACK 0x52004 | ||
63 | #define ATH10K_AHB_TCSR_WCSS1_HALTACK 0x52014 | ||
64 | |||
65 | #define ATH10K_AHB_AXI_BUS_HALT_TIMEOUT 10 /* msec */ | ||
66 | #define AHB_AXI_BUS_HALT_REQ 1 | ||
67 | #define AHB_AXI_BUS_HALT_ACK 1 | ||
68 | |||
69 | #define ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK 1 | ||
70 | |||
71 | int ath10k_ahb_init(void); | ||
72 | void ath10k_ahb_exit(void); | ||
73 | |||
74 | #else /* CONFIG_ATH10K_AHB */ | ||
75 | |||
76 | static inline int ath10k_ahb_init(void) | ||
77 | { | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static inline void ath10k_ahb_exit(void) | ||
82 | { | ||
83 | } | ||
84 | |||
85 | #endif /* CONFIG_ATH10K_AHB */ | ||
86 | |||
87 | #endif /* _AHB_H_ */ | ||
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b41eb3f4ee56..c84c2d30ef1f 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -156,6 +156,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { | |||
156 | .channel_counters_freq_hz = 150000, | 156 | .channel_counters_freq_hz = 150000, |
157 | .max_probe_resp_desc_thres = 24, | 157 | .max_probe_resp_desc_thres = 24, |
158 | .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, | 158 | .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, |
159 | .num_msdu_desc = 1424, | ||
160 | .qcache_active_peers = 50, | ||
161 | .tx_chain_mask = 0xf, | ||
162 | .rx_chain_mask = 0xf, | ||
163 | .max_spatial_stream = 4, | ||
159 | .fw = { | 164 | .fw = { |
160 | .dir = QCA99X0_HW_2_0_FW_DIR, | 165 | .dir = QCA99X0_HW_2_0_FW_DIR, |
161 | .fw = QCA99X0_HW_2_0_FW_FILE, | 166 | .fw = QCA99X0_HW_2_0_FW_FILE, |
@@ -201,6 +206,31 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { | |||
201 | .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, | 206 | .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, |
202 | }, | 207 | }, |
203 | }, | 208 | }, |
209 | { | ||
210 | .id = QCA4019_HW_1_0_DEV_VERSION, | ||
211 | .dev_id = 0, | ||
212 | .name = "qca4019 hw1.0", | ||
213 | .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, | ||
214 | .uart_pin = 7, | ||
215 | .otp_exe_param = 0x0010000, | ||
216 | .continuous_frag_desc = true, | ||
217 | .channel_counters_freq_hz = 125000, | ||
218 | .max_probe_resp_desc_thres = 24, | ||
219 | .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, | ||
220 | .num_msdu_desc = 2500, | ||
221 | .qcache_active_peers = 35, | ||
222 | .tx_chain_mask = 0x3, | ||
223 | .rx_chain_mask = 0x3, | ||
224 | .max_spatial_stream = 2, | ||
225 | .fw = { | ||
226 | .dir = QCA4019_HW_1_0_FW_DIR, | ||
227 | .fw = QCA4019_HW_1_0_FW_FILE, | ||
228 | .otp = QCA4019_HW_1_0_OTP_FILE, | ||
229 | .board = QCA4019_HW_1_0_BOARD_DATA_FILE, | ||
230 | .board_size = QCA4019_BOARD_DATA_SZ, | ||
231 | .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ, | ||
232 | }, | ||
233 | }, | ||
204 | }; | 234 | }; |
205 | 235 | ||
206 | static const char *const ath10k_core_fw_feature_str[] = { | 236 | static const char *const ath10k_core_fw_feature_str[] = { |
@@ -217,6 +247,7 @@ static const char *const ath10k_core_fw_feature_str[] = { | |||
217 | [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", | 247 | [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", |
218 | [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", | 248 | [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", |
219 | [ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp", | 249 | [ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp", |
250 | [ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl", | ||
220 | }; | 251 | }; |
221 | 252 | ||
222 | static unsigned int ath10k_core_get_fw_feature_str(char *buf, | 253 | static unsigned int ath10k_core_get_fw_feature_str(char *buf, |
@@ -1478,8 +1509,13 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) | |||
1478 | case ATH10K_FW_WMI_OP_VERSION_10_1: | 1509 | case ATH10K_FW_WMI_OP_VERSION_10_1: |
1479 | case ATH10K_FW_WMI_OP_VERSION_10_2: | 1510 | case ATH10K_FW_WMI_OP_VERSION_10_2: |
1480 | case ATH10K_FW_WMI_OP_VERSION_10_2_4: | 1511 | case ATH10K_FW_WMI_OP_VERSION_10_2_4: |
1481 | ar->max_num_peers = TARGET_10X_NUM_PEERS; | 1512 | if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { |
1482 | ar->max_num_stations = TARGET_10X_NUM_STATIONS; | 1513 | ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS; |
1514 | ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS; | ||
1515 | } else { | ||
1516 | ar->max_num_peers = TARGET_10X_NUM_PEERS; | ||
1517 | ar->max_num_stations = TARGET_10X_NUM_STATIONS; | ||
1518 | } | ||
1483 | ar->max_num_vdevs = TARGET_10X_NUM_VDEVS; | 1519 | ar->max_num_vdevs = TARGET_10X_NUM_VDEVS; |
1484 | ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; | 1520 | ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; |
1485 | ar->fw_stats_req_mask = WMI_STAT_PEER; | 1521 | ar->fw_stats_req_mask = WMI_STAT_PEER; |
@@ -1502,9 +1538,9 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) | |||
1502 | ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS; | 1538 | ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS; |
1503 | ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; | 1539 | ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; |
1504 | ar->num_tids = TARGET_10_4_TGT_NUM_TIDS; | 1540 | ar->num_tids = TARGET_10_4_TGT_NUM_TIDS; |
1505 | ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC; | 1541 | ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc; |
1506 | ar->fw_stats_req_mask = WMI_STAT_PEER; | 1542 | ar->fw_stats_req_mask = WMI_STAT_PEER; |
1507 | ar->max_spatial_stream = WMI_10_4_MAX_SPATIAL_STREAM; | 1543 | ar->max_spatial_stream = ar->hw_params.max_spatial_stream; |
1508 | break; | 1544 | break; |
1509 | case ATH10K_FW_WMI_OP_VERSION_UNSET: | 1545 | case ATH10K_FW_WMI_OP_VERSION_UNSET: |
1510 | case ATH10K_FW_WMI_OP_VERSION_MAX: | 1546 | case ATH10K_FW_WMI_OP_VERSION_MAX: |
@@ -1979,6 +2015,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | |||
1979 | ar->regs = &qca99x0_regs; | 2015 | ar->regs = &qca99x0_regs; |
1980 | ar->hw_values = &qca99x0_values; | 2016 | ar->hw_values = &qca99x0_values; |
1981 | break; | 2017 | break; |
2018 | case ATH10K_HW_QCA4019: | ||
2019 | ar->regs = &qca4019_regs; | ||
2020 | ar->hw_values = &qca4019_values; | ||
2021 | break; | ||
1982 | default: | 2022 | default: |
1983 | ath10k_err(ar, "unsupported core hardware revision %d\n", | 2023 | ath10k_err(ar, "unsupported core hardware revision %d\n", |
1984 | hw_rev); | 2024 | hw_rev); |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7840cf3ef7a6..a62b62a62266 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -69,6 +69,7 @@ struct ath10k; | |||
69 | 69 | ||
70 | enum ath10k_bus { | 70 | enum ath10k_bus { |
71 | ATH10K_BUS_PCI, | 71 | ATH10K_BUS_PCI, |
72 | ATH10K_BUS_AHB, | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static inline const char *ath10k_bus_str(enum ath10k_bus bus) | 75 | static inline const char *ath10k_bus_str(enum ath10k_bus bus) |
@@ -76,6 +77,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus) | |||
76 | switch (bus) { | 77 | switch (bus) { |
77 | case ATH10K_BUS_PCI: | 78 | case ATH10K_BUS_PCI: |
78 | return "pci"; | 79 | return "pci"; |
80 | case ATH10K_BUS_AHB: | ||
81 | return "ahb"; | ||
79 | } | 82 | } |
80 | 83 | ||
81 | return "unknown"; | 84 | return "unknown"; |
@@ -159,6 +162,7 @@ struct ath10k_fw_stats_peer { | |||
159 | u32 peer_rssi; | 162 | u32 peer_rssi; |
160 | u32 peer_tx_rate; | 163 | u32 peer_tx_rate; |
161 | u32 peer_rx_rate; /* 10x only */ | 164 | u32 peer_rx_rate; /* 10x only */ |
165 | u32 rx_duration; | ||
162 | }; | 166 | }; |
163 | 167 | ||
164 | struct ath10k_fw_stats_vdev { | 168 | struct ath10k_fw_stats_vdev { |
@@ -315,6 +319,7 @@ struct ath10k_sta { | |||
315 | #ifdef CONFIG_MAC80211_DEBUGFS | 319 | #ifdef CONFIG_MAC80211_DEBUGFS |
316 | /* protected by conf_mutex */ | 320 | /* protected by conf_mutex */ |
317 | bool aggr_mode; | 321 | bool aggr_mode; |
322 | u64 rx_duration; | ||
318 | #endif | 323 | #endif |
319 | }; | 324 | }; |
320 | 325 | ||
@@ -510,6 +515,15 @@ enum ath10k_fw_features { | |||
510 | /* Firmware supports management frame protection */ | 515 | /* Firmware supports management frame protection */ |
511 | ATH10K_FW_FEATURE_MFP_SUPPORT = 12, | 516 | ATH10K_FW_FEATURE_MFP_SUPPORT = 12, |
512 | 517 | ||
518 | /* Firmware supports pull-push model where host shares it's software | ||
519 | * queue state with firmware and firmware generates fetch requests | ||
520 | * telling host which queues to dequeue tx from. | ||
521 | * | ||
522 | * Primary function of this is improved MU-MIMO performance with | ||
523 | * multiple clients. | ||
524 | */ | ||
525 | ATH10K_FW_FEATURE_PEER_FLOW_CONTROL = 13, | ||
526 | |||
513 | /* keep last */ | 527 | /* keep last */ |
514 | ATH10K_FW_FEATURE_COUNT, | 528 | ATH10K_FW_FEATURE_COUNT, |
515 | }; | 529 | }; |
@@ -666,6 +680,12 @@ struct ath10k { | |||
666 | /* The padding bytes's location is different on various chips */ | 680 | /* The padding bytes's location is different on various chips */ |
667 | enum ath10k_hw_4addr_pad hw_4addr_pad; | 681 | enum ath10k_hw_4addr_pad hw_4addr_pad; |
668 | 682 | ||
683 | u32 num_msdu_desc; | ||
684 | u32 qcache_active_peers; | ||
685 | u32 tx_chain_mask; | ||
686 | u32 rx_chain_mask; | ||
687 | u32 max_spatial_stream; | ||
688 | |||
669 | struct ath10k_hw_params_fw { | 689 | struct ath10k_hw_params_fw { |
670 | const char *dir; | 690 | const char *dir; |
671 | const char *fw; | 691 | const char *fw; |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 2bdf5408b0d9..076d29b53ddf 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -276,7 +276,7 @@ static const struct file_operations fops_wmi_services = { | |||
276 | .llseek = default_llseek, | 276 | .llseek = default_llseek, |
277 | }; | 277 | }; |
278 | 278 | ||
279 | static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) | 279 | static void ath10k_fw_stats_pdevs_free(struct list_head *head) |
280 | { | 280 | { |
281 | struct ath10k_fw_stats_pdev *i, *tmp; | 281 | struct ath10k_fw_stats_pdev *i, *tmp; |
282 | 282 | ||
@@ -286,7 +286,7 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) | |||
286 | } | 286 | } |
287 | } | 287 | } |
288 | 288 | ||
289 | static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head) | 289 | static void ath10k_fw_stats_vdevs_free(struct list_head *head) |
290 | { | 290 | { |
291 | struct ath10k_fw_stats_vdev *i, *tmp; | 291 | struct ath10k_fw_stats_vdev *i, *tmp; |
292 | 292 | ||
@@ -296,7 +296,7 @@ static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head) | |||
296 | } | 296 | } |
297 | } | 297 | } |
298 | 298 | ||
299 | static void ath10k_debug_fw_stats_peers_free(struct list_head *head) | 299 | static void ath10k_fw_stats_peers_free(struct list_head *head) |
300 | { | 300 | { |
301 | struct ath10k_fw_stats_peer *i, *tmp; | 301 | struct ath10k_fw_stats_peer *i, *tmp; |
302 | 302 | ||
@@ -310,16 +310,16 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) | |||
310 | { | 310 | { |
311 | spin_lock_bh(&ar->data_lock); | 311 | spin_lock_bh(&ar->data_lock); |
312 | ar->debug.fw_stats_done = false; | 312 | ar->debug.fw_stats_done = false; |
313 | ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); | 313 | ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); |
314 | ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); | 314 | ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); |
315 | ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers); | 315 | ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); |
316 | spin_unlock_bh(&ar->data_lock); | 316 | spin_unlock_bh(&ar->data_lock); |
317 | } | 317 | } |
318 | 318 | ||
319 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) | 319 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) |
320 | { | 320 | { |
321 | struct ath10k_fw_stats stats = {}; | 321 | struct ath10k_fw_stats stats = {}; |
322 | bool is_start, is_started, is_end; | 322 | bool is_start, is_started, is_end, peer_stats_svc; |
323 | size_t num_peers; | 323 | size_t num_peers; |
324 | size_t num_vdevs; | 324 | size_t num_vdevs; |
325 | int ret; | 325 | int ret; |
@@ -347,8 +347,14 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) | |||
347 | * delivered which is treated as end-of-data and is itself discarded | 347 | * delivered which is treated as end-of-data and is itself discarded |
348 | */ | 348 | */ |
349 | 349 | ||
350 | peer_stats_svc = test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map); | ||
351 | if (peer_stats_svc) | ||
352 | ath10k_sta_update_rx_duration(ar, &stats.peers); | ||
353 | |||
350 | if (ar->debug.fw_stats_done) { | 354 | if (ar->debug.fw_stats_done) { |
351 | ath10k_warn(ar, "received unsolicited stats update event\n"); | 355 | if (!peer_stats_svc) |
356 | ath10k_warn(ar, "received unsolicited stats update event\n"); | ||
357 | |||
352 | goto free; | 358 | goto free; |
353 | } | 359 | } |
354 | 360 | ||
@@ -372,11 +378,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) | |||
372 | /* Although this is unlikely impose a sane limit to | 378 | /* Although this is unlikely impose a sane limit to |
373 | * prevent firmware from DoS-ing the host. | 379 | * prevent firmware from DoS-ing the host. |
374 | */ | 380 | */ |
381 | ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); | ||
375 | ath10k_warn(ar, "dropping fw peer stats\n"); | 382 | ath10k_warn(ar, "dropping fw peer stats\n"); |
376 | goto free; | 383 | goto free; |
377 | } | 384 | } |
378 | 385 | ||
379 | if (num_vdevs >= BITS_PER_LONG) { | 386 | if (num_vdevs >= BITS_PER_LONG) { |
387 | ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); | ||
380 | ath10k_warn(ar, "dropping fw vdev stats\n"); | 388 | ath10k_warn(ar, "dropping fw vdev stats\n"); |
381 | goto free; | 389 | goto free; |
382 | } | 390 | } |
@@ -391,9 +399,9 @@ free: | |||
391 | /* In some cases lists have been spliced and cleared. Free up | 399 | /* In some cases lists have been spliced and cleared. Free up |
392 | * resources if that is not the case. | 400 | * resources if that is not the case. |
393 | */ | 401 | */ |
394 | ath10k_debug_fw_stats_pdevs_free(&stats.pdevs); | 402 | ath10k_fw_stats_pdevs_free(&stats.pdevs); |
395 | ath10k_debug_fw_stats_vdevs_free(&stats.vdevs); | 403 | ath10k_fw_stats_vdevs_free(&stats.vdevs); |
396 | ath10k_debug_fw_stats_peers_free(&stats.peers); | 404 | ath10k_fw_stats_peers_free(&stats.peers); |
397 | 405 | ||
398 | spin_unlock_bh(&ar->data_lock); | 406 | spin_unlock_bh(&ar->data_lock); |
399 | } | 407 | } |
@@ -2106,6 +2114,7 @@ static ssize_t ath10k_write_btcoex(struct file *file, | |||
2106 | struct ath10k *ar = file->private_data; | 2114 | struct ath10k *ar = file->private_data; |
2107 | char buf[32]; | 2115 | char buf[32]; |
2108 | size_t buf_size; | 2116 | size_t buf_size; |
2117 | int ret = 0; | ||
2109 | bool val; | 2118 | bool val; |
2110 | 2119 | ||
2111 | buf_size = min(count, (sizeof(buf) - 1)); | 2120 | buf_size = min(count, (sizeof(buf) - 1)); |
@@ -2119,6 +2128,12 @@ static ssize_t ath10k_write_btcoex(struct file *file, | |||
2119 | 2128 | ||
2120 | mutex_lock(&ar->conf_mutex); | 2129 | mutex_lock(&ar->conf_mutex); |
2121 | 2130 | ||
2131 | if (ar->state != ATH10K_STATE_ON && | ||
2132 | ar->state != ATH10K_STATE_RESTARTED) { | ||
2133 | ret = -ENETDOWN; | ||
2134 | goto exit; | ||
2135 | } | ||
2136 | |||
2122 | if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) | 2137 | if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val)) |
2123 | goto exit; | 2138 | goto exit; |
2124 | 2139 | ||
@@ -2127,17 +2142,15 @@ static ssize_t ath10k_write_btcoex(struct file *file, | |||
2127 | else | 2142 | else |
2128 | clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags); | 2143 | clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags); |
2129 | 2144 | ||
2130 | if (ar->state != ATH10K_STATE_ON) | ||
2131 | goto exit; | ||
2132 | |||
2133 | ath10k_info(ar, "restarting firmware due to btcoex change"); | 2145 | ath10k_info(ar, "restarting firmware due to btcoex change"); |
2134 | 2146 | ||
2135 | queue_work(ar->workqueue, &ar->restart_work); | 2147 | queue_work(ar->workqueue, &ar->restart_work); |
2148 | ret = count; | ||
2136 | 2149 | ||
2137 | exit: | 2150 | exit: |
2138 | mutex_unlock(&ar->conf_mutex); | 2151 | mutex_unlock(&ar->conf_mutex); |
2139 | 2152 | ||
2140 | return count; | 2153 | return ret; |
2141 | } | 2154 | } |
2142 | 2155 | ||
2143 | static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf, | 2156 | static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf, |
@@ -2176,9 +2189,6 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file, | |||
2176 | 2189 | ||
2177 | mutex_lock(&ar->conf_mutex); | 2190 | mutex_lock(&ar->conf_mutex); |
2178 | 2191 | ||
2179 | if (len > buf_len) | ||
2180 | len = buf_len; | ||
2181 | |||
2182 | len += scnprintf(buf + len, buf_len - len, | 2192 | len += scnprintf(buf + len, buf_len - len, |
2183 | "firmware-N.bin\t\t%08x\n", | 2193 | "firmware-N.bin\t\t%08x\n", |
2184 | crc32_le(0, ar->firmware->data, ar->firmware->size)); | 2194 | crc32_le(0, ar->firmware->data, ar->firmware->size)); |
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 814719cf4f22..6206edd7c49f 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h | |||
@@ -37,6 +37,7 @@ enum ath10k_debug_mask { | |||
37 | ATH10K_DBG_TESTMODE = 0x00001000, | 37 | ATH10K_DBG_TESTMODE = 0x00001000, |
38 | ATH10K_DBG_WMI_PRINT = 0x00002000, | 38 | ATH10K_DBG_WMI_PRINT = 0x00002000, |
39 | ATH10K_DBG_PCI_PS = 0x00004000, | 39 | ATH10K_DBG_PCI_PS = 0x00004000, |
40 | ATH10K_DBG_AHB = 0x00008000, | ||
40 | ATH10K_DBG_ANY = 0xffffffff, | 41 | ATH10K_DBG_ANY = 0xffffffff, |
41 | }; | 42 | }; |
42 | 43 | ||
@@ -153,6 +154,12 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) | |||
153 | #ifdef CONFIG_MAC80211_DEBUGFS | 154 | #ifdef CONFIG_MAC80211_DEBUGFS |
154 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 155 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
155 | struct ieee80211_sta *sta, struct dentry *dir); | 156 | struct ieee80211_sta *sta, struct dentry *dir); |
157 | void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *peer); | ||
158 | #else | ||
159 | static inline void ath10k_sta_update_rx_duration(struct ath10k *ar, | ||
160 | struct list_head *peer) | ||
161 | { | ||
162 | } | ||
156 | #endif /* CONFIG_MAC80211_DEBUGFS */ | 163 | #endif /* CONFIG_MAC80211_DEBUGFS */ |
157 | 164 | ||
158 | #ifdef CONFIG_ATH10K_DEBUG | 165 | #ifdef CONFIG_ATH10K_DEBUG |
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 95b5c49374e0..67ef75b60567 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c | |||
@@ -18,6 +18,23 @@ | |||
18 | #include "wmi-ops.h" | 18 | #include "wmi-ops.h" |
19 | #include "debug.h" | 19 | #include "debug.h" |
20 | 20 | ||
21 | void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head) | ||
22 | { struct ieee80211_sta *sta; | ||
23 | struct ath10k_fw_stats_peer *peer; | ||
24 | struct ath10k_sta *arsta; | ||
25 | |||
26 | rcu_read_lock(); | ||
27 | list_for_each_entry(peer, head, list) { | ||
28 | sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr, | ||
29 | NULL); | ||
30 | if (!sta) | ||
31 | continue; | ||
32 | arsta = (struct ath10k_sta *)sta->drv_priv; | ||
33 | arsta->rx_duration += (u64)peer->rx_duration; | ||
34 | } | ||
35 | rcu_read_unlock(); | ||
36 | } | ||
37 | |||
21 | static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, | 38 | static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, |
22 | char __user *user_buf, | 39 | char __user *user_buf, |
23 | size_t count, loff_t *ppos) | 40 | size_t count, loff_t *ppos) |
@@ -232,6 +249,28 @@ static const struct file_operations fops_delba = { | |||
232 | .llseek = default_llseek, | 249 | .llseek = default_llseek, |
233 | }; | 250 | }; |
234 | 251 | ||
252 | static ssize_t ath10k_dbg_sta_read_rx_duration(struct file *file, | ||
253 | char __user *user_buf, | ||
254 | size_t count, loff_t *ppos) | ||
255 | { | ||
256 | struct ieee80211_sta *sta = file->private_data; | ||
257 | struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; | ||
258 | char buf[100]; | ||
259 | int len = 0; | ||
260 | |||
261 | len = scnprintf(buf, sizeof(buf), | ||
262 | "%llu usecs\n", arsta->rx_duration); | ||
263 | |||
264 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
265 | } | ||
266 | |||
267 | static const struct file_operations fops_rx_duration = { | ||
268 | .read = ath10k_dbg_sta_read_rx_duration, | ||
269 | .open = simple_open, | ||
270 | .owner = THIS_MODULE, | ||
271 | .llseek = default_llseek, | ||
272 | }; | ||
273 | |||
235 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 274 | void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
236 | struct ieee80211_sta *sta, struct dentry *dir) | 275 | struct ieee80211_sta *sta, struct dentry *dir) |
237 | { | 276 | { |
@@ -240,4 +279,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
240 | debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba); | 279 | debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba); |
241 | debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp); | 280 | debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp); |
242 | debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba); | 281 | debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba); |
282 | debugfs_create_file("rx_duration", S_IRUGO, dir, sta, | ||
283 | &fops_rx_duration); | ||
243 | } | 284 | } |
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 3e6ba63dfdff..7561f22f10f9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c | |||
@@ -131,12 +131,12 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = { | |||
131 | [HTT_10_4_T2H_MSG_TYPE_AGGR_CONF] = HTT_T2H_MSG_TYPE_AGGR_CONF, | 131 | [HTT_10_4_T2H_MSG_TYPE_AGGR_CONF] = HTT_T2H_MSG_TYPE_AGGR_CONF, |
132 | [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND] = | 132 | [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND] = |
133 | HTT_T2H_MSG_TYPE_TX_FETCH_IND, | 133 | HTT_T2H_MSG_TYPE_TX_FETCH_IND, |
134 | [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF] = | 134 | [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM] = |
135 | HTT_T2H_MSG_TYPE_TX_FETCH_CONF, | 135 | HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, |
136 | [HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD] = | 136 | [HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD] = |
137 | HTT_T2H_MSG_TYPE_STATS_NOUPLOAD, | 137 | HTT_T2H_MSG_TYPE_STATS_NOUPLOAD, |
138 | [HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND] = | 138 | [HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] = |
139 | HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND, | 139 | HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, |
140 | }; | 140 | }; |
141 | 141 | ||
142 | int ath10k_htt_connect(struct ath10k_htt *htt) | 142 | int ath10k_htt_connect(struct ath10k_htt *htt) |
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 47ca048feaf0..13391ea4422d 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
@@ -52,6 +52,7 @@ enum htt_h2t_msg_type { /* host-to-target */ | |||
52 | /* This command is used for sending management frames in HTT < 3.0. | 52 | /* This command is used for sending management frames in HTT < 3.0. |
53 | * HTT >= 3.0 uses TX_FRM for everything. */ | 53 | * HTT >= 3.0 uses TX_FRM for everything. */ |
54 | HTT_H2T_MSG_TYPE_MGMT_TX = 7, | 54 | HTT_H2T_MSG_TYPE_MGMT_TX = 7, |
55 | HTT_H2T_MSG_TYPE_TX_FETCH_RESP = 11, | ||
55 | 56 | ||
56 | HTT_H2T_NUM_MSGS /* keep this last */ | 57 | HTT_H2T_NUM_MSGS /* keep this last */ |
57 | }; | 58 | }; |
@@ -413,10 +414,10 @@ enum htt_10_4_t2h_msg_type { | |||
413 | HTT_10_4_T2H_MSG_TYPE_EN_STATS = 0x14, | 414 | HTT_10_4_T2H_MSG_TYPE_EN_STATS = 0x14, |
414 | HTT_10_4_T2H_MSG_TYPE_AGGR_CONF = 0x15, | 415 | HTT_10_4_T2H_MSG_TYPE_AGGR_CONF = 0x15, |
415 | HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND = 0x16, | 416 | HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND = 0x16, |
416 | HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF = 0x17, | 417 | HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM = 0x17, |
417 | HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18, | 418 | HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18, |
418 | /* 0x19 to 0x2f are reserved */ | 419 | /* 0x19 to 0x2f are reserved */ |
419 | HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND = 0x30, | 420 | HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30, |
420 | /* keep this last */ | 421 | /* keep this last */ |
421 | HTT_10_4_T2H_NUM_MSGS | 422 | HTT_10_4_T2H_NUM_MSGS |
422 | }; | 423 | }; |
@@ -449,8 +450,8 @@ enum htt_t2h_msg_type { | |||
449 | HTT_T2H_MSG_TYPE_TEST, | 450 | HTT_T2H_MSG_TYPE_TEST, |
450 | HTT_T2H_MSG_TYPE_EN_STATS, | 451 | HTT_T2H_MSG_TYPE_EN_STATS, |
451 | HTT_T2H_MSG_TYPE_TX_FETCH_IND, | 452 | HTT_T2H_MSG_TYPE_TX_FETCH_IND, |
452 | HTT_T2H_MSG_TYPE_TX_FETCH_CONF, | 453 | HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, |
453 | HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND, | 454 | HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, |
454 | /* keep this last */ | 455 | /* keep this last */ |
455 | HTT_T2H_NUM_MSGS | 456 | HTT_T2H_NUM_MSGS |
456 | }; | 457 | }; |
@@ -1306,9 +1307,43 @@ struct htt_frag_desc_bank_id { | |||
1306 | * so we use a conservatively safe value for now */ | 1307 | * so we use a conservatively safe value for now */ |
1307 | #define HTT_FRAG_DESC_BANK_MAX 4 | 1308 | #define HTT_FRAG_DESC_BANK_MAX 4 |
1308 | 1309 | ||
1309 | #define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03 | 1310 | #define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03 |
1310 | #define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0 | 1311 | #define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0 |
1311 | #define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP (1 << 2) | 1312 | #define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP BIT(2) |
1313 | #define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID BIT(3) | ||
1314 | #define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_MASK BIT(4) | ||
1315 | #define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_LSB 4 | ||
1316 | |||
1317 | enum htt_q_depth_type { | ||
1318 | HTT_Q_DEPTH_TYPE_BYTES = 0, | ||
1319 | HTT_Q_DEPTH_TYPE_MSDUS = 1, | ||
1320 | }; | ||
1321 | |||
1322 | #define HTT_TX_Q_STATE_NUM_PEERS (TARGET_10_4_NUM_QCACHE_PEERS_MAX + \ | ||
1323 | TARGET_10_4_NUM_VDEVS) | ||
1324 | #define HTT_TX_Q_STATE_NUM_TIDS 8 | ||
1325 | #define HTT_TX_Q_STATE_ENTRY_SIZE 1 | ||
1326 | #define HTT_TX_Q_STATE_ENTRY_MULTIPLIER 0 | ||
1327 | |||
1328 | /** | ||
1329 | * htt_q_state_conf - part of htt_frag_desc_bank_cfg for host q state config | ||
1330 | * | ||
1331 | * Defines host q state format and behavior. See htt_q_state. | ||
1332 | * | ||
1333 | * @record_size: Defines the size of each host q entry in bytes. In practice | ||
1334 | * however firmware (at least 10.4.3-00191) ignores this host | ||
1335 | * configuration value and uses hardcoded value of 1. | ||
1336 | * @record_multiplier: This is valid only when q depth type is MSDUs. It | ||
1337 | * defines the exponent for the power of 2 multiplication. | ||
1338 | */ | ||
1339 | struct htt_q_state_conf { | ||
1340 | __le32 paddr; | ||
1341 | __le16 num_peers; | ||
1342 | __le16 num_tids; | ||
1343 | u8 record_size; | ||
1344 | u8 record_multiplier; | ||
1345 | u8 pad[2]; | ||
1346 | } __packed; | ||
1312 | 1347 | ||
1313 | struct htt_frag_desc_bank_cfg { | 1348 | struct htt_frag_desc_bank_cfg { |
1314 | u8 info; /* HTT_FRAG_DESC_BANK_CFG_INFO_ */ | 1349 | u8 info; /* HTT_FRAG_DESC_BANK_CFG_INFO_ */ |
@@ -1316,6 +1351,114 @@ struct htt_frag_desc_bank_cfg { | |||
1316 | u8 desc_size; | 1351 | u8 desc_size; |
1317 | __le32 bank_base_addrs[HTT_FRAG_DESC_BANK_MAX]; | 1352 | __le32 bank_base_addrs[HTT_FRAG_DESC_BANK_MAX]; |
1318 | struct htt_frag_desc_bank_id bank_id[HTT_FRAG_DESC_BANK_MAX]; | 1353 | struct htt_frag_desc_bank_id bank_id[HTT_FRAG_DESC_BANK_MAX]; |
1354 | struct htt_q_state_conf q_state; | ||
1355 | } __packed; | ||
1356 | |||
1357 | #define HTT_TX_Q_STATE_ENTRY_COEFFICIENT 128 | ||
1358 | #define HTT_TX_Q_STATE_ENTRY_FACTOR_MASK 0x3f | ||
1359 | #define HTT_TX_Q_STATE_ENTRY_FACTOR_LSB 0 | ||
1360 | #define HTT_TX_Q_STATE_ENTRY_EXP_MASK 0xc0 | ||
1361 | #define HTT_TX_Q_STATE_ENTRY_EXP_LSB 6 | ||
1362 | |||
1363 | /** | ||
1364 | * htt_q_state - shared between host and firmware via DMA | ||
1365 | * | ||
1366 | * This structure is used for the host to expose it's software queue state to | ||
1367 | * firmware so that its rate control can schedule fetch requests for optimized | ||
1368 | * performance. This is most notably used for MU-MIMO aggregation when multiple | ||
1369 | * MU clients are connected. | ||
1370 | * | ||
1371 | * @count: Each element defines the host queue depth. When q depth type was | ||
1372 | * configured as HTT_Q_DEPTH_TYPE_BYTES then each entry is defined as: | ||
1373 | * FACTOR * 128 * 8^EXP (see HTT_TX_Q_STATE_ENTRY_FACTOR_MASK and | ||
1374 | * HTT_TX_Q_STATE_ENTRY_EXP_MASK). When q depth type was configured as | ||
1375 | * HTT_Q_DEPTH_TYPE_MSDUS the number of packets is scaled by 2 ** | ||
1376 | * record_multiplier (see htt_q_state_conf). | ||
1377 | * @map: Used by firmware to quickly check which host queues are not empty. It | ||
1378 | * is a bitmap simply saying. | ||
1379 | * @seq: Used by firmware to quickly check if the host queues were updated | ||
1380 | * since it last checked. | ||
1381 | * | ||
1382 | * FIXME: Is the q_state map[] size calculation really correct? | ||
1383 | */ | ||
1384 | struct htt_q_state { | ||
1385 | u8 count[HTT_TX_Q_STATE_NUM_TIDS][HTT_TX_Q_STATE_NUM_PEERS]; | ||
1386 | u32 map[HTT_TX_Q_STATE_NUM_TIDS][(HTT_TX_Q_STATE_NUM_PEERS + 31) / 32]; | ||
1387 | __le32 seq; | ||
1388 | } __packed; | ||
1389 | |||
1390 | #define HTT_TX_FETCH_RECORD_INFO_PEER_ID_MASK 0x0fff | ||
1391 | #define HTT_TX_FETCH_RECORD_INFO_PEER_ID_LSB 0 | ||
1392 | #define HTT_TX_FETCH_RECORD_INFO_TID_MASK 0xf000 | ||
1393 | #define HTT_TX_FETCH_RECORD_INFO_TID_LSB 12 | ||
1394 | |||
1395 | struct htt_tx_fetch_record { | ||
1396 | __le16 info; /* HTT_TX_FETCH_IND_RECORD_INFO_ */ | ||
1397 | __le16 num_msdus; | ||
1398 | __le32 num_bytes; | ||
1399 | } __packed; | ||
1400 | |||
1401 | struct htt_tx_fetch_ind { | ||
1402 | u8 pad0; | ||
1403 | __le16 fetch_seq_num; | ||
1404 | __le32 token; | ||
1405 | __le16 num_resp_ids; | ||
1406 | __le16 num_records; | ||
1407 | struct htt_tx_fetch_record records[0]; | ||
1408 | __le32 resp_ids[0]; /* ath10k_htt_get_tx_fetch_ind_resp_ids() */ | ||
1409 | } __packed; | ||
1410 | |||
1411 | static inline void * | ||
1412 | ath10k_htt_get_tx_fetch_ind_resp_ids(struct htt_tx_fetch_ind *ind) | ||
1413 | { | ||
1414 | return (void *)&ind->records[le16_to_cpu(ind->num_records)]; | ||
1415 | } | ||
1416 | |||
1417 | struct htt_tx_fetch_resp { | ||
1418 | u8 pad0; | ||
1419 | __le16 resp_id; | ||
1420 | __le16 fetch_seq_num; | ||
1421 | __le16 num_records; | ||
1422 | __le32 token; | ||
1423 | struct htt_tx_fetch_record records[0]; | ||
1424 | } __packed; | ||
1425 | |||
1426 | struct htt_tx_fetch_confirm { | ||
1427 | u8 pad0; | ||
1428 | __le16 num_resp_ids; | ||
1429 | __le32 resp_ids[0]; | ||
1430 | } __packed; | ||
1431 | |||
1432 | enum htt_tx_mode_switch_mode { | ||
1433 | HTT_TX_MODE_SWITCH_PUSH = 0, | ||
1434 | HTT_TX_MODE_SWITCH_PUSH_PULL = 1, | ||
1435 | }; | ||
1436 | |||
1437 | #define HTT_TX_MODE_SWITCH_IND_INFO0_ENABLE BIT(0) | ||
1438 | #define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_MASK 0xfffe | ||
1439 | #define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_LSB 1 | ||
1440 | |||
1441 | #define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_MASK 0x0003 | ||
1442 | #define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_LSB 0 | ||
1443 | #define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_MASK 0xfffc | ||
1444 | #define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_LSB 2 | ||
1445 | |||
1446 | #define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_MASK 0x0fff | ||
1447 | #define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_LSB 0 | ||
1448 | #define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_MASK 0xf000 | ||
1449 | #define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_LSB 12 | ||
1450 | |||
1451 | struct htt_tx_mode_switch_record { | ||
1452 | __le16 info0; /* HTT_TX_MODE_SWITCH_RECORD_INFO0_ */ | ||
1453 | __le16 num_max_msdus; | ||
1454 | } __packed; | ||
1455 | |||
1456 | struct htt_tx_mode_switch_ind { | ||
1457 | u8 pad0; | ||
1458 | __le16 info0; /* HTT_TX_MODE_SWITCH_IND_INFO0_ */ | ||
1459 | __le16 info1; /* HTT_TX_MODE_SWITCH_IND_INFO1_ */ | ||
1460 | u8 pad1[2]; | ||
1461 | struct htt_tx_mode_switch_record records[0]; | ||
1319 | } __packed; | 1462 | } __packed; |
1320 | 1463 | ||
1321 | union htt_rx_pn_t { | 1464 | union htt_rx_pn_t { |
@@ -1340,6 +1483,7 @@ struct htt_cmd { | |||
1340 | struct htt_oob_sync_req oob_sync_req; | 1483 | struct htt_oob_sync_req oob_sync_req; |
1341 | struct htt_aggr_conf aggr_conf; | 1484 | struct htt_aggr_conf aggr_conf; |
1342 | struct htt_frag_desc_bank_cfg frag_desc_bank_cfg; | 1485 | struct htt_frag_desc_bank_cfg frag_desc_bank_cfg; |
1486 | struct htt_tx_fetch_resp tx_fetch_resp; | ||
1343 | }; | 1487 | }; |
1344 | } __packed; | 1488 | } __packed; |
1345 | 1489 | ||
@@ -1364,6 +1508,9 @@ struct htt_resp { | |||
1364 | struct htt_rx_pn_ind rx_pn_ind; | 1508 | struct htt_rx_pn_ind rx_pn_ind; |
1365 | struct htt_rx_offload_ind rx_offload_ind; | 1509 | struct htt_rx_offload_ind rx_offload_ind; |
1366 | struct htt_rx_in_ord_ind rx_in_ord_ind; | 1510 | struct htt_rx_in_ord_ind rx_in_ord_ind; |
1511 | struct htt_tx_fetch_ind tx_fetch_ind; | ||
1512 | struct htt_tx_fetch_confirm tx_fetch_confirm; | ||
1513 | struct htt_tx_mode_switch_ind tx_mode_switch_ind; | ||
1367 | }; | 1514 | }; |
1368 | } __packed; | 1515 | } __packed; |
1369 | 1516 | ||
@@ -1518,6 +1665,14 @@ struct ath10k_htt { | |||
1518 | dma_addr_t paddr; | 1665 | dma_addr_t paddr; |
1519 | struct ath10k_htt_txbuf *vaddr; | 1666 | struct ath10k_htt_txbuf *vaddr; |
1520 | } txbuf; | 1667 | } txbuf; |
1668 | |||
1669 | struct { | ||
1670 | struct htt_q_state *vaddr; | ||
1671 | dma_addr_t paddr; | ||
1672 | u16 num_peers; | ||
1673 | u16 num_tids; | ||
1674 | enum htt_q_depth_type type; | ||
1675 | } tx_q_state; | ||
1521 | }; | 1676 | }; |
1522 | 1677 | ||
1523 | #define RX_HTT_HDR_STATUS_LEN 64 | 1678 | #define RX_HTT_HDR_STATUS_LEN 64 |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 91afa3ae414c..ae9b686a4e91 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -2011,9 +2011,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
2011 | break; | 2011 | break; |
2012 | } | 2012 | } |
2013 | case HTT_T2H_MSG_TYPE_RX_IND: | 2013 | case HTT_T2H_MSG_TYPE_RX_IND: |
2014 | spin_lock_bh(&htt->rx_ring.lock); | 2014 | skb_queue_tail(&htt->rx_compl_q, skb); |
2015 | __skb_queue_tail(&htt->rx_compl_q, skb); | ||
2016 | spin_unlock_bh(&htt->rx_ring.lock); | ||
2017 | tasklet_schedule(&htt->txrx_compl_task); | 2015 | tasklet_schedule(&htt->txrx_compl_task); |
2018 | return; | 2016 | return; |
2019 | case HTT_T2H_MSG_TYPE_PEER_MAP: { | 2017 | case HTT_T2H_MSG_TYPE_PEER_MAP: { |
@@ -2111,9 +2109,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
2111 | break; | 2109 | break; |
2112 | } | 2110 | } |
2113 | case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: { | 2111 | case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: { |
2114 | spin_lock_bh(&htt->rx_ring.lock); | 2112 | skb_queue_tail(&htt->rx_in_ord_compl_q, skb); |
2115 | __skb_queue_tail(&htt->rx_in_ord_compl_q, skb); | ||
2116 | spin_unlock_bh(&htt->rx_ring.lock); | ||
2117 | tasklet_schedule(&htt->txrx_compl_task); | 2113 | tasklet_schedule(&htt->txrx_compl_task); |
2118 | return; | 2114 | return; |
2119 | } | 2115 | } |
@@ -2123,10 +2119,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
2123 | break; | 2119 | break; |
2124 | case HTT_T2H_MSG_TYPE_AGGR_CONF: | 2120 | case HTT_T2H_MSG_TYPE_AGGR_CONF: |
2125 | break; | 2121 | break; |
2126 | case HTT_T2H_MSG_TYPE_EN_STATS: | ||
2127 | case HTT_T2H_MSG_TYPE_TX_FETCH_IND: | 2122 | case HTT_T2H_MSG_TYPE_TX_FETCH_IND: |
2128 | case HTT_T2H_MSG_TYPE_TX_FETCH_CONF: | 2123 | case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: |
2129 | case HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND: | 2124 | case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: |
2125 | /* TODO: Implement pull-push logic */ | ||
2126 | break; | ||
2127 | case HTT_T2H_MSG_TYPE_EN_STATS: | ||
2130 | default: | 2128 | default: |
2131 | ath10k_warn(ar, "htt event (%d) not handled\n", | 2129 | ath10k_warn(ar, "htt event (%d) not handled\n", |
2132 | resp->hdr.msg_type); | 2130 | resp->hdr.msg_type); |
@@ -2143,11 +2141,7 @@ EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler); | |||
2143 | void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar, | 2141 | void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar, |
2144 | struct sk_buff *skb) | 2142 | struct sk_buff *skb) |
2145 | { | 2143 | { |
2146 | struct ath10k_pktlog_10_4_hdr *hdr = | 2144 | trace_ath10k_htt_pktlog(ar, skb->data, skb->len); |
2147 | (struct ath10k_pktlog_10_4_hdr *)skb->data; | ||
2148 | |||
2149 | trace_ath10k_htt_pktlog(ar, hdr->payload, | ||
2150 | sizeof(*hdr) + __le16_to_cpu(hdr->size)); | ||
2151 | dev_kfree_skb_any(skb); | 2145 | dev_kfree_skb_any(skb); |
2152 | } | 2146 | } |
2153 | EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler); | 2147 | EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler); |
@@ -2156,24 +2150,46 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) | |||
2156 | { | 2150 | { |
2157 | struct ath10k_htt *htt = (struct ath10k_htt *)ptr; | 2151 | struct ath10k_htt *htt = (struct ath10k_htt *)ptr; |
2158 | struct ath10k *ar = htt->ar; | 2152 | struct ath10k *ar = htt->ar; |
2153 | struct sk_buff_head tx_q; | ||
2154 | struct sk_buff_head rx_q; | ||
2155 | struct sk_buff_head rx_ind_q; | ||
2159 | struct htt_resp *resp; | 2156 | struct htt_resp *resp; |
2160 | struct sk_buff *skb; | 2157 | struct sk_buff *skb; |
2158 | unsigned long flags; | ||
2159 | |||
2160 | __skb_queue_head_init(&tx_q); | ||
2161 | __skb_queue_head_init(&rx_q); | ||
2162 | __skb_queue_head_init(&rx_ind_q); | ||
2161 | 2163 | ||
2162 | while ((skb = skb_dequeue(&htt->tx_compl_q))) { | 2164 | spin_lock_irqsave(&htt->tx_compl_q.lock, flags); |
2165 | skb_queue_splice_init(&htt->tx_compl_q, &tx_q); | ||
2166 | spin_unlock_irqrestore(&htt->tx_compl_q.lock, flags); | ||
2167 | |||
2168 | spin_lock_irqsave(&htt->rx_compl_q.lock, flags); | ||
2169 | skb_queue_splice_init(&htt->rx_compl_q, &rx_q); | ||
2170 | spin_unlock_irqrestore(&htt->rx_compl_q.lock, flags); | ||
2171 | |||
2172 | spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags); | ||
2173 | skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q); | ||
2174 | spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags); | ||
2175 | |||
2176 | while ((skb = __skb_dequeue(&tx_q))) { | ||
2163 | ath10k_htt_rx_frm_tx_compl(htt->ar, skb); | 2177 | ath10k_htt_rx_frm_tx_compl(htt->ar, skb); |
2164 | dev_kfree_skb_any(skb); | 2178 | dev_kfree_skb_any(skb); |
2165 | } | 2179 | } |
2166 | 2180 | ||
2167 | spin_lock_bh(&htt->rx_ring.lock); | 2181 | while ((skb = __skb_dequeue(&rx_q))) { |
2168 | while ((skb = __skb_dequeue(&htt->rx_compl_q))) { | ||
2169 | resp = (struct htt_resp *)skb->data; | 2182 | resp = (struct htt_resp *)skb->data; |
2183 | spin_lock_bh(&htt->rx_ring.lock); | ||
2170 | ath10k_htt_rx_handler(htt, &resp->rx_ind); | 2184 | ath10k_htt_rx_handler(htt, &resp->rx_ind); |
2185 | spin_unlock_bh(&htt->rx_ring.lock); | ||
2171 | dev_kfree_skb_any(skb); | 2186 | dev_kfree_skb_any(skb); |
2172 | } | 2187 | } |
2173 | 2188 | ||
2174 | while ((skb = __skb_dequeue(&htt->rx_in_ord_compl_q))) { | 2189 | while ((skb = __skb_dequeue(&rx_ind_q))) { |
2190 | spin_lock_bh(&htt->rx_ring.lock); | ||
2175 | ath10k_htt_rx_in_ord_ind(ar, skb); | 2191 | ath10k_htt_rx_in_ord_ind(ar, skb); |
2192 | spin_unlock_bh(&htt->rx_ring.lock); | ||
2176 | dev_kfree_skb_any(skb); | 2193 | dev_kfree_skb_any(skb); |
2177 | } | 2194 | } |
2178 | spin_unlock_bh(&htt->rx_ring.lock); | ||
2179 | } | 2195 | } |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index b3adadb5f824..95acb727c068 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -97,6 +97,85 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) | |||
97 | idr_remove(&htt->pending_tx, msdu_id); | 97 | idr_remove(&htt->pending_tx, msdu_id); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void ath10k_htt_tx_free_cont_frag_desc(struct ath10k_htt *htt) | ||
101 | { | ||
102 | size_t size; | ||
103 | |||
104 | if (!htt->frag_desc.vaddr) | ||
105 | return; | ||
106 | |||
107 | size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); | ||
108 | |||
109 | dma_free_coherent(htt->ar->dev, | ||
110 | size, | ||
111 | htt->frag_desc.vaddr, | ||
112 | htt->frag_desc.paddr); | ||
113 | } | ||
114 | |||
115 | static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt) | ||
116 | { | ||
117 | struct ath10k *ar = htt->ar; | ||
118 | size_t size; | ||
119 | |||
120 | if (!ar->hw_params.continuous_frag_desc) | ||
121 | return 0; | ||
122 | |||
123 | size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); | ||
124 | htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size, | ||
125 | &htt->frag_desc.paddr, | ||
126 | GFP_KERNEL); | ||
127 | if (!htt->frag_desc.vaddr) { | ||
128 | ath10k_err(ar, "failed to alloc fragment desc memory\n"); | ||
129 | return -ENOMEM; | ||
130 | } | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static void ath10k_htt_tx_free_txq(struct ath10k_htt *htt) | ||
136 | { | ||
137 | struct ath10k *ar = htt->ar; | ||
138 | size_t size; | ||
139 | |||
140 | if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) | ||
141 | return; | ||
142 | |||
143 | size = sizeof(*htt->tx_q_state.vaddr); | ||
144 | |||
145 | dma_unmap_single(ar->dev, htt->tx_q_state.paddr, size, DMA_TO_DEVICE); | ||
146 | kfree(htt->tx_q_state.vaddr); | ||
147 | } | ||
148 | |||
149 | static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt) | ||
150 | { | ||
151 | struct ath10k *ar = htt->ar; | ||
152 | size_t size; | ||
153 | int ret; | ||
154 | |||
155 | if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) | ||
156 | return 0; | ||
157 | |||
158 | htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS; | ||
159 | htt->tx_q_state.num_tids = HTT_TX_Q_STATE_NUM_TIDS; | ||
160 | htt->tx_q_state.type = HTT_Q_DEPTH_TYPE_BYTES; | ||
161 | |||
162 | size = sizeof(*htt->tx_q_state.vaddr); | ||
163 | htt->tx_q_state.vaddr = kzalloc(size, GFP_KERNEL); | ||
164 | if (!htt->tx_q_state.vaddr) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | htt->tx_q_state.paddr = dma_map_single(ar->dev, htt->tx_q_state.vaddr, | ||
168 | size, DMA_TO_DEVICE); | ||
169 | ret = dma_mapping_error(ar->dev, htt->tx_q_state.paddr); | ||
170 | if (ret) { | ||
171 | ath10k_warn(ar, "failed to dma map tx_q_state: %d\n", ret); | ||
172 | kfree(htt->tx_q_state.vaddr); | ||
173 | return -EIO; | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
100 | int ath10k_htt_tx_alloc(struct ath10k_htt *htt) | 179 | int ath10k_htt_tx_alloc(struct ath10k_htt *htt) |
101 | { | 180 | { |
102 | struct ath10k *ar = htt->ar; | 181 | struct ath10k *ar = htt->ar; |
@@ -118,29 +197,32 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) | |||
118 | goto free_idr_pending_tx; | 197 | goto free_idr_pending_tx; |
119 | } | 198 | } |
120 | 199 | ||
121 | if (!ar->hw_params.continuous_frag_desc) | 200 | ret = ath10k_htt_tx_alloc_cont_frag_desc(htt); |
122 | goto skip_frag_desc_alloc; | 201 | if (ret) { |
123 | 202 | ath10k_err(ar, "failed to alloc cont frag desc: %d\n", ret); | |
124 | size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); | ||
125 | htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size, | ||
126 | &htt->frag_desc.paddr, | ||
127 | GFP_KERNEL); | ||
128 | if (!htt->frag_desc.vaddr) { | ||
129 | ath10k_warn(ar, "failed to alloc fragment desc memory\n"); | ||
130 | ret = -ENOMEM; | ||
131 | goto free_txbuf; | 203 | goto free_txbuf; |
132 | } | 204 | } |
133 | 205 | ||
134 | skip_frag_desc_alloc: | 206 | ret = ath10k_htt_tx_alloc_txq(htt); |
207 | if (ret) { | ||
208 | ath10k_err(ar, "failed to alloc txq: %d\n", ret); | ||
209 | goto free_frag_desc; | ||
210 | } | ||
211 | |||
135 | return 0; | 212 | return 0; |
136 | 213 | ||
214 | free_frag_desc: | ||
215 | ath10k_htt_tx_free_cont_frag_desc(htt); | ||
216 | |||
137 | free_txbuf: | 217 | free_txbuf: |
138 | size = htt->max_num_pending_tx * | 218 | size = htt->max_num_pending_tx * |
139 | sizeof(struct ath10k_htt_txbuf); | 219 | sizeof(struct ath10k_htt_txbuf); |
140 | dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, | 220 | dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, |
141 | htt->txbuf.paddr); | 221 | htt->txbuf.paddr); |
222 | |||
142 | free_idr_pending_tx: | 223 | free_idr_pending_tx: |
143 | idr_destroy(&htt->pending_tx); | 224 | idr_destroy(&htt->pending_tx); |
225 | |||
144 | return ret; | 226 | return ret; |
145 | } | 227 | } |
146 | 228 | ||
@@ -174,12 +256,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) | |||
174 | htt->txbuf.paddr); | 256 | htt->txbuf.paddr); |
175 | } | 257 | } |
176 | 258 | ||
177 | if (htt->frag_desc.vaddr) { | 259 | ath10k_htt_tx_free_txq(htt); |
178 | size = htt->max_num_pending_tx * | 260 | ath10k_htt_tx_free_cont_frag_desc(htt); |
179 | sizeof(struct htt_msdu_ext_desc); | ||
180 | dma_free_coherent(htt->ar->dev, size, htt->frag_desc.vaddr, | ||
181 | htt->frag_desc.paddr); | ||
182 | } | ||
183 | } | 261 | } |
184 | 262 | ||
185 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) | 263 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
@@ -268,7 +346,9 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) | |||
268 | struct ath10k *ar = htt->ar; | 346 | struct ath10k *ar = htt->ar; |
269 | struct sk_buff *skb; | 347 | struct sk_buff *skb; |
270 | struct htt_cmd *cmd; | 348 | struct htt_cmd *cmd; |
349 | struct htt_frag_desc_bank_cfg *cfg; | ||
271 | int ret, size; | 350 | int ret, size; |
351 | u8 info; | ||
272 | 352 | ||
273 | if (!ar->hw_params.continuous_frag_desc) | 353 | if (!ar->hw_params.continuous_frag_desc) |
274 | return 0; | 354 | return 0; |
@@ -286,14 +366,30 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) | |||
286 | skb_put(skb, size); | 366 | skb_put(skb, size); |
287 | cmd = (struct htt_cmd *)skb->data; | 367 | cmd = (struct htt_cmd *)skb->data; |
288 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG; | 368 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG; |
289 | cmd->frag_desc_bank_cfg.info = 0; | 369 | |
290 | cmd->frag_desc_bank_cfg.num_banks = 1; | 370 | info = 0; |
291 | cmd->frag_desc_bank_cfg.desc_size = sizeof(struct htt_msdu_ext_desc); | 371 | info |= SM(htt->tx_q_state.type, |
292 | cmd->frag_desc_bank_cfg.bank_base_addrs[0] = | 372 | HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE); |
293 | __cpu_to_le32(htt->frag_desc.paddr); | 373 | |
294 | cmd->frag_desc_bank_cfg.bank_id[0].bank_min_id = 0; | 374 | if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) |
295 | cmd->frag_desc_bank_cfg.bank_id[0].bank_max_id = | 375 | info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID; |
296 | __cpu_to_le16(htt->max_num_pending_tx - 1); | 376 | |
377 | cfg = &cmd->frag_desc_bank_cfg; | ||
378 | cfg->info = info; | ||
379 | cfg->num_banks = 1; | ||
380 | cfg->desc_size = sizeof(struct htt_msdu_ext_desc); | ||
381 | cfg->bank_base_addrs[0] = __cpu_to_le32(htt->frag_desc.paddr); | ||
382 | cfg->bank_id[0].bank_min_id = 0; | ||
383 | cfg->bank_id[0].bank_max_id = __cpu_to_le16(htt->max_num_pending_tx - | ||
384 | 1); | ||
385 | |||
386 | cfg->q_state.paddr = cpu_to_le32(htt->tx_q_state.paddr); | ||
387 | cfg->q_state.num_peers = cpu_to_le16(htt->tx_q_state.num_peers); | ||
388 | cfg->q_state.num_tids = cpu_to_le16(htt->tx_q_state.num_tids); | ||
389 | cfg->q_state.record_size = HTT_TX_Q_STATE_ENTRY_SIZE; | ||
390 | cfg->q_state.record_multiplier = HTT_TX_Q_STATE_ENTRY_MULTIPLIER; | ||
391 | |||
392 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt frag desc bank cmd\n"); | ||
297 | 393 | ||
298 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); | 394 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); |
299 | if (ret) { | 395 | if (ret) { |
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 7b84d08a5154..f544d48518c3 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c | |||
@@ -109,6 +109,38 @@ const struct ath10k_hw_regs qca99x0_regs = { | |||
109 | .pcie_intr_clr_address = 0x00000010, | 109 | .pcie_intr_clr_address = 0x00000010, |
110 | }; | 110 | }; |
111 | 111 | ||
112 | const struct ath10k_hw_regs qca4019_regs = { | ||
113 | .rtc_soc_base_address = 0x00080000, | ||
114 | .soc_core_base_address = 0x00082000, | ||
115 | .ce_wrapper_base_address = 0x0004d000, | ||
116 | .ce0_base_address = 0x0004a000, | ||
117 | .ce1_base_address = 0x0004a400, | ||
118 | .ce2_base_address = 0x0004a800, | ||
119 | .ce3_base_address = 0x0004ac00, | ||
120 | .ce4_base_address = 0x0004b000, | ||
121 | .ce5_base_address = 0x0004b400, | ||
122 | .ce6_base_address = 0x0004b800, | ||
123 | .ce7_base_address = 0x0004bc00, | ||
124 | /* qca4019 supports upto 12 copy engines. Since base address | ||
125 | * of ce8 to ce11 are not directly referred in the code, | ||
126 | * no need have them in separate members in this table. | ||
127 | * Copy Engine Address | ||
128 | * CE8 0x0004c000 | ||
129 | * CE9 0x0004c400 | ||
130 | * CE10 0x0004c800 | ||
131 | * CE11 0x0004cc00 | ||
132 | */ | ||
133 | .soc_reset_control_si0_rst_mask = 0x00000001, | ||
134 | .soc_reset_control_ce_rst_mask = 0x00000100, | ||
135 | .soc_chip_id_address = 0x000000ec, | ||
136 | .fw_indicator_address = 0x0004f00c, | ||
137 | .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c, | ||
138 | .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, | ||
139 | .pcie_intr_fw_mask = 0x00100000, | ||
140 | .pcie_intr_ce_mask_all = 0x000fff00, | ||
141 | .pcie_intr_clr_address = 0x00000010, | ||
142 | }; | ||
143 | |||
112 | const struct ath10k_hw_values qca988x_values = { | 144 | const struct ath10k_hw_values qca988x_values = { |
113 | .rtc_state_val_on = 3, | 145 | .rtc_state_val_on = 3, |
114 | .ce_count = 8, | 146 | .ce_count = 8, |
@@ -136,6 +168,13 @@ const struct ath10k_hw_values qca99x0_values = { | |||
136 | .ce_desc_meta_data_lsb = 4, | 168 | .ce_desc_meta_data_lsb = 4, |
137 | }; | 169 | }; |
138 | 170 | ||
171 | const struct ath10k_hw_values qca4019_values = { | ||
172 | .ce_count = 12, | ||
173 | .num_target_ce_config_wlan = 10, | ||
174 | .ce_desc_meta_data_mask = 0xFFF0, | ||
175 | .ce_desc_meta_data_lsb = 4, | ||
176 | }; | ||
177 | |||
139 | void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, | 178 | void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, |
140 | u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) | 179 | u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) |
141 | { | 180 | { |
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 0678831e8671..f0cfbc745c97 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
@@ -106,6 +106,14 @@ enum qca9377_chip_id_rev { | |||
106 | #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" | 106 | #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" |
107 | #define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 | 107 | #define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 |
108 | 108 | ||
109 | /* QCA4019 1.0 definitions */ | ||
110 | #define QCA4019_HW_1_0_DEV_VERSION 0x01000000 | ||
111 | #define QCA4019_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA4019/hw1.0" | ||
112 | #define QCA4019_HW_1_0_FW_FILE "firmware.bin" | ||
113 | #define QCA4019_HW_1_0_OTP_FILE "otp.bin" | ||
114 | #define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin" | ||
115 | #define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234 | ||
116 | |||
109 | #define ATH10K_FW_API2_FILE "firmware-2.bin" | 117 | #define ATH10K_FW_API2_FILE "firmware-2.bin" |
110 | #define ATH10K_FW_API3_FILE "firmware-3.bin" | 118 | #define ATH10K_FW_API3_FILE "firmware-3.bin" |
111 | 119 | ||
@@ -200,6 +208,7 @@ enum ath10k_hw_rev { | |||
200 | ATH10K_HW_QCA6174, | 208 | ATH10K_HW_QCA6174, |
201 | ATH10K_HW_QCA99X0, | 209 | ATH10K_HW_QCA99X0, |
202 | ATH10K_HW_QCA9377, | 210 | ATH10K_HW_QCA9377, |
211 | ATH10K_HW_QCA4019, | ||
203 | }; | 212 | }; |
204 | 213 | ||
205 | struct ath10k_hw_regs { | 214 | struct ath10k_hw_regs { |
@@ -232,6 +241,7 @@ struct ath10k_hw_regs { | |||
232 | extern const struct ath10k_hw_regs qca988x_regs; | 241 | extern const struct ath10k_hw_regs qca988x_regs; |
233 | extern const struct ath10k_hw_regs qca6174_regs; | 242 | extern const struct ath10k_hw_regs qca6174_regs; |
234 | extern const struct ath10k_hw_regs qca99x0_regs; | 243 | extern const struct ath10k_hw_regs qca99x0_regs; |
244 | extern const struct ath10k_hw_regs qca4019_regs; | ||
235 | 245 | ||
236 | struct ath10k_hw_values { | 246 | struct ath10k_hw_values { |
237 | u32 rtc_state_val_on; | 247 | u32 rtc_state_val_on; |
@@ -245,6 +255,7 @@ struct ath10k_hw_values { | |||
245 | extern const struct ath10k_hw_values qca988x_values; | 255 | extern const struct ath10k_hw_values qca988x_values; |
246 | extern const struct ath10k_hw_values qca6174_values; | 256 | extern const struct ath10k_hw_values qca6174_values; |
247 | extern const struct ath10k_hw_values qca99x0_values; | 257 | extern const struct ath10k_hw_values qca99x0_values; |
258 | extern const struct ath10k_hw_values qca4019_values; | ||
248 | 259 | ||
249 | void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, | 260 | void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, |
250 | u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); | 261 | u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); |
@@ -253,6 +264,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, | |||
253 | #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) | 264 | #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) |
254 | #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) | 265 | #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) |
255 | #define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) | 266 | #define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) |
267 | #define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019) | ||
256 | 268 | ||
257 | /* Known pecularities: | 269 | /* Known pecularities: |
258 | * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap | 270 | * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap |
@@ -363,14 +375,19 @@ enum ath10k_hw_4addr_pad { | |||
363 | #define TARGET_10X_MAC_AGGR_DELIM 0 | 375 | #define TARGET_10X_MAC_AGGR_DELIM 0 |
364 | #define TARGET_10X_AST_SKID_LIMIT 128 | 376 | #define TARGET_10X_AST_SKID_LIMIT 128 |
365 | #define TARGET_10X_NUM_STATIONS 128 | 377 | #define TARGET_10X_NUM_STATIONS 128 |
378 | #define TARGET_10X_TX_STATS_NUM_STATIONS 118 | ||
366 | #define TARGET_10X_NUM_PEERS ((TARGET_10X_NUM_STATIONS) + \ | 379 | #define TARGET_10X_NUM_PEERS ((TARGET_10X_NUM_STATIONS) + \ |
367 | (TARGET_10X_NUM_VDEVS)) | 380 | (TARGET_10X_NUM_VDEVS)) |
381 | #define TARGET_10X_TX_STATS_NUM_PEERS ((TARGET_10X_TX_STATS_NUM_STATIONS) + \ | ||
382 | (TARGET_10X_NUM_VDEVS)) | ||
368 | #define TARGET_10X_NUM_OFFLOAD_PEERS 0 | 383 | #define TARGET_10X_NUM_OFFLOAD_PEERS 0 |
369 | #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0 | 384 | #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0 |
370 | #define TARGET_10X_NUM_PEER_KEYS 2 | 385 | #define TARGET_10X_NUM_PEER_KEYS 2 |
371 | #define TARGET_10X_NUM_TIDS_MAX 256 | 386 | #define TARGET_10X_NUM_TIDS_MAX 256 |
372 | #define TARGET_10X_NUM_TIDS min((TARGET_10X_NUM_TIDS_MAX), \ | 387 | #define TARGET_10X_NUM_TIDS min((TARGET_10X_NUM_TIDS_MAX), \ |
373 | (TARGET_10X_NUM_PEERS) * 2) | 388 | (TARGET_10X_NUM_PEERS) * 2) |
389 | #define TARGET_10X_TX_STATS_NUM_TIDS min((TARGET_10X_NUM_TIDS_MAX), \ | ||
390 | (TARGET_10X_TX_STATS_NUM_PEERS) * 2) | ||
374 | #define TARGET_10X_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) | 391 | #define TARGET_10X_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) |
375 | #define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) | 392 | #define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) |
376 | #define TARGET_10X_RX_TIMEOUT_LO_PRI 100 | 393 | #define TARGET_10X_RX_TIMEOUT_LO_PRI 100 |
@@ -414,16 +431,11 @@ enum ath10k_hw_4addr_pad { | |||
414 | #define TARGET_10_4_ACTIVE_PEERS 0 | 431 | #define TARGET_10_4_ACTIVE_PEERS 0 |
415 | 432 | ||
416 | #define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512 | 433 | #define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512 |
417 | #define TARGET_10_4_QCACHE_ACTIVE_PEERS 50 | ||
418 | #define TARGET_10_4_NUM_OFFLOAD_PEERS 0 | 434 | #define TARGET_10_4_NUM_OFFLOAD_PEERS 0 |
419 | #define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0 | 435 | #define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0 |
420 | #define TARGET_10_4_NUM_PEER_KEYS 2 | 436 | #define TARGET_10_4_NUM_PEER_KEYS 2 |
421 | #define TARGET_10_4_TGT_NUM_TIDS ((TARGET_10_4_NUM_PEERS) * 2) | 437 | #define TARGET_10_4_TGT_NUM_TIDS ((TARGET_10_4_NUM_PEERS) * 2) |
422 | #define TARGET_10_4_AST_SKID_LIMIT 32 | 438 | #define TARGET_10_4_AST_SKID_LIMIT 32 |
423 | #define TARGET_10_4_TX_CHAIN_MASK (BIT(0) | BIT(1) | \ | ||
424 | BIT(2) | BIT(3)) | ||
425 | #define TARGET_10_4_RX_CHAIN_MASK (BIT(0) | BIT(1) | \ | ||
426 | BIT(2) | BIT(3)) | ||
427 | 439 | ||
428 | /* 100 ms for video, best-effort, and background */ | 440 | /* 100 ms for video, best-effort, and background */ |
429 | #define TARGET_10_4_RX_TIMEOUT_LO_PRI 100 | 441 | #define TARGET_10_4_RX_TIMEOUT_LO_PRI 100 |
@@ -449,7 +461,6 @@ enum ath10k_hw_4addr_pad { | |||
449 | #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 | 461 | #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 |
450 | #define TARGET_10_4_VOW_CONFIG 0 | 462 | #define TARGET_10_4_VOW_CONFIG 0 |
451 | #define TARGET_10_4_GTK_OFFLOAD_MAX_VDEV 3 | 463 | #define TARGET_10_4_GTK_OFFLOAD_MAX_VDEV 3 |
452 | #define TARGET_10_4_NUM_MSDU_DESC (1024 + 400) | ||
453 | #define TARGET_10_4_11AC_TX_MAX_FRAGS 2 | 464 | #define TARGET_10_4_11AC_TX_MAX_FRAGS 2 |
454 | #define TARGET_10_4_MAX_PEER_EXT_STATS 16 | 465 | #define TARGET_10_4_MAX_PEER_EXT_STATS 16 |
455 | #define TARGET_10_4_SMART_ANT_CAP 0 | 466 | #define TARGET_10_4_SMART_ANT_CAP 0 |
@@ -601,6 +612,7 @@ enum ath10k_hw_4addr_pad { | |||
601 | #define FW_INDICATOR_ADDRESS ar->regs->fw_indicator_address | 612 | #define FW_INDICATOR_ADDRESS ar->regs->fw_indicator_address |
602 | #define FW_IND_EVENT_PENDING 1 | 613 | #define FW_IND_EVENT_PENDING 1 |
603 | #define FW_IND_INITIALIZED 2 | 614 | #define FW_IND_INITIALIZED 2 |
615 | #define FW_IND_HOST_READY 0x80000000 | ||
604 | 616 | ||
605 | /* HOST_REG interrupt from firmware */ | 617 | /* HOST_REG interrupt from firmware */ |
606 | #define PCIE_INTR_FIRMWARE_MASK ar->regs->pcie_intr_fw_mask | 618 | #define PCIE_INTR_FIRMWARE_MASK ar->regs->pcie_intr_fw_mask |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 368de5e5a04f..78999c9de23b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -1358,10 +1358,7 @@ static int ath10k_mac_setup_bcn_p2p_ie(struct ath10k_vif *arvif, | |||
1358 | const u8 *p2p_ie; | 1358 | const u8 *p2p_ie; |
1359 | int ret; | 1359 | int ret; |
1360 | 1360 | ||
1361 | if (arvif->vdev_type != WMI_VDEV_TYPE_AP) | 1361 | if (arvif->vif->type != NL80211_IFTYPE_AP || !arvif->vif->p2p) |
1362 | return 0; | ||
1363 | |||
1364 | if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) | ||
1365 | return 0; | 1362 | return 0; |
1366 | 1363 | ||
1367 | mgmt = (void *)bcn->data; | 1364 | mgmt = (void *)bcn->data; |
@@ -3259,8 +3256,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, | |||
3259 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 3256 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
3260 | 3257 | ||
3261 | /* This is case only for P2P_GO */ | 3258 | /* This is case only for P2P_GO */ |
3262 | if (arvif->vdev_type != WMI_VDEV_TYPE_AP || | 3259 | if (vif->type != NL80211_IFTYPE_AP || !vif->p2p) |
3263 | arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) | ||
3264 | return; | 3260 | return; |
3265 | 3261 | ||
3266 | if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { | 3262 | if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { |
@@ -3988,7 +3984,7 @@ static int ath10k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) | |||
3988 | static int ath10k_start(struct ieee80211_hw *hw) | 3984 | static int ath10k_start(struct ieee80211_hw *hw) |
3989 | { | 3985 | { |
3990 | struct ath10k *ar = hw->priv; | 3986 | struct ath10k *ar = hw->priv; |
3991 | u32 burst_enable; | 3987 | u32 param; |
3992 | int ret = 0; | 3988 | int ret = 0; |
3993 | 3989 | ||
3994 | /* | 3990 | /* |
@@ -4031,13 +4027,15 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
4031 | goto err_power_down; | 4027 | goto err_power_down; |
4032 | } | 4028 | } |
4033 | 4029 | ||
4034 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1); | 4030 | param = ar->wmi.pdev_param->pmf_qos; |
4031 | ret = ath10k_wmi_pdev_set_param(ar, param, 1); | ||
4035 | if (ret) { | 4032 | if (ret) { |
4036 | ath10k_warn(ar, "failed to enable PMF QOS: %d\n", ret); | 4033 | ath10k_warn(ar, "failed to enable PMF QOS: %d\n", ret); |
4037 | goto err_core_stop; | 4034 | goto err_core_stop; |
4038 | } | 4035 | } |
4039 | 4036 | ||
4040 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1); | 4037 | param = ar->wmi.pdev_param->dynamic_bw; |
4038 | ret = ath10k_wmi_pdev_set_param(ar, param, 1); | ||
4041 | if (ret) { | 4039 | if (ret) { |
4042 | ath10k_warn(ar, "failed to enable dynamic BW: %d\n", ret); | 4040 | ath10k_warn(ar, "failed to enable dynamic BW: %d\n", ret); |
4043 | goto err_core_stop; | 4041 | goto err_core_stop; |
@@ -4053,8 +4051,8 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
4053 | } | 4051 | } |
4054 | 4052 | ||
4055 | if (test_bit(WMI_SERVICE_BURST, ar->wmi.svc_map)) { | 4053 | if (test_bit(WMI_SERVICE_BURST, ar->wmi.svc_map)) { |
4056 | burst_enable = ar->wmi.pdev_param->burst_enable; | 4054 | param = ar->wmi.pdev_param->burst_enable; |
4057 | ret = ath10k_wmi_pdev_set_param(ar, burst_enable, 0); | 4055 | ret = ath10k_wmi_pdev_set_param(ar, param, 0); |
4058 | if (ret) { | 4056 | if (ret) { |
4059 | ath10k_warn(ar, "failed to disable burst: %d\n", ret); | 4057 | ath10k_warn(ar, "failed to disable burst: %d\n", ret); |
4060 | goto err_core_stop; | 4058 | goto err_core_stop; |
@@ -4072,8 +4070,8 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
4072 | * this problem. | 4070 | * this problem. |
4073 | */ | 4071 | */ |
4074 | 4072 | ||
4075 | ret = ath10k_wmi_pdev_set_param(ar, | 4073 | param = ar->wmi.pdev_param->arp_ac_override; |
4076 | ar->wmi.pdev_param->arp_ac_override, 0); | 4074 | ret = ath10k_wmi_pdev_set_param(ar, param, 0); |
4077 | if (ret) { | 4075 | if (ret) { |
4078 | ath10k_warn(ar, "failed to set arp ac override parameter: %d\n", | 4076 | ath10k_warn(ar, "failed to set arp ac override parameter: %d\n", |
4079 | ret); | 4077 | ret); |
@@ -4092,8 +4090,8 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
4092 | } | 4090 | } |
4093 | } | 4091 | } |
4094 | 4092 | ||
4095 | ret = ath10k_wmi_pdev_set_param(ar, | 4093 | param = ar->wmi.pdev_param->ani_enable; |
4096 | ar->wmi.pdev_param->ani_enable, 1); | 4094 | ret = ath10k_wmi_pdev_set_param(ar, param, 1); |
4097 | if (ret) { | 4095 | if (ret) { |
4098 | ath10k_warn(ar, "failed to enable ani by default: %d\n", | 4096 | ath10k_warn(ar, "failed to enable ani by default: %d\n", |
4099 | ret); | 4097 | ret); |
@@ -4102,6 +4100,18 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
4102 | 4100 | ||
4103 | ar->ani_enabled = true; | 4101 | ar->ani_enabled = true; |
4104 | 4102 | ||
4103 | if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { | ||
4104 | param = ar->wmi.pdev_param->peer_stats_update_period; | ||
4105 | ret = ath10k_wmi_pdev_set_param(ar, param, | ||
4106 | PEER_DEFAULT_STATS_UPDATE_PERIOD); | ||
4107 | if (ret) { | ||
4108 | ath10k_warn(ar, | ||
4109 | "failed to set peer stats period : %d\n", | ||
4110 | ret); | ||
4111 | goto err_core_stop; | ||
4112 | } | ||
4113 | } | ||
4114 | |||
4105 | ar->num_started_vdevs = 0; | 4115 | ar->num_started_vdevs = 0; |
4106 | ath10k_regd_update(ar); | 4116 | ath10k_regd_update(ar); |
4107 | 4117 | ||
@@ -4349,25 +4359,29 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
4349 | bit, ar->free_vdev_map); | 4359 | bit, ar->free_vdev_map); |
4350 | 4360 | ||
4351 | arvif->vdev_id = bit; | 4361 | arvif->vdev_id = bit; |
4352 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; | 4362 | arvif->vdev_subtype = |
4363 | ath10k_wmi_get_vdev_subtype(ar, WMI_VDEV_SUBTYPE_NONE); | ||
4353 | 4364 | ||
4354 | switch (vif->type) { | 4365 | switch (vif->type) { |
4355 | case NL80211_IFTYPE_P2P_DEVICE: | 4366 | case NL80211_IFTYPE_P2P_DEVICE: |
4356 | arvif->vdev_type = WMI_VDEV_TYPE_STA; | 4367 | arvif->vdev_type = WMI_VDEV_TYPE_STA; |
4357 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; | 4368 | arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype |
4369 | (ar, WMI_VDEV_SUBTYPE_P2P_DEVICE); | ||
4358 | break; | 4370 | break; |
4359 | case NL80211_IFTYPE_UNSPECIFIED: | 4371 | case NL80211_IFTYPE_UNSPECIFIED: |
4360 | case NL80211_IFTYPE_STATION: | 4372 | case NL80211_IFTYPE_STATION: |
4361 | arvif->vdev_type = WMI_VDEV_TYPE_STA; | 4373 | arvif->vdev_type = WMI_VDEV_TYPE_STA; |
4362 | if (vif->p2p) | 4374 | if (vif->p2p) |
4363 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT; | 4375 | arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype |
4376 | (ar, WMI_VDEV_SUBTYPE_P2P_CLIENT); | ||
4364 | break; | 4377 | break; |
4365 | case NL80211_IFTYPE_ADHOC: | 4378 | case NL80211_IFTYPE_ADHOC: |
4366 | arvif->vdev_type = WMI_VDEV_TYPE_IBSS; | 4379 | arvif->vdev_type = WMI_VDEV_TYPE_IBSS; |
4367 | break; | 4380 | break; |
4368 | case NL80211_IFTYPE_MESH_POINT: | 4381 | case NL80211_IFTYPE_MESH_POINT: |
4369 | if (test_bit(WMI_SERVICE_MESH, ar->wmi.svc_map)) { | 4382 | if (test_bit(WMI_SERVICE_MESH_11S, ar->wmi.svc_map)) { |
4370 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH; | 4383 | arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype |
4384 | (ar, WMI_VDEV_SUBTYPE_MESH_11S); | ||
4371 | } else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { | 4385 | } else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { |
4372 | ret = -EINVAL; | 4386 | ret = -EINVAL; |
4373 | ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); | 4387 | ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); |
@@ -4379,7 +4393,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
4379 | arvif->vdev_type = WMI_VDEV_TYPE_AP; | 4393 | arvif->vdev_type = WMI_VDEV_TYPE_AP; |
4380 | 4394 | ||
4381 | if (vif->p2p) | 4395 | if (vif->p2p) |
4382 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO; | 4396 | arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype |
4397 | (ar, WMI_VDEV_SUBTYPE_P2P_GO); | ||
4383 | break; | 4398 | break; |
4384 | case NL80211_IFTYPE_MONITOR: | 4399 | case NL80211_IFTYPE_MONITOR: |
4385 | arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; | 4400 | arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index ee925c618535..b3cff1d3364a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -94,7 +94,6 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { | |||
94 | static void ath10k_pci_buffer_cleanup(struct ath10k *ar); | 94 | static void ath10k_pci_buffer_cleanup(struct ath10k *ar); |
95 | static int ath10k_pci_cold_reset(struct ath10k *ar); | 95 | static int ath10k_pci_cold_reset(struct ath10k *ar); |
96 | static int ath10k_pci_safe_chip_reset(struct ath10k *ar); | 96 | static int ath10k_pci_safe_chip_reset(struct ath10k *ar); |
97 | static int ath10k_pci_wait_for_target_init(struct ath10k *ar); | ||
98 | static int ath10k_pci_init_irq(struct ath10k *ar); | 97 | static int ath10k_pci_init_irq(struct ath10k *ar); |
99 | static int ath10k_pci_deinit_irq(struct ath10k *ar); | 98 | static int ath10k_pci_deinit_irq(struct ath10k *ar); |
100 | static int ath10k_pci_request_irq(struct ath10k *ar); | 99 | static int ath10k_pci_request_irq(struct ath10k *ar); |
@@ -620,7 +619,7 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar) | |||
620 | spin_unlock_irqrestore(&ar_pci->ps_lock, flags); | 619 | spin_unlock_irqrestore(&ar_pci->ps_lock, flags); |
621 | } | 620 | } |
622 | 621 | ||
623 | void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) | 622 | static void ath10k_bus_pci_write32(struct ath10k *ar, u32 offset, u32 value) |
624 | { | 623 | { |
625 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 624 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
626 | int ret; | 625 | int ret; |
@@ -642,7 +641,7 @@ void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) | |||
642 | ath10k_pci_sleep(ar); | 641 | ath10k_pci_sleep(ar); |
643 | } | 642 | } |
644 | 643 | ||
645 | u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) | 644 | static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset) |
646 | { | 645 | { |
647 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 646 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
648 | u32 val; | 647 | u32 val; |
@@ -667,6 +666,20 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) | |||
667 | return val; | 666 | return val; |
668 | } | 667 | } |
669 | 668 | ||
669 | inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) | ||
670 | { | ||
671 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
672 | |||
673 | ar_pci->bus_ops->write32(ar, offset, value); | ||
674 | } | ||
675 | |||
676 | inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) | ||
677 | { | ||
678 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
679 | |||
680 | return ar_pci->bus_ops->read32(ar, offset); | ||
681 | } | ||
682 | |||
670 | u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr) | 683 | u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr) |
671 | { | 684 | { |
672 | return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr); | 685 | return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr); |
@@ -687,7 +700,7 @@ void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val) | |||
687 | ath10k_pci_write32(ar, PCIE_LOCAL_BASE_ADDRESS + addr, val); | 700 | ath10k_pci_write32(ar, PCIE_LOCAL_BASE_ADDRESS + addr, val); |
688 | } | 701 | } |
689 | 702 | ||
690 | static bool ath10k_pci_irq_pending(struct ath10k *ar) | 703 | bool ath10k_pci_irq_pending(struct ath10k *ar) |
691 | { | 704 | { |
692 | u32 cause; | 705 | u32 cause; |
693 | 706 | ||
@@ -700,7 +713,7 @@ static bool ath10k_pci_irq_pending(struct ath10k *ar) | |||
700 | return false; | 713 | return false; |
701 | } | 714 | } |
702 | 715 | ||
703 | static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) | 716 | void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) |
704 | { | 717 | { |
705 | /* IMPORTANT: INTR_CLR register has to be set after | 718 | /* IMPORTANT: INTR_CLR register has to be set after |
706 | * INTR_ENABLE is set to 0, otherwise interrupt can not be | 719 | * INTR_ENABLE is set to 0, otherwise interrupt can not be |
@@ -716,7 +729,7 @@ static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) | |||
716 | PCIE_INTR_ENABLE_ADDRESS); | 729 | PCIE_INTR_ENABLE_ADDRESS); |
717 | } | 730 | } |
718 | 731 | ||
719 | static void ath10k_pci_enable_legacy_irq(struct ath10k *ar) | 732 | void ath10k_pci_enable_legacy_irq(struct ath10k *ar) |
720 | { | 733 | { |
721 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + | 734 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + |
722 | PCIE_INTR_ENABLE_ADDRESS, | 735 | PCIE_INTR_ENABLE_ADDRESS, |
@@ -809,7 +822,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) | |||
809 | } | 822 | } |
810 | } | 823 | } |
811 | 824 | ||
812 | static void ath10k_pci_rx_post(struct ath10k *ar) | 825 | void ath10k_pci_rx_post(struct ath10k *ar) |
813 | { | 826 | { |
814 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 827 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
815 | int i; | 828 | int i; |
@@ -818,7 +831,7 @@ static void ath10k_pci_rx_post(struct ath10k *ar) | |||
818 | ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); | 831 | ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); |
819 | } | 832 | } |
820 | 833 | ||
821 | static void ath10k_pci_rx_replenish_retry(unsigned long ptr) | 834 | void ath10k_pci_rx_replenish_retry(unsigned long ptr) |
822 | { | 835 | { |
823 | struct ath10k *ar = (void *)ptr; | 836 | struct ath10k *ar = (void *)ptr; |
824 | 837 | ||
@@ -838,6 +851,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) | |||
838 | 0x7ff) << 21; | 851 | 0x7ff) << 21; |
839 | break; | 852 | break; |
840 | case ATH10K_HW_QCA99X0: | 853 | case ATH10K_HW_QCA99X0: |
854 | case ATH10K_HW_QCA4019: | ||
841 | val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); | 855 | val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); |
842 | break; | 856 | break; |
843 | } | 857 | } |
@@ -1007,8 +1021,8 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest, | |||
1007 | #define ath10k_pci_diag_read_hi(ar, dest, src, len) \ | 1021 | #define ath10k_pci_diag_read_hi(ar, dest, src, len) \ |
1008 | __ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len) | 1022 | __ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len) |
1009 | 1023 | ||
1010 | static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | 1024 | int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, |
1011 | const void *data, int nbytes) | 1025 | const void *data, int nbytes) |
1012 | { | 1026 | { |
1013 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1027 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
1014 | int ret = 0; | 1028 | int ret = 0; |
@@ -1263,8 +1277,8 @@ static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state) | |||
1263 | ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); | 1277 | ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); |
1264 | } | 1278 | } |
1265 | 1279 | ||
1266 | static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, | 1280 | int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, |
1267 | struct ath10k_hif_sg_item *items, int n_items) | 1281 | struct ath10k_hif_sg_item *items, int n_items) |
1268 | { | 1282 | { |
1269 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1283 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
1270 | struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id]; | 1284 | struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id]; |
@@ -1332,13 +1346,13 @@ err: | |||
1332 | return err; | 1346 | return err; |
1333 | } | 1347 | } |
1334 | 1348 | ||
1335 | static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, | 1349 | int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, |
1336 | size_t buf_len) | 1350 | size_t buf_len) |
1337 | { | 1351 | { |
1338 | return ath10k_pci_diag_read_mem(ar, address, buf, buf_len); | 1352 | return ath10k_pci_diag_read_mem(ar, address, buf, buf_len); |
1339 | } | 1353 | } |
1340 | 1354 | ||
1341 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) | 1355 | u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) |
1342 | { | 1356 | { |
1343 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1357 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
1344 | 1358 | ||
@@ -1406,8 +1420,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) | |||
1406 | queue_work(ar->workqueue, &ar->restart_work); | 1420 | queue_work(ar->workqueue, &ar->restart_work); |
1407 | } | 1421 | } |
1408 | 1422 | ||
1409 | static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, | 1423 | void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, |
1410 | int force) | 1424 | int force) |
1411 | { | 1425 | { |
1412 | ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif send complete check\n"); | 1426 | ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif send complete check\n"); |
1413 | 1427 | ||
@@ -1432,7 +1446,7 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, | |||
1432 | ath10k_ce_per_engine_service(ar, pipe); | 1446 | ath10k_ce_per_engine_service(ar, pipe); |
1433 | } | 1447 | } |
1434 | 1448 | ||
1435 | static void ath10k_pci_kill_tasklet(struct ath10k *ar) | 1449 | void ath10k_pci_kill_tasklet(struct ath10k *ar) |
1436 | { | 1450 | { |
1437 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1451 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
1438 | int i; | 1452 | int i; |
@@ -1446,8 +1460,8 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) | |||
1446 | del_timer_sync(&ar_pci->rx_post_retry); | 1460 | del_timer_sync(&ar_pci->rx_post_retry); |
1447 | } | 1461 | } |
1448 | 1462 | ||
1449 | static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, | 1463 | int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, |
1450 | u8 *ul_pipe, u8 *dl_pipe) | 1464 | u8 *ul_pipe, u8 *dl_pipe) |
1451 | { | 1465 | { |
1452 | const struct service_to_pipe *entry; | 1466 | const struct service_to_pipe *entry; |
1453 | bool ul_set = false, dl_set = false; | 1467 | bool ul_set = false, dl_set = false; |
@@ -1491,8 +1505,8 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, | |||
1491 | return 0; | 1505 | return 0; |
1492 | } | 1506 | } |
1493 | 1507 | ||
1494 | static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, | 1508 | void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, |
1495 | u8 *ul_pipe, u8 *dl_pipe) | 1509 | u8 *ul_pipe, u8 *dl_pipe) |
1496 | { | 1510 | { |
1497 | ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n"); | 1511 | ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n"); |
1498 | 1512 | ||
@@ -1516,6 +1530,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) | |||
1516 | CORE_CTRL_ADDRESS, val); | 1530 | CORE_CTRL_ADDRESS, val); |
1517 | break; | 1531 | break; |
1518 | case ATH10K_HW_QCA99X0: | 1532 | case ATH10K_HW_QCA99X0: |
1533 | case ATH10K_HW_QCA4019: | ||
1519 | /* TODO: Find appropriate register configuration for QCA99X0 | 1534 | /* TODO: Find appropriate register configuration for QCA99X0 |
1520 | * to mask irq/MSI. | 1535 | * to mask irq/MSI. |
1521 | */ | 1536 | */ |
@@ -1538,6 +1553,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) | |||
1538 | CORE_CTRL_ADDRESS, val); | 1553 | CORE_CTRL_ADDRESS, val); |
1539 | break; | 1554 | break; |
1540 | case ATH10K_HW_QCA99X0: | 1555 | case ATH10K_HW_QCA99X0: |
1556 | case ATH10K_HW_QCA4019: | ||
1541 | /* TODO: Find appropriate register configuration for QCA99X0 | 1557 | /* TODO: Find appropriate register configuration for QCA99X0 |
1542 | * to unmask irq/MSI. | 1558 | * to unmask irq/MSI. |
1543 | */ | 1559 | */ |
@@ -1668,7 +1684,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar) | |||
1668 | } | 1684 | } |
1669 | } | 1685 | } |
1670 | 1686 | ||
1671 | static void ath10k_pci_ce_deinit(struct ath10k *ar) | 1687 | void ath10k_pci_ce_deinit(struct ath10k *ar) |
1672 | { | 1688 | { |
1673 | int i; | 1689 | int i; |
1674 | 1690 | ||
@@ -1676,7 +1692,7 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar) | |||
1676 | ath10k_ce_deinit_pipe(ar, i); | 1692 | ath10k_ce_deinit_pipe(ar, i); |
1677 | } | 1693 | } |
1678 | 1694 | ||
1679 | static void ath10k_pci_flush(struct ath10k *ar) | 1695 | void ath10k_pci_flush(struct ath10k *ar) |
1680 | { | 1696 | { |
1681 | ath10k_pci_kill_tasklet(ar); | 1697 | ath10k_pci_kill_tasklet(ar); |
1682 | ath10k_pci_buffer_cleanup(ar); | 1698 | ath10k_pci_buffer_cleanup(ar); |
@@ -1711,9 +1727,9 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) | |||
1711 | spin_unlock_irqrestore(&ar_pci->ps_lock, flags); | 1727 | spin_unlock_irqrestore(&ar_pci->ps_lock, flags); |
1712 | } | 1728 | } |
1713 | 1729 | ||
1714 | static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, | 1730 | int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, |
1715 | void *req, u32 req_len, | 1731 | void *req, u32 req_len, |
1716 | void *resp, u32 *resp_len) | 1732 | void *resp, u32 *resp_len) |
1717 | { | 1733 | { |
1718 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1734 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
1719 | struct ath10k_pci_pipe *pci_tx = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; | 1735 | struct ath10k_pci_pipe *pci_tx = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; |
@@ -1756,7 +1772,7 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, | |||
1756 | DMA_FROM_DEVICE); | 1772 | DMA_FROM_DEVICE); |
1757 | ret = dma_mapping_error(ar->dev, resp_paddr); | 1773 | ret = dma_mapping_error(ar->dev, resp_paddr); |
1758 | if (ret) { | 1774 | if (ret) { |
1759 | ret = EIO; | 1775 | ret = -EIO; |
1760 | goto err_req; | 1776 | goto err_req; |
1761 | } | 1777 | } |
1762 | 1778 | ||
@@ -1907,7 +1923,14 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) | |||
1907 | return 1; | 1923 | return 1; |
1908 | } | 1924 | } |
1909 | 1925 | ||
1910 | static int ath10k_pci_init_config(struct ath10k *ar) | 1926 | static int ath10k_bus_get_num_banks(struct ath10k *ar) |
1927 | { | ||
1928 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
1929 | |||
1930 | return ar_pci->bus_ops->get_num_banks(ar); | ||
1931 | } | ||
1932 | |||
1933 | int ath10k_pci_init_config(struct ath10k *ar) | ||
1911 | { | 1934 | { |
1912 | u32 interconnect_targ_addr; | 1935 | u32 interconnect_targ_addr; |
1913 | u32 pcie_state_targ_addr = 0; | 1936 | u32 pcie_state_targ_addr = 0; |
@@ -2018,7 +2041,7 @@ static int ath10k_pci_init_config(struct ath10k *ar) | |||
2018 | /* first bank is switched to IRAM */ | 2041 | /* first bank is switched to IRAM */ |
2019 | ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & | 2042 | ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & |
2020 | HI_EARLY_ALLOC_MAGIC_MASK); | 2043 | HI_EARLY_ALLOC_MAGIC_MASK); |
2021 | ealloc_value |= ((ath10k_pci_get_num_banks(ar) << | 2044 | ealloc_value |= ((ath10k_bus_get_num_banks(ar) << |
2022 | HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & | 2045 | HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & |
2023 | HI_EARLY_ALLOC_IRAM_BANKS_MASK); | 2046 | HI_EARLY_ALLOC_IRAM_BANKS_MASK); |
2024 | 2047 | ||
@@ -2071,7 +2094,7 @@ static void ath10k_pci_override_ce_config(struct ath10k *ar) | |||
2071 | target_service_to_ce_map_wlan[15].pipenum = __cpu_to_le32(1); | 2094 | target_service_to_ce_map_wlan[15].pipenum = __cpu_to_le32(1); |
2072 | } | 2095 | } |
2073 | 2096 | ||
2074 | static int ath10k_pci_alloc_pipes(struct ath10k *ar) | 2097 | int ath10k_pci_alloc_pipes(struct ath10k *ar) |
2075 | { | 2098 | { |
2076 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 2099 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
2077 | struct ath10k_pci_pipe *pipe; | 2100 | struct ath10k_pci_pipe *pipe; |
@@ -2102,7 +2125,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) | |||
2102 | return 0; | 2125 | return 0; |
2103 | } | 2126 | } |
2104 | 2127 | ||
2105 | static void ath10k_pci_free_pipes(struct ath10k *ar) | 2128 | void ath10k_pci_free_pipes(struct ath10k *ar) |
2106 | { | 2129 | { |
2107 | int i; | 2130 | int i; |
2108 | 2131 | ||
@@ -2110,7 +2133,7 @@ static void ath10k_pci_free_pipes(struct ath10k *ar) | |||
2110 | ath10k_ce_free_pipe(ar, i); | 2133 | ath10k_ce_free_pipe(ar, i); |
2111 | } | 2134 | } |
2112 | 2135 | ||
2113 | static int ath10k_pci_init_pipes(struct ath10k *ar) | 2136 | int ath10k_pci_init_pipes(struct ath10k *ar) |
2114 | { | 2137 | { |
2115 | int i, ret; | 2138 | int i, ret; |
2116 | 2139 | ||
@@ -2453,7 +2476,7 @@ err_sleep: | |||
2453 | return ret; | 2476 | return ret; |
2454 | } | 2477 | } |
2455 | 2478 | ||
2456 | static void ath10k_pci_hif_power_down(struct ath10k *ar) | 2479 | void ath10k_pci_hif_power_down(struct ath10k *ar) |
2457 | { | 2480 | { |
2458 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); | 2481 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); |
2459 | 2482 | ||
@@ -2722,7 +2745,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar) | |||
2722 | free_irq(ar_pci->pdev->irq + i, ar); | 2745 | free_irq(ar_pci->pdev->irq + i, ar); |
2723 | } | 2746 | } |
2724 | 2747 | ||
2725 | static void ath10k_pci_init_irq_tasklets(struct ath10k *ar) | 2748 | void ath10k_pci_init_irq_tasklets(struct ath10k *ar) |
2726 | { | 2749 | { |
2727 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 2750 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
2728 | int i; | 2751 | int i; |
@@ -2808,7 +2831,7 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) | |||
2808 | return 0; | 2831 | return 0; |
2809 | } | 2832 | } |
2810 | 2833 | ||
2811 | static int ath10k_pci_wait_for_target_init(struct ath10k *ar) | 2834 | int ath10k_pci_wait_for_target_init(struct ath10k *ar) |
2812 | { | 2835 | { |
2813 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 2836 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
2814 | unsigned long timeout; | 2837 | unsigned long timeout; |
@@ -2989,6 +3012,43 @@ static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id) | |||
2989 | return false; | 3012 | return false; |
2990 | } | 3013 | } |
2991 | 3014 | ||
3015 | int ath10k_pci_setup_resource(struct ath10k *ar) | ||
3016 | { | ||
3017 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
3018 | int ret; | ||
3019 | |||
3020 | spin_lock_init(&ar_pci->ce_lock); | ||
3021 | spin_lock_init(&ar_pci->ps_lock); | ||
3022 | |||
3023 | setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, | ||
3024 | (unsigned long)ar); | ||
3025 | |||
3026 | if (QCA_REV_6174(ar)) | ||
3027 | ath10k_pci_override_ce_config(ar); | ||
3028 | |||
3029 | ret = ath10k_pci_alloc_pipes(ar); | ||
3030 | if (ret) { | ||
3031 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", | ||
3032 | ret); | ||
3033 | return ret; | ||
3034 | } | ||
3035 | |||
3036 | return 0; | ||
3037 | } | ||
3038 | |||
3039 | void ath10k_pci_release_resource(struct ath10k *ar) | ||
3040 | { | ||
3041 | ath10k_pci_kill_tasklet(ar); | ||
3042 | ath10k_pci_ce_deinit(ar); | ||
3043 | ath10k_pci_free_pipes(ar); | ||
3044 | } | ||
3045 | |||
3046 | static const struct ath10k_bus_ops ath10k_pci_bus_ops = { | ||
3047 | .read32 = ath10k_bus_pci_read32, | ||
3048 | .write32 = ath10k_bus_pci_write32, | ||
3049 | .get_num_banks = ath10k_pci_get_num_banks, | ||
3050 | }; | ||
3051 | |||
2992 | static int ath10k_pci_probe(struct pci_dev *pdev, | 3052 | static int ath10k_pci_probe(struct pci_dev *pdev, |
2993 | const struct pci_device_id *pci_dev) | 3053 | const struct pci_device_id *pci_dev) |
2994 | { | 3054 | { |
@@ -3039,40 +3099,32 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
3039 | ar_pci->ar = ar; | 3099 | ar_pci->ar = ar; |
3040 | ar->dev_id = pci_dev->device; | 3100 | ar->dev_id = pci_dev->device; |
3041 | ar_pci->pci_ps = pci_ps; | 3101 | ar_pci->pci_ps = pci_ps; |
3102 | ar_pci->bus_ops = &ath10k_pci_bus_ops; | ||
3042 | 3103 | ||
3043 | ar->id.vendor = pdev->vendor; | 3104 | ar->id.vendor = pdev->vendor; |
3044 | ar->id.device = pdev->device; | 3105 | ar->id.device = pdev->device; |
3045 | ar->id.subsystem_vendor = pdev->subsystem_vendor; | 3106 | ar->id.subsystem_vendor = pdev->subsystem_vendor; |
3046 | ar->id.subsystem_device = pdev->subsystem_device; | 3107 | ar->id.subsystem_device = pdev->subsystem_device; |
3047 | 3108 | ||
3048 | spin_lock_init(&ar_pci->ce_lock); | ||
3049 | spin_lock_init(&ar_pci->ps_lock); | ||
3050 | |||
3051 | setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, | ||
3052 | (unsigned long)ar); | ||
3053 | setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer, | 3109 | setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer, |
3054 | (unsigned long)ar); | 3110 | (unsigned long)ar); |
3055 | 3111 | ||
3056 | ret = ath10k_pci_claim(ar); | 3112 | ret = ath10k_pci_setup_resource(ar); |
3057 | if (ret) { | 3113 | if (ret) { |
3058 | ath10k_err(ar, "failed to claim device: %d\n", ret); | 3114 | ath10k_err(ar, "failed to setup resource: %d\n", ret); |
3059 | goto err_core_destroy; | 3115 | goto err_core_destroy; |
3060 | } | 3116 | } |
3061 | 3117 | ||
3062 | if (QCA_REV_6174(ar)) | 3118 | ret = ath10k_pci_claim(ar); |
3063 | ath10k_pci_override_ce_config(ar); | ||
3064 | |||
3065 | ret = ath10k_pci_alloc_pipes(ar); | ||
3066 | if (ret) { | 3119 | if (ret) { |
3067 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", | 3120 | ath10k_err(ar, "failed to claim device: %d\n", ret); |
3068 | ret); | 3121 | goto err_free_pipes; |
3069 | goto err_sleep; | ||
3070 | } | 3122 | } |
3071 | 3123 | ||
3072 | ret = ath10k_pci_force_wake(ar); | 3124 | ret = ath10k_pci_force_wake(ar); |
3073 | if (ret) { | 3125 | if (ret) { |
3074 | ath10k_warn(ar, "failed to wake up device : %d\n", ret); | 3126 | ath10k_warn(ar, "failed to wake up device : %d\n", ret); |
3075 | goto err_free_pipes; | 3127 | goto err_sleep; |
3076 | } | 3128 | } |
3077 | 3129 | ||
3078 | ath10k_pci_ce_deinit(ar); | 3130 | ath10k_pci_ce_deinit(ar); |
@@ -3081,7 +3133,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
3081 | ret = ath10k_pci_init_irq(ar); | 3133 | ret = ath10k_pci_init_irq(ar); |
3082 | if (ret) { | 3134 | if (ret) { |
3083 | ath10k_err(ar, "failed to init irqs: %d\n", ret); | 3135 | ath10k_err(ar, "failed to init irqs: %d\n", ret); |
3084 | goto err_free_pipes; | 3136 | goto err_sleep; |
3085 | } | 3137 | } |
3086 | 3138 | ||
3087 | ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", | 3139 | ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", |
@@ -3127,13 +3179,13 @@ err_free_irq: | |||
3127 | err_deinit_irq: | 3179 | err_deinit_irq: |
3128 | ath10k_pci_deinit_irq(ar); | 3180 | ath10k_pci_deinit_irq(ar); |
3129 | 3181 | ||
3130 | err_free_pipes: | ||
3131 | ath10k_pci_free_pipes(ar); | ||
3132 | |||
3133 | err_sleep: | 3182 | err_sleep: |
3134 | ath10k_pci_sleep_sync(ar); | 3183 | ath10k_pci_sleep_sync(ar); |
3135 | ath10k_pci_release(ar); | 3184 | ath10k_pci_release(ar); |
3136 | 3185 | ||
3186 | err_free_pipes: | ||
3187 | ath10k_pci_free_pipes(ar); | ||
3188 | |||
3137 | err_core_destroy: | 3189 | err_core_destroy: |
3138 | ath10k_core_destroy(ar); | 3190 | ath10k_core_destroy(ar); |
3139 | 3191 | ||
@@ -3157,10 +3209,8 @@ static void ath10k_pci_remove(struct pci_dev *pdev) | |||
3157 | 3209 | ||
3158 | ath10k_core_unregister(ar); | 3210 | ath10k_core_unregister(ar); |
3159 | ath10k_pci_free_irq(ar); | 3211 | ath10k_pci_free_irq(ar); |
3160 | ath10k_pci_kill_tasklet(ar); | ||
3161 | ath10k_pci_deinit_irq(ar); | 3212 | ath10k_pci_deinit_irq(ar); |
3162 | ath10k_pci_ce_deinit(ar); | 3213 | ath10k_pci_release_resource(ar); |
3163 | ath10k_pci_free_pipes(ar); | ||
3164 | ath10k_pci_sleep_sync(ar); | 3214 | ath10k_pci_sleep_sync(ar); |
3165 | ath10k_pci_release(ar); | 3215 | ath10k_pci_release(ar); |
3166 | ath10k_core_destroy(ar); | 3216 | ath10k_core_destroy(ar); |
@@ -3184,6 +3234,10 @@ static int __init ath10k_pci_init(void) | |||
3184 | printk(KERN_ERR "failed to register ath10k pci driver: %d\n", | 3234 | printk(KERN_ERR "failed to register ath10k pci driver: %d\n", |
3185 | ret); | 3235 | ret); |
3186 | 3236 | ||
3237 | ret = ath10k_ahb_init(); | ||
3238 | if (ret) | ||
3239 | printk(KERN_ERR "ahb init failed: %d\n", ret); | ||
3240 | |||
3187 | return ret; | 3241 | return ret; |
3188 | } | 3242 | } |
3189 | module_init(ath10k_pci_init); | 3243 | module_init(ath10k_pci_init); |
@@ -3191,6 +3245,7 @@ module_init(ath10k_pci_init); | |||
3191 | static void __exit ath10k_pci_exit(void) | 3245 | static void __exit ath10k_pci_exit(void) |
3192 | { | 3246 | { |
3193 | pci_unregister_driver(&ath10k_pci_driver); | 3247 | pci_unregister_driver(&ath10k_pci_driver); |
3248 | ath10k_ahb_exit(); | ||
3194 | } | 3249 | } |
3195 | 3250 | ||
3196 | module_exit(ath10k_pci_exit); | 3251 | module_exit(ath10k_pci_exit); |
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index f91bf333cb75..249c73a69800 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include "hw.h" | 23 | #include "hw.h" |
24 | #include "ce.h" | 24 | #include "ce.h" |
25 | #include "ahb.h" | ||
25 | 26 | ||
26 | /* | 27 | /* |
27 | * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite | 28 | * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite |
@@ -157,6 +158,12 @@ struct ath10k_pci_supp_chip { | |||
157 | u32 rev_id; | 158 | u32 rev_id; |
158 | }; | 159 | }; |
159 | 160 | ||
161 | struct ath10k_bus_ops { | ||
162 | u32 (*read32)(struct ath10k *ar, u32 offset); | ||
163 | void (*write32)(struct ath10k *ar, u32 offset, u32 value); | ||
164 | int (*get_num_banks)(struct ath10k *ar); | ||
165 | }; | ||
166 | |||
160 | struct ath10k_pci { | 167 | struct ath10k_pci { |
161 | struct pci_dev *pdev; | 168 | struct pci_dev *pdev; |
162 | struct device *dev; | 169 | struct device *dev; |
@@ -225,6 +232,14 @@ struct ath10k_pci { | |||
225 | * on MMIO read/write. | 232 | * on MMIO read/write. |
226 | */ | 233 | */ |
227 | bool pci_ps; | 234 | bool pci_ps; |
235 | |||
236 | const struct ath10k_bus_ops *bus_ops; | ||
237 | |||
238 | /* Keep this entry in the last, memory for struct ath10k_ahb is | ||
239 | * allocated (ahb support enabled case) in the continuation of | ||
240 | * this struct. | ||
241 | */ | ||
242 | struct ath10k_ahb ahb[0]; | ||
228 | }; | 243 | }; |
229 | 244 | ||
230 | static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) | 245 | static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) |
@@ -253,6 +268,40 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset); | |||
253 | u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr); | 268 | u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr); |
254 | u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr); | 269 | u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr); |
255 | 270 | ||
271 | int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, | ||
272 | struct ath10k_hif_sg_item *items, int n_items); | ||
273 | int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, | ||
274 | size_t buf_len); | ||
275 | int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | ||
276 | const void *data, int nbytes); | ||
277 | int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, void *req, u32 req_len, | ||
278 | void *resp, u32 *resp_len); | ||
279 | int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, | ||
280 | u8 *ul_pipe, u8 *dl_pipe); | ||
281 | void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, u8 *ul_pipe, | ||
282 | u8 *dl_pipe); | ||
283 | void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, | ||
284 | int force); | ||
285 | u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe); | ||
286 | void ath10k_pci_hif_power_down(struct ath10k *ar); | ||
287 | int ath10k_pci_alloc_pipes(struct ath10k *ar); | ||
288 | void ath10k_pci_free_pipes(struct ath10k *ar); | ||
289 | void ath10k_pci_free_pipes(struct ath10k *ar); | ||
290 | void ath10k_pci_rx_replenish_retry(unsigned long ptr); | ||
291 | void ath10k_pci_ce_deinit(struct ath10k *ar); | ||
292 | void ath10k_pci_init_irq_tasklets(struct ath10k *ar); | ||
293 | void ath10k_pci_kill_tasklet(struct ath10k *ar); | ||
294 | int ath10k_pci_init_pipes(struct ath10k *ar); | ||
295 | int ath10k_pci_init_config(struct ath10k *ar); | ||
296 | void ath10k_pci_rx_post(struct ath10k *ar); | ||
297 | void ath10k_pci_flush(struct ath10k *ar); | ||
298 | void ath10k_pci_enable_legacy_irq(struct ath10k *ar); | ||
299 | bool ath10k_pci_irq_pending(struct ath10k *ar); | ||
300 | void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar); | ||
301 | int ath10k_pci_wait_for_target_init(struct ath10k *ar); | ||
302 | int ath10k_pci_setup_resource(struct ath10k *ar); | ||
303 | void ath10k_pci_release_resource(struct ath10k *ar); | ||
304 | |||
256 | /* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too | 305 | /* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too |
257 | * frequently. To avoid this put SoC to sleep after a very conservative grace | 306 | * frequently. To avoid this put SoC to sleep after a very conservative grace |
258 | * period. Adjust with great care. | 307 | * period. Adjust with great care. |
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 05a421bc322a..361f143b019c 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h | |||
@@ -456,4 +456,7 @@ Fw Mode/SubMode Mask | |||
456 | #define QCA99X0_BOARD_DATA_SZ 12288 | 456 | #define QCA99X0_BOARD_DATA_SZ 12288 |
457 | #define QCA99X0_BOARD_EXT_DATA_SZ 0 | 457 | #define QCA99X0_BOARD_EXT_DATA_SZ 0 |
458 | 458 | ||
459 | #define QCA4019_BOARD_DATA_SZ 12064 | ||
460 | #define QCA4019_BOARD_EXT_DATA_SZ 0 | ||
461 | |||
459 | #endif /* __TARGADDRS_H__ */ | 462 | #endif /* __TARGADDRS_H__ */ |
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 71bdb368813d..e0d00cef0bd8 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
@@ -250,6 +250,7 @@ TRACE_EVENT(ath10k_wmi_dbglog, | |||
250 | TP_STRUCT__entry( | 250 | TP_STRUCT__entry( |
251 | __string(device, dev_name(ar->dev)) | 251 | __string(device, dev_name(ar->dev)) |
252 | __string(driver, dev_driver_string(ar->dev)) | 252 | __string(driver, dev_driver_string(ar->dev)) |
253 | __field(u8, hw_type); | ||
253 | __field(size_t, buf_len) | 254 | __field(size_t, buf_len) |
254 | __dynamic_array(u8, buf, buf_len) | 255 | __dynamic_array(u8, buf, buf_len) |
255 | ), | 256 | ), |
@@ -257,14 +258,16 @@ TRACE_EVENT(ath10k_wmi_dbglog, | |||
257 | TP_fast_assign( | 258 | TP_fast_assign( |
258 | __assign_str(device, dev_name(ar->dev)); | 259 | __assign_str(device, dev_name(ar->dev)); |
259 | __assign_str(driver, dev_driver_string(ar->dev)); | 260 | __assign_str(driver, dev_driver_string(ar->dev)); |
261 | __entry->hw_type = ar->hw_rev; | ||
260 | __entry->buf_len = buf_len; | 262 | __entry->buf_len = buf_len; |
261 | memcpy(__get_dynamic_array(buf), buf, buf_len); | 263 | memcpy(__get_dynamic_array(buf), buf, buf_len); |
262 | ), | 264 | ), |
263 | 265 | ||
264 | TP_printk( | 266 | TP_printk( |
265 | "%s %s len %zu", | 267 | "%s %s %d len %zu", |
266 | __get_str(driver), | 268 | __get_str(driver), |
267 | __get_str(device), | 269 | __get_str(device), |
270 | __entry->hw_type, | ||
268 | __entry->buf_len | 271 | __entry->buf_len |
269 | ) | 272 | ) |
270 | ); | 273 | ); |
@@ -277,6 +280,7 @@ TRACE_EVENT(ath10k_htt_pktlog, | |||
277 | TP_STRUCT__entry( | 280 | TP_STRUCT__entry( |
278 | __string(device, dev_name(ar->dev)) | 281 | __string(device, dev_name(ar->dev)) |
279 | __string(driver, dev_driver_string(ar->dev)) | 282 | __string(driver, dev_driver_string(ar->dev)) |
283 | __field(u8, hw_type); | ||
280 | __field(u16, buf_len) | 284 | __field(u16, buf_len) |
281 | __dynamic_array(u8, pktlog, buf_len) | 285 | __dynamic_array(u8, pktlog, buf_len) |
282 | ), | 286 | ), |
@@ -284,14 +288,16 @@ TRACE_EVENT(ath10k_htt_pktlog, | |||
284 | TP_fast_assign( | 288 | TP_fast_assign( |
285 | __assign_str(device, dev_name(ar->dev)); | 289 | __assign_str(device, dev_name(ar->dev)); |
286 | __assign_str(driver, dev_driver_string(ar->dev)); | 290 | __assign_str(driver, dev_driver_string(ar->dev)); |
291 | __entry->hw_type = ar->hw_rev; | ||
287 | __entry->buf_len = buf_len; | 292 | __entry->buf_len = buf_len; |
288 | memcpy(__get_dynamic_array(pktlog), buf, buf_len); | 293 | memcpy(__get_dynamic_array(pktlog), buf, buf_len); |
289 | ), | 294 | ), |
290 | 295 | ||
291 | TP_printk( | 296 | TP_printk( |
292 | "%s %s size %hu", | 297 | "%s %s %d size %hu", |
293 | __get_str(driver), | 298 | __get_str(driver), |
294 | __get_str(device), | 299 | __get_str(device), |
300 | __entry->hw_type, | ||
295 | __entry->buf_len | 301 | __entry->buf_len |
296 | ) | 302 | ) |
297 | ); | 303 | ); |
@@ -440,6 +446,7 @@ TRACE_EVENT(ath10k_htt_rx_desc, | |||
440 | TP_STRUCT__entry( | 446 | TP_STRUCT__entry( |
441 | __string(device, dev_name(ar->dev)) | 447 | __string(device, dev_name(ar->dev)) |
442 | __string(driver, dev_driver_string(ar->dev)) | 448 | __string(driver, dev_driver_string(ar->dev)) |
449 | __field(u8, hw_type); | ||
443 | __field(u16, len) | 450 | __field(u16, len) |
444 | __dynamic_array(u8, rxdesc, len) | 451 | __dynamic_array(u8, rxdesc, len) |
445 | ), | 452 | ), |
@@ -447,14 +454,16 @@ TRACE_EVENT(ath10k_htt_rx_desc, | |||
447 | TP_fast_assign( | 454 | TP_fast_assign( |
448 | __assign_str(device, dev_name(ar->dev)); | 455 | __assign_str(device, dev_name(ar->dev)); |
449 | __assign_str(driver, dev_driver_string(ar->dev)); | 456 | __assign_str(driver, dev_driver_string(ar->dev)); |
457 | __entry->hw_type = ar->hw_rev; | ||
450 | __entry->len = len; | 458 | __entry->len = len; |
451 | memcpy(__get_dynamic_array(rxdesc), data, len); | 459 | memcpy(__get_dynamic_array(rxdesc), data, len); |
452 | ), | 460 | ), |
453 | 461 | ||
454 | TP_printk( | 462 | TP_printk( |
455 | "%s %s rxdesc len %d", | 463 | "%s %s %d rxdesc len %d", |
456 | __get_str(driver), | 464 | __get_str(driver), |
457 | __get_str(device), | 465 | __get_str(device), |
466 | __entry->hw_type, | ||
458 | __entry->len | 467 | __entry->len |
459 | ) | 468 | ) |
460 | ); | 469 | ); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 8f4f6a892581..32ab34edceb5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h | |||
@@ -186,6 +186,8 @@ struct wmi_ops { | |||
186 | u8 enable, | 186 | u8 enable, |
187 | u32 detect_level, | 187 | u32 detect_level, |
188 | u32 detect_margin); | 188 | u32 detect_margin); |
189 | int (*get_vdev_subtype)(struct ath10k *ar, | ||
190 | enum wmi_vdev_subtype subtype); | ||
189 | }; | 191 | }; |
190 | 192 | ||
191 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); | 193 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); |
@@ -1327,4 +1329,13 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, | |||
1327 | ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); | 1329 | ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); |
1328 | } | 1330 | } |
1329 | 1331 | ||
1332 | static inline int | ||
1333 | ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype) | ||
1334 | { | ||
1335 | if (!ar->wmi.ops->get_vdev_subtype) | ||
1336 | return -EOPNOTSUPP; | ||
1337 | |||
1338 | return ar->wmi.ops->get_vdev_subtype(ar, subtype); | ||
1339 | } | ||
1340 | |||
1330 | #endif | 1341 | #endif |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 3b3a27b859f3..108593202052 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c | |||
@@ -3483,6 +3483,7 @@ static const struct wmi_ops wmi_tlv_ops = { | |||
3483 | .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, | 3483 | .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, |
3484 | .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, | 3484 | .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, |
3485 | .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, | 3485 | .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, |
3486 | .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, | ||
3486 | }; | 3487 | }; |
3487 | 3488 | ||
3488 | static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { | 3489 | static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index a7c3d299639b..70261387d1a5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -2862,11 +2862,20 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, | |||
2862 | /* fw doesn't implement vdev stats */ | 2862 | /* fw doesn't implement vdev stats */ |
2863 | 2863 | ||
2864 | for (i = 0; i < num_peer_stats; i++) { | 2864 | for (i = 0; i < num_peer_stats; i++) { |
2865 | const struct wmi_10_2_4_peer_stats *src; | 2865 | const struct wmi_10_2_4_ext_peer_stats *src; |
2866 | struct ath10k_fw_stats_peer *dst; | 2866 | struct ath10k_fw_stats_peer *dst; |
2867 | int stats_len; | ||
2868 | bool ext_peer_stats_support; | ||
2869 | |||
2870 | ext_peer_stats_support = test_bit(WMI_SERVICE_PEER_STATS, | ||
2871 | ar->wmi.svc_map); | ||
2872 | if (ext_peer_stats_support) | ||
2873 | stats_len = sizeof(struct wmi_10_2_4_ext_peer_stats); | ||
2874 | else | ||
2875 | stats_len = sizeof(struct wmi_10_2_4_peer_stats); | ||
2867 | 2876 | ||
2868 | src = (void *)skb->data; | 2877 | src = (void *)skb->data; |
2869 | if (!skb_pull(skb, sizeof(*src))) | 2878 | if (!skb_pull(skb, stats_len)) |
2870 | return -EPROTO; | 2879 | return -EPROTO; |
2871 | 2880 | ||
2872 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | 2881 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); |
@@ -2876,6 +2885,9 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, | |||
2876 | ath10k_wmi_pull_peer_stats(&src->common.old, dst); | 2885 | ath10k_wmi_pull_peer_stats(&src->common.old, dst); |
2877 | 2886 | ||
2878 | dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate); | 2887 | dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate); |
2888 | |||
2889 | if (ext_peer_stats_support) | ||
2890 | dst->rx_duration = __le32_to_cpu(src->rx_duration); | ||
2879 | /* FIXME: expose 10.2 specific values */ | 2891 | /* FIXME: expose 10.2 specific values */ |
2880 | 2892 | ||
2881 | list_add_tail(&dst->list, &stats->peers); | 2893 | list_add_tail(&dst->list, &stats->peers); |
@@ -3184,7 +3196,7 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, | |||
3184 | struct sk_buff *bcn, | 3196 | struct sk_buff *bcn, |
3185 | const struct wmi_p2p_noa_info *noa) | 3197 | const struct wmi_p2p_noa_info *noa) |
3186 | { | 3198 | { |
3187 | if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) | 3199 | if (!arvif->vif->p2p) |
3188 | return; | 3200 | return; |
3189 | 3201 | ||
3190 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); | 3202 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); |
@@ -3244,6 +3256,50 @@ static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, | |||
3244 | return 0; | 3256 | return 0; |
3245 | } | 3257 | } |
3246 | 3258 | ||
3259 | static int ath10k_wmi_10_2_4_op_pull_swba_ev(struct ath10k *ar, | ||
3260 | struct sk_buff *skb, | ||
3261 | struct wmi_swba_ev_arg *arg) | ||
3262 | { | ||
3263 | struct wmi_10_2_4_host_swba_event *ev = (void *)skb->data; | ||
3264 | u32 map; | ||
3265 | size_t i; | ||
3266 | |||
3267 | if (skb->len < sizeof(*ev)) | ||
3268 | return -EPROTO; | ||
3269 | |||
3270 | skb_pull(skb, sizeof(*ev)); | ||
3271 | arg->vdev_map = ev->vdev_map; | ||
3272 | |||
3273 | for (i = 0, map = __le32_to_cpu(ev->vdev_map); map; map >>= 1) { | ||
3274 | if (!(map & BIT(0))) | ||
3275 | continue; | ||
3276 | |||
3277 | /* If this happens there were some changes in firmware and | ||
3278 | * ath10k should update the max size of tim_info array. | ||
3279 | */ | ||
3280 | if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info))) | ||
3281 | break; | ||
3282 | |||
3283 | if (__le32_to_cpu(ev->bcn_info[i].tim_info.tim_len) > | ||
3284 | sizeof(ev->bcn_info[i].tim_info.tim_bitmap)) { | ||
3285 | ath10k_warn(ar, "refusing to parse invalid swba structure\n"); | ||
3286 | return -EPROTO; | ||
3287 | } | ||
3288 | |||
3289 | arg->tim_info[i].tim_len = ev->bcn_info[i].tim_info.tim_len; | ||
3290 | arg->tim_info[i].tim_mcast = ev->bcn_info[i].tim_info.tim_mcast; | ||
3291 | arg->tim_info[i].tim_bitmap = | ||
3292 | ev->bcn_info[i].tim_info.tim_bitmap; | ||
3293 | arg->tim_info[i].tim_changed = | ||
3294 | ev->bcn_info[i].tim_info.tim_changed; | ||
3295 | arg->tim_info[i].tim_num_ps_pending = | ||
3296 | ev->bcn_info[i].tim_info.tim_num_ps_pending; | ||
3297 | i++; | ||
3298 | } | ||
3299 | |||
3300 | return 0; | ||
3301 | } | ||
3302 | |||
3247 | static int ath10k_wmi_10_4_op_pull_swba_ev(struct ath10k *ar, | 3303 | static int ath10k_wmi_10_4_op_pull_swba_ev(struct ath10k *ar, |
3248 | struct sk_buff *skb, | 3304 | struct sk_buff *skb, |
3249 | struct wmi_swba_ev_arg *arg) | 3305 | struct wmi_swba_ev_arg *arg) |
@@ -4562,9 +4618,9 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) | |||
4562 | 4618 | ||
4563 | if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { | 4619 | if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { |
4564 | ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX + | 4620 | ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX + |
4565 | TARGET_10_4_NUM_VDEVS; | 4621 | ar->max_num_vdevs; |
4566 | ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS + | 4622 | ar->num_active_peers = ar->hw_params.qcache_active_peers + |
4567 | TARGET_10_4_NUM_VDEVS; | 4623 | ar->max_num_vdevs; |
4568 | ar->num_tids = ar->num_active_peers * 2; | 4624 | ar->num_tids = ar->num_active_peers * 2; |
4569 | ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX; | 4625 | ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX; |
4570 | } | 4626 | } |
@@ -5460,9 +5516,15 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) | |||
5460 | u32 len, val, features; | 5516 | u32 len, val, features; |
5461 | 5517 | ||
5462 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | 5518 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); |
5463 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | ||
5464 | config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); | 5519 | config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); |
5465 | config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS); | 5520 | if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { |
5521 | config.num_peers = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_PEERS); | ||
5522 | config.num_tids = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_TIDS); | ||
5523 | } else { | ||
5524 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | ||
5525 | config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS); | ||
5526 | } | ||
5527 | |||
5466 | config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT); | 5528 | config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT); |
5467 | config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK); | 5529 | config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK); |
5468 | config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK); | 5530 | config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK); |
@@ -5517,6 +5579,9 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) | |||
5517 | test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map)) | 5579 | test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map)) |
5518 | features |= WMI_10_2_COEX_GPIO; | 5580 | features |= WMI_10_2_COEX_GPIO; |
5519 | 5581 | ||
5582 | if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) | ||
5583 | features |= WMI_10_2_PEER_STATS; | ||
5584 | |||
5520 | cmd->resource_config.feature_mask = __cpu_to_le32(features); | 5585 | cmd->resource_config.feature_mask = __cpu_to_le32(features); |
5521 | 5586 | ||
5522 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); | 5587 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); |
@@ -5543,8 +5608,8 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) | |||
5543 | __cpu_to_le32(TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS); | 5608 | __cpu_to_le32(TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS); |
5544 | config.num_peer_keys = __cpu_to_le32(TARGET_10_4_NUM_PEER_KEYS); | 5609 | config.num_peer_keys = __cpu_to_le32(TARGET_10_4_NUM_PEER_KEYS); |
5545 | config.ast_skid_limit = __cpu_to_le32(TARGET_10_4_AST_SKID_LIMIT); | 5610 | config.ast_skid_limit = __cpu_to_le32(TARGET_10_4_AST_SKID_LIMIT); |
5546 | config.tx_chain_mask = __cpu_to_le32(TARGET_10_4_TX_CHAIN_MASK); | 5611 | config.tx_chain_mask = __cpu_to_le32(ar->hw_params.tx_chain_mask); |
5547 | config.rx_chain_mask = __cpu_to_le32(TARGET_10_4_RX_CHAIN_MASK); | 5612 | config.rx_chain_mask = __cpu_to_le32(ar->hw_params.rx_chain_mask); |
5548 | 5613 | ||
5549 | config.rx_timeout_pri[0] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); | 5614 | config.rx_timeout_pri[0] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); |
5550 | config.rx_timeout_pri[1] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); | 5615 | config.rx_timeout_pri[1] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); |
@@ -5575,7 +5640,7 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) | |||
5575 | config.vow_config = __cpu_to_le32(TARGET_10_4_VOW_CONFIG); | 5640 | config.vow_config = __cpu_to_le32(TARGET_10_4_VOW_CONFIG); |
5576 | config.gtk_offload_max_vdev = | 5641 | config.gtk_offload_max_vdev = |
5577 | __cpu_to_le32(TARGET_10_4_GTK_OFFLOAD_MAX_VDEV); | 5642 | __cpu_to_le32(TARGET_10_4_GTK_OFFLOAD_MAX_VDEV); |
5578 | config.num_msdu_desc = __cpu_to_le32(TARGET_10_4_NUM_MSDU_DESC); | 5643 | config.num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx); |
5579 | config.max_frag_entries = __cpu_to_le32(TARGET_10_4_11AC_TX_MAX_FRAGS); | 5644 | config.max_frag_entries = __cpu_to_le32(TARGET_10_4_11AC_TX_MAX_FRAGS); |
5580 | config.max_peer_ext_stats = | 5645 | config.max_peer_ext_stats = |
5581 | __cpu_to_le32(TARGET_10_4_MAX_PEER_EXT_STATS); | 5646 | __cpu_to_le32(TARGET_10_4_MAX_PEER_EXT_STATS); |
@@ -7126,6 +7191,9 @@ ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer, | |||
7126 | "Peer TX rate", peer->peer_tx_rate); | 7191 | "Peer TX rate", peer->peer_tx_rate); |
7127 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | 7192 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", |
7128 | "Peer RX rate", peer->peer_rx_rate); | 7193 | "Peer RX rate", peer->peer_rx_rate); |
7194 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
7195 | "Peer RX duration", peer->rx_duration); | ||
7196 | |||
7129 | len += scnprintf(buf + len, buf_len - len, "\n"); | 7197 | len += scnprintf(buf + len, buf_len - len, "\n"); |
7130 | *length = len; | 7198 | *length = len; |
7131 | } | 7199 | } |
@@ -7351,6 +7419,71 @@ unlock: | |||
7351 | buf[len] = 0; | 7419 | buf[len] = 0; |
7352 | } | 7420 | } |
7353 | 7421 | ||
7422 | int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, | ||
7423 | enum wmi_vdev_subtype subtype) | ||
7424 | { | ||
7425 | switch (subtype) { | ||
7426 | case WMI_VDEV_SUBTYPE_NONE: | ||
7427 | return WMI_VDEV_SUBTYPE_LEGACY_NONE; | ||
7428 | case WMI_VDEV_SUBTYPE_P2P_DEVICE: | ||
7429 | return WMI_VDEV_SUBTYPE_LEGACY_P2P_DEV; | ||
7430 | case WMI_VDEV_SUBTYPE_P2P_CLIENT: | ||
7431 | return WMI_VDEV_SUBTYPE_LEGACY_P2P_CLI; | ||
7432 | case WMI_VDEV_SUBTYPE_P2P_GO: | ||
7433 | return WMI_VDEV_SUBTYPE_LEGACY_P2P_GO; | ||
7434 | case WMI_VDEV_SUBTYPE_PROXY_STA: | ||
7435 | return WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA; | ||
7436 | case WMI_VDEV_SUBTYPE_MESH_11S: | ||
7437 | case WMI_VDEV_SUBTYPE_MESH_NON_11S: | ||
7438 | return -ENOTSUPP; | ||
7439 | } | ||
7440 | return -ENOTSUPP; | ||
7441 | } | ||
7442 | |||
7443 | static int ath10k_wmi_10_2_4_op_get_vdev_subtype(struct ath10k *ar, | ||
7444 | enum wmi_vdev_subtype subtype) | ||
7445 | { | ||
7446 | switch (subtype) { | ||
7447 | case WMI_VDEV_SUBTYPE_NONE: | ||
7448 | return WMI_VDEV_SUBTYPE_10_2_4_NONE; | ||
7449 | case WMI_VDEV_SUBTYPE_P2P_DEVICE: | ||
7450 | return WMI_VDEV_SUBTYPE_10_2_4_P2P_DEV; | ||
7451 | case WMI_VDEV_SUBTYPE_P2P_CLIENT: | ||
7452 | return WMI_VDEV_SUBTYPE_10_2_4_P2P_CLI; | ||
7453 | case WMI_VDEV_SUBTYPE_P2P_GO: | ||
7454 | return WMI_VDEV_SUBTYPE_10_2_4_P2P_GO; | ||
7455 | case WMI_VDEV_SUBTYPE_PROXY_STA: | ||
7456 | return WMI_VDEV_SUBTYPE_10_2_4_PROXY_STA; | ||
7457 | case WMI_VDEV_SUBTYPE_MESH_11S: | ||
7458 | return WMI_VDEV_SUBTYPE_10_2_4_MESH_11S; | ||
7459 | case WMI_VDEV_SUBTYPE_MESH_NON_11S: | ||
7460 | return -ENOTSUPP; | ||
7461 | } | ||
7462 | return -ENOTSUPP; | ||
7463 | } | ||
7464 | |||
7465 | static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar, | ||
7466 | enum wmi_vdev_subtype subtype) | ||
7467 | { | ||
7468 | switch (subtype) { | ||
7469 | case WMI_VDEV_SUBTYPE_NONE: | ||
7470 | return WMI_VDEV_SUBTYPE_10_4_NONE; | ||
7471 | case WMI_VDEV_SUBTYPE_P2P_DEVICE: | ||
7472 | return WMI_VDEV_SUBTYPE_10_4_P2P_DEV; | ||
7473 | case WMI_VDEV_SUBTYPE_P2P_CLIENT: | ||
7474 | return WMI_VDEV_SUBTYPE_10_4_P2P_CLI; | ||
7475 | case WMI_VDEV_SUBTYPE_P2P_GO: | ||
7476 | return WMI_VDEV_SUBTYPE_10_4_P2P_GO; | ||
7477 | case WMI_VDEV_SUBTYPE_PROXY_STA: | ||
7478 | return WMI_VDEV_SUBTYPE_10_4_PROXY_STA; | ||
7479 | case WMI_VDEV_SUBTYPE_MESH_11S: | ||
7480 | return WMI_VDEV_SUBTYPE_10_4_MESH_11S; | ||
7481 | case WMI_VDEV_SUBTYPE_MESH_NON_11S: | ||
7482 | return WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S; | ||
7483 | } | ||
7484 | return -ENOTSUPP; | ||
7485 | } | ||
7486 | |||
7354 | static const struct wmi_ops wmi_ops = { | 7487 | static const struct wmi_ops wmi_ops = { |
7355 | .rx = ath10k_wmi_op_rx, | 7488 | .rx = ath10k_wmi_op_rx, |
7356 | .map_svc = wmi_main_svc_map, | 7489 | .map_svc = wmi_main_svc_map, |
@@ -7410,6 +7543,7 @@ static const struct wmi_ops wmi_ops = { | |||
7410 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | 7543 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, |
7411 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | 7544 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, |
7412 | .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, | 7545 | .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, |
7546 | .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, | ||
7413 | /* .gen_bcn_tmpl not implemented */ | 7547 | /* .gen_bcn_tmpl not implemented */ |
7414 | /* .gen_prb_tmpl not implemented */ | 7548 | /* .gen_prb_tmpl not implemented */ |
7415 | /* .gen_p2p_go_bcn_ie not implemented */ | 7549 | /* .gen_p2p_go_bcn_ie not implemented */ |
@@ -7477,6 +7611,7 @@ static const struct wmi_ops wmi_10_1_ops = { | |||
7477 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | 7611 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, |
7478 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | 7612 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, |
7479 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, | 7613 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, |
7614 | .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, | ||
7480 | /* .gen_bcn_tmpl not implemented */ | 7615 | /* .gen_bcn_tmpl not implemented */ |
7481 | /* .gen_prb_tmpl not implemented */ | 7616 | /* .gen_prb_tmpl not implemented */ |
7482 | /* .gen_p2p_go_bcn_ie not implemented */ | 7617 | /* .gen_p2p_go_bcn_ie not implemented */ |
@@ -7545,6 +7680,7 @@ static const struct wmi_ops wmi_10_2_ops = { | |||
7545 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | 7680 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, |
7546 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | 7681 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, |
7547 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, | 7682 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, |
7683 | .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, | ||
7548 | /* .gen_pdev_enable_adaptive_cca not implemented */ | 7684 | /* .gen_pdev_enable_adaptive_cca not implemented */ |
7549 | }; | 7685 | }; |
7550 | 7686 | ||
@@ -7566,7 +7702,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { | |||
7566 | .pull_ch_info = ath10k_wmi_op_pull_ch_info_ev, | 7702 | .pull_ch_info = ath10k_wmi_op_pull_ch_info_ev, |
7567 | .pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev, | 7703 | .pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev, |
7568 | .pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev, | 7704 | .pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev, |
7569 | .pull_swba = ath10k_wmi_op_pull_swba_ev, | 7705 | .pull_swba = ath10k_wmi_10_2_4_op_pull_swba_ev, |
7570 | .pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr, | 7706 | .pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr, |
7571 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, | 7707 | .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, |
7572 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, | 7708 | .pull_rdy = ath10k_wmi_op_pull_rdy_ev, |
@@ -7611,6 +7747,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { | |||
7611 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, | 7747 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, |
7612 | .gen_pdev_enable_adaptive_cca = | 7748 | .gen_pdev_enable_adaptive_cca = |
7613 | ath10k_wmi_op_gen_pdev_enable_adaptive_cca, | 7749 | ath10k_wmi_op_gen_pdev_enable_adaptive_cca, |
7750 | .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype, | ||
7614 | /* .gen_bcn_tmpl not implemented */ | 7751 | /* .gen_bcn_tmpl not implemented */ |
7615 | /* .gen_prb_tmpl not implemented */ | 7752 | /* .gen_prb_tmpl not implemented */ |
7616 | /* .gen_p2p_go_bcn_ie not implemented */ | 7753 | /* .gen_p2p_go_bcn_ie not implemented */ |
@@ -7677,6 +7814,7 @@ static const struct wmi_ops wmi_10_4_ops = { | |||
7677 | /* shared with 10.2 */ | 7814 | /* shared with 10.2 */ |
7678 | .gen_request_stats = ath10k_wmi_op_gen_request_stats, | 7815 | .gen_request_stats = ath10k_wmi_op_gen_request_stats, |
7679 | .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, | 7816 | .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, |
7817 | .get_vdev_subtype = ath10k_wmi_10_4_op_get_vdev_subtype, | ||
7680 | }; | 7818 | }; |
7681 | 7819 | ||
7682 | int ath10k_wmi_attach(struct ath10k *ar) | 7820 | 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 d85ad7855d20..4d3cbc44fcd2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -176,7 +176,10 @@ enum wmi_service { | |||
176 | WMI_SERVICE_AUX_CHAN_LOAD_INTF, | 176 | WMI_SERVICE_AUX_CHAN_LOAD_INTF, |
177 | WMI_SERVICE_BSS_CHANNEL_INFO_64, | 177 | WMI_SERVICE_BSS_CHANNEL_INFO_64, |
178 | WMI_SERVICE_EXT_RES_CFG_SUPPORT, | 178 | WMI_SERVICE_EXT_RES_CFG_SUPPORT, |
179 | WMI_SERVICE_MESH, | 179 | WMI_SERVICE_MESH_11S, |
180 | WMI_SERVICE_MESH_NON_11S, | ||
181 | WMI_SERVICE_PEER_STATS, | ||
182 | WMI_SERVICE_RESTRT_CHNL_SUPPORT, | ||
180 | 183 | ||
181 | /* keep last */ | 184 | /* keep last */ |
182 | WMI_SERVICE_MAX, | 185 | WMI_SERVICE_MAX, |
@@ -213,6 +216,7 @@ enum wmi_10x_service { | |||
213 | WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, | 216 | WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, |
214 | WMI_10X_SERVICE_MESH, | 217 | WMI_10X_SERVICE_MESH, |
215 | WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, | 218 | WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, |
219 | WMI_10X_SERVICE_PEER_STATS, | ||
216 | }; | 220 | }; |
217 | 221 | ||
218 | enum wmi_main_service { | 222 | enum wmi_main_service { |
@@ -294,7 +298,10 @@ enum wmi_10_4_service { | |||
294 | WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF, | 298 | WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF, |
295 | WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, | 299 | WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, |
296 | WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, | 300 | WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, |
297 | WMI_10_4_SERVICE_MESH, | 301 | WMI_10_4_SERVICE_MESH_NON_11S, |
302 | WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, | ||
303 | WMI_10_4_SERVICE_PEER_STATS, | ||
304 | WMI_10_4_SERVICE_MESH_11S, | ||
298 | }; | 305 | }; |
299 | 306 | ||
300 | static inline char *wmi_service_name(int service_id) | 307 | static inline char *wmi_service_name(int service_id) |
@@ -385,7 +392,10 @@ static inline char *wmi_service_name(int service_id) | |||
385 | SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF); | 392 | SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF); |
386 | SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); | 393 | SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); |
387 | SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT); | 394 | SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT); |
388 | SVCSTR(WMI_SERVICE_MESH); | 395 | SVCSTR(WMI_SERVICE_MESH_11S); |
396 | SVCSTR(WMI_SERVICE_MESH_NON_11S); | ||
397 | SVCSTR(WMI_SERVICE_PEER_STATS); | ||
398 | SVCSTR(WMI_SERVICE_RESTRT_CHNL_SUPPORT); | ||
389 | default: | 399 | default: |
390 | return NULL; | 400 | return NULL; |
391 | } | 401 | } |
@@ -460,9 +470,11 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out, | |||
460 | SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, | 470 | SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, |
461 | WMI_SERVICE_BSS_CHANNEL_INFO_64, len); | 471 | WMI_SERVICE_BSS_CHANNEL_INFO_64, len); |
462 | SVCMAP(WMI_10X_SERVICE_MESH, | 472 | SVCMAP(WMI_10X_SERVICE_MESH, |
463 | WMI_SERVICE_MESH, len); | 473 | WMI_SERVICE_MESH_11S, len); |
464 | SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, | 474 | SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, |
465 | WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); | 475 | WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); |
476 | SVCMAP(WMI_10X_SERVICE_PEER_STATS, | ||
477 | WMI_SERVICE_PEER_STATS, len); | ||
466 | } | 478 | } |
467 | 479 | ||
468 | static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out, | 480 | static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out, |
@@ -623,8 +635,14 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, | |||
623 | WMI_SERVICE_BSS_CHANNEL_INFO_64, len); | 635 | WMI_SERVICE_BSS_CHANNEL_INFO_64, len); |
624 | SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, | 636 | SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, |
625 | WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); | 637 | WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); |
626 | SVCMAP(WMI_10_4_SERVICE_MESH, | 638 | SVCMAP(WMI_10_4_SERVICE_MESH_NON_11S, |
627 | WMI_SERVICE_MESH, len); | 639 | WMI_SERVICE_MESH_NON_11S, len); |
640 | SVCMAP(WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, | ||
641 | WMI_SERVICE_RESTRT_CHNL_SUPPORT, len); | ||
642 | SVCMAP(WMI_10_4_SERVICE_PEER_STATS, | ||
643 | WMI_SERVICE_PEER_STATS, len); | ||
644 | SVCMAP(WMI_10_4_SERVICE_MESH_11S, | ||
645 | WMI_SERVICE_MESH_11S, len); | ||
628 | } | 646 | } |
629 | 647 | ||
630 | #undef SVCMAP | 648 | #undef SVCMAP |
@@ -1800,7 +1818,6 @@ enum wmi_channel_change_cause { | |||
1800 | #define WMI_CHANNEL_CHANGE_CAUSE_CSA (1 << 13) | 1818 | #define WMI_CHANNEL_CHANGE_CAUSE_CSA (1 << 13) |
1801 | 1819 | ||
1802 | #define WMI_MAX_SPATIAL_STREAM 3 /* default max ss */ | 1820 | #define WMI_MAX_SPATIAL_STREAM 3 /* default max ss */ |
1803 | #define WMI_10_4_MAX_SPATIAL_STREAM 4 | ||
1804 | 1821 | ||
1805 | /* HT Capabilities*/ | 1822 | /* HT Capabilities*/ |
1806 | #define WMI_HT_CAP_ENABLED 0x0001 /* HT Enabled/ disabled */ | 1823 | #define WMI_HT_CAP_ENABLED 0x0001 /* HT Enabled/ disabled */ |
@@ -2417,6 +2434,7 @@ enum wmi_10_2_feature_mask { | |||
2417 | WMI_10_2_RX_BATCH_MODE = BIT(0), | 2434 | WMI_10_2_RX_BATCH_MODE = BIT(0), |
2418 | WMI_10_2_ATF_CONFIG = BIT(1), | 2435 | WMI_10_2_ATF_CONFIG = BIT(1), |
2419 | WMI_10_2_COEX_GPIO = BIT(3), | 2436 | WMI_10_2_COEX_GPIO = BIT(3), |
2437 | WMI_10_2_PEER_STATS = BIT(7), | ||
2420 | }; | 2438 | }; |
2421 | 2439 | ||
2422 | struct wmi_resource_config_10_2 { | 2440 | struct wmi_resource_config_10_2 { |
@@ -4227,7 +4245,13 @@ struct wmi_10_2_peer_stats { | |||
4227 | 4245 | ||
4228 | struct wmi_10_2_4_peer_stats { | 4246 | struct wmi_10_2_4_peer_stats { |
4229 | struct wmi_10_2_peer_stats common; | 4247 | struct wmi_10_2_peer_stats common; |
4230 | __le32 unknown_value; /* FIXME: what is this word? */ | 4248 | __le32 peer_rssi_changed; |
4249 | } __packed; | ||
4250 | |||
4251 | struct wmi_10_2_4_ext_peer_stats { | ||
4252 | struct wmi_10_2_peer_stats common; | ||
4253 | __le32 peer_rssi_changed; | ||
4254 | __le32 rx_duration; | ||
4231 | } __packed; | 4255 | } __packed; |
4232 | 4256 | ||
4233 | struct wmi_10_4_peer_stats { | 4257 | struct wmi_10_4_peer_stats { |
@@ -4270,12 +4294,40 @@ enum wmi_vdev_type { | |||
4270 | }; | 4294 | }; |
4271 | 4295 | ||
4272 | enum wmi_vdev_subtype { | 4296 | enum wmi_vdev_subtype { |
4273 | WMI_VDEV_SUBTYPE_NONE = 0, | 4297 | WMI_VDEV_SUBTYPE_NONE, |
4274 | WMI_VDEV_SUBTYPE_P2P_DEVICE = 1, | 4298 | WMI_VDEV_SUBTYPE_P2P_DEVICE, |
4275 | WMI_VDEV_SUBTYPE_P2P_CLIENT = 2, | 4299 | WMI_VDEV_SUBTYPE_P2P_CLIENT, |
4276 | WMI_VDEV_SUBTYPE_P2P_GO = 3, | 4300 | WMI_VDEV_SUBTYPE_P2P_GO, |
4277 | WMI_VDEV_SUBTYPE_PROXY_STA = 4, | 4301 | WMI_VDEV_SUBTYPE_PROXY_STA, |
4278 | WMI_VDEV_SUBTYPE_MESH = 5, | 4302 | WMI_VDEV_SUBTYPE_MESH_11S, |
4303 | WMI_VDEV_SUBTYPE_MESH_NON_11S, | ||
4304 | }; | ||
4305 | |||
4306 | enum wmi_vdev_subtype_legacy { | ||
4307 | WMI_VDEV_SUBTYPE_LEGACY_NONE = 0, | ||
4308 | WMI_VDEV_SUBTYPE_LEGACY_P2P_DEV = 1, | ||
4309 | WMI_VDEV_SUBTYPE_LEGACY_P2P_CLI = 2, | ||
4310 | WMI_VDEV_SUBTYPE_LEGACY_P2P_GO = 3, | ||
4311 | WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA = 4, | ||
4312 | }; | ||
4313 | |||
4314 | enum wmi_vdev_subtype_10_2_4 { | ||
4315 | WMI_VDEV_SUBTYPE_10_2_4_NONE = 0, | ||
4316 | WMI_VDEV_SUBTYPE_10_2_4_P2P_DEV = 1, | ||
4317 | WMI_VDEV_SUBTYPE_10_2_4_P2P_CLI = 2, | ||
4318 | WMI_VDEV_SUBTYPE_10_2_4_P2P_GO = 3, | ||
4319 | WMI_VDEV_SUBTYPE_10_2_4_PROXY_STA = 4, | ||
4320 | WMI_VDEV_SUBTYPE_10_2_4_MESH_11S = 5, | ||
4321 | }; | ||
4322 | |||
4323 | enum wmi_vdev_subtype_10_4 { | ||
4324 | WMI_VDEV_SUBTYPE_10_4_NONE = 0, | ||
4325 | WMI_VDEV_SUBTYPE_10_4_P2P_DEV = 1, | ||
4326 | WMI_VDEV_SUBTYPE_10_4_P2P_CLI = 2, | ||
4327 | WMI_VDEV_SUBTYPE_10_4_P2P_GO = 3, | ||
4328 | WMI_VDEV_SUBTYPE_10_4_PROXY_STA = 4, | ||
4329 | WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S = 5, | ||
4330 | WMI_VDEV_SUBTYPE_10_4_MESH_11S = 6, | ||
4279 | }; | 4331 | }; |
4280 | 4332 | ||
4281 | /* values for vdev_subtype */ | 4333 | /* values for vdev_subtype */ |
@@ -5442,6 +5494,16 @@ struct wmi_host_swba_event { | |||
5442 | struct wmi_bcn_info bcn_info[0]; | 5494 | struct wmi_bcn_info bcn_info[0]; |
5443 | } __packed; | 5495 | } __packed; |
5444 | 5496 | ||
5497 | struct wmi_10_2_4_bcn_info { | ||
5498 | struct wmi_tim_info tim_info; | ||
5499 | /* The 10.2.4 FW doesn't have p2p NOA info */ | ||
5500 | } __packed; | ||
5501 | |||
5502 | struct wmi_10_2_4_host_swba_event { | ||
5503 | __le32 vdev_map; | ||
5504 | struct wmi_10_2_4_bcn_info bcn_info[0]; | ||
5505 | } __packed; | ||
5506 | |||
5445 | /* 16 words = 512 client + 1 word = for guard */ | 5507 | /* 16 words = 512 client + 1 word = for guard */ |
5446 | #define WMI_10_4_TIM_BITMAP_ARRAY_SIZE 17 | 5508 | #define WMI_10_4_TIM_BITMAP_ARRAY_SIZE 17 |
5447 | 5509 | ||
@@ -6436,5 +6498,7 @@ size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); | |||
6436 | void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, | 6498 | void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, |
6437 | struct ath10k_fw_stats *fw_stats, | 6499 | struct ath10k_fw_stats *fw_stats, |
6438 | char *buf); | 6500 | char *buf); |
6501 | int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, | ||
6502 | enum wmi_vdev_subtype subtype); | ||
6439 | 6503 | ||
6440 | #endif /* _WMI_H_ */ | 6504 | #endif /* _WMI_H_ */ |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 25e45e4d1a60..815efe9fd208 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -126,12 +126,8 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
126 | 126 | ||
127 | static void ath9k_ani_restart(struct ath_hw *ah) | 127 | static void ath9k_ani_restart(struct ath_hw *ah) |
128 | { | 128 | { |
129 | struct ar5416AniState *aniState; | 129 | struct ar5416AniState *aniState = &ah->ani; |
130 | |||
131 | if (!ah->curchan) | ||
132 | return; | ||
133 | 130 | ||
134 | aniState = &ah->ani; | ||
135 | aniState->listenTime = 0; | 131 | aniState->listenTime = 0; |
136 | 132 | ||
137 | ENABLE_REGWRITE_BUFFER(ah); | 133 | ENABLE_REGWRITE_BUFFER(ah); |
@@ -221,12 +217,7 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, | |||
221 | 217 | ||
222 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | 218 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) |
223 | { | 219 | { |
224 | struct ar5416AniState *aniState; | 220 | struct ar5416AniState *aniState = &ah->ani; |
225 | |||
226 | if (!ah->curchan) | ||
227 | return; | ||
228 | |||
229 | aniState = &ah->ani; | ||
230 | 221 | ||
231 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) | 222 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) |
232 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false); | 223 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false); |
@@ -281,12 +272,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, | |||
281 | 272 | ||
282 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | 273 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) |
283 | { | 274 | { |
284 | struct ar5416AniState *aniState; | 275 | struct ar5416AniState *aniState = &ah->ani; |
285 | |||
286 | if (!ah->curchan) | ||
287 | return; | ||
288 | |||
289 | aniState = &ah->ani; | ||
290 | 276 | ||
291 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) | 277 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) |
292 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1, | 278 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1, |
@@ -299,9 +285,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | |||
299 | */ | 285 | */ |
300 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | 286 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) |
301 | { | 287 | { |
302 | struct ar5416AniState *aniState; | 288 | struct ar5416AniState *aniState = &ah->ani; |
303 | |||
304 | aniState = &ah->ani; | ||
305 | 289 | ||
306 | /* lower OFDM noise immunity */ | 290 | /* lower OFDM noise immunity */ |
307 | if (aniState->ofdmNoiseImmunityLevel > 0 && | 291 | if (aniState->ofdmNoiseImmunityLevel > 0 && |
@@ -329,7 +313,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
329 | struct ath_common *common = ath9k_hw_common(ah); | 313 | struct ath_common *common = ath9k_hw_common(ah); |
330 | int ofdm_nil, cck_nil; | 314 | int ofdm_nil, cck_nil; |
331 | 315 | ||
332 | if (!ah->curchan) | 316 | if (!chan) |
333 | return; | 317 | return; |
334 | 318 | ||
335 | BUG_ON(aniState == NULL); | 319 | BUG_ON(aniState == NULL); |
@@ -416,14 +400,10 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) | |||
416 | 400 | ||
417 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) | 401 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) |
418 | { | 402 | { |
419 | struct ar5416AniState *aniState; | 403 | struct ar5416AniState *aniState = &ah->ani; |
420 | struct ath_common *common = ath9k_hw_common(ah); | 404 | struct ath_common *common = ath9k_hw_common(ah); |
421 | u32 ofdmPhyErrRate, cckPhyErrRate; | 405 | u32 ofdmPhyErrRate, cckPhyErrRate; |
422 | 406 | ||
423 | if (!ah->curchan) | ||
424 | return; | ||
425 | |||
426 | aniState = &ah->ani; | ||
427 | if (!ath9k_hw_ani_read_counters(ah)) | 407 | if (!ath9k_hw_ani_read_counters(ah)) |
428 | return; | 408 | return; |
429 | 409 | ||
@@ -450,7 +430,9 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) | |||
450 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { | 430 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { |
451 | ath9k_hw_ani_cck_err_trigger(ah); | 431 | ath9k_hw_ani_cck_err_trigger(ah); |
452 | aniState->ofdmsTurn = true; | 432 | aniState->ofdmsTurn = true; |
453 | } | 433 | } else |
434 | return; | ||
435 | |||
454 | ath9k_ani_restart(ah); | 436 | ath9k_ani_restart(ah); |
455 | } | 437 | } |
456 | } | 438 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_aic.c b/drivers/net/wireless/ath/ath9k/ar9003_aic.c index 1db119d77783..547cd46da260 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_aic.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_aic.c | |||
@@ -53,19 +53,19 @@ static bool ar9003_hw_is_aic_enabled(struct ath_hw *ah) | |||
53 | return true; | 53 | return true; |
54 | } | 54 | } |
55 | 55 | ||
56 | static int16_t ar9003_aic_find_valid(struct ath_aic_sram_info *cal_sram, | 56 | static int16_t ar9003_aic_find_valid(bool *cal_sram_valid, |
57 | bool dir, u8 index) | 57 | bool dir, u8 index) |
58 | { | 58 | { |
59 | int16_t i; | 59 | int16_t i; |
60 | 60 | ||
61 | if (dir) { | 61 | if (dir) { |
62 | for (i = index + 1; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | 62 | for (i = index + 1; i < ATH_AIC_MAX_BT_CHANNEL; i++) { |
63 | if (cal_sram[i].valid) | 63 | if (cal_sram_valid[i]) |
64 | break; | 64 | break; |
65 | } | 65 | } |
66 | } else { | 66 | } else { |
67 | for (i = index - 1; i >= 0; i--) { | 67 | for (i = index - 1; i >= 0; i--) { |
68 | if (cal_sram[i].valid) | 68 | if (cal_sram_valid[i]) |
69 | break; | 69 | break; |
70 | } | 70 | } |
71 | } | 71 | } |
@@ -264,7 +264,7 @@ static u8 ar9003_aic_cal_start(struct ath_hw *ah, u8 min_valid_count) | |||
264 | static bool ar9003_aic_cal_post_process(struct ath_hw *ah) | 264 | static bool ar9003_aic_cal_post_process(struct ath_hw *ah) |
265 | { | 265 | { |
266 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | 266 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; |
267 | struct ath_aic_sram_info cal_sram[ATH_AIC_MAX_BT_CHANNEL]; | 267 | bool cal_sram_valid[ATH_AIC_MAX_BT_CHANNEL]; |
268 | struct ath_aic_out_info aic_sram[ATH_AIC_MAX_BT_CHANNEL]; | 268 | struct ath_aic_out_info aic_sram[ATH_AIC_MAX_BT_CHANNEL]; |
269 | u32 dir_path_gain_idx, quad_path_gain_idx, value; | 269 | u32 dir_path_gain_idx, quad_path_gain_idx, value; |
270 | u32 fixed_com_att_db; | 270 | u32 fixed_com_att_db; |
@@ -272,33 +272,34 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah) | |||
272 | int16_t i; | 272 | int16_t i; |
273 | bool ret = true; | 273 | bool ret = true; |
274 | 274 | ||
275 | memset(&cal_sram, 0, sizeof(cal_sram)); | 275 | memset(&cal_sram_valid, 0, sizeof(cal_sram_valid)); |
276 | memset(&aic_sram, 0, sizeof(aic_sram)); | 276 | memset(&aic_sram, 0, sizeof(aic_sram)); |
277 | 277 | ||
278 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | 278 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { |
279 | struct ath_aic_sram_info sram; | ||
279 | value = aic->aic_sram[i]; | 280 | value = aic->aic_sram[i]; |
280 | 281 | ||
281 | cal_sram[i].valid = | 282 | cal_sram_valid[i] = sram.valid = |
282 | MS(value, AR_PHY_AIC_SRAM_VALID); | 283 | MS(value, AR_PHY_AIC_SRAM_VALID); |
283 | cal_sram[i].rot_quad_att_db = | 284 | sram.rot_quad_att_db = |
284 | MS(value, AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB); | 285 | MS(value, AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB); |
285 | cal_sram[i].vga_quad_sign = | 286 | sram.vga_quad_sign = |
286 | MS(value, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN); | 287 | MS(value, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN); |
287 | cal_sram[i].rot_dir_att_db = | 288 | sram.rot_dir_att_db = |
288 | MS(value, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB); | 289 | MS(value, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB); |
289 | cal_sram[i].vga_dir_sign = | 290 | sram.vga_dir_sign = |
290 | MS(value, AR_PHY_AIC_SRAM_VGA_DIR_SIGN); | 291 | MS(value, AR_PHY_AIC_SRAM_VGA_DIR_SIGN); |
291 | cal_sram[i].com_att_6db = | 292 | sram.com_att_6db = |
292 | MS(value, AR_PHY_AIC_SRAM_COM_ATT_6DB); | 293 | MS(value, AR_PHY_AIC_SRAM_COM_ATT_6DB); |
293 | 294 | ||
294 | if (cal_sram[i].valid) { | 295 | if (sram.valid) { |
295 | dir_path_gain_idx = cal_sram[i].rot_dir_att_db + | 296 | dir_path_gain_idx = sram.rot_dir_att_db + |
296 | com_att_db_table[cal_sram[i].com_att_6db]; | 297 | com_att_db_table[sram.com_att_6db]; |
297 | quad_path_gain_idx = cal_sram[i].rot_quad_att_db + | 298 | quad_path_gain_idx = sram.rot_quad_att_db + |
298 | com_att_db_table[cal_sram[i].com_att_6db]; | 299 | com_att_db_table[sram.com_att_6db]; |
299 | 300 | ||
300 | dir_path_sign = (cal_sram[i].vga_dir_sign) ? 1 : -1; | 301 | dir_path_sign = (sram.vga_dir_sign) ? 1 : -1; |
301 | quad_path_sign = (cal_sram[i].vga_quad_sign) ? 1 : -1; | 302 | quad_path_sign = (sram.vga_quad_sign) ? 1 : -1; |
302 | 303 | ||
303 | aic_sram[i].dir_path_gain_lin = dir_path_sign * | 304 | aic_sram[i].dir_path_gain_lin = dir_path_sign * |
304 | aic_lin_table[dir_path_gain_idx]; | 305 | aic_lin_table[dir_path_gain_idx]; |
@@ -310,16 +311,16 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah) | |||
310 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | 311 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { |
311 | int16_t start_idx, end_idx; | 312 | int16_t start_idx, end_idx; |
312 | 313 | ||
313 | if (cal_sram[i].valid) | 314 | if (cal_sram_valid[i]) |
314 | continue; | 315 | continue; |
315 | 316 | ||
316 | start_idx = ar9003_aic_find_valid(cal_sram, 0, i); | 317 | start_idx = ar9003_aic_find_valid(cal_sram_valid, 0, i); |
317 | end_idx = ar9003_aic_find_valid(cal_sram, 1, i); | 318 | end_idx = ar9003_aic_find_valid(cal_sram_valid, 1, i); |
318 | 319 | ||
319 | if (start_idx < 0) { | 320 | if (start_idx < 0) { |
320 | /* extrapolation */ | 321 | /* extrapolation */ |
321 | start_idx = end_idx; | 322 | start_idx = end_idx; |
322 | end_idx = ar9003_aic_find_valid(cal_sram, 1, start_idx); | 323 | end_idx = ar9003_aic_find_valid(cal_sram_valid, 1, start_idx); |
323 | 324 | ||
324 | if (end_idx < 0) { | 325 | if (end_idx < 0) { |
325 | ret = false; | 326 | ret = false; |
@@ -342,7 +343,7 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah) | |||
342 | 343 | ||
343 | if (end_idx < 0) { | 344 | if (end_idx < 0) { |
344 | /* extrapolation */ | 345 | /* extrapolation */ |
345 | end_idx = ar9003_aic_find_valid(cal_sram, 0, start_idx); | 346 | end_idx = ar9003_aic_find_valid(cal_sram_valid, 0, start_idx); |
346 | 347 | ||
347 | if (end_idx < 0) { | 348 | if (end_idx < 0) { |
348 | ret = false; | 349 | ret = false; |
@@ -378,19 +379,21 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah) | |||
378 | } | 379 | } |
379 | 380 | ||
380 | /* From dir/quad_path_gain_lin to sram. */ | 381 | /* From dir/quad_path_gain_lin to sram. */ |
381 | i = ar9003_aic_find_valid(cal_sram, 1, 0); | 382 | i = ar9003_aic_find_valid(cal_sram_valid, 1, 0); |
382 | if (i < 0) { | 383 | if (i < 0) { |
383 | i = 0; | 384 | i = 0; |
384 | ret = false; | 385 | ret = false; |
385 | } | 386 | } |
386 | fixed_com_att_db = com_att_db_table[cal_sram[i].com_att_6db]; | 387 | fixed_com_att_db = com_att_db_table[MS(aic->aic_sram[i], |
388 | AR_PHY_AIC_SRAM_COM_ATT_6DB)]; | ||
387 | 389 | ||
388 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | 390 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { |
389 | int16_t rot_dir_path_att_db, rot_quad_path_att_db; | 391 | int16_t rot_dir_path_att_db, rot_quad_path_att_db; |
392 | struct ath_aic_sram_info sram; | ||
390 | 393 | ||
391 | aic_sram[i].sram.vga_dir_sign = | 394 | sram.vga_dir_sign = |
392 | (aic_sram[i].dir_path_gain_lin >= 0) ? 1 : 0; | 395 | (aic_sram[i].dir_path_gain_lin >= 0) ? 1 : 0; |
393 | aic_sram[i].sram.vga_quad_sign= | 396 | sram.vga_quad_sign = |
394 | (aic_sram[i].quad_path_gain_lin >= 0) ? 1 : 0; | 397 | (aic_sram[i].quad_path_gain_lin >= 0) ? 1 : 0; |
395 | 398 | ||
396 | rot_dir_path_att_db = | 399 | rot_dir_path_att_db = |
@@ -400,33 +403,31 @@ static bool ar9003_aic_cal_post_process(struct ath_hw *ah) | |||
400 | ar9003_aic_find_index(0, abs(aic_sram[i].quad_path_gain_lin)) - | 403 | ar9003_aic_find_index(0, abs(aic_sram[i].quad_path_gain_lin)) - |
401 | fixed_com_att_db; | 404 | fixed_com_att_db; |
402 | 405 | ||
403 | aic_sram[i].sram.com_att_6db = | 406 | sram.com_att_6db = |
404 | ar9003_aic_find_index(1, fixed_com_att_db); | 407 | ar9003_aic_find_index(1, fixed_com_att_db); |
405 | 408 | ||
406 | aic_sram[i].sram.valid = 1; | 409 | sram.valid = 1; |
407 | 410 | ||
408 | aic_sram[i].sram.rot_dir_att_db = | 411 | sram.rot_dir_att_db = |
409 | min(max(rot_dir_path_att_db, | 412 | min(max(rot_dir_path_att_db, |
410 | (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB), | 413 | (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB), |
411 | ATH_AIC_MAX_ROT_DIR_ATT_DB); | 414 | ATH_AIC_MAX_ROT_DIR_ATT_DB); |
412 | aic_sram[i].sram.rot_quad_att_db = | 415 | sram.rot_quad_att_db = |
413 | min(max(rot_quad_path_att_db, | 416 | min(max(rot_quad_path_att_db, |
414 | (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB), | 417 | (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB), |
415 | ATH_AIC_MAX_ROT_QUAD_ATT_DB); | 418 | ATH_AIC_MAX_ROT_QUAD_ATT_DB); |
416 | } | ||
417 | 419 | ||
418 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | 420 | aic->aic_sram[i] = (SM(sram.vga_dir_sign, |
419 | aic->aic_sram[i] = (SM(aic_sram[i].sram.vga_dir_sign, | ||
420 | AR_PHY_AIC_SRAM_VGA_DIR_SIGN) | | 421 | AR_PHY_AIC_SRAM_VGA_DIR_SIGN) | |
421 | SM(aic_sram[i].sram.vga_quad_sign, | 422 | SM(sram.vga_quad_sign, |
422 | AR_PHY_AIC_SRAM_VGA_QUAD_SIGN) | | 423 | AR_PHY_AIC_SRAM_VGA_QUAD_SIGN) | |
423 | SM(aic_sram[i].sram.com_att_6db, | 424 | SM(sram.com_att_6db, |
424 | AR_PHY_AIC_SRAM_COM_ATT_6DB) | | 425 | AR_PHY_AIC_SRAM_COM_ATT_6DB) | |
425 | SM(aic_sram[i].sram.valid, | 426 | SM(sram.valid, |
426 | AR_PHY_AIC_SRAM_VALID) | | 427 | AR_PHY_AIC_SRAM_VALID) | |
427 | SM(aic_sram[i].sram.rot_dir_att_db, | 428 | SM(sram.rot_dir_att_db, |
428 | AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB) | | 429 | AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB) | |
429 | SM(aic_sram[i].sram.rot_quad_att_db, | 430 | SM(sram.rot_quad_att_db, |
430 | AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB)); | 431 | AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB)); |
431 | } | 432 | } |
432 | 433 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_aic.h b/drivers/net/wireless/ath/ath9k/ar9003_aic.h index 86f40644be43..9512c63799f2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_aic.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_aic.h | |||
@@ -50,7 +50,6 @@ struct ath_aic_sram_info { | |||
50 | struct ath_aic_out_info { | 50 | struct ath_aic_out_info { |
51 | int16_t dir_path_gain_lin; | 51 | int16_t dir_path_gain_lin; |
52 | int16_t quad_path_gain_lin; | 52 | int16_t quad_path_gain_lin; |
53 | struct ath_aic_sram_info sram; | ||
54 | }; | 53 | }; |
55 | 54 | ||
56 | u8 ar9003_aic_calibration(struct ath_hw *ah); | 55 | u8 ar9003_aic_calibration(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 8b4561e8ce1a..54ed2f72d35e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -5485,11 +5485,11 @@ unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, | |||
5485 | AR9300_PAPRD_SCALE_1); | 5485 | AR9300_PAPRD_SCALE_1); |
5486 | else { | 5486 | else { |
5487 | if (chan->channel >= 5700) | 5487 | if (chan->channel >= 5700) |
5488 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), | 5488 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), |
5489 | AR9300_PAPRD_SCALE_1); | 5489 | AR9300_PAPRD_SCALE_1); |
5490 | else if (chan->channel >= 5400) | 5490 | else if (chan->channel >= 5400) |
5491 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), | 5491 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), |
5492 | AR9300_PAPRD_SCALE_2); | 5492 | AR9300_PAPRD_SCALE_2); |
5493 | else | 5493 | else |
5494 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), | 5494 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), |
5495 | AR9300_PAPRD_SCALE_1); | 5495 | AR9300_PAPRD_SCALE_1); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 8b238c15916d..2fe12b0de5b4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -698,6 +698,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah) | |||
698 | else if (AR_SREV_9340(ah)) | 698 | else if (AR_SREV_9340(ah)) |
699 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 699 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
700 | ar9340Modes_low_ob_db_tx_gain_table_1p0); | 700 | ar9340Modes_low_ob_db_tx_gain_table_1p0); |
701 | else if (AR_SREV_9531_11(ah)) | ||
702 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
703 | qca953x_1p1_modes_no_xpa_low_power_tx_gain_table); | ||
701 | else if (AR_SREV_9485_11_OR_LATER(ah)) | 704 | else if (AR_SREV_9485_11_OR_LATER(ah)) |
702 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 705 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
703 | ar9485Modes_low_ob_db_tx_gain_1_1); | 706 | ar9485Modes_low_ob_db_tx_gain_1_1); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 201425e7f9cb..06c1ca6e8290 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -976,9 +976,14 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
976 | /* | 976 | /* |
977 | * JAPAN regulatory. | 977 | * JAPAN regulatory. |
978 | */ | 978 | */ |
979 | if (chan->channel == 2484) | 979 | if (chan->channel == 2484) { |
980 | ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1); | 980 | ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1); |
981 | 981 | ||
982 | if (AR_SREV_9531(ah)) | ||
983 | REG_RMW_FIELD(ah, AR_PHY_FCAL_2_0, | ||
984 | AR_PHY_FLC_PWR_THRESH, 0); | ||
985 | } | ||
986 | |||
982 | ah->modes_index = modesIndex; | 987 | ah->modes_index = modesIndex; |
983 | ar9003_hw_override_ini(ah); | 988 | ar9003_hw_override_ini(ah); |
984 | ar9003_hw_set_channel_regs(ah, chan); | 989 | ar9003_hw_set_channel_regs(ah, chan); |
@@ -2071,7 +2076,8 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
2071 | * to be disabled. | 2076 | * to be disabled. |
2072 | * | 2077 | * |
2073 | * 0x04000409: Packet stuck on receive. | 2078 | * 0x04000409: Packet stuck on receive. |
2074 | * Full chip reset is required for all chips except AR9340. | 2079 | * Full chip reset is required for all chips except |
2080 | * AR9340, AR9531 and AR9561. | ||
2075 | */ | 2081 | */ |
2076 | 2082 | ||
2077 | /* | 2083 | /* |
@@ -2100,7 +2106,7 @@ bool ar9003_hw_bb_watchdog_check(struct ath_hw *ah) | |||
2100 | case 0x04000b09: | 2106 | case 0x04000b09: |
2101 | return true; | 2107 | return true; |
2102 | case 0x04000409: | 2108 | case 0x04000409: |
2103 | if (AR_SREV_9340(ah) || AR_SREV_9531(ah)) | 2109 | if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) |
2104 | return false; | 2110 | return false; |
2105 | else | 2111 | else |
2106 | return true; | 2112 | return true; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index c5f8bc4b5595..566da789f97e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -487,6 +487,9 @@ | |||
487 | #define AR_PHY_ADDAC_PARA_CTL (AR_SM_BASE + 0x150) | 487 | #define AR_PHY_ADDAC_PARA_CTL (AR_SM_BASE + 0x150) |
488 | #define AR_PHY_XPA_CFG (AR_SM_BASE + 0x158) | 488 | #define AR_PHY_XPA_CFG (AR_SM_BASE + 0x158) |
489 | 489 | ||
490 | #define AR_PHY_FLC_PWR_THRESH 7 | ||
491 | #define AR_PHY_FLC_PWR_THRESH_S 0 | ||
492 | |||
490 | #define AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW 3 | 493 | #define AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW 3 |
491 | #define AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW_S 0 | 494 | #define AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW_S 0 |
492 | 495 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 6fc0d07e5ec6..c0b90daa3e3d 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h | |||
@@ -757,6 +757,71 @@ static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = { | |||
757 | {0x00016448, 0x6c927a70}, | 757 | {0x00016448, 0x6c927a70}, |
758 | }; | 758 | }; |
759 | 759 | ||
760 | static const u32 qca953x_1p1_modes_no_xpa_low_power_tx_gain_table[][2] = { | ||
761 | /* Addr allmodes */ | ||
762 | {0x0000a2dc, 0xfff55592}, | ||
763 | {0x0000a2e0, 0xfff99924}, | ||
764 | {0x0000a2e4, 0xfffe1e00}, | ||
765 | {0x0000a2e8, 0xffffe000}, | ||
766 | {0x0000a410, 0x000050d6}, | ||
767 | {0x0000a500, 0x00000069}, | ||
768 | {0x0000a504, 0x0400006b}, | ||
769 | {0x0000a508, 0x0800006d}, | ||
770 | {0x0000a50c, 0x0c000269}, | ||
771 | {0x0000a510, 0x1000026b}, | ||
772 | {0x0000a514, 0x1400026d}, | ||
773 | {0x0000a518, 0x18000669}, | ||
774 | {0x0000a51c, 0x1c00066b}, | ||
775 | {0x0000a520, 0x1d000a68}, | ||
776 | {0x0000a524, 0x21000a6a}, | ||
777 | {0x0000a528, 0x25000a6c}, | ||
778 | {0x0000a52c, 0x29000a6e}, | ||
779 | {0x0000a530, 0x2d0012a9}, | ||
780 | {0x0000a534, 0x310012ab}, | ||
781 | {0x0000a538, 0x350012ad}, | ||
782 | {0x0000a53c, 0x39001b0a}, | ||
783 | {0x0000a540, 0x3d001b0c}, | ||
784 | {0x0000a544, 0x41001b0e}, | ||
785 | {0x0000a548, 0x43001bae}, | ||
786 | {0x0000a54c, 0x45001914}, | ||
787 | {0x0000a550, 0x47001916}, | ||
788 | {0x0000a554, 0x49001b96}, | ||
789 | {0x0000a558, 0x49001b96}, | ||
790 | {0x0000a55c, 0x49001b96}, | ||
791 | {0x0000a560, 0x49001b96}, | ||
792 | {0x0000a564, 0x49001b96}, | ||
793 | {0x0000a568, 0x49001b96}, | ||
794 | {0x0000a56c, 0x49001b96}, | ||
795 | {0x0000a570, 0x49001b96}, | ||
796 | {0x0000a574, 0x49001b96}, | ||
797 | {0x0000a578, 0x49001b96}, | ||
798 | {0x0000a57c, 0x49001b96}, | ||
799 | {0x0000a600, 0x00000000}, | ||
800 | {0x0000a604, 0x00000000}, | ||
801 | {0x0000a608, 0x00000000}, | ||
802 | {0x0000a60c, 0x00000000}, | ||
803 | {0x0000a610, 0x00000000}, | ||
804 | {0x0000a614, 0x00000000}, | ||
805 | {0x0000a618, 0x00804201}, | ||
806 | {0x0000a61c, 0x01408201}, | ||
807 | {0x0000a620, 0x01408502}, | ||
808 | {0x0000a624, 0x01408502}, | ||
809 | {0x0000a628, 0x01408502}, | ||
810 | {0x0000a62c, 0x01408502}, | ||
811 | {0x0000a630, 0x01408502}, | ||
812 | {0x0000a634, 0x01408502}, | ||
813 | {0x0000a638, 0x01408502}, | ||
814 | {0x0000a63c, 0x01408502}, | ||
815 | {0x0000b2dc, 0xfff55592}, | ||
816 | {0x0000b2e0, 0xfff99924}, | ||
817 | {0x0000b2e4, 0xfffe1e00}, | ||
818 | {0x0000b2e8, 0xffffe000}, | ||
819 | {0x00016044, 0x044922db}, | ||
820 | {0x00016048, 0x6c927a70}, | ||
821 | {0x00016444, 0x044922db}, | ||
822 | {0x00016448, 0x6c927a70}, | ||
823 | }; | ||
824 | |||
760 | static const u32 qca953x_2p0_baseband_core[][2] = { | 825 | static const u32 qca953x_2p0_baseband_core[][2] = { |
761 | /* Addr allmodes */ | 826 | /* Addr allmodes */ |
762 | {0x00009800, 0xafe68e30}, | 827 | {0x00009800, 0xafe68e30}, |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 3e2e24e4843f..37f6d66d1671 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -241,6 +241,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
241 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 241 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
242 | struct ath_common *common = ath9k_hw_common(ah); | 242 | struct ath_common *common = ath9k_hw_common(ah); |
243 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | 243 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); |
244 | u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL); | ||
244 | 245 | ||
245 | if (ah->caldata) | 246 | if (ah->caldata) |
246 | h = ah->caldata->nfCalHist; | 247 | h = ah->caldata->nfCalHist; |
@@ -264,6 +265,16 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
264 | } | 265 | } |
265 | 266 | ||
266 | /* | 267 | /* |
268 | * stop NF cal if ongoing to ensure NF load completes immediately | ||
269 | * (or after end rx/tx frame if ongoing) | ||
270 | */ | ||
271 | if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) { | ||
272 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | ||
273 | REG_RMW_BUFFER_FLUSH(ah); | ||
274 | ENABLE_REG_RMW_BUFFER(ah); | ||
275 | } | ||
276 | |||
277 | /* | ||
267 | * Load software filtered NF value into baseband internal minCCApwr | 278 | * Load software filtered NF value into baseband internal minCCApwr |
268 | * variable. | 279 | * variable. |
269 | */ | 280 | */ |
@@ -276,18 +287,33 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
276 | 287 | ||
277 | /* | 288 | /* |
278 | * Wait for load to complete, should be fast, a few 10s of us. | 289 | * Wait for load to complete, should be fast, a few 10s of us. |
279 | * The max delay was changed from an original 250us to 10000us | 290 | * The max delay was changed from an original 250us to 22.2 msec. |
280 | * since 250us often results in NF load timeout and causes deaf | 291 | * This would increase timeout to the longest possible frame |
281 | * condition during stress testing 12/12/2009 | 292 | * (11n max length 22.1 msec) |
282 | */ | 293 | */ |
283 | for (j = 0; j < 10000; j++) { | 294 | for (j = 0; j < 22200; j++) { |
284 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & | 295 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & |
285 | AR_PHY_AGC_CONTROL_NF) == 0) | 296 | AR_PHY_AGC_CONTROL_NF) == 0) |
286 | break; | 297 | break; |
287 | udelay(10); | 298 | udelay(10); |
288 | } | 299 | } |
289 | 300 | ||
290 | /* | 301 | /* |
302 | * Restart NF so it can continue. | ||
303 | */ | ||
304 | if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) { | ||
305 | ENABLE_REG_RMW_BUFFER(ah); | ||
306 | if (bb_agc_ctl & AR_PHY_AGC_CONTROL_ENABLE_NF) | ||
307 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
308 | AR_PHY_AGC_CONTROL_ENABLE_NF); | ||
309 | if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NO_UPDATE_NF) | ||
310 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
311 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
312 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | ||
313 | REG_RMW_BUFFER_FLUSH(ah); | ||
314 | } | ||
315 | |||
316 | /* | ||
291 | * We timed out waiting for the noisefloor to load, probably due to an | 317 | * We timed out waiting for the noisefloor to load, probably due to an |
292 | * in-progress rx. Simply return here and allow the load plenty of time | 318 | * in-progress rx. Simply return here and allow the load plenty of time |
293 | * to complete before the next calibration interval. We need to avoid | 319 | * to complete before the next calibration interval. We need to avoid |
@@ -296,7 +322,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
296 | * here, the baseband nf cal will just be capped by our present | 322 | * here, the baseband nf cal will just be capped by our present |
297 | * noisefloor until the next calibration timer. | 323 | * noisefloor until the next calibration timer. |
298 | */ | 324 | */ |
299 | if (j == 10000) { | 325 | if (j == 22200) { |
300 | ath_dbg(common, ANY, | 326 | ath_dbg(common, ANY, |
301 | "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", | 327 | "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", |
302 | REG_READ(ah, AR_PHY_AGC_CONTROL)); | 328 | REG_READ(ah, AR_PHY_AGC_CONTROL)); |
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 50e614b915f1..319cb5f25f58 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
@@ -226,7 +226,7 @@ static const char *chanctx_state_string(enum ath_chanctx_state state) | |||
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | static const u32 chanctx_event_delta(struct ath_softc *sc) | 229 | static u32 chanctx_event_delta(struct ath_softc *sc) |
230 | { | 230 | { |
231 | u64 ms; | 231 | u64 ms; |
232 | struct timespec ts, *old; | 232 | struct timespec ts, *old; |
@@ -1454,7 +1454,7 @@ static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
1454 | if (!sc->p2p_ps_timer) | 1454 | if (!sc->p2p_ps_timer) |
1455 | return; | 1455 | return; |
1456 | 1456 | ||
1457 | if (vif->type != NL80211_IFTYPE_STATION || !vif->p2p) | 1457 | if (vif->type != NL80211_IFTYPE_STATION) |
1458 | return; | 1458 | return; |
1459 | 1459 | ||
1460 | sc->p2p_ps_vif = avp; | 1460 | sc->p2p_ps_vif = avp; |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 165dd202c365..8cbf4904db7b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -55,6 +55,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { | |||
55 | .driver_info = AR9280_USB }, /* Buffalo WLI-UV-AG300P */ | 55 | .driver_info = AR9280_USB }, /* Buffalo WLI-UV-AG300P */ |
56 | { USB_DEVICE(0x04da, 0x3904), | 56 | { USB_DEVICE(0x04da, 0x3904), |
57 | .driver_info = AR9280_USB }, | 57 | .driver_info = AR9280_USB }, |
58 | { USB_DEVICE(0x0930, 0x0a08), | ||
59 | .driver_info = AR9280_USB }, /* Toshiba WLM-20U2 and GN-1080 */ | ||
58 | 60 | ||
59 | { USB_DEVICE(0x0cf3, 0x20ff), | 61 | { USB_DEVICE(0x0cf3, 0x20ff), |
60 | .driver_info = STORAGE_DEVICE }, | 62 | .driver_info = STORAGE_DEVICE }, |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 257f46ed4a04..e7a31016f370 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1368,6 +1368,16 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1368 | if (ath9k_hw_mci_is_enabled(ah)) | 1368 | if (ath9k_hw_mci_is_enabled(ah)) |
1369 | ar9003_mci_check_gpm_offset(ah); | 1369 | ar9003_mci_check_gpm_offset(ah); |
1370 | 1370 | ||
1371 | /* DMA HALT added to resolve ar9300 and ar9580 bus error during | ||
1372 | * RTC_RC reg read | ||
1373 | */ | ||
1374 | if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { | ||
1375 | REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); | ||
1376 | ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, | ||
1377 | 20 * AH_WAIT_TIMEOUT); | ||
1378 | REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); | ||
1379 | } | ||
1380 | |||
1371 | REG_WRITE(ah, AR_RTC_RC, rst_flags); | 1381 | REG_WRITE(ah, AR_RTC_RC, rst_flags); |
1372 | 1382 | ||
1373 | REGWRITE_BUFFER_FLUSH(ah); | 1383 | REGWRITE_BUFFER_FLUSH(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index ab7a1ac37849..d4e0ac946c3a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -751,14 +751,6 @@ static const struct ieee80211_iface_combination if_comb_multi[] = { | |||
751 | 751 | ||
752 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ | 752 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ |
753 | 753 | ||
754 | static const struct ieee80211_iface_limit if_dfs_limits[] = { | ||
755 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | | ||
756 | #ifdef CONFIG_MAC80211_MESH | ||
757 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
758 | #endif | ||
759 | BIT(NL80211_IFTYPE_ADHOC) }, | ||
760 | }; | ||
761 | |||
762 | static const struct ieee80211_iface_combination if_comb[] = { | 754 | static const struct ieee80211_iface_combination if_comb[] = { |
763 | { | 755 | { |
764 | .limits = if_limits, | 756 | .limits = if_limits, |
@@ -766,6 +758,11 @@ static const struct ieee80211_iface_combination if_comb[] = { | |||
766 | .max_interfaces = 2048, | 758 | .max_interfaces = 2048, |
767 | .num_different_channels = 1, | 759 | .num_different_channels = 1, |
768 | .beacon_int_infra_match = true, | 760 | .beacon_int_infra_match = true, |
761 | #ifdef CONFIG_ATH9K_DFS_CERTIFIED | ||
762 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | ||
763 | BIT(NL80211_CHAN_WIDTH_20) | | ||
764 | BIT(NL80211_CHAN_WIDTH_40), | ||
765 | #endif | ||
769 | }, | 766 | }, |
770 | { | 767 | { |
771 | .limits = wds_limits, | 768 | .limits = wds_limits, |
@@ -774,18 +771,6 @@ static const struct ieee80211_iface_combination if_comb[] = { | |||
774 | .num_different_channels = 1, | 771 | .num_different_channels = 1, |
775 | .beacon_int_infra_match = true, | 772 | .beacon_int_infra_match = true, |
776 | }, | 773 | }, |
777 | #ifdef CONFIG_ATH9K_DFS_CERTIFIED | ||
778 | { | ||
779 | .limits = if_dfs_limits, | ||
780 | .n_limits = ARRAY_SIZE(if_dfs_limits), | ||
781 | .max_interfaces = 1, | ||
782 | .num_different_channels = 1, | ||
783 | .beacon_int_infra_match = true, | ||
784 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | ||
785 | BIT(NL80211_CHAN_WIDTH_20) | | ||
786 | BIT(NL80211_CHAN_WIDTH_40), | ||
787 | } | ||
788 | #endif | ||
789 | }; | 774 | }; |
790 | 775 | ||
791 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT | 776 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index cf58a304e9f0..3aed43a63f94 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -978,7 +978,7 @@ static void ath9k_update_bssid_mask(struct ath_softc *sc, | |||
978 | if (ctx->nvifs_assigned != 1) | 978 | if (ctx->nvifs_assigned != 1) |
979 | continue; | 979 | continue; |
980 | 980 | ||
981 | if (!avp->vif->p2p || !iter_data->has_hw_macaddr) | 981 | if (!iter_data->has_hw_macaddr) |
982 | continue; | 982 | continue; |
983 | 983 | ||
984 | ether_addr_copy(common->curbssid, avp->bssid); | 984 | ether_addr_copy(common->curbssid, avp->bssid); |
@@ -1255,6 +1255,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1255 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); | 1255 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); |
1256 | sc->cur_chan->nvifs++; | 1256 | sc->cur_chan->nvifs++; |
1257 | 1257 | ||
1258 | if (vif->type == NL80211_IFTYPE_STATION && ath9k_is_chanctx_enabled()) | ||
1259 | vif->driver_flags |= IEEE80211_VIF_GET_NOA_UPDATE; | ||
1260 | |||
1258 | if (ath9k_uses_beacons(vif->type)) | 1261 | if (ath9k_uses_beacons(vif->type)) |
1259 | ath9k_beacon_assign_slot(sc, vif); | 1262 | ath9k_beacon_assign_slot(sc, vif); |
1260 | 1263 | ||
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index caba54ddad25..c8d35febaf0f 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -34,8 +34,10 @@ | |||
34 | #define AR_CFG_SWRG 0x00000010 | 34 | #define AR_CFG_SWRG 0x00000010 |
35 | #define AR_CFG_AP_ADHOC_INDICATION 0x00000020 | 35 | #define AR_CFG_AP_ADHOC_INDICATION 0x00000020 |
36 | #define AR_CFG_PHOK 0x00000100 | 36 | #define AR_CFG_PHOK 0x00000100 |
37 | #define AR_CFG_CLK_GATE_DIS 0x00000400 | ||
38 | #define AR_CFG_EEBS 0x00000200 | 37 | #define AR_CFG_EEBS 0x00000200 |
38 | #define AR_CFG_CLK_GATE_DIS 0x00000400 | ||
39 | #define AR_CFG_HALT_REQ 0x00000800 | ||
40 | #define AR_CFG_HALT_ACK 0x00001000 | ||
39 | #define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 | 41 | #define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 |
40 | #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 | 42 | #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 |
41 | 43 | ||
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 9111d4ffc1b3..ea1d80f9a50e 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h | |||
@@ -56,6 +56,7 @@ enum carl9170_cmd_oids { | |||
56 | CARL9170_CMD_RX_FILTER = 0x07, | 56 | CARL9170_CMD_RX_FILTER = 0x07, |
57 | CARL9170_CMD_WOL = 0x08, | 57 | CARL9170_CMD_WOL = 0x08, |
58 | CARL9170_CMD_TALLY = 0x09, | 58 | CARL9170_CMD_TALLY = 0x09, |
59 | CARL9170_CMD_WREGB = 0x0a, | ||
59 | 60 | ||
60 | /* CAM */ | 61 | /* CAM */ |
61 | CARL9170_CMD_EKEY = 0x10, | 62 | CARL9170_CMD_EKEY = 0x10, |
@@ -123,6 +124,12 @@ struct carl9170_write_reg { | |||
123 | } regs[0] __packed; | 124 | } regs[0] __packed; |
124 | } __packed; | 125 | } __packed; |
125 | 126 | ||
127 | struct carl9170_write_reg_byte { | ||
128 | __le32 addr; | ||
129 | __le32 count; | ||
130 | u8 val[0]; | ||
131 | } __packed; | ||
132 | |||
126 | #define CARL9170FW_PHY_HT_ENABLE 0x4 | 133 | #define CARL9170FW_PHY_HT_ENABLE 0x4 |
127 | #define CARL9170FW_PHY_HT_DYN2040 0x8 | 134 | #define CARL9170FW_PHY_HT_DYN2040 0x8 |
128 | #define CARL9170FW_PHY_HT_EXT_CHAN_OFF 0x3 | 135 | #define CARL9170FW_PHY_HT_EXT_CHAN_OFF 0x3 |
@@ -226,6 +233,7 @@ struct carl9170_cmd { | |||
226 | struct carl9170_u32_list echo; | 233 | struct carl9170_u32_list echo; |
227 | struct carl9170_reg_list rreg; | 234 | struct carl9170_reg_list rreg; |
228 | struct carl9170_write_reg wreg; | 235 | struct carl9170_write_reg wreg; |
236 | struct carl9170_write_reg_byte wregb; | ||
229 | struct carl9170_rf_init rf_init; | 237 | struct carl9170_rf_init rf_init; |
230 | struct carl9170_psm psm; | 238 | struct carl9170_psm psm; |
231 | struct carl9170_wol_cmd wol; | 239 | struct carl9170_wol_cmd wol; |
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h index 66848d47c88e..0533f79cb998 100644 --- a/drivers/net/wireless/ath/carl9170/fwdesc.h +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h | |||
@@ -81,6 +81,12 @@ enum carl9170fw_feature_list { | |||
81 | /* Firmware will pass BA when BARs are queued */ | 81 | /* Firmware will pass BA when BARs are queued */ |
82 | CARL9170FW_RX_BA_FILTER, | 82 | CARL9170FW_RX_BA_FILTER, |
83 | 83 | ||
84 | /* Firmware has support to write a byte at a time */ | ||
85 | CARL9170FW_HAS_WREGB_CMD, | ||
86 | |||
87 | /* Pattern generator */ | ||
88 | CARL9170FW_PATTERN_GENERATOR, | ||
89 | |||
84 | /* KEEP LAST */ | 90 | /* KEEP LAST */ |
85 | __CARL9170FW_FEATURE_NUM | 91 | __CARL9170FW_FEATURE_NUM |
86 | }; | 92 | }; |
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index 0db874abde50..08e0ae9c5836 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h | |||
@@ -453,9 +453,74 @@ | |||
453 | #define AR9170_MC_REG_BASE 0x1d1000 | 453 | #define AR9170_MC_REG_BASE 0x1d1000 |
454 | 454 | ||
455 | #define AR9170_MC_REG_FLASH_WAIT_STATE (AR9170_MC_REG_BASE + 0x000) | 455 | #define AR9170_MC_REG_FLASH_WAIT_STATE (AR9170_MC_REG_BASE + 0x000) |
456 | #define AR9170_MC_REG_SEEPROM_WP0 (AR9170_MC_REG_BASE + 0x400) | 456 | |
457 | #define AR9170_MC_REG_SEEPROM_WP1 (AR9170_MC_REG_BASE + 0x404) | 457 | #define AR9170_SPI_REG_BASE (AR9170_MC_REG_BASE + 0x200) |
458 | #define AR9170_MC_REG_SEEPROM_WP2 (AR9170_MC_REG_BASE + 0x408) | 458 | #define AR9170_SPI_REG_CONTROL0 (AR9170_SPI_REG_BASE + 0x000) |
459 | #define AR9170_SPI_CONTROL0_BUSY BIT(0) | ||
460 | #define AR9170_SPI_CONTROL0_CMD_GO BIT(1) | ||
461 | #define AR9170_SPI_CONTROL0_PAGE_WR BIT(2) | ||
462 | #define AR9170_SPI_CONTROL0_SEQ_RD BIT(3) | ||
463 | #define AR9170_SPI_CONTROL0_CMD_ABORT BIT(4) | ||
464 | #define AR9170_SPI_CONTROL0_CMD_LEN_S 8 | ||
465 | #define AR9170_SPI_CONTROL0_CMD_LEN 0x00000f00 | ||
466 | #define AR9170_SPI_CONTROL0_RD_LEN_S 12 | ||
467 | #define AR9170_SPI_CONTROL0_RD_LEN 0x00007000 | ||
468 | |||
469 | #define AR9170_SPI_REG_CONTROL1 (AR9170_SPI_REG_BASE + 0x004) | ||
470 | #define AR9170_SPI_CONTROL1_SCK_RATE BIT(0) | ||
471 | #define AR9170_SPI_CONTROL1_DRIVE_SDO BIT(1) | ||
472 | #define AR9170_SPI_CONTROL1_MODE_SEL_S 2 | ||
473 | #define AR9170_SPI_CONTROL1_MODE_SEL 0x000000c0 | ||
474 | #define AR9170_SPI_CONTROL1_WRITE_PROTECT BIT(4) | ||
475 | |||
476 | #define AR9170_SPI_REG_COMMAND_PORT0 (AR9170_SPI_REG_BASE + 0x008) | ||
477 | #define AR9170_SPI_COMMAND_PORT0_CMD0_S 0 | ||
478 | #define AR9170_SPI_COMMAND_PORT0_CMD0 0x000000ff | ||
479 | #define AR9170_SPI_COMMAND_PORT0_CMD1_S 8 | ||
480 | #define AR9170_SPI_COMMAND_PORT0_CMD1 0x0000ff00 | ||
481 | #define AR9170_SPI_COMMAND_PORT0_CMD2_S 16 | ||
482 | #define AR9170_SPI_COMMAND_PORT0_CMD2 0x00ff0000 | ||
483 | #define AR9170_SPI_COMMAND_PORT0_CMD3_S 24 | ||
484 | #define AR9170_SPI_COMMAND_PORT0_CMD3 0xff000000 | ||
485 | |||
486 | #define AR9170_SPI_REG_COMMAND_PORT1 (AR9170_SPI_REG_BASE + 0x00C) | ||
487 | #define AR9170_SPI_COMMAND_PORT1_CMD4_S 0 | ||
488 | #define AR9170_SPI_COMMAND_PORT1_CMD4 0x000000ff | ||
489 | #define AR9170_SPI_COMMAND_PORT1_CMD5_S 8 | ||
490 | #define AR9170_SPI_COMMAND_PORT1_CMD5 0x0000ff00 | ||
491 | #define AR9170_SPI_COMMAND_PORT1_CMD6_S 16 | ||
492 | #define AR9170_SPI_COMMAND_PORT1_CMD6 0x00ff0000 | ||
493 | #define AR9170_SPI_COMMAND_PORT1_CMD7_S 24 | ||
494 | #define AR9170_SPI_COMMAND_PORT1_CMD7 0xff000000 | ||
495 | |||
496 | #define AR9170_SPI_REG_DATA_PORT (AR9170_SPI_REG_BASE + 0x010) | ||
497 | #define AR9170_SPI_REG_PAGE_WRITE_LEN (AR9170_SPI_REG_BASE + 0x014) | ||
498 | |||
499 | #define AR9170_EEPROM_REG_BASE (AR9170_MC_REG_BASE + 0x400) | ||
500 | #define AR9170_EEPROM_REG_WP_MAGIC1 (AR9170_EEPROM_REG_BASE + 0x000) | ||
501 | #define AR9170_EEPROM_WP_MAGIC1 0x12345678 | ||
502 | |||
503 | #define AR9170_EEPROM_REG_WP_MAGIC2 (AR9170_EEPROM_REG_BASE + 0x004) | ||
504 | #define AR9170_EEPROM_WP_MAGIC2 0x55aa00ff | ||
505 | |||
506 | #define AR9170_EEPROM_REG_WP_MAGIC3 (AR9170_EEPROM_REG_BASE + 0x008) | ||
507 | #define AR9170_EEPROM_WP_MAGIC3 0x13579ace | ||
508 | |||
509 | #define AR9170_EEPROM_REG_CLOCK_DIV (AR9170_EEPROM_REG_BASE + 0x00C) | ||
510 | #define AR9170_EEPROM_CLOCK_DIV_FAC_S 0 | ||
511 | #define AR9170_EEPROM_CLOCK_DIV_FAC 0x000001ff | ||
512 | #define AR9170_EEPROM_CLOCK_DIV_FAC_39KHZ 0xff | ||
513 | #define AR9170_EEPROM_CLOCK_DIV_FAC_78KHZ 0x7f | ||
514 | #define AR9170_EEPROM_CLOCK_DIV_FAC_312KHZ 0x1f | ||
515 | #define AR9170_EEPROM_CLOCK_DIV_FAC_10MHZ 0x0 | ||
516 | #define AR9170_EEPROM_CLOCK_DIV_SOFT_RST BIT(9) | ||
517 | |||
518 | #define AR9170_EEPROM_REG_MODE (AR9170_EEPROM_REG_BASE + 0x010) | ||
519 | #define AR9170_EEPROM_MODE_EEPROM_SIZE_16K_PLUS BIT(31) | ||
520 | |||
521 | #define AR9170_EEPROM_REG_WRITE_PROTECT (AR9170_EEPROM_REG_BASE + 0x014) | ||
522 | #define AR9170_EEPROM_WRITE_PROTECT_WP_STATUS BIT(0) | ||
523 | #define AR9170_EEPROM_WRITE_PROTECT_WP_SET BIT(8) | ||
459 | 524 | ||
460 | /* Interrupt Controller */ | 525 | /* Interrupt Controller */ |
461 | #define AR9170_MAX_INT_SRC 9 | 526 | #define AR9170_MAX_INT_SRC 9 |
@@ -589,11 +654,13 @@ | |||
589 | #define AR9170_USB_REG_EP10_MAP (AR9170_USB_REG_BASE + 0x039) | 654 | #define AR9170_USB_REG_EP10_MAP (AR9170_USB_REG_BASE + 0x039) |
590 | 655 | ||
591 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x03f) | 656 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x03f) |
657 | #define AR9170_USB_EP_IN_STALL 0x8 | ||
592 | #define AR9170_USB_EP_IN_TOGGLE 0x10 | 658 | #define AR9170_USB_EP_IN_TOGGLE 0x10 |
593 | 659 | ||
594 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x03e) | 660 | #define AR9170_USB_REG_EP_IN_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x03e) |
595 | 661 | ||
596 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x05f) | 662 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH (AR9170_USB_REG_BASE + 0x05f) |
663 | #define AR9170_USB_EP_OUT_STALL 0x8 | ||
597 | #define AR9170_USB_EP_OUT_TOGGLE 0x10 | 664 | #define AR9170_USB_EP_OUT_TOGGLE 0x10 |
598 | 665 | ||
599 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x05e) | 666 | #define AR9170_USB_REG_EP_OUT_MAX_SIZE_LOW (AR9170_USB_REG_BASE + 0x05e) |
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index 2282847d4bb8..a0410fe8c03a 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __CARL9170_SHARED_VERSION_H | 1 | #ifndef __CARL9170_SHARED_VERSION_H |
2 | #define __CARL9170_SHARED_VERSION_H | 2 | #define __CARL9170_SHARED_VERSION_H |
3 | #define CARL9170FW_VERSION_YEAR 12 | 3 | #define CARL9170FW_VERSION_YEAR 16 |
4 | #define CARL9170FW_VERSION_MONTH 12 | 4 | #define CARL9170FW_VERSION_MONTH 2 |
5 | #define CARL9170FW_VERSION_DAY 15 | 5 | #define CARL9170FW_VERSION_DAY 15 |
6 | #define CARL9170FW_VERSION_GIT "1.9.7" | 6 | #define CARL9170FW_VERSION_GIT "1.9.9" |
7 | #endif /* __CARL9170_SHARED_VERSION_H */ | 7 | #endif /* __CARL9170_SHARED_VERSION_H */ |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 1f231cd08138..11f1bb8dfebe 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-2015 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 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 |
@@ -540,7 +540,18 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, | |||
540 | 540 | ||
541 | wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code); | 541 | wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code); |
542 | 542 | ||
543 | rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); | 543 | if (!(test_bit(wil_status_fwconnecting, wil->status) || |
544 | test_bit(wil_status_fwconnected, wil->status))) { | ||
545 | wil_err(wil, "%s: Disconnect was called while disconnected\n", | ||
546 | __func__); | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, | ||
551 | WMI_DISCONNECT_EVENTID, NULL, 0, | ||
552 | WIL6210_DISCONNECT_TO_MS); | ||
553 | if (rc) | ||
554 | wil_err(wil, "%s: disconnect error %d\n", __func__, rc); | ||
544 | 555 | ||
545 | return rc; | 556 | return rc; |
546 | } | 557 | } |
@@ -701,6 +712,79 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, | |||
701 | return rc; | 712 | return rc; |
702 | } | 713 | } |
703 | 714 | ||
715 | /** | ||
716 | * find a specific IE in a list of IEs | ||
717 | * return a pointer to the beginning of IE in the list | ||
718 | * or NULL if not found | ||
719 | */ | ||
720 | static const u8 *_wil_cfg80211_find_ie(const u8 *ies, u16 ies_len, const u8 *ie, | ||
721 | u16 ie_len) | ||
722 | { | ||
723 | struct ieee80211_vendor_ie *vie; | ||
724 | u32 oui; | ||
725 | |||
726 | /* IE tag at offset 0, length at offset 1 */ | ||
727 | if (ie_len < 2 || 2 + ie[1] > ie_len) | ||
728 | return NULL; | ||
729 | |||
730 | if (ie[0] != WLAN_EID_VENDOR_SPECIFIC) | ||
731 | return cfg80211_find_ie(ie[0], ies, ies_len); | ||
732 | |||
733 | /* make sure there is room for 3 bytes OUI + 1 byte OUI type */ | ||
734 | if (ie[1] < 4) | ||
735 | return NULL; | ||
736 | vie = (struct ieee80211_vendor_ie *)ie; | ||
737 | oui = vie->oui[0] << 16 | vie->oui[1] << 8 | vie->oui[2]; | ||
738 | return cfg80211_find_vendor_ie(oui, vie->oui_type, ies, | ||
739 | ies_len); | ||
740 | } | ||
741 | |||
742 | /** | ||
743 | * merge the IEs in two lists into a single list. | ||
744 | * do not include IEs from the second list which exist in the first list. | ||
745 | * add only vendor specific IEs from second list to keep | ||
746 | * the merged list sorted (since vendor-specific IE has the | ||
747 | * highest tag number) | ||
748 | * caller must free the allocated memory for merged IEs | ||
749 | */ | ||
750 | static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len, | ||
751 | const u8 *ies2, u16 ies2_len, | ||
752 | u8 **merged_ies, u16 *merged_len) | ||
753 | { | ||
754 | u8 *buf, *dpos; | ||
755 | const u8 *spos; | ||
756 | |||
757 | if (ies1_len == 0 && ies2_len == 0) { | ||
758 | *merged_ies = NULL; | ||
759 | *merged_len = 0; | ||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL); | ||
764 | if (!buf) | ||
765 | return -ENOMEM; | ||
766 | memcpy(buf, ies1, ies1_len); | ||
767 | dpos = buf + ies1_len; | ||
768 | spos = ies2; | ||
769 | while (spos + 1 < ies2 + ies2_len) { | ||
770 | /* IE tag at offset 0, length at offset 1 */ | ||
771 | u16 ielen = 2 + spos[1]; | ||
772 | |||
773 | if (spos + ielen > ies2 + ies2_len) | ||
774 | break; | ||
775 | if (spos[0] == WLAN_EID_VENDOR_SPECIFIC && | ||
776 | !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) { | ||
777 | memcpy(dpos, spos, ielen); | ||
778 | dpos += ielen; | ||
779 | } | ||
780 | spos += ielen; | ||
781 | } | ||
782 | |||
783 | *merged_ies = buf; | ||
784 | *merged_len = dpos - buf; | ||
785 | return 0; | ||
786 | } | ||
787 | |||
704 | static void wil_print_bcon_data(struct cfg80211_beacon_data *b) | 788 | static void wil_print_bcon_data(struct cfg80211_beacon_data *b) |
705 | { | 789 | { |
706 | print_hex_dump_bytes("head ", DUMP_PREFIX_OFFSET, | 790 | print_hex_dump_bytes("head ", DUMP_PREFIX_OFFSET, |
@@ -717,49 +801,49 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) | |||
717 | b->assocresp_ies, b->assocresp_ies_len); | 801 | b->assocresp_ies, b->assocresp_ies_len); |
718 | } | 802 | } |
719 | 803 | ||
720 | static int wil_fix_bcon(struct wil6210_priv *wil, | ||
721 | struct cfg80211_beacon_data *bcon) | ||
722 | { | ||
723 | struct ieee80211_mgmt *f = (struct ieee80211_mgmt *)bcon->probe_resp; | ||
724 | size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | ||
725 | |||
726 | if (bcon->probe_resp_len <= hlen) | ||
727 | return 0; | ||
728 | |||
729 | /* always use IE's from full probe frame, they has more info | ||
730 | * notable RSN | ||
731 | */ | ||
732 | bcon->proberesp_ies = f->u.probe_resp.variable; | ||
733 | bcon->proberesp_ies_len = bcon->probe_resp_len - hlen; | ||
734 | if (!bcon->assocresp_ies) { | ||
735 | bcon->assocresp_ies = bcon->proberesp_ies; | ||
736 | bcon->assocresp_ies_len = bcon->proberesp_ies_len; | ||
737 | } | ||
738 | |||
739 | return 1; | ||
740 | } | ||
741 | |||
742 | /* internal functions for device reset and starting AP */ | 804 | /* internal functions for device reset and starting AP */ |
743 | static int _wil_cfg80211_set_ies(struct wiphy *wiphy, | 805 | static int _wil_cfg80211_set_ies(struct wiphy *wiphy, |
744 | struct cfg80211_beacon_data *bcon) | 806 | struct cfg80211_beacon_data *bcon) |
745 | { | 807 | { |
746 | int rc; | 808 | int rc; |
747 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 809 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
810 | u16 len = 0, proberesp_len = 0; | ||
811 | u8 *ies = NULL, *proberesp = NULL; | ||
812 | |||
813 | if (bcon->probe_resp) { | ||
814 | struct ieee80211_mgmt *f = | ||
815 | (struct ieee80211_mgmt *)bcon->probe_resp; | ||
816 | size_t hlen = offsetof(struct ieee80211_mgmt, | ||
817 | u.probe_resp.variable); | ||
818 | proberesp = f->u.probe_resp.variable; | ||
819 | proberesp_len = bcon->probe_resp_len - hlen; | ||
820 | } | ||
821 | rc = _wil_cfg80211_merge_extra_ies(proberesp, | ||
822 | proberesp_len, | ||
823 | bcon->proberesp_ies, | ||
824 | bcon->proberesp_ies_len, | ||
825 | &ies, &len); | ||
748 | 826 | ||
749 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, | ||
750 | bcon->proberesp_ies); | ||
751 | if (rc) | 827 | if (rc) |
752 | return rc; | 828 | goto out; |
753 | 829 | ||
754 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, | 830 | rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies); |
755 | bcon->assocresp_ies); | 831 | if (rc) |
832 | goto out; | ||
833 | |||
834 | if (bcon->assocresp_ies) | ||
835 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, | ||
836 | bcon->assocresp_ies_len, bcon->assocresp_ies); | ||
837 | else | ||
838 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies); | ||
756 | #if 0 /* to use beacon IE's, remove this #if 0 */ | 839 | #if 0 /* to use beacon IE's, remove this #if 0 */ |
757 | if (rc) | 840 | if (rc) |
758 | return rc; | 841 | goto out; |
759 | 842 | ||
760 | rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail); | 843 | rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail); |
761 | #endif | 844 | #endif |
762 | 845 | out: | |
846 | kfree(ies); | ||
763 | return rc; | 847 | return rc; |
764 | } | 848 | } |
765 | 849 | ||
@@ -828,14 +912,9 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, | |||
828 | wil_dbg_misc(wil, "%s()\n", __func__); | 912 | wil_dbg_misc(wil, "%s()\n", __func__); |
829 | wil_print_bcon_data(bcon); | 913 | wil_print_bcon_data(bcon); |
830 | 914 | ||
831 | if (wil_fix_bcon(wil, bcon)) { | 915 | if (bcon->tail && |
832 | wil_dbg_misc(wil, "Fixed bcon\n"); | 916 | cfg80211_find_ie(WLAN_EID_RSN, bcon->tail, |
833 | wil_print_bcon_data(bcon); | 917 | bcon->tail_len)) |
834 | } | ||
835 | |||
836 | if (bcon->proberesp_ies && | ||
837 | cfg80211_find_ie(WLAN_EID_RSN, bcon->proberesp_ies, | ||
838 | bcon->proberesp_ies_len)) | ||
839 | privacy = 1; | 918 | privacy = 1; |
840 | 919 | ||
841 | /* in case privacy has changed, need to restart the AP */ | 920 | /* in case privacy has changed, need to restart the AP */ |
@@ -910,11 +989,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
910 | wil_print_bcon_data(bcon); | 989 | wil_print_bcon_data(bcon); |
911 | wil_print_crypto(wil, crypto); | 990 | wil_print_crypto(wil, crypto); |
912 | 991 | ||
913 | if (wil_fix_bcon(wil, bcon)) { | ||
914 | wil_dbg_misc(wil, "Fixed bcon\n"); | ||
915 | wil_print_bcon_data(bcon); | ||
916 | } | ||
917 | |||
918 | rc = _wil_cfg80211_start_ap(wiphy, ndev, | 992 | rc = _wil_cfg80211_start_ap(wiphy, ndev, |
919 | info->ssid, info->ssid_len, info->privacy, | 993 | info->ssid, info->ssid_len, info->privacy, |
920 | info->beacon_interval, channel->hw_value, | 994 | info->beacon_interval, channel->hw_value, |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index a1d10b85989f..3bbe73b6d05a 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 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 |
@@ -68,13 +68,13 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, | |||
68 | seq_puts(s, "???\n"); | 68 | seq_puts(s, "???\n"); |
69 | } | 69 | } |
70 | 70 | ||
71 | if (vring->va && (vring->size < 1025)) { | 71 | if (vring->va && (vring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { |
72 | uint i; | 72 | uint i; |
73 | 73 | ||
74 | for (i = 0; i < vring->size; i++) { | 74 | for (i = 0; i < vring->size; i++) { |
75 | volatile struct vring_tx_desc *d = &vring->va[i].tx; | 75 | volatile struct vring_tx_desc *d = &vring->va[i].tx; |
76 | 76 | ||
77 | if ((i % 64) == 0 && (i != 0)) | 77 | if ((i % 128) == 0 && (i != 0)) |
78 | seq_puts(s, "\n"); | 78 | seq_puts(s, "\n"); |
79 | seq_printf(s, "%c", (d->dma.status & BIT(0)) ? | 79 | seq_printf(s, "%c", (d->dma.status & BIT(0)) ? |
80 | _s : (vring->ctx[i].skb ? _h : 'h')); | 80 | _s : (vring->ctx[i].skb ? _h : 'h')); |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index b39f0bfc591e..78ba6e04c944 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-2015 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 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 |
@@ -23,9 +23,6 @@ | |||
23 | #include "wmi.h" | 23 | #include "wmi.h" |
24 | #include "boot_loader.h" | 24 | #include "boot_loader.h" |
25 | 25 | ||
26 | #define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000 | ||
27 | #define WAIT_FOR_DISCONNECT_INTERVAL_MS 10 | ||
28 | |||
29 | bool debug_fw; /* = false; */ | 26 | bool debug_fw; /* = false; */ |
30 | module_param(debug_fw, bool, S_IRUGO); | 27 | module_param(debug_fw, bool, S_IRUGO); |
31 | MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); | 28 | MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); |
@@ -155,7 +152,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
155 | 152 | ||
156 | if (sta->status != wil_sta_unused) { | 153 | if (sta->status != wil_sta_unused) { |
157 | if (!from_event) | 154 | if (!from_event) |
158 | wmi_disconnect_sta(wil, sta->addr, reason_code); | 155 | wmi_disconnect_sta(wil, sta->addr, reason_code, true); |
159 | 156 | ||
160 | switch (wdev->iftype) { | 157 | switch (wdev->iftype) { |
161 | case NL80211_IFTYPE_AP: | 158 | case NL80211_IFTYPE_AP: |
@@ -195,8 +192,8 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
195 | struct wireless_dev *wdev = wil->wdev; | 192 | struct wireless_dev *wdev = wil->wdev; |
196 | 193 | ||
197 | might_sleep(); | 194 | might_sleep(); |
198 | wil_dbg_misc(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, | 195 | wil_info(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, |
199 | reason_code, from_event ? "+" : "-"); | 196 | reason_code, from_event ? "+" : "-"); |
200 | 197 | ||
201 | /* Cases are: | 198 | /* Cases are: |
202 | * - disconnect single STA, still connected | 199 | * - disconnect single STA, still connected |
@@ -258,13 +255,16 @@ static void wil_disconnect_worker(struct work_struct *work) | |||
258 | static void wil_connect_timer_fn(ulong x) | 255 | static void wil_connect_timer_fn(ulong x) |
259 | { | 256 | { |
260 | struct wil6210_priv *wil = (void *)x; | 257 | struct wil6210_priv *wil = (void *)x; |
258 | bool q; | ||
261 | 259 | ||
262 | wil_dbg_misc(wil, "Connect timeout\n"); | 260 | wil_err(wil, "Connect timeout detected, disconnect station\n"); |
263 | 261 | ||
264 | /* reschedule to thread context - disconnect won't | 262 | /* reschedule to thread context - disconnect won't |
265 | * run from atomic context | 263 | * run from atomic context. |
264 | * queue on wmi_wq to prevent race with connect event. | ||
266 | */ | 265 | */ |
267 | schedule_work(&wil->disconnect_worker); | 266 | q = queue_work(wil->wmi_wq, &wil->disconnect_worker); |
267 | wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q); | ||
268 | } | 268 | } |
269 | 269 | ||
270 | static void wil_scan_timer_fn(ulong x) | 270 | static void wil_scan_timer_fn(ulong x) |
@@ -369,6 +369,32 @@ static int wil_find_free_vring(struct wil6210_priv *wil) | |||
369 | return -EINVAL; | 369 | return -EINVAL; |
370 | } | 370 | } |
371 | 371 | ||
372 | int wil_tx_init(struct wil6210_priv *wil, int cid) | ||
373 | { | ||
374 | int rc = -EINVAL, ringid; | ||
375 | |||
376 | if (cid < 0) { | ||
377 | wil_err(wil, "No connection pending\n"); | ||
378 | goto out; | ||
379 | } | ||
380 | ringid = wil_find_free_vring(wil); | ||
381 | if (ringid < 0) { | ||
382 | wil_err(wil, "No free vring found\n"); | ||
383 | goto out; | ||
384 | } | ||
385 | |||
386 | wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", | ||
387 | cid, ringid); | ||
388 | |||
389 | rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); | ||
390 | if (rc) | ||
391 | wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n", | ||
392 | cid, ringid); | ||
393 | |||
394 | out: | ||
395 | return rc; | ||
396 | } | ||
397 | |||
372 | int wil_bcast_init(struct wil6210_priv *wil) | 398 | int wil_bcast_init(struct wil6210_priv *wil) |
373 | { | 399 | { |
374 | int ri = wil->bcast_vring, rc; | 400 | int ri = wil->bcast_vring, rc; |
@@ -399,41 +425,6 @@ void wil_bcast_fini(struct wil6210_priv *wil) | |||
399 | wil_vring_fini_tx(wil, ri); | 425 | wil_vring_fini_tx(wil, ri); |
400 | } | 426 | } |
401 | 427 | ||
402 | static void wil_connect_worker(struct work_struct *work) | ||
403 | { | ||
404 | int rc, cid, ringid; | ||
405 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
406 | connect_worker); | ||
407 | struct net_device *ndev = wil_to_ndev(wil); | ||
408 | |||
409 | mutex_lock(&wil->mutex); | ||
410 | |||
411 | cid = wil->pending_connect_cid; | ||
412 | if (cid < 0) { | ||
413 | wil_err(wil, "No connection pending\n"); | ||
414 | goto out; | ||
415 | } | ||
416 | ringid = wil_find_free_vring(wil); | ||
417 | if (ringid < 0) { | ||
418 | wil_err(wil, "No free vring found\n"); | ||
419 | goto out; | ||
420 | } | ||
421 | |||
422 | wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", | ||
423 | cid, ringid); | ||
424 | |||
425 | rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); | ||
426 | wil->pending_connect_cid = -1; | ||
427 | if (rc == 0) { | ||
428 | wil->sta[cid].status = wil_sta_connected; | ||
429 | netif_tx_wake_all_queues(ndev); | ||
430 | } else { | ||
431 | wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true); | ||
432 | } | ||
433 | out: | ||
434 | mutex_unlock(&wil->mutex); | ||
435 | } | ||
436 | |||
437 | int wil_priv_init(struct wil6210_priv *wil) | 428 | int wil_priv_init(struct wil6210_priv *wil) |
438 | { | 429 | { |
439 | uint i; | 430 | uint i; |
@@ -444,6 +435,9 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
444 | for (i = 0; i < WIL6210_MAX_CID; i++) | 435 | for (i = 0; i < WIL6210_MAX_CID; i++) |
445 | spin_lock_init(&wil->sta[i].tid_rx_lock); | 436 | spin_lock_init(&wil->sta[i].tid_rx_lock); |
446 | 437 | ||
438 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) | ||
439 | spin_lock_init(&wil->vring_tx_data[i].lock); | ||
440 | |||
447 | mutex_init(&wil->mutex); | 441 | mutex_init(&wil->mutex); |
448 | mutex_init(&wil->wmi_mutex); | 442 | mutex_init(&wil->wmi_mutex); |
449 | mutex_init(&wil->back_rx_mutex); | 443 | mutex_init(&wil->back_rx_mutex); |
@@ -453,12 +447,10 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
453 | init_completion(&wil->wmi_ready); | 447 | init_completion(&wil->wmi_ready); |
454 | init_completion(&wil->wmi_call); | 448 | init_completion(&wil->wmi_call); |
455 | 449 | ||
456 | wil->pending_connect_cid = -1; | ||
457 | wil->bcast_vring = -1; | 450 | wil->bcast_vring = -1; |
458 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); | 451 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); |
459 | setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); | 452 | setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); |
460 | 453 | ||
461 | INIT_WORK(&wil->connect_worker, wil_connect_worker); | ||
462 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | 454 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); |
463 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | 455 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); |
464 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); | 456 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); |
@@ -844,7 +836,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
844 | } | 836 | } |
845 | 837 | ||
846 | /* init after reset */ | 838 | /* init after reset */ |
847 | wil->pending_connect_cid = -1; | ||
848 | wil->ap_isolate = 0; | 839 | wil->ap_isolate = 0; |
849 | reinit_completion(&wil->wmi_ready); | 840 | reinit_completion(&wil->wmi_ready); |
850 | reinit_completion(&wil->wmi_call); | 841 | reinit_completion(&wil->wmi_call); |
@@ -948,8 +939,7 @@ int wil_up(struct wil6210_priv *wil) | |||
948 | 939 | ||
949 | int __wil_down(struct wil6210_priv *wil) | 940 | int __wil_down(struct wil6210_priv *wil) |
950 | { | 941 | { |
951 | int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS / | 942 | int rc; |
952 | WAIT_FOR_DISCONNECT_INTERVAL_MS; | ||
953 | 943 | ||
954 | WARN_ON(!mutex_is_locked(&wil->mutex)); | 944 | WARN_ON(!mutex_is_locked(&wil->mutex)); |
955 | 945 | ||
@@ -973,22 +963,16 @@ int __wil_down(struct wil6210_priv *wil) | |||
973 | } | 963 | } |
974 | 964 | ||
975 | if (test_bit(wil_status_fwconnected, wil->status) || | 965 | if (test_bit(wil_status_fwconnected, wil->status) || |
976 | test_bit(wil_status_fwconnecting, wil->status)) | 966 | test_bit(wil_status_fwconnecting, wil->status)) { |
977 | wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); | ||
978 | 967 | ||
979 | /* make sure wil is idle (not connected) */ | 968 | mutex_unlock(&wil->mutex); |
980 | mutex_unlock(&wil->mutex); | 969 | rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, |
981 | while (iter--) { | 970 | WMI_DISCONNECT_EVENTID, NULL, 0, |
982 | int idle = !test_bit(wil_status_fwconnected, wil->status) && | 971 | WIL6210_DISCONNECT_TO_MS); |
983 | !test_bit(wil_status_fwconnecting, wil->status); | 972 | mutex_lock(&wil->mutex); |
984 | if (idle) | 973 | if (rc) |
985 | break; | 974 | wil_err(wil, "timeout waiting for disconnect\n"); |
986 | msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS); | ||
987 | } | 975 | } |
988 | mutex_lock(&wil->mutex); | ||
989 | |||
990 | if (iter < 0) | ||
991 | wil_err(wil, "timeout waiting for idle FW/HW\n"); | ||
992 | 976 | ||
993 | wil_reset(wil, false); | 977 | wil_reset(wil, false); |
994 | 978 | ||
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 56aaa2d4fb0e..ecc3c1bdae4b 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-2015 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 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 |
@@ -108,8 +108,9 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) | |||
108 | /* always process ALL Tx complete, regardless budget - it is fast */ | 108 | /* always process ALL Tx complete, regardless budget - it is fast */ |
109 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 109 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
110 | struct vring *vring = &wil->vring_tx[i]; | 110 | struct vring *vring = &wil->vring_tx[i]; |
111 | struct vring_tx_data *txdata = &wil->vring_tx_data[i]; | ||
111 | 112 | ||
112 | if (!vring->va) | 113 | if (!vring->va || !txdata->enabled) |
113 | continue; | 114 | continue; |
114 | 115 | ||
115 | tx_done += wil_tx_complete(wil, i); | 116 | tx_done += wil_tx_complete(wil, i); |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 7887e6cfd817..6af20903cf89 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 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 |
@@ -717,6 +717,21 @@ void wil_rx_fini(struct wil6210_priv *wil) | |||
717 | wil_vring_free(wil, vring, 0); | 717 | wil_vring_free(wil, vring, 0); |
718 | } | 718 | } |
719 | 719 | ||
720 | static inline void wil_tx_data_init(struct vring_tx_data *txdata) | ||
721 | { | ||
722 | spin_lock_bh(&txdata->lock); | ||
723 | txdata->dot1x_open = 0; | ||
724 | txdata->enabled = 0; | ||
725 | txdata->idle = 0; | ||
726 | txdata->last_idle = 0; | ||
727 | txdata->begin = 0; | ||
728 | txdata->agg_wsize = 0; | ||
729 | txdata->agg_timeout = 0; | ||
730 | txdata->agg_amsdu = 0; | ||
731 | txdata->addba_in_progress = false; | ||
732 | spin_unlock_bh(&txdata->lock); | ||
733 | } | ||
734 | |||
720 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | 735 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, |
721 | int cid, int tid) | 736 | int cid, int tid) |
722 | { | 737 | { |
@@ -758,8 +773,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
758 | goto out; | 773 | goto out; |
759 | } | 774 | } |
760 | 775 | ||
761 | memset(txdata, 0, sizeof(*txdata)); | 776 | wil_tx_data_init(txdata); |
762 | spin_lock_init(&txdata->lock); | ||
763 | vring->size = size; | 777 | vring->size = size; |
764 | rc = wil_vring_alloc(wil, vring); | 778 | rc = wil_vring_alloc(wil, vring); |
765 | if (rc) | 779 | if (rc) |
@@ -791,9 +805,14 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
791 | 805 | ||
792 | return 0; | 806 | return 0; |
793 | out_free: | 807 | out_free: |
808 | spin_lock_bh(&txdata->lock); | ||
794 | txdata->dot1x_open = false; | 809 | txdata->dot1x_open = false; |
795 | txdata->enabled = 0; | 810 | txdata->enabled = 0; |
811 | spin_unlock_bh(&txdata->lock); | ||
796 | wil_vring_free(wil, vring, 1); | 812 | wil_vring_free(wil, vring, 1); |
813 | wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; | ||
814 | wil->vring2cid_tid[id][1] = 0; | ||
815 | |||
797 | out: | 816 | out: |
798 | 817 | ||
799 | return rc; | 818 | return rc; |
@@ -831,8 +850,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) | |||
831 | goto out; | 850 | goto out; |
832 | } | 851 | } |
833 | 852 | ||
834 | memset(txdata, 0, sizeof(*txdata)); | 853 | wil_tx_data_init(txdata); |
835 | spin_lock_init(&txdata->lock); | ||
836 | vring->size = size; | 854 | vring->size = size; |
837 | rc = wil_vring_alloc(wil, vring); | 855 | rc = wil_vring_alloc(wil, vring); |
838 | if (rc) | 856 | if (rc) |
@@ -862,8 +880,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) | |||
862 | 880 | ||
863 | return 0; | 881 | return 0; |
864 | out_free: | 882 | out_free: |
883 | spin_lock_bh(&txdata->lock); | ||
865 | txdata->enabled = 0; | 884 | txdata->enabled = 0; |
866 | txdata->dot1x_open = false; | 885 | txdata->dot1x_open = false; |
886 | spin_unlock_bh(&txdata->lock); | ||
867 | wil_vring_free(wil, vring, 1); | 887 | wil_vring_free(wil, vring, 1); |
868 | out: | 888 | out: |
869 | 889 | ||
@@ -891,7 +911,6 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | |||
891 | napi_synchronize(&wil->napi_tx); | 911 | napi_synchronize(&wil->napi_tx); |
892 | 912 | ||
893 | wil_vring_free(wil, vring, 1); | 913 | wil_vring_free(wil, vring, 1); |
894 | memset(txdata, 0, sizeof(*txdata)); | ||
895 | } | 914 | } |
896 | 915 | ||
897 | static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, | 916 | static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, |
@@ -911,10 +930,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, | |||
911 | continue; | 930 | continue; |
912 | if (wil->vring2cid_tid[i][0] == cid) { | 931 | if (wil->vring2cid_tid[i][0] == cid) { |
913 | struct vring *v = &wil->vring_tx[i]; | 932 | struct vring *v = &wil->vring_tx[i]; |
933 | struct vring_tx_data *txdata = &wil->vring_tx_data[i]; | ||
914 | 934 | ||
915 | wil_dbg_txrx(wil, "%s(%pM) -> [%d]\n", | 935 | wil_dbg_txrx(wil, "%s(%pM) -> [%d]\n", |
916 | __func__, eth->h_dest, i); | 936 | __func__, eth->h_dest, i); |
917 | if (v->va) { | 937 | if (v->va && txdata->enabled) { |
918 | return v; | 938 | return v; |
919 | } else { | 939 | } else { |
920 | wil_dbg_txrx(wil, "vring[%d] not valid\n", i); | 940 | wil_dbg_txrx(wil, "vring[%d] not valid\n", i); |
@@ -935,6 +955,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | |||
935 | struct vring *v; | 955 | struct vring *v; |
936 | int i; | 956 | int i; |
937 | u8 cid; | 957 | u8 cid; |
958 | struct vring_tx_data *txdata; | ||
938 | 959 | ||
939 | /* In the STA mode, it is expected to have only 1 VRING | 960 | /* In the STA mode, it is expected to have only 1 VRING |
940 | * for the AP we connected to. | 961 | * for the AP we connected to. |
@@ -942,7 +963,8 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | |||
942 | */ | 963 | */ |
943 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 964 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
944 | v = &wil->vring_tx[i]; | 965 | v = &wil->vring_tx[i]; |
945 | if (!v->va) | 966 | txdata = &wil->vring_tx_data[i]; |
967 | if (!v->va || !txdata->enabled) | ||
946 | continue; | 968 | continue; |
947 | 969 | ||
948 | cid = wil->vring2cid_tid[i][0]; | 970 | cid = wil->vring2cid_tid[i][0]; |
@@ -978,12 +1000,14 @@ static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, | |||
978 | struct sk_buff *skb) | 1000 | struct sk_buff *skb) |
979 | { | 1001 | { |
980 | struct vring *v; | 1002 | struct vring *v; |
1003 | struct vring_tx_data *txdata; | ||
981 | int i = wil->bcast_vring; | 1004 | int i = wil->bcast_vring; |
982 | 1005 | ||
983 | if (i < 0) | 1006 | if (i < 0) |
984 | return NULL; | 1007 | return NULL; |
985 | v = &wil->vring_tx[i]; | 1008 | v = &wil->vring_tx[i]; |
986 | if (!v->va) | 1009 | txdata = &wil->vring_tx_data[i]; |
1010 | if (!v->va || !txdata->enabled) | ||
987 | return NULL; | 1011 | return NULL; |
988 | if (!wil->vring_tx_data[i].dot1x_open && | 1012 | if (!wil->vring_tx_data[i].dot1x_open && |
989 | (skb->protocol != cpu_to_be16(ETH_P_PAE))) | 1013 | (skb->protocol != cpu_to_be16(ETH_P_PAE))) |
@@ -1010,11 +1034,13 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, | |||
1010 | u8 cid; | 1034 | u8 cid; |
1011 | struct ethhdr *eth = (void *)skb->data; | 1035 | struct ethhdr *eth = (void *)skb->data; |
1012 | char *src = eth->h_source; | 1036 | char *src = eth->h_source; |
1037 | struct vring_tx_data *txdata; | ||
1013 | 1038 | ||
1014 | /* find 1-st vring eligible for data */ | 1039 | /* find 1-st vring eligible for data */ |
1015 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 1040 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
1016 | v = &wil->vring_tx[i]; | 1041 | v = &wil->vring_tx[i]; |
1017 | if (!v->va) | 1042 | txdata = &wil->vring_tx_data[i]; |
1043 | if (!v->va || !txdata->enabled) | ||
1018 | continue; | 1044 | continue; |
1019 | 1045 | ||
1020 | cid = wil->vring2cid_tid[i][0]; | 1046 | cid = wil->vring2cid_tid[i][0]; |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 235e205ce2bc..8427d68b6fa8 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-2015 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 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 |
@@ -51,7 +51,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
51 | 51 | ||
52 | #define WIL_TX_Q_LEN_DEFAULT (4000) | 52 | #define WIL_TX_Q_LEN_DEFAULT (4000) |
53 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) | 53 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) |
54 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (10) | 54 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (12) |
55 | #define WIL_BCAST_RING_SIZE_ORDER_DEFAULT (7) | 55 | #define WIL_BCAST_RING_SIZE_ORDER_DEFAULT (7) |
56 | #define WIL_BCAST_MCS0_LIMIT (1024) /* limit for MCS0 frame size */ | 56 | #define WIL_BCAST_MCS0_LIMIT (1024) /* limit for MCS0 frame size */ |
57 | /* limit ring size in range [32..32k] */ | 57 | /* limit ring size in range [32..32k] */ |
@@ -92,6 +92,7 @@ static inline u32 wil_mtu2macbuf(u32 mtu) | |||
92 | #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ | 92 | #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ |
93 | #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) | 93 | #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) |
94 | #define WIL6210_SCAN_TO msecs_to_jiffies(10000) | 94 | #define WIL6210_SCAN_TO msecs_to_jiffies(10000) |
95 | #define WIL6210_DISCONNECT_TO_MS (2000) | ||
95 | #define WIL6210_RX_HIGH_TRSH_INIT (0) | 96 | #define WIL6210_RX_HIGH_TRSH_INIT (0) |
96 | #define WIL6210_RX_HIGH_TRSH_DEFAULT \ | 97 | #define WIL6210_RX_HIGH_TRSH_DEFAULT \ |
97 | (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) | 98 | (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) |
@@ -581,12 +582,10 @@ struct wil6210_priv { | |||
581 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | 582 | struct workqueue_struct *wmi_wq; /* for deferred calls */ |
582 | struct work_struct wmi_event_worker; | 583 | struct work_struct wmi_event_worker; |
583 | struct workqueue_struct *wq_service; | 584 | struct workqueue_struct *wq_service; |
584 | struct work_struct connect_worker; | ||
585 | struct work_struct disconnect_worker; | 585 | struct work_struct disconnect_worker; |
586 | struct work_struct fw_error_worker; /* for FW error recovery */ | 586 | struct work_struct fw_error_worker; /* for FW error recovery */ |
587 | struct timer_list connect_timer; | 587 | struct timer_list connect_timer; |
588 | struct timer_list scan_timer; /* detect scan timeout */ | 588 | struct timer_list scan_timer; /* detect scan timeout */ |
589 | int pending_connect_cid; | ||
590 | struct list_head pending_wmi_ev; | 589 | struct list_head pending_wmi_ev; |
591 | /* | 590 | /* |
592 | * protect pending_wmi_ev | 591 | * protect pending_wmi_ev |
@@ -756,7 +755,8 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); | |||
756 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); | 755 | int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); |
757 | int wmi_rxon(struct wil6210_priv *wil, bool on); | 756 | int wmi_rxon(struct wil6210_priv *wil, bool on); |
758 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); | 757 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); |
759 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason); | 758 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, |
759 | bool full_disconnect); | ||
760 | int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); | 760 | int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); |
761 | int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); | 761 | int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); |
762 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); | 762 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); |
@@ -807,6 +807,7 @@ void wil_rx_fini(struct wil6210_priv *wil); | |||
807 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | 807 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, |
808 | int cid, int tid); | 808 | int cid, int tid); |
809 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); | 809 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); |
810 | int wil_tx_init(struct wil6210_priv *wil, int cid); | ||
810 | int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); | 811 | int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); |
811 | int wil_bcast_init(struct wil6210_priv *wil); | 812 | int wil_bcast_init(struct wil6210_priv *wil); |
812 | void wil_bcast_fini(struct wil6210_priv *wil); | 813 | void wil_bcast_fini(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index e3ea74cdd4aa..493e721c4fa7 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 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 |
@@ -426,6 +426,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
426 | const size_t assoc_req_ie_offset = sizeof(u16) * 2; | 426 | const size_t assoc_req_ie_offset = sizeof(u16) * 2; |
427 | /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ | 427 | /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ |
428 | const size_t assoc_resp_ie_offset = sizeof(u16) * 3; | 428 | const size_t assoc_resp_ie_offset = sizeof(u16) * 3; |
429 | int rc; | ||
429 | 430 | ||
430 | if (len < sizeof(*evt)) { | 431 | if (len < sizeof(*evt)) { |
431 | wil_err(wil, "Connect event too short : %d bytes\n", len); | 432 | wil_err(wil, "Connect event too short : %d bytes\n", len); |
@@ -445,8 +446,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
445 | } | 446 | } |
446 | 447 | ||
447 | ch = evt->channel + 1; | 448 | ch = evt->channel + 1; |
448 | wil_dbg_wmi(wil, "Connect %pM channel [%d] cid %d\n", | 449 | wil_info(wil, "Connect %pM channel [%d] cid %d\n", |
449 | evt->bssid, ch, evt->cid); | 450 | evt->bssid, ch, evt->cid); |
450 | wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, | 451 | wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, |
451 | evt->assoc_info, len - sizeof(*evt), true); | 452 | evt->assoc_info, len - sizeof(*evt), true); |
452 | 453 | ||
@@ -468,20 +469,67 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
468 | assoc_resp_ielen = 0; | 469 | assoc_resp_ielen = 0; |
469 | } | 470 | } |
470 | 471 | ||
472 | mutex_lock(&wil->mutex); | ||
473 | if (test_bit(wil_status_resetting, wil->status) || | ||
474 | !test_bit(wil_status_fwready, wil->status)) { | ||
475 | wil_err(wil, "status_resetting, cancel connect event, CID %d\n", | ||
476 | evt->cid); | ||
477 | mutex_unlock(&wil->mutex); | ||
478 | /* no need for cleanup, wil_reset will do that */ | ||
479 | return; | ||
480 | } | ||
481 | |||
471 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | 482 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || |
472 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | 483 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { |
473 | if (!test_bit(wil_status_fwconnecting, wil->status)) { | 484 | if (!test_bit(wil_status_fwconnecting, wil->status)) { |
474 | wil_err(wil, "Not in connecting state\n"); | 485 | wil_err(wil, "Not in connecting state\n"); |
486 | mutex_unlock(&wil->mutex); | ||
475 | return; | 487 | return; |
476 | } | 488 | } |
477 | del_timer_sync(&wil->connect_timer); | 489 | del_timer_sync(&wil->connect_timer); |
478 | cfg80211_connect_result(ndev, evt->bssid, | 490 | } |
479 | assoc_req_ie, assoc_req_ielen, | 491 | |
480 | assoc_resp_ie, assoc_resp_ielen, | 492 | /* FIXME FW can transmit only ucast frames to peer */ |
481 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | 493 | /* FIXME real ring_id instead of hard coded 0 */ |
494 | ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); | ||
495 | wil->sta[evt->cid].status = wil_sta_conn_pending; | ||
482 | 496 | ||
497 | rc = wil_tx_init(wil, evt->cid); | ||
498 | if (rc) { | ||
499 | wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n", | ||
500 | __func__, evt->cid, rc); | ||
501 | wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, | ||
502 | WLAN_REASON_UNSPECIFIED, false); | ||
503 | } else { | ||
504 | wil_info(wil, "%s: successful connection to CID %d\n", | ||
505 | __func__, evt->cid); | ||
506 | } | ||
507 | |||
508 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | ||
509 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | ||
510 | if (rc) { | ||
511 | netif_tx_stop_all_queues(ndev); | ||
512 | netif_carrier_off(ndev); | ||
513 | wil_err(wil, | ||
514 | "%s: cfg80211_connect_result with failure\n", | ||
515 | __func__); | ||
516 | cfg80211_connect_result(ndev, evt->bssid, NULL, 0, | ||
517 | NULL, 0, | ||
518 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
519 | GFP_KERNEL); | ||
520 | goto out; | ||
521 | } else { | ||
522 | cfg80211_connect_result(ndev, evt->bssid, | ||
523 | assoc_req_ie, assoc_req_ielen, | ||
524 | assoc_resp_ie, assoc_resp_ielen, | ||
525 | WLAN_STATUS_SUCCESS, | ||
526 | GFP_KERNEL); | ||
527 | } | ||
483 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || | 528 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || |
484 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | 529 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { |
530 | if (rc) | ||
531 | goto out; | ||
532 | |||
485 | memset(&sinfo, 0, sizeof(sinfo)); | 533 | memset(&sinfo, 0, sizeof(sinfo)); |
486 | 534 | ||
487 | sinfo.generation = wil->sinfo_gen++; | 535 | sinfo.generation = wil->sinfo_gen++; |
@@ -492,17 +540,21 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
492 | } | 540 | } |
493 | 541 | ||
494 | cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); | 542 | cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); |
543 | } else { | ||
544 | wil_err(wil, "%s: unhandled iftype %d for CID %d\n", | ||
545 | __func__, wdev->iftype, evt->cid); | ||
546 | goto out; | ||
495 | } | 547 | } |
496 | clear_bit(wil_status_fwconnecting, wil->status); | ||
497 | set_bit(wil_status_fwconnected, wil->status); | ||
498 | 548 | ||
499 | /* FIXME FW can transmit only ucast frames to peer */ | 549 | wil->sta[evt->cid].status = wil_sta_connected; |
500 | /* FIXME real ring_id instead of hard coded 0 */ | 550 | set_bit(wil_status_fwconnected, wil->status); |
501 | ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); | 551 | netif_tx_wake_all_queues(ndev); |
502 | wil->sta[evt->cid].status = wil_sta_conn_pending; | ||
503 | 552 | ||
504 | wil->pending_connect_cid = evt->cid; | 553 | out: |
505 | queue_work(wil->wq_service, &wil->connect_worker); | 554 | if (rc) |
555 | wil->sta[evt->cid].status = wil_sta_unused; | ||
556 | clear_bit(wil_status_fwconnecting, wil->status); | ||
557 | mutex_unlock(&wil->mutex); | ||
506 | } | 558 | } |
507 | 559 | ||
508 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | 560 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, |
@@ -511,8 +563,8 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | |||
511 | struct wmi_disconnect_event *evt = d; | 563 | struct wmi_disconnect_event *evt = d; |
512 | u16 reason_code = le16_to_cpu(evt->protocol_reason_status); | 564 | u16 reason_code = le16_to_cpu(evt->protocol_reason_status); |
513 | 565 | ||
514 | wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", | 566 | wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n", |
515 | evt->bssid, reason_code, evt->disconnect_reason); | 567 | evt->bssid, reason_code, evt->disconnect_reason); |
516 | 568 | ||
517 | wil->sinfo_gen++; | 569 | wil->sinfo_gen++; |
518 | 570 | ||
@@ -727,6 +779,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
727 | void __iomem *src; | 779 | void __iomem *src; |
728 | ulong flags; | 780 | ulong flags; |
729 | unsigned n; | 781 | unsigned n; |
782 | unsigned int num_immed_reply = 0; | ||
730 | 783 | ||
731 | if (!test_bit(wil_status_mbox_ready, wil->status)) { | 784 | if (!test_bit(wil_status_mbox_ready, wil->status)) { |
732 | wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); | 785 | wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); |
@@ -736,6 +789,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
736 | for (n = 0;; n++) { | 789 | for (n = 0;; n++) { |
737 | u16 len; | 790 | u16 len; |
738 | bool q; | 791 | bool q; |
792 | bool immed_reply = false; | ||
739 | 793 | ||
740 | r->head = wil_r(wil, RGF_MBOX + | 794 | r->head = wil_r(wil, RGF_MBOX + |
741 | offsetof(struct wil6210_mbox_ctl, rx.head)); | 795 | offsetof(struct wil6210_mbox_ctl, rx.head)); |
@@ -784,6 +838,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
784 | struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi; | 838 | struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi; |
785 | u16 id = le16_to_cpu(wmi->id); | 839 | u16 id = le16_to_cpu(wmi->id); |
786 | u32 tstamp = le32_to_cpu(wmi->timestamp); | 840 | u32 tstamp = le32_to_cpu(wmi->timestamp); |
841 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
842 | if (wil->reply_id && wil->reply_id == id) { | ||
843 | if (wil->reply_buf) { | ||
844 | memcpy(wil->reply_buf, wmi, | ||
845 | min(len, wil->reply_size)); | ||
846 | immed_reply = true; | ||
847 | } | ||
848 | } | ||
849 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
787 | 850 | ||
788 | wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n", | 851 | wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n", |
789 | id, wmi->mid, tstamp); | 852 | id, wmi->mid, tstamp); |
@@ -799,15 +862,24 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
799 | wil_w(wil, RGF_MBOX + | 862 | wil_w(wil, RGF_MBOX + |
800 | offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail); | 863 | offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail); |
801 | 864 | ||
802 | /* add to the pending list */ | 865 | if (immed_reply) { |
803 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | 866 | wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", |
804 | list_add_tail(&evt->list, &wil->pending_wmi_ev); | 867 | __func__, wil->reply_id); |
805 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | 868 | kfree(evt); |
806 | q = queue_work(wil->wmi_wq, &wil->wmi_event_worker); | 869 | num_immed_reply++; |
807 | wil_dbg_wmi(wil, "queue_work -> %d\n", q); | 870 | complete(&wil->wmi_call); |
871 | } else { | ||
872 | /* add to the pending list */ | ||
873 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
874 | list_add_tail(&evt->list, &wil->pending_wmi_ev); | ||
875 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
876 | q = queue_work(wil->wmi_wq, &wil->wmi_event_worker); | ||
877 | wil_dbg_wmi(wil, "queue_work -> %d\n", q); | ||
878 | } | ||
808 | } | 879 | } |
809 | /* normally, 1 event per IRQ should be processed */ | 880 | /* normally, 1 event per IRQ should be processed */ |
810 | wil_dbg_wmi(wil, "%s -> %d events queued\n", __func__, n); | 881 | wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__, |
882 | n - num_immed_reply, num_immed_reply); | ||
811 | } | 883 | } |
812 | 884 | ||
813 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | 885 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, |
@@ -818,13 +890,16 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | |||
818 | 890 | ||
819 | mutex_lock(&wil->wmi_mutex); | 891 | mutex_lock(&wil->wmi_mutex); |
820 | 892 | ||
893 | spin_lock(&wil->wmi_ev_lock); | ||
894 | wil->reply_id = reply_id; | ||
895 | wil->reply_buf = reply; | ||
896 | wil->reply_size = reply_size; | ||
897 | spin_unlock(&wil->wmi_ev_lock); | ||
898 | |||
821 | rc = __wmi_send(wil, cmdid, buf, len); | 899 | rc = __wmi_send(wil, cmdid, buf, len); |
822 | if (rc) | 900 | if (rc) |
823 | goto out; | 901 | goto out; |
824 | 902 | ||
825 | wil->reply_id = reply_id; | ||
826 | wil->reply_buf = reply; | ||
827 | wil->reply_size = reply_size; | ||
828 | remain = wait_for_completion_timeout(&wil->wmi_call, | 903 | remain = wait_for_completion_timeout(&wil->wmi_call, |
829 | msecs_to_jiffies(to_msec)); | 904 | msecs_to_jiffies(to_msec)); |
830 | if (0 == remain) { | 905 | if (0 == remain) { |
@@ -837,10 +912,14 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | |||
837 | cmdid, reply_id, | 912 | cmdid, reply_id, |
838 | to_msec - jiffies_to_msecs(remain)); | 913 | to_msec - jiffies_to_msecs(remain)); |
839 | } | 914 | } |
915 | |||
916 | out: | ||
917 | spin_lock(&wil->wmi_ev_lock); | ||
840 | wil->reply_id = 0; | 918 | wil->reply_id = 0; |
841 | wil->reply_buf = NULL; | 919 | wil->reply_buf = NULL; |
842 | wil->reply_size = 0; | 920 | wil->reply_size = 0; |
843 | out: | 921 | spin_unlock(&wil->wmi_ev_lock); |
922 | |||
844 | mutex_unlock(&wil->wmi_mutex); | 923 | mutex_unlock(&wil->wmi_mutex); |
845 | 924 | ||
846 | return rc; | 925 | return rc; |
@@ -1184,7 +1263,8 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) | |||
1184 | return 0; | 1263 | return 0; |
1185 | } | 1264 | } |
1186 | 1265 | ||
1187 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) | 1266 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, |
1267 | bool full_disconnect) | ||
1188 | { | 1268 | { |
1189 | int rc; | 1269 | int rc; |
1190 | u16 reason_code; | 1270 | u16 reason_code; |
@@ -1208,19 +1288,20 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) | |||
1208 | return rc; | 1288 | return rc; |
1209 | } | 1289 | } |
1210 | 1290 | ||
1211 | /* call event handler manually after processing wmi_call, | 1291 | if (full_disconnect) { |
1212 | * to avoid deadlock - disconnect event handler acquires wil->mutex | 1292 | /* call event handler manually after processing wmi_call, |
1213 | * while it is already held here | 1293 | * to avoid deadlock - disconnect event handler acquires |
1214 | */ | 1294 | * wil->mutex while it is already held here |
1215 | reason_code = le16_to_cpu(reply.evt.protocol_reason_status); | 1295 | */ |
1216 | 1296 | reason_code = le16_to_cpu(reply.evt.protocol_reason_status); | |
1217 | wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", | ||
1218 | reply.evt.bssid, reason_code, | ||
1219 | reply.evt.disconnect_reason); | ||
1220 | 1297 | ||
1221 | wil->sinfo_gen++; | 1298 | wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", |
1222 | wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); | 1299 | reply.evt.bssid, reason_code, |
1300 | reply.evt.disconnect_reason); | ||
1223 | 1301 | ||
1302 | wil->sinfo_gen++; | ||
1303 | wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); | ||
1304 | } | ||
1224 | return 0; | 1305 | return 0; |
1225 | } | 1306 | } |
1226 | 1307 | ||
@@ -1348,14 +1429,11 @@ static void wmi_event_handle(struct wil6210_priv *wil, | |||
1348 | id, wil->reply_id); | 1429 | id, wil->reply_id); |
1349 | /* check if someone waits for this event */ | 1430 | /* check if someone waits for this event */ |
1350 | if (wil->reply_id && wil->reply_id == id) { | 1431 | if (wil->reply_id && wil->reply_id == id) { |
1351 | if (wil->reply_buf) { | 1432 | WARN_ON(wil->reply_buf); |
1352 | memcpy(wil->reply_buf, wmi, | 1433 | wmi_evt_call_handler(wil, id, evt_data, |
1353 | min(len, wil->reply_size)); | 1434 | len - sizeof(*wmi)); |
1354 | } else { | 1435 | wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", |
1355 | wmi_evt_call_handler(wil, id, evt_data, | 1436 | __func__, id); |
1356 | len - sizeof(*wmi)); | ||
1357 | } | ||
1358 | wil_dbg_wmi(wil, "Complete WMI 0x%04x\n", id); | ||
1359 | complete(&wil->wmi_call); | 1437 | complete(&wil->wmi_call); |
1360 | return; | 1438 | return; |
1361 | } | 1439 | } |
diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c index dab25136214a..1efb1d66e0b7 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.c +++ b/drivers/net/wireless/atmel/at76c50x-usb.c | |||
@@ -2481,9 +2481,7 @@ static int at76_probe(struct usb_interface *interface, | |||
2481 | dev_err(&interface->dev, | 2481 | dev_err(&interface->dev, |
2482 | "error %d downloading internal firmware\n", | 2482 | "error %d downloading internal firmware\n", |
2483 | ret); | 2483 | ret); |
2484 | goto exit; | ||
2485 | } | 2484 | } |
2486 | usb_put_dev(udev); | ||
2487 | goto exit; | 2485 | goto exit; |
2488 | } | 2486 | } |
2489 | 2487 | ||
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index c279211e49f9..72380af9dc52 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c | |||
@@ -4375,12 +4375,10 @@ redo: | |||
4375 | /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ | 4375 | /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ |
4376 | orig_dev = dev; | 4376 | orig_dev = dev; |
4377 | mutex_unlock(&wl->mutex); | 4377 | mutex_unlock(&wl->mutex); |
4378 | if (b43_bus_host_is_sdio(dev->dev)) { | 4378 | if (b43_bus_host_is_sdio(dev->dev)) |
4379 | b43_sdio_free_irq(dev); | 4379 | b43_sdio_free_irq(dev); |
4380 | } else { | 4380 | else |
4381 | synchronize_irq(dev->dev->irq); | ||
4382 | free_irq(dev->dev->irq, dev); | 4381 | free_irq(dev->dev->irq, dev); |
4383 | } | ||
4384 | mutex_lock(&wl->mutex); | 4382 | mutex_lock(&wl->mutex); |
4385 | dev = wl->current_dev; | 4383 | dev = wl->current_dev; |
4386 | if (!dev) | 4384 | if (!dev) |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index b98db8a0a069..da0cdd313880 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -27,8 +27,6 @@ | |||
27 | #include <linux/mmc/sdio_func.h> | 27 | #include <linux/mmc/sdio_func.h> |
28 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
32 | #include <linux/pm_runtime.h> | 30 | #include <linux/pm_runtime.h> |
33 | #include <linux/suspend.h> | 31 | #include <linux/suspend.h> |
34 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
@@ -46,7 +44,6 @@ | |||
46 | #include "bus.h" | 44 | #include "bus.h" |
47 | #include "debug.h" | 45 | #include "debug.h" |
48 | #include "sdio.h" | 46 | #include "sdio.h" |
49 | #include "of.h" | ||
50 | #include "core.h" | 47 | #include "core.h" |
51 | #include "common.h" | 48 | #include "common.h" |
52 | 49 | ||
@@ -106,18 +103,18 @@ static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func) | |||
106 | 103 | ||
107 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) | 104 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) |
108 | { | 105 | { |
106 | struct brcmfmac_sdio_pd *pdata; | ||
109 | int ret = 0; | 107 | int ret = 0; |
110 | u8 data; | 108 | u8 data; |
111 | u32 addr, gpiocontrol; | 109 | u32 addr, gpiocontrol; |
112 | unsigned long flags; | 110 | unsigned long flags; |
113 | 111 | ||
114 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { | 112 | pdata = &sdiodev->settings->bus.sdio; |
113 | if (pdata->oob_irq_supported) { | ||
115 | brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n", | 114 | brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n", |
116 | sdiodev->pdata->oob_irq_nr); | 115 | pdata->oob_irq_nr); |
117 | ret = request_irq(sdiodev->pdata->oob_irq_nr, | 116 | ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler, |
118 | brcmf_sdiod_oob_irqhandler, | 117 | pdata->oob_irq_flags, "brcmf_oob_intr", |
119 | sdiodev->pdata->oob_irq_flags, | ||
120 | "brcmf_oob_intr", | ||
121 | &sdiodev->func[1]->dev); | 118 | &sdiodev->func[1]->dev); |
122 | if (ret != 0) { | 119 | if (ret != 0) { |
123 | brcmf_err("request_irq failed %d\n", ret); | 120 | brcmf_err("request_irq failed %d\n", ret); |
@@ -129,7 +126,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
129 | sdiodev->irq_en = true; | 126 | sdiodev->irq_en = true; |
130 | spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); | 127 | spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); |
131 | 128 | ||
132 | ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr); | 129 | ret = enable_irq_wake(pdata->oob_irq_nr); |
133 | if (ret != 0) { | 130 | if (ret != 0) { |
134 | brcmf_err("enable_irq_wake failed %d\n", ret); | 131 | brcmf_err("enable_irq_wake failed %d\n", ret); |
135 | return ret; | 132 | return ret; |
@@ -158,7 +155,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
158 | 155 | ||
159 | /* redirect, configure and enable io for interrupt signal */ | 156 | /* redirect, configure and enable io for interrupt signal */ |
160 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | 157 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; |
161 | if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) | 158 | if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) |
162 | data |= SDIO_SEPINT_ACT_HI; | 159 | data |= SDIO_SEPINT_ACT_HI; |
163 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); | 160 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); |
164 | 161 | ||
@@ -176,9 +173,12 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
176 | 173 | ||
177 | int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev) | 174 | int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev) |
178 | { | 175 | { |
176 | struct brcmfmac_sdio_pd *pdata; | ||
177 | |||
179 | brcmf_dbg(SDIO, "Entering\n"); | 178 | brcmf_dbg(SDIO, "Entering\n"); |
180 | 179 | ||
181 | if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) { | 180 | pdata = &sdiodev->settings->bus.sdio; |
181 | if (pdata->oob_irq_supported) { | ||
182 | sdio_claim_host(sdiodev->func[1]); | 182 | sdio_claim_host(sdiodev->func[1]); |
183 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); | 183 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); |
184 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); | 184 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); |
@@ -187,11 +187,10 @@ int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
187 | if (sdiodev->oob_irq_requested) { | 187 | if (sdiodev->oob_irq_requested) { |
188 | sdiodev->oob_irq_requested = false; | 188 | sdiodev->oob_irq_requested = false; |
189 | if (sdiodev->irq_wake) { | 189 | if (sdiodev->irq_wake) { |
190 | disable_irq_wake(sdiodev->pdata->oob_irq_nr); | 190 | disable_irq_wake(pdata->oob_irq_nr); |
191 | sdiodev->irq_wake = false; | 191 | sdiodev->irq_wake = false; |
192 | } | 192 | } |
193 | free_irq(sdiodev->pdata->oob_irq_nr, | 193 | free_irq(pdata->oob_irq_nr, &sdiodev->func[1]->dev); |
194 | &sdiodev->func[1]->dev); | ||
195 | sdiodev->irq_en = false; | 194 | sdiodev->irq_en = false; |
196 | } | 195 | } |
197 | } else { | 196 | } else { |
@@ -523,7 +522,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
523 | target_list = pktlist; | 522 | target_list = pktlist; |
524 | /* for host with broken sg support, prepare a page aligned list */ | 523 | /* for host with broken sg support, prepare a page aligned list */ |
525 | __skb_queue_head_init(&local_list); | 524 | __skb_queue_head_init(&local_list); |
526 | if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) { | 525 | if (!write && sdiodev->settings->bus.sdio.broken_sg_support) { |
527 | req_sz = 0; | 526 | req_sz = 0; |
528 | skb_queue_walk(pktlist, pkt_next) | 527 | skb_queue_walk(pktlist, pkt_next) |
529 | req_sz += pkt_next->len; | 528 | req_sz += pkt_next->len; |
@@ -630,7 +629,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
630 | } | 629 | } |
631 | } | 630 | } |
632 | 631 | ||
633 | if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) { | 632 | if (!write && sdiodev->settings->bus.sdio.broken_sg_support) { |
634 | local_pkt_next = local_list.next; | 633 | local_pkt_next = local_list.next; |
635 | orig_offset = 0; | 634 | orig_offset = 0; |
636 | skb_queue_walk(pktlist, pkt_next) { | 635 | skb_queue_walk(pktlist, pkt_next) { |
@@ -901,7 +900,7 @@ void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) | |||
901 | return; | 900 | return; |
902 | 901 | ||
903 | nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE, | 902 | nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE, |
904 | sdiodev->bus_if->drvr->settings->sdiod_txglomsz); | 903 | sdiodev->settings->bus.sdio.txglomsz); |
905 | nents += (nents >> 4) + 1; | 904 | nents += (nents >> 4) + 1; |
906 | 905 | ||
907 | WARN_ON(nents > sdiodev->max_segment_count); | 906 | WARN_ON(nents > sdiodev->max_segment_count); |
@@ -913,7 +912,7 @@ void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) | |||
913 | sdiodev->sg_support = false; | 912 | sdiodev->sg_support = false; |
914 | } | 913 | } |
915 | 914 | ||
916 | sdiodev->txglomsz = sdiodev->bus_if->drvr->settings->sdiod_txglomsz; | 915 | sdiodev->txglomsz = sdiodev->settings->bus.sdio.txglomsz; |
917 | } | 916 | } |
918 | 917 | ||
919 | #ifdef CONFIG_PM_SLEEP | 918 | #ifdef CONFIG_PM_SLEEP |
@@ -1103,8 +1102,6 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { | |||
1103 | }; | 1102 | }; |
1104 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 1103 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
1105 | 1104 | ||
1106 | static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata; | ||
1107 | |||
1108 | 1105 | ||
1109 | static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev, | 1106 | static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev, |
1110 | int val) | 1107 | int val) |
@@ -1167,20 +1164,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
1167 | dev_set_drvdata(&func->dev, bus_if); | 1164 | dev_set_drvdata(&func->dev, bus_if); |
1168 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); | 1165 | dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); |
1169 | sdiodev->dev = &sdiodev->func[1]->dev; | 1166 | sdiodev->dev = &sdiodev->func[1]->dev; |
1170 | sdiodev->pdata = brcmfmac_sdio_pdata; | ||
1171 | |||
1172 | if (!sdiodev->pdata) | ||
1173 | brcmf_of_probe(sdiodev); | ||
1174 | |||
1175 | #ifdef CONFIG_PM_SLEEP | ||
1176 | /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ | ||
1177 | * is true or when platform data OOB irq is true). | ||
1178 | */ | ||
1179 | if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) && | ||
1180 | ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) || | ||
1181 | (sdiodev->pdata && sdiodev->pdata->oob_irq_supported))) | ||
1182 | bus_if->wowl_supported = true; | ||
1183 | #endif | ||
1184 | 1167 | ||
1185 | brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN); | 1168 | brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN); |
1186 | 1169 | ||
@@ -1263,8 +1246,8 @@ static int brcmf_ops_sdio_suspend(struct device *dev) | |||
1263 | 1246 | ||
1264 | sdio_flags = MMC_PM_KEEP_POWER; | 1247 | sdio_flags = MMC_PM_KEEP_POWER; |
1265 | if (sdiodev->wowl_enabled) { | 1248 | if (sdiodev->wowl_enabled) { |
1266 | if (sdiodev->pdata->oob_irq_supported) | 1249 | if (sdiodev->settings->bus.sdio.oob_irq_supported) |
1267 | enable_irq_wake(sdiodev->pdata->oob_irq_nr); | 1250 | enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); |
1268 | else | 1251 | else |
1269 | sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; | 1252 | sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; |
1270 | } | 1253 | } |
@@ -1296,7 +1279,7 @@ static const struct dev_pm_ops brcmf_sdio_pm_ops = { | |||
1296 | static struct sdio_driver brcmf_sdmmc_driver = { | 1279 | static struct sdio_driver brcmf_sdmmc_driver = { |
1297 | .probe = brcmf_ops_sdio_probe, | 1280 | .probe = brcmf_ops_sdio_probe, |
1298 | .remove = brcmf_ops_sdio_remove, | 1281 | .remove = brcmf_ops_sdio_remove, |
1299 | .name = BRCMFMAC_SDIO_PDATA_NAME, | 1282 | .name = KBUILD_MODNAME, |
1300 | .id_table = brcmf_sdmmc_ids, | 1283 | .id_table = brcmf_sdmmc_ids, |
1301 | .drv = { | 1284 | .drv = { |
1302 | .owner = THIS_MODULE, | 1285 | .owner = THIS_MODULE, |
@@ -1306,37 +1289,6 @@ static struct sdio_driver brcmf_sdmmc_driver = { | |||
1306 | }, | 1289 | }, |
1307 | }; | 1290 | }; |
1308 | 1291 | ||
1309 | static int __init brcmf_sdio_pd_probe(struct platform_device *pdev) | ||
1310 | { | ||
1311 | brcmf_dbg(SDIO, "Enter\n"); | ||
1312 | |||
1313 | brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev); | ||
1314 | |||
1315 | if (brcmfmac_sdio_pdata->power_on) | ||
1316 | brcmfmac_sdio_pdata->power_on(); | ||
1317 | |||
1318 | return 0; | ||
1319 | } | ||
1320 | |||
1321 | static int brcmf_sdio_pd_remove(struct platform_device *pdev) | ||
1322 | { | ||
1323 | brcmf_dbg(SDIO, "Enter\n"); | ||
1324 | |||
1325 | if (brcmfmac_sdio_pdata->power_off) | ||
1326 | brcmfmac_sdio_pdata->power_off(); | ||
1327 | |||
1328 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
1329 | |||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | static struct platform_driver brcmf_sdio_pd = { | ||
1334 | .remove = brcmf_sdio_pd_remove, | ||
1335 | .driver = { | ||
1336 | .name = BRCMFMAC_SDIO_PDATA_NAME, | ||
1337 | } | ||
1338 | }; | ||
1339 | |||
1340 | void brcmf_sdio_register(void) | 1292 | void brcmf_sdio_register(void) |
1341 | { | 1293 | { |
1342 | int ret; | 1294 | int ret; |
@@ -1350,19 +1302,6 @@ void brcmf_sdio_exit(void) | |||
1350 | { | 1302 | { |
1351 | brcmf_dbg(SDIO, "Enter\n"); | 1303 | brcmf_dbg(SDIO, "Enter\n"); |
1352 | 1304 | ||
1353 | if (brcmfmac_sdio_pdata) | 1305 | sdio_unregister_driver(&brcmf_sdmmc_driver); |
1354 | platform_driver_unregister(&brcmf_sdio_pd); | ||
1355 | else | ||
1356 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
1357 | } | 1306 | } |
1358 | 1307 | ||
1359 | void __init brcmf_sdio_init(void) | ||
1360 | { | ||
1361 | int ret; | ||
1362 | |||
1363 | brcmf_dbg(SDIO, "Enter\n"); | ||
1364 | |||
1365 | ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe); | ||
1366 | if (ret == -ENODEV) | ||
1367 | brcmf_dbg(SDIO, "No platform data available.\n"); | ||
1368 | } | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 36093f93bfbe..8e02a478e889 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | |||
@@ -43,6 +43,8 @@ enum brcmf_bus_protocol_type { | |||
43 | BRCMF_PROTO_MSGBUF | 43 | BRCMF_PROTO_MSGBUF |
44 | }; | 44 | }; |
45 | 45 | ||
46 | struct brcmf_mp_device; | ||
47 | |||
46 | struct brcmf_bus_dcmd { | 48 | struct brcmf_bus_dcmd { |
47 | char *name; | 49 | char *name; |
48 | char *param; | 50 | char *param; |
@@ -217,7 +219,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, | |||
217 | void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); | 219 | void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); |
218 | 220 | ||
219 | /* Indication from bus module regarding presence/insertion of dongle. */ | 221 | /* Indication from bus module regarding presence/insertion of dongle. */ |
220 | int brcmf_attach(struct device *dev); | 222 | int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings); |
221 | /* Indication from bus module regarding removal/absence of dongle */ | 223 | /* Indication from bus module regarding removal/absence of dongle */ |
222 | void brcmf_detach(struct device *dev); | 224 | void brcmf_detach(struct device *dev); |
223 | /* Indication from bus module that dongle should be reset */ | 225 | /* Indication from bus module that dongle should be reset */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index d00c5c1d58bf..d5c2a27573b4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | |||
@@ -72,8 +72,13 @@ | |||
72 | #define RSN_AKM_NONE 0 /* None (IBSS) */ | 72 | #define RSN_AKM_NONE 0 /* None (IBSS) */ |
73 | #define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ | 73 | #define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ |
74 | #define RSN_AKM_PSK 2 /* Pre-shared Key */ | 74 | #define RSN_AKM_PSK 2 /* Pre-shared Key */ |
75 | #define RSN_AKM_SHA256_1X 5 /* SHA256, 802.1X */ | ||
76 | #define RSN_AKM_SHA256_PSK 6 /* SHA256, Pre-shared Key */ | ||
75 | #define RSN_CAP_LEN 2 /* Length of RSN capabilities */ | 77 | #define RSN_CAP_LEN 2 /* Length of RSN capabilities */ |
76 | #define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C | 78 | #define RSN_CAP_PTK_REPLAY_CNTR_MASK (BIT(2) | BIT(3)) |
79 | #define RSN_CAP_MFPR_MASK BIT(6) | ||
80 | #define RSN_CAP_MFPC_MASK BIT(7) | ||
81 | #define RSN_PMKID_COUNT_LEN 2 | ||
77 | 82 | ||
78 | #define VNDR_IE_CMD_LEN 4 /* length of the set command | 83 | #define VNDR_IE_CMD_LEN 4 /* length of the set command |
79 | * string :"add", "del" (+ NUL) | 84 | * string :"add", "del" (+ NUL) |
@@ -211,12 +216,19 @@ static const struct ieee80211_regdomain brcmf_regdom = { | |||
211 | REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), } | 216 | REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), } |
212 | }; | 217 | }; |
213 | 218 | ||
214 | static const u32 __wl_cipher_suites[] = { | 219 | /* Note: brcmf_cipher_suites is an array of int defining which cipher suites |
220 | * are supported. A pointer to this array and the number of entries is passed | ||
221 | * on to upper layers. AES_CMAC defines whether or not the driver supports MFP. | ||
222 | * So the cipher suite AES_CMAC has to be the last one in the array, and when | ||
223 | * device does not support MFP then the number of suites will be decreased by 1 | ||
224 | */ | ||
225 | static const u32 brcmf_cipher_suites[] = { | ||
215 | WLAN_CIPHER_SUITE_WEP40, | 226 | WLAN_CIPHER_SUITE_WEP40, |
216 | WLAN_CIPHER_SUITE_WEP104, | 227 | WLAN_CIPHER_SUITE_WEP104, |
217 | WLAN_CIPHER_SUITE_TKIP, | 228 | WLAN_CIPHER_SUITE_TKIP, |
218 | WLAN_CIPHER_SUITE_CCMP, | 229 | WLAN_CIPHER_SUITE_CCMP, |
219 | WLAN_CIPHER_SUITE_AES_CMAC, | 230 | /* Keep as last entry: */ |
231 | WLAN_CIPHER_SUITE_AES_CMAC | ||
220 | }; | 232 | }; |
221 | 233 | ||
222 | /* Vendor specific ie. id = 221, oui and type defines exact ie */ | 234 | /* Vendor specific ie. id = 221, oui and type defines exact ie */ |
@@ -456,7 +468,7 @@ send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key) | |||
456 | } | 468 | } |
457 | 469 | ||
458 | static s32 | 470 | static s32 |
459 | brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable) | 471 | brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable) |
460 | { | 472 | { |
461 | s32 err; | 473 | s32 err; |
462 | u32 mode; | 474 | u32 mode; |
@@ -484,6 +496,15 @@ brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable) | |||
484 | enable, mode); | 496 | enable, mode); |
485 | } | 497 | } |
486 | 498 | ||
499 | err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable); | ||
500 | if (err) { | ||
501 | brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n", | ||
502 | enable, err); | ||
503 | err = 0; | ||
504 | } else | ||
505 | brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n", | ||
506 | enable, mode); | ||
507 | |||
487 | return err; | 508 | return err; |
488 | } | 509 | } |
489 | 510 | ||
@@ -564,8 +585,8 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, | |||
564 | } | 585 | } |
565 | 586 | ||
566 | /* wait for firmware event */ | 587 | /* wait for firmware event */ |
567 | err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD, | 588 | err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_ADD, |
568 | BRCMF_VIF_EVENT_TIMEOUT); | 589 | BRCMF_VIF_EVENT_TIMEOUT); |
569 | brcmf_cfg80211_arm_vif_event(cfg, NULL); | 590 | brcmf_cfg80211_arm_vif_event(cfg, NULL); |
570 | if (!err) { | 591 | if (!err) { |
571 | brcmf_err("timeout occurred\n"); | 592 | brcmf_err("timeout occurred\n"); |
@@ -1125,7 +1146,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, | |||
1125 | 1146 | ||
1126 | /* Arm scan timeout timer */ | 1147 | /* Arm scan timeout timer */ |
1127 | mod_timer(&cfg->escan_timeout, jiffies + | 1148 | mod_timer(&cfg->escan_timeout, jiffies + |
1128 | WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); | 1149 | BRCMF_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); |
1129 | 1150 | ||
1130 | return 0; | 1151 | return 0; |
1131 | 1152 | ||
@@ -1524,7 +1545,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, | |||
1524 | 1545 | ||
1525 | static s32 | 1546 | static s32 |
1526 | brcmf_set_wsec_mode(struct net_device *ndev, | 1547 | brcmf_set_wsec_mode(struct net_device *ndev, |
1527 | struct cfg80211_connect_params *sme, bool mfp) | 1548 | struct cfg80211_connect_params *sme) |
1528 | { | 1549 | { |
1529 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | 1550 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); |
1530 | struct brcmf_cfg80211_security *sec; | 1551 | struct brcmf_cfg80211_security *sec; |
@@ -1583,10 +1604,7 @@ brcmf_set_wsec_mode(struct net_device *ndev, | |||
1583 | sme->privacy) | 1604 | sme->privacy) |
1584 | pval = AES_ENABLED; | 1605 | pval = AES_ENABLED; |
1585 | 1606 | ||
1586 | if (mfp) | 1607 | wsec = pval | gval; |
1587 | wsec = pval | gval | MFP_CAPABLE; | ||
1588 | else | ||
1589 | wsec = pval | gval; | ||
1590 | err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec); | 1608 | err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec); |
1591 | if (err) { | 1609 | if (err) { |
1592 | brcmf_err("error (%d)\n", err); | 1610 | brcmf_err("error (%d)\n", err); |
@@ -1603,56 +1621,100 @@ brcmf_set_wsec_mode(struct net_device *ndev, | |||
1603 | static s32 | 1621 | static s32 |
1604 | brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) | 1622 | brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) |
1605 | { | 1623 | { |
1606 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | 1624 | struct brcmf_if *ifp = netdev_priv(ndev); |
1607 | struct brcmf_cfg80211_security *sec; | 1625 | s32 val; |
1608 | s32 val = 0; | 1626 | s32 err; |
1609 | s32 err = 0; | 1627 | const struct brcmf_tlv *rsn_ie; |
1628 | const u8 *ie; | ||
1629 | u32 ie_len; | ||
1630 | u32 offset; | ||
1631 | u16 rsn_cap; | ||
1632 | u32 mfp; | ||
1633 | u16 count; | ||
1610 | 1634 | ||
1611 | if (sme->crypto.n_akm_suites) { | 1635 | if (!sme->crypto.n_akm_suites) |
1612 | err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), | 1636 | return 0; |
1613 | "wpa_auth", &val); | 1637 | |
1614 | if (err) { | 1638 | err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val); |
1615 | brcmf_err("could not get wpa_auth (%d)\n", err); | 1639 | if (err) { |
1616 | return err; | 1640 | brcmf_err("could not get wpa_auth (%d)\n", err); |
1641 | return err; | ||
1642 | } | ||
1643 | if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { | ||
1644 | switch (sme->crypto.akm_suites[0]) { | ||
1645 | case WLAN_AKM_SUITE_8021X: | ||
1646 | val = WPA_AUTH_UNSPECIFIED; | ||
1647 | break; | ||
1648 | case WLAN_AKM_SUITE_PSK: | ||
1649 | val = WPA_AUTH_PSK; | ||
1650 | break; | ||
1651 | default: | ||
1652 | brcmf_err("invalid cipher group (%d)\n", | ||
1653 | sme->crypto.cipher_group); | ||
1654 | return -EINVAL; | ||
1617 | } | 1655 | } |
1618 | if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { | 1656 | } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { |
1619 | switch (sme->crypto.akm_suites[0]) { | 1657 | switch (sme->crypto.akm_suites[0]) { |
1620 | case WLAN_AKM_SUITE_8021X: | 1658 | case WLAN_AKM_SUITE_8021X: |
1621 | val = WPA_AUTH_UNSPECIFIED; | 1659 | val = WPA2_AUTH_UNSPECIFIED; |
1622 | break; | 1660 | break; |
1623 | case WLAN_AKM_SUITE_PSK: | 1661 | case WLAN_AKM_SUITE_8021X_SHA256: |
1624 | val = WPA_AUTH_PSK; | 1662 | val = WPA2_AUTH_1X_SHA256; |
1625 | break; | 1663 | break; |
1626 | default: | 1664 | case WLAN_AKM_SUITE_PSK_SHA256: |
1627 | brcmf_err("invalid cipher group (%d)\n", | 1665 | val = WPA2_AUTH_PSK_SHA256; |
1628 | sme->crypto.cipher_group); | 1666 | break; |
1629 | return -EINVAL; | 1667 | case WLAN_AKM_SUITE_PSK: |
1630 | } | 1668 | val = WPA2_AUTH_PSK; |
1631 | } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { | 1669 | break; |
1632 | switch (sme->crypto.akm_suites[0]) { | 1670 | default: |
1633 | case WLAN_AKM_SUITE_8021X: | 1671 | brcmf_err("invalid cipher group (%d)\n", |
1634 | val = WPA2_AUTH_UNSPECIFIED; | 1672 | sme->crypto.cipher_group); |
1635 | break; | 1673 | return -EINVAL; |
1636 | case WLAN_AKM_SUITE_PSK: | ||
1637 | val = WPA2_AUTH_PSK; | ||
1638 | break; | ||
1639 | default: | ||
1640 | brcmf_err("invalid cipher group (%d)\n", | ||
1641 | sme->crypto.cipher_group); | ||
1642 | return -EINVAL; | ||
1643 | } | ||
1644 | } | 1674 | } |
1675 | } | ||
1645 | 1676 | ||
1646 | brcmf_dbg(CONN, "setting wpa_auth to %d\n", val); | 1677 | if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) |
1647 | err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), | 1678 | goto skip_mfp_config; |
1648 | "wpa_auth", val); | 1679 | /* The MFP mode (1 or 2) needs to be determined, parse IEs. The |
1649 | if (err) { | 1680 | * IE will not be verified, just a quick search for MFP config |
1650 | brcmf_err("could not set wpa_auth (%d)\n", err); | 1681 | */ |
1651 | return err; | 1682 | rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie, sme->ie_len, |
1652 | } | 1683 | WLAN_EID_RSN); |
1684 | if (!rsn_ie) | ||
1685 | goto skip_mfp_config; | ||
1686 | ie = (const u8 *)rsn_ie; | ||
1687 | ie_len = rsn_ie->len + TLV_HDR_LEN; | ||
1688 | /* Skip unicast suite */ | ||
1689 | offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN; | ||
1690 | if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len) | ||
1691 | goto skip_mfp_config; | ||
1692 | /* Skip multicast suite */ | ||
1693 | count = ie[offset] + (ie[offset + 1] << 8); | ||
1694 | offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN); | ||
1695 | if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len) | ||
1696 | goto skip_mfp_config; | ||
1697 | /* Skip auth key management suite(s) */ | ||
1698 | count = ie[offset] + (ie[offset + 1] << 8); | ||
1699 | offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN); | ||
1700 | if (offset + WPA_IE_SUITE_COUNT_LEN > ie_len) | ||
1701 | goto skip_mfp_config; | ||
1702 | /* Ready to read capabilities */ | ||
1703 | mfp = BRCMF_MFP_NONE; | ||
1704 | rsn_cap = ie[offset] + (ie[offset + 1] << 8); | ||
1705 | if (rsn_cap & RSN_CAP_MFPR_MASK) | ||
1706 | mfp = BRCMF_MFP_REQUIRED; | ||
1707 | else if (rsn_cap & RSN_CAP_MFPC_MASK) | ||
1708 | mfp = BRCMF_MFP_CAPABLE; | ||
1709 | brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp); | ||
1710 | |||
1711 | skip_mfp_config: | ||
1712 | brcmf_dbg(CONN, "setting wpa_auth to %d\n", val); | ||
1713 | err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val); | ||
1714 | if (err) { | ||
1715 | brcmf_err("could not set wpa_auth (%d)\n", err); | ||
1716 | return err; | ||
1653 | } | 1717 | } |
1654 | sec = &profile->sec; | ||
1655 | sec->wpa_auth = sme->crypto.akm_suites[0]; | ||
1656 | 1718 | ||
1657 | return err; | 1719 | return err; |
1658 | } | 1720 | } |
@@ -1818,7 +1880,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1818 | goto done; | 1880 | goto done; |
1819 | } | 1881 | } |
1820 | 1882 | ||
1821 | err = brcmf_set_wsec_mode(ndev, sme, sme->mfp == NL80211_MFP_REQUIRED); | 1883 | err = brcmf_set_wsec_mode(ndev, sme); |
1822 | if (err) { | 1884 | if (err) { |
1823 | brcmf_err("wl_set_set_cipher failed (%d)\n", err); | 1885 | brcmf_err("wl_set_set_cipher failed (%d)\n", err); |
1824 | goto done; | 1886 | goto done; |
@@ -2064,98 +2126,54 @@ done: | |||
2064 | } | 2126 | } |
2065 | 2127 | ||
2066 | static s32 | 2128 | static s32 |
2067 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | 2129 | brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, |
2068 | u8 key_idx, const u8 *mac_addr, struct key_params *params) | 2130 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
2069 | { | 2131 | { |
2070 | struct brcmf_if *ifp = netdev_priv(ndev); | 2132 | struct brcmf_if *ifp = netdev_priv(ndev); |
2071 | struct brcmf_wsec_key key; | 2133 | struct brcmf_wsec_key *key; |
2072 | s32 err = 0; | 2134 | s32 err; |
2073 | u8 keybuf[8]; | ||
2074 | 2135 | ||
2075 | memset(&key, 0, sizeof(key)); | 2136 | brcmf_dbg(TRACE, "Enter\n"); |
2076 | key.index = (u32) key_idx; | 2137 | brcmf_dbg(CONN, "key index (%d)\n", key_idx); |
2077 | /* Instead of bcast for ea address for default wep keys, | ||
2078 | driver needs it to be Null */ | ||
2079 | if (!is_multicast_ether_addr(mac_addr)) | ||
2080 | memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); | ||
2081 | key.len = (u32) params->key_len; | ||
2082 | /* check for key index change */ | ||
2083 | if (key.len == 0) { | ||
2084 | /* key delete */ | ||
2085 | err = send_key_to_dongle(ifp, &key); | ||
2086 | if (err) | ||
2087 | brcmf_err("key delete error (%d)\n", err); | ||
2088 | } else { | ||
2089 | if (key.len > sizeof(key.data)) { | ||
2090 | brcmf_err("Invalid key length (%d)\n", key.len); | ||
2091 | return -EINVAL; | ||
2092 | } | ||
2093 | 2138 | ||
2094 | brcmf_dbg(CONN, "Setting the key index %d\n", key.index); | 2139 | if (!check_vif_up(ifp->vif)) |
2095 | memcpy(key.data, params->key, key.len); | 2140 | return -EIO; |
2096 | 2141 | ||
2097 | if (!brcmf_is_apmode(ifp->vif) && | 2142 | if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) { |
2098 | (params->cipher == WLAN_CIPHER_SUITE_TKIP)) { | 2143 | /* we ignore this key index in this case */ |
2099 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); | 2144 | return -EINVAL; |
2100 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 2145 | } |
2101 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); | ||
2102 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); | ||
2103 | } | ||
2104 | 2146 | ||
2105 | /* if IW_ENCODE_EXT_RX_SEQ_VALID set */ | 2147 | key = &ifp->vif->profile.key[key_idx]; |
2106 | if (params->seq && params->seq_len == 6) { | ||
2107 | /* rx iv */ | ||
2108 | u8 *ivptr; | ||
2109 | ivptr = (u8 *) params->seq; | ||
2110 | key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | | ||
2111 | (ivptr[3] << 8) | ivptr[2]; | ||
2112 | key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; | ||
2113 | key.iv_initialized = true; | ||
2114 | } | ||
2115 | 2148 | ||
2116 | switch (params->cipher) { | 2149 | if (key->algo == CRYPTO_ALGO_OFF) { |
2117 | case WLAN_CIPHER_SUITE_WEP40: | 2150 | brcmf_dbg(CONN, "Ignore clearing of (never configured) key\n"); |
2118 | key.algo = CRYPTO_ALGO_WEP1; | 2151 | return -EINVAL; |
2119 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n"); | ||
2120 | break; | ||
2121 | case WLAN_CIPHER_SUITE_WEP104: | ||
2122 | key.algo = CRYPTO_ALGO_WEP128; | ||
2123 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); | ||
2124 | break; | ||
2125 | case WLAN_CIPHER_SUITE_TKIP: | ||
2126 | key.algo = CRYPTO_ALGO_TKIP; | ||
2127 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n"); | ||
2128 | break; | ||
2129 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
2130 | key.algo = CRYPTO_ALGO_AES_CCM; | ||
2131 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); | ||
2132 | break; | ||
2133 | case WLAN_CIPHER_SUITE_CCMP: | ||
2134 | key.algo = CRYPTO_ALGO_AES_CCM; | ||
2135 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n"); | ||
2136 | break; | ||
2137 | default: | ||
2138 | brcmf_err("Invalid cipher (0x%x)\n", params->cipher); | ||
2139 | return -EINVAL; | ||
2140 | } | ||
2141 | err = send_key_to_dongle(ifp, &key); | ||
2142 | if (err) | ||
2143 | brcmf_err("wsec_key error (%d)\n", err); | ||
2144 | } | 2152 | } |
2153 | |||
2154 | memset(key, 0, sizeof(*key)); | ||
2155 | key->index = (u32)key_idx; | ||
2156 | key->flags = BRCMF_PRIMARY_KEY; | ||
2157 | |||
2158 | /* Clear the key/index */ | ||
2159 | err = send_key_to_dongle(ifp, key); | ||
2160 | |||
2161 | brcmf_dbg(TRACE, "Exit\n"); | ||
2145 | return err; | 2162 | return err; |
2146 | } | 2163 | } |
2147 | 2164 | ||
2148 | static s32 | 2165 | static s32 |
2149 | brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 2166 | brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
2150 | u8 key_idx, bool pairwise, const u8 *mac_addr, | 2167 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
2151 | struct key_params *params) | 2168 | struct key_params *params) |
2152 | { | 2169 | { |
2153 | struct brcmf_if *ifp = netdev_priv(ndev); | 2170 | struct brcmf_if *ifp = netdev_priv(ndev); |
2154 | struct brcmf_wsec_key *key; | 2171 | struct brcmf_wsec_key *key; |
2155 | s32 val; | 2172 | s32 val; |
2156 | s32 wsec; | 2173 | s32 wsec; |
2157 | s32 err = 0; | 2174 | s32 err; |
2158 | u8 keybuf[8]; | 2175 | u8 keybuf[8]; |
2176 | bool ext_key; | ||
2159 | 2177 | ||
2160 | brcmf_dbg(TRACE, "Enter\n"); | 2178 | brcmf_dbg(TRACE, "Enter\n"); |
2161 | brcmf_dbg(CONN, "key index (%d)\n", key_idx); | 2179 | brcmf_dbg(CONN, "key index (%d)\n", key_idx); |
@@ -2168,27 +2186,32 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2168 | return -EINVAL; | 2186 | return -EINVAL; |
2169 | } | 2187 | } |
2170 | 2188 | ||
2171 | if (mac_addr && | 2189 | if (params->key_len == 0) |
2172 | (params->cipher != WLAN_CIPHER_SUITE_WEP40) && | 2190 | return brcmf_cfg80211_del_key(wiphy, ndev, key_idx, pairwise, |
2173 | (params->cipher != WLAN_CIPHER_SUITE_WEP104)) { | 2191 | mac_addr); |
2174 | brcmf_dbg(TRACE, "Exit"); | ||
2175 | return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params); | ||
2176 | } | ||
2177 | |||
2178 | key = &ifp->vif->profile.key[key_idx]; | ||
2179 | memset(key, 0, sizeof(*key)); | ||
2180 | 2192 | ||
2181 | if (params->key_len > sizeof(key->data)) { | 2193 | if (params->key_len > sizeof(key->data)) { |
2182 | brcmf_err("Too long key length (%u)\n", params->key_len); | 2194 | brcmf_err("Too long key length (%u)\n", params->key_len); |
2183 | err = -EINVAL; | 2195 | return -EINVAL; |
2184 | goto done; | 2196 | } |
2197 | |||
2198 | ext_key = false; | ||
2199 | if (mac_addr && (params->cipher != WLAN_CIPHER_SUITE_WEP40) && | ||
2200 | (params->cipher != WLAN_CIPHER_SUITE_WEP104)) { | ||
2201 | brcmf_dbg(TRACE, "Ext key, mac %pM", mac_addr); | ||
2202 | ext_key = true; | ||
2185 | } | 2203 | } |
2204 | |||
2205 | key = &ifp->vif->profile.key[key_idx]; | ||
2206 | memset(key, 0, sizeof(*key)); | ||
2207 | if ((ext_key) && (!is_multicast_ether_addr(mac_addr))) | ||
2208 | memcpy((char *)&key->ea, (void *)mac_addr, ETH_ALEN); | ||
2186 | key->len = params->key_len; | 2209 | key->len = params->key_len; |
2187 | key->index = key_idx; | 2210 | key->index = key_idx; |
2188 | |||
2189 | memcpy(key->data, params->key, key->len); | 2211 | memcpy(key->data, params->key, key->len); |
2212 | if (!ext_key) | ||
2213 | key->flags = BRCMF_PRIMARY_KEY; | ||
2190 | 2214 | ||
2191 | key->flags = BRCMF_PRIMARY_KEY; | ||
2192 | switch (params->cipher) { | 2215 | switch (params->cipher) { |
2193 | case WLAN_CIPHER_SUITE_WEP40: | 2216 | case WLAN_CIPHER_SUITE_WEP40: |
2194 | key->algo = CRYPTO_ALGO_WEP1; | 2217 | key->algo = CRYPTO_ALGO_WEP1; |
@@ -2228,7 +2251,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2228 | } | 2251 | } |
2229 | 2252 | ||
2230 | err = send_key_to_dongle(ifp, key); | 2253 | err = send_key_to_dongle(ifp, key); |
2231 | if (err) | 2254 | if (ext_key || err) |
2232 | goto done; | 2255 | goto done; |
2233 | 2256 | ||
2234 | err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); | 2257 | err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); |
@@ -2249,41 +2272,10 @@ done: | |||
2249 | } | 2272 | } |
2250 | 2273 | ||
2251 | static s32 | 2274 | static s32 |
2252 | brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | 2275 | brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, |
2253 | u8 key_idx, bool pairwise, const u8 *mac_addr) | 2276 | bool pairwise, const u8 *mac_addr, void *cookie, |
2254 | { | 2277 | void (*callback)(void *cookie, |
2255 | struct brcmf_if *ifp = netdev_priv(ndev); | 2278 | struct key_params *params)) |
2256 | struct brcmf_wsec_key key; | ||
2257 | s32 err = 0; | ||
2258 | |||
2259 | brcmf_dbg(TRACE, "Enter\n"); | ||
2260 | if (!check_vif_up(ifp->vif)) | ||
2261 | return -EIO; | ||
2262 | |||
2263 | if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) { | ||
2264 | /* we ignore this key index in this case */ | ||
2265 | return -EINVAL; | ||
2266 | } | ||
2267 | |||
2268 | memset(&key, 0, sizeof(key)); | ||
2269 | |||
2270 | key.index = (u32) key_idx; | ||
2271 | key.flags = BRCMF_PRIMARY_KEY; | ||
2272 | key.algo = CRYPTO_ALGO_OFF; | ||
2273 | |||
2274 | brcmf_dbg(CONN, "key index (%d)\n", key_idx); | ||
2275 | |||
2276 | /* Set the new key/index */ | ||
2277 | err = send_key_to_dongle(ifp, &key); | ||
2278 | |||
2279 | brcmf_dbg(TRACE, "Exit\n"); | ||
2280 | return err; | ||
2281 | } | ||
2282 | |||
2283 | static s32 | ||
2284 | brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | ||
2285 | u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, | ||
2286 | void (*callback) (void *cookie, struct key_params * params)) | ||
2287 | { | 2279 | { |
2288 | struct key_params params; | 2280 | struct key_params params; |
2289 | struct brcmf_if *ifp = netdev_priv(ndev); | 2281 | struct brcmf_if *ifp = netdev_priv(ndev); |
@@ -2335,8 +2327,15 @@ done: | |||
2335 | 2327 | ||
2336 | static s32 | 2328 | static s32 |
2337 | brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, | 2329 | brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, |
2338 | struct net_device *ndev, u8 key_idx) | 2330 | struct net_device *ndev, u8 key_idx) |
2339 | { | 2331 | { |
2332 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
2333 | |||
2334 | brcmf_dbg(TRACE, "Enter key_idx %d\n", key_idx); | ||
2335 | |||
2336 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) | ||
2337 | return 0; | ||
2338 | |||
2340 | brcmf_dbg(INFO, "Not supported\n"); | 2339 | brcmf_dbg(INFO, "Not supported\n"); |
2341 | 2340 | ||
2342 | return -EOPNOTSUPP; | 2341 | return -EOPNOTSUPP; |
@@ -3020,7 +3019,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
3020 | 3019 | ||
3021 | list = (struct brcmf_scan_results *) | 3020 | list = (struct brcmf_scan_results *) |
3022 | cfg->escan_info.escan_buf; | 3021 | cfg->escan_info.escan_buf; |
3023 | if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) { | 3022 | if (bi_length > BRCMF_ESCAN_BUF_SIZE - list->buflen) { |
3024 | brcmf_err("Buffer is too small: ignoring\n"); | 3023 | brcmf_err("Buffer is too small: ignoring\n"); |
3025 | goto exit; | 3024 | goto exit; |
3026 | } | 3025 | } |
@@ -3033,8 +3032,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
3033 | bss_info_le)) | 3032 | bss_info_le)) |
3034 | goto exit; | 3033 | goto exit; |
3035 | } | 3034 | } |
3036 | memcpy(&(cfg->escan_info.escan_buf[list->buflen]), | 3035 | memcpy(&cfg->escan_info.escan_buf[list->buflen], bss_info_le, |
3037 | bss_info_le, bi_length); | 3036 | bi_length); |
3038 | list->version = le32_to_cpu(bss_info_le->version); | 3037 | list->version = le32_to_cpu(bss_info_le->version); |
3039 | list->buflen += bi_length; | 3038 | list->buflen += bi_length; |
3040 | list->count++; | 3039 | list->count++; |
@@ -3092,6 +3091,11 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
3092 | 3091 | ||
3093 | brcmf_dbg(SCAN, "Enter\n"); | 3092 | brcmf_dbg(SCAN, "Enter\n"); |
3094 | 3093 | ||
3094 | if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) { | ||
3095 | brcmf_dbg(SCAN, "Event data to small. Ignore\n"); | ||
3096 | return 0; | ||
3097 | } | ||
3098 | |||
3095 | if (e->event_code == BRCMF_E_PFN_NET_LOST) { | 3099 | if (e->event_code == BRCMF_E_PFN_NET_LOST) { |
3096 | brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n"); | 3100 | brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n"); |
3097 | return 0; | 3101 | return 0; |
@@ -3415,6 +3419,11 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, | |||
3415 | 3419 | ||
3416 | brcmf_dbg(SCAN, "Enter\n"); | 3420 | brcmf_dbg(SCAN, "Enter\n"); |
3417 | 3421 | ||
3422 | if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) { | ||
3423 | brcmf_dbg(SCAN, "Event data to small. Ignore\n"); | ||
3424 | return 0; | ||
3425 | } | ||
3426 | |||
3418 | pfn_result = (struct brcmf_pno_scanresults_le *)data; | 3427 | pfn_result = (struct brcmf_pno_scanresults_le *)data; |
3419 | 3428 | ||
3420 | if (e->event_code == BRCMF_E_PFN_NET_LOST) { | 3429 | if (e->event_code == BRCMF_E_PFN_NET_LOST) { |
@@ -3507,6 +3516,10 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp) | |||
3507 | else | 3516 | else |
3508 | wakeup_data.net_detect = cfg->wowl.nd_info; | 3517 | wakeup_data.net_detect = cfg->wowl.nd_info; |
3509 | } | 3518 | } |
3519 | if (wakeind & BRCMF_WOWL_GTK_FAILURE) { | ||
3520 | brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_GTK_FAILURE\n"); | ||
3521 | wakeup_data.gtk_rekey_failure = true; | ||
3522 | } | ||
3510 | } else { | 3523 | } else { |
3511 | wakeup = NULL; | 3524 | wakeup = NULL; |
3512 | } | 3525 | } |
@@ -3533,7 +3546,8 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) | |||
3533 | brcmf_report_wowl_wakeind(wiphy, ifp); | 3546 | brcmf_report_wowl_wakeind(wiphy, ifp); |
3534 | brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0); | 3547 | brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0); |
3535 | brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0); | 3548 | brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0); |
3536 | brcmf_configure_arp_offload(ifp, true); | 3549 | if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND)) |
3550 | brcmf_configure_arp_nd_offload(ifp, true); | ||
3537 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, | 3551 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, |
3538 | cfg->wowl.pre_pmmode); | 3552 | cfg->wowl.pre_pmmode); |
3539 | cfg->wowl.active = false; | 3553 | cfg->wowl.active = false; |
@@ -3557,7 +3571,8 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, | |||
3557 | 3571 | ||
3558 | brcmf_dbg(TRACE, "Suspend, wowl config.\n"); | 3572 | brcmf_dbg(TRACE, "Suspend, wowl config.\n"); |
3559 | 3573 | ||
3560 | brcmf_configure_arp_offload(ifp, false); | 3574 | if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND)) |
3575 | brcmf_configure_arp_nd_offload(ifp, false); | ||
3561 | brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->wowl.pre_pmmode); | 3576 | brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->wowl.pre_pmmode); |
3562 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX); | 3577 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX); |
3563 | 3578 | ||
@@ -3588,6 +3603,8 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, | |||
3588 | brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND, | 3603 | brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND, |
3589 | brcmf_wowl_nd_results); | 3604 | brcmf_wowl_nd_results); |
3590 | } | 3605 | } |
3606 | if (wowl->gtk_rekey_failure) | ||
3607 | wowl_config |= BRCMF_WOWL_GTK_FAILURE; | ||
3591 | if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) | 3608 | if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) |
3592 | wowl_config |= BRCMF_WOWL_UNASSOC; | 3609 | wowl_config |= BRCMF_WOWL_UNASSOC; |
3593 | 3610 | ||
@@ -3818,7 +3835,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, | |||
3818 | u32 auth = 0; /* d11 open authentication */ | 3835 | u32 auth = 0; /* d11 open authentication */ |
3819 | u16 count; | 3836 | u16 count; |
3820 | s32 err = 0; | 3837 | s32 err = 0; |
3821 | s32 len = 0; | 3838 | s32 len; |
3822 | u32 i; | 3839 | u32 i; |
3823 | u32 wsec; | 3840 | u32 wsec; |
3824 | u32 pval = 0; | 3841 | u32 pval = 0; |
@@ -3828,6 +3845,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, | |||
3828 | u8 *data; | 3845 | u8 *data; |
3829 | u16 rsn_cap; | 3846 | u16 rsn_cap; |
3830 | u32 wme_bss_disable; | 3847 | u32 wme_bss_disable; |
3848 | u32 mfp; | ||
3831 | 3849 | ||
3832 | brcmf_dbg(TRACE, "Enter\n"); | 3850 | brcmf_dbg(TRACE, "Enter\n"); |
3833 | if (wpa_ie == NULL) | 3851 | if (wpa_ie == NULL) |
@@ -3942,19 +3960,53 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, | |||
3942 | is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : | 3960 | is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : |
3943 | (wpa_auth |= WPA_AUTH_PSK); | 3961 | (wpa_auth |= WPA_AUTH_PSK); |
3944 | break; | 3962 | break; |
3963 | case RSN_AKM_SHA256_PSK: | ||
3964 | brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); | ||
3965 | wpa_auth |= WPA2_AUTH_PSK_SHA256; | ||
3966 | break; | ||
3967 | case RSN_AKM_SHA256_1X: | ||
3968 | brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); | ||
3969 | wpa_auth |= WPA2_AUTH_1X_SHA256; | ||
3970 | break; | ||
3945 | default: | 3971 | default: |
3946 | brcmf_err("Ivalid key mgmt info\n"); | 3972 | brcmf_err("Ivalid key mgmt info\n"); |
3947 | } | 3973 | } |
3948 | offset++; | 3974 | offset++; |
3949 | } | 3975 | } |
3950 | 3976 | ||
3977 | mfp = BRCMF_MFP_NONE; | ||
3951 | if (is_rsn_ie) { | 3978 | if (is_rsn_ie) { |
3952 | wme_bss_disable = 1; | 3979 | wme_bss_disable = 1; |
3953 | if ((offset + RSN_CAP_LEN) <= len) { | 3980 | if ((offset + RSN_CAP_LEN) <= len) { |
3954 | rsn_cap = data[offset] + (data[offset + 1] << 8); | 3981 | rsn_cap = data[offset] + (data[offset + 1] << 8); |
3955 | if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK) | 3982 | if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK) |
3956 | wme_bss_disable = 0; | 3983 | wme_bss_disable = 0; |
3984 | if (rsn_cap & RSN_CAP_MFPR_MASK) { | ||
3985 | brcmf_dbg(TRACE, "MFP Required\n"); | ||
3986 | mfp = BRCMF_MFP_REQUIRED; | ||
3987 | /* Firmware only supports mfp required in | ||
3988 | * combination with WPA2_AUTH_PSK_SHA256 or | ||
3989 | * WPA2_AUTH_1X_SHA256. | ||
3990 | */ | ||
3991 | if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 | | ||
3992 | WPA2_AUTH_1X_SHA256))) { | ||
3993 | err = -EINVAL; | ||
3994 | goto exit; | ||
3995 | } | ||
3996 | /* Firmware has requirement that WPA2_AUTH_PSK/ | ||
3997 | * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI | ||
3998 | * is to be included in the rsn ie. | ||
3999 | */ | ||
4000 | if (wpa_auth & WPA2_AUTH_PSK_SHA256) | ||
4001 | wpa_auth |= WPA2_AUTH_PSK; | ||
4002 | else if (wpa_auth & WPA2_AUTH_1X_SHA256) | ||
4003 | wpa_auth |= WPA2_AUTH_UNSPECIFIED; | ||
4004 | } else if (rsn_cap & RSN_CAP_MFPC_MASK) { | ||
4005 | brcmf_dbg(TRACE, "MFP Capable\n"); | ||
4006 | mfp = BRCMF_MFP_CAPABLE; | ||
4007 | } | ||
3957 | } | 4008 | } |
4009 | offset += RSN_CAP_LEN; | ||
3958 | /* set wme_bss_disable to sync RSN Capabilities */ | 4010 | /* set wme_bss_disable to sync RSN Capabilities */ |
3959 | err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable", | 4011 | err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable", |
3960 | wme_bss_disable); | 4012 | wme_bss_disable); |
@@ -3962,6 +4014,21 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, | |||
3962 | brcmf_err("wme_bss_disable error %d\n", err); | 4014 | brcmf_err("wme_bss_disable error %d\n", err); |
3963 | goto exit; | 4015 | goto exit; |
3964 | } | 4016 | } |
4017 | |||
4018 | /* Skip PMKID cnt as it is know to be 0 for AP. */ | ||
4019 | offset += RSN_PMKID_COUNT_LEN; | ||
4020 | |||
4021 | /* See if there is BIP wpa suite left for MFP */ | ||
4022 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP) && | ||
4023 | ((offset + WPA_IE_MIN_OUI_LEN) <= len)) { | ||
4024 | err = brcmf_fil_bsscfg_data_set(ifp, "bip", | ||
4025 | &data[offset], | ||
4026 | WPA_IE_MIN_OUI_LEN); | ||
4027 | if (err < 0) { | ||
4028 | brcmf_err("bip error %d\n", err); | ||
4029 | goto exit; | ||
4030 | } | ||
4031 | } | ||
3965 | } | 4032 | } |
3966 | /* FOR WPS , set SES_OW_ENABLED */ | 4033 | /* FOR WPS , set SES_OW_ENABLED */ |
3967 | wsec = (pval | gval | SES_OW_ENABLED); | 4034 | wsec = (pval | gval | SES_OW_ENABLED); |
@@ -3978,6 +4045,16 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, | |||
3978 | brcmf_err("wsec error %d\n", err); | 4045 | brcmf_err("wsec error %d\n", err); |
3979 | goto exit; | 4046 | goto exit; |
3980 | } | 4047 | } |
4048 | /* Configure MFP, this needs to go after wsec otherwise the wsec command | ||
4049 | * will overwrite the values set by MFP | ||
4050 | */ | ||
4051 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) { | ||
4052 | err = brcmf_fil_bsscfg_int_set(ifp, "mfp", mfp); | ||
4053 | if (err < 0) { | ||
4054 | brcmf_err("mfp error %d\n", err); | ||
4055 | goto exit; | ||
4056 | } | ||
4057 | } | ||
3981 | /* set upper-layer auth */ | 4058 | /* set upper-layer auth */ |
3982 | err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth); | 4059 | err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth); |
3983 | if (err < 0) { | 4060 | if (err < 0) { |
@@ -4326,7 +4403,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4326 | 4403 | ||
4327 | if (!mbss) { | 4404 | if (!mbss) { |
4328 | brcmf_set_mpc(ifp, 0); | 4405 | brcmf_set_mpc(ifp, 0); |
4329 | brcmf_configure_arp_offload(ifp, false); | 4406 | brcmf_configure_arp_nd_offload(ifp, false); |
4330 | } | 4407 | } |
4331 | 4408 | ||
4332 | /* find the RSN_IE */ | 4409 | /* find the RSN_IE */ |
@@ -4472,7 +4549,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4472 | exit: | 4549 | exit: |
4473 | if ((err) && (!mbss)) { | 4550 | if ((err) && (!mbss)) { |
4474 | brcmf_set_mpc(ifp, 1); | 4551 | brcmf_set_mpc(ifp, 1); |
4475 | brcmf_configure_arp_offload(ifp, true); | 4552 | brcmf_configure_arp_nd_offload(ifp, true); |
4476 | } | 4553 | } |
4477 | return err; | 4554 | return err; |
4478 | } | 4555 | } |
@@ -4530,7 +4607,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | |||
4530 | brcmf_err("bss_enable config failed %d\n", err); | 4607 | brcmf_err("bss_enable config failed %d\n", err); |
4531 | } | 4608 | } |
4532 | brcmf_set_mpc(ifp, 1); | 4609 | brcmf_set_mpc(ifp, 1); |
4533 | brcmf_configure_arp_offload(ifp, true); | 4610 | brcmf_configure_arp_nd_offload(ifp, true); |
4534 | clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); | 4611 | clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); |
4535 | brcmf_net_setcarrier(ifp, false); | 4612 | brcmf_net_setcarrier(ifp, false); |
4536 | 4613 | ||
@@ -4855,7 +4932,32 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, | |||
4855 | return ret; | 4932 | return ret; |
4856 | } | 4933 | } |
4857 | 4934 | ||
4858 | static struct cfg80211_ops wl_cfg80211_ops = { | 4935 | #ifdef CONFIG_PM |
4936 | static int | ||
4937 | brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev, | ||
4938 | struct cfg80211_gtk_rekey_data *gtk) | ||
4939 | { | ||
4940 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4941 | struct brcmf_gtk_keyinfo_le gtk_le; | ||
4942 | int ret; | ||
4943 | |||
4944 | brcmf_dbg(TRACE, "Enter, bssidx=%d\n", ifp->bsscfgidx); | ||
4945 | |||
4946 | memcpy(gtk_le.kck, gtk->kck, sizeof(gtk_le.kck)); | ||
4947 | memcpy(gtk_le.kek, gtk->kek, sizeof(gtk_le.kek)); | ||
4948 | memcpy(gtk_le.replay_counter, gtk->replay_ctr, | ||
4949 | sizeof(gtk_le.replay_counter)); | ||
4950 | |||
4951 | ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", >k_le, | ||
4952 | sizeof(gtk_le)); | ||
4953 | if (ret < 0) | ||
4954 | brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret); | ||
4955 | |||
4956 | return ret; | ||
4957 | } | ||
4958 | #endif | ||
4959 | |||
4960 | static struct cfg80211_ops brcmf_cfg80211_ops = { | ||
4859 | .add_virtual_intf = brcmf_cfg80211_add_iface, | 4961 | .add_virtual_intf = brcmf_cfg80211_add_iface, |
4860 | .del_virtual_intf = brcmf_cfg80211_del_iface, | 4962 | .del_virtual_intf = brcmf_cfg80211_del_iface, |
4861 | .change_virtual_intf = brcmf_cfg80211_change_iface, | 4963 | .change_virtual_intf = brcmf_cfg80211_change_iface, |
@@ -5402,14 +5504,14 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg) | |||
5402 | { | 5504 | { |
5403 | kfree(cfg->conf); | 5505 | kfree(cfg->conf); |
5404 | cfg->conf = NULL; | 5506 | cfg->conf = NULL; |
5405 | kfree(cfg->escan_ioctl_buf); | ||
5406 | cfg->escan_ioctl_buf = NULL; | ||
5407 | kfree(cfg->extra_buf); | 5507 | kfree(cfg->extra_buf); |
5408 | cfg->extra_buf = NULL; | 5508 | cfg->extra_buf = NULL; |
5409 | kfree(cfg->wowl.nd); | 5509 | kfree(cfg->wowl.nd); |
5410 | cfg->wowl.nd = NULL; | 5510 | cfg->wowl.nd = NULL; |
5411 | kfree(cfg->wowl.nd_info); | 5511 | kfree(cfg->wowl.nd_info); |
5412 | cfg->wowl.nd_info = NULL; | 5512 | cfg->wowl.nd_info = NULL; |
5513 | kfree(cfg->escan_info.escan_buf); | ||
5514 | cfg->escan_info.escan_buf = NULL; | ||
5413 | } | 5515 | } |
5414 | 5516 | ||
5415 | static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) | 5517 | static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) |
@@ -5417,9 +5519,6 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) | |||
5417 | cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL); | 5519 | cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL); |
5418 | if (!cfg->conf) | 5520 | if (!cfg->conf) |
5419 | goto init_priv_mem_out; | 5521 | goto init_priv_mem_out; |
5420 | cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); | ||
5421 | if (!cfg->escan_ioctl_buf) | ||
5422 | goto init_priv_mem_out; | ||
5423 | cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); | 5522 | cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); |
5424 | if (!cfg->extra_buf) | 5523 | if (!cfg->extra_buf) |
5425 | goto init_priv_mem_out; | 5524 | goto init_priv_mem_out; |
@@ -5431,6 +5530,9 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) | |||
5431 | GFP_KERNEL); | 5530 | GFP_KERNEL); |
5432 | if (!cfg->wowl.nd_info) | 5531 | if (!cfg->wowl.nd_info) |
5433 | goto init_priv_mem_out; | 5532 | goto init_priv_mem_out; |
5533 | cfg->escan_info.escan_buf = kzalloc(BRCMF_ESCAN_BUF_SIZE, GFP_KERNEL); | ||
5534 | if (!cfg->escan_info.escan_buf) | ||
5535 | goto init_priv_mem_out; | ||
5434 | 5536 | ||
5435 | return 0; | 5537 | return 0; |
5436 | 5538 | ||
@@ -6120,19 +6222,18 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp) | |||
6120 | { | 6222 | { |
6121 | #ifdef CONFIG_PM | 6223 | #ifdef CONFIG_PM |
6122 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 6224 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
6123 | s32 err; | ||
6124 | u32 wowl_cap; | ||
6125 | 6225 | ||
6126 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) { | 6226 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) { |
6127 | err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap); | 6227 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) { |
6128 | if (!err) { | 6228 | brcmf_wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT; |
6129 | if (wowl_cap & BRCMF_WOWL_PFN_FOUND) { | 6229 | init_waitqueue_head(&cfg->wowl.nd_data_wait); |
6130 | brcmf_wowlan_support.flags |= | ||
6131 | WIPHY_WOWLAN_NET_DETECT; | ||
6132 | init_waitqueue_head(&cfg->wowl.nd_data_wait); | ||
6133 | } | ||
6134 | } | 6230 | } |
6135 | } | 6231 | } |
6232 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) { | ||
6233 | brcmf_wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY; | ||
6234 | brcmf_wowlan_support.flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE; | ||
6235 | } | ||
6236 | |||
6136 | wiphy->wowlan = &brcmf_wowlan_support; | 6237 | wiphy->wowlan = &brcmf_wowlan_support; |
6137 | #endif | 6238 | #endif |
6138 | } | 6239 | } |
@@ -6174,8 +6275,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) | |||
6174 | wiphy->n_addresses = i; | 6275 | wiphy->n_addresses = i; |
6175 | 6276 | ||
6176 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 6277 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
6177 | wiphy->cipher_suites = __wl_cipher_suites; | 6278 | wiphy->cipher_suites = brcmf_cipher_suites; |
6178 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | 6279 | wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites); |
6280 | if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) | ||
6281 | wiphy->n_cipher_suites--; | ||
6179 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | | 6282 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | |
6180 | WIPHY_FLAG_OFFCHAN_TX | | 6283 | WIPHY_FLAG_OFFCHAN_TX | |
6181 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 6284 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
@@ -6277,7 +6380,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
6277 | if (err) | 6380 | if (err) |
6278 | goto default_conf_out; | 6381 | goto default_conf_out; |
6279 | 6382 | ||
6280 | brcmf_configure_arp_offload(ifp, true); | 6383 | brcmf_configure_arp_nd_offload(ifp, true); |
6281 | 6384 | ||
6282 | cfg->dongle_up = true; | 6385 | cfg->dongle_up = true; |
6283 | default_conf_out: | 6386 | default_conf_out: |
@@ -6395,8 +6498,9 @@ bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg) | |||
6395 | 6498 | ||
6396 | return armed; | 6499 | return armed; |
6397 | } | 6500 | } |
6398 | int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, | 6501 | |
6399 | u8 action, ulong timeout) | 6502 | int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg, |
6503 | u8 action, ulong timeout) | ||
6400 | { | 6504 | { |
6401 | struct brcmf_cfg80211_vif_event *event = &cfg->vif_event; | 6505 | struct brcmf_cfg80211_vif_event *event = &cfg->vif_event; |
6402 | 6506 | ||
@@ -6404,28 +6508,85 @@ int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, | |||
6404 | vif_event_equals(event, action), timeout); | 6508 | vif_event_equals(event, action), timeout); |
6405 | } | 6509 | } |
6406 | 6510 | ||
6511 | static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], | ||
6512 | struct brcmf_fil_country_le *ccreq) | ||
6513 | { | ||
6514 | struct brcmfmac_pd_cc *country_codes; | ||
6515 | struct brcmfmac_pd_cc_entry *cc; | ||
6516 | s32 found_index; | ||
6517 | int i; | ||
6518 | |||
6519 | country_codes = drvr->settings->country_codes; | ||
6520 | if (!country_codes) { | ||
6521 | brcmf_dbg(TRACE, "No country codes configured for device\n"); | ||
6522 | return -EINVAL; | ||
6523 | } | ||
6524 | |||
6525 | if ((alpha2[0] == ccreq->country_abbrev[0]) && | ||
6526 | (alpha2[1] == ccreq->country_abbrev[1])) { | ||
6527 | brcmf_dbg(TRACE, "Country code already set\n"); | ||
6528 | return -EAGAIN; | ||
6529 | } | ||
6530 | |||
6531 | found_index = -1; | ||
6532 | for (i = 0; i < country_codes->table_size; i++) { | ||
6533 | cc = &country_codes->table[i]; | ||
6534 | if ((cc->iso3166[0] == '\0') && (found_index == -1)) | ||
6535 | found_index = i; | ||
6536 | if ((cc->iso3166[0] == alpha2[0]) && | ||
6537 | (cc->iso3166[1] == alpha2[1])) { | ||
6538 | found_index = i; | ||
6539 | break; | ||
6540 | } | ||
6541 | } | ||
6542 | if (found_index == -1) { | ||
6543 | brcmf_dbg(TRACE, "No country code match found\n"); | ||
6544 | return -EINVAL; | ||
6545 | } | ||
6546 | memset(ccreq, 0, sizeof(*ccreq)); | ||
6547 | ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); | ||
6548 | memcpy(ccreq->ccode, country_codes->table[found_index].cc, | ||
6549 | BRCMF_COUNTRY_BUF_SZ); | ||
6550 | ccreq->country_abbrev[0] = alpha2[0]; | ||
6551 | ccreq->country_abbrev[1] = alpha2[1]; | ||
6552 | ccreq->country_abbrev[2] = 0; | ||
6553 | |||
6554 | return 0; | ||
6555 | } | ||
6556 | |||
6407 | static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, | 6557 | static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, |
6408 | struct regulatory_request *req) | 6558 | struct regulatory_request *req) |
6409 | { | 6559 | { |
6410 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); | 6560 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); |
6411 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 6561 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
6412 | struct brcmf_fil_country_le ccreq; | 6562 | struct brcmf_fil_country_le ccreq; |
6563 | s32 err; | ||
6413 | int i; | 6564 | int i; |
6414 | 6565 | ||
6415 | brcmf_dbg(TRACE, "enter: initiator=%d, alpha=%c%c\n", req->initiator, | ||
6416 | req->alpha2[0], req->alpha2[1]); | ||
6417 | |||
6418 | /* ignore non-ISO3166 country codes */ | 6566 | /* ignore non-ISO3166 country codes */ |
6419 | for (i = 0; i < sizeof(req->alpha2); i++) | 6567 | for (i = 0; i < sizeof(req->alpha2); i++) |
6420 | if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { | 6568 | if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { |
6421 | brcmf_err("not a ISO3166 code\n"); | 6569 | brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n", |
6570 | req->alpha2[0], req->alpha2[1]); | ||
6422 | return; | 6571 | return; |
6423 | } | 6572 | } |
6424 | memset(&ccreq, 0, sizeof(ccreq)); | 6573 | |
6425 | ccreq.rev = cpu_to_le32(-1); | 6574 | brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator, |
6426 | memcpy(ccreq.ccode, req->alpha2, sizeof(req->alpha2)); | 6575 | req->alpha2[0], req->alpha2[1]); |
6427 | if (brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq))) { | 6576 | |
6428 | brcmf_err("firmware rejected country setting\n"); | 6577 | err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq)); |
6578 | if (err) { | ||
6579 | brcmf_err("Country code iovar returned err = %d\n", err); | ||
6580 | return; | ||
6581 | } | ||
6582 | |||
6583 | err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq); | ||
6584 | if (err) | ||
6585 | return; | ||
6586 | |||
6587 | err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq)); | ||
6588 | if (err) { | ||
6589 | brcmf_err("Firmware rejected country setting\n"); | ||
6429 | return; | 6590 | return; |
6430 | } | 6591 | } |
6431 | brcmf_setup_wiphybands(wiphy); | 6592 | brcmf_setup_wiphybands(wiphy); |
@@ -6461,6 +6622,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
6461 | struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; | 6622 | struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; |
6462 | struct brcmf_cfg80211_info *cfg; | 6623 | struct brcmf_cfg80211_info *cfg; |
6463 | struct wiphy *wiphy; | 6624 | struct wiphy *wiphy; |
6625 | struct cfg80211_ops *ops; | ||
6464 | struct brcmf_cfg80211_vif *vif; | 6626 | struct brcmf_cfg80211_vif *vif; |
6465 | struct brcmf_if *ifp; | 6627 | struct brcmf_if *ifp; |
6466 | s32 err = 0; | 6628 | s32 err = 0; |
@@ -6472,8 +6634,17 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
6472 | return NULL; | 6634 | return NULL; |
6473 | } | 6635 | } |
6474 | 6636 | ||
6637 | ops = kzalloc(sizeof(*ops), GFP_KERNEL); | ||
6638 | if (!ops) | ||
6639 | return NULL; | ||
6640 | |||
6641 | memcpy(ops, &brcmf_cfg80211_ops, sizeof(*ops)); | ||
6475 | ifp = netdev_priv(ndev); | 6642 | ifp = netdev_priv(ndev); |
6476 | wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info)); | 6643 | #ifdef CONFIG_PM |
6644 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) | ||
6645 | ops->set_rekey_data = brcmf_cfg80211_set_rekey_data; | ||
6646 | #endif | ||
6647 | wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info)); | ||
6477 | if (!wiphy) { | 6648 | if (!wiphy) { |
6478 | brcmf_err("Could not allocate wiphy device\n"); | 6649 | brcmf_err("Could not allocate wiphy device\n"); |
6479 | return NULL; | 6650 | return NULL; |
@@ -6483,6 +6654,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
6483 | 6654 | ||
6484 | cfg = wiphy_priv(wiphy); | 6655 | cfg = wiphy_priv(wiphy); |
6485 | cfg->wiphy = wiphy; | 6656 | cfg->wiphy = wiphy; |
6657 | cfg->ops = ops; | ||
6486 | cfg->pub = drvr; | 6658 | cfg->pub = drvr; |
6487 | init_vif_event(&cfg->vif_event); | 6659 | init_vif_event(&cfg->vif_event); |
6488 | INIT_LIST_HEAD(&cfg->vif_list); | 6660 | INIT_LIST_HEAD(&cfg->vif_list); |
@@ -6593,7 +6765,8 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
6593 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_RANDOM_MAC)) { | 6765 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_RANDOM_MAC)) { |
6594 | wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; | 6766 | wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; |
6595 | #ifdef CONFIG_PM | 6767 | #ifdef CONFIG_PM |
6596 | if (wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT) | 6768 | if (wiphy->wowlan && |
6769 | wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT) | ||
6597 | wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR; | 6770 | wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR; |
6598 | #endif | 6771 | #endif |
6599 | } | 6772 | } |
@@ -6608,6 +6781,7 @@ priv_out: | |||
6608 | ifp->vif = NULL; | 6781 | ifp->vif = NULL; |
6609 | wiphy_out: | 6782 | wiphy_out: |
6610 | brcmf_free_wiphy(wiphy); | 6783 | brcmf_free_wiphy(wiphy); |
6784 | kfree(ops); | ||
6611 | return NULL; | 6785 | return NULL; |
6612 | } | 6786 | } |
6613 | 6787 | ||
@@ -6618,6 +6792,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | |||
6618 | 6792 | ||
6619 | brcmf_btcoex_detach(cfg); | 6793 | brcmf_btcoex_detach(cfg); |
6620 | wiphy_unregister(cfg->wiphy); | 6794 | wiphy_unregister(cfg->wiphy); |
6795 | kfree(cfg->ops); | ||
6621 | wl_deinit_priv(cfg); | 6796 | wl_deinit_priv(cfg); |
6622 | brcmf_free_wiphy(cfg->wiphy); | 6797 | brcmf_free_wiphy(cfg->wiphy); |
6623 | } | 6798 | } |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 40efb539ac26..95e35bcc16ce 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h | |||
@@ -28,8 +28,11 @@ | |||
28 | #define WL_ROAM_TRIGGER_LEVEL -75 | 28 | #define WL_ROAM_TRIGGER_LEVEL -75 |
29 | #define WL_ROAM_DELTA 20 | 29 | #define WL_ROAM_DELTA 20 |
30 | 30 | ||
31 | #define WL_ESCAN_BUF_SIZE (1024 * 64) | 31 | /* Keep BRCMF_ESCAN_BUF_SIZE below 64K (65536). Allocing over 64K can be |
32 | #define WL_ESCAN_TIMER_INTERVAL_MS 10000 /* E-Scan timeout */ | 32 | * problematic on some systems and should be avoided. |
33 | */ | ||
34 | #define BRCMF_ESCAN_BUF_SIZE 65000 | ||
35 | #define BRCMF_ESCAN_TIMER_INTERVAL_MS 10000 /* E-Scan timeout */ | ||
33 | 36 | ||
34 | #define WL_ESCAN_ACTION_START 1 | 37 | #define WL_ESCAN_ACTION_START 1 |
35 | #define WL_ESCAN_ACTION_CONTINUE 2 | 38 | #define WL_ESCAN_ACTION_CONTINUE 2 |
@@ -69,7 +72,7 @@ | |||
69 | 72 | ||
70 | #define BRCMF_VNDR_IE_P2PAF_SHIFT 12 | 73 | #define BRCMF_VNDR_IE_P2PAF_SHIFT 12 |
71 | 74 | ||
72 | #define BRCMF_MAX_DEFAULT_KEYS 4 | 75 | #define BRCMF_MAX_DEFAULT_KEYS 6 |
73 | 76 | ||
74 | /* beacon loss timeout defaults */ | 77 | /* beacon loss timeout defaults */ |
75 | #define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON 2 | 78 | #define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON 2 |
@@ -104,7 +107,6 @@ struct brcmf_cfg80211_security { | |||
104 | u32 auth_type; | 107 | u32 auth_type; |
105 | u32 cipher_pairwise; | 108 | u32 cipher_pairwise; |
106 | u32 cipher_group; | 109 | u32 cipher_group; |
107 | u32 wpa_auth; | ||
108 | }; | 110 | }; |
109 | 111 | ||
110 | /** | 112 | /** |
@@ -205,7 +207,7 @@ enum wl_escan_state { | |||
205 | 207 | ||
206 | struct escan_info { | 208 | struct escan_info { |
207 | u32 escan_state; | 209 | u32 escan_state; |
208 | u8 escan_buf[WL_ESCAN_BUF_SIZE]; | 210 | u8 *escan_buf; |
209 | struct wiphy *wiphy; | 211 | struct wiphy *wiphy; |
210 | struct brcmf_if *ifp; | 212 | struct brcmf_if *ifp; |
211 | s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, | 213 | s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, |
@@ -253,6 +255,7 @@ struct brcmf_cfg80211_wowl { | |||
253 | * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface | 255 | * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface |
254 | * | 256 | * |
255 | * @wiphy: wiphy object for cfg80211 interface. | 257 | * @wiphy: wiphy object for cfg80211 interface. |
258 | * @ops: pointer to copy of ops as registered with wiphy object. | ||
256 | * @conf: dongle configuration. | 259 | * @conf: dongle configuration. |
257 | * @p2p: peer-to-peer specific information. | 260 | * @p2p: peer-to-peer specific information. |
258 | * @btcoex: Bluetooth coexistence information. | 261 | * @btcoex: Bluetooth coexistence information. |
@@ -278,7 +281,6 @@ struct brcmf_cfg80211_wowl { | |||
278 | * @escan_info: escan information. | 281 | * @escan_info: escan information. |
279 | * @escan_timeout: Timer for catch scan timeout. | 282 | * @escan_timeout: Timer for catch scan timeout. |
280 | * @escan_timeout_work: scan timeout worker. | 283 | * @escan_timeout_work: scan timeout worker. |
281 | * @escan_ioctl_buf: dongle command buffer for escan commands. | ||
282 | * @vif_list: linked list of vif instances. | 284 | * @vif_list: linked list of vif instances. |
283 | * @vif_cnt: number of vif instances. | 285 | * @vif_cnt: number of vif instances. |
284 | * @vif_event: vif event signalling. | 286 | * @vif_event: vif event signalling. |
@@ -286,6 +288,7 @@ struct brcmf_cfg80211_wowl { | |||
286 | */ | 288 | */ |
287 | struct brcmf_cfg80211_info { | 289 | struct brcmf_cfg80211_info { |
288 | struct wiphy *wiphy; | 290 | struct wiphy *wiphy; |
291 | struct cfg80211_ops *ops; | ||
289 | struct brcmf_cfg80211_conf *conf; | 292 | struct brcmf_cfg80211_conf *conf; |
290 | struct brcmf_p2p_info p2p; | 293 | struct brcmf_p2p_info p2p; |
291 | struct brcmf_btcoex_info *btcoex; | 294 | struct brcmf_btcoex_info *btcoex; |
@@ -309,7 +312,6 @@ struct brcmf_cfg80211_info { | |||
309 | struct escan_info escan_info; | 312 | struct escan_info escan_info; |
310 | struct timer_list escan_timeout; | 313 | struct timer_list escan_timeout; |
311 | struct work_struct escan_timeout_work; | 314 | struct work_struct escan_timeout_work; |
312 | u8 *escan_ioctl_buf; | ||
313 | struct list_head vif_list; | 315 | struct list_head vif_list; |
314 | struct brcmf_cfg80211_vif_event vif_event; | 316 | struct brcmf_cfg80211_vif_event vif_event; |
315 | struct completion vif_disabled; | 317 | struct completion vif_disabled; |
@@ -402,8 +404,8 @@ bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, | |||
402 | void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, | 404 | void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, |
403 | struct brcmf_cfg80211_vif *vif); | 405 | struct brcmf_cfg80211_vif *vif); |
404 | bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); | 406 | bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); |
405 | int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, | 407 | int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg, |
406 | u8 action, ulong timeout); | 408 | u8 action, ulong timeout); |
407 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | 409 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, |
408 | struct brcmf_if *ifp, bool aborted, | 410 | struct brcmf_if *ifp, bool aborted, |
409 | bool fw_abort); | 411 | bool fw_abort); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index cfee477a6eb1..9e909e3c2f0c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | |||
@@ -27,6 +27,11 @@ | |||
27 | #include "fwil_types.h" | 27 | #include "fwil_types.h" |
28 | #include "tracepoint.h" | 28 | #include "tracepoint.h" |
29 | #include "common.h" | 29 | #include "common.h" |
30 | #include "of.h" | ||
31 | |||
32 | MODULE_AUTHOR("Broadcom Corporation"); | ||
33 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); | ||
34 | MODULE_LICENSE("Dual BSD/GPL"); | ||
30 | 35 | ||
31 | const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 36 | const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
32 | 37 | ||
@@ -75,6 +80,7 @@ module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0); | |||
75 | MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging"); | 80 | MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging"); |
76 | #endif | 81 | #endif |
77 | 82 | ||
83 | static struct brcmfmac_platform_data *brcmfmac_pdata; | ||
78 | struct brcmf_mp_global_t brcmf_mp_global; | 84 | struct brcmf_mp_global_t brcmf_mp_global; |
79 | 85 | ||
80 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | 86 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) |
@@ -221,33 +227,147 @@ void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) | |||
221 | } | 227 | } |
222 | #endif | 228 | #endif |
223 | 229 | ||
224 | void brcmf_mp_attach(void) | 230 | static void brcmf_mp_attach(void) |
225 | { | 231 | { |
232 | /* If module param firmware path is set then this will always be used, | ||
233 | * if not set then if available use the platform data version. To make | ||
234 | * sure it gets initialized at all, always copy the module param version | ||
235 | */ | ||
226 | strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path, | 236 | strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path, |
227 | BRCMF_FW_ALTPATH_LEN); | 237 | BRCMF_FW_ALTPATH_LEN); |
238 | if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) && | ||
239 | (brcmf_mp_global.firmware_path[0] == '\0')) { | ||
240 | strlcpy(brcmf_mp_global.firmware_path, | ||
241 | brcmfmac_pdata->fw_alternative_path, | ||
242 | BRCMF_FW_ALTPATH_LEN); | ||
243 | } | ||
228 | } | 244 | } |
229 | 245 | ||
230 | int brcmf_mp_device_attach(struct brcmf_pub *drvr) | 246 | struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, |
247 | enum brcmf_bus_type bus_type, | ||
248 | u32 chip, u32 chiprev) | ||
231 | { | 249 | { |
232 | drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC); | 250 | struct brcmf_mp_device *settings; |
233 | if (!drvr->settings) { | 251 | struct brcmfmac_pd_device *device_pd; |
234 | brcmf_err("Failed to alloca storage space for settings\n"); | 252 | bool found; |
235 | return -ENOMEM; | 253 | int i; |
236 | } | 254 | |
237 | 255 | brcmf_dbg(INFO, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type, chip, | |
238 | drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz; | 256 | chiprev); |
239 | drvr->settings->p2p_enable = !!brcmf_p2p_enable; | 257 | settings = kzalloc(sizeof(*settings), GFP_ATOMIC); |
240 | drvr->settings->feature_disable = brcmf_feature_disable; | 258 | if (!settings) |
241 | drvr->settings->fcmode = brcmf_fcmode; | 259 | return NULL; |
242 | drvr->settings->roamoff = !!brcmf_roamoff; | 260 | |
261 | /* start by using the module paramaters */ | ||
262 | settings->p2p_enable = !!brcmf_p2p_enable; | ||
263 | settings->feature_disable = brcmf_feature_disable; | ||
264 | settings->fcmode = brcmf_fcmode; | ||
265 | settings->roamoff = !!brcmf_roamoff; | ||
243 | #ifdef DEBUG | 266 | #ifdef DEBUG |
244 | drvr->settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; | 267 | settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; |
245 | #endif | 268 | #endif |
269 | |||
270 | if (bus_type == BRCMF_BUSTYPE_SDIO) | ||
271 | settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz; | ||
272 | |||
273 | /* See if there is any device specific platform data configured */ | ||
274 | found = false; | ||
275 | if (brcmfmac_pdata) { | ||
276 | for (i = 0; i < brcmfmac_pdata->device_count; i++) { | ||
277 | device_pd = &brcmfmac_pdata->devices[i]; | ||
278 | if ((device_pd->bus_type == bus_type) && | ||
279 | (device_pd->id == chip) && | ||
280 | ((device_pd->rev == chiprev) || | ||
281 | (device_pd->rev == -1))) { | ||
282 | brcmf_dbg(INFO, "Platform data for device found\n"); | ||
283 | settings->country_codes = | ||
284 | device_pd->country_codes; | ||
285 | if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO) | ||
286 | memcpy(&settings->bus.sdio, | ||
287 | &device_pd->bus.sdio, | ||
288 | sizeof(settings->bus.sdio)); | ||
289 | found = true; | ||
290 | break; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | if ((bus_type == BRCMF_BUSTYPE_SDIO) && (!found)) { | ||
295 | /* No platform data for this device. In case of SDIO try OF | ||
296 | * (Open Firwmare) Device Tree. | ||
297 | */ | ||
298 | brcmf_of_probe(dev, &settings->bus.sdio); | ||
299 | } | ||
300 | return settings; | ||
301 | } | ||
302 | |||
303 | void brcmf_release_module_param(struct brcmf_mp_device *module_param) | ||
304 | { | ||
305 | kfree(module_param); | ||
306 | } | ||
307 | |||
308 | static int __init brcmf_common_pd_probe(struct platform_device *pdev) | ||
309 | { | ||
310 | brcmf_dbg(INFO, "Enter\n"); | ||
311 | |||
312 | brcmfmac_pdata = dev_get_platdata(&pdev->dev); | ||
313 | |||
314 | if (brcmfmac_pdata->power_on) | ||
315 | brcmfmac_pdata->power_on(); | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int brcmf_common_pd_remove(struct platform_device *pdev) | ||
321 | { | ||
322 | brcmf_dbg(INFO, "Enter\n"); | ||
323 | |||
324 | if (brcmfmac_pdata->power_off) | ||
325 | brcmfmac_pdata->power_off(); | ||
326 | |||
246 | return 0; | 327 | return 0; |
247 | } | 328 | } |
248 | 329 | ||
249 | void brcmf_mp_device_detach(struct brcmf_pub *drvr) | 330 | static struct platform_driver brcmf_pd = { |
331 | .remove = brcmf_common_pd_remove, | ||
332 | .driver = { | ||
333 | .name = BRCMFMAC_PDATA_NAME, | ||
334 | } | ||
335 | }; | ||
336 | |||
337 | static int __init brcmfmac_module_init(void) | ||
338 | { | ||
339 | int err; | ||
340 | |||
341 | /* Initialize debug system first */ | ||
342 | brcmf_debugfs_init(); | ||
343 | |||
344 | /* Get the platform data (if available) for our devices */ | ||
345 | err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe); | ||
346 | if (err == -ENODEV) | ||
347 | brcmf_dbg(INFO, "No platform data available.\n"); | ||
348 | |||
349 | /* Initialize global module paramaters */ | ||
350 | brcmf_mp_attach(); | ||
351 | |||
352 | /* Continue the initialization by registering the different busses */ | ||
353 | err = brcmf_core_init(); | ||
354 | if (err) { | ||
355 | brcmf_debugfs_exit(); | ||
356 | if (brcmfmac_pdata) | ||
357 | platform_driver_unregister(&brcmf_pd); | ||
358 | } | ||
359 | |||
360 | return err; | ||
361 | } | ||
362 | |||
363 | static void __exit brcmfmac_module_exit(void) | ||
250 | { | 364 | { |
251 | kfree(drvr->settings); | 365 | brcmf_core_exit(); |
366 | if (brcmfmac_pdata) | ||
367 | platform_driver_unregister(&brcmf_pd); | ||
368 | brcmf_debugfs_exit(); | ||
252 | } | 369 | } |
253 | 370 | ||
371 | module_init(brcmfmac_module_init); | ||
372 | module_exit(brcmfmac_module_exit); | ||
373 | |||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index 3b0a63b98e99..bd095abca393 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h | |||
@@ -15,6 +15,10 @@ | |||
15 | #ifndef BRCMFMAC_COMMON_H | 15 | #ifndef BRCMFMAC_COMMON_H |
16 | #define BRCMFMAC_COMMON_H | 16 | #define BRCMFMAC_COMMON_H |
17 | 17 | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/platform_data/brcmfmac.h> | ||
20 | #include "fwil_types.h" | ||
21 | |||
18 | extern const u8 ALLFFMAC[ETH_ALEN]; | 22 | extern const u8 ALLFFMAC[ETH_ALEN]; |
19 | 23 | ||
20 | #define BRCMF_FW_ALTPATH_LEN 256 | 24 | #define BRCMF_FW_ALTPATH_LEN 256 |
@@ -41,37 +45,30 @@ extern struct brcmf_mp_global_t brcmf_mp_global; | |||
41 | /** | 45 | /** |
42 | * struct brcmf_mp_device - Device module paramaters. | 46 | * struct brcmf_mp_device - Device module paramaters. |
43 | * | 47 | * |
44 | * @sdiod_txglomsz: SDIO txglom size. | ||
45 | * @joinboost_5g_rssi: 5g rssi booost for preferred join selection. | ||
46 | * @p2p_enable: Legacy P2P0 enable (old wpa_supplicant). | 48 | * @p2p_enable: Legacy P2P0 enable (old wpa_supplicant). |
47 | * @feature_disable: Feature_disable bitmask. | 49 | * @feature_disable: Feature_disable bitmask. |
48 | * @fcmode: FWS flow control. | 50 | * @fcmode: FWS flow control. |
49 | * @roamoff: Firmware roaming off? | 51 | * @roamoff: Firmware roaming off? |
52 | * @ignore_probe_fail: Ignore probe failure. | ||
53 | * @country_codes: If available, pointer to struct for translating country codes | ||
54 | * @bus: Bus specific platform data. Only SDIO at the mmoment. | ||
50 | */ | 55 | */ |
51 | struct brcmf_mp_device { | 56 | struct brcmf_mp_device { |
52 | int sdiod_txglomsz; | 57 | bool p2p_enable; |
53 | int joinboost_5g_rssi; | 58 | unsigned int feature_disable; |
54 | bool p2p_enable; | 59 | int fcmode; |
55 | int feature_disable; | 60 | bool roamoff; |
56 | int fcmode; | 61 | bool ignore_probe_fail; |
57 | bool roamoff; | 62 | struct brcmfmac_pd_cc *country_codes; |
58 | bool ignore_probe_fail; | 63 | union { |
64 | struct brcmfmac_sdio_pd sdio; | ||
65 | } bus; | ||
59 | }; | 66 | }; |
60 | 67 | ||
61 | void brcmf_mp_attach(void); | 68 | struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, |
62 | int brcmf_mp_device_attach(struct brcmf_pub *drvr); | 69 | enum brcmf_bus_type bus_type, |
63 | void brcmf_mp_device_detach(struct brcmf_pub *drvr); | 70 | u32 chip, u32 chiprev); |
64 | #ifdef DEBUG | 71 | void brcmf_release_module_param(struct brcmf_mp_device *module_param); |
65 | static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr) | ||
66 | { | ||
67 | return drvr->settings->ignore_probe_fail; | ||
68 | } | ||
69 | #else | ||
70 | static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr) | ||
71 | { | ||
72 | return false; | ||
73 | } | ||
74 | #endif | ||
75 | 72 | ||
76 | /* Sets dongle media info (drv_version, mac address). */ | 73 | /* Sets dongle media info (drv_version, mac address). */ |
77 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); | 74 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index ed9998b69709..ff825cd7739e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/inetdevice.h> | 20 | #include <linux/inetdevice.h> |
21 | #include <net/cfg80211.h> | 21 | #include <net/cfg80211.h> |
22 | #include <net/rtnetlink.h> | 22 | #include <net/rtnetlink.h> |
23 | #include <net/addrconf.h> | ||
24 | #include <net/ipv6.h> | ||
23 | #include <brcmu_utils.h> | 25 | #include <brcmu_utils.h> |
24 | #include <brcmu_wifi.h> | 26 | #include <brcmu_wifi.h> |
25 | 27 | ||
@@ -36,11 +38,7 @@ | |||
36 | #include "pcie.h" | 38 | #include "pcie.h" |
37 | #include "common.h" | 39 | #include "common.h" |
38 | 40 | ||
39 | MODULE_AUTHOR("Broadcom Corporation"); | 41 | #define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950) |
40 | MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); | ||
41 | MODULE_LICENSE("Dual BSD/GPL"); | ||
42 | |||
43 | #define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(50) | ||
44 | 42 | ||
45 | /* AMPDU rx reordering definitions */ | 43 | /* AMPDU rx reordering definitions */ |
46 | #define BRCMF_RXREORDER_FLOWID_OFFSET 0 | 44 | #define BRCMF_RXREORDER_FLOWID_OFFSET 0 |
@@ -172,6 +170,35 @@ _brcmf_set_mac_address(struct work_struct *work) | |||
172 | } | 170 | } |
173 | } | 171 | } |
174 | 172 | ||
173 | #if IS_ENABLED(CONFIG_IPV6) | ||
174 | static void _brcmf_update_ndtable(struct work_struct *work) | ||
175 | { | ||
176 | struct brcmf_if *ifp; | ||
177 | int i, ret; | ||
178 | |||
179 | ifp = container_of(work, struct brcmf_if, ndoffload_work); | ||
180 | |||
181 | /* clear the table in firmware */ | ||
182 | ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip_clear", NULL, 0); | ||
183 | if (ret) { | ||
184 | brcmf_dbg(TRACE, "fail to clear nd ip table err:%d\n", ret); | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | for (i = 0; i < ifp->ipv6addr_idx; i++) { | ||
189 | ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip", | ||
190 | &ifp->ipv6_addr_tbl[i], | ||
191 | sizeof(struct in6_addr)); | ||
192 | if (ret) | ||
193 | brcmf_err("add nd ip err %d\n", ret); | ||
194 | } | ||
195 | } | ||
196 | #else | ||
197 | static void _brcmf_update_ndtable(struct work_struct *work) | ||
198 | { | ||
199 | } | ||
200 | #endif | ||
201 | |||
175 | static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) | 202 | static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) |
176 | { | 203 | { |
177 | struct brcmf_if *ifp = netdev_priv(ndev); | 204 | struct brcmf_if *ifp = netdev_priv(ndev); |
@@ -685,6 +712,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) | |||
685 | 712 | ||
686 | INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address); | 713 | INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address); |
687 | INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list); | 714 | INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list); |
715 | INIT_WORK(&ifp->ndoffload_work, _brcmf_update_ndtable); | ||
688 | 716 | ||
689 | if (rtnl_locked) | 717 | if (rtnl_locked) |
690 | err = register_netdevice(ndev); | 718 | err = register_netdevice(ndev); |
@@ -884,6 +912,7 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx) | |||
884 | if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { | 912 | if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { |
885 | cancel_work_sync(&ifp->setmacaddr_work); | 913 | cancel_work_sync(&ifp->setmacaddr_work); |
886 | cancel_work_sync(&ifp->multicast_work); | 914 | cancel_work_sync(&ifp->multicast_work); |
915 | cancel_work_sync(&ifp->ndoffload_work); | ||
887 | } | 916 | } |
888 | brcmf_net_detach(ifp->ndev); | 917 | brcmf_net_detach(ifp->ndev); |
889 | } else { | 918 | } else { |
@@ -1006,14 +1035,14 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, | |||
1006 | return NOTIFY_OK; | 1035 | return NOTIFY_OK; |
1007 | } | 1036 | } |
1008 | for (i = 0; i < ARPOL_MAX_ENTRIES; i++) { | 1037 | for (i = 0; i < ARPOL_MAX_ENTRIES; i++) { |
1009 | if (addr_table[i] != 0) { | 1038 | if (addr_table[i] == 0) |
1010 | brcmf_fil_iovar_data_set(ifp, | 1039 | continue; |
1011 | "arp_hostip", &addr_table[i], | 1040 | ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", |
1012 | sizeof(addr_table[i])); | 1041 | &addr_table[i], |
1013 | if (ret) | 1042 | sizeof(addr_table[i])); |
1014 | brcmf_err("add arp ip err %d\n", | 1043 | if (ret) |
1015 | ret); | 1044 | brcmf_err("add arp ip err %d\n", |
1016 | } | 1045 | ret); |
1017 | } | 1046 | } |
1018 | } | 1047 | } |
1019 | break; | 1048 | break; |
@@ -1025,7 +1054,57 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, | |||
1025 | } | 1054 | } |
1026 | #endif | 1055 | #endif |
1027 | 1056 | ||
1028 | int brcmf_attach(struct device *dev) | 1057 | #if IS_ENABLED(CONFIG_IPV6) |
1058 | static int brcmf_inet6addr_changed(struct notifier_block *nb, | ||
1059 | unsigned long action, void *data) | ||
1060 | { | ||
1061 | struct brcmf_pub *drvr = container_of(nb, struct brcmf_pub, | ||
1062 | inet6addr_notifier); | ||
1063 | struct inet6_ifaddr *ifa = data; | ||
1064 | struct brcmf_if *ifp; | ||
1065 | int i; | ||
1066 | struct in6_addr *table; | ||
1067 | |||
1068 | /* Only handle primary interface */ | ||
1069 | ifp = drvr->iflist[0]; | ||
1070 | if (!ifp) | ||
1071 | return NOTIFY_DONE; | ||
1072 | if (ifp->ndev != ifa->idev->dev) | ||
1073 | return NOTIFY_DONE; | ||
1074 | |||
1075 | table = ifp->ipv6_addr_tbl; | ||
1076 | for (i = 0; i < NDOL_MAX_ENTRIES; i++) | ||
1077 | if (ipv6_addr_equal(&ifa->addr, &table[i])) | ||
1078 | break; | ||
1079 | |||
1080 | switch (action) { | ||
1081 | case NETDEV_UP: | ||
1082 | if (i == NDOL_MAX_ENTRIES) { | ||
1083 | if (ifp->ipv6addr_idx < NDOL_MAX_ENTRIES) { | ||
1084 | table[ifp->ipv6addr_idx++] = ifa->addr; | ||
1085 | } else { | ||
1086 | for (i = 0; i < NDOL_MAX_ENTRIES - 1; i++) | ||
1087 | table[i] = table[i + 1]; | ||
1088 | table[NDOL_MAX_ENTRIES - 1] = ifa->addr; | ||
1089 | } | ||
1090 | } | ||
1091 | break; | ||
1092 | case NETDEV_DOWN: | ||
1093 | if (i < NDOL_MAX_ENTRIES) | ||
1094 | for (; i < ifp->ipv6addr_idx; i++) | ||
1095 | table[i] = table[i + 1]; | ||
1096 | break; | ||
1097 | default: | ||
1098 | break; | ||
1099 | } | ||
1100 | |||
1101 | schedule_work(&ifp->ndoffload_work); | ||
1102 | |||
1103 | return NOTIFY_OK; | ||
1104 | } | ||
1105 | #endif | ||
1106 | |||
1107 | int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings) | ||
1029 | { | 1108 | { |
1030 | struct brcmf_pub *drvr = NULL; | 1109 | struct brcmf_pub *drvr = NULL; |
1031 | int ret = 0; | 1110 | int ret = 0; |
@@ -1047,10 +1126,7 @@ int brcmf_attach(struct device *dev) | |||
1047 | drvr->hdrlen = 0; | 1126 | drvr->hdrlen = 0; |
1048 | drvr->bus_if = dev_get_drvdata(dev); | 1127 | drvr->bus_if = dev_get_drvdata(dev); |
1049 | drvr->bus_if->drvr = drvr; | 1128 | drvr->bus_if->drvr = drvr; |
1050 | 1129 | drvr->settings = settings; | |
1051 | /* Initialize device specific settings */ | ||
1052 | if (brcmf_mp_device_attach(drvr)) | ||
1053 | goto fail; | ||
1054 | 1130 | ||
1055 | /* attach debug facilities */ | 1131 | /* attach debug facilities */ |
1056 | brcmf_debug_attach(drvr); | 1132 | brcmf_debug_attach(drvr); |
@@ -1164,30 +1240,41 @@ int brcmf_bus_start(struct device *dev) | |||
1164 | #ifdef CONFIG_INET | 1240 | #ifdef CONFIG_INET |
1165 | drvr->inetaddr_notifier.notifier_call = brcmf_inetaddr_changed; | 1241 | drvr->inetaddr_notifier.notifier_call = brcmf_inetaddr_changed; |
1166 | ret = register_inetaddr_notifier(&drvr->inetaddr_notifier); | 1242 | ret = register_inetaddr_notifier(&drvr->inetaddr_notifier); |
1243 | if (ret) | ||
1244 | goto fail; | ||
1245 | |||
1246 | #if IS_ENABLED(CONFIG_IPV6) | ||
1247 | drvr->inet6addr_notifier.notifier_call = brcmf_inet6addr_changed; | ||
1248 | ret = register_inet6addr_notifier(&drvr->inet6addr_notifier); | ||
1249 | if (ret) { | ||
1250 | unregister_inetaddr_notifier(&drvr->inetaddr_notifier); | ||
1251 | goto fail; | ||
1252 | } | ||
1167 | #endif | 1253 | #endif |
1254 | #endif /* CONFIG_INET */ | ||
1255 | |||
1256 | return 0; | ||
1168 | 1257 | ||
1169 | fail: | 1258 | fail: |
1170 | if (ret < 0) { | 1259 | brcmf_err("failed: %d\n", ret); |
1171 | brcmf_err("failed: %d\n", ret); | 1260 | if (drvr->config) { |
1172 | if (drvr->config) { | 1261 | brcmf_cfg80211_detach(drvr->config); |
1173 | brcmf_cfg80211_detach(drvr->config); | 1262 | drvr->config = NULL; |
1174 | drvr->config = NULL; | ||
1175 | } | ||
1176 | if (drvr->fws) { | ||
1177 | brcmf_fws_del_interface(ifp); | ||
1178 | brcmf_fws_deinit(drvr); | ||
1179 | } | ||
1180 | if (ifp) | ||
1181 | brcmf_net_detach(ifp->ndev); | ||
1182 | if (p2p_ifp) | ||
1183 | brcmf_net_detach(p2p_ifp->ndev); | ||
1184 | drvr->iflist[0] = NULL; | ||
1185 | drvr->iflist[1] = NULL; | ||
1186 | if (brcmf_ignoring_probe_fail(drvr)) | ||
1187 | ret = 0; | ||
1188 | return ret; | ||
1189 | } | 1263 | } |
1190 | return 0; | 1264 | if (drvr->fws) { |
1265 | brcmf_fws_del_interface(ifp); | ||
1266 | brcmf_fws_deinit(drvr); | ||
1267 | } | ||
1268 | if (ifp) | ||
1269 | brcmf_net_detach(ifp->ndev); | ||
1270 | if (p2p_ifp) | ||
1271 | brcmf_net_detach(p2p_ifp->ndev); | ||
1272 | drvr->iflist[0] = NULL; | ||
1273 | drvr->iflist[1] = NULL; | ||
1274 | if (drvr->settings->ignore_probe_fail) | ||
1275 | ret = 0; | ||
1276 | |||
1277 | return ret; | ||
1191 | } | 1278 | } |
1192 | 1279 | ||
1193 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len) | 1280 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len) |
@@ -1237,6 +1324,10 @@ void brcmf_detach(struct device *dev) | |||
1237 | unregister_inetaddr_notifier(&drvr->inetaddr_notifier); | 1324 | unregister_inetaddr_notifier(&drvr->inetaddr_notifier); |
1238 | #endif | 1325 | #endif |
1239 | 1326 | ||
1327 | #if IS_ENABLED(CONFIG_IPV6) | ||
1328 | unregister_inet6addr_notifier(&drvr->inet6addr_notifier); | ||
1329 | #endif | ||
1330 | |||
1240 | /* stop firmware event handling */ | 1331 | /* stop firmware event handling */ |
1241 | brcmf_fweh_detach(drvr); | 1332 | brcmf_fweh_detach(drvr); |
1242 | if (drvr->config) | 1333 | if (drvr->config) |
@@ -1256,8 +1347,6 @@ void brcmf_detach(struct device *dev) | |||
1256 | 1347 | ||
1257 | brcmf_proto_detach(drvr); | 1348 | brcmf_proto_detach(drvr); |
1258 | 1349 | ||
1259 | brcmf_mp_device_detach(drvr); | ||
1260 | |||
1261 | brcmf_debug_detach(drvr); | 1350 | brcmf_debug_detach(drvr); |
1262 | bus_if->drvr = NULL; | 1351 | bus_if->drvr = NULL; |
1263 | kfree(drvr); | 1352 | kfree(drvr); |
@@ -1324,19 +1413,15 @@ static void brcmf_driver_register(struct work_struct *work) | |||
1324 | } | 1413 | } |
1325 | static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register); | 1414 | static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register); |
1326 | 1415 | ||
1327 | static int __init brcmfmac_module_init(void) | 1416 | int __init brcmf_core_init(void) |
1328 | { | 1417 | { |
1329 | brcmf_debugfs_init(); | ||
1330 | #ifdef CONFIG_BRCMFMAC_SDIO | ||
1331 | brcmf_sdio_init(); | ||
1332 | #endif | ||
1333 | if (!schedule_work(&brcmf_driver_work)) | 1418 | if (!schedule_work(&brcmf_driver_work)) |
1334 | return -EBUSY; | 1419 | return -EBUSY; |
1335 | 1420 | ||
1336 | return 0; | 1421 | return 0; |
1337 | } | 1422 | } |
1338 | 1423 | ||
1339 | static void __exit brcmfmac_module_exit(void) | 1424 | void __exit brcmf_core_exit(void) |
1340 | { | 1425 | { |
1341 | cancel_work_sync(&brcmf_driver_work); | 1426 | cancel_work_sync(&brcmf_driver_work); |
1342 | 1427 | ||
@@ -1349,8 +1434,5 @@ static void __exit brcmfmac_module_exit(void) | |||
1349 | #ifdef CONFIG_BRCMFMAC_PCIE | 1434 | #ifdef CONFIG_BRCMFMAC_PCIE |
1350 | brcmf_pcie_exit(); | 1435 | brcmf_pcie_exit(); |
1351 | #endif | 1436 | #endif |
1352 | brcmf_debugfs_exit(); | ||
1353 | } | 1437 | } |
1354 | 1438 | ||
1355 | module_init(brcmfmac_module_init); | ||
1356 | module_exit(brcmfmac_module_exit); | ||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 8f39435f976f..7bdb6fef99c3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | |||
@@ -48,6 +48,8 @@ | |||
48 | */ | 48 | */ |
49 | #define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32 | 49 | #define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32 |
50 | 50 | ||
51 | #define NDOL_MAX_ENTRIES 8 | ||
52 | |||
51 | /** | 53 | /** |
52 | * struct brcmf_ampdu_rx_reorder - AMPDU receive reorder info | 54 | * struct brcmf_ampdu_rx_reorder - AMPDU receive reorder info |
53 | * | 55 | * |
@@ -143,6 +145,7 @@ struct brcmf_pub { | |||
143 | #endif | 145 | #endif |
144 | 146 | ||
145 | struct notifier_block inetaddr_notifier; | 147 | struct notifier_block inetaddr_notifier; |
148 | struct notifier_block inet6addr_notifier; | ||
146 | struct brcmf_mp_device *settings; | 149 | struct brcmf_mp_device *settings; |
147 | }; | 150 | }; |
148 | 151 | ||
@@ -175,6 +178,7 @@ enum brcmf_netif_stop_reason { | |||
175 | * @stats: interface specific network statistics. | 178 | * @stats: interface specific network statistics. |
176 | * @setmacaddr_work: worker object for setting mac address. | 179 | * @setmacaddr_work: worker object for setting mac address. |
177 | * @multicast_work: worker object for multicast provisioning. | 180 | * @multicast_work: worker object for multicast provisioning. |
181 | * @ndoffload_work: worker object for neighbor discovery offload configuration. | ||
178 | * @fws_desc: interface specific firmware-signalling descriptor. | 182 | * @fws_desc: interface specific firmware-signalling descriptor. |
179 | * @ifidx: interface index in device firmware. | 183 | * @ifidx: interface index in device firmware. |
180 | * @bsscfgidx: index of bss associated with this interface. | 184 | * @bsscfgidx: index of bss associated with this interface. |
@@ -191,6 +195,7 @@ struct brcmf_if { | |||
191 | struct net_device_stats stats; | 195 | struct net_device_stats stats; |
192 | struct work_struct setmacaddr_work; | 196 | struct work_struct setmacaddr_work; |
193 | struct work_struct multicast_work; | 197 | struct work_struct multicast_work; |
198 | struct work_struct ndoffload_work; | ||
194 | struct brcmf_fws_mac_descriptor *fws_desc; | 199 | struct brcmf_fws_mac_descriptor *fws_desc; |
195 | int ifidx; | 200 | int ifidx; |
196 | s32 bsscfgidx; | 201 | s32 bsscfgidx; |
@@ -199,6 +204,8 @@ struct brcmf_if { | |||
199 | spinlock_t netif_stop_lock; | 204 | spinlock_t netif_stop_lock; |
200 | atomic_t pend_8021x_cnt; | 205 | atomic_t pend_8021x_cnt; |
201 | wait_queue_head_t pend_8021x_wait; | 206 | wait_queue_head_t pend_8021x_wait; |
207 | struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES]; | ||
208 | u8 ipv6addr_idx; | ||
202 | }; | 209 | }; |
203 | 210 | ||
204 | struct brcmf_skb_reorder_data { | 211 | struct brcmf_skb_reorder_data { |
@@ -220,5 +227,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, | |||
220 | void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); | 227 | void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); |
221 | void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); | 228 | void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); |
222 | void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); | 229 | void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); |
230 | int __init brcmf_core_init(void); | ||
231 | void __exit brcmf_core_exit(void); | ||
223 | 232 | ||
224 | #endif /* BRCMFMAC_CORE_H */ | 233 | #endif /* BRCMFMAC_CORE_H */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index 1ffa95f1b8d2..62985f2c0853 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | |||
@@ -136,6 +136,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) | |||
136 | { | 136 | { |
137 | struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); | 137 | struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); |
138 | struct brcmf_pno_macaddr_le pfn_mac; | 138 | struct brcmf_pno_macaddr_le pfn_mac; |
139 | u32 wowl_cap; | ||
139 | s32 err; | 140 | s32 err; |
140 | 141 | ||
141 | brcmf_feat_firmware_capabilities(ifp); | 142 | brcmf_feat_firmware_capabilities(ifp); |
@@ -143,11 +144,24 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) | |||
143 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn"); | 144 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn"); |
144 | if (drvr->bus_if->wowl_supported) | 145 | if (drvr->bus_if->wowl_supported) |
145 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); | 146 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); |
147 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) { | ||
148 | err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap); | ||
149 | if (!err) { | ||
150 | ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_WOWL_ARP_ND); | ||
151 | if (wowl_cap & BRCMF_WOWL_PFN_FOUND) | ||
152 | ifp->drvr->feat_flags |= | ||
153 | BIT(BRCMF_FEAT_WOWL_ND); | ||
154 | if (wowl_cap & BRCMF_WOWL_GTK_FAILURE) | ||
155 | ifp->drvr->feat_flags |= | ||
156 | BIT(BRCMF_FEAT_WOWL_GTK); | ||
157 | } | ||
158 | } | ||
146 | /* MBSS does not work for 43362 */ | 159 | /* MBSS does not work for 43362 */ |
147 | if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID) | 160 | if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID) |
148 | ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS); | 161 | ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS); |
149 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode"); | 162 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode"); |
150 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable"); | 163 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable"); |
164 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MFP, "mfp"); | ||
151 | 165 | ||
152 | pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; | 166 | pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; |
153 | err = brcmf_fil_iovar_data_get(ifp, "pfn_macaddr", &pfn_mac, | 167 | err = brcmf_fil_iovar_data_get(ifp, "pfn_macaddr", &pfn_mac, |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h index 2e2479d41337..db4733a95e28 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h | |||
@@ -27,6 +27,10 @@ | |||
27 | * RSDB: Real Simultaneous Dual Band | 27 | * RSDB: Real Simultaneous Dual Band |
28 | * TDLS: Tunneled Direct Link Setup | 28 | * TDLS: Tunneled Direct Link Setup |
29 | * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan. | 29 | * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan. |
30 | * WOWL_ND: WOWL net detect (PNO) | ||
31 | * WOWL_GTK: (WOWL) GTK rekeying offload | ||
32 | * WOWL_ARP_ND: ARP and Neighbor Discovery offload support during WOWL. | ||
33 | * MFP: 802.11w Management Frame Protection. | ||
30 | */ | 34 | */ |
31 | #define BRCMF_FEAT_LIST \ | 35 | #define BRCMF_FEAT_LIST \ |
32 | BRCMF_FEAT_DEF(MBSS) \ | 36 | BRCMF_FEAT_DEF(MBSS) \ |
@@ -36,7 +40,11 @@ | |||
36 | BRCMF_FEAT_DEF(P2P) \ | 40 | BRCMF_FEAT_DEF(P2P) \ |
37 | BRCMF_FEAT_DEF(RSDB) \ | 41 | BRCMF_FEAT_DEF(RSDB) \ |
38 | BRCMF_FEAT_DEF(TDLS) \ | 42 | BRCMF_FEAT_DEF(TDLS) \ |
39 | BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) | 43 | BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \ |
44 | BRCMF_FEAT_DEF(WOWL_ND) \ | ||
45 | BRCMF_FEAT_DEF(WOWL_GTK) \ | ||
46 | BRCMF_FEAT_DEF(WOWL_ARP_ND) \ | ||
47 | BRCMF_FEAT_DEF(MFP) | ||
40 | 48 | ||
41 | /* | 49 | /* |
42 | * Quirks: | 50 | * Quirks: |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c index 2ca783fa50cf..7e269f9aa607 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256) | 32 | #define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256) |
33 | #define BRCMF_FLOWRING_INVALID_IFIDX 0xff | 33 | #define BRCMF_FLOWRING_INVALID_IFIDX 0xff |
34 | 34 | ||
35 | #define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16) | 35 | #define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] * 2 + fifo + ifidx * 16) |
36 | #define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16) | 36 | #define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16) |
37 | 37 | ||
38 | static const u8 brcmf_flowring_prio2fifo[] = { | 38 | static const u8 brcmf_flowring_prio2fifo[] = { |
@@ -68,7 +68,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
68 | u8 prio, u8 ifidx) | 68 | u8 prio, u8 ifidx) |
69 | { | 69 | { |
70 | struct brcmf_flowring_hash *hash; | 70 | struct brcmf_flowring_hash *hash; |
71 | u8 hash_idx; | 71 | u16 hash_idx; |
72 | u32 i; | 72 | u32 i; |
73 | bool found; | 73 | bool found; |
74 | bool sta; | 74 | bool sta; |
@@ -88,6 +88,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
88 | } | 88 | } |
89 | hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : | 89 | hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : |
90 | BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); | 90 | BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); |
91 | hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); | ||
91 | found = false; | 92 | found = false; |
92 | hash = flow->hash; | 93 | hash = flow->hash; |
93 | for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { | 94 | for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { |
@@ -98,6 +99,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
98 | break; | 99 | break; |
99 | } | 100 | } |
100 | hash_idx++; | 101 | hash_idx++; |
102 | hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); | ||
101 | } | 103 | } |
102 | if (found) | 104 | if (found) |
103 | return hash[hash_idx].flowid; | 105 | return hash[hash_idx].flowid; |
@@ -111,7 +113,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
111 | { | 113 | { |
112 | struct brcmf_flowring_ring *ring; | 114 | struct brcmf_flowring_ring *ring; |
113 | struct brcmf_flowring_hash *hash; | 115 | struct brcmf_flowring_hash *hash; |
114 | u8 hash_idx; | 116 | u16 hash_idx; |
115 | u32 i; | 117 | u32 i; |
116 | bool found; | 118 | bool found; |
117 | u8 fifo; | 119 | u8 fifo; |
@@ -131,6 +133,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
131 | } | 133 | } |
132 | hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : | 134 | hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : |
133 | BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); | 135 | BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); |
136 | hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); | ||
134 | found = false; | 137 | found = false; |
135 | hash = flow->hash; | 138 | hash = flow->hash; |
136 | for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { | 139 | for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { |
@@ -140,6 +143,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
140 | break; | 143 | break; |
141 | } | 144 | } |
142 | hash_idx++; | 145 | hash_idx++; |
146 | hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); | ||
143 | } | 147 | } |
144 | if (found) { | 148 | if (found) { |
145 | for (i = 0; i < flow->nrofrings; i++) { | 149 | for (i = 0; i < flow->nrofrings; i++) { |
@@ -169,7 +173,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
169 | } | 173 | } |
170 | 174 | ||
171 | 175 | ||
172 | u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid) | 176 | u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid) |
173 | { | 177 | { |
174 | struct brcmf_flowring_ring *ring; | 178 | struct brcmf_flowring_ring *ring; |
175 | 179 | ||
@@ -179,7 +183,7 @@ u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid) | |||
179 | } | 183 | } |
180 | 184 | ||
181 | 185 | ||
182 | static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, | 186 | static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid, |
183 | bool blocked) | 187 | bool blocked) |
184 | { | 188 | { |
185 | struct brcmf_flowring_ring *ring; | 189 | struct brcmf_flowring_ring *ring; |
@@ -228,10 +232,10 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, | |||
228 | } | 232 | } |
229 | 233 | ||
230 | 234 | ||
231 | void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid) | 235 | void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid) |
232 | { | 236 | { |
233 | struct brcmf_flowring_ring *ring; | 237 | struct brcmf_flowring_ring *ring; |
234 | u8 hash_idx; | 238 | u16 hash_idx; |
235 | struct sk_buff *skb; | 239 | struct sk_buff *skb; |
236 | 240 | ||
237 | ring = flow->rings[flowid]; | 241 | ring = flow->rings[flowid]; |
@@ -253,7 +257,7 @@ void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid) | |||
253 | } | 257 | } |
254 | 258 | ||
255 | 259 | ||
256 | u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, | 260 | u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid, |
257 | struct sk_buff *skb) | 261 | struct sk_buff *skb) |
258 | { | 262 | { |
259 | struct brcmf_flowring_ring *ring; | 263 | struct brcmf_flowring_ring *ring; |
@@ -279,7 +283,7 @@ u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, | |||
279 | } | 283 | } |
280 | 284 | ||
281 | 285 | ||
282 | struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid) | 286 | struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid) |
283 | { | 287 | { |
284 | struct brcmf_flowring_ring *ring; | 288 | struct brcmf_flowring_ring *ring; |
285 | struct sk_buff *skb; | 289 | struct sk_buff *skb; |
@@ -300,7 +304,7 @@ struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid) | |||
300 | } | 304 | } |
301 | 305 | ||
302 | 306 | ||
303 | void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, | 307 | void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid, |
304 | struct sk_buff *skb) | 308 | struct sk_buff *skb) |
305 | { | 309 | { |
306 | struct brcmf_flowring_ring *ring; | 310 | struct brcmf_flowring_ring *ring; |
@@ -311,7 +315,7 @@ void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, | |||
311 | } | 315 | } |
312 | 316 | ||
313 | 317 | ||
314 | u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid) | 318 | u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid) |
315 | { | 319 | { |
316 | struct brcmf_flowring_ring *ring; | 320 | struct brcmf_flowring_ring *ring; |
317 | 321 | ||
@@ -326,7 +330,7 @@ u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid) | |||
326 | } | 330 | } |
327 | 331 | ||
328 | 332 | ||
329 | void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid) | 333 | void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid) |
330 | { | 334 | { |
331 | struct brcmf_flowring_ring *ring; | 335 | struct brcmf_flowring_ring *ring; |
332 | 336 | ||
@@ -340,10 +344,10 @@ void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid) | |||
340 | } | 344 | } |
341 | 345 | ||
342 | 346 | ||
343 | u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid) | 347 | u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid) |
344 | { | 348 | { |
345 | struct brcmf_flowring_ring *ring; | 349 | struct brcmf_flowring_ring *ring; |
346 | u8 hash_idx; | 350 | u16 hash_idx; |
347 | 351 | ||
348 | ring = flow->rings[flowid]; | 352 | ring = flow->rings[flowid]; |
349 | hash_idx = ring->hash_id; | 353 | hash_idx = ring->hash_id; |
@@ -384,7 +388,7 @@ void brcmf_flowring_detach(struct brcmf_flowring *flow) | |||
384 | struct brcmf_pub *drvr = bus_if->drvr; | 388 | struct brcmf_pub *drvr = bus_if->drvr; |
385 | struct brcmf_flowring_tdls_entry *search; | 389 | struct brcmf_flowring_tdls_entry *search; |
386 | struct brcmf_flowring_tdls_entry *remove; | 390 | struct brcmf_flowring_tdls_entry *remove; |
387 | u8 flowid; | 391 | u16 flowid; |
388 | 392 | ||
389 | for (flowid = 0; flowid < flow->nrofrings; flowid++) { | 393 | for (flowid = 0; flowid < flow->nrofrings; flowid++) { |
390 | if (flow->rings[flowid]) | 394 | if (flow->rings[flowid]) |
@@ -408,7 +412,7 @@ void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx, | |||
408 | struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev); | 412 | struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev); |
409 | struct brcmf_pub *drvr = bus_if->drvr; | 413 | struct brcmf_pub *drvr = bus_if->drvr; |
410 | u32 i; | 414 | u32 i; |
411 | u8 flowid; | 415 | u16 flowid; |
412 | 416 | ||
413 | if (flow->addr_mode[ifidx] != addr_mode) { | 417 | if (flow->addr_mode[ifidx] != addr_mode) { |
414 | for (i = 0; i < ARRAY_SIZE(flow->hash); i++) { | 418 | for (i = 0; i < ARRAY_SIZE(flow->hash); i++) { |
@@ -434,7 +438,7 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx, | |||
434 | struct brcmf_flowring_tdls_entry *prev; | 438 | struct brcmf_flowring_tdls_entry *prev; |
435 | struct brcmf_flowring_tdls_entry *search; | 439 | struct brcmf_flowring_tdls_entry *search; |
436 | u32 i; | 440 | u32 i; |
437 | u8 flowid; | 441 | u16 flowid; |
438 | bool sta; | 442 | bool sta; |
439 | 443 | ||
440 | sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT); | 444 | sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h index 95fd1c9675d1..068e68d94999 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h | |||
@@ -16,7 +16,7 @@ | |||
16 | #define BRCMFMAC_FLOWRING_H | 16 | #define BRCMFMAC_FLOWRING_H |
17 | 17 | ||
18 | 18 | ||
19 | #define BRCMF_FLOWRING_HASHSIZE 256 | 19 | #define BRCMF_FLOWRING_HASHSIZE 512 /* has to be 2^x */ |
20 | #define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF | 20 | #define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF |
21 | 21 | ||
22 | 22 | ||
@@ -24,7 +24,7 @@ struct brcmf_flowring_hash { | |||
24 | u8 mac[ETH_ALEN]; | 24 | u8 mac[ETH_ALEN]; |
25 | u8 fifo; | 25 | u8 fifo; |
26 | u8 ifidx; | 26 | u8 ifidx; |
27 | u8 flowid; | 27 | u16 flowid; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | enum ring_status { | 30 | enum ring_status { |
@@ -61,16 +61,16 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | |||
61 | u8 prio, u8 ifidx); | 61 | u8 prio, u8 ifidx); |
62 | u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], | 62 | u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], |
63 | u8 prio, u8 ifidx); | 63 | u8 prio, u8 ifidx); |
64 | void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid); | 64 | void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid); |
65 | void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid); | 65 | void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid); |
66 | u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid); | 66 | u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid); |
67 | u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, | 67 | u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid, |
68 | struct sk_buff *skb); | 68 | struct sk_buff *skb); |
69 | struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid); | 69 | struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid); |
70 | void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, | 70 | void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid, |
71 | struct sk_buff *skb); | 71 | struct sk_buff *skb); |
72 | u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid); | 72 | u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid); |
73 | u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid); | 73 | u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid); |
74 | struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings); | 74 | struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings); |
75 | void brcmf_flowring_detach(struct brcmf_flowring *flow); | 75 | void brcmf_flowring_detach(struct brcmf_flowring *flow); |
76 | void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx, | 76 | void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx, |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index 7b26fb1b437c..d414fbbcc814 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | |||
@@ -26,50 +26,6 @@ | |||
26 | #include "fwil.h" | 26 | #include "fwil.h" |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * struct brcm_ethhdr - broadcom specific ether header. | ||
30 | * | ||
31 | * @subtype: subtype for this packet. | ||
32 | * @length: TODO: length of appended data. | ||
33 | * @version: version indication. | ||
34 | * @oui: OUI of this packet. | ||
35 | * @usr_subtype: subtype for this OUI. | ||
36 | */ | ||
37 | struct brcm_ethhdr { | ||
38 | __be16 subtype; | ||
39 | __be16 length; | ||
40 | u8 version; | ||
41 | u8 oui[3]; | ||
42 | __be16 usr_subtype; | ||
43 | } __packed; | ||
44 | |||
45 | struct brcmf_event_msg_be { | ||
46 | __be16 version; | ||
47 | __be16 flags; | ||
48 | __be32 event_type; | ||
49 | __be32 status; | ||
50 | __be32 reason; | ||
51 | __be32 auth_type; | ||
52 | __be32 datalen; | ||
53 | u8 addr[ETH_ALEN]; | ||
54 | char ifname[IFNAMSIZ]; | ||
55 | u8 ifidx; | ||
56 | u8 bsscfgidx; | ||
57 | } __packed; | ||
58 | |||
59 | /** | ||
60 | * struct brcmf_event - contents of broadcom event packet. | ||
61 | * | ||
62 | * @eth: standard ether header. | ||
63 | * @hdr: broadcom specific ether header. | ||
64 | * @msg: common part of the actual event message. | ||
65 | */ | ||
66 | struct brcmf_event { | ||
67 | struct ethhdr eth; | ||
68 | struct brcm_ethhdr hdr; | ||
69 | struct brcmf_event_msg_be msg; | ||
70 | } __packed; | ||
71 | |||
72 | /** | ||
73 | * struct brcmf_fweh_queue_item - event item on event queue. | 29 | * struct brcmf_fweh_queue_item - event item on event queue. |
74 | * | 30 | * |
75 | * @q: list element for queuing. | 31 | * @q: list element for queuing. |
@@ -85,6 +41,7 @@ struct brcmf_fweh_queue_item { | |||
85 | u8 ifidx; | 41 | u8 ifidx; |
86 | u8 ifaddr[ETH_ALEN]; | 42 | u8 ifaddr[ETH_ALEN]; |
87 | struct brcmf_event_msg_be emsg; | 43 | struct brcmf_event_msg_be emsg; |
44 | u32 datalen; | ||
88 | u8 data[0]; | 45 | u8 data[0]; |
89 | }; | 46 | }; |
90 | 47 | ||
@@ -294,6 +251,11 @@ static void brcmf_fweh_event_worker(struct work_struct *work) | |||
294 | brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data, | 251 | brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data, |
295 | min_t(u32, emsg.datalen, 64), | 252 | min_t(u32, emsg.datalen, 64), |
296 | "event payload, len=%d\n", emsg.datalen); | 253 | "event payload, len=%d\n", emsg.datalen); |
254 | if (emsg.datalen > event->datalen) { | ||
255 | brcmf_err("event invalid length header=%d, msg=%d\n", | ||
256 | event->datalen, emsg.datalen); | ||
257 | goto event_free; | ||
258 | } | ||
297 | 259 | ||
298 | /* special handling of interface event */ | 260 | /* special handling of interface event */ |
299 | if (event->code == BRCMF_E_IF) { | 261 | if (event->code == BRCMF_E_IF) { |
@@ -439,7 +401,8 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp) | |||
439 | * dispatch the event to a registered handler (using worker). | 401 | * dispatch the event to a registered handler (using worker). |
440 | */ | 402 | */ |
441 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, | 403 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, |
442 | struct brcmf_event *event_packet) | 404 | struct brcmf_event *event_packet, |
405 | u32 packet_len) | ||
443 | { | 406 | { |
444 | enum brcmf_fweh_event_code code; | 407 | enum brcmf_fweh_event_code code; |
445 | struct brcmf_fweh_info *fweh = &drvr->fweh; | 408 | struct brcmf_fweh_info *fweh = &drvr->fweh; |
@@ -459,6 +422,9 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |||
459 | if (code != BRCMF_E_IF && !fweh->evt_handler[code]) | 422 | if (code != BRCMF_E_IF && !fweh->evt_handler[code]) |
460 | return; | 423 | return; |
461 | 424 | ||
425 | if (datalen > BRCMF_DCMD_MAXLEN) | ||
426 | return; | ||
427 | |||
462 | if (in_interrupt()) | 428 | if (in_interrupt()) |
463 | alloc_flag = GFP_ATOMIC; | 429 | alloc_flag = GFP_ATOMIC; |
464 | 430 | ||
@@ -472,6 +438,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |||
472 | /* use memcpy to get aligned event message */ | 438 | /* use memcpy to get aligned event message */ |
473 | memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); | 439 | memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); |
474 | memcpy(event->data, data, datalen); | 440 | memcpy(event->data, data, datalen); |
441 | event->datalen = datalen; | ||
475 | memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN); | 442 | memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN); |
476 | 443 | ||
477 | brcmf_fweh_queue_event(fweh, event); | 444 | brcmf_fweh_queue_event(fweh, event); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h index 5e39e2a9e388..26ff5a9648f3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h | |||
@@ -27,7 +27,6 @@ | |||
27 | struct brcmf_pub; | 27 | struct brcmf_pub; |
28 | struct brcmf_if; | 28 | struct brcmf_if; |
29 | struct brcmf_cfg80211_info; | 29 | struct brcmf_cfg80211_info; |
30 | struct brcmf_event; | ||
31 | 30 | ||
32 | /* list of firmware events */ | 31 | /* list of firmware events */ |
33 | #define BRCMF_FWEH_EVENT_ENUM_DEFLIST \ | 32 | #define BRCMF_FWEH_EVENT_ENUM_DEFLIST \ |
@@ -180,13 +179,55 @@ enum brcmf_fweh_event_code { | |||
180 | /** | 179 | /** |
181 | * definitions for event packet validation. | 180 | * definitions for event packet validation. |
182 | */ | 181 | */ |
183 | #define BRCMF_EVENT_OUI_OFFSET 19 | 182 | #define BRCM_OUI "\x00\x10\x18" |
184 | #define BRCM_OUI "\x00\x10\x18" | 183 | #define BCMILCP_BCM_SUBTYPE_EVENT 1 |
185 | #define DOT11_OUI_LEN 3 | ||
186 | #define BCMILCP_BCM_SUBTYPE_EVENT 1 | ||
187 | 184 | ||
188 | 185 | ||
189 | /** | 186 | /** |
187 | * struct brcm_ethhdr - broadcom specific ether header. | ||
188 | * | ||
189 | * @subtype: subtype for this packet. | ||
190 | * @length: TODO: length of appended data. | ||
191 | * @version: version indication. | ||
192 | * @oui: OUI of this packet. | ||
193 | * @usr_subtype: subtype for this OUI. | ||
194 | */ | ||
195 | struct brcm_ethhdr { | ||
196 | __be16 subtype; | ||
197 | __be16 length; | ||
198 | u8 version; | ||
199 | u8 oui[3]; | ||
200 | __be16 usr_subtype; | ||
201 | } __packed; | ||
202 | |||
203 | struct brcmf_event_msg_be { | ||
204 | __be16 version; | ||
205 | __be16 flags; | ||
206 | __be32 event_type; | ||
207 | __be32 status; | ||
208 | __be32 reason; | ||
209 | __be32 auth_type; | ||
210 | __be32 datalen; | ||
211 | u8 addr[ETH_ALEN]; | ||
212 | char ifname[IFNAMSIZ]; | ||
213 | u8 ifidx; | ||
214 | u8 bsscfgidx; | ||
215 | } __packed; | ||
216 | |||
217 | /** | ||
218 | * struct brcmf_event - contents of broadcom event packet. | ||
219 | * | ||
220 | * @eth: standard ether header. | ||
221 | * @hdr: broadcom specific ether header. | ||
222 | * @msg: common part of the actual event message. | ||
223 | */ | ||
224 | struct brcmf_event { | ||
225 | struct ethhdr eth; | ||
226 | struct brcm_ethhdr hdr; | ||
227 | struct brcmf_event_msg_be msg; | ||
228 | } __packed; | ||
229 | |||
230 | /** | ||
190 | * struct brcmf_event_msg - firmware event message. | 231 | * struct brcmf_event_msg - firmware event message. |
191 | * | 232 | * |
192 | * @version: version information. | 233 | * @version: version information. |
@@ -256,34 +297,35 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr, | |||
256 | enum brcmf_fweh_event_code code); | 297 | enum brcmf_fweh_event_code code); |
257 | int brcmf_fweh_activate_events(struct brcmf_if *ifp); | 298 | int brcmf_fweh_activate_events(struct brcmf_if *ifp); |
258 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, | 299 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, |
259 | struct brcmf_event *event_packet); | 300 | struct brcmf_event *event_packet, |
301 | u32 packet_len); | ||
260 | void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing); | 302 | void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing); |
261 | 303 | ||
262 | static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, | 304 | static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, |
263 | struct sk_buff *skb) | 305 | struct sk_buff *skb) |
264 | { | 306 | { |
265 | struct brcmf_event *event_packet; | 307 | struct brcmf_event *event_packet; |
266 | u8 *data; | ||
267 | u16 usr_stype; | 308 | u16 usr_stype; |
268 | 309 | ||
269 | /* only process events when protocol matches */ | 310 | /* only process events when protocol matches */ |
270 | if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL)) | 311 | if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL)) |
271 | return; | 312 | return; |
272 | 313 | ||
314 | if ((skb->len + ETH_HLEN) < sizeof(*event_packet)) | ||
315 | return; | ||
316 | |||
273 | /* check for BRCM oui match */ | 317 | /* check for BRCM oui match */ |
274 | event_packet = (struct brcmf_event *)skb_mac_header(skb); | 318 | event_packet = (struct brcmf_event *)skb_mac_header(skb); |
275 | data = (u8 *)event_packet; | 319 | if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0], |
276 | data += BRCMF_EVENT_OUI_OFFSET; | 320 | sizeof(event_packet->hdr.oui))) |
277 | if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN)) | ||
278 | return; | 321 | return; |
279 | 322 | ||
280 | /* final match on usr_subtype */ | 323 | /* final match on usr_subtype */ |
281 | data += DOT11_OUI_LEN; | 324 | usr_stype = get_unaligned_be16(&event_packet->hdr.usr_subtype); |
282 | usr_stype = get_unaligned_be16(data); | ||
283 | if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT) | 325 | if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT) |
284 | return; | 326 | return; |
285 | 327 | ||
286 | brcmf_fweh_process_event(drvr, event_packet); | 328 | brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN); |
287 | } | 329 | } |
288 | 330 | ||
289 | #endif /* FWEH_H_ */ | 331 | #endif /* FWEH_H_ */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index 1afc2ad83b6c..a4118c0ef6ca 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h | |||
@@ -111,7 +111,9 @@ | |||
111 | /* Wakeup if received matched secured pattern: */ | 111 | /* Wakeup if received matched secured pattern: */ |
112 | #define BRCMF_WOWL_SECURE (1 << 25) | 112 | #define BRCMF_WOWL_SECURE (1 << 25) |
113 | /* Wakeup on finding preferred network */ | 113 | /* Wakeup on finding preferred network */ |
114 | #define BRCMF_WOWL_PFN_FOUND (1 << 26) | 114 | #define BRCMF_WOWL_PFN_FOUND (1 << 27) |
115 | /* Wakeup on receiving pairwise key EAP packets: */ | ||
116 | #define WIPHY_WOWL_EAP_PK (1 << 28) | ||
115 | /* Link Down indication in WoWL mode: */ | 117 | /* Link Down indication in WoWL mode: */ |
116 | #define BRCMF_WOWL_LINKDOWN (1 << 31) | 118 | #define BRCMF_WOWL_LINKDOWN (1 << 31) |
117 | 119 | ||
@@ -134,6 +136,16 @@ | |||
134 | #define BRCMF_PFN_MAC_OUI_ONLY BIT(0) | 136 | #define BRCMF_PFN_MAC_OUI_ONLY BIT(0) |
135 | #define BRCMF_PFN_SET_MAC_UNASSOC BIT(1) | 137 | #define BRCMF_PFN_SET_MAC_UNASSOC BIT(1) |
136 | 138 | ||
139 | #define BRCMF_MCSSET_LEN 16 | ||
140 | |||
141 | #define BRCMF_RSN_KCK_LENGTH 16 | ||
142 | #define BRCMF_RSN_KEK_LENGTH 16 | ||
143 | #define BRCMF_RSN_REPLAY_LEN 8 | ||
144 | |||
145 | #define BRCMF_MFP_NONE 0 | ||
146 | #define BRCMF_MFP_CAPABLE 1 | ||
147 | #define BRCMF_MFP_REQUIRED 2 | ||
148 | |||
137 | /* join preference types for join_pref iovar */ | 149 | /* join preference types for join_pref iovar */ |
138 | enum brcmf_join_pref_types { | 150 | enum brcmf_join_pref_types { |
139 | BRCMF_JOIN_PREF_RSSI = 1, | 151 | BRCMF_JOIN_PREF_RSSI = 1, |
@@ -279,7 +291,7 @@ struct brcmf_bss_info_le { | |||
279 | __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ | 291 | __le32 reserved32[1]; /* Reserved for expansion of BSS properties */ |
280 | u8 flags; /* flags */ | 292 | u8 flags; /* flags */ |
281 | u8 reserved[3]; /* Reserved for expansion of BSS properties */ | 293 | u8 reserved[3]; /* Reserved for expansion of BSS properties */ |
282 | u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ | 294 | u8 basic_mcs[BRCMF_MCSSET_LEN]; /* 802.11N BSS required MCS set */ |
283 | 295 | ||
284 | __le16 ie_offset; /* offset at which IEs start, from beginning */ | 296 | __le16 ie_offset; /* offset at which IEs start, from beginning */ |
285 | __le32 ie_length; /* byte length of Information Elements */ | 297 | __le32 ie_length; /* byte length of Information Elements */ |
@@ -787,4 +799,17 @@ struct brcmf_pktcnt_le { | |||
787 | __le32 rx_ocast_good_pkt; | 799 | __le32 rx_ocast_good_pkt; |
788 | }; | 800 | }; |
789 | 801 | ||
802 | /** | ||
803 | * struct brcmf_gtk_keyinfo_le - GTP rekey data | ||
804 | * | ||
805 | * @kck: key confirmation key. | ||
806 | * @kek: key encryption key. | ||
807 | * @replay_counter: replay counter. | ||
808 | */ | ||
809 | struct brcmf_gtk_keyinfo_le { | ||
810 | u8 kck[BRCMF_RSN_KCK_LENGTH]; | ||
811 | u8 kek[BRCMF_RSN_KEK_LENGTH]; | ||
812 | u8 replay_counter[BRCMF_RSN_REPLAY_LEN]; | ||
813 | }; | ||
814 | |||
790 | #endif /* FWIL_TYPES_H_ */ | 815 | #endif /* FWIL_TYPES_H_ */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index c2bdb91746cf..922966734a7f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | |||
@@ -677,7 +677,7 @@ static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx, | |||
677 | } | 677 | } |
678 | 678 | ||
679 | 679 | ||
680 | static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid) | 680 | static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid) |
681 | { | 681 | { |
682 | struct brcmf_flowring *flow = msgbuf->flow; | 682 | struct brcmf_flowring *flow = msgbuf->flow; |
683 | struct brcmf_commonring *commonring; | 683 | struct brcmf_commonring *commonring; |
@@ -1310,7 +1310,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) | |||
1310 | } | 1310 | } |
1311 | 1311 | ||
1312 | 1312 | ||
1313 | void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid) | 1313 | void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid) |
1314 | { | 1314 | { |
1315 | struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; | 1315 | struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; |
1316 | struct msgbuf_tx_flowring_delete_req *delete; | 1316 | struct msgbuf_tx_flowring_delete_req *delete; |
@@ -1415,6 +1415,13 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) | |||
1415 | u32 count; | 1415 | u32 count; |
1416 | 1416 | ||
1417 | if_msgbuf = drvr->bus_if->msgbuf; | 1417 | if_msgbuf = drvr->bus_if->msgbuf; |
1418 | |||
1419 | if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) { | ||
1420 | brcmf_err("driver not configured for this many flowrings %d\n", | ||
1421 | if_msgbuf->nrof_flowrings); | ||
1422 | if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1; | ||
1423 | } | ||
1424 | |||
1418 | msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL); | 1425 | msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL); |
1419 | if (!msgbuf) | 1426 | if (!msgbuf) |
1420 | goto fail; | 1427 | goto fail; |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h index 3d513e407e3d..ee6906a3c3f6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | 34 | ||
35 | int brcmf_proto_msgbuf_rx_trigger(struct device *dev); | 35 | int brcmf_proto_msgbuf_rx_trigger(struct device *dev); |
36 | void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid); | 36 | void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid); |
37 | int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr); | 37 | int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr); |
38 | void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr); | 38 | void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr); |
39 | #else | 39 | #else |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c index 03f35e0c52ca..425c41dc0a59 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c | |||
@@ -16,17 +16,15 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/of_irq.h> | 18 | #include <linux/of_irq.h> |
19 | #include <linux/mmc/card.h> | ||
20 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
21 | #include <linux/mmc/sdio_func.h> | ||
22 | 19 | ||
23 | #include <defs.h> | 20 | #include <defs.h> |
24 | #include "debug.h" | 21 | #include "debug.h" |
25 | #include "sdio.h" | 22 | #include "core.h" |
23 | #include "common.h" | ||
24 | #include "of.h" | ||
26 | 25 | ||
27 | void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) | 26 | void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio) |
28 | { | 27 | { |
29 | struct device *dev = sdiodev->dev; | ||
30 | struct device_node *np = dev->of_node; | 28 | struct device_node *np = dev->of_node; |
31 | int irq; | 29 | int irq; |
32 | u32 irqf; | 30 | u32 irqf; |
@@ -35,12 +33,8 @@ void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) | |||
35 | if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) | 33 | if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) |
36 | return; | 34 | return; |
37 | 35 | ||
38 | sdiodev->pdata = devm_kzalloc(dev, sizeof(*sdiodev->pdata), GFP_KERNEL); | ||
39 | if (!sdiodev->pdata) | ||
40 | return; | ||
41 | |||
42 | if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) | 36 | if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) |
43 | sdiodev->pdata->drive_strength = val; | 37 | sdio->drive_strength = val; |
44 | 38 | ||
45 | /* make sure there are interrupts defined in the node */ | 39 | /* make sure there are interrupts defined in the node */ |
46 | if (!of_find_property(np, "interrupts", NULL)) | 40 | if (!of_find_property(np, "interrupts", NULL)) |
@@ -53,7 +47,7 @@ void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) | |||
53 | } | 47 | } |
54 | irqf = irqd_get_trigger_type(irq_get_irq_data(irq)); | 48 | irqf = irqd_get_trigger_type(irq_get_irq_data(irq)); |
55 | 49 | ||
56 | sdiodev->pdata->oob_irq_supported = true; | 50 | sdio->oob_irq_supported = true; |
57 | sdiodev->pdata->oob_irq_nr = irq; | 51 | sdio->oob_irq_nr = irq; |
58 | sdiodev->pdata->oob_irq_flags = irqf; | 52 | sdio->oob_irq_flags = irqf; |
59 | } | 53 | } |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h index 5f7c3550deda..a9d94c15d0f5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h | |||
@@ -14,9 +14,9 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | #ifdef CONFIG_OF | 16 | #ifdef CONFIG_OF |
17 | void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev); | 17 | void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio); |
18 | #else | 18 | #else |
19 | static void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) | 19 | static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio) |
20 | { | 20 | { |
21 | } | 21 | } |
22 | #endif /* CONFIG_OF */ | 22 | #endif /* CONFIG_OF */ |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 821b6494f9d1..b5a49e564f25 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | |||
@@ -1361,6 +1361,11 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1361 | u16 mgmt_type; | 1361 | u16 mgmt_type; |
1362 | u8 action; | 1362 | u8 action; |
1363 | 1363 | ||
1364 | if (e->datalen < sizeof(*rxframe)) { | ||
1365 | brcmf_dbg(SCAN, "Event data to small. Ignore\n"); | ||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1364 | ch.chspec = be16_to_cpu(rxframe->chanspec); | 1369 | ch.chspec = be16_to_cpu(rxframe->chanspec); |
1365 | cfg->d11inf.decchspec(&ch); | 1370 | cfg->d11inf.decchspec(&ch); |
1366 | /* Check if wpa_supplicant has registered for this frame */ | 1371 | /* Check if wpa_supplicant has registered for this frame */ |
@@ -1858,6 +1863,11 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1858 | brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, | 1863 | brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, |
1859 | e->reason); | 1864 | e->reason); |
1860 | 1865 | ||
1866 | if (e->datalen < sizeof(*rxframe)) { | ||
1867 | brcmf_dbg(SCAN, "Event data to small. Ignore\n"); | ||
1868 | return 0; | ||
1869 | } | ||
1870 | |||
1861 | ch.chspec = be16_to_cpu(rxframe->chanspec); | 1871 | ch.chspec = be16_to_cpu(rxframe->chanspec); |
1862 | cfg->d11inf.decchspec(&ch); | 1872 | cfg->d11inf.decchspec(&ch); |
1863 | 1873 | ||
@@ -1988,8 +1998,8 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, | |||
1988 | brcmf_cfg80211_arm_vif_event(cfg, NULL); | 1998 | brcmf_cfg80211_arm_vif_event(cfg, NULL); |
1989 | return err; | 1999 | return err; |
1990 | } | 2000 | } |
1991 | err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_CHANGE, | 2001 | err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_CHANGE, |
1992 | BRCMF_VIF_EVENT_TIMEOUT); | 2002 | BRCMF_VIF_EVENT_TIMEOUT); |
1993 | brcmf_cfg80211_arm_vif_event(cfg, NULL); | 2003 | brcmf_cfg80211_arm_vif_event(cfg, NULL); |
1994 | if (!err) { | 2004 | if (!err) { |
1995 | brcmf_err("No BRCMF_E_IF_CHANGE event received\n"); | 2005 | brcmf_err("No BRCMF_E_IF_CHANGE event received\n"); |
@@ -2090,8 +2100,8 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, | |||
2090 | } | 2100 | } |
2091 | 2101 | ||
2092 | /* wait for firmware event */ | 2102 | /* wait for firmware event */ |
2093 | err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD, | 2103 | err = brcmf_cfg80211_wait_vif_event(p2p->cfg, BRCMF_E_IF_ADD, |
2094 | BRCMF_VIF_EVENT_TIMEOUT); | 2104 | BRCMF_VIF_EVENT_TIMEOUT); |
2095 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | 2105 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); |
2096 | brcmf_fweh_p2pdev_setup(pri_ifp, false); | 2106 | brcmf_fweh_p2pdev_setup(pri_ifp, false); |
2097 | if (!err) { | 2107 | if (!err) { |
@@ -2180,8 +2190,8 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
2180 | } | 2190 | } |
2181 | 2191 | ||
2182 | /* wait for firmware event */ | 2192 | /* wait for firmware event */ |
2183 | err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD, | 2193 | err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_ADD, |
2184 | BRCMF_VIF_EVENT_TIMEOUT); | 2194 | BRCMF_VIF_EVENT_TIMEOUT); |
2185 | brcmf_cfg80211_arm_vif_event(cfg, NULL); | 2195 | brcmf_cfg80211_arm_vif_event(cfg, NULL); |
2186 | if (!err) { | 2196 | if (!err) { |
2187 | brcmf_err("timeout occurred\n"); | 2197 | brcmf_err("timeout occurred\n"); |
@@ -2272,8 +2282,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2272 | } | 2282 | } |
2273 | if (!err) { | 2283 | if (!err) { |
2274 | /* wait for firmware event */ | 2284 | /* wait for firmware event */ |
2275 | err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL, | 2285 | err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL, |
2276 | BRCMF_VIF_EVENT_TIMEOUT); | 2286 | BRCMF_VIF_EVENT_TIMEOUT); |
2277 | if (!err) | 2287 | if (!err) |
2278 | err = -EIO; | 2288 | err = -EIO; |
2279 | else | 2289 | else |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index d5f9ef470447..52fef5e1d615 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include "pcie.h" | 37 | #include "pcie.h" |
38 | #include "firmware.h" | 38 | #include "firmware.h" |
39 | #include "chip.h" | 39 | #include "chip.h" |
40 | #include "core.h" | ||
41 | #include "common.h" | ||
40 | 42 | ||
41 | 43 | ||
42 | enum brcmf_pcie_state { | 44 | enum brcmf_pcie_state { |
@@ -53,6 +55,7 @@ BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-pcie.bin", "brcmfmac4358-pcie.txt"); | |||
53 | BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt"); | 55 | BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt"); |
54 | BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt"); | 56 | BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt"); |
55 | BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt"); | 57 | BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt"); |
58 | BRCMF_FW_NVRAM_DEF(4366C, "brcmfmac4366c-pcie.bin", "brcmfmac4366c-pcie.txt"); | ||
56 | BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt"); | 59 | BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt"); |
57 | 60 | ||
58 | static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { | 61 | static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { |
@@ -66,13 +69,13 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { | |||
66 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358), | 69 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358), |
67 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), | 70 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), |
68 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFFF, 4365B), | 71 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFFF, 4365B), |
69 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFFF, 4366B), | 72 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B), |
73 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C), | ||
70 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), | 74 | BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), |
71 | }; | 75 | }; |
72 | 76 | ||
73 | #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ | 77 | #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ |
74 | 78 | ||
75 | #define BRCMF_PCIE_TCM_MAP_SIZE (4096 * 1024) | ||
76 | #define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024) | 79 | #define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024) |
77 | 80 | ||
78 | /* backplane addres space accessed by BAR0 */ | 81 | /* backplane addres space accessed by BAR0 */ |
@@ -99,9 +102,6 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { | |||
99 | #define BRCMF_PCIE_PCIE2REG_CONFIGDATA 0x124 | 102 | #define BRCMF_PCIE_PCIE2REG_CONFIGDATA 0x124 |
100 | #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX 0x140 | 103 | #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX 0x140 |
101 | 104 | ||
102 | #define BRCMF_PCIE_GENREV1 1 | ||
103 | #define BRCMF_PCIE_GENREV2 2 | ||
104 | |||
105 | #define BRCMF_PCIE2_INTA 0x01 | 105 | #define BRCMF_PCIE2_INTA 0x01 |
106 | #define BRCMF_PCIE2_INTB 0x02 | 106 | #define BRCMF_PCIE2_INTB 0x02 |
107 | 107 | ||
@@ -207,6 +207,10 @@ static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { | |||
207 | #define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG 0x4F4 | 207 | #define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG 0x4F4 |
208 | #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3 | 208 | #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3 |
209 | 209 | ||
210 | /* Magic number at a magic location to find RAM size */ | ||
211 | #define BRCMF_RAMSIZE_MAGIC 0x534d4152 /* SMAR */ | ||
212 | #define BRCMF_RAMSIZE_OFFSET 0x6c | ||
213 | |||
210 | 214 | ||
211 | struct brcmf_pcie_console { | 215 | struct brcmf_pcie_console { |
212 | u32 base_addr; | 216 | u32 base_addr; |
@@ -248,14 +252,11 @@ struct brcmf_pciedev_info { | |||
248 | char nvram_name[BRCMF_FW_NAME_LEN]; | 252 | char nvram_name[BRCMF_FW_NAME_LEN]; |
249 | void __iomem *regs; | 253 | void __iomem *regs; |
250 | void __iomem *tcm; | 254 | void __iomem *tcm; |
251 | u32 tcm_size; | ||
252 | u32 ram_base; | 255 | u32 ram_base; |
253 | u32 ram_size; | 256 | u32 ram_size; |
254 | struct brcmf_chip *ci; | 257 | struct brcmf_chip *ci; |
255 | u32 coreid; | 258 | u32 coreid; |
256 | u32 generic_corerev; | ||
257 | struct brcmf_pcie_shared_info shared; | 259 | struct brcmf_pcie_shared_info shared; |
258 | void (*ringbell)(struct brcmf_pciedev_info *devinfo); | ||
259 | wait_queue_head_t mbdata_resp_wait; | 260 | wait_queue_head_t mbdata_resp_wait; |
260 | bool mbdata_completed; | 261 | bool mbdata_completed; |
261 | bool irq_allocated; | 262 | bool irq_allocated; |
@@ -267,6 +268,7 @@ struct brcmf_pciedev_info { | |||
267 | u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset); | 268 | u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset); |
268 | void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset, | 269 | void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset, |
269 | u16 value); | 270 | u16 value); |
271 | struct brcmf_mp_device *settings; | ||
270 | }; | 272 | }; |
271 | 273 | ||
272 | struct brcmf_pcie_ringbuf { | 274 | struct brcmf_pcie_ringbuf { |
@@ -742,68 +744,22 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) | |||
742 | } | 744 | } |
743 | 745 | ||
744 | 746 | ||
745 | static __used void brcmf_pcie_ringbell_v1(struct brcmf_pciedev_info *devinfo) | ||
746 | { | ||
747 | u32 reg_value; | ||
748 | |||
749 | brcmf_dbg(PCIE, "RING !\n"); | ||
750 | reg_value = brcmf_pcie_read_reg32(devinfo, | ||
751 | BRCMF_PCIE_PCIE2REG_MAILBOXINT); | ||
752 | reg_value |= BRCMF_PCIE2_INTB; | ||
753 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, | ||
754 | reg_value); | ||
755 | } | ||
756 | |||
757 | |||
758 | static void brcmf_pcie_ringbell_v2(struct brcmf_pciedev_info *devinfo) | ||
759 | { | ||
760 | brcmf_dbg(PCIE, "RING !\n"); | ||
761 | /* Any arbitrary value will do, lets use 1 */ | ||
762 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX, 1); | ||
763 | } | ||
764 | |||
765 | |||
766 | static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo) | 747 | static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo) |
767 | { | 748 | { |
768 | if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) | 749 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, 0); |
769 | pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK, | ||
770 | 0); | ||
771 | else | ||
772 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, | ||
773 | 0); | ||
774 | } | 750 | } |
775 | 751 | ||
776 | 752 | ||
777 | static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo) | 753 | static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo) |
778 | { | 754 | { |
779 | if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) | 755 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, |
780 | pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK, | 756 | BRCMF_PCIE_MB_INT_D2H_DB | |
781 | BRCMF_PCIE_INT_DEF); | 757 | BRCMF_PCIE_MB_INT_FN0_0 | |
782 | else | 758 | BRCMF_PCIE_MB_INT_FN0_1); |
783 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, | ||
784 | BRCMF_PCIE_MB_INT_D2H_DB | | ||
785 | BRCMF_PCIE_MB_INT_FN0_0 | | ||
786 | BRCMF_PCIE_MB_INT_FN0_1); | ||
787 | } | ||
788 | |||
789 | |||
790 | static irqreturn_t brcmf_pcie_quick_check_isr_v1(int irq, void *arg) | ||
791 | { | ||
792 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; | ||
793 | u32 status; | ||
794 | |||
795 | status = 0; | ||
796 | pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTSTATUS, &status); | ||
797 | if (status) { | ||
798 | brcmf_pcie_intr_disable(devinfo); | ||
799 | brcmf_dbg(PCIE, "Enter\n"); | ||
800 | return IRQ_WAKE_THREAD; | ||
801 | } | ||
802 | return IRQ_NONE; | ||
803 | } | 759 | } |
804 | 760 | ||
805 | 761 | ||
806 | static irqreturn_t brcmf_pcie_quick_check_isr_v2(int irq, void *arg) | 762 | static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg) |
807 | { | 763 | { |
808 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; | 764 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; |
809 | 765 | ||
@@ -816,29 +772,7 @@ static irqreturn_t brcmf_pcie_quick_check_isr_v2(int irq, void *arg) | |||
816 | } | 772 | } |
817 | 773 | ||
818 | 774 | ||
819 | static irqreturn_t brcmf_pcie_isr_thread_v1(int irq, void *arg) | 775 | static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg) |
820 | { | ||
821 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; | ||
822 | const struct pci_dev *pdev = devinfo->pdev; | ||
823 | u32 status; | ||
824 | |||
825 | devinfo->in_irq = true; | ||
826 | status = 0; | ||
827 | pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status); | ||
828 | brcmf_dbg(PCIE, "Enter %x\n", status); | ||
829 | if (status) { | ||
830 | pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status); | ||
831 | if (devinfo->state == BRCMFMAC_PCIE_STATE_UP) | ||
832 | brcmf_proto_msgbuf_rx_trigger(&devinfo->pdev->dev); | ||
833 | } | ||
834 | if (devinfo->state == BRCMFMAC_PCIE_STATE_UP) | ||
835 | brcmf_pcie_intr_enable(devinfo); | ||
836 | devinfo->in_irq = false; | ||
837 | return IRQ_HANDLED; | ||
838 | } | ||
839 | |||
840 | |||
841 | static irqreturn_t brcmf_pcie_isr_thread_v2(int irq, void *arg) | ||
842 | { | 776 | { |
843 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; | 777 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; |
844 | u32 status; | 778 | u32 status; |
@@ -875,28 +809,14 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo) | |||
875 | brcmf_pcie_intr_disable(devinfo); | 809 | brcmf_pcie_intr_disable(devinfo); |
876 | 810 | ||
877 | brcmf_dbg(PCIE, "Enter\n"); | 811 | brcmf_dbg(PCIE, "Enter\n"); |
878 | /* is it a v1 or v2 implementation */ | 812 | |
879 | pci_enable_msi(pdev); | 813 | pci_enable_msi(pdev); |
880 | if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) { | 814 | if (request_threaded_irq(pdev->irq, brcmf_pcie_quick_check_isr, |
881 | if (request_threaded_irq(pdev->irq, | 815 | brcmf_pcie_isr_thread, IRQF_SHARED, |
882 | brcmf_pcie_quick_check_isr_v1, | 816 | "brcmf_pcie_intr", devinfo)) { |
883 | brcmf_pcie_isr_thread_v1, | 817 | pci_disable_msi(pdev); |
884 | IRQF_SHARED, "brcmf_pcie_intr", | 818 | brcmf_err("Failed to request IRQ %d\n", pdev->irq); |
885 | devinfo)) { | 819 | return -EIO; |
886 | pci_disable_msi(pdev); | ||
887 | brcmf_err("Failed to request IRQ %d\n", pdev->irq); | ||
888 | return -EIO; | ||
889 | } | ||
890 | } else { | ||
891 | if (request_threaded_irq(pdev->irq, | ||
892 | brcmf_pcie_quick_check_isr_v2, | ||
893 | brcmf_pcie_isr_thread_v2, | ||
894 | IRQF_SHARED, "brcmf_pcie_intr", | ||
895 | devinfo)) { | ||
896 | pci_disable_msi(pdev); | ||
897 | brcmf_err("Failed to request IRQ %d\n", pdev->irq); | ||
898 | return -EIO; | ||
899 | } | ||
900 | } | 820 | } |
901 | devinfo->irq_allocated = true; | 821 | devinfo->irq_allocated = true; |
902 | return 0; | 822 | return 0; |
@@ -927,16 +847,9 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo) | |||
927 | if (devinfo->in_irq) | 847 | if (devinfo->in_irq) |
928 | brcmf_err("Still in IRQ (processing) !!!\n"); | 848 | brcmf_err("Still in IRQ (processing) !!!\n"); |
929 | 849 | ||
930 | if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) { | 850 | status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); |
931 | status = 0; | 851 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status); |
932 | pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status); | 852 | |
933 | pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status); | ||
934 | } else { | ||
935 | status = brcmf_pcie_read_reg32(devinfo, | ||
936 | BRCMF_PCIE_PCIE2REG_MAILBOXINT); | ||
937 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, | ||
938 | status); | ||
939 | } | ||
940 | devinfo->irq_allocated = false; | 853 | devinfo->irq_allocated = false; |
941 | } | 854 | } |
942 | 855 | ||
@@ -985,7 +898,9 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx) | |||
985 | if (devinfo->state != BRCMFMAC_PCIE_STATE_UP) | 898 | if (devinfo->state != BRCMFMAC_PCIE_STATE_UP) |
986 | return -EIO; | 899 | return -EIO; |
987 | 900 | ||
988 | devinfo->ringbell(devinfo); | 901 | brcmf_dbg(PCIE, "RING !\n"); |
902 | /* Any arbitrary value will do, lets use 1 */ | ||
903 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX, 1); | ||
989 | 904 | ||
990 | return 0; | 905 | return 0; |
991 | } | 906 | } |
@@ -1412,6 +1327,28 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { | |||
1412 | }; | 1327 | }; |
1413 | 1328 | ||
1414 | 1329 | ||
1330 | static void | ||
1331 | brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data, | ||
1332 | u32 data_len) | ||
1333 | { | ||
1334 | __le32 *field; | ||
1335 | u32 newsize; | ||
1336 | |||
1337 | if (data_len < BRCMF_RAMSIZE_OFFSET + 8) | ||
1338 | return; | ||
1339 | |||
1340 | field = (__le32 *)&data[BRCMF_RAMSIZE_OFFSET]; | ||
1341 | if (le32_to_cpup(field) != BRCMF_RAMSIZE_MAGIC) | ||
1342 | return; | ||
1343 | field++; | ||
1344 | newsize = le32_to_cpup(field); | ||
1345 | |||
1346 | brcmf_dbg(PCIE, "Found ramsize info in FW, adjusting to 0x%x\n", | ||
1347 | newsize); | ||
1348 | devinfo->ci->ramsize = newsize; | ||
1349 | } | ||
1350 | |||
1351 | |||
1415 | static int | 1352 | static int |
1416 | brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo, | 1353 | brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo, |
1417 | u32 sharedram_addr) | 1354 | u32 sharedram_addr) |
@@ -1477,9 +1414,6 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, | |||
1477 | u32 address; | 1414 | u32 address; |
1478 | u32 resetintr; | 1415 | u32 resetintr; |
1479 | 1416 | ||
1480 | devinfo->ringbell = brcmf_pcie_ringbell_v2; | ||
1481 | devinfo->generic_corerev = BRCMF_PCIE_GENREV2; | ||
1482 | |||
1483 | brcmf_dbg(PCIE, "Halt ARM.\n"); | 1417 | brcmf_dbg(PCIE, "Halt ARM.\n"); |
1484 | err = brcmf_pcie_enter_download_state(devinfo); | 1418 | err = brcmf_pcie_enter_download_state(devinfo); |
1485 | if (err) | 1419 | if (err) |
@@ -1566,8 +1500,7 @@ static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo) | |||
1566 | } | 1500 | } |
1567 | 1501 | ||
1568 | devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE); | 1502 | devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE); |
1569 | devinfo->tcm = ioremap_nocache(bar1_addr, BRCMF_PCIE_TCM_MAP_SIZE); | 1503 | devinfo->tcm = ioremap_nocache(bar1_addr, bar1_size); |
1570 | devinfo->tcm_size = BRCMF_PCIE_TCM_MAP_SIZE; | ||
1571 | 1504 | ||
1572 | if (!devinfo->regs || !devinfo->tcm) { | 1505 | if (!devinfo->regs || !devinfo->tcm) { |
1573 | brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs, | 1506 | brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs, |
@@ -1576,8 +1509,9 @@ static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo) | |||
1576 | } | 1509 | } |
1577 | brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n", | 1510 | brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n", |
1578 | devinfo->regs, (unsigned long long)bar0_addr); | 1511 | devinfo->regs, (unsigned long long)bar0_addr); |
1579 | brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx\n", | 1512 | brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx size 0x%x\n", |
1580 | devinfo->tcm, (unsigned long long)bar1_addr); | 1513 | devinfo->tcm, (unsigned long long)bar1_addr, |
1514 | (unsigned int)bar1_size); | ||
1581 | 1515 | ||
1582 | return 0; | 1516 | return 0; |
1583 | } | 1517 | } |
@@ -1594,16 +1528,16 @@ static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo) | |||
1594 | } | 1528 | } |
1595 | 1529 | ||
1596 | 1530 | ||
1597 | static int brcmf_pcie_attach_bus(struct device *dev) | 1531 | static int brcmf_pcie_attach_bus(struct brcmf_pciedev_info *devinfo) |
1598 | { | 1532 | { |
1599 | int ret; | 1533 | int ret; |
1600 | 1534 | ||
1601 | /* Attach to the common driver interface */ | 1535 | /* Attach to the common driver interface */ |
1602 | ret = brcmf_attach(dev); | 1536 | ret = brcmf_attach(&devinfo->pdev->dev, devinfo->settings); |
1603 | if (ret) { | 1537 | if (ret) { |
1604 | brcmf_err("brcmf_attach failed\n"); | 1538 | brcmf_err("brcmf_attach failed\n"); |
1605 | } else { | 1539 | } else { |
1606 | ret = brcmf_bus_start(dev); | 1540 | ret = brcmf_bus_start(&devinfo->pdev->dev); |
1607 | if (ret) | 1541 | if (ret) |
1608 | brcmf_err("dongle is not responding\n"); | 1542 | brcmf_err("dongle is not responding\n"); |
1609 | } | 1543 | } |
@@ -1694,6 +1628,13 @@ static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, | |||
1694 | 1628 | ||
1695 | brcmf_pcie_attach(devinfo); | 1629 | brcmf_pcie_attach(devinfo); |
1696 | 1630 | ||
1631 | /* Some of the firmwares have the size of the memory of the device | ||
1632 | * defined inside the firmware. This is because part of the memory in | ||
1633 | * the device is shared and the devision is determined by FW. Parse | ||
1634 | * the firmware and adjust the chip memory size now. | ||
1635 | */ | ||
1636 | brcmf_pcie_adjust_ramsize(devinfo, (u8 *)fw->data, fw->size); | ||
1637 | |||
1697 | ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len); | 1638 | ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len); |
1698 | if (ret) | 1639 | if (ret) |
1699 | goto fail; | 1640 | goto fail; |
@@ -1734,7 +1675,7 @@ static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, | |||
1734 | init_waitqueue_head(&devinfo->mbdata_resp_wait); | 1675 | init_waitqueue_head(&devinfo->mbdata_resp_wait); |
1735 | 1676 | ||
1736 | brcmf_pcie_intr_enable(devinfo); | 1677 | brcmf_pcie_intr_enable(devinfo); |
1737 | if (brcmf_pcie_attach_bus(bus->dev) == 0) | 1678 | if (brcmf_pcie_attach_bus(devinfo) == 0) |
1738 | return; | 1679 | return; |
1739 | 1680 | ||
1740 | brcmf_pcie_bus_console_read(devinfo); | 1681 | brcmf_pcie_bus_console_read(devinfo); |
@@ -1778,6 +1719,15 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1778 | goto fail; | 1719 | goto fail; |
1779 | } | 1720 | } |
1780 | 1721 | ||
1722 | devinfo->settings = brcmf_get_module_param(&devinfo->pdev->dev, | ||
1723 | BRCMF_BUSTYPE_PCIE, | ||
1724 | devinfo->ci->chip, | ||
1725 | devinfo->ci->chiprev); | ||
1726 | if (!devinfo->settings) { | ||
1727 | ret = -ENOMEM; | ||
1728 | goto fail; | ||
1729 | } | ||
1730 | |||
1781 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); | 1731 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); |
1782 | if (!bus) { | 1732 | if (!bus) { |
1783 | ret = -ENOMEM; | 1733 | ret = -ENOMEM; |
@@ -1822,6 +1772,8 @@ fail: | |||
1822 | brcmf_pcie_release_resource(devinfo); | 1772 | brcmf_pcie_release_resource(devinfo); |
1823 | if (devinfo->ci) | 1773 | if (devinfo->ci) |
1824 | brcmf_chip_detach(devinfo->ci); | 1774 | brcmf_chip_detach(devinfo->ci); |
1775 | if (devinfo->settings) | ||
1776 | brcmf_release_module_param(devinfo->settings); | ||
1825 | kfree(pcie_bus_dev); | 1777 | kfree(pcie_bus_dev); |
1826 | kfree(devinfo); | 1778 | kfree(devinfo); |
1827 | return ret; | 1779 | return ret; |
@@ -1861,6 +1813,8 @@ brcmf_pcie_remove(struct pci_dev *pdev) | |||
1861 | 1813 | ||
1862 | if (devinfo->ci) | 1814 | if (devinfo->ci) |
1863 | brcmf_chip_detach(devinfo->ci); | 1815 | brcmf_chip_detach(devinfo->ci); |
1816 | if (devinfo->settings) | ||
1817 | brcmf_release_module_param(devinfo->settings); | ||
1864 | 1818 | ||
1865 | kfree(devinfo); | 1819 | kfree(devinfo); |
1866 | dev_set_drvdata(&pdev->dev, NULL); | 1820 | dev_set_drvdata(&pdev->dev, NULL); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index c790fa89db05..43fd3f402eba 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | |||
@@ -33,8 +33,6 @@ | |||
33 | #include <linux/bcma/bcma.h> | 33 | #include <linux/bcma/bcma.h> |
34 | #include <linux/debugfs.h> | 34 | #include <linux/debugfs.h> |
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <linux/platform_data/brcmfmac-sdio.h> | ||
37 | #include <linux/moduleparam.h> | ||
38 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
39 | #include <defs.h> | 37 | #include <defs.h> |
40 | #include <brcmu_wifi.h> | 38 | #include <brcmu_wifi.h> |
@@ -44,6 +42,8 @@ | |||
44 | #include "sdio.h" | 42 | #include "sdio.h" |
45 | #include "chip.h" | 43 | #include "chip.h" |
46 | #include "firmware.h" | 44 | #include "firmware.h" |
45 | #include "core.h" | ||
46 | #include "common.h" | ||
47 | 47 | ||
48 | #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) | 48 | #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) |
49 | #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) | 49 | #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) |
@@ -2442,15 +2442,17 @@ static void brcmf_sdio_bus_stop(struct device *dev) | |||
2442 | 2442 | ||
2443 | static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus) | 2443 | static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus) |
2444 | { | 2444 | { |
2445 | struct brcmf_sdio_dev *sdiodev; | ||
2445 | unsigned long flags; | 2446 | unsigned long flags; |
2446 | 2447 | ||
2447 | if (bus->sdiodev->oob_irq_requested) { | 2448 | sdiodev = bus->sdiodev; |
2448 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); | 2449 | if (sdiodev->oob_irq_requested) { |
2449 | if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { | 2450 | spin_lock_irqsave(&sdiodev->irq_en_lock, flags); |
2450 | enable_irq(bus->sdiodev->pdata->oob_irq_nr); | 2451 | if (!sdiodev->irq_en && !atomic_read(&bus->ipend)) { |
2451 | bus->sdiodev->irq_en = true; | 2452 | enable_irq(sdiodev->settings->bus.sdio.oob_irq_nr); |
2453 | sdiodev->irq_en = true; | ||
2452 | } | 2454 | } |
2453 | spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags); | 2455 | spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags); |
2454 | } | 2456 | } |
2455 | } | 2457 | } |
2456 | 2458 | ||
@@ -3394,9 +3396,7 @@ static int brcmf_sdio_bus_preinit(struct device *dev) | |||
3394 | sizeof(u32)); | 3396 | sizeof(u32)); |
3395 | } else { | 3397 | } else { |
3396 | /* otherwise, set txglomalign */ | 3398 | /* otherwise, set txglomalign */ |
3397 | value = 4; | 3399 | value = sdiodev->settings->bus.sdio.sd_sgentry_align; |
3398 | if (sdiodev->pdata) | ||
3399 | value = sdiodev->pdata->sd_sgentry_align; | ||
3400 | /* SDIO ADMA requires at least 32 bit alignment */ | 3400 | /* SDIO ADMA requires at least 32 bit alignment */ |
3401 | value = max_t(u32, value, 4); | 3401 | value = max_t(u32, value, 4); |
3402 | err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value, | 3402 | err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value, |
@@ -3775,26 +3775,28 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { | |||
3775 | static bool | 3775 | static bool |
3776 | brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | 3776 | brcmf_sdio_probe_attach(struct brcmf_sdio *bus) |
3777 | { | 3777 | { |
3778 | struct brcmf_sdio_dev *sdiodev; | ||
3778 | u8 clkctl = 0; | 3779 | u8 clkctl = 0; |
3779 | int err = 0; | 3780 | int err = 0; |
3780 | int reg_addr; | 3781 | int reg_addr; |
3781 | u32 reg_val; | 3782 | u32 reg_val; |
3782 | u32 drivestrength; | 3783 | u32 drivestrength; |
3783 | 3784 | ||
3784 | sdio_claim_host(bus->sdiodev->func[1]); | 3785 | sdiodev = bus->sdiodev; |
3786 | sdio_claim_host(sdiodev->func[1]); | ||
3785 | 3787 | ||
3786 | pr_debug("F1 signature read @0x18000000=0x%4x\n", | 3788 | pr_debug("F1 signature read @0x18000000=0x%4x\n", |
3787 | brcmf_sdiod_regrl(bus->sdiodev, SI_ENUM_BASE, NULL)); | 3789 | brcmf_sdiod_regrl(sdiodev, SI_ENUM_BASE, NULL)); |
3788 | 3790 | ||
3789 | /* | 3791 | /* |
3790 | * Force PLL off until brcmf_chip_attach() | 3792 | * Force PLL off until brcmf_chip_attach() |
3791 | * programs PLL control regs | 3793 | * programs PLL control regs |
3792 | */ | 3794 | */ |
3793 | 3795 | ||
3794 | brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 3796 | brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
3795 | BRCMF_INIT_CLKCTL1, &err); | 3797 | BRCMF_INIT_CLKCTL1, &err); |
3796 | if (!err) | 3798 | if (!err) |
3797 | clkctl = brcmf_sdiod_regrb(bus->sdiodev, | 3799 | clkctl = brcmf_sdiod_regrb(sdiodev, |
3798 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 3800 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
3799 | 3801 | ||
3800 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { | 3802 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { |
@@ -3803,50 +3805,81 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | |||
3803 | goto fail; | 3805 | goto fail; |
3804 | } | 3806 | } |
3805 | 3807 | ||
3806 | bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops); | 3808 | bus->ci = brcmf_chip_attach(sdiodev, &brcmf_sdio_buscore_ops); |
3807 | if (IS_ERR(bus->ci)) { | 3809 | if (IS_ERR(bus->ci)) { |
3808 | brcmf_err("brcmf_chip_attach failed!\n"); | 3810 | brcmf_err("brcmf_chip_attach failed!\n"); |
3809 | bus->ci = NULL; | 3811 | bus->ci = NULL; |
3810 | goto fail; | 3812 | goto fail; |
3811 | } | 3813 | } |
3814 | sdiodev->settings = brcmf_get_module_param(sdiodev->dev, | ||
3815 | BRCMF_BUSTYPE_SDIO, | ||
3816 | bus->ci->chip, | ||
3817 | bus->ci->chiprev); | ||
3818 | if (!sdiodev->settings) { | ||
3819 | brcmf_err("Failed to get device parameters\n"); | ||
3820 | goto fail; | ||
3821 | } | ||
3822 | /* platform specific configuration: | ||
3823 | * alignments must be at least 4 bytes for ADMA | ||
3824 | */ | ||
3825 | bus->head_align = ALIGNMENT; | ||
3826 | bus->sgentry_align = ALIGNMENT; | ||
3827 | if (sdiodev->settings->bus.sdio.sd_head_align > ALIGNMENT) | ||
3828 | bus->head_align = sdiodev->settings->bus.sdio.sd_head_align; | ||
3829 | if (sdiodev->settings->bus.sdio.sd_sgentry_align > ALIGNMENT) | ||
3830 | bus->sgentry_align = | ||
3831 | sdiodev->settings->bus.sdio.sd_sgentry_align; | ||
3832 | |||
3833 | /* allocate scatter-gather table. sg support | ||
3834 | * will be disabled upon allocation failure. | ||
3835 | */ | ||
3836 | brcmf_sdiod_sgtable_alloc(sdiodev); | ||
3837 | |||
3838 | #ifdef CONFIG_PM_SLEEP | ||
3839 | /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ | ||
3840 | * is true or when platform data OOB irq is true). | ||
3841 | */ | ||
3842 | if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) && | ||
3843 | ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) || | ||
3844 | (sdiodev->settings->bus.sdio.oob_irq_supported))) | ||
3845 | sdiodev->bus_if->wowl_supported = true; | ||
3846 | #endif | ||
3812 | 3847 | ||
3813 | if (brcmf_sdio_kso_init(bus)) { | 3848 | if (brcmf_sdio_kso_init(bus)) { |
3814 | brcmf_err("error enabling KSO\n"); | 3849 | brcmf_err("error enabling KSO\n"); |
3815 | goto fail; | 3850 | goto fail; |
3816 | } | 3851 | } |
3817 | 3852 | ||
3818 | if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength)) | 3853 | if (sdiodev->settings->bus.sdio.drive_strength) |
3819 | drivestrength = bus->sdiodev->pdata->drive_strength; | 3854 | drivestrength = sdiodev->settings->bus.sdio.drive_strength; |
3820 | else | 3855 | else |
3821 | drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; | 3856 | drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; |
3822 | brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength); | 3857 | brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength); |
3823 | 3858 | ||
3824 | /* Set card control so an SDIO card reset does a WLAN backplane reset */ | 3859 | /* Set card control so an SDIO card reset does a WLAN backplane reset */ |
3825 | reg_val = brcmf_sdiod_regrb(bus->sdiodev, | 3860 | reg_val = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err); |
3826 | SDIO_CCCR_BRCM_CARDCTRL, &err); | ||
3827 | if (err) | 3861 | if (err) |
3828 | goto fail; | 3862 | goto fail; |
3829 | 3863 | ||
3830 | reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET; | 3864 | reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET; |
3831 | 3865 | ||
3832 | brcmf_sdiod_regwb(bus->sdiodev, | 3866 | brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err); |
3833 | SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err); | ||
3834 | if (err) | 3867 | if (err) |
3835 | goto fail; | 3868 | goto fail; |
3836 | 3869 | ||
3837 | /* set PMUControl so a backplane reset does PMU state reload */ | 3870 | /* set PMUControl so a backplane reset does PMU state reload */ |
3838 | reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol); | 3871 | reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol); |
3839 | reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err); | 3872 | reg_val = brcmf_sdiod_regrl(sdiodev, reg_addr, &err); |
3840 | if (err) | 3873 | if (err) |
3841 | goto fail; | 3874 | goto fail; |
3842 | 3875 | ||
3843 | reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT); | 3876 | reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT); |
3844 | 3877 | ||
3845 | brcmf_sdiod_regwl(bus->sdiodev, reg_addr, reg_val, &err); | 3878 | brcmf_sdiod_regwl(sdiodev, reg_addr, reg_val, &err); |
3846 | if (err) | 3879 | if (err) |
3847 | goto fail; | 3880 | goto fail; |
3848 | 3881 | ||
3849 | sdio_release_host(bus->sdiodev->func[1]); | 3882 | sdio_release_host(sdiodev->func[1]); |
3850 | 3883 | ||
3851 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); | 3884 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); |
3852 | 3885 | ||
@@ -3867,7 +3900,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | |||
3867 | return true; | 3900 | return true; |
3868 | 3901 | ||
3869 | fail: | 3902 | fail: |
3870 | sdio_release_host(bus->sdiodev->func[1]); | 3903 | sdio_release_host(sdiodev->func[1]); |
3871 | return false; | 3904 | return false; |
3872 | } | 3905 | } |
3873 | 3906 | ||
@@ -4045,18 +4078,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4045 | bus->txminmax = BRCMF_TXMINMAX; | 4078 | bus->txminmax = BRCMF_TXMINMAX; |
4046 | bus->tx_seq = SDPCM_SEQ_WRAP - 1; | 4079 | bus->tx_seq = SDPCM_SEQ_WRAP - 1; |
4047 | 4080 | ||
4048 | /* platform specific configuration: | ||
4049 | * alignments must be at least 4 bytes for ADMA | ||
4050 | */ | ||
4051 | bus->head_align = ALIGNMENT; | ||
4052 | bus->sgentry_align = ALIGNMENT; | ||
4053 | if (sdiodev->pdata) { | ||
4054 | if (sdiodev->pdata->sd_head_align > ALIGNMENT) | ||
4055 | bus->head_align = sdiodev->pdata->sd_head_align; | ||
4056 | if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT) | ||
4057 | bus->sgentry_align = sdiodev->pdata->sd_sgentry_align; | ||
4058 | } | ||
4059 | |||
4060 | /* single-threaded workqueue */ | 4081 | /* single-threaded workqueue */ |
4061 | wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM, | 4082 | wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM, |
4062 | dev_name(&sdiodev->func[1]->dev)); | 4083 | dev_name(&sdiodev->func[1]->dev)); |
@@ -4107,7 +4128,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4107 | bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; | 4128 | bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; |
4108 | 4129 | ||
4109 | /* Attach to the common layer, reserve hdr space */ | 4130 | /* Attach to the common layer, reserve hdr space */ |
4110 | ret = brcmf_attach(bus->sdiodev->dev); | 4131 | ret = brcmf_attach(bus->sdiodev->dev, bus->sdiodev->settings); |
4111 | if (ret != 0) { | 4132 | if (ret != 0) { |
4112 | brcmf_err("brcmf_attach failed\n"); | 4133 | brcmf_err("brcmf_attach failed\n"); |
4113 | goto fail; | 4134 | goto fail; |
@@ -4211,6 +4232,8 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) | |||
4211 | } | 4232 | } |
4212 | brcmf_chip_detach(bus->ci); | 4233 | brcmf_chip_detach(bus->ci); |
4213 | } | 4234 | } |
4235 | if (bus->sdiodev->settings) | ||
4236 | brcmf_release_module_param(bus->sdiodev->settings); | ||
4214 | 4237 | ||
4215 | kfree(bus->rxbuf); | 4238 | kfree(bus->rxbuf); |
4216 | kfree(bus->hdrbuf); | 4239 | kfree(bus->hdrbuf); |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h index 23f223150cef..dcf0ce8cd2c1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | |||
@@ -184,7 +184,7 @@ struct brcmf_sdio_dev { | |||
184 | struct brcmf_sdio *bus; | 184 | struct brcmf_sdio *bus; |
185 | struct device *dev; | 185 | struct device *dev; |
186 | struct brcmf_bus *bus_if; | 186 | struct brcmf_bus *bus_if; |
187 | struct brcmfmac_sdio_platform_data *pdata; | 187 | struct brcmf_mp_device *settings; |
188 | bool oob_irq_requested; | 188 | bool oob_irq_requested; |
189 | bool irq_en; /* irq enable flags */ | 189 | bool irq_en; /* irq enable flags */ |
190 | spinlock_t irq_en_lock; | 190 | spinlock_t irq_en_lock; |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index c72b7b352a77..869eb82db8b1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include "debug.h" | 27 | #include "debug.h" |
28 | #include "firmware.h" | 28 | #include "firmware.h" |
29 | #include "usb.h" | 29 | #include "usb.h" |
30 | #include "core.h" | ||
31 | #include "common.h" | ||
30 | 32 | ||
31 | 33 | ||
32 | #define IOCTL_RESP_TIMEOUT msecs_to_jiffies(2000) | 34 | #define IOCTL_RESP_TIMEOUT msecs_to_jiffies(2000) |
@@ -171,6 +173,7 @@ struct brcmf_usbdev_info { | |||
171 | struct urb *bulk_urb; /* used for FW download */ | 173 | struct urb *bulk_urb; /* used for FW download */ |
172 | 174 | ||
173 | bool wowl_enabled; | 175 | bool wowl_enabled; |
176 | struct brcmf_mp_device *settings; | ||
174 | }; | 177 | }; |
175 | 178 | ||
176 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, | 179 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, |
@@ -1027,6 +1030,9 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) | |||
1027 | 1030 | ||
1028 | kfree(devinfo->tx_reqs); | 1031 | kfree(devinfo->tx_reqs); |
1029 | kfree(devinfo->rx_reqs); | 1032 | kfree(devinfo->rx_reqs); |
1033 | |||
1034 | if (devinfo->settings) | ||
1035 | brcmf_release_module_param(devinfo->settings); | ||
1030 | } | 1036 | } |
1031 | 1037 | ||
1032 | 1038 | ||
@@ -1136,7 +1142,7 @@ static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) | |||
1136 | int ret; | 1142 | int ret; |
1137 | 1143 | ||
1138 | /* Attach to the common driver interface */ | 1144 | /* Attach to the common driver interface */ |
1139 | ret = brcmf_attach(devinfo->dev); | 1145 | ret = brcmf_attach(devinfo->dev, devinfo->settings); |
1140 | if (ret) { | 1146 | if (ret) { |
1141 | brcmf_err("brcmf_attach failed\n"); | 1147 | brcmf_err("brcmf_attach failed\n"); |
1142 | return ret; | 1148 | return ret; |
@@ -1223,6 +1229,14 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) | |||
1223 | bus->wowl_supported = true; | 1229 | bus->wowl_supported = true; |
1224 | #endif | 1230 | #endif |
1225 | 1231 | ||
1232 | devinfo->settings = brcmf_get_module_param(bus->dev, BRCMF_BUSTYPE_USB, | ||
1233 | bus_pub->devid, | ||
1234 | bus_pub->chiprev); | ||
1235 | if (!devinfo->settings) { | ||
1236 | ret = -ENOMEM; | ||
1237 | goto fail; | ||
1238 | } | ||
1239 | |||
1226 | if (!brcmf_usb_dlneeded(devinfo)) { | 1240 | if (!brcmf_usb_dlneeded(devinfo)) { |
1227 | ret = brcmf_usb_bus_setup(devinfo); | 1241 | ret = brcmf_usb_bus_setup(devinfo); |
1228 | if (ret) | 1242 | if (ret) |
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h index 3f68dd5ecd11..7b9a77981df1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h | |||
@@ -236,6 +236,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) | |||
236 | #define WPA2_AUTH_RESERVED3 0x0200 | 236 | #define WPA2_AUTH_RESERVED3 0x0200 |
237 | #define WPA2_AUTH_RESERVED4 0x0400 | 237 | #define WPA2_AUTH_RESERVED4 0x0400 |
238 | #define WPA2_AUTH_RESERVED5 0x0800 | 238 | #define WPA2_AUTH_RESERVED5 0x0800 |
239 | #define WPA2_AUTH_1X_SHA256 0x1000 /* 1X with SHA256 key derivation */ | ||
240 | #define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */ | ||
239 | 241 | ||
240 | #define DOT11_DEFAULT_RTS_LEN 2347 | 242 | #define DOT11_DEFAULT_RTS_LEN 2347 |
241 | #define DOT11_DEFAULT_FRAG_LEN 2346 | 243 | #define DOT11_DEFAULT_FRAG_LEN 2346 |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index fa41a5e1c890..fc475ce59b47 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c | |||
@@ -73,8 +73,8 @@ | |||
73 | /* Highest firmware API version supported */ | 73 | /* Highest firmware API version supported */ |
74 | #define IWL7260_UCODE_API_MAX 17 | 74 | #define IWL7260_UCODE_API_MAX 17 |
75 | #define IWL7265_UCODE_API_MAX 17 | 75 | #define IWL7265_UCODE_API_MAX 17 |
76 | #define IWL7265D_UCODE_API_MAX 20 | 76 | #define IWL7265D_UCODE_API_MAX 21 |
77 | #define IWL3168_UCODE_API_MAX 20 | 77 | #define IWL3168_UCODE_API_MAX 21 |
78 | 78 | ||
79 | /* Oldest version we won't warn about */ | 79 | /* Oldest version we won't warn about */ |
80 | #define IWL7260_UCODE_API_OK 13 | 80 | #define IWL7260_UCODE_API_OK 13 |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index bce9b3420a13..97be104d1203 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c | |||
@@ -70,8 +70,8 @@ | |||
70 | #include "iwl-agn-hw.h" | 70 | #include "iwl-agn-hw.h" |
71 | 71 | ||
72 | /* Highest firmware API version supported */ | 72 | /* Highest firmware API version supported */ |
73 | #define IWL8000_UCODE_API_MAX 20 | 73 | #define IWL8000_UCODE_API_MAX 21 |
74 | #define IWL8265_UCODE_API_MAX 20 | 74 | #define IWL8265_UCODE_API_MAX 21 |
75 | 75 | ||
76 | /* Oldest version we won't warn about */ | 76 | /* Oldest version we won't warn about */ |
77 | #define IWL8000_UCODE_API_OK 13 | 77 | #define IWL8000_UCODE_API_OK 13 |
@@ -217,6 +217,7 @@ const struct iwl_cfg iwl8265_2ac_cfg = { | |||
217 | .nvm_ver = IWL8000_NVM_VERSION, | 217 | .nvm_ver = IWL8000_NVM_VERSION, |
218 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 218 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
219 | .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, | 219 | .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, |
220 | .vht_mu_mimo_supported = true, | ||
220 | }; | 221 | }; |
221 | 222 | ||
222 | const struct iwl_cfg iwl4165_2ac_cfg = { | 223 | const struct iwl_cfg iwl4165_2ac_cfg = { |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index 4b93404f46a7..8e32a57dda0f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #include "iwl-agn-hw.h" | 55 | #include "iwl-agn-hw.h" |
56 | 56 | ||
57 | /* Highest firmware API version supported */ | 57 | /* Highest firmware API version supported */ |
58 | #define IWL9000_UCODE_API_MAX 20 | 58 | #define IWL9000_UCODE_API_MAX 21 |
59 | 59 | ||
60 | /* Oldest version we won't warn about */ | 60 | /* Oldest version we won't warn about */ |
61 | #define IWL9000_UCODE_API_OK 13 | 61 | #define IWL9000_UCODE_API_OK 13 |
@@ -139,7 +139,8 @@ static const struct iwl_tt_params iwl9000_tt_params = { | |||
139 | .smem_len = IWL9000_SMEM_LEN, \ | 139 | .smem_len = IWL9000_SMEM_LEN, \ |
140 | .thermal_params = &iwl9000_tt_params, \ | 140 | .thermal_params = &iwl9000_tt_params, \ |
141 | .apmg_not_supported = true, \ | 141 | .apmg_not_supported = true, \ |
142 | .mq_rx_supported = true | 142 | .mq_rx_supported = true, \ |
143 | .vht_mu_mimo_supported = true | ||
143 | 144 | ||
144 | const struct iwl_cfg iwl9260_2ac_cfg = { | 145 | const struct iwl_cfg iwl9260_2ac_cfg = { |
145 | .name = "Intel(R) Dual Band Wireless AC 9260", | 146 | .name = "Intel(R) Dual Band Wireless AC 9260", |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index dad5570d6cc8..4f2b57e8bbc7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h | |||
@@ -312,6 +312,7 @@ struct iwl_pwr_tx_backoff { | |||
312 | * @smem_offset: offset from which the SMEM begins | 312 | * @smem_offset: offset from which the SMEM begins |
313 | * @smem_len: the length of SMEM | 313 | * @smem_len: the length of SMEM |
314 | * @mq_rx_supported: multi-queue rx support | 314 | * @mq_rx_supported: multi-queue rx support |
315 | * @vht_mu_mimo_supported: VHT MU-MIMO support | ||
315 | * | 316 | * |
316 | * We enable the driver to be backward compatible wrt. hardware features. | 317 | * We enable the driver to be backward compatible wrt. hardware features. |
317 | * API differences in uCode shouldn't be handled here but through TLVs | 318 | * API differences in uCode shouldn't be handled here but through TLVs |
@@ -364,6 +365,7 @@ struct iwl_cfg { | |||
364 | const struct iwl_tt_params *thermal_params; | 365 | const struct iwl_tt_params *thermal_params; |
365 | bool apmg_not_supported; | 366 | bool apmg_not_supported; |
366 | bool mq_rx_supported; | 367 | bool mq_rx_supported; |
368 | bool vht_mu_mimo_supported; | ||
367 | }; | 369 | }; |
368 | 370 | ||
369 | /* | 371 | /* |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 163b21bc20cb..a79c4f61a851 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -549,4 +550,52 @@ enum dtd_diode_reg { | |||
549 | DTS_DIODE_REG_FLAGS_PASS_ONCE = 0x00000080, /* bits [7:7] */ | 550 | DTS_DIODE_REG_FLAGS_PASS_ONCE = 0x00000080, /* bits [7:7] */ |
550 | }; | 551 | }; |
551 | 552 | ||
553 | /***************************************************************************** | ||
554 | * MSIX related registers * | ||
555 | *****************************************************************************/ | ||
556 | |||
557 | #define CSR_MSIX_BASE (0x2000) | ||
558 | #define CSR_MSIX_FH_INT_CAUSES_AD (CSR_MSIX_BASE + 0x800) | ||
559 | #define CSR_MSIX_FH_INT_MASK_AD (CSR_MSIX_BASE + 0x804) | ||
560 | #define CSR_MSIX_HW_INT_CAUSES_AD (CSR_MSIX_BASE + 0x808) | ||
561 | #define CSR_MSIX_HW_INT_MASK_AD (CSR_MSIX_BASE + 0x80C) | ||
562 | #define CSR_MSIX_AUTOMASK_ST_AD (CSR_MSIX_BASE + 0x810) | ||
563 | #define CSR_MSIX_RX_IVAR_AD_REG (CSR_MSIX_BASE + 0x880) | ||
564 | #define CSR_MSIX_IVAR_AD_REG (CSR_MSIX_BASE + 0x890) | ||
565 | #define CSR_MSIX_PENDING_PBA_AD (CSR_MSIX_BASE + 0x1000) | ||
566 | #define CSR_MSIX_RX_IVAR(cause) (CSR_MSIX_RX_IVAR_AD_REG + (cause)) | ||
567 | #define CSR_MSIX_IVAR(cause) (CSR_MSIX_IVAR_AD_REG + (cause)) | ||
568 | |||
569 | #define MSIX_FH_INT_CAUSES_Q(q) (q) | ||
570 | |||
571 | /* | ||
572 | * Causes for the FH register interrupts | ||
573 | */ | ||
574 | enum msix_fh_int_causes { | ||
575 | MSIX_FH_INT_CAUSES_D2S_CH0_NUM = BIT(16), | ||
576 | MSIX_FH_INT_CAUSES_D2S_CH1_NUM = BIT(17), | ||
577 | MSIX_FH_INT_CAUSES_S2D = BIT(19), | ||
578 | MSIX_FH_INT_CAUSES_FH_ERR = BIT(21), | ||
579 | }; | ||
580 | |||
581 | /* | ||
582 | * Causes for the HW register interrupts | ||
583 | */ | ||
584 | enum msix_hw_int_causes { | ||
585 | MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0), | ||
586 | MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1), | ||
587 | MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6), | ||
588 | MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7), | ||
589 | MSIX_HW_INT_CAUSES_REG_PERIODIC = BIT(8), | ||
590 | MSIX_HW_INT_CAUSES_REG_SW_ERR = BIT(25), | ||
591 | MSIX_HW_INT_CAUSES_REG_SCD = BIT(26), | ||
592 | MSIX_HW_INT_CAUSES_REG_FH_TX = BIT(27), | ||
593 | MSIX_HW_INT_CAUSES_REG_HW_ERR = BIT(29), | ||
594 | MSIX_HW_INT_CAUSES_REG_HAP = BIT(30), | ||
595 | }; | ||
596 | |||
597 | #define MSIX_MIN_INTERRUPT_VECTORS 2 | ||
598 | #define MSIX_AUTO_CLEAR_CAUSE 0 | ||
599 | #define MSIX_NON_AUTO_CLEAR_CAUSE BIT(7) | ||
600 | |||
552 | #endif /* !__iwl_csr_h__ */ | 601 | #endif /* !__iwl_csr_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h index 22786d7dc00a..2a0703fcec56 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h | |||
@@ -73,12 +73,12 @@ TRACE_EVENT(iwlwifi_dev_rx, | |||
73 | TP_ARGS(dev, trans, pkt, len), | 73 | TP_ARGS(dev, trans, pkt, len), |
74 | TP_STRUCT__entry( | 74 | TP_STRUCT__entry( |
75 | DEV_ENTRY | 75 | DEV_ENTRY |
76 | __field(u8, cmd) | 76 | __field(u16, cmd) |
77 | __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, pkt, len)) | 77 | __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, pkt, len)) |
78 | ), | 78 | ), |
79 | TP_fast_assign( | 79 | TP_fast_assign( |
80 | DEV_ASSIGN; | 80 | DEV_ASSIGN; |
81 | __entry->cmd = pkt->hdr.cmd; | 81 | __entry->cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd); |
82 | memcpy(__get_dynamic_array(rxbuf), pkt, | 82 | memcpy(__get_dynamic_array(rxbuf), pkt, |
83 | iwl_rx_trace_len(trans, pkt, len)); | 83 | iwl_rx_trace_len(trans, pkt, len)); |
84 | ), | 84 | ), |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index ab4c2a0470b2..184c0fef37c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c | |||
@@ -1033,7 +1033,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
1033 | } | 1033 | } |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | if (usniffer_req && !*usniffer_images) { | 1036 | if (!fw_has_capa(capa, IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED) && |
1037 | usniffer_req && !*usniffer_images) { | ||
1037 | IWL_ERR(drv, | 1038 | IWL_ERR(drv, |
1038 | "user selected to work with usniffer but usniffer image isn't available in ucode package\n"); | 1039 | "user selected to work with usniffer but usniffer image isn't available in ucode package\n"); |
1039 | return -EINVAL; | 1040 | return -EINVAL; |
@@ -1718,3 +1719,7 @@ MODULE_PARM_DESC(fw_monitor, | |||
1718 | module_param_named(d0i3_timeout, iwlwifi_mod_params.d0i3_entry_delay, | 1719 | module_param_named(d0i3_timeout, iwlwifi_mod_params.d0i3_entry_delay, |
1719 | uint, S_IRUGO); | 1720 | uint, S_IRUGO); |
1720 | MODULE_PARM_DESC(d0i3_timeout, "Timeout to D0i3 entry when idle (ms)"); | 1721 | MODULE_PARM_DESC(d0i3_timeout, "Timeout to D0i3 entry when idle (ms)"); |
1722 | |||
1723 | module_param_named(disable_11ac, iwlwifi_mod_params.disable_11ac, bool, | ||
1724 | S_IRUGO); | ||
1725 | MODULE_PARM_DESC(disable_11ac, "Disable VHT capabilities"); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index 4ab6682ea53e..8af818b10e71 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2015 Intel Deutschland GmbH | 9 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 12 | * it under the terms of version 2 of the GNU General Public License as |
@@ -32,7 +32,7 @@ | |||
32 | * BSD LICENSE | 32 | * BSD LICENSE |
33 | * | 33 | * |
34 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 34 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2015 Intel Deutschland GmbH | 35 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
36 | * All rights reserved. | 36 | * All rights reserved. |
37 | * | 37 | * |
38 | * Redistribution and use in source and binary forms, with or without | 38 | * Redistribution and use in source and binary forms, with or without |
@@ -368,20 +368,24 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) | |||
368 | #define RFH_RXF_DMA_RBDCB_SIZE_512 (0x9 << RFH_RXF_DMA_RBDCB_SIZE_POS) | 368 | #define RFH_RXF_DMA_RBDCB_SIZE_512 (0x9 << RFH_RXF_DMA_RBDCB_SIZE_POS) |
369 | #define RFH_RXF_DMA_RBDCB_SIZE_1024 (0xA << RFH_RXF_DMA_RBDCB_SIZE_POS) | 369 | #define RFH_RXF_DMA_RBDCB_SIZE_1024 (0xA << RFH_RXF_DMA_RBDCB_SIZE_POS) |
370 | #define RFH_RXF_DMA_RBDCB_SIZE_2048 (0xB << RFH_RXF_DMA_RBDCB_SIZE_POS) | 370 | #define RFH_RXF_DMA_RBDCB_SIZE_2048 (0xB << RFH_RXF_DMA_RBDCB_SIZE_POS) |
371 | #define RFH_RXF_DMA_MIN_RB_SIZE_MASK (0x03000000) /* bit 24-25 */ | 371 | #define RFH_RXF_DMA_MIN_RB_SIZE_MASK (0x03000000) /* bit 24-25 */ |
372 | #define RFH_RXF_DMA_MIN_RB_SIZE_POS 24 | 372 | #define RFH_RXF_DMA_MIN_RB_SIZE_POS 24 |
373 | #define RFH_RXF_DMA_MIN_RB_4_8 (3 << RFH_RXF_DMA_MIN_RB_SIZE_POS) | 373 | #define RFH_RXF_DMA_MIN_RB_4_8 (3 << RFH_RXF_DMA_MIN_RB_SIZE_POS) |
374 | #define RFH_RXF_DMA_SINGLE_FRAME_MASK (0x20000000) /* bit 29 */ | 374 | #define RFH_RXF_DMA_DROP_TOO_LARGE_MASK (0x04000000) /* bit 26 */ |
375 | #define RFH_DMA_EN_MASK (0xC0000000) /* bits 30-31*/ | 375 | #define RFH_RXF_DMA_SINGLE_FRAME_MASK (0x20000000) /* bit 29 */ |
376 | #define RFH_DMA_EN_ENABLE_VAL BIT(31) | 376 | #define RFH_DMA_EN_MASK (0xC0000000) /* bits 30-31*/ |
377 | #define RFH_DMA_EN_ENABLE_VAL BIT(31) | ||
377 | 378 | ||
378 | #define RFH_RXF_RXQ_ACTIVE 0xA0980C | 379 | #define RFH_RXF_RXQ_ACTIVE 0xA0980C |
379 | 380 | ||
380 | #define RFH_GEN_CFG 0xA09800 | 381 | #define RFH_GEN_CFG 0xA09800 |
382 | #define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0) | ||
383 | #define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1) | ||
384 | #define RFH_GEN_CFG_RB_CHUNK_SIZE BIT(4) /* 0 - 64B, 1- 128B */ | ||
381 | #define RFH_GEN_CFG_DEFAULT_RXQ_NUM_MASK 0xF00 | 385 | #define RFH_GEN_CFG_DEFAULT_RXQ_NUM_MASK 0xF00 |
382 | #define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0) | 386 | #define RFH_GEN_CFG_DEFAULT_RXQ_NUM_POS 8 |
383 | #define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1) | 387 | |
384 | #define DEFAULT_RXQ_NUM 8 | 388 | #define DEFAULT_RXQ_NUM 0 |
385 | 389 | ||
386 | /* end of 9000 rx series registers */ | 390 | /* end of 9000 rx series registers */ |
387 | 391 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index e2dbc67a367b..5f69bf5e04c7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | |||
@@ -318,6 +318,12 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; | |||
318 | * @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon | 318 | * @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon |
319 | * from AP and will send it upon d0i3 exit. | 319 | * from AP and will send it upon d0i3 exit. |
320 | * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2 | 320 | * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2 |
321 | * @IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill | ||
322 | * @IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature | ||
323 | * thresholds reporting | ||
324 | * @IWL_UCODE_TLV_CAPA_CTDP_SUPPORT: supports cTDP command | ||
325 | * @IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED: supports usniffer enabled in | ||
326 | * regular image. | ||
321 | * | 327 | * |
322 | * @NUM_IWL_UCODE_TLV_CAPA: number of bits used | 328 | * @NUM_IWL_UCODE_TLV_CAPA: number of bits used |
323 | */ | 329 | */ |
@@ -351,6 +357,10 @@ enum iwl_ucode_tlv_capa { | |||
351 | IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71, | 357 | IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71, |
352 | IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72, | 358 | IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72, |
353 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, | 359 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, |
360 | IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW = (__force iwl_ucode_tlv_capa_t)74, | ||
361 | IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT = (__force iwl_ucode_tlv_capa_t)75, | ||
362 | IWL_UCODE_TLV_CAPA_CTDP_SUPPORT = (__force iwl_ucode_tlv_capa_t)76, | ||
363 | IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED = (__force iwl_ucode_tlv_capa_t)77, | ||
354 | 364 | ||
355 | NUM_IWL_UCODE_TLV_CAPA | 365 | NUM_IWL_UCODE_TLV_CAPA |
356 | #ifdef __CHECKER__ | 366 | #ifdef __CHECKER__ |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h index b88ecc7892a9..d1a5dd1602f5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h | |||
@@ -115,6 +115,7 @@ enum iwl_amsdu_size { | |||
115 | * entering D0i3 (in msecs) | 115 | * entering D0i3 (in msecs) |
116 | * @lar_disable: disable LAR (regulatory), default = 0 | 116 | * @lar_disable: disable LAR (regulatory), default = 0 |
117 | * @fw_monitor: allow to use firmware monitor | 117 | * @fw_monitor: allow to use firmware monitor |
118 | * @disable_11ac: disable VHT capabilities, default = false. | ||
118 | */ | 119 | */ |
119 | struct iwl_mod_params { | 120 | struct iwl_mod_params { |
120 | int sw_crypto; | 121 | int sw_crypto; |
@@ -135,6 +136,7 @@ struct iwl_mod_params { | |||
135 | unsigned int d0i3_entry_delay; | 136 | unsigned int d0i3_entry_delay; |
136 | bool lar_disable; | 137 | bool lar_disable; |
137 | bool fw_monitor; | 138 | bool fw_monitor; |
139 | bool disable_11ac; | ||
138 | }; | 140 | }; |
139 | 141 | ||
140 | #endif /* #__iwl_modparams_h__ */ | 142 | #endif /* #__iwl_modparams_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 50f4cc60cf3e..348135792f3e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | |||
@@ -366,6 +366,9 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
366 | max_ampdu_exponent << | 366 | max_ampdu_exponent << |
367 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | 367 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; |
368 | 368 | ||
369 | if (cfg->vht_mu_mimo_supported) | ||
370 | vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; | ||
371 | |||
369 | if (cfg->ht_params->ldpc) | 372 | if (cfg->ht_params->ldpc) |
370 | vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC; | 373 | vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC; |
371 | 374 | ||
@@ -449,7 +452,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
449 | IEEE80211_BAND_5GHZ); | 452 | IEEE80211_BAND_5GHZ); |
450 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, | 453 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, |
451 | tx_chains, rx_chains); | 454 | tx_chains, rx_chains); |
452 | if (data->sku_cap_11ac_enable) | 455 | if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac) |
453 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, | 456 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, |
454 | tx_chains, rx_chains); | 457 | tx_chains, rx_chains); |
455 | 458 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 5bde23a472b4..c46e596e12b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h | |||
@@ -404,4 +404,6 @@ enum { | |||
404 | LMPM_PAGE_PASS_NOTIF_POS = BIT(20), | 404 | LMPM_PAGE_PASS_NOTIF_POS = BIT(20), |
405 | }; | 405 | }; |
406 | 406 | ||
407 | #define UREG_CHICK (0xA05C00) | ||
408 | #define UREG_CHICK_MSIX_ENABLE BIT(25) | ||
407 | #endif /* __iwl_prph_h__ */ | 409 | #endif /* __iwl_prph_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 0ca0f13b69b0..91d74b3f666b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h | |||
@@ -836,6 +836,7 @@ struct iwl_trans { | |||
836 | 836 | ||
837 | enum iwl_plat_pm_mode system_pm_mode; | 837 | enum iwl_plat_pm_mode system_pm_mode; |
838 | enum iwl_plat_pm_mode runtime_pm_mode; | 838 | enum iwl_plat_pm_mode runtime_pm_mode; |
839 | bool suspending; | ||
839 | 840 | ||
840 | /* pointer to trans specific struct */ | 841 | /* pointer to trans specific struct */ |
841 | /*Ensure that this pointer will always be aligned to sizeof pointer */ | 842 | /*Ensure that this pointer will always be aligned to sizeof pointer */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 5214482a0403..c1a313149eed 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c | |||
@@ -816,8 +816,7 @@ static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm) | |||
816 | { | 816 | { |
817 | iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true); | 817 | iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true); |
818 | 818 | ||
819 | iwl_trans_stop_device(mvm->trans); | 819 | iwl_mvm_stop_device(mvm); |
820 | |||
821 | /* | 820 | /* |
822 | * Set the HW restart bit -- this is mostly true as we're | 821 | * Set the HW restart bit -- this is mostly true as we're |
823 | * going to load new firmware and reprogram that, though | 822 | * going to load new firmware and reprogram that, though |
@@ -856,8 +855,7 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm, | |||
856 | wowlan_config_cmd->is_11n_connection = | 855 | wowlan_config_cmd->is_11n_connection = |
857 | ap_sta->ht_cap.ht_supported; | 856 | ap_sta->ht_cap.ht_supported; |
858 | wowlan_config_cmd->flags = ENABLE_L3_FILTERING | | 857 | wowlan_config_cmd->flags = ENABLE_L3_FILTERING | |
859 | ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING | | 858 | ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING; |
860 | ENABLE_STORE_BEACON; | ||
861 | 859 | ||
862 | /* Query the last used seqno and set it */ | 860 | /* Query the last used seqno and set it */ |
863 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); | 861 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index c529e5355803..56e6b0b8b9cc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | |||
@@ -64,6 +64,7 @@ | |||
64 | * | 64 | * |
65 | *****************************************************************************/ | 65 | *****************************************************************************/ |
66 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
67 | #include <linux/ieee80211.h> | ||
67 | 68 | ||
68 | #include "mvm.h" | 69 | #include "mvm.h" |
69 | #include "fw-dbg.h" | 70 | #include "fw-dbg.h" |
@@ -976,7 +977,7 @@ static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm, | |||
976 | memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table, | 977 | memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table, |
977 | ARRAY_SIZE(cmd.indirection_table) % nbytes); | 978 | ARRAY_SIZE(cmd.indirection_table) % nbytes); |
978 | 979 | ||
979 | memcpy(cmd.secret_key, mvm->secret_key, ARRAY_SIZE(cmd.secret_key)); | 980 | memcpy(cmd.secret_key, mvm->secret_key, sizeof(cmd.secret_key)); |
980 | 981 | ||
981 | mutex_lock(&mvm->mutex); | 982 | mutex_lock(&mvm->mutex); |
982 | ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); | 983 | ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); |
@@ -1080,6 +1081,22 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, | |||
1080 | return count; | 1081 | return count; |
1081 | } | 1082 | } |
1082 | 1083 | ||
1084 | static ssize_t iwl_dbgfs_max_amsdu_len_write(struct iwl_mvm *mvm, | ||
1085 | char *buf, size_t count, | ||
1086 | loff_t *ppos) | ||
1087 | { | ||
1088 | unsigned int max_amsdu_len; | ||
1089 | int ret; | ||
1090 | |||
1091 | ret = kstrtouint(buf, 0, &max_amsdu_len); | ||
1092 | |||
1093 | if (max_amsdu_len > IEEE80211_MAX_MPDU_LEN_VHT_11454) | ||
1094 | return -EINVAL; | ||
1095 | mvm->max_amsdu_len = max_amsdu_len; | ||
1096 | |||
1097 | return count; | ||
1098 | } | ||
1099 | |||
1083 | #define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__) | 1100 | #define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__) |
1084 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1101 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
1085 | static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file, | 1102 | static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file, |
@@ -1497,7 +1514,9 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); | |||
1497 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); | 1514 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); |
1498 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); | 1515 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); |
1499 | MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8); | 1516 | MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8); |
1500 | MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, 16); | 1517 | MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8); |
1518 | MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, | ||
1519 | (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); | ||
1501 | 1520 | ||
1502 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1521 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
1503 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); | 1522 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); |
@@ -1540,6 +1559,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1540 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1559 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
1541 | MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1560 | MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
1542 | MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); | 1561 | MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); |
1562 | MVM_DEBUGFS_ADD_FILE(max_amsdu_len, mvm->debugfs_dir, S_IWUSR); | ||
1543 | MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); | 1563 | MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); |
1544 | MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR); | 1564 | MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR); |
1545 | MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR); | 1565 | MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h index df939f51d9b9..eb9b87038e1f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | |||
@@ -391,4 +391,56 @@ struct iwl_rss_config_cmd { | |||
391 | u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE]; | 391 | u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE]; |
392 | } __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */ | 392 | } __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */ |
393 | 393 | ||
394 | #define IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE 128 | ||
395 | #define IWL_MULTI_QUEUE_SYNC_SENDER_POS 0 | ||
396 | #define IWL_MULTI_QUEUE_SYNC_SENDER_MSK 0xf | ||
397 | |||
398 | /** | ||
399 | * struct iwl_rxq_sync_cmd - RXQ notification trigger | ||
400 | * | ||
401 | * @flags: flags of the notification. bit 0:3 are the sender queue | ||
402 | * @rxq_mask: rx queues to send the notification on | ||
403 | * @count: number of bytes in payload, should be DWORD aligned | ||
404 | * @payload: data to send to rx queues | ||
405 | */ | ||
406 | struct iwl_rxq_sync_cmd { | ||
407 | __le32 flags; | ||
408 | __le32 rxq_mask; | ||
409 | __le32 count; | ||
410 | u8 payload[]; | ||
411 | } __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */ | ||
412 | |||
413 | /** | ||
414 | * struct iwl_rxq_sync_notification - Notification triggered by RXQ | ||
415 | * sync command | ||
416 | * | ||
417 | * @count: number of bytes in payload | ||
418 | * @payload: data to send to rx queues | ||
419 | */ | ||
420 | struct iwl_rxq_sync_notification { | ||
421 | __le32 count; | ||
422 | u8 payload[]; | ||
423 | } __packed; /* MULTI_QUEUE_DRV_SYNC_HDR_CMD_API_S_VER_1 */ | ||
424 | |||
425 | /** | ||
426 | * Internal message identifier | ||
427 | * | ||
428 | * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA | ||
429 | */ | ||
430 | enum iwl_mvm_rxq_notif_type { | ||
431 | IWL_MVM_RXQ_NOTIF_DEL_BA, | ||
432 | }; | ||
433 | |||
434 | /** | ||
435 | * struct iwl_mvm_internal_rxq_notif - Internal representation of the data sent | ||
436 | * in &iwl_rxq_sync_cmd. Should be DWORD aligned. | ||
437 | * | ||
438 | * @type: value from &iwl_mvm_rxq_notif_type | ||
439 | * @data: payload | ||
440 | */ | ||
441 | struct iwl_mvm_internal_rxq_notif { | ||
442 | u32 type; | ||
443 | u8 data[]; | ||
444 | } __packed; | ||
445 | |||
394 | #endif /* __fw_api_rx_h__ */ | 446 | #endif /* __fw_api_rx_h__ */ |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index f332497e29d1..4a0fc47c81f2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | |||
@@ -119,6 +119,8 @@ enum { | |||
119 | SCAN_ABORT_UMAC = 0xe, | 119 | SCAN_ABORT_UMAC = 0xe, |
120 | SCAN_COMPLETE_UMAC = 0xf, | 120 | SCAN_COMPLETE_UMAC = 0xf, |
121 | 121 | ||
122 | BA_WINDOW_STATUS_NOTIFICATION_ID = 0x13, | ||
123 | |||
122 | /* station table */ | 124 | /* station table */ |
123 | ADD_STA_KEY = 0x17, | 125 | ADD_STA_KEY = 0x17, |
124 | ADD_STA = 0x18, | 126 | ADD_STA = 0x18, |
@@ -279,9 +281,19 @@ enum { | |||
279 | */ | 281 | */ |
280 | enum iwl_phy_ops_subcmd_ids { | 282 | enum iwl_phy_ops_subcmd_ids { |
281 | CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0, | 283 | CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0, |
284 | CTDP_CONFIG_CMD = 0x03, | ||
285 | TEMP_REPORTING_THRESHOLDS_CMD = 0x04, | ||
286 | CT_KILL_NOTIFICATION = 0xFE, | ||
282 | DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, | 287 | DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, |
283 | }; | 288 | }; |
284 | 289 | ||
290 | enum iwl_data_path_subcmd_ids { | ||
291 | UPDATE_MU_GROUPS_CMD = 0x1, | ||
292 | TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2, | ||
293 | MU_GROUP_MGMT_NOTIF = 0xFE, | ||
294 | RX_QUEUES_NOTIFICATION = 0xFF, | ||
295 | }; | ||
296 | |||
285 | enum iwl_prot_offload_subcmd_ids { | 297 | enum iwl_prot_offload_subcmd_ids { |
286 | STORED_BEACON_NTF = 0xFF, | 298 | STORED_BEACON_NTF = 0xFF, |
287 | }; | 299 | }; |
@@ -291,6 +303,7 @@ enum { | |||
291 | LEGACY_GROUP = 0x0, | 303 | LEGACY_GROUP = 0x0, |
292 | LONG_GROUP = 0x1, | 304 | LONG_GROUP = 0x1, |
293 | PHY_OPS_GROUP = 0x4, | 305 | PHY_OPS_GROUP = 0x4, |
306 | DATA_PATH_GROUP = 0x5, | ||
294 | PROT_OFFLOAD_GROUP = 0xb, | 307 | PROT_OFFLOAD_GROUP = 0xb, |
295 | }; | 308 | }; |
296 | 309 | ||
@@ -1278,6 +1291,26 @@ struct iwl_fw_bcast_filter { | |||
1278 | struct iwl_fw_bcast_filter_attr attrs[MAX_BCAST_FILTER_ATTRS]; | 1291 | struct iwl_fw_bcast_filter_attr attrs[MAX_BCAST_FILTER_ATTRS]; |
1279 | } __packed; /* BCAST_FILTER_S_VER_1 */ | 1292 | } __packed; /* BCAST_FILTER_S_VER_1 */ |
1280 | 1293 | ||
1294 | #define BA_WINDOW_STREAMS_MAX 16 | ||
1295 | #define BA_WINDOW_STATUS_TID_MSK 0x000F | ||
1296 | #define BA_WINDOW_STATUS_STA_ID_POS 4 | ||
1297 | #define BA_WINDOW_STATUS_STA_ID_MSK 0x01F0 | ||
1298 | #define BA_WINDOW_STATUS_VALID_MSK BIT(9) | ||
1299 | |||
1300 | /** | ||
1301 | * struct iwl_ba_window_status_notif - reordering window's status notification | ||
1302 | * @bitmap: bitmap of received frames [start_seq_num + 0]..[start_seq_num + 63] | ||
1303 | * @ra_tid: bit 3:0 - TID, bit 8:4 - STA_ID, bit 9 - valid | ||
1304 | * @start_seq_num: the start sequence number of the bitmap | ||
1305 | * @mpdu_rx_count: the number of received MPDUs since entering D0i3 | ||
1306 | */ | ||
1307 | struct iwl_ba_window_status_notif { | ||
1308 | __le64 bitmap[BA_WINDOW_STREAMS_MAX]; | ||
1309 | __le16 ra_tid[BA_WINDOW_STREAMS_MAX]; | ||
1310 | __le32 start_seq_num[BA_WINDOW_STREAMS_MAX]; | ||
1311 | __le16 mpdu_rx_count[BA_WINDOW_STREAMS_MAX]; | ||
1312 | } __packed; /* BA_WINDOW_STATUS_NTFY_API_S_VER_1 */ | ||
1313 | |||
1281 | /** | 1314 | /** |
1282 | * struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration. | 1315 | * struct iwl_fw_bcast_mac - per-mac broadcast filtering configuration. |
1283 | * @default_discard: default action for this mac (discard (1) / pass (0)). | 1316 | * @default_discard: default action for this mac (discard (1) / pass (0)). |
@@ -1675,15 +1708,77 @@ struct iwl_ext_dts_measurement_cmd { | |||
1675 | } __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */ | 1708 | } __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */ |
1676 | 1709 | ||
1677 | /** | 1710 | /** |
1678 | * iwl_dts_measurement_notif - notification received with the measurements | 1711 | * struct iwl_dts_measurement_notif_v1 - measurements notification |
1679 | * | 1712 | * |
1680 | * @temp: the measured temperature | 1713 | * @temp: the measured temperature |
1681 | * @voltage: the measured voltage | 1714 | * @voltage: the measured voltage |
1682 | */ | 1715 | */ |
1683 | struct iwl_dts_measurement_notif { | 1716 | struct iwl_dts_measurement_notif_v1 { |
1684 | __le32 temp; | 1717 | __le32 temp; |
1685 | __le32 voltage; | 1718 | __le32 voltage; |
1686 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S */ | 1719 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S_VER_1*/ |
1720 | |||
1721 | /** | ||
1722 | * struct iwl_dts_measurement_notif_v2 - measurements notification | ||
1723 | * | ||
1724 | * @temp: the measured temperature | ||
1725 | * @voltage: the measured voltage | ||
1726 | * @threshold_idx: the trip index that was crossed | ||
1727 | */ | ||
1728 | struct iwl_dts_measurement_notif_v2 { | ||
1729 | __le32 temp; | ||
1730 | __le32 voltage; | ||
1731 | __le32 threshold_idx; | ||
1732 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S_VER_2 */ | ||
1733 | |||
1734 | /** | ||
1735 | * struct ct_kill_notif - CT-kill entry notification | ||
1736 | * | ||
1737 | * @temperature: the current temperature in celsius | ||
1738 | * @reserved: reserved | ||
1739 | */ | ||
1740 | struct ct_kill_notif { | ||
1741 | __le16 temperature; | ||
1742 | __le16 reserved; | ||
1743 | } __packed; /* GRP_PHY_CT_KILL_NTF */ | ||
1744 | |||
1745 | /** | ||
1746 | * enum ctdp_cmd_operation - CTDP command operations | ||
1747 | * @CTDP_CMD_OPERATION_START: update the current budget | ||
1748 | * @CTDP_CMD_OPERATION_STOP: stop ctdp | ||
1749 | * @CTDP_CMD_OPERATION_REPORT: get the avgerage budget | ||
1750 | */ | ||
1751 | enum iwl_mvm_ctdp_cmd_operation { | ||
1752 | CTDP_CMD_OPERATION_START = 0x1, | ||
1753 | CTDP_CMD_OPERATION_STOP = 0x2, | ||
1754 | CTDP_CMD_OPERATION_REPORT = 0x4, | ||
1755 | };/* CTDP_CMD_OPERATION_TYPE_E */ | ||
1756 | |||
1757 | /** | ||
1758 | * struct iwl_mvm_ctdp_cmd - track and manage the FW power consumption budget | ||
1759 | * | ||
1760 | * @operation: see &enum iwl_mvm_ctdp_cmd_operation | ||
1761 | * @budget: the budget in milliwatt | ||
1762 | * @window_size: defined in API but not used | ||
1763 | */ | ||
1764 | struct iwl_mvm_ctdp_cmd { | ||
1765 | __le32 operation; | ||
1766 | __le32 budget; | ||
1767 | __le32 window_size; | ||
1768 | } __packed; | ||
1769 | |||
1770 | #define IWL_MAX_DTS_TRIPS 8 | ||
1771 | |||
1772 | /** | ||
1773 | * struct iwl_temp_report_ths_cmd - set temperature thresholds | ||
1774 | * | ||
1775 | * @num_temps: number of temperature thresholds passed | ||
1776 | * @thresholds: array with the thresholds to be configured | ||
1777 | */ | ||
1778 | struct temp_report_ths_cmd { | ||
1779 | __le32 num_temps; | ||
1780 | __le16 thresholds[IWL_MAX_DTS_TRIPS]; | ||
1781 | } __packed; /* GRP_PHY_TEMP_REPORTING_THRESHOLDS_CMD */ | ||
1687 | 1782 | ||
1688 | /*********************************** | 1783 | /*********************************** |
1689 | * TDLS API | 1784 | * TDLS API |
@@ -1858,6 +1953,31 @@ struct iwl_shared_mem_cfg { | |||
1858 | __le32 page_buff_size; | 1953 | __le32 page_buff_size; |
1859 | } __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */ | 1954 | } __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */ |
1860 | 1955 | ||
1956 | /** | ||
1957 | * VHT MU-MIMO group configuration | ||
1958 | * | ||
1959 | * @membership_status: a bitmap of MU groups | ||
1960 | * @user_position:the position of station in a group. If the station is in the | ||
1961 | * group then bits (group * 2) is the position -1 | ||
1962 | */ | ||
1963 | struct iwl_mu_group_mgmt_cmd { | ||
1964 | __le32 reserved; | ||
1965 | __le32 membership_status[2]; | ||
1966 | __le32 user_position[4]; | ||
1967 | } __packed; /* MU_GROUP_ID_MNG_TABLE_API_S_VER_1 */ | ||
1968 | |||
1969 | /** | ||
1970 | * struct iwl_mu_group_mgmt_notif - VHT MU-MIMO group id notification | ||
1971 | * | ||
1972 | * @membership_status: a bitmap of MU groups | ||
1973 | * @user_position: the position of station in a group. If the station is in the | ||
1974 | * group then bits (group * 2) is the position -1 | ||
1975 | */ | ||
1976 | struct iwl_mu_group_mgmt_notif { | ||
1977 | __le32 membership_status[2]; | ||
1978 | __le32 user_position[4]; | ||
1979 | } __packed; /* MU_GROUP_MNG_NTFY_API_S_VER_1 */ | ||
1980 | |||
1861 | #define MAX_STORED_BEACON_SIZE 600 | 1981 | #define MAX_STORED_BEACON_SIZE 600 |
1862 | 1982 | ||
1863 | /** | 1983 | /** |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 62ae43d2ab7b..594cd0dc7df9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c | |||
@@ -121,7 +121,7 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) | |||
121 | 121 | ||
122 | for (i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++) | 122 | for (i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++) |
123 | cmd.indirection_table[i] = i % mvm->trans->num_rx_queues; | 123 | cmd.indirection_table[i] = i % mvm->trans->num_rx_queues; |
124 | memcpy(cmd.secret_key, mvm->secret_key, ARRAY_SIZE(cmd.secret_key)); | 124 | memcpy(cmd.secret_key, mvm->secret_key, sizeof(cmd.secret_key)); |
125 | 125 | ||
126 | return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); | 126 | return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); |
127 | } | 127 | } |
@@ -539,7 +539,9 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
539 | struct iwl_sf_region st_fwrd_space; | 539 | struct iwl_sf_region st_fwrd_space; |
540 | 540 | ||
541 | if (ucode_type == IWL_UCODE_REGULAR && | 541 | if (ucode_type == IWL_UCODE_REGULAR && |
542 | iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE)) | 542 | iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) && |
543 | !(fw_has_capa(&mvm->fw->ucode_capa, | ||
544 | IWL_UCODE_TLV_CAPA_USNIFFER_UNIFIED))) | ||
543 | fw = iwl_get_ucode_image(mvm, IWL_UCODE_REGULAR_USNIFFER); | 545 | fw = iwl_get_ucode_image(mvm, IWL_UCODE_REGULAR_USNIFFER); |
544 | else | 546 | else |
545 | fw = iwl_get_ucode_image(mvm, ucode_type); | 547 | fw = iwl_get_ucode_image(mvm, ucode_type); |
@@ -954,8 +956,26 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
954 | goto error; | 956 | goto error; |
955 | } | 957 | } |
956 | 958 | ||
959 | #ifdef CONFIG_THERMAL | ||
960 | if (iwl_mvm_is_tt_in_fw(mvm)) { | ||
961 | /* in order to give the responsibility of ct-kill and | ||
962 | * TX backoff to FW we need to send empty temperature reporting | ||
963 | * cmd during init time | ||
964 | */ | ||
965 | iwl_mvm_send_temp_report_ths_cmd(mvm); | ||
966 | } else { | ||
967 | /* Initialize tx backoffs to the minimal possible */ | ||
968 | iwl_mvm_tt_tx_backoff(mvm, 0); | ||
969 | } | ||
970 | |||
971 | /* TODO: read the budget from BIOS / Platform NVM */ | ||
972 | if (iwl_mvm_is_ctdp_supported(mvm) && mvm->cooling_dev.cur_state > 0) | ||
973 | ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START, | ||
974 | mvm->cooling_dev.cur_state); | ||
975 | #else | ||
957 | /* Initialize tx backoffs to the minimal possible */ | 976 | /* Initialize tx backoffs to the minimal possible */ |
958 | iwl_mvm_tt_tx_backoff(mvm, 0); | 977 | iwl_mvm_tt_tx_backoff(mvm, 0); |
978 | #endif | ||
959 | 979 | ||
960 | WARN_ON(iwl_mvm_config_ltr(mvm)); | 980 | WARN_ON(iwl_mvm_config_ltr(mvm)); |
961 | 981 | ||
@@ -991,7 +1011,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
991 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); | 1011 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); |
992 | return 0; | 1012 | return 0; |
993 | error: | 1013 | error: |
994 | iwl_trans_stop_device(mvm->trans); | 1014 | iwl_mvm_stop_device(mvm); |
995 | return ret; | 1015 | return ret; |
996 | } | 1016 | } |
997 | 1017 | ||
@@ -1035,7 +1055,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) | |||
1035 | 1055 | ||
1036 | return 0; | 1056 | return 0; |
1037 | error: | 1057 | error: |
1038 | iwl_trans_stop_device(mvm->trans); | 1058 | iwl_mvm_stop_device(mvm); |
1039 | return ret; | 1059 | return ret; |
1040 | } | 1060 | } |
1041 | 1061 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 535134d639e0..e885db3464b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | |||
@@ -1484,6 +1484,8 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, | |||
1484 | /* update rx_status according to the notification's metadata */ | 1484 | /* update rx_status according to the notification's metadata */ |
1485 | memset(&rx_status, 0, sizeof(rx_status)); | 1485 | memset(&rx_status, 0, sizeof(rx_status)); |
1486 | rx_status.mactime = le64_to_cpu(sb->tsf); | 1486 | rx_status.mactime = le64_to_cpu(sb->tsf); |
1487 | /* TSF as indicated by the firmware is at INA time */ | ||
1488 | rx_status.flag |= RX_FLAG_MACTIME_PLCP_START; | ||
1487 | rx_status.device_timestamp = le32_to_cpu(sb->system_time); | 1489 | rx_status.device_timestamp = le32_to_cpu(sb->system_time); |
1488 | rx_status.band = | 1490 | rx_status.band = |
1489 | (sb->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? | 1491 | (sb->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 53156810185d..ec6b07282e7d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -69,7 +70,6 @@ | |||
69 | #include <linux/etherdevice.h> | 70 | #include <linux/etherdevice.h> |
70 | #include <linux/ip.h> | 71 | #include <linux/ip.h> |
71 | #include <linux/if_arp.h> | 72 | #include <linux/if_arp.h> |
72 | #include <linux/devcoredump.h> | ||
73 | #include <linux/time.h> | 73 | #include <linux/time.h> |
74 | #include <net/mac80211.h> | 74 | #include <net/mac80211.h> |
75 | #include <net/ieee80211_radiotap.h> | 75 | #include <net/ieee80211_radiotap.h> |
@@ -85,7 +85,6 @@ | |||
85 | #include "testmode.h" | 85 | #include "testmode.h" |
86 | #include "iwl-fw-error-dump.h" | 86 | #include "iwl-fw-error-dump.h" |
87 | #include "iwl-prph.h" | 87 | #include "iwl-prph.h" |
88 | #include "iwl-csr.h" | ||
89 | #include "iwl-nvm-parse.h" | 88 | #include "iwl-nvm-parse.h" |
90 | #include "fw-dbg.h" | 89 | #include "fw-dbg.h" |
91 | 90 | ||
@@ -611,6 +610,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
611 | IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT)) | 610 | IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT)) |
612 | hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES; | 611 | hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES; |
613 | 612 | ||
613 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_RRM); | ||
614 | |||
614 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 615 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
615 | 616 | ||
616 | #ifdef CONFIG_PM_SLEEP | 617 | #ifdef CONFIG_PM_SLEEP |
@@ -847,6 +848,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
847 | u16 tid = params->tid; | 848 | u16 tid = params->tid; |
848 | u16 *ssn = ¶ms->ssn; | 849 | u16 *ssn = ¶ms->ssn; |
849 | u8 buf_size = params->buf_size; | 850 | u8 buf_size = params->buf_size; |
851 | bool amsdu = params->amsdu; | ||
850 | 852 | ||
851 | IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n", | 853 | IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n", |
852 | sta->addr, tid, action); | 854 | sta->addr, tid, action); |
@@ -907,7 +909,8 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
907 | ret = iwl_mvm_sta_tx_agg_flush(mvm, vif, sta, tid); | 909 | ret = iwl_mvm_sta_tx_agg_flush(mvm, vif, sta, tid); |
908 | break; | 910 | break; |
909 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 911 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
910 | ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size); | 912 | ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, |
913 | buf_size, amsdu); | ||
911 | break; | 914 | break; |
912 | default: | 915 | default: |
913 | WARN_ON_ONCE(1); | 916 | WARN_ON_ONCE(1); |
@@ -969,7 +972,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | |||
969 | */ | 972 | */ |
970 | iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN); | 973 | iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN); |
971 | 974 | ||
972 | iwl_trans_stop_device(mvm->trans); | 975 | iwl_mvm_stop_device(mvm); |
973 | 976 | ||
974 | mvm->scan_status = 0; | 977 | mvm->scan_status = 0; |
975 | mvm->ps_disabled = false; | 978 | mvm->ps_disabled = false; |
@@ -1138,7 +1141,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) | |||
1138 | */ | 1141 | */ |
1139 | flush_work(&mvm->roc_done_wk); | 1142 | flush_work(&mvm->roc_done_wk); |
1140 | 1143 | ||
1141 | iwl_trans_stop_device(mvm->trans); | 1144 | iwl_mvm_stop_device(mvm); |
1142 | 1145 | ||
1143 | iwl_mvm_async_handlers_purge(mvm); | 1146 | iwl_mvm_async_handlers_purge(mvm); |
1144 | /* async_handlers_list is empty and will stay empty: HW is stopped */ | 1147 | /* async_handlers_list is empty and will stay empty: HW is stopped */ |
@@ -1169,8 +1172,6 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) | |||
1169 | mvm->scan_uid_status[i] = 0; | 1172 | mvm->scan_uid_status[i] = 0; |
1170 | } | 1173 | } |
1171 | } | 1174 | } |
1172 | |||
1173 | mvm->ucode_loaded = false; | ||
1174 | } | 1175 | } |
1175 | 1176 | ||
1176 | static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) | 1177 | static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) |
@@ -1762,6 +1763,50 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm) | |||
1762 | } | 1763 | } |
1763 | #endif | 1764 | #endif |
1764 | 1765 | ||
1766 | static int iwl_mvm_update_mu_groups(struct iwl_mvm *mvm, | ||
1767 | struct ieee80211_vif *vif) | ||
1768 | { | ||
1769 | struct iwl_mu_group_mgmt_cmd cmd = {}; | ||
1770 | |||
1771 | memcpy(cmd.membership_status, vif->bss_conf.mu_group.membership, | ||
1772 | WLAN_MEMBERSHIP_LEN); | ||
1773 | memcpy(cmd.user_position, vif->bss_conf.mu_group.position, | ||
1774 | WLAN_USER_POSITION_LEN); | ||
1775 | |||
1776 | return iwl_mvm_send_cmd_pdu(mvm, | ||
1777 | WIDE_ID(DATA_PATH_GROUP, | ||
1778 | UPDATE_MU_GROUPS_CMD), | ||
1779 | 0, sizeof(cmd), &cmd); | ||
1780 | } | ||
1781 | |||
1782 | static void iwl_mvm_mu_mimo_iface_iterator(void *_data, u8 *mac, | ||
1783 | struct ieee80211_vif *vif) | ||
1784 | { | ||
1785 | if (vif->mu_mimo_owner) { | ||
1786 | struct iwl_mu_group_mgmt_notif *notif = _data; | ||
1787 | |||
1788 | /* | ||
1789 | * MU-MIMO Group Id action frame is little endian. We treat | ||
1790 | * the data received from firmware as if it came from the | ||
1791 | * action frame, so no conversion is needed. | ||
1792 | */ | ||
1793 | ieee80211_update_mu_groups(vif, | ||
1794 | (u8 *)¬if->membership_status, | ||
1795 | (u8 *)¬if->user_position); | ||
1796 | } | ||
1797 | } | ||
1798 | |||
1799 | void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm, | ||
1800 | struct iwl_rx_cmd_buffer *rxb) | ||
1801 | { | ||
1802 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1803 | struct iwl_mu_group_mgmt_notif *notif = (void *)pkt->data; | ||
1804 | |||
1805 | ieee80211_iterate_active_interfaces_atomic( | ||
1806 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
1807 | iwl_mvm_mu_mimo_iface_iterator, notif); | ||
1808 | } | ||
1809 | |||
1765 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | 1810 | static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, |
1766 | struct ieee80211_vif *vif, | 1811 | struct ieee80211_vif *vif, |
1767 | struct ieee80211_bss_conf *bss_conf, | 1812 | struct ieee80211_bss_conf *bss_conf, |
@@ -1870,6 +1915,18 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1870 | vif->addr); | 1915 | vif->addr); |
1871 | } | 1916 | } |
1872 | 1917 | ||
1918 | /* | ||
1919 | * The firmware tracks the MU-MIMO group on its own. | ||
1920 | * However, on HW restart we should restore this data. | ||
1921 | */ | ||
1922 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | ||
1923 | (changes & BSS_CHANGED_MU_GROUPS) && vif->mu_mimo_owner) { | ||
1924 | ret = iwl_mvm_update_mu_groups(mvm, vif); | ||
1925 | if (ret) | ||
1926 | IWL_ERR(mvm, | ||
1927 | "failed to update VHT MU_MIMO groups\n"); | ||
1928 | } | ||
1929 | |||
1873 | iwl_mvm_recalc_multicast(mvm); | 1930 | iwl_mvm_recalc_multicast(mvm); |
1874 | iwl_mvm_configure_bcast_filter(mvm); | 1931 | iwl_mvm_configure_bcast_filter(mvm); |
1875 | 1932 | ||
@@ -1896,7 +1953,12 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1896 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); | 1953 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); |
1897 | } | 1954 | } |
1898 | 1955 | ||
1899 | if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) { | 1956 | if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS | |
1957 | /* | ||
1958 | * Send power command on every beacon change, | ||
1959 | * because we may have not enabled beacon abort yet. | ||
1960 | */ | ||
1961 | BSS_CHANGED_BEACON_INFO)) { | ||
1900 | ret = iwl_mvm_power_update_mac(mvm); | 1962 | ret = iwl_mvm_power_update_mac(mvm); |
1901 | if (ret) | 1963 | if (ret) |
1902 | IWL_ERR(mvm, "failed to update power mode\n"); | 1964 | IWL_ERR(mvm, "failed to update power mode\n"); |
@@ -2083,7 +2145,6 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, | |||
2083 | bss_conf->txpower); | 2145 | bss_conf->txpower); |
2084 | iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); | 2146 | iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); |
2085 | } | 2147 | } |
2086 | |||
2087 | } | 2148 | } |
2088 | 2149 | ||
2089 | static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | 2150 | static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, |
@@ -2276,6 +2337,11 @@ static void iwl_mvm_check_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
2276 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT)) | 2337 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT)) |
2277 | return; | 2338 | return; |
2278 | 2339 | ||
2340 | if (vif->p2p && !iwl_mvm_is_p2p_standalone_uapsd_supported(mvm)) { | ||
2341 | vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD; | ||
2342 | return; | ||
2343 | } | ||
2344 | |||
2279 | if (iwlwifi_mod_params.uapsd_disable) { | 2345 | if (iwlwifi_mod_params.uapsd_disable) { |
2280 | vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD; | 2346 | vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD; |
2281 | return; | 2347 | return; |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index cc279e0961fa..ab410b4659f3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -33,6 +34,7 @@ | |||
33 | * | 34 | * |
34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 36 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
37 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
36 | * All rights reserved. | 38 | * All rights reserved. |
37 | * | 39 | * |
38 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -71,6 +73,10 @@ | |||
71 | #include <linux/leds.h> | 73 | #include <linux/leds.h> |
72 | #include <linux/in6.h> | 74 | #include <linux/in6.h> |
73 | 75 | ||
76 | #ifdef CONFIG_THERMAL | ||
77 | #include <linux/thermal.h> | ||
78 | #endif | ||
79 | |||
74 | #include "iwl-op-mode.h" | 80 | #include "iwl-op-mode.h" |
75 | #include "iwl-trans.h" | 81 | #include "iwl-trans.h" |
76 | #include "iwl-notif-wait.h" | 82 | #include "iwl-notif-wait.h" |
@@ -487,6 +493,12 @@ enum iwl_mvm_scan_type { | |||
487 | IWL_SCAN_TYPE_FRAGMENTED, | 493 | IWL_SCAN_TYPE_FRAGMENTED, |
488 | }; | 494 | }; |
489 | 495 | ||
496 | enum iwl_mvm_sched_scan_pass_all_states { | ||
497 | SCHED_SCAN_PASS_ALL_DISABLED, | ||
498 | SCHED_SCAN_PASS_ALL_ENABLED, | ||
499 | SCHED_SCAN_PASS_ALL_FOUND, | ||
500 | }; | ||
501 | |||
490 | /** | 502 | /** |
491 | * struct iwl_nvm_section - describes an NVM section in memory. | 503 | * struct iwl_nvm_section - describes an NVM section in memory. |
492 | * | 504 | * |
@@ -517,6 +529,30 @@ struct iwl_mvm_tt_mgmt { | |||
517 | bool throttle; | 529 | bool throttle; |
518 | }; | 530 | }; |
519 | 531 | ||
532 | #ifdef CONFIG_THERMAL | ||
533 | /** | ||
534 | *struct iwl_mvm_thermal_device - thermal zone related data | ||
535 | * @temp_trips: temperature thresholds for report | ||
536 | * @fw_trips_index: keep indexes to original array - temp_trips | ||
537 | * @tzone: thermal zone device data | ||
538 | */ | ||
539 | struct iwl_mvm_thermal_device { | ||
540 | s16 temp_trips[IWL_MAX_DTS_TRIPS]; | ||
541 | u8 fw_trips_index[IWL_MAX_DTS_TRIPS]; | ||
542 | struct thermal_zone_device *tzone; | ||
543 | }; | ||
544 | |||
545 | /* | ||
546 | * iwl_mvm_cooling_device | ||
547 | * @cur_state: current state in milliwatts | ||
548 | * @cdev: struct thermal cooling device | ||
549 | */ | ||
550 | struct iwl_mvm_cooling_device { | ||
551 | u32 cur_state; | ||
552 | struct thermal_cooling_device *cdev; | ||
553 | }; | ||
554 | #endif | ||
555 | |||
520 | #define IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES 8 | 556 | #define IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES 8 |
521 | 557 | ||
522 | struct iwl_mvm_frame_stats { | 558 | struct iwl_mvm_frame_stats { |
@@ -657,6 +693,7 @@ struct iwl_mvm { | |||
657 | void *scan_cmd; | 693 | void *scan_cmd; |
658 | struct iwl_mcast_filter_cmd *mcast_filter_cmd; | 694 | struct iwl_mcast_filter_cmd *mcast_filter_cmd; |
659 | enum iwl_mvm_scan_type scan_type; | 695 | enum iwl_mvm_scan_type scan_type; |
696 | enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all; | ||
660 | 697 | ||
661 | /* max number of simultaneous scans the FW supports */ | 698 | /* max number of simultaneous scans the FW supports */ |
662 | unsigned int max_scans; | 699 | unsigned int max_scans; |
@@ -797,6 +834,11 @@ struct iwl_mvm { | |||
797 | 834 | ||
798 | /* Thermal Throttling and CTkill */ | 835 | /* Thermal Throttling and CTkill */ |
799 | struct iwl_mvm_tt_mgmt thermal_throttle; | 836 | struct iwl_mvm_tt_mgmt thermal_throttle; |
837 | #ifdef CONFIG_THERMAL | ||
838 | struct iwl_mvm_thermal_device tz_device; | ||
839 | struct iwl_mvm_cooling_device cooling_dev; | ||
840 | #endif | ||
841 | |||
800 | s32 temperature; /* Celsius */ | 842 | s32 temperature; /* Celsius */ |
801 | /* | 843 | /* |
802 | * Debug option to set the NIC temperature. This option makes the | 844 | * Debug option to set the NIC temperature. This option makes the |
@@ -819,6 +861,7 @@ struct iwl_mvm { | |||
819 | 861 | ||
820 | /* Indicate if device power save is allowed */ | 862 | /* Indicate if device power save is allowed */ |
821 | u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */ | 863 | u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */ |
864 | unsigned int max_amsdu_len; /* used for debugfs only */ | ||
822 | 865 | ||
823 | struct ieee80211_vif __rcu *csa_vif; | 866 | struct ieee80211_vif __rcu *csa_vif; |
824 | struct ieee80211_vif __rcu *csa_tx_blocked_vif; | 867 | struct ieee80211_vif __rcu *csa_tx_blocked_vif; |
@@ -943,8 +986,9 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) | |||
943 | 986 | ||
944 | static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) | 987 | static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) |
945 | { | 988 | { |
946 | return fw_has_capa(&mvm->fw->ucode_capa, | 989 | /* Make sure DQA isn't allowed in driver until feature is complete */ |
947 | IWL_UCODE_TLV_CAPA_DQA_SUPPORT); | 990 | return false && fw_has_capa(&mvm->fw->ucode_capa, |
991 | IWL_UCODE_TLV_CAPA_DQA_SUPPORT); | ||
948 | } | 992 | } |
949 | 993 | ||
950 | static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) | 994 | static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) |
@@ -1028,6 +1072,28 @@ static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) | |||
1028 | IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT); | 1072 | IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT); |
1029 | } | 1073 | } |
1030 | 1074 | ||
1075 | static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm) | ||
1076 | { | ||
1077 | #ifdef CONFIG_THERMAL | ||
1078 | /* these two TLV are redundant since the responsibility to CT-kill by | ||
1079 | * FW happens only after we send at least one command of | ||
1080 | * temperature THs report. | ||
1081 | */ | ||
1082 | return fw_has_capa(&mvm->fw->ucode_capa, | ||
1083 | IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW) && | ||
1084 | fw_has_capa(&mvm->fw->ucode_capa, | ||
1085 | IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT); | ||
1086 | #else /* CONFIG_THERMAL */ | ||
1087 | return false; | ||
1088 | #endif /* CONFIG_THERMAL */ | ||
1089 | } | ||
1090 | |||
1091 | static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm) | ||
1092 | { | ||
1093 | return fw_has_capa(&mvm->fw->ucode_capa, | ||
1094 | IWL_UCODE_TLV_CAPA_CTDP_SUPPORT); | ||
1095 | } | ||
1096 | |||
1031 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 1097 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
1032 | 1098 | ||
1033 | struct iwl_rate_info { | 1099 | struct iwl_rate_info { |
@@ -1160,6 +1226,10 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
1160 | struct iwl_rx_cmd_buffer *rxb, int queue); | 1226 | struct iwl_rx_cmd_buffer *rxb, int queue); |
1161 | void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, | 1227 | void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, |
1162 | struct iwl_rx_cmd_buffer *rxb, int queue); | 1228 | struct iwl_rx_cmd_buffer *rxb, int queue); |
1229 | int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask, | ||
1230 | const u8 *data, u32 count); | ||
1231 | void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | ||
1232 | int queue); | ||
1163 | void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); | 1233 | void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); |
1164 | void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); | 1234 | void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); |
1165 | void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | 1235 | void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, |
@@ -1203,6 +1273,10 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, | |||
1203 | struct iwl_rx_cmd_buffer *rxb); | 1273 | struct iwl_rx_cmd_buffer *rxb); |
1204 | void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, | 1274 | void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, |
1205 | struct iwl_rx_cmd_buffer *rxb); | 1275 | struct iwl_rx_cmd_buffer *rxb); |
1276 | void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm, | ||
1277 | struct iwl_rx_cmd_buffer *rxb); | ||
1278 | void iwl_mvm_window_status_notif(struct iwl_mvm *mvm, | ||
1279 | struct iwl_rx_cmd_buffer *rxb); | ||
1206 | void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, | 1280 | void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, |
1207 | struct ieee80211_vif *vif); | 1281 | struct ieee80211_vif *vif); |
1208 | unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, | 1282 | unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, |
@@ -1479,32 +1553,30 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, | |||
1479 | iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); | 1553 | iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); |
1480 | } | 1554 | } |
1481 | 1555 | ||
1482 | static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, | 1556 | static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) |
1483 | int mac80211_queue, int fifo, | ||
1484 | int sta_id, int tid, int frame_limit, | ||
1485 | u16 ssn, unsigned int wdg_timeout) | ||
1486 | { | 1557 | { |
1487 | struct iwl_trans_txq_scd_cfg cfg = { | 1558 | mvm->ucode_loaded = false; |
1488 | .fifo = fifo, | 1559 | iwl_trans_stop_device(mvm->trans); |
1489 | .sta_id = sta_id, | ||
1490 | .tid = tid, | ||
1491 | .frame_limit = frame_limit, | ||
1492 | .aggregate = true, | ||
1493 | }; | ||
1494 | |||
1495 | iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); | ||
1496 | } | 1560 | } |
1497 | 1561 | ||
1562 | /* Stop/start all mac queues in a given bitmap */ | ||
1563 | void iwl_mvm_start_mac_queues(struct iwl_mvm *mvm, unsigned long mq); | ||
1564 | void iwl_mvm_stop_mac_queues(struct iwl_mvm *mvm, unsigned long mq); | ||
1565 | |||
1498 | /* Thermal management and CT-kill */ | 1566 | /* Thermal management and CT-kill */ |
1499 | void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff); | 1567 | void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff); |
1500 | void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp); | 1568 | void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp); |
1501 | void iwl_mvm_temp_notif(struct iwl_mvm *mvm, | 1569 | void iwl_mvm_temp_notif(struct iwl_mvm *mvm, |
1502 | struct iwl_rx_cmd_buffer *rxb); | 1570 | struct iwl_rx_cmd_buffer *rxb); |
1503 | void iwl_mvm_tt_handler(struct iwl_mvm *mvm); | 1571 | void iwl_mvm_tt_handler(struct iwl_mvm *mvm); |
1504 | void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff); | 1572 | void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff); |
1505 | void iwl_mvm_tt_exit(struct iwl_mvm *mvm); | 1573 | void iwl_mvm_thermal_exit(struct iwl_mvm *mvm); |
1506 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); | 1574 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); |
1507 | int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp); | 1575 | int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp); |
1576 | void iwl_mvm_ct_kill_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); | ||
1577 | int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm); | ||
1578 | int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm); | ||
1579 | int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget); | ||
1508 | 1580 | ||
1509 | /* Location Aware Regulatory */ | 1581 | /* Location Aware Regulatory */ |
1510 | struct iwl_mcc_update_resp * | 1582 | struct iwl_mcc_update_resp * |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index fd8f4a80ddfc..699a80863e86 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c | |||
@@ -236,6 +236,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
236 | RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION, | 236 | RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION, |
237 | iwl_mvm_rx_ant_coupling_notif, true), | 237 | iwl_mvm_rx_ant_coupling_notif, true), |
238 | 238 | ||
239 | RX_HANDLER(BA_WINDOW_STATUS_NOTIFICATION_ID, | ||
240 | iwl_mvm_window_status_notif, false), | ||
241 | |||
239 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), | 242 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), |
240 | RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, true), | 243 | RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, true), |
241 | 244 | ||
@@ -263,6 +266,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
263 | RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true), | 266 | RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true), |
264 | RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE, | 267 | RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE, |
265 | iwl_mvm_temp_notif, true), | 268 | iwl_mvm_temp_notif, true), |
269 | RX_HANDLER_GRP(PHY_OPS_GROUP, CT_KILL_NOTIFICATION, | ||
270 | iwl_mvm_ct_kill_notif, false), | ||
266 | 271 | ||
267 | RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif, | 272 | RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif, |
268 | true), | 273 | true), |
@@ -270,6 +275,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
270 | RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, true), | 275 | RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, true), |
271 | RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, | 276 | RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, |
272 | iwl_mvm_rx_stored_beacon_notif, false), | 277 | iwl_mvm_rx_stored_beacon_notif, false), |
278 | RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF, | ||
279 | iwl_mvm_mu_mimo_grp_notif, false), | ||
273 | 280 | ||
274 | }; | 281 | }; |
275 | #undef RX_HANDLER | 282 | #undef RX_HANDLER |
@@ -292,6 +299,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { | |||
292 | HCMD_NAME(SCAN_COMPLETE_UMAC), | 299 | HCMD_NAME(SCAN_COMPLETE_UMAC), |
293 | HCMD_NAME(TOF_CMD), | 300 | HCMD_NAME(TOF_CMD), |
294 | HCMD_NAME(TOF_NOTIFICATION), | 301 | HCMD_NAME(TOF_NOTIFICATION), |
302 | HCMD_NAME(BA_WINDOW_STATUS_NOTIFICATION_ID), | ||
295 | HCMD_NAME(ADD_STA_KEY), | 303 | HCMD_NAME(ADD_STA_KEY), |
296 | HCMD_NAME(ADD_STA), | 304 | HCMD_NAME(ADD_STA), |
297 | HCMD_NAME(REMOVE_STA), | 305 | HCMD_NAME(REMOVE_STA), |
@@ -387,12 +395,25 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { | |||
387 | */ | 395 | */ |
388 | static const struct iwl_hcmd_names iwl_mvm_phy_names[] = { | 396 | static const struct iwl_hcmd_names iwl_mvm_phy_names[] = { |
389 | HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE), | 397 | HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE), |
398 | HCMD_NAME(CTDP_CONFIG_CMD), | ||
399 | HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD), | ||
400 | HCMD_NAME(CT_KILL_NOTIFICATION), | ||
390 | HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), | 401 | HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), |
391 | }; | 402 | }; |
392 | 403 | ||
393 | /* Please keep this array *SORTED* by hex value. | 404 | /* Please keep this array *SORTED* by hex value. |
394 | * Access is done through binary search | 405 | * Access is done through binary search |
395 | */ | 406 | */ |
407 | static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { | ||
408 | HCMD_NAME(UPDATE_MU_GROUPS_CMD), | ||
409 | HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), | ||
410 | HCMD_NAME(MU_GROUP_MGMT_NOTIF), | ||
411 | HCMD_NAME(RX_QUEUES_NOTIFICATION), | ||
412 | }; | ||
413 | |||
414 | /* Please keep this array *SORTED* by hex value. | ||
415 | * Access is done through binary search | ||
416 | */ | ||
396 | static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = { | 417 | static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = { |
397 | HCMD_NAME(STORED_BEACON_NTF), | 418 | HCMD_NAME(STORED_BEACON_NTF), |
398 | }; | 419 | }; |
@@ -401,6 +422,7 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = { | |||
401 | [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), | 422 | [LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), |
402 | [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), | 423 | [LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names), |
403 | [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), | 424 | [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), |
425 | [DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names), | ||
404 | [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), | 426 | [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), |
405 | }; | 427 | }; |
406 | 428 | ||
@@ -474,8 +496,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
474 | 496 | ||
475 | if (iwl_mvm_has_new_rx_api(mvm)) { | 497 | if (iwl_mvm_has_new_rx_api(mvm)) { |
476 | op_mode->ops = &iwl_mvm_ops_mq; | 498 | op_mode->ops = &iwl_mvm_ops_mq; |
499 | trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc); | ||
477 | } else { | 500 | } else { |
478 | op_mode->ops = &iwl_mvm_ops; | 501 | op_mode->ops = &iwl_mvm_ops; |
502 | trans->rx_mpdu_cmd_hdr_size = | ||
503 | sizeof(struct iwl_rx_mpdu_res_start); | ||
479 | 504 | ||
480 | if (WARN_ON(trans->num_rx_queues > 1)) | 505 | if (WARN_ON(trans->num_rx_queues > 1)) |
481 | goto out_free; | 506 | goto out_free; |
@@ -567,7 +592,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
567 | iwl_trans_configure(mvm->trans, &trans_cfg); | 592 | iwl_trans_configure(mvm->trans, &trans_cfg); |
568 | 593 | ||
569 | trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; | 594 | trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; |
570 | trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); | ||
571 | trans->dbg_dest_tlv = mvm->fw->dbg_dest_tlv; | 595 | trans->dbg_dest_tlv = mvm->fw->dbg_dest_tlv; |
572 | trans->dbg_dest_reg_num = mvm->fw->dbg_dest_reg_num; | 596 | trans->dbg_dest_reg_num = mvm->fw->dbg_dest_reg_num; |
573 | memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv, | 597 | memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv, |
@@ -588,7 +612,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
588 | mvm->cfg->name, mvm->trans->hw_rev); | 612 | mvm->cfg->name, mvm->trans->hw_rev); |
589 | 613 | ||
590 | min_backoff = calc_min_backoff(trans, cfg); | 614 | min_backoff = calc_min_backoff(trans, cfg); |
591 | iwl_mvm_tt_initialize(mvm, min_backoff); | 615 | iwl_mvm_thermal_initialize(mvm, min_backoff); |
592 | 616 | ||
593 | if (iwlwifi_mod_params.nvm_file) | 617 | if (iwlwifi_mod_params.nvm_file) |
594 | mvm->nvm_file_name = iwlwifi_mod_params.nvm_file; | 618 | mvm->nvm_file_name = iwlwifi_mod_params.nvm_file; |
@@ -619,7 +643,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
619 | iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); | 643 | iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); |
620 | err = iwl_run_init_mvm_ucode(mvm, true); | 644 | err = iwl_run_init_mvm_ucode(mvm, true); |
621 | if (!err || !iwlmvm_mod_params.init_dbg) | 645 | if (!err || !iwlmvm_mod_params.init_dbg) |
622 | iwl_trans_stop_device(trans); | 646 | iwl_mvm_stop_device(mvm); |
623 | iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE); | 647 | iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE); |
624 | mutex_unlock(&mvm->mutex); | 648 | mutex_unlock(&mvm->mutex); |
625 | /* returns 0 if successful, 1 if success but in rfkill */ | 649 | /* returns 0 if successful, 1 if success but in rfkill */ |
@@ -648,19 +672,22 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
648 | 672 | ||
649 | memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); | 673 | memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx)); |
650 | 674 | ||
651 | /* rpm starts with a taken reference, we can release it now */ | 675 | /* The transport always starts with a taken reference, we can |
652 | iwl_trans_unref(mvm->trans); | 676 | * release it now if d0i3 is supported */ |
677 | if (iwl_mvm_is_d0i3_supported(mvm)) | ||
678 | iwl_trans_unref(mvm->trans); | ||
653 | 679 | ||
654 | iwl_mvm_tof_init(mvm); | 680 | iwl_mvm_tof_init(mvm); |
655 | 681 | ||
656 | /* init RSS hash key */ | 682 | /* init RSS hash key */ |
657 | get_random_bytes(mvm->secret_key, ARRAY_SIZE(mvm->secret_key)); | 683 | get_random_bytes(mvm->secret_key, sizeof(mvm->secret_key)); |
658 | 684 | ||
659 | return op_mode; | 685 | return op_mode; |
660 | 686 | ||
661 | out_unregister: | 687 | out_unregister: |
662 | ieee80211_unregister_hw(mvm->hw); | 688 | ieee80211_unregister_hw(mvm->hw); |
663 | iwl_mvm_leds_exit(mvm); | 689 | iwl_mvm_leds_exit(mvm); |
690 | iwl_mvm_thermal_exit(mvm); | ||
664 | out_free: | 691 | out_free: |
665 | flush_delayed_work(&mvm->fw_dump_wk); | 692 | flush_delayed_work(&mvm->fw_dump_wk); |
666 | iwl_phy_db_free(mvm->phy_db); | 693 | iwl_phy_db_free(mvm->phy_db); |
@@ -676,9 +703,16 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
676 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 703 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
677 | int i; | 704 | int i; |
678 | 705 | ||
706 | /* If d0i3 is supported, we have released the reference that | ||
707 | * the transport started with, so we should take it back now | ||
708 | * that we are leaving. | ||
709 | */ | ||
710 | if (iwl_mvm_is_d0i3_supported(mvm)) | ||
711 | iwl_trans_ref(mvm->trans); | ||
712 | |||
679 | iwl_mvm_leds_exit(mvm); | 713 | iwl_mvm_leds_exit(mvm); |
680 | 714 | ||
681 | iwl_mvm_tt_exit(mvm); | 715 | iwl_mvm_thermal_exit(mvm); |
682 | 716 | ||
683 | ieee80211_unregister_hw(mvm->hw); | 717 | ieee80211_unregister_hw(mvm->hw); |
684 | 718 | ||
@@ -858,28 +892,24 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, | |||
858 | iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0); | 892 | iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0); |
859 | else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) | 893 | else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) |
860 | iwl_mvm_rx_phy_cmd_mq(mvm, rxb); | 894 | iwl_mvm_rx_phy_cmd_mq(mvm, rxb); |
895 | else if (unlikely(pkt->hdr.group_id == DATA_PATH_GROUP && | ||
896 | pkt->hdr.cmd == RX_QUEUES_NOTIFICATION)) | ||
897 | iwl_mvm_rx_queue_notif(mvm, rxb, 0); | ||
861 | else | 898 | else |
862 | iwl_mvm_rx_common(mvm, rxb, pkt); | 899 | iwl_mvm_rx_common(mvm, rxb, pkt); |
863 | } | 900 | } |
864 | 901 | ||
865 | static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | 902 | void iwl_mvm_stop_mac_queues(struct iwl_mvm *mvm, unsigned long mq) |
866 | { | 903 | { |
867 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
868 | unsigned long mq; | ||
869 | int q; | 904 | int q; |
870 | 905 | ||
871 | spin_lock_bh(&mvm->queue_info_lock); | ||
872 | mq = mvm->queue_info[queue].hw_queue_to_mac80211; | ||
873 | spin_unlock_bh(&mvm->queue_info_lock); | ||
874 | |||
875 | if (WARN_ON_ONCE(!mq)) | 906 | if (WARN_ON_ONCE(!mq)) |
876 | return; | 907 | return; |
877 | 908 | ||
878 | for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { | 909 | for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { |
879 | if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) { | 910 | if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) { |
880 | IWL_DEBUG_TX_QUEUES(mvm, | 911 | IWL_DEBUG_TX_QUEUES(mvm, |
881 | "queue %d (mac80211 %d) already stopped\n", | 912 | "mac80211 %d already stopped\n", q); |
882 | queue, q); | ||
883 | continue; | 913 | continue; |
884 | } | 914 | } |
885 | 915 | ||
@@ -899,24 +929,29 @@ static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, | |||
899 | iwl_trans_block_txq_ptrs(mvm->trans, false); | 929 | iwl_trans_block_txq_ptrs(mvm->trans, false); |
900 | } | 930 | } |
901 | 931 | ||
902 | static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | 932 | static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) |
903 | { | 933 | { |
904 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 934 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
905 | unsigned long mq; | 935 | unsigned long mq; |
906 | int q; | ||
907 | 936 | ||
908 | spin_lock_bh(&mvm->queue_info_lock); | 937 | spin_lock_bh(&mvm->queue_info_lock); |
909 | mq = mvm->queue_info[queue].hw_queue_to_mac80211; | 938 | mq = mvm->queue_info[hw_queue].hw_queue_to_mac80211; |
910 | spin_unlock_bh(&mvm->queue_info_lock); | 939 | spin_unlock_bh(&mvm->queue_info_lock); |
911 | 940 | ||
941 | iwl_mvm_stop_mac_queues(mvm, mq); | ||
942 | } | ||
943 | |||
944 | void iwl_mvm_start_mac_queues(struct iwl_mvm *mvm, unsigned long mq) | ||
945 | { | ||
946 | int q; | ||
947 | |||
912 | if (WARN_ON_ONCE(!mq)) | 948 | if (WARN_ON_ONCE(!mq)) |
913 | return; | 949 | return; |
914 | 950 | ||
915 | for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { | 951 | for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { |
916 | if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) { | 952 | if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) { |
917 | IWL_DEBUG_TX_QUEUES(mvm, | 953 | IWL_DEBUG_TX_QUEUES(mvm, |
918 | "queue %d (mac80211 %d) still stopped\n", | 954 | "mac80211 %d still stopped\n", q); |
919 | queue, q); | ||
920 | continue; | 955 | continue; |
921 | } | 956 | } |
922 | 957 | ||
@@ -924,6 +959,18 @@ static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | |||
924 | } | 959 | } |
925 | } | 960 | } |
926 | 961 | ||
962 | static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) | ||
963 | { | ||
964 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
965 | unsigned long mq; | ||
966 | |||
967 | spin_lock_bh(&mvm->queue_info_lock); | ||
968 | mq = mvm->queue_info[hw_queue].hw_queue_to_mac80211; | ||
969 | spin_unlock_bh(&mvm->queue_info_lock); | ||
970 | |||
971 | iwl_mvm_start_mac_queues(mvm, mq); | ||
972 | } | ||
973 | |||
927 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) | 974 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) |
928 | { | 975 | { |
929 | if (state) | 976 | if (state) |
@@ -1530,6 +1577,9 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode, | |||
1530 | 1577 | ||
1531 | if (unlikely(pkt->hdr.cmd == FRAME_RELEASE)) | 1578 | if (unlikely(pkt->hdr.cmd == FRAME_RELEASE)) |
1532 | iwl_mvm_rx_frame_release(mvm, rxb, queue); | 1579 | iwl_mvm_rx_frame_release(mvm, rxb, queue); |
1580 | else if (unlikely(pkt->hdr.cmd == RX_QUEUES_NOTIFICATION && | ||
1581 | pkt->hdr.group_id == DATA_PATH_GROUP)) | ||
1582 | iwl_mvm_rx_queue_notif(mvm, rxb, queue); | ||
1533 | else | 1583 | else |
1534 | iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue); | 1584 | iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue); |
1535 | } | 1585 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 6e7e78a37879..61d0a8cd13f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c | |||
@@ -556,6 +556,7 @@ static char *rs_pretty_rate(const struct rs_rate *rate) | |||
556 | if (is_type_legacy(rate->type) && (rate->index <= IWL_RATE_54M_INDEX)) | 556 | if (is_type_legacy(rate->type) && (rate->index <= IWL_RATE_54M_INDEX)) |
557 | rate_str = legacy_rates[rate->index]; | 557 | rate_str = legacy_rates[rate->index]; |
558 | else if ((is_type_ht(rate->type) || is_type_vht(rate->type)) && | 558 | else if ((is_type_ht(rate->type) || is_type_vht(rate->type)) && |
559 | (rate->index >= IWL_RATE_MCS_0_INDEX) && | ||
559 | (rate->index <= IWL_RATE_MCS_9_INDEX)) | 560 | (rate->index <= IWL_RATE_MCS_9_INDEX)) |
560 | rate_str = ht_vht_rates[rate->index]; | 561 | rate_str = ht_vht_rates[rate->index]; |
561 | else | 562 | else |
@@ -1672,6 +1673,20 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
1672 | } | 1673 | } |
1673 | } | 1674 | } |
1674 | 1675 | ||
1676 | static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||
1677 | struct iwl_scale_tbl_info *tbl, | ||
1678 | enum rs_action scale_action) | ||
1679 | { | ||
1680 | struct iwl_mvm_sta *sta_priv = iwl_mvm_sta_from_mac80211(sta); | ||
1681 | |||
1682 | if ((!is_vht(&tbl->rate) && !is_ht(&tbl->rate)) || | ||
1683 | tbl->rate.index < IWL_RATE_MCS_5_INDEX || | ||
1684 | scale_action == RS_ACTION_DOWNSCALE) | ||
1685 | sta_priv->tlc_amsdu = false; | ||
1686 | else | ||
1687 | sta_priv->tlc_amsdu = true; | ||
1688 | } | ||
1689 | |||
1675 | /* | 1690 | /* |
1676 | * setup rate table in uCode | 1691 | * setup rate table in uCode |
1677 | */ | 1692 | */ |
@@ -2415,6 +2430,7 @@ lq_update: | |||
2415 | tbl->rate.index = index; | 2430 | tbl->rate.index = index; |
2416 | if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK) | 2431 | if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK) |
2417 | rs_tweak_rate_tbl(mvm, sta, lq_sta, tbl, scale_action); | 2432 | rs_tweak_rate_tbl(mvm, sta, lq_sta, tbl, scale_action); |
2433 | rs_set_amsdu_len(mvm, sta, tbl, scale_action); | ||
2418 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl); | 2434 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl); |
2419 | } | 2435 | } |
2420 | 2436 | ||
@@ -3098,6 +3114,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
3098 | sband = hw->wiphy->bands[band]; | 3114 | sband = hw->wiphy->bands[band]; |
3099 | 3115 | ||
3100 | lq_sta->lq.sta_id = sta_priv->sta_id; | 3116 | lq_sta->lq.sta_id = sta_priv->sta_id; |
3117 | sta_priv->tlc_amsdu = false; | ||
3101 | 3118 | ||
3102 | for (j = 0; j < LQ_SIZE; j++) | 3119 | for (j = 0; j < LQ_SIZE; j++) |
3103 | rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); | 3120 | rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); |
@@ -3657,10 +3674,13 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3657 | ssize_t ret; | 3674 | ssize_t ret; |
3658 | 3675 | ||
3659 | struct iwl_lq_sta *lq_sta = file->private_data; | 3676 | struct iwl_lq_sta *lq_sta = file->private_data; |
3677 | struct iwl_mvm_sta *mvmsta = | ||
3678 | container_of(lq_sta, struct iwl_mvm_sta, lq_sta); | ||
3660 | struct iwl_mvm *mvm; | 3679 | struct iwl_mvm *mvm; |
3661 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 3680 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
3662 | struct rs_rate *rate = &tbl->rate; | 3681 | struct rs_rate *rate = &tbl->rate; |
3663 | u32 ss_params; | 3682 | u32 ss_params; |
3683 | |||
3664 | mvm = lq_sta->pers.drv; | 3684 | mvm = lq_sta->pers.drv; |
3665 | buff = kmalloc(2048, GFP_KERNEL); | 3685 | buff = kmalloc(2048, GFP_KERNEL); |
3666 | if (!buff) | 3686 | if (!buff) |
@@ -3686,10 +3706,11 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3686 | (is_ht20(rate)) ? "20MHz" : | 3706 | (is_ht20(rate)) ? "20MHz" : |
3687 | (is_ht40(rate)) ? "40MHz" : | 3707 | (is_ht40(rate)) ? "40MHz" : |
3688 | (is_ht80(rate)) ? "80Mhz" : "BAD BW"); | 3708 | (is_ht80(rate)) ? "80Mhz" : "BAD BW"); |
3689 | desc += sprintf(buff + desc, " %s %s %s\n", | 3709 | desc += sprintf(buff + desc, " %s %s %s %s\n", |
3690 | (rate->sgi) ? "SGI" : "NGI", | 3710 | (rate->sgi) ? "SGI" : "NGI", |
3691 | (rate->ldpc) ? "LDPC" : "BCC", | 3711 | (rate->ldpc) ? "LDPC" : "BCC", |
3692 | (lq_sta->is_agg) ? "AGG on" : ""); | 3712 | (lq_sta->is_agg) ? "AGG on" : "", |
3713 | (mvmsta->tlc_amsdu) ? "AMSDU on" : ""); | ||
3693 | } | 3714 | } |
3694 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 3715 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
3695 | lq_sta->last_rate_n_flags); | 3716 | lq_sta->last_rate_n_flags); |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 145ec68ce6f9..485cfc1a4daa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -322,11 +323,9 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
322 | rx_status->freq = | 323 | rx_status->freq = |
323 | ieee80211_channel_to_frequency(le16_to_cpu(phy_info->channel), | 324 | ieee80211_channel_to_frequency(le16_to_cpu(phy_info->channel), |
324 | rx_status->band); | 325 | rx_status->band); |
325 | /* | 326 | |
326 | * TSF as indicated by the fw is at INA time, but mac80211 expects the | 327 | /* TSF as indicated by the firmware is at INA time */ |
327 | * TSF at the beginning of the MPDU. | 328 | rx_status->flag |= RX_FLAG_MACTIME_PLCP_START; |
328 | */ | ||
329 | /*rx_status->flag |= RX_FLAG_MACTIME_MPDU;*/ | ||
330 | 329 | ||
331 | iwl_mvm_get_signal_strength(mvm, phy_info, rx_status); | 330 | iwl_mvm_get_signal_strength(mvm, phy_info, rx_status); |
332 | 331 | ||
@@ -448,6 +447,12 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
448 | iwl_mvm_update_frame_stats(mvm, rate_n_flags, | 447 | iwl_mvm_update_frame_stats(mvm, rate_n_flags, |
449 | rx_status->flag & RX_FLAG_AMPDU_DETAILS); | 448 | rx_status->flag & RX_FLAG_AMPDU_DETAILS); |
450 | #endif | 449 | #endif |
450 | |||
451 | if (unlikely((ieee80211_is_beacon(hdr->frame_control) || | ||
452 | ieee80211_is_probe_resp(hdr->frame_control)) && | ||
453 | mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)) | ||
454 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_FOUND; | ||
455 | |||
451 | iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, hdr, len, ampdu_status, | 456 | iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, hdr, len, ampdu_status, |
452 | crypt_len, rxb); | 457 | crypt_len, rxb); |
453 | } | 458 | } |
@@ -622,3 +627,51 @@ void iwl_mvm_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | |||
622 | { | 627 | { |
623 | iwl_mvm_handle_rx_statistics(mvm, rxb_addr(rxb)); | 628 | iwl_mvm_handle_rx_statistics(mvm, rxb_addr(rxb)); |
624 | } | 629 | } |
630 | |||
631 | void iwl_mvm_window_status_notif(struct iwl_mvm *mvm, | ||
632 | struct iwl_rx_cmd_buffer *rxb) | ||
633 | { | ||
634 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
635 | struct iwl_ba_window_status_notif *notif = (void *)pkt->data; | ||
636 | int i; | ||
637 | u32 pkt_len = iwl_rx_packet_payload_len(pkt); | ||
638 | |||
639 | if (WARN_ONCE(pkt_len != sizeof(*notif), | ||
640 | "Received window status notification of wrong size (%u)\n", | ||
641 | pkt_len)) | ||
642 | return; | ||
643 | |||
644 | rcu_read_lock(); | ||
645 | for (i = 0; i < BA_WINDOW_STREAMS_MAX; i++) { | ||
646 | struct ieee80211_sta *sta; | ||
647 | u8 sta_id, tid; | ||
648 | u64 bitmap; | ||
649 | u32 ssn; | ||
650 | u16 ratid; | ||
651 | u16 received_mpdu; | ||
652 | |||
653 | ratid = le16_to_cpu(notif->ra_tid[i]); | ||
654 | /* check that this TID is valid */ | ||
655 | if (!(ratid & BA_WINDOW_STATUS_VALID_MSK)) | ||
656 | continue; | ||
657 | |||
658 | received_mpdu = le16_to_cpu(notif->mpdu_rx_count[i]); | ||
659 | if (received_mpdu == 0) | ||
660 | continue; | ||
661 | |||
662 | tid = ratid & BA_WINDOW_STATUS_TID_MSK; | ||
663 | /* get the station */ | ||
664 | sta_id = (ratid & BA_WINDOW_STATUS_STA_ID_MSK) | ||
665 | >> BA_WINDOW_STATUS_STA_ID_POS; | ||
666 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | ||
667 | if (IS_ERR_OR_NULL(sta)) | ||
668 | continue; | ||
669 | bitmap = le64_to_cpu(notif->bitmap[i]); | ||
670 | ssn = le32_to_cpu(notif->start_seq_num[i]); | ||
671 | |||
672 | /* update mac80211 with the bitmap for the reordering buffer */ | ||
673 | ieee80211_mark_rx_ba_filtered_frames(sta, tid, ssn, bitmap, | ||
674 | received_mpdu); | ||
675 | } | ||
676 | rcu_read_unlock(); | ||
677 | } | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 615dea143d4e..cd6ca374e5d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2015 Intel Deutschland GmbH | 10 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -29,7 +29,7 @@ | |||
29 | * | 29 | * |
30 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 30 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
31 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 31 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
32 | * Copyright(c) 2015 Intel Deutschland GmbH | 32 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
33 | * All rights reserved. | 33 | * All rights reserved. |
34 | * | 34 | * |
35 | * Redistribution and use in source and binary forms, with or without | 35 | * Redistribution and use in source and binary forms, with or without |
@@ -156,7 +156,14 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr, | |||
156 | u16 len, u8 crypt_len, | 156 | u16 len, u8 crypt_len, |
157 | struct iwl_rx_cmd_buffer *rxb) | 157 | struct iwl_rx_cmd_buffer *rxb) |
158 | { | 158 | { |
159 | unsigned int hdrlen, fraglen; | 159 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
160 | struct iwl_rx_mpdu_desc *desc = (void *)pkt->data; | ||
161 | unsigned int headlen, fraglen, pad_len = 0; | ||
162 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
163 | |||
164 | if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) | ||
165 | pad_len = 2; | ||
166 | len -= pad_len; | ||
160 | 167 | ||
161 | /* If frame is small enough to fit in skb->head, pull it completely. | 168 | /* If frame is small enough to fit in skb->head, pull it completely. |
162 | * If not, only pull ieee80211_hdr (including crypto if present, and | 169 | * If not, only pull ieee80211_hdr (including crypto if present, and |
@@ -170,14 +177,23 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr, | |||
170 | * If the latter changes (there are efforts in the standards group | 177 | * If the latter changes (there are efforts in the standards group |
171 | * to do so) we should revisit this and ieee80211_data_to_8023(). | 178 | * to do so) we should revisit this and ieee80211_data_to_8023(). |
172 | */ | 179 | */ |
173 | hdrlen = (len <= skb_tailroom(skb)) ? len : | 180 | headlen = (len <= skb_tailroom(skb)) ? len : |
174 | sizeof(*hdr) + crypt_len + 8; | 181 | hdrlen + crypt_len + 8; |
175 | 182 | ||
183 | /* The firmware may align the packet to DWORD. | ||
184 | * The padding is inserted after the IV. | ||
185 | * After copying the header + IV skip the padding if | ||
186 | * present before copying packet data. | ||
187 | */ | ||
188 | hdrlen += crypt_len; | ||
176 | memcpy(skb_put(skb, hdrlen), hdr, hdrlen); | 189 | memcpy(skb_put(skb, hdrlen), hdr, hdrlen); |
177 | fraglen = len - hdrlen; | 190 | memcpy(skb_put(skb, headlen - hdrlen), (u8 *)hdr + hdrlen + pad_len, |
191 | headlen - hdrlen); | ||
192 | |||
193 | fraglen = len - headlen; | ||
178 | 194 | ||
179 | if (fraglen) { | 195 | if (fraglen) { |
180 | int offset = (void *)hdr + hdrlen - | 196 | int offset = (void *)hdr + headlen + pad_len - |
181 | rxb_addr(rxb) + rxb_offset(rxb); | 197 | rxb_addr(rxb) + rxb_offset(rxb); |
182 | 198 | ||
183 | skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset, | 199 | skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset, |
@@ -285,6 +301,114 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta, | |||
285 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 301 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
286 | } | 302 | } |
287 | 303 | ||
304 | /* | ||
305 | * returns true if a packet outside BA session is a duplicate and | ||
306 | * should be dropped | ||
307 | */ | ||
308 | static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue, | ||
309 | struct ieee80211_rx_status *rx_status, | ||
310 | struct ieee80211_hdr *hdr, | ||
311 | struct iwl_rx_mpdu_desc *desc) | ||
312 | { | ||
313 | struct iwl_mvm_sta *mvm_sta; | ||
314 | struct iwl_mvm_rxq_dup_data *dup_data; | ||
315 | u8 baid, tid, sub_frame_idx; | ||
316 | |||
317 | if (WARN_ON(IS_ERR_OR_NULL(sta))) | ||
318 | return false; | ||
319 | |||
320 | baid = (le32_to_cpu(desc->reorder_data) & | ||
321 | IWL_RX_MPDU_REORDER_BAID_MASK) >> | ||
322 | IWL_RX_MPDU_REORDER_BAID_SHIFT; | ||
323 | |||
324 | if (baid != IWL_RX_REORDER_DATA_INVALID_BAID) | ||
325 | return false; | ||
326 | |||
327 | mvm_sta = iwl_mvm_sta_from_mac80211(sta); | ||
328 | dup_data = &mvm_sta->dup_data[queue]; | ||
329 | |||
330 | /* | ||
331 | * Drop duplicate 802.11 retransmissions | ||
332 | * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery") | ||
333 | */ | ||
334 | if (ieee80211_is_ctl(hdr->frame_control) || | ||
335 | ieee80211_is_qos_nullfunc(hdr->frame_control) || | ||
336 | is_multicast_ether_addr(hdr->addr1)) { | ||
337 | rx_status->flag |= RX_FLAG_DUP_VALIDATED; | ||
338 | return false; | ||
339 | } | ||
340 | |||
341 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
342 | /* frame has qos control */ | ||
343 | tid = *ieee80211_get_qos_ctl(hdr) & | ||
344 | IEEE80211_QOS_CTL_TID_MASK; | ||
345 | else | ||
346 | tid = IWL_MAX_TID_COUNT; | ||
347 | |||
348 | /* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */ | ||
349 | sub_frame_idx = desc->amsdu_info & IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK; | ||
350 | |||
351 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && | ||
352 | dup_data->last_seq[tid] == hdr->seq_ctrl && | ||
353 | dup_data->last_sub_frame[tid] >= sub_frame_idx)) | ||
354 | return true; | ||
355 | |||
356 | dup_data->last_seq[tid] = hdr->seq_ctrl; | ||
357 | dup_data->last_sub_frame[tid] = sub_frame_idx; | ||
358 | |||
359 | rx_status->flag |= RX_FLAG_DUP_VALIDATED; | ||
360 | |||
361 | return false; | ||
362 | } | ||
363 | |||
364 | int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask, | ||
365 | const u8 *data, u32 count) | ||
366 | { | ||
367 | struct iwl_rxq_sync_cmd *cmd; | ||
368 | u32 data_size = sizeof(*cmd) + count; | ||
369 | int ret; | ||
370 | |||
371 | /* should be DWORD aligned */ | ||
372 | if (WARN_ON(count & 3 || count > IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE)) | ||
373 | return -EINVAL; | ||
374 | |||
375 | cmd = kzalloc(data_size, GFP_KERNEL); | ||
376 | if (!cmd) | ||
377 | return -ENOMEM; | ||
378 | |||
379 | cmd->rxq_mask = cpu_to_le32(rxq_mask); | ||
380 | cmd->count = cpu_to_le32(count); | ||
381 | cmd->flags = 0; | ||
382 | memcpy(cmd->payload, data, count); | ||
383 | |||
384 | ret = iwl_mvm_send_cmd_pdu(mvm, | ||
385 | WIDE_ID(DATA_PATH_GROUP, | ||
386 | TRIGGER_RX_QUEUES_NOTIF_CMD), | ||
387 | 0, data_size, cmd); | ||
388 | |||
389 | kfree(cmd); | ||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | ||
394 | int queue) | ||
395 | { | ||
396 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
397 | struct iwl_rxq_sync_notification *notif; | ||
398 | struct iwl_mvm_internal_rxq_notif *internal_notif; | ||
399 | |||
400 | notif = (void *)pkt->data; | ||
401 | internal_notif = (void *)notif->payload; | ||
402 | |||
403 | switch (internal_notif->type) { | ||
404 | case IWL_MVM_RXQ_NOTIF_DEL_BA: | ||
405 | /* TODO */ | ||
406 | break; | ||
407 | default: | ||
408 | WARN_ONCE(1, "Invalid identifier %d", internal_notif->type); | ||
409 | } | ||
410 | } | ||
411 | |||
288 | void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, | 412 | void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, |
289 | struct iwl_rx_cmd_buffer *rxb, int queue) | 413 | struct iwl_rx_cmd_buffer *rxb, int queue) |
290 | { | 414 | { |
@@ -332,6 +456,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
332 | rx_status->freq = ieee80211_channel_to_frequency(desc->channel, | 456 | rx_status->freq = ieee80211_channel_to_frequency(desc->channel, |
333 | rx_status->band); | 457 | rx_status->band); |
334 | iwl_mvm_get_signal_strength(mvm, desc, rx_status); | 458 | iwl_mvm_get_signal_strength(mvm, desc, rx_status); |
459 | /* TSF as indicated by the firmware is at INA time */ | ||
460 | rx_status->flag |= RX_FLAG_MACTIME_PLCP_START; | ||
335 | 461 | ||
336 | rcu_read_lock(); | 462 | rcu_read_lock(); |
337 | 463 | ||
@@ -387,6 +513,12 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
387 | 513 | ||
388 | if (ieee80211_is_data(hdr->frame_control)) | 514 | if (ieee80211_is_data(hdr->frame_control)) |
389 | iwl_mvm_rx_csum(sta, skb, desc); | 515 | iwl_mvm_rx_csum(sta, skb, desc); |
516 | |||
517 | if (iwl_mvm_is_nonagg_dup(sta, queue, rx_status, hdr, desc)) { | ||
518 | kfree_skb(skb); | ||
519 | rcu_read_unlock(); | ||
520 | return; | ||
521 | } | ||
390 | } | 522 | } |
391 | 523 | ||
392 | /* | 524 | /* |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index aa6d8074f63a..09eb72c4ae43 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -33,6 +34,7 @@ | |||
33 | * | 34 | * |
34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | 36 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
37 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
36 | * All rights reserved. | 38 | * All rights reserved. |
37 | * | 39 | * |
38 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -297,6 +299,12 @@ void iwl_mvm_rx_lmac_scan_iter_complete_notif(struct iwl_mvm *mvm, | |||
297 | iwl_mvm_dump_channel_list(notif->results, | 299 | iwl_mvm_dump_channel_list(notif->results, |
298 | notif->scanned_channels, buf, | 300 | notif->scanned_channels, buf, |
299 | sizeof(buf))); | 301 | sizeof(buf))); |
302 | |||
303 | if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_FOUND) { | ||
304 | IWL_DEBUG_SCAN(mvm, "Pass all scheduled scan results found\n"); | ||
305 | ieee80211_sched_scan_results(mvm->hw); | ||
306 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED; | ||
307 | } | ||
300 | } | 308 | } |
301 | 309 | ||
302 | void iwl_mvm_rx_scan_match_found(struct iwl_mvm *mvm, | 310 | void iwl_mvm_rx_scan_match_found(struct iwl_mvm *mvm, |
@@ -380,6 +388,7 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, | |||
380 | 388 | ||
381 | mvm->scan_status &= ~IWL_MVM_SCAN_SCHED; | 389 | mvm->scan_status &= ~IWL_MVM_SCAN_SCHED; |
382 | ieee80211_sched_scan_stopped(mvm->hw); | 390 | ieee80211_sched_scan_stopped(mvm->hw); |
391 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; | ||
383 | } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) { | 392 | } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) { |
384 | IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n", | 393 | IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n", |
385 | aborted ? "aborted" : "completed", | 394 | aborted ? "aborted" : "completed", |
@@ -533,10 +542,13 @@ static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm, | |||
533 | IWL_DEBUG_SCAN(mvm, | 542 | IWL_DEBUG_SCAN(mvm, |
534 | "Sending scheduled scan with filtering, n_match_sets %d\n", | 543 | "Sending scheduled scan with filtering, n_match_sets %d\n", |
535 | req->n_match_sets); | 544 | req->n_match_sets); |
545 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; | ||
536 | return false; | 546 | return false; |
537 | } | 547 | } |
538 | 548 | ||
539 | IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n"); | 549 | IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n"); |
550 | |||
551 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED; | ||
540 | return true; | 552 | return true; |
541 | } | 553 | } |
542 | 554 | ||
@@ -788,6 +800,9 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, | |||
788 | flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE; | 800 | flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE; |
789 | #endif | 801 | #endif |
790 | 802 | ||
803 | if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED) | ||
804 | flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE; | ||
805 | |||
791 | if (iwl_mvm_is_regular_scan(params) && | 806 | if (iwl_mvm_is_regular_scan(params) && |
792 | vif->type != NL80211_IFTYPE_P2P_DEVICE && | 807 | vif->type != NL80211_IFTYPE_P2P_DEVICE && |
793 | params->type != IWL_SCAN_TYPE_FRAGMENTED) | 808 | params->type != IWL_SCAN_TYPE_FRAGMENTED) |
@@ -1074,6 +1089,9 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, | |||
1074 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; | 1089 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; |
1075 | #endif | 1090 | #endif |
1076 | 1091 | ||
1092 | if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED) | ||
1093 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; | ||
1094 | |||
1077 | if (iwl_mvm_is_regular_scan(params) && | 1095 | if (iwl_mvm_is_regular_scan(params) && |
1078 | vif->type != NL80211_IFTYPE_P2P_DEVICE && | 1096 | vif->type != NL80211_IFTYPE_P2P_DEVICE && |
1079 | params->type != IWL_SCAN_TYPE_FRAGMENTED) | 1097 | params->type != IWL_SCAN_TYPE_FRAGMENTED) |
@@ -1301,10 +1319,6 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
1301 | return -EBUSY; | 1319 | return -EBUSY; |
1302 | } | 1320 | } |
1303 | 1321 | ||
1304 | /* we don't support "match all" in the firmware */ | ||
1305 | if (!req->n_match_sets) | ||
1306 | return -EOPNOTSUPP; | ||
1307 | |||
1308 | ret = iwl_mvm_check_running_scans(mvm, type); | 1322 | ret = iwl_mvm_check_running_scans(mvm, type); |
1309 | if (ret) | 1323 | if (ret) |
1310 | return ret; | 1324 | return ret; |
@@ -1400,6 +1414,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, | |||
1400 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1414 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
1401 | } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { | 1415 | } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { |
1402 | ieee80211_sched_scan_stopped(mvm->hw); | 1416 | ieee80211_sched_scan_stopped(mvm->hw); |
1417 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; | ||
1403 | } | 1418 | } |
1404 | 1419 | ||
1405 | mvm->scan_status &= ~mvm->scan_uid_status[uid]; | 1420 | mvm->scan_status &= ~mvm->scan_uid_status[uid]; |
@@ -1434,6 +1449,12 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, | |||
1434 | iwl_mvm_dump_channel_list(notif->results, | 1449 | iwl_mvm_dump_channel_list(notif->results, |
1435 | notif->scanned_channels, buf, | 1450 | notif->scanned_channels, buf, |
1436 | sizeof(buf))); | 1451 | sizeof(buf))); |
1452 | |||
1453 | if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_FOUND) { | ||
1454 | IWL_DEBUG_SCAN(mvm, "Pass all scheduled scan results found\n"); | ||
1455 | ieee80211_sched_scan_results(mvm->hw); | ||
1456 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED; | ||
1457 | } | ||
1437 | } | 1458 | } |
1438 | 1459 | ||
1439 | static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type) | 1460 | static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type) |
@@ -1528,6 +1549,7 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm) | |||
1528 | uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED); | 1549 | uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED); |
1529 | if (uid >= 0 && !mvm->restart_fw) { | 1550 | if (uid >= 0 && !mvm->restart_fw) { |
1530 | ieee80211_sched_scan_stopped(mvm->hw); | 1551 | ieee80211_sched_scan_stopped(mvm->hw); |
1552 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; | ||
1531 | mvm->scan_uid_status[uid] = 0; | 1553 | mvm->scan_uid_status[uid] = 0; |
1532 | } | 1554 | } |
1533 | 1555 | ||
@@ -1549,8 +1571,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm) | |||
1549 | * restart_hw, so do not report if FW is about to be | 1571 | * restart_hw, so do not report if FW is about to be |
1550 | * restarted. | 1572 | * restarted. |
1551 | */ | 1573 | */ |
1552 | if ((mvm->scan_status & IWL_MVM_SCAN_SCHED) && !mvm->restart_fw) | 1574 | if ((mvm->scan_status & IWL_MVM_SCAN_SCHED) && |
1575 | !mvm->restart_fw) { | ||
1553 | ieee80211_sched_scan_stopped(mvm->hw); | 1576 | ieee80211_sched_scan_stopped(mvm->hw); |
1577 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; | ||
1578 | } | ||
1554 | } | 1579 | } |
1555 | } | 1580 | } |
1556 | 1581 | ||
@@ -1586,6 +1611,7 @@ out: | |||
1586 | ieee80211_scan_completed(mvm->hw, true); | 1611 | ieee80211_scan_completed(mvm->hw, true); |
1587 | } else if (notify) { | 1612 | } else if (notify) { |
1588 | ieee80211_sched_scan_stopped(mvm->hw); | 1613 | ieee80211_sched_scan_stopped(mvm->hw); |
1614 | mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; | ||
1589 | } | 1615 | } |
1590 | 1616 | ||
1591 | return ret; | 1617 | return ret; |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 4854e79cbda8..ef99942d7169 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c | |||
@@ -280,6 +280,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
280 | { | 280 | { |
281 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 281 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
282 | struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); | 282 | struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); |
283 | struct iwl_mvm_rxq_dup_data *dup_data; | ||
283 | int i, ret, sta_id; | 284 | int i, ret, sta_id; |
284 | 285 | ||
285 | lockdep_assert_held(&mvm->mutex); | 286 | lockdep_assert_held(&mvm->mutex); |
@@ -327,6 +328,16 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
327 | } | 328 | } |
328 | mvm_sta->agg_tids = 0; | 329 | mvm_sta->agg_tids = 0; |
329 | 330 | ||
331 | if (iwl_mvm_has_new_rx_api(mvm) && | ||
332 | !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | ||
333 | dup_data = kcalloc(mvm->trans->num_rx_queues, | ||
334 | sizeof(*dup_data), | ||
335 | GFP_KERNEL); | ||
336 | if (!dup_data) | ||
337 | return -ENOMEM; | ||
338 | mvm_sta->dup_data = dup_data; | ||
339 | } | ||
340 | |||
330 | ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); | 341 | ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); |
331 | if (ret) | 342 | if (ret) |
332 | goto err; | 343 | goto err; |
@@ -508,6 +519,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
508 | 519 | ||
509 | lockdep_assert_held(&mvm->mutex); | 520 | lockdep_assert_held(&mvm->mutex); |
510 | 521 | ||
522 | if (iwl_mvm_has_new_rx_api(mvm)) | ||
523 | kfree(mvm_sta->dup_data); | ||
524 | |||
511 | if (vif->type == NL80211_IFTYPE_STATION && | 525 | if (vif->type == NL80211_IFTYPE_STATION && |
512 | mvmvif->ap_sta_id == mvm_sta->sta_id) { | 526 | mvmvif->ap_sta_id == mvm_sta->sta_id) { |
513 | ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); | 527 | ret = iwl_mvm_drain_sta(mvm, mvm_sta, true); |
@@ -1031,15 +1045,23 @@ release_locks: | |||
1031 | } | 1045 | } |
1032 | 1046 | ||
1033 | int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1047 | int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
1034 | struct ieee80211_sta *sta, u16 tid, u8 buf_size) | 1048 | struct ieee80211_sta *sta, u16 tid, u8 buf_size, |
1049 | bool amsdu) | ||
1035 | { | 1050 | { |
1036 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1051 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1037 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | 1052 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; |
1038 | unsigned int wdg_timeout = | 1053 | unsigned int wdg_timeout = |
1039 | iwl_mvm_get_wd_timeout(mvm, vif, sta->tdls, false); | 1054 | iwl_mvm_get_wd_timeout(mvm, vif, sta->tdls, false); |
1040 | int queue, fifo, ret; | 1055 | int queue, ret; |
1041 | u16 ssn; | 1056 | u16 ssn; |
1042 | 1057 | ||
1058 | struct iwl_trans_txq_scd_cfg cfg = { | ||
1059 | .sta_id = mvmsta->sta_id, | ||
1060 | .tid = tid, | ||
1061 | .frame_limit = buf_size, | ||
1062 | .aggregate = true, | ||
1063 | }; | ||
1064 | |||
1043 | BUILD_BUG_ON((sizeof(mvmsta->agg_tids) * BITS_PER_BYTE) | 1065 | BUILD_BUG_ON((sizeof(mvmsta->agg_tids) * BITS_PER_BYTE) |
1044 | != IWL_MAX_TID_COUNT); | 1066 | != IWL_MAX_TID_COUNT); |
1045 | 1067 | ||
@@ -1051,13 +1073,13 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1051 | tid_data->state = IWL_AGG_ON; | 1073 | tid_data->state = IWL_AGG_ON; |
1052 | mvmsta->agg_tids |= BIT(tid); | 1074 | mvmsta->agg_tids |= BIT(tid); |
1053 | tid_data->ssn = 0xffff; | 1075 | tid_data->ssn = 0xffff; |
1076 | tid_data->amsdu_in_ampdu_allowed = amsdu; | ||
1054 | spin_unlock_bh(&mvmsta->lock); | 1077 | spin_unlock_bh(&mvmsta->lock); |
1055 | 1078 | ||
1056 | fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; | 1079 | cfg.fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; |
1057 | 1080 | ||
1058 | iwl_mvm_enable_agg_txq(mvm, queue, | 1081 | iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[tid_to_mac80211_ac[tid]], |
1059 | vif->hw_queue[tid_to_mac80211_ac[tid]], fifo, | 1082 | ssn, &cfg, wdg_timeout); |
1060 | mvmsta->sta_id, tid, buf_size, ssn, wdg_timeout); | ||
1061 | 1083 | ||
1062 | ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); | 1084 | ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); |
1063 | if (ret) | 1085 | if (ret) |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index e3b9446ee995..1a8f69a41405 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h | |||
@@ -258,8 +258,7 @@ enum iwl_mvm_agg_state { | |||
258 | * This is basically (last acked packet++). | 258 | * This is basically (last acked packet++). |
259 | * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the | 259 | * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the |
260 | * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). | 260 | * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). |
261 | * @reduced_tpc: Reduced tx power. Holds the data between the | 261 | * @amsdu_in_ampdu_allowed: true if A-MSDU in A-MPDU is allowed. |
262 | * Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). | ||
263 | * @state: state of the BA agreement establishment / tear down. | 262 | * @state: state of the BA agreement establishment / tear down. |
264 | * @txq_id: Tx queue used by the BA session | 263 | * @txq_id: Tx queue used by the BA session |
265 | * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or | 264 | * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or |
@@ -273,7 +272,7 @@ struct iwl_mvm_tid_data { | |||
273 | u16 next_reclaimed; | 272 | u16 next_reclaimed; |
274 | /* The rest is Tx AGG related */ | 273 | /* The rest is Tx AGG related */ |
275 | u32 rate_n_flags; | 274 | u32 rate_n_flags; |
276 | u8 reduced_tpc; | 275 | bool amsdu_in_ampdu_allowed; |
277 | enum iwl_mvm_agg_state state; | 276 | enum iwl_mvm_agg_state state; |
278 | u16 txq_id; | 277 | u16 txq_id; |
279 | u16 ssn; | 278 | u16 ssn; |
@@ -294,6 +293,16 @@ struct iwl_mvm_key_pn { | |||
294 | }; | 293 | }; |
295 | 294 | ||
296 | /** | 295 | /** |
296 | * struct iwl_mvm_rxq_dup_data - per station per rx queue data | ||
297 | * @last_seq: last sequence per tid for duplicate packet detection | ||
298 | * @last_sub_frame: last subframe packet | ||
299 | */ | ||
300 | struct iwl_mvm_rxq_dup_data { | ||
301 | __le16 last_seq[IWL_MAX_TID_COUNT + 1]; | ||
302 | u8 last_sub_frame[IWL_MAX_TID_COUNT + 1]; | ||
303 | } ____cacheline_aligned_in_smp; | ||
304 | |||
305 | /** | ||
297 | * struct iwl_mvm_sta - representation of a station in the driver | 306 | * struct iwl_mvm_sta - representation of a station in the driver |
298 | * @sta_id: the index of the station in the fw (will be replaced by id_n_color) | 307 | * @sta_id: the index of the station in the fw (will be replaced by id_n_color) |
299 | * @tfd_queue_msk: the tfd queues used by the station | 308 | * @tfd_queue_msk: the tfd queues used by the station |
@@ -311,6 +320,7 @@ struct iwl_mvm_key_pn { | |||
311 | * @tx_protection: reference counter for controlling the Tx protection. | 320 | * @tx_protection: reference counter for controlling the Tx protection. |
312 | * @tt_tx_protection: is thermal throttling enable Tx protection? | 321 | * @tt_tx_protection: is thermal throttling enable Tx protection? |
313 | * @disable_tx: is tx to this STA disabled? | 322 | * @disable_tx: is tx to this STA disabled? |
323 | * @tlc_amsdu: true if A-MSDU is allowed | ||
314 | * @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON) | 324 | * @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON) |
315 | * @sleep_tx_count: the number of frames that we told the firmware to let out | 325 | * @sleep_tx_count: the number of frames that we told the firmware to let out |
316 | * even when that station is asleep. This is useful in case the queue | 326 | * even when that station is asleep. This is useful in case the queue |
@@ -318,6 +328,7 @@ struct iwl_mvm_key_pn { | |||
318 | * we are sending frames from an AMPDU queue and there was a hole in | 328 | * we are sending frames from an AMPDU queue and there was a hole in |
319 | * the BA window. To be used for UAPSD only. | 329 | * the BA window. To be used for UAPSD only. |
320 | * @ptk_pn: per-queue PTK PN data structures | 330 | * @ptk_pn: per-queue PTK PN data structures |
331 | * @dup_data: per queue duplicate packet detection data | ||
321 | * | 332 | * |
322 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) | 333 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) |
323 | * in the structure for use by driver. This structure is placed in that | 334 | * in the structure for use by driver. This structure is placed in that |
@@ -337,14 +348,15 @@ struct iwl_mvm_sta { | |||
337 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; | 348 | struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; |
338 | struct iwl_lq_sta lq_sta; | 349 | struct iwl_lq_sta lq_sta; |
339 | struct ieee80211_vif *vif; | 350 | struct ieee80211_vif *vif; |
340 | |||
341 | struct iwl_mvm_key_pn __rcu *ptk_pn[4]; | 351 | struct iwl_mvm_key_pn __rcu *ptk_pn[4]; |
352 | struct iwl_mvm_rxq_dup_data *dup_data; | ||
342 | 353 | ||
343 | /* Temporary, until the new TLC will control the Tx protection */ | 354 | /* Temporary, until the new TLC will control the Tx protection */ |
344 | s8 tx_protection; | 355 | s8 tx_protection; |
345 | bool tt_tx_protection; | 356 | bool tt_tx_protection; |
346 | 357 | ||
347 | bool disable_tx; | 358 | bool disable_tx; |
359 | bool tlc_amsdu; | ||
348 | u8 agg_tids; | 360 | u8 agg_tids; |
349 | u8 sleep_tx_count; | 361 | u8 sleep_tx_count; |
350 | }; | 362 | }; |
@@ -405,7 +417,8 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
405 | int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 417 | int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
406 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 418 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); |
407 | int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 419 | int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
408 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); | 420 | struct ieee80211_sta *sta, u16 tid, u8 buf_size, |
421 | bool amsdu); | ||
409 | int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 422 | int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
410 | struct ieee80211_sta *sta, u16 tid); | 423 | struct ieee80211_sta *sta, u16 tid); |
411 | int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 424 | int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index 758d05a8c6aa..999bcb898be8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -33,7 +34,7 @@ | |||
33 | * | 34 | * |
34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 36 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
36 | * Copyright(c) 2015 Intel Deutschland GmbH | 37 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
37 | * All rights reserved. | 38 | * All rights reserved. |
38 | * | 39 | * |
39 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -64,6 +65,8 @@ | |||
64 | * | 65 | * |
65 | *****************************************************************************/ | 66 | *****************************************************************************/ |
66 | 67 | ||
68 | #include <linux/sort.h> | ||
69 | |||
67 | #include "mvm.h" | 70 | #include "mvm.h" |
68 | 71 | ||
69 | #define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ | 72 | #define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ |
@@ -79,8 +82,10 @@ static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm) | |||
79 | IWL_ERR(mvm, "Enter CT Kill\n"); | 82 | IWL_ERR(mvm, "Enter CT Kill\n"); |
80 | iwl_mvm_set_hw_ctkill_state(mvm, true); | 83 | iwl_mvm_set_hw_ctkill_state(mvm, true); |
81 | 84 | ||
82 | tt->throttle = false; | 85 | if (!iwl_mvm_is_tt_in_fw(mvm)) { |
83 | tt->dynamic_smps = false; | 86 | tt->throttle = false; |
87 | tt->dynamic_smps = false; | ||
88 | } | ||
84 | 89 | ||
85 | /* Don't schedule an exit work if we're in test mode, since | 90 | /* Don't schedule an exit work if we're in test mode, since |
86 | * the temperature will not change unless we manually set it | 91 | * the temperature will not change unless we manually set it |
@@ -116,18 +121,21 @@ void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp) | |||
116 | static int iwl_mvm_temp_notif_parse(struct iwl_mvm *mvm, | 121 | static int iwl_mvm_temp_notif_parse(struct iwl_mvm *mvm, |
117 | struct iwl_rx_packet *pkt) | 122 | struct iwl_rx_packet *pkt) |
118 | { | 123 | { |
119 | struct iwl_dts_measurement_notif *notif; | 124 | struct iwl_dts_measurement_notif_v1 *notif_v1; |
120 | int len = iwl_rx_packet_payload_len(pkt); | 125 | int len = iwl_rx_packet_payload_len(pkt); |
121 | int temp; | 126 | int temp; |
122 | 127 | ||
123 | if (WARN_ON_ONCE(len < sizeof(*notif))) { | 128 | /* we can use notif_v1 only, because v2 only adds an additional |
129 | * parameter, which is not used in this function. | ||
130 | */ | ||
131 | if (WARN_ON_ONCE(len < sizeof(*notif_v1))) { | ||
124 | IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n"); | 132 | IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n"); |
125 | return -EINVAL; | 133 | return -EINVAL; |
126 | } | 134 | } |
127 | 135 | ||
128 | notif = (void *)pkt->data; | 136 | notif_v1 = (void *)pkt->data; |
129 | 137 | ||
130 | temp = le32_to_cpu(notif->temp); | 138 | temp = le32_to_cpu(notif_v1->temp); |
131 | 139 | ||
132 | /* shouldn't be negative, but since it's s32, make sure it isn't */ | 140 | /* shouldn't be negative, but since it's s32, make sure it isn't */ |
133 | if (WARN_ON_ONCE(temp < 0)) | 141 | if (WARN_ON_ONCE(temp < 0)) |
@@ -158,17 +166,74 @@ static bool iwl_mvm_temp_notif_wait(struct iwl_notif_wait_data *notif_wait, | |||
158 | void iwl_mvm_temp_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | 166 | void iwl_mvm_temp_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) |
159 | { | 167 | { |
160 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 168 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
169 | struct iwl_dts_measurement_notif_v2 *notif_v2; | ||
170 | int len = iwl_rx_packet_payload_len(pkt); | ||
161 | int temp; | 171 | int temp; |
172 | u32 ths_crossed; | ||
162 | 173 | ||
163 | /* the notification is handled synchronously in ctkill, so skip here */ | 174 | /* the notification is handled synchronously in ctkill, so skip here */ |
164 | if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) | 175 | if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) |
165 | return; | 176 | return; |
166 | 177 | ||
167 | temp = iwl_mvm_temp_notif_parse(mvm, pkt); | 178 | temp = iwl_mvm_temp_notif_parse(mvm, pkt); |
168 | if (temp < 0) | 179 | |
180 | if (!iwl_mvm_is_tt_in_fw(mvm)) { | ||
181 | if (temp >= 0) | ||
182 | iwl_mvm_tt_temp_changed(mvm, temp); | ||
169 | return; | 183 | return; |
184 | } | ||
185 | |||
186 | if (WARN_ON_ONCE(len < sizeof(*notif_v2))) { | ||
187 | IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | notif_v2 = (void *)pkt->data; | ||
192 | ths_crossed = le32_to_cpu(notif_v2->threshold_idx); | ||
170 | 193 | ||
171 | iwl_mvm_tt_temp_changed(mvm, temp); | 194 | /* 0xFF in ths_crossed means the notification is not related |
195 | * to a trip, so we can ignore it here. | ||
196 | */ | ||
197 | if (ths_crossed == 0xFF) | ||
198 | return; | ||
199 | |||
200 | IWL_DEBUG_TEMP(mvm, "Temp = %d Threshold crossed = %d\n", | ||
201 | temp, ths_crossed); | ||
202 | |||
203 | #ifdef CONFIG_THERMAL | ||
204 | if (WARN_ON(ths_crossed >= IWL_MAX_DTS_TRIPS)) | ||
205 | return; | ||
206 | |||
207 | /* | ||
208 | * We are now handling a temperature notification from the firmware | ||
209 | * in ASYNC and hold the mutex. thermal_notify_framework will call | ||
210 | * us back through get_temp() which ought to send a SYNC command to | ||
211 | * the firmware and hence to take the mutex. | ||
212 | * Avoid the deadlock by unlocking the mutex here. | ||
213 | */ | ||
214 | mutex_unlock(&mvm->mutex); | ||
215 | thermal_notify_framework(mvm->tz_device.tzone, | ||
216 | mvm->tz_device.fw_trips_index[ths_crossed]); | ||
217 | mutex_lock(&mvm->mutex); | ||
218 | #endif /* CONFIG_THERMAL */ | ||
219 | } | ||
220 | |||
221 | void iwl_mvm_ct_kill_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | ||
222 | { | ||
223 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
224 | struct ct_kill_notif *notif; | ||
225 | int len = iwl_rx_packet_payload_len(pkt); | ||
226 | |||
227 | if (WARN_ON_ONCE(len != sizeof(*notif))) { | ||
228 | IWL_ERR(mvm, "Invalid CT_KILL_NOTIFICATION\n"); | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | notif = (struct ct_kill_notif *)pkt->data; | ||
233 | IWL_DEBUG_TEMP(mvm, "CT Kill notification temperature = %d\n", | ||
234 | notif->temperature); | ||
235 | |||
236 | iwl_mvm_enter_ctkill(mvm); | ||
172 | } | 237 | } |
173 | 238 | ||
174 | static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) | 239 | static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) |
@@ -236,6 +301,12 @@ static void check_exit_ctkill(struct work_struct *work) | |||
236 | tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work); | 301 | tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work); |
237 | mvm = container_of(tt, struct iwl_mvm, thermal_throttle); | 302 | mvm = container_of(tt, struct iwl_mvm, thermal_throttle); |
238 | 303 | ||
304 | if (iwl_mvm_is_tt_in_fw(mvm)) { | ||
305 | iwl_mvm_exit_ctkill(mvm); | ||
306 | |||
307 | return; | ||
308 | } | ||
309 | |||
239 | duration = tt->params.ct_kill_duration; | 310 | duration = tt->params.ct_kill_duration; |
240 | 311 | ||
241 | mutex_lock(&mvm->mutex); | 312 | mutex_lock(&mvm->mutex); |
@@ -435,7 +506,365 @@ static const struct iwl_tt_params iwl_mvm_default_tt_params = { | |||
435 | .support_tx_backoff = true, | 506 | .support_tx_backoff = true, |
436 | }; | 507 | }; |
437 | 508 | ||
438 | void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff) | 509 | #ifdef CONFIG_THERMAL |
510 | static int compare_temps(const void *a, const void *b) | ||
511 | { | ||
512 | return ((s16)le16_to_cpu(*(__le16 *)a) - | ||
513 | (s16)le16_to_cpu(*(__le16 *)b)); | ||
514 | } | ||
515 | |||
516 | int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm) | ||
517 | { | ||
518 | struct temp_report_ths_cmd cmd = {0}; | ||
519 | int ret, i, j, idx = 0; | ||
520 | |||
521 | lockdep_assert_held(&mvm->mutex); | ||
522 | |||
523 | /* The driver holds array of temperature trips that are unsorted | ||
524 | * and uncompressed, the FW should get it compressed and sorted | ||
525 | */ | ||
526 | |||
527 | /* compress temp_trips to cmd array, remove uninitialized values*/ | ||
528 | for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) | ||
529 | if (mvm->tz_device.temp_trips[i] != S16_MIN) { | ||
530 | cmd.thresholds[idx++] = | ||
531 | cpu_to_le16(mvm->tz_device.temp_trips[i]); | ||
532 | } | ||
533 | cmd.num_temps = cpu_to_le32(idx); | ||
534 | |||
535 | if (!idx) | ||
536 | goto send; | ||
537 | |||
538 | /*sort cmd array*/ | ||
539 | sort(cmd.thresholds, idx, sizeof(s16), compare_temps, NULL); | ||
540 | |||
541 | /* we should save the indexes of trips because we sort | ||
542 | * and compress the orginal array | ||
543 | */ | ||
544 | for (i = 0; i < idx; i++) { | ||
545 | for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) { | ||
546 | if (le16_to_cpu(cmd.thresholds[i]) == | ||
547 | mvm->tz_device.temp_trips[j]) | ||
548 | mvm->tz_device.fw_trips_index[i] = j; | ||
549 | } | ||
550 | } | ||
551 | |||
552 | send: | ||
553 | ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP, | ||
554 | TEMP_REPORTING_THRESHOLDS_CMD), | ||
555 | 0, sizeof(cmd), &cmd); | ||
556 | if (ret) | ||
557 | IWL_ERR(mvm, "TEMP_REPORT_THS_CMD command failed (err=%d)\n", | ||
558 | ret); | ||
559 | |||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device, | ||
564 | int *temperature) | ||
565 | { | ||
566 | struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata; | ||
567 | int ret; | ||
568 | int temp; | ||
569 | |||
570 | mutex_lock(&mvm->mutex); | ||
571 | |||
572 | if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) { | ||
573 | ret = -EIO; | ||
574 | goto out; | ||
575 | } | ||
576 | |||
577 | ret = iwl_mvm_get_temp(mvm, &temp); | ||
578 | if (ret) | ||
579 | goto out; | ||
580 | |||
581 | *temperature = temp * 1000; | ||
582 | |||
583 | out: | ||
584 | mutex_unlock(&mvm->mutex); | ||
585 | return ret; | ||
586 | } | ||
587 | |||
588 | static int iwl_mvm_tzone_get_trip_temp(struct thermal_zone_device *device, | ||
589 | int trip, int *temp) | ||
590 | { | ||
591 | struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata; | ||
592 | |||
593 | if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) | ||
594 | return -EINVAL; | ||
595 | |||
596 | *temp = mvm->tz_device.temp_trips[trip] * 1000; | ||
597 | |||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | static int iwl_mvm_tzone_get_trip_type(struct thermal_zone_device *device, | ||
602 | int trip, enum thermal_trip_type *type) | ||
603 | { | ||
604 | if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) | ||
605 | return -EINVAL; | ||
606 | |||
607 | *type = THERMAL_TRIP_PASSIVE; | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device, | ||
613 | int trip, int temp) | ||
614 | { | ||
615 | struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata; | ||
616 | struct iwl_mvm_thermal_device *tzone; | ||
617 | int i, ret; | ||
618 | s16 temperature; | ||
619 | |||
620 | mutex_lock(&mvm->mutex); | ||
621 | |||
622 | if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) { | ||
623 | ret = -EIO; | ||
624 | goto out; | ||
625 | } | ||
626 | |||
627 | if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) { | ||
628 | ret = -EINVAL; | ||
629 | goto out; | ||
630 | } | ||
631 | |||
632 | if ((temp / 1000) > S16_MAX) { | ||
633 | ret = -EINVAL; | ||
634 | goto out; | ||
635 | } | ||
636 | |||
637 | temperature = (s16)(temp / 1000); | ||
638 | tzone = &mvm->tz_device; | ||
639 | |||
640 | if (!tzone) { | ||
641 | ret = -EIO; | ||
642 | goto out; | ||
643 | } | ||
644 | |||
645 | /* no updates*/ | ||
646 | if (tzone->temp_trips[trip] == temperature) { | ||
647 | ret = 0; | ||
648 | goto out; | ||
649 | } | ||
650 | |||
651 | /* already existing temperature */ | ||
652 | for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) { | ||
653 | if (tzone->temp_trips[i] == temperature) { | ||
654 | ret = -EINVAL; | ||
655 | goto out; | ||
656 | } | ||
657 | } | ||
658 | |||
659 | tzone->temp_trips[trip] = temperature; | ||
660 | |||
661 | ret = iwl_mvm_send_temp_report_ths_cmd(mvm); | ||
662 | out: | ||
663 | mutex_unlock(&mvm->mutex); | ||
664 | return ret; | ||
665 | } | ||
666 | |||
667 | static struct thermal_zone_device_ops tzone_ops = { | ||
668 | .get_temp = iwl_mvm_tzone_get_temp, | ||
669 | .get_trip_temp = iwl_mvm_tzone_get_trip_temp, | ||
670 | .get_trip_type = iwl_mvm_tzone_get_trip_type, | ||
671 | .set_trip_temp = iwl_mvm_tzone_set_trip_temp, | ||
672 | }; | ||
673 | |||
674 | /* make all trips writable */ | ||
675 | #define IWL_WRITABLE_TRIPS_MSK (BIT(IWL_MAX_DTS_TRIPS) - 1) | ||
676 | |||
677 | static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) | ||
678 | { | ||
679 | int i; | ||
680 | char name[] = "iwlwifi"; | ||
681 | |||
682 | if (!iwl_mvm_is_tt_in_fw(mvm)) { | ||
683 | mvm->tz_device.tzone = NULL; | ||
684 | |||
685 | return; | ||
686 | } | ||
687 | |||
688 | BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); | ||
689 | |||
690 | mvm->tz_device.tzone = thermal_zone_device_register(name, | ||
691 | IWL_MAX_DTS_TRIPS, | ||
692 | IWL_WRITABLE_TRIPS_MSK, | ||
693 | mvm, &tzone_ops, | ||
694 | NULL, 0, 0); | ||
695 | if (IS_ERR(mvm->tz_device.tzone)) { | ||
696 | IWL_DEBUG_TEMP(mvm, | ||
697 | "Failed to register to thermal zone (err = %ld)\n", | ||
698 | PTR_ERR(mvm->tz_device.tzone)); | ||
699 | return; | ||
700 | } | ||
701 | |||
702 | /* 0 is a valid temperature, | ||
703 | * so initialize the array with S16_MIN which invalid temperature | ||
704 | */ | ||
705 | for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) | ||
706 | mvm->tz_device.temp_trips[i] = S16_MIN; | ||
707 | } | ||
708 | |||
709 | static const u32 iwl_mvm_cdev_budgets[] = { | ||
710 | 2000, /* cooling state 0 */ | ||
711 | 1800, /* cooling state 1 */ | ||
712 | 1600, /* cooling state 2 */ | ||
713 | 1400, /* cooling state 3 */ | ||
714 | 1200, /* cooling state 4 */ | ||
715 | 1000, /* cooling state 5 */ | ||
716 | 900, /* cooling state 6 */ | ||
717 | 800, /* cooling state 7 */ | ||
718 | 700, /* cooling state 8 */ | ||
719 | 650, /* cooling state 9 */ | ||
720 | 600, /* cooling state 10 */ | ||
721 | 550, /* cooling state 11 */ | ||
722 | 500, /* cooling state 12 */ | ||
723 | 450, /* cooling state 13 */ | ||
724 | 400, /* cooling state 14 */ | ||
725 | 350, /* cooling state 15 */ | ||
726 | 300, /* cooling state 16 */ | ||
727 | 250, /* cooling state 17 */ | ||
728 | 200, /* cooling state 18 */ | ||
729 | 150, /* cooling state 19 */ | ||
730 | }; | ||
731 | |||
732 | int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget) | ||
733 | { | ||
734 | struct iwl_mvm_ctdp_cmd cmd = { | ||
735 | .operation = cpu_to_le32(op), | ||
736 | .budget = cpu_to_le32(budget), | ||
737 | .window_size = 0, | ||
738 | }; | ||
739 | int ret; | ||
740 | u32 status; | ||
741 | |||
742 | lockdep_assert_held(&mvm->mutex); | ||
743 | |||
744 | ret = iwl_mvm_send_cmd_pdu_status(mvm, WIDE_ID(PHY_OPS_GROUP, | ||
745 | CTDP_CONFIG_CMD), | ||
746 | sizeof(cmd), &cmd, &status); | ||
747 | |||
748 | if (ret) { | ||
749 | IWL_ERR(mvm, "cTDP command failed (err=%d)\n", ret); | ||
750 | return ret; | ||
751 | } | ||
752 | |||
753 | if (op == CTDP_CMD_OPERATION_START) | ||
754 | mvm->cooling_dev.cur_state = budget; | ||
755 | |||
756 | else if (op == CTDP_CMD_OPERATION_REPORT) | ||
757 | IWL_DEBUG_TEMP(mvm, "cTDP avg energy in mWatt = %d\n", status); | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev, | ||
763 | unsigned long *state) | ||
764 | { | ||
765 | *state = ARRAY_SIZE(iwl_mvm_cdev_budgets) - 1; | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static int iwl_mvm_tcool_get_cur_state(struct thermal_cooling_device *cdev, | ||
771 | unsigned long *state) | ||
772 | { | ||
773 | struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata); | ||
774 | |||
775 | if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) | ||
776 | return -EBUSY; | ||
777 | |||
778 | *state = mvm->cooling_dev.cur_state; | ||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev, | ||
783 | unsigned long new_state) | ||
784 | { | ||
785 | struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata); | ||
786 | int ret; | ||
787 | |||
788 | if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) | ||
789 | return -EIO; | ||
790 | |||
791 | if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) | ||
792 | return -EBUSY; | ||
793 | |||
794 | mutex_lock(&mvm->mutex); | ||
795 | |||
796 | if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) { | ||
797 | ret = -EINVAL; | ||
798 | goto unlock; | ||
799 | } | ||
800 | |||
801 | ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START, | ||
802 | iwl_mvm_cdev_budgets[new_state]); | ||
803 | |||
804 | unlock: | ||
805 | mutex_unlock(&mvm->mutex); | ||
806 | return ret; | ||
807 | } | ||
808 | |||
809 | static struct thermal_cooling_device_ops tcooling_ops = { | ||
810 | .get_max_state = iwl_mvm_tcool_get_max_state, | ||
811 | .get_cur_state = iwl_mvm_tcool_get_cur_state, | ||
812 | .set_cur_state = iwl_mvm_tcool_set_cur_state, | ||
813 | }; | ||
814 | |||
815 | int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm) | ||
816 | { | ||
817 | char name[] = "iwlwifi"; | ||
818 | |||
819 | if (!iwl_mvm_is_ctdp_supported(mvm)) { | ||
820 | mvm->cooling_dev.cdev = NULL; | ||
821 | |||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); | ||
826 | |||
827 | mvm->cooling_dev.cdev = | ||
828 | thermal_cooling_device_register(name, | ||
829 | mvm, | ||
830 | &tcooling_ops); | ||
831 | |||
832 | if (IS_ERR(mvm->cooling_dev.cdev)) { | ||
833 | IWL_DEBUG_TEMP(mvm, | ||
834 | "Failed to register to cooling device (err = %ld)\n", | ||
835 | PTR_ERR(mvm->cooling_dev.cdev)); | ||
836 | return PTR_ERR(mvm->cooling_dev.cdev); | ||
837 | } | ||
838 | |||
839 | return 0; | ||
840 | } | ||
841 | |||
842 | static void iwl_mvm_thermal_zone_unregister(struct iwl_mvm *mvm) | ||
843 | { | ||
844 | if (!iwl_mvm_is_tt_in_fw(mvm)) | ||
845 | return; | ||
846 | |||
847 | if (mvm->tz_device.tzone) { | ||
848 | IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n"); | ||
849 | thermal_zone_device_unregister(mvm->tz_device.tzone); | ||
850 | mvm->tz_device.tzone = NULL; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm) | ||
855 | { | ||
856 | if (!iwl_mvm_is_ctdp_supported(mvm)) | ||
857 | return; | ||
858 | |||
859 | if (mvm->cooling_dev.cdev) { | ||
860 | IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n"); | ||
861 | thermal_cooling_device_unregister(mvm->cooling_dev.cdev); | ||
862 | mvm->cooling_dev.cdev = NULL; | ||
863 | } | ||
864 | } | ||
865 | #endif /* CONFIG_THERMAL */ | ||
866 | |||
867 | void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff) | ||
439 | { | 868 | { |
440 | struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; | 869 | struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; |
441 | 870 | ||
@@ -450,10 +879,20 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff) | |||
450 | tt->dynamic_smps = false; | 879 | tt->dynamic_smps = false; |
451 | tt->min_backoff = min_backoff; | 880 | tt->min_backoff = min_backoff; |
452 | INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); | 881 | INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); |
882 | |||
883 | #ifdef CONFIG_THERMAL | ||
884 | iwl_mvm_cooling_device_register(mvm); | ||
885 | iwl_mvm_thermal_zone_register(mvm); | ||
886 | #endif | ||
453 | } | 887 | } |
454 | 888 | ||
455 | void iwl_mvm_tt_exit(struct iwl_mvm *mvm) | 889 | void iwl_mvm_thermal_exit(struct iwl_mvm *mvm) |
456 | { | 890 | { |
457 | cancel_delayed_work_sync(&mvm->thermal_throttle.ct_kill_exit); | 891 | cancel_delayed_work_sync(&mvm->thermal_throttle.ct_kill_exit); |
458 | IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n"); | 892 | IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n"); |
893 | |||
894 | #ifdef CONFIG_THERMAL | ||
895 | iwl_mvm_cooling_device_unregister(mvm); | ||
896 | iwl_mvm_thermal_zone_unregister(mvm); | ||
897 | #endif | ||
459 | } | 898 | } |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index dae2c40d605c..271e8da6d140 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c | |||
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/ieee80211.h> | 65 | #include <linux/ieee80211.h> |
66 | #include <linux/etherdevice.h> | 66 | #include <linux/etherdevice.h> |
67 | #include <linux/tcp.h> | 67 | #include <linux/tcp.h> |
68 | #include <net/ip.h> | ||
68 | 69 | ||
69 | #include "iwl-trans.h" | 70 | #include "iwl-trans.h" |
70 | #include "iwl-eeprom-parse.h" | 71 | #include "iwl-eeprom-parse.h" |
@@ -182,7 +183,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
182 | 183 | ||
183 | tx_cmd->tx_flags = cpu_to_le32(tx_flags); | 184 | tx_cmd->tx_flags = cpu_to_le32(tx_flags); |
184 | /* Total # bytes to be transmitted */ | 185 | /* Total # bytes to be transmitted */ |
185 | tx_cmd->len = cpu_to_le16((u16)skb->len); | 186 | tx_cmd->len = cpu_to_le16((u16)skb->len + |
187 | (uintptr_t)info->driver_data[0]); | ||
186 | tx_cmd->next_frame_len = 0; | 188 | tx_cmd->next_frame_len = 0; |
187 | tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); | 189 | tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); |
188 | tx_cmd->sta_id = sta_id; | 190 | tx_cmd->sta_id = sta_id; |
@@ -372,6 +374,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
372 | info->hw_queue != info->control.vif->cab_queue))) | 374 | info->hw_queue != info->control.vif->cab_queue))) |
373 | return -1; | 375 | return -1; |
374 | 376 | ||
377 | /* This holds the amsdu headers length */ | ||
378 | info->driver_data[0] = (void *)(uintptr_t)0; | ||
379 | |||
375 | /* | 380 | /* |
376 | * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used | 381 | * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used |
377 | * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel | 382 | * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel |
@@ -437,33 +442,194 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) | |||
437 | return 0; | 442 | return 0; |
438 | } | 443 | } |
439 | 444 | ||
440 | static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb_gso, | 445 | #ifdef CONFIG_INET |
446 | static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | ||
441 | struct ieee80211_sta *sta, | 447 | struct ieee80211_sta *sta, |
442 | struct sk_buff_head *mpdus_skb) | 448 | struct sk_buff_head *mpdus_skb) |
443 | { | 449 | { |
450 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
451 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
452 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
453 | unsigned int mss = skb_shinfo(skb)->gso_size; | ||
444 | struct sk_buff *tmp, *next; | 454 | struct sk_buff *tmp, *next; |
445 | char cb[sizeof(skb_gso->cb)]; | 455 | char cb[sizeof(skb->cb)]; |
456 | unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len; | ||
457 | bool ipv4 = (skb->protocol == htons(ETH_P_IP)); | ||
458 | u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; | ||
459 | u16 amsdu_add, snap_ip_tcp, pad, i = 0; | ||
460 | unsigned int dbg_max_amsdu_len; | ||
461 | u8 *qc, tid, txf; | ||
462 | |||
463 | snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) + | ||
464 | tcp_hdrlen(skb); | ||
465 | |||
466 | qc = ieee80211_get_qos_ctl(hdr); | ||
467 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | ||
468 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | ||
469 | return -EINVAL; | ||
470 | |||
471 | if (!sta->max_amsdu_len || | ||
472 | !ieee80211_is_data_qos(hdr->frame_control) || | ||
473 | !mvmsta->tlc_amsdu) { | ||
474 | num_subframes = 1; | ||
475 | pad = 0; | ||
476 | goto segment; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * No need to lock amsdu_in_ampdu_allowed since it can't be modified | ||
481 | * during an BA session. | ||
482 | */ | ||
483 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
484 | !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) { | ||
485 | num_subframes = 1; | ||
486 | pad = 0; | ||
487 | goto segment; | ||
488 | } | ||
489 | |||
490 | max_amsdu_len = sta->max_amsdu_len; | ||
491 | dbg_max_amsdu_len = ACCESS_ONCE(mvm->max_amsdu_len); | ||
492 | |||
493 | /* the Tx FIFO to which this A-MSDU will be routed */ | ||
494 | txf = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; | ||
495 | |||
496 | /* | ||
497 | * Don't send an AMSDU that will be longer than the TXF. | ||
498 | * Add a security margin of 256 for the TX command + headers. | ||
499 | * We also want to have the start of the next packet inside the | ||
500 | * fifo to be able to send bursts. | ||
501 | */ | ||
502 | max_amsdu_len = min_t(unsigned int, max_amsdu_len, | ||
503 | mvm->shared_mem_cfg.txfifo_size[txf] - 256); | ||
504 | |||
505 | if (dbg_max_amsdu_len) | ||
506 | max_amsdu_len = min_t(unsigned int, max_amsdu_len, | ||
507 | dbg_max_amsdu_len); | ||
508 | |||
509 | /* | ||
510 | * Limit A-MSDU in A-MPDU to 4095 bytes when VHT is not | ||
511 | * supported. This is a spec requirement (IEEE 802.11-2015 | ||
512 | * section 8.7.3 NOTE 3). | ||
513 | */ | ||
514 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
515 | !sta->vht_cap.vht_supported) | ||
516 | max_amsdu_len = min_t(unsigned int, max_amsdu_len, 4095); | ||
517 | |||
518 | /* Sub frame header + SNAP + IP header + TCP header + MSS */ | ||
519 | subf_len = sizeof(struct ethhdr) + snap_ip_tcp + mss; | ||
520 | pad = (4 - subf_len) & 0x3; | ||
521 | |||
522 | /* | ||
523 | * If we have N subframes in the A-MSDU, then the A-MSDU's size is | ||
524 | * N * subf_len + (N - 1) * pad. | ||
525 | */ | ||
526 | num_subframes = (max_amsdu_len + pad) / (subf_len + pad); | ||
527 | if (num_subframes > 1) | ||
528 | *qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT; | ||
446 | 529 | ||
447 | memcpy(cb, skb_gso->cb, sizeof(cb)); | 530 | tcp_payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - |
448 | next = skb_gso_segment(skb_gso, 0); | 531 | tcp_hdrlen(skb) + skb->data_len; |
449 | if (IS_ERR(next)) | 532 | |
533 | /* | ||
534 | * Make sure we have enough TBs for the A-MSDU: | ||
535 | * 2 for each subframe | ||
536 | * 1 more for each fragment | ||
537 | * 1 more for the potential data in the header | ||
538 | */ | ||
539 | num_subframes = | ||
540 | min_t(unsigned int, num_subframes, | ||
541 | (mvm->trans->max_skb_frags - 1 - | ||
542 | skb_shinfo(skb)->nr_frags) / 2); | ||
543 | |||
544 | /* This skb fits in one single A-MSDU */ | ||
545 | if (num_subframes * mss >= tcp_payload_len) { | ||
546 | /* | ||
547 | * Compute the length of all the data added for the A-MSDU. | ||
548 | * This will be used to compute the length to write in the TX | ||
549 | * command. We have: SNAP + IP + TCP for n -1 subframes and | ||
550 | * ETH header for n subframes. Note that the original skb | ||
551 | * already had one set of SNAP / IP / TCP headers. | ||
552 | */ | ||
553 | num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); | ||
554 | info = IEEE80211_SKB_CB(skb); | ||
555 | amsdu_add = num_subframes * sizeof(struct ethhdr) + | ||
556 | (num_subframes - 1) * (snap_ip_tcp + pad); | ||
557 | /* This holds the amsdu headers length */ | ||
558 | info->driver_data[0] = (void *)(uintptr_t)amsdu_add; | ||
559 | |||
560 | __skb_queue_tail(mpdus_skb, skb); | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | /* | ||
565 | * Trick the segmentation function to make it | ||
566 | * create SKBs that can fit into one A-MSDU. | ||
567 | */ | ||
568 | segment: | ||
569 | skb_shinfo(skb)->gso_size = num_subframes * mss; | ||
570 | memcpy(cb, skb->cb, sizeof(cb)); | ||
571 | |||
572 | next = skb_gso_segment(skb, NETIF_F_CSUM_MASK | NETIF_F_SG); | ||
573 | skb_shinfo(skb)->gso_size = mss; | ||
574 | if (WARN_ON_ONCE(IS_ERR(next))) | ||
450 | return -EINVAL; | 575 | return -EINVAL; |
451 | else if (next) | 576 | else if (next) |
452 | consume_skb(skb_gso); | 577 | consume_skb(skb); |
453 | 578 | ||
454 | while (next) { | 579 | while (next) { |
455 | tmp = next; | 580 | tmp = next; |
456 | next = tmp->next; | 581 | next = tmp->next; |
582 | |||
457 | memcpy(tmp->cb, cb, sizeof(tmp->cb)); | 583 | memcpy(tmp->cb, cb, sizeof(tmp->cb)); |
584 | /* | ||
585 | * Compute the length of all the data added for the A-MSDU. | ||
586 | * This will be used to compute the length to write in the TX | ||
587 | * command. We have: SNAP + IP + TCP for n -1 subframes and | ||
588 | * ETH header for n subframes. | ||
589 | */ | ||
590 | tcp_payload_len = skb_tail_pointer(tmp) - | ||
591 | skb_transport_header(tmp) - | ||
592 | tcp_hdrlen(tmp) + tmp->data_len; | ||
593 | |||
594 | if (ipv4) | ||
595 | ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); | ||
596 | |||
597 | if (tcp_payload_len > mss) { | ||
598 | num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); | ||
599 | info = IEEE80211_SKB_CB(tmp); | ||
600 | amsdu_add = num_subframes * sizeof(struct ethhdr) + | ||
601 | (num_subframes - 1) * (snap_ip_tcp + pad); | ||
602 | info->driver_data[0] = (void *)(uintptr_t)amsdu_add; | ||
603 | skb_shinfo(tmp)->gso_size = mss; | ||
604 | } else { | ||
605 | qc = ieee80211_get_qos_ctl((void *)tmp->data); | ||
606 | |||
607 | if (ipv4) | ||
608 | ip_send_check(ip_hdr(tmp)); | ||
609 | *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; | ||
610 | skb_shinfo(tmp)->gso_size = 0; | ||
611 | } | ||
458 | 612 | ||
459 | tmp->prev = NULL; | 613 | tmp->prev = NULL; |
460 | tmp->next = NULL; | 614 | tmp->next = NULL; |
461 | 615 | ||
462 | __skb_queue_tail(mpdus_skb, tmp); | 616 | __skb_queue_tail(mpdus_skb, tmp); |
617 | i++; | ||
463 | } | 618 | } |
464 | 619 | ||
465 | return 0; | 620 | return 0; |
466 | } | 621 | } |
622 | #else /* CONFIG_INET */ | ||
623 | static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | ||
624 | struct ieee80211_sta *sta, | ||
625 | struct sk_buff_head *mpdus_skb) | ||
626 | { | ||
627 | /* Impossible to get TSO with CONFIG_INET */ | ||
628 | WARN_ON(1); | ||
629 | |||
630 | return -1; | ||
631 | } | ||
632 | #endif | ||
467 | 633 | ||
468 | /* | 634 | /* |
469 | * Sets the fields in the Tx cmd that are crypto related | 635 | * Sets the fields in the Tx cmd that are crypto related |
@@ -569,6 +735,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
569 | struct ieee80211_sta *sta) | 735 | struct ieee80211_sta *sta) |
570 | { | 736 | { |
571 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 737 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
738 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
572 | struct sk_buff_head mpdus_skbs; | 739 | struct sk_buff_head mpdus_skbs; |
573 | unsigned int payload_len; | 740 | unsigned int payload_len; |
574 | int ret; | 741 | int ret; |
@@ -579,6 +746,9 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
579 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) | 746 | if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) |
580 | return -1; | 747 | return -1; |
581 | 748 | ||
749 | /* This holds the amsdu headers length */ | ||
750 | info->driver_data[0] = (void *)(uintptr_t)0; | ||
751 | |||
582 | if (!skb_is_gso(skb)) | 752 | if (!skb_is_gso(skb)) |
583 | return iwl_mvm_tx_mpdu(mvm, skb, sta); | 753 | return iwl_mvm_tx_mpdu(mvm, skb, sta); |
584 | 754 | ||
@@ -598,7 +768,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
598 | return ret; | 768 | return ret; |
599 | 769 | ||
600 | while (!skb_queue_empty(&mpdus_skbs)) { | 770 | while (!skb_queue_empty(&mpdus_skbs)) { |
601 | struct sk_buff *skb = __skb_dequeue(&mpdus_skbs); | 771 | skb = __skb_dequeue(&mpdus_skbs); |
602 | 772 | ||
603 | ret = iwl_mvm_tx_mpdu(mvm, skb, sta); | 773 | ret = iwl_mvm_tx_mpdu(mvm, skb, sta); |
604 | if (ret) { | 774 | if (ret) { |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 753ec6785912..d33b6baf5f98 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c | |||
@@ -811,6 +811,45 @@ static int iwl_pci_runtime_resume(struct device *device) | |||
811 | 811 | ||
812 | return 0; | 812 | return 0; |
813 | } | 813 | } |
814 | |||
815 | static int iwl_pci_system_prepare(struct device *device) | ||
816 | { | ||
817 | struct pci_dev *pdev = to_pci_dev(device); | ||
818 | struct iwl_trans *trans = pci_get_drvdata(pdev); | ||
819 | |||
820 | IWL_DEBUG_RPM(trans, "preparing for system suspend\n"); | ||
821 | |||
822 | /* This is called before entering system suspend and before | ||
823 | * the runtime resume is called. Set the suspending flag to | ||
824 | * prevent the wakelock from being taken. | ||
825 | */ | ||
826 | trans->suspending = true; | ||
827 | |||
828 | /* Wake the device up from runtime suspend before going to | ||
829 | * platform suspend. This is needed because we don't know | ||
830 | * whether wowlan any is set and, if it's not, mac80211 will | ||
831 | * disconnect (in which case, we can't be in D0i3). | ||
832 | */ | ||
833 | pm_runtime_resume(device); | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | static void iwl_pci_system_complete(struct device *device) | ||
839 | { | ||
840 | struct pci_dev *pdev = to_pci_dev(device); | ||
841 | struct iwl_trans *trans = pci_get_drvdata(pdev); | ||
842 | |||
843 | IWL_DEBUG_RPM(trans, "completing system suspend\n"); | ||
844 | |||
845 | /* This is called as a counterpart to the prepare op. It is | ||
846 | * called either when suspending fails or when suspend | ||
847 | * completed successfully. Now there's no risk of grabbing | ||
848 | * the wakelock anymore, so we can release the suspending | ||
849 | * flag. | ||
850 | */ | ||
851 | trans->suspending = false; | ||
852 | } | ||
814 | #endif /* CONFIG_IWLWIFI_PCIE_RTPM */ | 853 | #endif /* CONFIG_IWLWIFI_PCIE_RTPM */ |
815 | 854 | ||
816 | static const struct dev_pm_ops iwl_dev_pm_ops = { | 855 | static const struct dev_pm_ops iwl_dev_pm_ops = { |
@@ -820,6 +859,8 @@ static const struct dev_pm_ops iwl_dev_pm_ops = { | |||
820 | SET_RUNTIME_PM_OPS(iwl_pci_runtime_suspend, | 859 | SET_RUNTIME_PM_OPS(iwl_pci_runtime_suspend, |
821 | iwl_pci_runtime_resume, | 860 | iwl_pci_runtime_resume, |
822 | NULL) | 861 | NULL) |
862 | .prepare = iwl_pci_system_prepare, | ||
863 | .complete = iwl_pci_system_complete, | ||
823 | #endif /* CONFIG_IWLWIFI_PCIE_RTPM */ | 864 | #endif /* CONFIG_IWLWIFI_PCIE_RTPM */ |
824 | }; | 865 | }; |
825 | 866 | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 542bbc5e2b24..6677f3122226 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h | |||
@@ -336,6 +336,14 @@ struct iwl_tso_hdr_page { | |||
336 | * @fw_mon_phys: physical address of the buffer for the firmware monitor | 336 | * @fw_mon_phys: physical address of the buffer for the firmware monitor |
337 | * @fw_mon_page: points to the first page of the buffer for the firmware monitor | 337 | * @fw_mon_page: points to the first page of the buffer for the firmware monitor |
338 | * @fw_mon_size: size of the buffer for the firmware monitor | 338 | * @fw_mon_size: size of the buffer for the firmware monitor |
339 | * @msix_entries: array of MSI-X entries | ||
340 | * @msix_enabled: true if managed to enable MSI-X | ||
341 | * @allocated_vector: the number of interrupt vector allocated by the OS | ||
342 | * @default_irq_num: default irq for non rx interrupt | ||
343 | * @fh_init_mask: initial unmasked fh causes | ||
344 | * @hw_init_mask: initial unmasked hw causes | ||
345 | * @fh_mask: current unmasked fh causes | ||
346 | * @hw_mask: current unmasked hw causes | ||
339 | */ | 347 | */ |
340 | struct iwl_trans_pcie { | 348 | struct iwl_trans_pcie { |
341 | struct iwl_rxq *rxq; | 349 | struct iwl_rxq *rxq; |
@@ -402,6 +410,15 @@ struct iwl_trans_pcie { | |||
402 | dma_addr_t fw_mon_phys; | 410 | dma_addr_t fw_mon_phys; |
403 | struct page *fw_mon_page; | 411 | struct page *fw_mon_page; |
404 | u32 fw_mon_size; | 412 | u32 fw_mon_size; |
413 | |||
414 | struct msix_entry msix_entries[IWL_MAX_RX_HW_QUEUES]; | ||
415 | bool msix_enabled; | ||
416 | u32 allocated_vector; | ||
417 | u32 default_irq_num; | ||
418 | u32 fh_init_mask; | ||
419 | u32 hw_init_mask; | ||
420 | u32 fh_mask; | ||
421 | u32 hw_mask; | ||
405 | }; | 422 | }; |
406 | 423 | ||
407 | static inline struct iwl_trans_pcie * | 424 | static inline struct iwl_trans_pcie * |
@@ -430,7 +447,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans); | |||
430 | * RX | 447 | * RX |
431 | ******************************************************/ | 448 | ******************************************************/ |
432 | int iwl_pcie_rx_init(struct iwl_trans *trans); | 449 | int iwl_pcie_rx_init(struct iwl_trans *trans); |
450 | irqreturn_t iwl_pcie_msix_isr(int irq, void *data); | ||
433 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id); | 451 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id); |
452 | irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id); | ||
453 | irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id); | ||
434 | int iwl_pcie_rx_stop(struct iwl_trans *trans); | 454 | int iwl_pcie_rx_stop(struct iwl_trans *trans); |
435 | void iwl_pcie_rx_free(struct iwl_trans *trans); | 455 | void iwl_pcie_rx_free(struct iwl_trans *trans); |
436 | 456 | ||
@@ -485,15 +505,24 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans); | |||
485 | ******************************************************/ | 505 | ******************************************************/ |
486 | static inline void iwl_disable_interrupts(struct iwl_trans *trans) | 506 | static inline void iwl_disable_interrupts(struct iwl_trans *trans) |
487 | { | 507 | { |
488 | clear_bit(STATUS_INT_ENABLED, &trans->status); | 508 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
489 | |||
490 | /* disable interrupts from uCode/NIC to host */ | ||
491 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); | ||
492 | 509 | ||
493 | /* acknowledge/clear/reset any interrupts still pending | 510 | clear_bit(STATUS_INT_ENABLED, &trans->status); |
494 | * from uCode or flow handler (Rx/Tx DMA) */ | 511 | if (!trans_pcie->msix_enabled) { |
495 | iwl_write32(trans, CSR_INT, 0xffffffff); | 512 | /* disable interrupts from uCode/NIC to host */ |
496 | iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); | 513 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); |
514 | |||
515 | /* acknowledge/clear/reset any interrupts still pending | ||
516 | * from uCode or flow handler (Rx/Tx DMA) */ | ||
517 | iwl_write32(trans, CSR_INT, 0xffffffff); | ||
518 | iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); | ||
519 | } else { | ||
520 | /* disable all the interrupt we might use */ | ||
521 | iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, | ||
522 | trans_pcie->fh_init_mask); | ||
523 | iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, | ||
524 | trans_pcie->hw_init_mask); | ||
525 | } | ||
497 | IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); | 526 | IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); |
498 | } | 527 | } |
499 | 528 | ||
@@ -503,8 +532,37 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) | |||
503 | 532 | ||
504 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); | 533 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); |
505 | set_bit(STATUS_INT_ENABLED, &trans->status); | 534 | set_bit(STATUS_INT_ENABLED, &trans->status); |
506 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | 535 | if (!trans_pcie->msix_enabled) { |
507 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | 536 | trans_pcie->inta_mask = CSR_INI_SET_MASK; |
537 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | ||
538 | } else { | ||
539 | /* | ||
540 | * fh/hw_mask keeps all the unmasked causes. | ||
541 | * Unlike msi, in msix cause is enabled when it is unset. | ||
542 | */ | ||
543 | trans_pcie->hw_mask = trans_pcie->hw_init_mask; | ||
544 | trans_pcie->fh_mask = trans_pcie->fh_init_mask; | ||
545 | iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, | ||
546 | ~trans_pcie->fh_mask); | ||
547 | iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, | ||
548 | ~trans_pcie->hw_mask); | ||
549 | } | ||
550 | } | ||
551 | |||
552 | static inline void iwl_enable_hw_int_msk_msix(struct iwl_trans *trans, u32 msk) | ||
553 | { | ||
554 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
555 | |||
556 | iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, ~msk); | ||
557 | trans_pcie->hw_mask = msk; | ||
558 | } | ||
559 | |||
560 | static inline void iwl_enable_fh_int_msk_msix(struct iwl_trans *trans, u32 msk) | ||
561 | { | ||
562 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
563 | |||
564 | iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~msk); | ||
565 | trans_pcie->fh_mask = msk; | ||
508 | } | 566 | } |
509 | 567 | ||
510 | static inline void iwl_enable_fw_load_int(struct iwl_trans *trans) | 568 | static inline void iwl_enable_fw_load_int(struct iwl_trans *trans) |
@@ -512,8 +570,15 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans) | |||
512 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 570 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
513 | 571 | ||
514 | IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n"); | 572 | IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n"); |
515 | trans_pcie->inta_mask = CSR_INT_BIT_FH_TX; | 573 | if (!trans_pcie->msix_enabled) { |
516 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | 574 | trans_pcie->inta_mask = CSR_INT_BIT_FH_TX; |
575 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | ||
576 | } else { | ||
577 | iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, | ||
578 | trans_pcie->hw_init_mask); | ||
579 | iwl_enable_fh_int_msk_msix(trans, | ||
580 | MSIX_FH_INT_CAUSES_D2S_CH0_NUM); | ||
581 | } | ||
517 | } | 582 | } |
518 | 583 | ||
519 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) | 584 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) |
@@ -521,8 +586,15 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) | |||
521 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 586 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
522 | 587 | ||
523 | IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); | 588 | IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); |
524 | trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL; | 589 | if (!trans_pcie->msix_enabled) { |
525 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | 590 | trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL; |
591 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | ||
592 | } else { | ||
593 | iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, | ||
594 | trans_pcie->fh_init_mask); | ||
595 | iwl_enable_hw_int_msk_msix(trans, | ||
596 | MSIX_HW_INT_CAUSES_REG_RF_KILL); | ||
597 | } | ||
526 | } | 598 | } |
527 | 599 | ||
528 | static inline void iwl_wake_queue(struct iwl_trans *trans, | 600 | static inline void iwl_wake_queue(struct iwl_trans *trans, |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 07973ef826c1..489b07a9e471 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c | |||
@@ -783,16 +783,26 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) | |||
783 | * Single frame mode | 783 | * Single frame mode |
784 | * Rx buffer size 4 or 8k or 12k | 784 | * Rx buffer size 4 or 8k or 12k |
785 | * Min RB size 4 or 8 | 785 | * Min RB size 4 or 8 |
786 | * Drop frames that exceed RB size | ||
786 | * 512 RBDs | 787 | * 512 RBDs |
787 | */ | 788 | */ |
788 | iwl_write_prph(trans, RFH_RXF_DMA_CFG, | 789 | iwl_write_prph(trans, RFH_RXF_DMA_CFG, |
789 | RFH_DMA_EN_ENABLE_VAL | | 790 | RFH_DMA_EN_ENABLE_VAL | |
790 | rb_size | RFH_RXF_DMA_SINGLE_FRAME_MASK | | 791 | rb_size | RFH_RXF_DMA_SINGLE_FRAME_MASK | |
791 | RFH_RXF_DMA_MIN_RB_4_8 | | 792 | RFH_RXF_DMA_MIN_RB_4_8 | |
793 | RFH_RXF_DMA_DROP_TOO_LARGE_MASK | | ||
792 | RFH_RXF_DMA_RBDCB_SIZE_512); | 794 | RFH_RXF_DMA_RBDCB_SIZE_512); |
793 | 795 | ||
796 | /* | ||
797 | * Activate DMA snooping. | ||
798 | * Set RX DMA chunk size to 128 bit | ||
799 | * Default queue is 0 | ||
800 | */ | ||
794 | iwl_write_prph(trans, RFH_GEN_CFG, RFH_GEN_CFG_RFH_DMA_SNOOP | | 801 | iwl_write_prph(trans, RFH_GEN_CFG, RFH_GEN_CFG_RFH_DMA_SNOOP | |
795 | RFH_GEN_CFG_SERVICE_DMA_SNOOP); | 802 | RFH_GEN_CFG_RB_CHUNK_SIZE | |
803 | (DEFAULT_RXQ_NUM << RFH_GEN_CFG_DEFAULT_RXQ_NUM_POS) | | ||
804 | RFH_GEN_CFG_SERVICE_DMA_SNOOP); | ||
805 | /* Enable the relevant rx queues */ | ||
796 | iwl_write_prph(trans, RFH_RXF_RXQ_ACTIVE, enabled); | 806 | iwl_write_prph(trans, RFH_RXF_RXQ_ACTIVE, enabled); |
797 | 807 | ||
798 | /* Set interrupt coalescing timer to default (2048 usecs) */ | 808 | /* Set interrupt coalescing timer to default (2048 usecs) */ |
@@ -1135,10 +1145,10 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
1135 | /* | 1145 | /* |
1136 | * iwl_pcie_rx_handle - Main entry function for receiving responses from fw | 1146 | * iwl_pcie_rx_handle - Main entry function for receiving responses from fw |
1137 | */ | 1147 | */ |
1138 | static void iwl_pcie_rx_handle(struct iwl_trans *trans) | 1148 | static void iwl_pcie_rx_handle(struct iwl_trans *trans, int queue) |
1139 | { | 1149 | { |
1140 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1150 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1141 | struct iwl_rxq *rxq = &trans_pcie->rxq[0]; | 1151 | struct iwl_rxq *rxq = &trans_pcie->rxq[queue]; |
1142 | u32 r, i, j, count = 0; | 1152 | u32 r, i, j, count = 0; |
1143 | bool emergency = false; | 1153 | bool emergency = false; |
1144 | 1154 | ||
@@ -1149,9 +1159,12 @@ restart: | |||
1149 | r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF; | 1159 | r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF; |
1150 | i = rxq->read; | 1160 | i = rxq->read; |
1151 | 1161 | ||
1162 | /* W/A 9000 device step A0 wrap-around bug */ | ||
1163 | r &= (rxq->queue_size - 1); | ||
1164 | |||
1152 | /* Rx interrupt, but nothing sent from uCode */ | 1165 | /* Rx interrupt, but nothing sent from uCode */ |
1153 | if (i == r) | 1166 | if (i == r) |
1154 | IWL_DEBUG_RX(trans, "HW = SW = %d\n", r); | 1167 | IWL_DEBUG_RX(trans, "Q %d: HW = SW = %d\n", rxq->id, r); |
1155 | 1168 | ||
1156 | while (i != r) { | 1169 | while (i != r) { |
1157 | struct iwl_rx_mem_buffer *rxb; | 1170 | struct iwl_rx_mem_buffer *rxb; |
@@ -1164,15 +1177,18 @@ restart: | |||
1164 | * used_bd is a 32 bit but only 12 are used to retrieve | 1177 | * used_bd is a 32 bit but only 12 are used to retrieve |
1165 | * the vid | 1178 | * the vid |
1166 | */ | 1179 | */ |
1167 | u16 vid = (u16)le32_to_cpu(rxq->used_bd[i]); | 1180 | u16 vid = le32_to_cpu(rxq->used_bd[i]) & 0x0FFF; |
1168 | 1181 | ||
1182 | if (WARN(vid >= ARRAY_SIZE(trans_pcie->global_table), | ||
1183 | "Invalid rxb index from HW %u\n", (u32)vid)) | ||
1184 | goto out; | ||
1169 | rxb = trans_pcie->global_table[vid]; | 1185 | rxb = trans_pcie->global_table[vid]; |
1170 | } else { | 1186 | } else { |
1171 | rxb = rxq->queue[i]; | 1187 | rxb = rxq->queue[i]; |
1172 | rxq->queue[i] = NULL; | 1188 | rxq->queue[i] = NULL; |
1173 | } | 1189 | } |
1174 | 1190 | ||
1175 | IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d\n", r, i); | 1191 | IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i); |
1176 | iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency); | 1192 | iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency); |
1177 | 1193 | ||
1178 | i = (i + 1) & (rxq->queue_size - 1); | 1194 | i = (i + 1) & (rxq->queue_size - 1); |
@@ -1235,7 +1251,7 @@ restart: | |||
1235 | goto restart; | 1251 | goto restart; |
1236 | } | 1252 | } |
1237 | } | 1253 | } |
1238 | 1254 | out: | |
1239 | /* Backtrack one entry */ | 1255 | /* Backtrack one entry */ |
1240 | rxq->read = i; | 1256 | rxq->read = i; |
1241 | spin_unlock(&rxq->lock); | 1257 | spin_unlock(&rxq->lock); |
@@ -1259,6 +1275,54 @@ restart: | |||
1259 | napi_gro_flush(&rxq->napi, false); | 1275 | napi_gro_flush(&rxq->napi, false); |
1260 | } | 1276 | } |
1261 | 1277 | ||
1278 | static struct iwl_trans_pcie *iwl_pcie_get_trans_pcie(struct msix_entry *entry) | ||
1279 | { | ||
1280 | u8 queue = entry->entry; | ||
1281 | struct msix_entry *entries = entry - queue; | ||
1282 | |||
1283 | return container_of(entries, struct iwl_trans_pcie, msix_entries[0]); | ||
1284 | } | ||
1285 | |||
1286 | static inline void iwl_pcie_clear_irq(struct iwl_trans *trans, | ||
1287 | struct msix_entry *entry) | ||
1288 | { | ||
1289 | /* | ||
1290 | * Before sending the interrupt the HW disables it to prevent | ||
1291 | * a nested interrupt. This is done by writing 1 to the corresponding | ||
1292 | * bit in the mask register. After handling the interrupt, it should be | ||
1293 | * re-enabled by clearing this bit. This register is defined as | ||
1294 | * write 1 clear (W1C) register, meaning that it's being clear | ||
1295 | * by writing 1 to the bit. | ||
1296 | */ | ||
1297 | iwl_write_direct32(trans, CSR_MSIX_AUTOMASK_ST_AD, BIT(entry->entry)); | ||
1298 | } | ||
1299 | |||
1300 | /* | ||
1301 | * iwl_pcie_rx_msix_handle - Main entry function for receiving responses from fw | ||
1302 | * This interrupt handler should be used with RSS queue only. | ||
1303 | */ | ||
1304 | irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id) | ||
1305 | { | ||
1306 | struct msix_entry *entry = dev_id; | ||
1307 | struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry); | ||
1308 | struct iwl_trans *trans = trans_pcie->trans; | ||
1309 | |||
1310 | if (WARN_ON(entry->entry >= trans->num_rx_queues)) | ||
1311 | return IRQ_NONE; | ||
1312 | |||
1313 | lock_map_acquire(&trans->sync_cmd_lockdep_map); | ||
1314 | |||
1315 | local_bh_disable(); | ||
1316 | iwl_pcie_rx_handle(trans, entry->entry); | ||
1317 | local_bh_enable(); | ||
1318 | |||
1319 | iwl_pcie_clear_irq(trans, entry); | ||
1320 | |||
1321 | lock_map_release(&trans->sync_cmd_lockdep_map); | ||
1322 | |||
1323 | return IRQ_HANDLED; | ||
1324 | } | ||
1325 | |||
1262 | /* | 1326 | /* |
1263 | * iwl_pcie_irq_handle_error - called for HW or SW error interrupt from card | 1327 | * iwl_pcie_irq_handle_error - called for HW or SW error interrupt from card |
1264 | */ | 1328 | */ |
@@ -1589,7 +1653,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
1589 | isr_stats->rx++; | 1653 | isr_stats->rx++; |
1590 | 1654 | ||
1591 | local_bh_disable(); | 1655 | local_bh_disable(); |
1592 | iwl_pcie_rx_handle(trans); | 1656 | iwl_pcie_rx_handle(trans, 0); |
1593 | local_bh_enable(); | 1657 | local_bh_enable(); |
1594 | } | 1658 | } |
1595 | 1659 | ||
@@ -1732,3 +1796,129 @@ irqreturn_t iwl_pcie_isr(int irq, void *data) | |||
1732 | 1796 | ||
1733 | return IRQ_WAKE_THREAD; | 1797 | return IRQ_WAKE_THREAD; |
1734 | } | 1798 | } |
1799 | |||
1800 | irqreturn_t iwl_pcie_msix_isr(int irq, void *data) | ||
1801 | { | ||
1802 | return IRQ_WAKE_THREAD; | ||
1803 | } | ||
1804 | |||
1805 | irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) | ||
1806 | { | ||
1807 | struct msix_entry *entry = dev_id; | ||
1808 | struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry); | ||
1809 | struct iwl_trans *trans = trans_pcie->trans; | ||
1810 | struct isr_statistics *isr_stats = isr_stats = &trans_pcie->isr_stats; | ||
1811 | u32 inta_fh, inta_hw; | ||
1812 | |||
1813 | lock_map_acquire(&trans->sync_cmd_lockdep_map); | ||
1814 | |||
1815 | spin_lock(&trans_pcie->irq_lock); | ||
1816 | inta_fh = iwl_read_direct32(trans, CSR_MSIX_FH_INT_CAUSES_AD); | ||
1817 | inta_hw = iwl_read_direct32(trans, CSR_MSIX_HW_INT_CAUSES_AD); | ||
1818 | /* | ||
1819 | * Clear causes registers to avoid being handling the same cause. | ||
1820 | */ | ||
1821 | iwl_write_direct32(trans, CSR_MSIX_FH_INT_CAUSES_AD, inta_fh); | ||
1822 | iwl_write_direct32(trans, CSR_MSIX_HW_INT_CAUSES_AD, inta_hw); | ||
1823 | spin_unlock(&trans_pcie->irq_lock); | ||
1824 | |||
1825 | if (unlikely(!(inta_fh | inta_hw))) { | ||
1826 | IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); | ||
1827 | lock_map_release(&trans->sync_cmd_lockdep_map); | ||
1828 | return IRQ_NONE; | ||
1829 | } | ||
1830 | |||
1831 | if (iwl_have_debug_level(IWL_DL_ISR)) | ||
1832 | IWL_DEBUG_ISR(trans, "ISR inta_fh 0x%08x, enabled 0x%08x\n", | ||
1833 | inta_fh, | ||
1834 | iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD)); | ||
1835 | |||
1836 | /* This "Tx" DMA channel is used only for loading uCode */ | ||
1837 | if (inta_fh & MSIX_FH_INT_CAUSES_D2S_CH0_NUM) { | ||
1838 | IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); | ||
1839 | isr_stats->tx++; | ||
1840 | /* | ||
1841 | * Wake up uCode load routine, | ||
1842 | * now that load is complete | ||
1843 | */ | ||
1844 | trans_pcie->ucode_write_complete = true; | ||
1845 | wake_up(&trans_pcie->ucode_write_waitq); | ||
1846 | } | ||
1847 | |||
1848 | /* Error detected by uCode */ | ||
1849 | if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) || | ||
1850 | (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) { | ||
1851 | IWL_ERR(trans, | ||
1852 | "Microcode SW error detected. Restarting 0x%X.\n", | ||
1853 | inta_fh); | ||
1854 | isr_stats->sw++; | ||
1855 | iwl_pcie_irq_handle_error(trans); | ||
1856 | } | ||
1857 | |||
1858 | /* After checking FH register check HW register */ | ||
1859 | if (iwl_have_debug_level(IWL_DL_ISR)) | ||
1860 | IWL_DEBUG_ISR(trans, | ||
1861 | "ISR inta_hw 0x%08x, enabled 0x%08x\n", | ||
1862 | inta_hw, | ||
1863 | iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD)); | ||
1864 | |||
1865 | /* Alive notification via Rx interrupt will do the real work */ | ||
1866 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_ALIVE) { | ||
1867 | IWL_DEBUG_ISR(trans, "Alive interrupt\n"); | ||
1868 | isr_stats->alive++; | ||
1869 | } | ||
1870 | |||
1871 | /* uCode wakes up after power-down sleep */ | ||
1872 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) { | ||
1873 | IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); | ||
1874 | iwl_pcie_rxq_check_wrptr(trans); | ||
1875 | iwl_pcie_txq_check_wrptrs(trans); | ||
1876 | |||
1877 | isr_stats->wakeup++; | ||
1878 | } | ||
1879 | |||
1880 | /* Chip got too hot and stopped itself */ | ||
1881 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_CT_KILL) { | ||
1882 | IWL_ERR(trans, "Microcode CT kill error detected.\n"); | ||
1883 | isr_stats->ctkill++; | ||
1884 | } | ||
1885 | |||
1886 | /* HW RF KILL switch toggled */ | ||
1887 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_RF_KILL) { | ||
1888 | bool hw_rfkill; | ||
1889 | |||
1890 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
1891 | IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", | ||
1892 | hw_rfkill ? "disable radio" : "enable radio"); | ||
1893 | |||
1894 | isr_stats->rfkill++; | ||
1895 | |||
1896 | mutex_lock(&trans_pcie->mutex); | ||
1897 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | ||
1898 | mutex_unlock(&trans_pcie->mutex); | ||
1899 | if (hw_rfkill) { | ||
1900 | set_bit(STATUS_RFKILL, &trans->status); | ||
1901 | if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE, | ||
1902 | &trans->status)) | ||
1903 | IWL_DEBUG_RF_KILL(trans, | ||
1904 | "Rfkill while SYNC HCMD in flight\n"); | ||
1905 | wake_up(&trans_pcie->wait_command_queue); | ||
1906 | } else { | ||
1907 | clear_bit(STATUS_RFKILL, &trans->status); | ||
1908 | } | ||
1909 | } | ||
1910 | |||
1911 | if (inta_hw & MSIX_HW_INT_CAUSES_REG_HW_ERR) { | ||
1912 | IWL_ERR(trans, | ||
1913 | "Hardware error detected. Restarting.\n"); | ||
1914 | |||
1915 | isr_stats->hw++; | ||
1916 | iwl_pcie_irq_handle_error(trans); | ||
1917 | } | ||
1918 | |||
1919 | iwl_pcie_clear_irq(trans, entry); | ||
1920 | |||
1921 | lock_map_release(&trans->sync_cmd_lockdep_map); | ||
1922 | |||
1923 | return IRQ_HANDLED; | ||
1924 | } | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 58591ca051fd..e67957d6ac79 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c | |||
@@ -616,38 +616,38 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, u32 dst_addr, | |||
616 | dma_addr_t phy_addr, u32 byte_cnt) | 616 | dma_addr_t phy_addr, u32 byte_cnt) |
617 | { | 617 | { |
618 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 618 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
619 | unsigned long flags; | ||
619 | int ret; | 620 | int ret; |
620 | 621 | ||
621 | trans_pcie->ucode_write_complete = false; | 622 | trans_pcie->ucode_write_complete = false; |
622 | 623 | ||
623 | iwl_write_direct32(trans, | 624 | if (!iwl_trans_grab_nic_access(trans, &flags)) |
624 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | 625 | return -EIO; |
625 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | 626 | |
627 | iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
628 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
626 | 629 | ||
627 | iwl_write_direct32(trans, | 630 | iwl_write32(trans, FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), |
628 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), | 631 | dst_addr); |
629 | dst_addr); | ||
630 | 632 | ||
631 | iwl_write_direct32(trans, | 633 | iwl_write32(trans, FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), |
632 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | 634 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); |
633 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
634 | 635 | ||
635 | iwl_write_direct32(trans, | 636 | iwl_write32(trans, FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), |
636 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | 637 | (iwl_get_dma_hi_addr(phy_addr) |
637 | (iwl_get_dma_hi_addr(phy_addr) | 638 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); |
638 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
639 | 639 | ||
640 | iwl_write_direct32(trans, | 640 | iwl_write32(trans, FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), |
641 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | 641 | BIT(FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM) | |
642 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | 642 | BIT(FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX) | |
643 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | 643 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); |
644 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
645 | 644 | ||
646 | iwl_write_direct32(trans, | 645 | iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), |
647 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | 646 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | |
648 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | 647 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | |
649 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | 648 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); |
650 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | 649 | |
650 | iwl_trans_release_nic_access(trans, &flags); | ||
651 | 651 | ||
652 | ret = wait_event_timeout(trans_pcie->ucode_write_waitq, | 652 | ret = wait_event_timeout(trans_pcie->ucode_write_waitq, |
653 | trans_pcie->ucode_write_complete, 5 * HZ); | 653 | trans_pcie->ucode_write_complete, 5 * HZ); |
@@ -1123,6 +1123,20 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | |||
1123 | iwl_pcie_prepare_card_hw(trans); | 1123 | iwl_pcie_prepare_card_hw(trans); |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | static void iwl_pcie_synchronize_irqs(struct iwl_trans *trans) | ||
1127 | { | ||
1128 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1129 | |||
1130 | if (trans_pcie->msix_enabled) { | ||
1131 | int i; | ||
1132 | |||
1133 | for (i = 0; i < trans_pcie->allocated_vector; i++) | ||
1134 | synchronize_irq(trans_pcie->msix_entries[i].vector); | ||
1135 | } else { | ||
1136 | synchronize_irq(trans_pcie->pci_dev->irq); | ||
1137 | } | ||
1138 | } | ||
1139 | |||
1126 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | 1140 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, |
1127 | const struct fw_img *fw, bool run_in_rfkill) | 1141 | const struct fw_img *fw, bool run_in_rfkill) |
1128 | { | 1142 | { |
@@ -1149,7 +1163,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
1149 | iwl_disable_interrupts(trans); | 1163 | iwl_disable_interrupts(trans); |
1150 | 1164 | ||
1151 | /* Make sure it finished running */ | 1165 | /* Make sure it finished running */ |
1152 | synchronize_irq(trans_pcie->pci_dev->irq); | 1166 | iwl_pcie_synchronize_irqs(trans); |
1153 | 1167 | ||
1154 | mutex_lock(&trans_pcie->mutex); | 1168 | mutex_lock(&trans_pcie->mutex); |
1155 | 1169 | ||
@@ -1252,8 +1266,6 @@ void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state) | |||
1252 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, | 1266 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, |
1253 | bool reset) | 1267 | bool reset) |
1254 | { | 1268 | { |
1255 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1256 | |||
1257 | if (!reset) { | 1269 | if (!reset) { |
1258 | /* Enable persistence mode to avoid reset */ | 1270 | /* Enable persistence mode to avoid reset */ |
1259 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | 1271 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, |
@@ -1271,7 +1283,7 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, | |||
1271 | 1283 | ||
1272 | iwl_pcie_disable_ict(trans); | 1284 | iwl_pcie_disable_ict(trans); |
1273 | 1285 | ||
1274 | synchronize_irq(trans_pcie->pci_dev->irq); | 1286 | iwl_pcie_synchronize_irqs(trans); |
1275 | 1287 | ||
1276 | iwl_clear_bit(trans, CSR_GP_CNTRL, | 1288 | iwl_clear_bit(trans, CSR_GP_CNTRL, |
1277 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 1289 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
@@ -1350,6 +1362,153 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
1350 | return 0; | 1362 | return 0; |
1351 | } | 1363 | } |
1352 | 1364 | ||
1365 | struct iwl_causes_list { | ||
1366 | u32 cause_num; | ||
1367 | u32 mask_reg; | ||
1368 | u8 addr; | ||
1369 | }; | ||
1370 | |||
1371 | static struct iwl_causes_list causes_list[] = { | ||
1372 | {MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0}, | ||
1373 | {MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1}, | ||
1374 | {MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3}, | ||
1375 | {MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5}, | ||
1376 | {MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10}, | ||
1377 | {MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11}, | ||
1378 | {MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16}, | ||
1379 | {MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17}, | ||
1380 | {MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18}, | ||
1381 | {MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29}, | ||
1382 | {MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A}, | ||
1383 | {MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B}, | ||
1384 | {MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D}, | ||
1385 | {MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E}, | ||
1386 | }; | ||
1387 | |||
1388 | static void iwl_pcie_init_msix(struct iwl_trans_pcie *trans_pcie) | ||
1389 | { | ||
1390 | u32 val, max_rx_vector, i; | ||
1391 | struct iwl_trans *trans = trans_pcie->trans; | ||
1392 | |||
1393 | max_rx_vector = trans_pcie->allocated_vector - 1; | ||
1394 | |||
1395 | if (!trans_pcie->msix_enabled) | ||
1396 | return; | ||
1397 | |||
1398 | iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); | ||
1399 | |||
1400 | /* | ||
1401 | * Each cause from the list above and the RX causes is represented as | ||
1402 | * a byte in the IVAR table. We access the first (N - 1) bytes and map | ||
1403 | * them to the (N - 1) vectors so these vectors will be used as rx | ||
1404 | * vectors. Then access all non rx causes and map them to the | ||
1405 | * default queue (N'th queue). | ||
1406 | */ | ||
1407 | for (i = 0; i < max_rx_vector; i++) { | ||
1408 | iwl_write8(trans, CSR_MSIX_RX_IVAR(i), MSIX_FH_INT_CAUSES_Q(i)); | ||
1409 | iwl_clear_bit(trans, CSR_MSIX_FH_INT_MASK_AD, | ||
1410 | BIT(MSIX_FH_INT_CAUSES_Q(i))); | ||
1411 | } | ||
1412 | |||
1413 | for (i = 0; i < ARRAY_SIZE(causes_list); i++) { | ||
1414 | val = trans_pcie->default_irq_num | | ||
1415 | MSIX_NON_AUTO_CLEAR_CAUSE; | ||
1416 | iwl_write8(trans, CSR_MSIX_IVAR(causes_list[i].addr), val); | ||
1417 | iwl_clear_bit(trans, causes_list[i].mask_reg, | ||
1418 | causes_list[i].cause_num); | ||
1419 | } | ||
1420 | trans_pcie->fh_init_mask = | ||
1421 | ~iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD); | ||
1422 | trans_pcie->fh_mask = trans_pcie->fh_init_mask; | ||
1423 | trans_pcie->hw_init_mask = | ||
1424 | ~iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD); | ||
1425 | trans_pcie->hw_mask = trans_pcie->hw_init_mask; | ||
1426 | } | ||
1427 | |||
1428 | static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev, | ||
1429 | struct iwl_trans *trans) | ||
1430 | { | ||
1431 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1432 | u16 pci_cmd; | ||
1433 | int max_vector; | ||
1434 | int ret, i; | ||
1435 | |||
1436 | if (trans->cfg->mq_rx_supported) { | ||
1437 | max_vector = min_t(u32, (num_possible_cpus() + 1), | ||
1438 | IWL_MAX_RX_HW_QUEUES); | ||
1439 | for (i = 0; i < max_vector; i++) | ||
1440 | trans_pcie->msix_entries[i].entry = i; | ||
1441 | |||
1442 | ret = pci_enable_msix_range(pdev, trans_pcie->msix_entries, | ||
1443 | MSIX_MIN_INTERRUPT_VECTORS, | ||
1444 | max_vector); | ||
1445 | if (ret > 1) { | ||
1446 | IWL_DEBUG_INFO(trans, | ||
1447 | "Enable MSI-X allocate %d interrupt vector\n", | ||
1448 | ret); | ||
1449 | trans_pcie->allocated_vector = ret; | ||
1450 | trans_pcie->default_irq_num = | ||
1451 | trans_pcie->allocated_vector - 1; | ||
1452 | trans_pcie->trans->num_rx_queues = | ||
1453 | trans_pcie->allocated_vector - 1; | ||
1454 | trans_pcie->msix_enabled = true; | ||
1455 | |||
1456 | return; | ||
1457 | } | ||
1458 | IWL_DEBUG_INFO(trans, | ||
1459 | "ret = %d %s move to msi mode\n", ret, | ||
1460 | (ret == 1) ? | ||
1461 | "can't allocate more than 1 interrupt vector" : | ||
1462 | "failed to enable msi-x mode"); | ||
1463 | pci_disable_msix(pdev); | ||
1464 | } | ||
1465 | |||
1466 | ret = pci_enable_msi(pdev); | ||
1467 | if (ret) { | ||
1468 | dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", ret); | ||
1469 | /* enable rfkill interrupt: hw bug w/a */ | ||
1470 | pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); | ||
1471 | if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { | ||
1472 | pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; | ||
1473 | pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); | ||
1474 | } | ||
1475 | } | ||
1476 | } | ||
1477 | |||
1478 | static int iwl_pcie_init_msix_handler(struct pci_dev *pdev, | ||
1479 | struct iwl_trans_pcie *trans_pcie) | ||
1480 | { | ||
1481 | int i, last_vector; | ||
1482 | |||
1483 | last_vector = trans_pcie->trans->num_rx_queues; | ||
1484 | |||
1485 | for (i = 0; i < trans_pcie->allocated_vector; i++) { | ||
1486 | int ret; | ||
1487 | |||
1488 | ret = request_threaded_irq(trans_pcie->msix_entries[i].vector, | ||
1489 | iwl_pcie_msix_isr, | ||
1490 | (i == last_vector) ? | ||
1491 | iwl_pcie_irq_msix_handler : | ||
1492 | iwl_pcie_irq_rx_msix_handler, | ||
1493 | IRQF_SHARED, | ||
1494 | DRV_NAME, | ||
1495 | &trans_pcie->msix_entries[i]); | ||
1496 | if (ret) { | ||
1497 | int j; | ||
1498 | |||
1499 | IWL_ERR(trans_pcie->trans, | ||
1500 | "Error allocating IRQ %d\n", i); | ||
1501 | for (j = 0; j < i; j++) | ||
1502 | free_irq(trans_pcie->msix_entries[i].vector, | ||
1503 | &trans_pcie->msix_entries[i]); | ||
1504 | pci_disable_msix(pdev); | ||
1505 | return ret; | ||
1506 | } | ||
1507 | } | ||
1508 | |||
1509 | return 0; | ||
1510 | } | ||
1511 | |||
1353 | static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) | 1512 | static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) |
1354 | { | 1513 | { |
1355 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1514 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
@@ -1371,6 +1530,7 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) | |||
1371 | 1530 | ||
1372 | iwl_pcie_apm_init(trans); | 1531 | iwl_pcie_apm_init(trans); |
1373 | 1532 | ||
1533 | iwl_pcie_init_msix(trans_pcie); | ||
1374 | /* From now on, the op_mode will be kept updated about RF kill state */ | 1534 | /* From now on, the op_mode will be kept updated about RF kill state */ |
1375 | iwl_enable_rfkill_int(trans); | 1535 | iwl_enable_rfkill_int(trans); |
1376 | 1536 | ||
@@ -1425,7 +1585,7 @@ static void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans) | |||
1425 | 1585 | ||
1426 | mutex_unlock(&trans_pcie->mutex); | 1586 | mutex_unlock(&trans_pcie->mutex); |
1427 | 1587 | ||
1428 | synchronize_irq(trans_pcie->pci_dev->irq); | 1588 | iwl_pcie_synchronize_irqs(trans); |
1429 | } | 1589 | } |
1430 | 1590 | ||
1431 | static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) | 1591 | static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) |
@@ -1506,15 +1666,25 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1506 | /* TODO: check if this is really needed */ | 1666 | /* TODO: check if this is really needed */ |
1507 | pm_runtime_disable(trans->dev); | 1667 | pm_runtime_disable(trans->dev); |
1508 | 1668 | ||
1509 | synchronize_irq(trans_pcie->pci_dev->irq); | 1669 | iwl_pcie_synchronize_irqs(trans); |
1510 | 1670 | ||
1511 | iwl_pcie_tx_free(trans); | 1671 | iwl_pcie_tx_free(trans); |
1512 | iwl_pcie_rx_free(trans); | 1672 | iwl_pcie_rx_free(trans); |
1513 | 1673 | ||
1514 | free_irq(trans_pcie->pci_dev->irq, trans); | 1674 | if (trans_pcie->msix_enabled) { |
1515 | iwl_pcie_free_ict(trans); | 1675 | for (i = 0; i < trans_pcie->allocated_vector; i++) |
1676 | free_irq(trans_pcie->msix_entries[i].vector, | ||
1677 | &trans_pcie->msix_entries[i]); | ||
1678 | |||
1679 | pci_disable_msix(trans_pcie->pci_dev); | ||
1680 | trans_pcie->msix_enabled = false; | ||
1681 | } else { | ||
1682 | free_irq(trans_pcie->pci_dev->irq, trans); | ||
1516 | 1683 | ||
1517 | pci_disable_msi(trans_pcie->pci_dev); | 1684 | iwl_pcie_free_ict(trans); |
1685 | |||
1686 | pci_disable_msi(trans_pcie->pci_dev); | ||
1687 | } | ||
1518 | iounmap(trans_pcie->hw_base); | 1688 | iounmap(trans_pcie->hw_base); |
1519 | pci_release_regions(trans_pcie->pci_dev); | 1689 | pci_release_regions(trans_pcie->pci_dev); |
1520 | pci_disable_device(trans_pcie->pci_dev); | 1690 | pci_disable_device(trans_pcie->pci_dev); |
@@ -2069,7 +2239,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
2069 | } else { | 2239 | } else { |
2070 | pos += scnprintf(buf + pos, bufsz - pos, | 2240 | pos += scnprintf(buf + pos, bufsz - pos, |
2071 | "\tclosed_rb_num: Not Allocated\n"); | 2241 | "\tclosed_rb_num: Not Allocated\n"); |
2072 | } | 2242 | } |
2073 | } | 2243 | } |
2074 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 2244 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2075 | kfree(buf); | 2245 | kfree(buf); |
@@ -2615,7 +2785,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2615 | { | 2785 | { |
2616 | struct iwl_trans_pcie *trans_pcie; | 2786 | struct iwl_trans_pcie *trans_pcie; |
2617 | struct iwl_trans *trans; | 2787 | struct iwl_trans *trans; |
2618 | u16 pci_cmd; | ||
2619 | int ret, addr_size; | 2788 | int ret, addr_size; |
2620 | 2789 | ||
2621 | trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), | 2790 | trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), |
@@ -2698,17 +2867,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2698 | trans_pcie->pci_dev = pdev; | 2867 | trans_pcie->pci_dev = pdev; |
2699 | iwl_disable_interrupts(trans); | 2868 | iwl_disable_interrupts(trans); |
2700 | 2869 | ||
2701 | ret = pci_enable_msi(pdev); | ||
2702 | if (ret) { | ||
2703 | dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", ret); | ||
2704 | /* enable rfkill interrupt: hw bug w/a */ | ||
2705 | pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); | ||
2706 | if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { | ||
2707 | pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; | ||
2708 | pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); | ||
2709 | } | ||
2710 | } | ||
2711 | |||
2712 | trans->hw_rev = iwl_read32(trans, CSR_HW_REV); | 2870 | trans->hw_rev = iwl_read32(trans, CSR_HW_REV); |
2713 | /* | 2871 | /* |
2714 | * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have | 2872 | * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have |
@@ -2760,6 +2918,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2760 | } | 2918 | } |
2761 | } | 2919 | } |
2762 | 2920 | ||
2921 | iwl_pcie_set_interrupt_capa(pdev, trans); | ||
2763 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; | 2922 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; |
2764 | snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), | 2923 | snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), |
2765 | "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); | 2924 | "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); |
@@ -2769,19 +2928,23 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2769 | 2928 | ||
2770 | init_waitqueue_head(&trans_pcie->d0i3_waitq); | 2929 | init_waitqueue_head(&trans_pcie->d0i3_waitq); |
2771 | 2930 | ||
2772 | ret = iwl_pcie_alloc_ict(trans); | 2931 | if (trans_pcie->msix_enabled) { |
2773 | if (ret) | 2932 | if (iwl_pcie_init_msix_handler(pdev, trans_pcie)) |
2774 | goto out_pci_disable_msi; | 2933 | goto out_pci_release_regions; |
2775 | 2934 | } else { | |
2776 | ret = request_threaded_irq(pdev->irq, iwl_pcie_isr, | 2935 | ret = iwl_pcie_alloc_ict(trans); |
2777 | iwl_pcie_irq_handler, | 2936 | if (ret) |
2778 | IRQF_SHARED, DRV_NAME, trans); | 2937 | goto out_pci_disable_msi; |
2779 | if (ret) { | ||
2780 | IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); | ||
2781 | goto out_free_ict; | ||
2782 | } | ||
2783 | 2938 | ||
2784 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | 2939 | ret = request_threaded_irq(pdev->irq, iwl_pcie_isr, |
2940 | iwl_pcie_irq_handler, | ||
2941 | IRQF_SHARED, DRV_NAME, trans); | ||
2942 | if (ret) { | ||
2943 | IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); | ||
2944 | goto out_free_ict; | ||
2945 | } | ||
2946 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | ||
2947 | } | ||
2785 | 2948 | ||
2786 | #ifdef CONFIG_IWLWIFI_PCIE_RTPM | 2949 | #ifdef CONFIG_IWLWIFI_PCIE_RTPM |
2787 | trans->runtime_pm_mode = IWL_PLAT_PM_MODE_D0I3; | 2950 | trans->runtime_pm_mode = IWL_PLAT_PM_MODE_D0I3; |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 837a7d536874..16ad820ca824 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c | |||
@@ -1062,10 +1062,10 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
1062 | 1062 | ||
1063 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && | 1063 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && |
1064 | test_bit(txq_id, trans_pcie->queue_stopped)) { | 1064 | test_bit(txq_id, trans_pcie->queue_stopped)) { |
1065 | struct sk_buff_head skbs; | 1065 | struct sk_buff_head overflow_skbs; |
1066 | 1066 | ||
1067 | __skb_queue_head_init(&skbs); | 1067 | __skb_queue_head_init(&overflow_skbs); |
1068 | skb_queue_splice_init(&txq->overflow_q, &skbs); | 1068 | skb_queue_splice_init(&txq->overflow_q, &overflow_skbs); |
1069 | 1069 | ||
1070 | /* | 1070 | /* |
1071 | * This is tricky: we are in reclaim path which is non | 1071 | * This is tricky: we are in reclaim path which is non |
@@ -1076,8 +1076,8 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
1076 | */ | 1076 | */ |
1077 | spin_unlock_bh(&txq->lock); | 1077 | spin_unlock_bh(&txq->lock); |
1078 | 1078 | ||
1079 | while (!skb_queue_empty(&skbs)) { | 1079 | while (!skb_queue_empty(&overflow_skbs)) { |
1080 | struct sk_buff *skb = __skb_dequeue(&skbs); | 1080 | struct sk_buff *skb = __skb_dequeue(&overflow_skbs); |
1081 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1081 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1082 | u8 dev_cmd_idx = IWL_TRANS_FIRST_DRIVER_DATA + 1; | 1082 | u8 dev_cmd_idx = IWL_TRANS_FIRST_DRIVER_DATA + 1; |
1083 | struct iwl_device_cmd *dev_cmd = | 1083 | struct iwl_device_cmd *dev_cmd = |
diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c index 71a1b580796f..81c60d0a1bda 100644 --- a/drivers/net/wireless/marvell/mwifiex/11h.c +++ b/drivers/net/wireless/marvell/mwifiex/11h.c | |||
@@ -123,8 +123,7 @@ void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, | |||
123 | void mwifiex_dfs_cac_work_queue(struct work_struct *work) | 123 | void mwifiex_dfs_cac_work_queue(struct work_struct *work) |
124 | { | 124 | { |
125 | struct cfg80211_chan_def chandef; | 125 | struct cfg80211_chan_def chandef; |
126 | struct delayed_work *delayed_work = | 126 | struct delayed_work *delayed_work = to_delayed_work(work); |
127 | container_of(work, struct delayed_work, work); | ||
128 | struct mwifiex_private *priv = | 127 | struct mwifiex_private *priv = |
129 | container_of(delayed_work, struct mwifiex_private, | 128 | container_of(delayed_work, struct mwifiex_private, |
130 | dfs_cac_work); | 129 | dfs_cac_work); |
@@ -289,8 +288,7 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | |||
289 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work) | 288 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work) |
290 | { | 289 | { |
291 | struct mwifiex_uap_bss_param *bss_cfg; | 290 | struct mwifiex_uap_bss_param *bss_cfg; |
292 | struct delayed_work *delayed_work = | 291 | struct delayed_work *delayed_work = to_delayed_work(work); |
293 | container_of(work, struct delayed_work, work); | ||
294 | struct mwifiex_private *priv = | 292 | struct mwifiex_private *priv = |
295 | container_of(delayed_work, struct mwifiex_private, | 293 | container_of(delayed_work, struct mwifiex_private, |
296 | dfs_chan_sw_work); | 294 | dfs_chan_sw_work); |
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index f2dce81ba36e..29b7f6eed240 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c | |||
@@ -676,7 +676,7 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
676 | } | 676 | } |
677 | break; | 677 | break; |
678 | 678 | ||
679 | case MWIFIEX_BSS_ROLE_STA: | 679 | case MWIFIEX_BSS_ROLE_STA: |
680 | if (priv->media_connected) { | 680 | if (priv->media_connected) { |
681 | mwifiex_dbg(adapter, ERROR, | 681 | mwifiex_dbg(adapter, ERROR, |
682 | "cannot change wiphy params when connected"); | 682 | "cannot change wiphy params when connected"); |
diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 14cfa37deb00..a5a48c183d37 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h | |||
@@ -184,6 +184,7 @@ struct mwifiex_ds_tx_ba_stream_tbl { | |||
184 | }; | 184 | }; |
185 | 185 | ||
186 | #define DBG_CMD_NUM 5 | 186 | #define DBG_CMD_NUM 5 |
187 | #define MWIFIEX_DBG_SDIO_MP_NUM 10 | ||
187 | 188 | ||
188 | struct tdls_peer_info { | 189 | struct tdls_peer_info { |
189 | u8 peer_addr[ETH_ALEN]; | 190 | u8 peer_addr[ETH_ALEN]; |
@@ -235,6 +236,11 @@ struct mwifiex_debug_info { | |||
235 | u8 cmd_sent; | 236 | u8 cmd_sent; |
236 | u8 cmd_resp_received; | 237 | u8 cmd_resp_received; |
237 | u8 event_received; | 238 | u8 event_received; |
239 | u32 last_mp_wr_bitmap[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
240 | u32 last_mp_wr_ports[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
241 | u32 last_mp_wr_len[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
242 | u32 last_mp_curr_wr_port[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
243 | u8 last_sdio_mp_index; | ||
238 | }; | 244 | }; |
239 | 245 | ||
240 | #define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 | 246 | #define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 |
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index aea7aee46cf7..aafc4ab4e5ae 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h | |||
@@ -223,6 +223,11 @@ struct mwifiex_dbg { | |||
223 | u16 last_cmd_resp_index; | 223 | u16 last_cmd_resp_index; |
224 | u16 last_event[DBG_CMD_NUM]; | 224 | u16 last_event[DBG_CMD_NUM]; |
225 | u16 last_event_index; | 225 | u16 last_event_index; |
226 | u32 last_mp_wr_bitmap[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
227 | u32 last_mp_wr_ports[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
228 | u32 last_mp_wr_len[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
229 | u32 last_mp_curr_wr_port[MWIFIEX_DBG_SDIO_MP_NUM]; | ||
230 | u8 last_sdio_mp_index; | ||
226 | }; | 231 | }; |
227 | 232 | ||
228 | enum MWIFIEX_HARDWARE_STATUS { | 233 | enum MWIFIEX_HARDWARE_STATUS { |
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index cc072142411a..de364381fe7b 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c | |||
@@ -1401,7 +1401,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1401 | return -1; | 1401 | return -1; |
1402 | } | 1402 | } |
1403 | 1403 | ||
1404 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE)) | 1404 | if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE)) |
1405 | return -1; | 1405 | return -1; |
1406 | 1406 | ||
1407 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); | 1407 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
@@ -2452,7 +2452,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) | |||
2452 | for (i = 0; i < 4; i++) { | 2452 | for (i = 0; i < 4; i++) { |
2453 | mwifiex_read_reg_byte(adapter, reg, &read_reg); | 2453 | mwifiex_read_reg_byte(adapter, reg, &read_reg); |
2454 | memory_size |= (read_reg << (i * 8)); | 2454 | memory_size |= (read_reg << (i * 8)); |
2455 | reg++; | 2455 | reg++; |
2456 | } | 2456 | } |
2457 | } else { | 2457 | } else { |
2458 | memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE; | 2458 | memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE; |
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index abf15dbdfe08..b2c839ae2c3c 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c | |||
@@ -1355,6 +1355,9 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1355 | card->mpa_rx.start_port; | 1355 | card->mpa_rx.start_port; |
1356 | } | 1356 | } |
1357 | 1357 | ||
1358 | if (card->mpa_rx.pkt_cnt == 1) | ||
1359 | mport = adapter->ioport + port; | ||
1360 | |||
1358 | if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, | 1361 | if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, |
1359 | card->mpa_rx.buf_len, mport, 1)) | 1362 | card->mpa_rx.buf_len, mport, 1)) |
1360 | goto error; | 1363 | goto error; |
@@ -1684,6 +1687,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, | |||
1684 | s32 f_precopy_cur_buf = 0; | 1687 | s32 f_precopy_cur_buf = 0; |
1685 | s32 f_postcopy_cur_buf = 0; | 1688 | s32 f_postcopy_cur_buf = 0; |
1686 | u32 mport; | 1689 | u32 mport; |
1690 | int index; | ||
1687 | 1691 | ||
1688 | if (!card->mpa_tx.enabled || | 1692 | if (!card->mpa_tx.enabled || |
1689 | (card->has_control_mask && (port == CTRL_PORT)) || | 1693 | (card->has_control_mask && (port == CTRL_PORT)) || |
@@ -1785,9 +1789,21 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, | |||
1785 | card->mpa_tx.start_port; | 1789 | card->mpa_tx.start_port; |
1786 | } | 1790 | } |
1787 | 1791 | ||
1792 | if (card->mpa_tx.pkt_cnt == 1) | ||
1793 | mport = adapter->ioport + port; | ||
1794 | |||
1788 | ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, | 1795 | ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, |
1789 | card->mpa_tx.buf_len, mport); | 1796 | card->mpa_tx.buf_len, mport); |
1790 | 1797 | ||
1798 | /* Save the last multi port tx aggreagation info to debug log */ | ||
1799 | index = adapter->dbg.last_sdio_mp_index; | ||
1800 | index = (index + 1) % MWIFIEX_DBG_SDIO_MP_NUM; | ||
1801 | adapter->dbg.last_sdio_mp_index = index; | ||
1802 | adapter->dbg.last_mp_wr_ports[index] = mport; | ||
1803 | adapter->dbg.last_mp_wr_bitmap[index] = card->mp_wr_bitmap; | ||
1804 | adapter->dbg.last_mp_wr_len[index] = card->mpa_tx.buf_len; | ||
1805 | adapter->dbg.last_mp_curr_wr_port[index] = card->curr_wr_port; | ||
1806 | |||
1791 | MP_TX_AGGR_BUF_RESET(card); | 1807 | MP_TX_AGGR_BUF_RESET(card); |
1792 | } | 1808 | } |
1793 | 1809 | ||
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 5cbee58f8781..d5c56eb9e985 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | |||
@@ -314,6 +314,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
314 | mwifiex_dbg(adapter, ERROR, | 314 | mwifiex_dbg(adapter, ERROR, |
315 | "Attempt to reconnect on csa closed chan(%d)\n", | 315 | "Attempt to reconnect on csa closed chan(%d)\n", |
316 | bss_desc->channel); | 316 | bss_desc->channel); |
317 | ret = -1; | ||
317 | goto done; | 318 | goto done; |
318 | } | 319 | } |
319 | 320 | ||
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 9275f9c3f869..150649602e98 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c | |||
@@ -680,6 +680,13 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, | |||
680 | __net_timestamp(skb); | 680 | __net_timestamp(skb); |
681 | mwifiex_queue_tx_pkt(priv, skb); | 681 | mwifiex_queue_tx_pkt(priv, skb); |
682 | 682 | ||
683 | /* Delay 10ms to make sure tdls setup confirm/teardown frame | ||
684 | * is received by peer | ||
685 | */ | ||
686 | if (action_code == WLAN_TDLS_SETUP_CONFIRM || | ||
687 | action_code == WLAN_TDLS_TEARDOWN) | ||
688 | msleep_interruptible(10); | ||
689 | |||
683 | return 0; | 690 | return 0; |
684 | } | 691 | } |
685 | 692 | ||
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c index e791166d90c4..16d95b22fe5c 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c | |||
@@ -192,7 +192,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
192 | } | 192 | } |
193 | priv->ap_11n_enabled = 1; | 193 | priv->ap_11n_enabled = 1; |
194 | } else { | 194 | } else { |
195 | memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); | 195 | memset(&bss_cfg->ht_cap, 0, sizeof(struct ieee80211_ht_cap)); |
196 | bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP); | 196 | bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP); |
197 | bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU; | 197 | bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU; |
198 | } | 198 | } |
diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index e43aff932360..05108618430d 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c | |||
@@ -244,9 +244,9 @@ setup_for_next: | |||
244 | if (card->rx_cmd_ep == context->ep) { | 244 | if (card->rx_cmd_ep == context->ep) { |
245 | mwifiex_usb_submit_rx_urb(context, size); | 245 | mwifiex_usb_submit_rx_urb(context, size); |
246 | } else { | 246 | } else { |
247 | if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING){ | 247 | if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING) { |
248 | mwifiex_usb_submit_rx_urb(context, size); | 248 | mwifiex_usb_submit_rx_urb(context, size); |
249 | }else{ | 249 | } else { |
250 | context->skb = NULL; | 250 | context->skb = NULL; |
251 | } | 251 | } |
252 | } | 252 | } |
diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index 0cec8a64473e..6681be0511c7 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c | |||
@@ -78,6 +78,16 @@ static struct mwifiex_debug_data items[] = { | |||
78 | item_addr(last_event), DBG_CMD_NUM}, | 78 | item_addr(last_event), DBG_CMD_NUM}, |
79 | {"last_event_index", item_size(last_event_index), | 79 | {"last_event_index", item_size(last_event_index), |
80 | item_addr(last_event_index), 1}, | 80 | item_addr(last_event_index), 1}, |
81 | {"last_mp_wr_bitmap", item_size(last_mp_wr_bitmap), | ||
82 | item_addr(last_mp_wr_bitmap), MWIFIEX_DBG_SDIO_MP_NUM}, | ||
83 | {"last_mp_wr_ports", item_size(last_mp_wr_ports), | ||
84 | item_addr(last_mp_wr_ports), MWIFIEX_DBG_SDIO_MP_NUM}, | ||
85 | {"last_mp_wr_len", item_size(last_mp_wr_len), | ||
86 | item_addr(last_mp_wr_len), MWIFIEX_DBG_SDIO_MP_NUM}, | ||
87 | {"last_mp_curr_wr_port", item_size(last_mp_curr_wr_port), | ||
88 | item_addr(last_mp_curr_wr_port), MWIFIEX_DBG_SDIO_MP_NUM}, | ||
89 | {"last_sdio_mp_index", item_size(last_sdio_mp_index), | ||
90 | item_addr(last_sdio_mp_index), 1}, | ||
81 | {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), | 91 | {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), |
82 | item_addr(num_cmd_host_to_card_failure), 1}, | 92 | item_addr(num_cmd_host_to_card_failure), 1}, |
83 | {"num_cmd_sleep_cfm_fail", | 93 | {"num_cmd_sleep_cfm_fail", |
@@ -233,6 +243,16 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, | |||
233 | memcpy(info->last_event, adapter->dbg.last_event, | 243 | memcpy(info->last_event, adapter->dbg.last_event, |
234 | sizeof(adapter->dbg.last_event)); | 244 | sizeof(adapter->dbg.last_event)); |
235 | info->last_event_index = adapter->dbg.last_event_index; | 245 | info->last_event_index = adapter->dbg.last_event_index; |
246 | memcpy(info->last_mp_wr_bitmap, adapter->dbg.last_mp_wr_bitmap, | ||
247 | sizeof(adapter->dbg.last_mp_wr_bitmap)); | ||
248 | memcpy(info->last_mp_wr_ports, adapter->dbg.last_mp_wr_ports, | ||
249 | sizeof(adapter->dbg.last_mp_wr_ports)); | ||
250 | memcpy(info->last_mp_curr_wr_port, | ||
251 | adapter->dbg.last_mp_curr_wr_port, | ||
252 | sizeof(adapter->dbg.last_mp_curr_wr_port)); | ||
253 | memcpy(info->last_mp_wr_len, adapter->dbg.last_mp_wr_len, | ||
254 | sizeof(adapter->dbg.last_mp_wr_len)); | ||
255 | info->last_sdio_mp_index = adapter->dbg.last_sdio_mp_index; | ||
236 | info->data_sent = adapter->data_sent; | 256 | info->data_sent = adapter->data_sent; |
237 | info->cmd_sent = adapter->cmd_sent; | 257 | info->cmd_sent = adapter->cmd_sent; |
238 | info->cmd_resp_received = adapter->cmd_resp_received; | 258 | info->cmd_resp_received = adapter->cmd_resp_received; |
diff --git a/drivers/net/wireless/mediatek/mt7601u/mcu.c b/drivers/net/wireless/mediatek/mt7601u/mcu.c index fbb1986eda3c..91c4b3427965 100644 --- a/drivers/net/wireless/mediatek/mt7601u/mcu.c +++ b/drivers/net/wireless/mediatek/mt7601u/mcu.c | |||
@@ -362,7 +362,9 @@ mt7601u_upload_firmware(struct mt7601u_dev *dev, const struct mt76_fw *fw) | |||
362 | int i, ret; | 362 | int i, ret; |
363 | 363 | ||
364 | ivb = kmemdup(fw->ivb, sizeof(fw->ivb), GFP_KERNEL); | 364 | ivb = kmemdup(fw->ivb, sizeof(fw->ivb), GFP_KERNEL); |
365 | if (!ivb || mt7601u_usb_alloc_buf(dev, MCU_FW_URB_SIZE, &dma_buf)) { | 365 | if (!ivb) |
366 | return -ENOMEM; | ||
367 | if (mt7601u_usb_alloc_buf(dev, MCU_FW_URB_SIZE, &dma_buf)) { | ||
366 | ret = -ENOMEM; | 368 | ret = -ENOMEM; |
367 | goto error; | 369 | goto error; |
368 | } | 370 | } |
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c index bf9afbf46c1b..4b0bb6b4f6f1 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c | |||
@@ -1026,6 +1026,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1026 | { USB_DEVICE(0x0411, 0x01a2) }, | 1026 | { USB_DEVICE(0x0411, 0x01a2) }, |
1027 | { USB_DEVICE(0x0411, 0x01ee) }, | 1027 | { USB_DEVICE(0x0411, 0x01ee) }, |
1028 | { USB_DEVICE(0x0411, 0x01a8) }, | 1028 | { USB_DEVICE(0x0411, 0x01a8) }, |
1029 | { USB_DEVICE(0x0411, 0x01fd) }, | ||
1029 | /* Corega */ | 1030 | /* Corega */ |
1030 | { USB_DEVICE(0x07aa, 0x002f) }, | 1031 | { USB_DEVICE(0x07aa, 0x002f) }, |
1031 | { USB_DEVICE(0x07aa, 0x003c) }, | 1032 | { USB_DEVICE(0x07aa, 0x003c) }, |
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index 25ee3cb8e982..72ae530e4a3b 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | |||
@@ -478,7 +478,7 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \ | |||
478 | { \ | 478 | { \ |
479 | struct rt2x00debug_intf *intf = file->private_data; \ | 479 | struct rt2x00debug_intf *intf = file->private_data; \ |
480 | const struct rt2x00debug *debug = intf->debug; \ | 480 | const struct rt2x00debug *debug = intf->debug; \ |
481 | char line[16]; \ | 481 | char line[17]; \ |
482 | size_t size; \ | 482 | size_t size; \ |
483 | unsigned int index = intf->offset_##__name; \ | 483 | unsigned int index = intf->offset_##__name; \ |
484 | __type value; \ | 484 | __type value; \ |
@@ -494,7 +494,8 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \ | |||
494 | \ | 494 | \ |
495 | if (copy_from_user(line, buf, length)) \ | 495 | if (copy_from_user(line, buf, length)) \ |
496 | return -EFAULT; \ | 496 | return -EFAULT; \ |
497 | \ | 497 | line[16] = 0; \ |
498 | \ | ||
498 | size = strlen(line); \ | 499 | size = strlen(line); \ |
499 | value = simple_strtoul(line, NULL, 0); \ | 500 | value = simple_strtoul(line, NULL, 0); \ |
500 | \ | 501 | \ |
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig index dd4d626aecbc..8f053c350227 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig +++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig | |||
@@ -13,7 +13,7 @@ config RTL8XXXU | |||
13 | This driver is under development and has a limited feature | 13 | This driver is under development and has a limited feature |
14 | set. In particular it does not yet support 40MHz channels | 14 | set. In particular it does not yet support 40MHz channels |
15 | and power management. However it should have a smaller | 15 | and power management. However it should have a smaller |
16 | memory footprint than the vendor drivers and benetifs | 16 | memory footprint than the vendor drivers and benefits |
17 | from the in kernel mac80211 stack. | 17 | from the in kernel mac80211 stack. |
18 | 18 | ||
19 | It can coexist with drivers from drivers/staging/rtl8723au, | 19 | It can coexist with drivers from drivers/staging/rtl8723au, |
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 7d820c395375..e654bd33b434 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | |||
@@ -1599,9 +1599,9 @@ rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) | |||
1599 | static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, | 1599 | static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, |
1600 | enum nl80211_iftype linktype) | 1600 | enum nl80211_iftype linktype) |
1601 | { | 1601 | { |
1602 | u16 val8; | 1602 | u8 val8; |
1603 | 1603 | ||
1604 | val8 = rtl8xxxu_read16(priv, REG_MSR); | 1604 | val8 = rtl8xxxu_read8(priv, REG_MSR); |
1605 | val8 &= ~MSR_LINKTYPE_MASK; | 1605 | val8 &= ~MSR_LINKTYPE_MASK; |
1606 | 1606 | ||
1607 | switch (linktype) { | 1607 | switch (linktype) { |
@@ -1704,6 +1704,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) | |||
1704 | priv->has_bluetooth = 1; | 1704 | priv->has_bluetooth = 1; |
1705 | if (val32 & MULTI_GPS_FUNC_EN) | 1705 | if (val32 & MULTI_GPS_FUNC_EN) |
1706 | priv->has_gps = 1; | 1706 | priv->has_gps = 1; |
1707 | priv->is_multi_func = 1; | ||
1707 | } else if (val32 & SYS_CFG_TYPE_ID) { | 1708 | } else if (val32 & SYS_CFG_TYPE_ID) { |
1708 | bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); | 1709 | bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); |
1709 | bonding &= HPON_FSM_BONDING_MASK; | 1710 | bonding &= HPON_FSM_BONDING_MASK; |
@@ -1938,9 +1939,11 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv) | |||
1938 | if (val16 & EEPROM_BOOT) | 1939 | if (val16 & EEPROM_BOOT) |
1939 | priv->boot_eeprom = 1; | 1940 | priv->boot_eeprom = 1; |
1940 | 1941 | ||
1941 | val32 = rtl8xxxu_read32(priv, REG_EFUSE_TEST); | 1942 | if (priv->is_multi_func) { |
1942 | val32 = (val32 & ~EFUSE_SELECT_MASK) | EFUSE_WIFI_SELECT; | 1943 | val32 = rtl8xxxu_read32(priv, REG_EFUSE_TEST); |
1943 | rtl8xxxu_write32(priv, REG_EFUSE_TEST, val32); | 1944 | val32 = (val32 & ~EFUSE_SELECT_MASK) | EFUSE_WIFI_SELECT; |
1945 | rtl8xxxu_write32(priv, REG_EFUSE_TEST, val32); | ||
1946 | } | ||
1944 | 1947 | ||
1945 | dev_dbg(dev, "Booting from %s\n", | 1948 | dev_dbg(dev, "Booting from %s\n", |
1946 | priv->boot_eeprom ? "EEPROM" : "EFUSE"); | 1949 | priv->boot_eeprom ? "EEPROM" : "EFUSE"); |
@@ -2043,6 +2046,24 @@ exit: | |||
2043 | return ret; | 2046 | return ret; |
2044 | } | 2047 | } |
2045 | 2048 | ||
2049 | static void rtl8xxxu_reset_8051(struct rtl8xxxu_priv *priv) | ||
2050 | { | ||
2051 | u8 val8; | ||
2052 | u16 sys_func; | ||
2053 | |||
2054 | val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); | ||
2055 | val8 &= ~BIT(0); | ||
2056 | rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); | ||
2057 | sys_func = rtl8xxxu_read16(priv, REG_SYS_FUNC); | ||
2058 | sys_func &= ~SYS_FUNC_CPU_ENABLE; | ||
2059 | rtl8xxxu_write16(priv, REG_SYS_FUNC, sys_func); | ||
2060 | val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); | ||
2061 | val8 |= BIT(0); | ||
2062 | rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); | ||
2063 | sys_func |= SYS_FUNC_CPU_ENABLE; | ||
2064 | rtl8xxxu_write16(priv, REG_SYS_FUNC, sys_func); | ||
2065 | } | ||
2066 | |||
2046 | static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) | 2067 | static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) |
2047 | { | 2068 | { |
2048 | struct device *dev = &priv->udev->dev; | 2069 | struct device *dev = &priv->udev->dev; |
@@ -2067,6 +2088,12 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) | |||
2067 | val32 &= ~MCU_WINT_INIT_READY; | 2088 | val32 &= ~MCU_WINT_INIT_READY; |
2068 | rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32); | 2089 | rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32); |
2069 | 2090 | ||
2091 | /* | ||
2092 | * Reset the 8051 in order for the firmware to start running, | ||
2093 | * otherwise it won't come up on the 8192eu | ||
2094 | */ | ||
2095 | rtl8xxxu_reset_8051(priv); | ||
2096 | |||
2070 | /* Wait for firmware to become ready */ | 2097 | /* Wait for firmware to become ready */ |
2071 | for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { | 2098 | for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { |
2072 | val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); | 2099 | val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); |
@@ -2100,19 +2127,30 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) | |||
2100 | 2127 | ||
2101 | /* 8051 enable */ | 2128 | /* 8051 enable */ |
2102 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); | 2129 | val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); |
2103 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val16 | SYS_FUNC_CPU_ENABLE); | 2130 | val16 |= SYS_FUNC_CPU_ENABLE; |
2131 | rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); | ||
2132 | |||
2133 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); | ||
2134 | if (val8 & MCU_FW_RAM_SEL) { | ||
2135 | pr_info("do the RAM reset\n"); | ||
2136 | rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); | ||
2137 | rtl8xxxu_reset_8051(priv); | ||
2138 | } | ||
2104 | 2139 | ||
2105 | /* MCU firmware download enable */ | 2140 | /* MCU firmware download enable */ |
2106 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); | 2141 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); |
2107 | rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_ENABLE); | 2142 | val8 |= MCU_FW_DL_ENABLE; |
2143 | rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8); | ||
2108 | 2144 | ||
2109 | /* 8051 reset */ | 2145 | /* 8051 reset */ |
2110 | val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); | 2146 | val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); |
2111 | rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32 & ~BIT(19)); | 2147 | val32 &= ~BIT(19); |
2148 | rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32); | ||
2112 | 2149 | ||
2113 | /* Reset firmware download checksum */ | 2150 | /* Reset firmware download checksum */ |
2114 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); | 2151 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); |
2115 | rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_CSUM_REPORT); | 2152 | val8 |= MCU_FW_DL_CSUM_REPORT; |
2153 | rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8); | ||
2116 | 2154 | ||
2117 | pages = priv->fw_size / RTL_FW_PAGE_SIZE; | 2155 | pages = priv->fw_size / RTL_FW_PAGE_SIZE; |
2118 | remainder = priv->fw_size % RTL_FW_PAGE_SIZE; | 2156 | remainder = priv->fw_size % RTL_FW_PAGE_SIZE; |
@@ -2121,7 +2159,8 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) | |||
2121 | 2159 | ||
2122 | for (i = 0; i < pages; i++) { | 2160 | for (i = 0; i < pages; i++) { |
2123 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; | 2161 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; |
2124 | rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i); | 2162 | val8 |= i; |
2163 | rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8); | ||
2125 | 2164 | ||
2126 | ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, | 2165 | ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, |
2127 | fwptr, RTL_FW_PAGE_SIZE); | 2166 | fwptr, RTL_FW_PAGE_SIZE); |
@@ -2135,7 +2174,8 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) | |||
2135 | 2174 | ||
2136 | if (remainder) { | 2175 | if (remainder) { |
2137 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; | 2176 | val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; |
2138 | rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i); | 2177 | val8 |= i; |
2178 | rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8); | ||
2139 | ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, | 2179 | ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, |
2140 | fwptr, remainder); | 2180 | fwptr, remainder); |
2141 | if (ret != remainder) { | 2181 | if (ret != remainder) { |
@@ -2148,8 +2188,8 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) | |||
2148 | fw_abort: | 2188 | fw_abort: |
2149 | /* MCU firmware download disable */ | 2189 | /* MCU firmware download disable */ |
2150 | val16 = rtl8xxxu_read16(priv, REG_MCU_FW_DL); | 2190 | val16 = rtl8xxxu_read16(priv, REG_MCU_FW_DL); |
2151 | rtl8xxxu_write16(priv, REG_MCU_FW_DL, | 2191 | val16 &= ~MCU_FW_DL_ENABLE; |
2152 | val16 & (~MCU_FW_DL_ENABLE & 0xff)); | 2192 | rtl8xxxu_write16(priv, REG_MCU_FW_DL, val16); |
2153 | 2193 | ||
2154 | return ret; | 2194 | return ret; |
2155 | } | 2195 | } |
@@ -2174,6 +2214,10 @@ static int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, char *fw_name) | |||
2174 | } | 2214 | } |
2175 | 2215 | ||
2176 | priv->fw_data = kmemdup(fw->data, fw->size, GFP_KERNEL); | 2216 | priv->fw_data = kmemdup(fw->data, fw->size, GFP_KERNEL); |
2217 | if (!priv->fw_data) { | ||
2218 | ret = -ENOMEM; | ||
2219 | goto exit; | ||
2220 | } | ||
2177 | priv->fw_size = fw->size - sizeof(struct rtl8xxxu_firmware_header); | 2221 | priv->fw_size = fw->size - sizeof(struct rtl8xxxu_firmware_header); |
2178 | 2222 | ||
2179 | signature = le16_to_cpu(priv->fw_data->signature); | 2223 | signature = le16_to_cpu(priv->fw_data->signature); |
@@ -2492,8 +2536,6 @@ static int rtl8xxxu_init_rf_regs(struct rtl8xxxu_priv *priv, | |||
2492 | continue; | 2536 | continue; |
2493 | } | 2537 | } |
2494 | 2538 | ||
2495 | reg &= 0x3f; | ||
2496 | |||
2497 | ret = rtl8xxxu_write_rfreg(priv, path, reg, val); | 2539 | ret = rtl8xxxu_write_rfreg(priv, path, reg, val); |
2498 | if (ret) { | 2540 | if (ret) { |
2499 | dev_warn(&priv->udev->dev, | 2541 | dev_warn(&priv->udev->dev, |
@@ -4155,7 +4197,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) | |||
4155 | * Configure initial WMAC settings | 4197 | * Configure initial WMAC settings |
4156 | */ | 4198 | */ |
4157 | val32 = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_MCAST | RCR_ACCEPT_BCAST | | 4199 | val32 = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_MCAST | RCR_ACCEPT_BCAST | |
4158 | /* RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON | */ | ||
4159 | RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL | | 4200 | RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL | |
4160 | RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC; | 4201 | RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC; |
4161 | rtl8xxxu_write32(priv, REG_RCR, val32); | 4202 | rtl8xxxu_write32(priv, REG_RCR, val32); |
@@ -4248,17 +4289,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) | |||
4248 | 4289 | ||
4249 | rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0); | 4290 | rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0); |
4250 | 4291 | ||
4251 | /* | 4292 | rtl8723a_phy_iq_calibrate(priv); |
4252 | * Not sure if we should get into this at all | ||
4253 | */ | ||
4254 | if (priv->iqk_initialized) { | ||
4255 | rtl8xxxu_restore_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, | ||
4256 | priv->bb_recovery_backup, | ||
4257 | RTL8XXXU_BB_REGS); | ||
4258 | } else { | ||
4259 | rtl8723a_phy_iq_calibrate(priv); | ||
4260 | priv->iqk_initialized = true; | ||
4261 | } | ||
4262 | 4293 | ||
4263 | /* | 4294 | /* |
4264 | * This should enable thermal meter | 4295 | * This should enable thermal meter |
@@ -4312,14 +4343,17 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) | |||
4312 | val8 = ((30000 + NAV_UPPER_UNIT - 1) / NAV_UPPER_UNIT); | 4343 | val8 = ((30000 + NAV_UPPER_UNIT - 1) / NAV_UPPER_UNIT); |
4313 | rtl8xxxu_write8(priv, REG_NAV_UPPER, val8); | 4344 | rtl8xxxu_write8(priv, REG_NAV_UPPER, val8); |
4314 | 4345 | ||
4315 | /* | 4346 | if (priv->rtlchip == 0x8723a) { |
4316 | * 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, | 4347 | /* |
4317 | * but we need to fin root cause. | 4348 | * 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, |
4318 | */ | 4349 | * but we need to find root cause. |
4319 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); | 4350 | * This is 8723au only. |
4320 | if ((val32 & 0xff000000) != 0x83000000) { | 4351 | */ |
4321 | val32 |= FPGA_RF_MODE_CCK; | 4352 | val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); |
4322 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); | 4353 | if ((val32 & 0xff000000) != 0x83000000) { |
4354 | val32 |= FPGA_RF_MODE_CCK; | ||
4355 | rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); | ||
4356 | } | ||
4323 | } | 4357 | } |
4324 | 4358 | ||
4325 | val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL); | 4359 | val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL); |
@@ -4381,7 +4415,7 @@ static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv, | |||
4381 | } | 4415 | } |
4382 | 4416 | ||
4383 | static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw, | 4417 | static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw, |
4384 | struct ieee80211_vif *vif, const u8* mac) | 4418 | struct ieee80211_vif *vif, const u8 *mac) |
4385 | { | 4419 | { |
4386 | struct rtl8xxxu_priv *priv = hw->priv; | 4420 | struct rtl8xxxu_priv *priv = hw->priv; |
4387 | u8 val8; | 4421 | u8 val8; |
@@ -4488,13 +4522,6 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
4488 | 4522 | ||
4489 | rtl8xxxu_update_rate_mask(priv, ramask, sgi); | 4523 | rtl8xxxu_update_rate_mask(priv, ramask, sgi); |
4490 | 4524 | ||
4491 | val32 = rtl8xxxu_read32(priv, REG_RCR); | ||
4492 | val32 |= RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON; | ||
4493 | rtl8xxxu_write32(priv, REG_RCR, val32); | ||
4494 | |||
4495 | /* Enable RX of data frames */ | ||
4496 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff); | ||
4497 | |||
4498 | rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); | 4525 | rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); |
4499 | 4526 | ||
4500 | rtl8723a_stop_tx_beacon(priv); | 4527 | rtl8723a_stop_tx_beacon(priv); |
@@ -4505,17 +4532,10 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
4505 | 4532 | ||
4506 | h2c.joinbss.data = H2C_JOIN_BSS_CONNECT; | 4533 | h2c.joinbss.data = H2C_JOIN_BSS_CONNECT; |
4507 | } else { | 4534 | } else { |
4508 | val32 = rtl8xxxu_read32(priv, REG_RCR); | ||
4509 | val32 &= ~(RCR_CHECK_BSSID_MATCH | | ||
4510 | RCR_CHECK_BSSID_BEACON); | ||
4511 | rtl8xxxu_write32(priv, REG_RCR, val32); | ||
4512 | |||
4513 | val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); | 4535 | val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); |
4514 | val8 |= BEACON_DISABLE_TSF_UPDATE; | 4536 | val8 |= BEACON_DISABLE_TSF_UPDATE; |
4515 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); | 4537 | rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); |
4516 | 4538 | ||
4517 | /* Disable RX of data frames */ | ||
4518 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); | ||
4519 | h2c.joinbss.data = H2C_JOIN_BSS_DISCONNECT; | 4539 | h2c.joinbss.data = H2C_JOIN_BSS_DISCONNECT; |
4520 | } | 4540 | } |
4521 | h2c.joinbss.cmd = H2C_JOIN_BSS_REPORT; | 4541 | h2c.joinbss.cmd = H2C_JOIN_BSS_REPORT; |
@@ -5012,17 +5032,14 @@ static void rtl8xxxu_rx_complete(struct urb *urb) | |||
5012 | struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; | 5032 | struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; |
5013 | struct rtl8723au_phy_stats *phy_stats; | 5033 | struct rtl8723au_phy_stats *phy_stats; |
5014 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | 5034 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); |
5015 | struct ieee80211_mgmt *mgmt; | ||
5016 | struct device *dev = &priv->udev->dev; | 5035 | struct device *dev = &priv->udev->dev; |
5017 | __le32 *_rx_desc_le = (__le32 *)skb->data; | 5036 | __le32 *_rx_desc_le = (__le32 *)skb->data; |
5018 | u32 *_rx_desc = (u32 *)skb->data; | 5037 | u32 *_rx_desc = (u32 *)skb->data; |
5019 | int cnt, len, drvinfo_sz, desc_shift, i; | 5038 | int drvinfo_sz, desc_shift, i; |
5020 | 5039 | ||
5021 | for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) | 5040 | for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) |
5022 | _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); | 5041 | _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); |
5023 | 5042 | ||
5024 | cnt = rx_desc->frag; | ||
5025 | len = rx_desc->pktlen; | ||
5026 | drvinfo_sz = rx_desc->drvinfo_sz * 8; | 5043 | drvinfo_sz = rx_desc->drvinfo_sz * 8; |
5027 | desc_shift = rx_desc->shift; | 5044 | desc_shift = rx_desc->shift; |
5028 | skb_put(skb, urb->actual_length); | 5045 | skb_put(skb, urb->actual_length); |
@@ -5033,8 +5050,6 @@ static void rtl8xxxu_rx_complete(struct urb *urb) | |||
5033 | 5050 | ||
5034 | skb_pull(skb, drvinfo_sz + desc_shift); | 5051 | skb_pull(skb, drvinfo_sz + desc_shift); |
5035 | 5052 | ||
5036 | mgmt = (struct ieee80211_mgmt *)skb->data; | ||
5037 | |||
5038 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | 5053 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); |
5039 | 5054 | ||
5040 | if (rx_desc->phy_stats) | 5055 | if (rx_desc->phy_stats) |
@@ -5284,11 +5299,56 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, | |||
5284 | unsigned int *total_flags, u64 multicast) | 5299 | unsigned int *total_flags, u64 multicast) |
5285 | { | 5300 | { |
5286 | struct rtl8xxxu_priv *priv = hw->priv; | 5301 | struct rtl8xxxu_priv *priv = hw->priv; |
5302 | u32 rcr = rtl8xxxu_read32(priv, REG_RCR); | ||
5287 | 5303 | ||
5288 | dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n", | 5304 | dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n", |
5289 | __func__, changed_flags, *total_flags); | 5305 | __func__, changed_flags, *total_flags); |
5290 | 5306 | ||
5291 | *total_flags &= (FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC); | 5307 | /* |
5308 | * FIF_ALLMULTI ignored as all multicast frames are accepted (REG_MAR) | ||
5309 | */ | ||
5310 | |||
5311 | if (*total_flags & FIF_FCSFAIL) | ||
5312 | rcr |= RCR_ACCEPT_CRC32; | ||
5313 | else | ||
5314 | rcr &= ~RCR_ACCEPT_CRC32; | ||
5315 | |||
5316 | /* | ||
5317 | * FIF_PLCPFAIL not supported? | ||
5318 | */ | ||
5319 | |||
5320 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
5321 | rcr &= ~RCR_CHECK_BSSID_BEACON; | ||
5322 | else | ||
5323 | rcr |= RCR_CHECK_BSSID_BEACON; | ||
5324 | |||
5325 | if (*total_flags & FIF_CONTROL) | ||
5326 | rcr |= RCR_ACCEPT_CTRL_FRAME; | ||
5327 | else | ||
5328 | rcr &= ~RCR_ACCEPT_CTRL_FRAME; | ||
5329 | |||
5330 | if (*total_flags & FIF_OTHER_BSS) { | ||
5331 | rcr |= RCR_ACCEPT_AP; | ||
5332 | rcr &= ~RCR_CHECK_BSSID_MATCH; | ||
5333 | } else { | ||
5334 | rcr &= ~RCR_ACCEPT_AP; | ||
5335 | rcr |= RCR_CHECK_BSSID_MATCH; | ||
5336 | } | ||
5337 | |||
5338 | if (*total_flags & FIF_PSPOLL) | ||
5339 | rcr |= RCR_ACCEPT_PM; | ||
5340 | else | ||
5341 | rcr &= ~RCR_ACCEPT_PM; | ||
5342 | |||
5343 | /* | ||
5344 | * FIF_PROBE_REQ ignored as probe requests always seem to be accepted | ||
5345 | */ | ||
5346 | |||
5347 | rtl8xxxu_write32(priv, REG_RCR, rcr); | ||
5348 | |||
5349 | *total_flags &= (FIF_ALLMULTI | FIF_FCSFAIL | FIF_BCN_PRBRESP_PROMISC | | ||
5350 | FIF_CONTROL | FIF_OTHER_BSS | FIF_PSPOLL | | ||
5351 | FIF_PROBE_REQ); | ||
5292 | } | 5352 | } |
5293 | 5353 | ||
5294 | static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts) | 5354 | static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts) |
@@ -5473,12 +5533,9 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw) | |||
5473 | } | 5533 | } |
5474 | exit: | 5534 | exit: |
5475 | /* | 5535 | /* |
5476 | * Disable all data frames | 5536 | * Accept all data and mgmt frames |
5477 | */ | ||
5478 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); | ||
5479 | /* | ||
5480 | * Accept all mgmt frames | ||
5481 | */ | 5537 | */ |
5538 | rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff); | ||
5482 | rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0xffff); | 5539 | rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0xffff); |
5483 | 5540 | ||
5484 | rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, 0x6954341e); | 5541 | rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, 0x6954341e); |
@@ -5891,8 +5948,6 @@ static struct usb_device_id dev_table[] = { | |||
5891 | .driver_info = (unsigned long)&rtl8192cu_fops}, | 5948 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
5892 | {USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff), | 5949 | {USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff), |
5893 | .driver_info = (unsigned long)&rtl8192cu_fops}, | 5950 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
5894 | {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff), | ||
5895 | .driver_info = (unsigned long)&rtl8192cu_fops}, /* Netcore 8188RU */ | ||
5896 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff), | 5951 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff), |
5897 | .driver_info = (unsigned long)&rtl8192cu_fops}, | 5952 | .driver_info = (unsigned long)&rtl8192cu_fops}, |
5898 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff9, 0xff, 0xff, 0xff), | 5953 | {USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff9, 0xff, 0xff, 0xff), |
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index f2a1bac6c8ec..bbd0f6b76b82 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | |||
@@ -597,6 +597,7 @@ struct rtl8xxxu_priv { | |||
597 | struct rtl8723au_idx ht20_max_power_offset[3]; | 597 | struct rtl8723au_idx ht20_max_power_offset[3]; |
598 | u32 chip_cut:4; | 598 | u32 chip_cut:4; |
599 | u32 rom_rev:4; | 599 | u32 rom_rev:4; |
600 | u32 is_multi_func:1; | ||
600 | u32 has_wifi:1; | 601 | u32 has_wifi:1; |
601 | u32 has_bluetooth:1; | 602 | u32 has_bluetooth:1; |
602 | u32 enable_bluetooth:1; | 603 | u32 enable_bluetooth:1; |
@@ -652,7 +653,6 @@ struct rtl8xxxu_priv { | |||
652 | u32 bb_recovery_backup[RTL8XXXU_BB_REGS]; | 653 | u32 bb_recovery_backup[RTL8XXXU_BB_REGS]; |
653 | u32 rtlchip; | 654 | u32 rtlchip; |
654 | u8 pi_enabled:1; | 655 | u8 pi_enabled:1; |
655 | u8 iqk_initialized:1; | ||
656 | u8 int_buf[USB_INTR_CONTENT_LENGTH]; | 656 | u8 int_buf[USB_INTR_CONTENT_LENGTH]; |
657 | }; | 657 | }; |
658 | 658 | ||
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 23208f79b97c..8f6c9c6c7c09 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | |||
@@ -45,6 +45,7 @@ | |||
45 | #define APS_FSMCO_ENABLE_POWERDOWN BIT(4) | 45 | #define APS_FSMCO_ENABLE_POWERDOWN BIT(4) |
46 | #define APS_FSMCO_MAC_ENABLE BIT(8) | 46 | #define APS_FSMCO_MAC_ENABLE BIT(8) |
47 | #define APS_FSMCO_MAC_OFF BIT(9) | 47 | #define APS_FSMCO_MAC_OFF BIT(9) |
48 | #define APS_FSMCO_SW_LPS BIT(10) | ||
48 | #define APS_FSMCO_HW_SUSPEND BIT(11) | 49 | #define APS_FSMCO_HW_SUSPEND BIT(11) |
49 | #define APS_FSMCO_PCIE BIT(12) | 50 | #define APS_FSMCO_PCIE BIT(12) |
50 | #define APS_FSMCO_HW_POWERDOWN BIT(15) | 51 | #define APS_FSMCO_HW_POWERDOWN BIT(15) |
@@ -213,6 +214,7 @@ | |||
213 | #define SYS_CFG_PCIRSTB BIT(4) | 214 | #define SYS_CFG_PCIRSTB BIT(4) |
214 | #define SYS_CFG_V15_VLD BIT(5) | 215 | #define SYS_CFG_V15_VLD BIT(5) |
215 | #define SYS_CFG_TRP_B15V_EN BIT(7) | 216 | #define SYS_CFG_TRP_B15V_EN BIT(7) |
217 | #define SYS_CFG_SW_OFFLOAD_EN BIT(7) /* For chips with IOL support */ | ||
216 | #define SYS_CFG_SIC_IDLE BIT(8) | 218 | #define SYS_CFG_SIC_IDLE BIT(8) |
217 | #define SYS_CFG_BD_MAC2 BIT(9) | 219 | #define SYS_CFG_BD_MAC2 BIT(9) |
218 | #define SYS_CFG_BD_MAC1 BIT(10) | 220 | #define SYS_CFG_BD_MAC1 BIT(10) |
@@ -340,6 +342,11 @@ | |||
340 | #define REG_BB_ACCEESS_CTRL 0x01e8 | 342 | #define REG_BB_ACCEESS_CTRL 0x01e8 |
341 | #define REG_BB_ACCESS_DATA 0x01ec | 343 | #define REG_BB_ACCESS_DATA 0x01ec |
342 | 344 | ||
345 | #define REG_HMBOX_EXT0_8723B 0x01f0 | ||
346 | #define REG_HMBOX_EXT1_8723B 0x01f4 | ||
347 | #define REG_HMBOX_EXT2_8723B 0x01f8 | ||
348 | #define REG_HMBOX_EXT3_8723B 0x01fc | ||
349 | |||
343 | /* 0x0200 ~ 0x027F TXDMA Configuration */ | 350 | /* 0x0200 ~ 0x027F TXDMA Configuration */ |
344 | #define REG_RQPN 0x0200 | 351 | #define REG_RQPN 0x0200 |
345 | #define RQPN_HI_PQ_SHIFT 0 | 352 | #define RQPN_HI_PQ_SHIFT 0 |
@@ -352,6 +359,8 @@ | |||
352 | #define REG_TXDMA_OFFSET_CHK 0x020c | 359 | #define REG_TXDMA_OFFSET_CHK 0x020c |
353 | #define REG_TXDMA_STATUS 0x0210 | 360 | #define REG_TXDMA_STATUS 0x0210 |
354 | #define REG_RQPN_NPQ 0x0214 | 361 | #define REG_RQPN_NPQ 0x0214 |
362 | #define RQPN_NPQ_SHIFT 0 | ||
363 | #define RQPN_EPQ_SHIFT 16 | ||
355 | 364 | ||
356 | /* 0x0280 ~ 0x02FF RXDMA Configuration */ | 365 | /* 0x0280 ~ 0x02FF RXDMA Configuration */ |
357 | #define REG_RXDMA_AGG_PG_TH 0x0280 | 366 | #define REG_RXDMA_AGG_PG_TH 0x0280 |
@@ -453,6 +462,8 @@ | |||
453 | #define REG_NEED_CPU_HANDLE 0x04e0 | 462 | #define REG_NEED_CPU_HANDLE 0x04e0 |
454 | #define REG_PKT_LOSE_RPT 0x04e1 | 463 | #define REG_PKT_LOSE_RPT 0x04e1 |
455 | #define REG_PTCL_ERR_STATUS 0x04e2 | 464 | #define REG_PTCL_ERR_STATUS 0x04e2 |
465 | #define REG_TX_REPORT_CTRL 0x04ec | ||
466 | #define REG_TX_REPORT_TIME 0x04f0 | ||
456 | #define REG_DUMMY 0x04fc | 467 | #define REG_DUMMY 0x04fc |
457 | 468 | ||
458 | /* 0x0500 ~ 0x05FF EDCA Configuration */ | 469 | /* 0x0500 ~ 0x05FF EDCA Configuration */ |
@@ -559,13 +570,25 @@ | |||
559 | (Rx beacon, probe rsp) */ | 570 | (Rx beacon, probe rsp) */ |
560 | #define RCR_ACCEPT_CRC32 BIT(8) /* Accept CRC32 error packet */ | 571 | #define RCR_ACCEPT_CRC32 BIT(8) /* Accept CRC32 error packet */ |
561 | #define RCR_ACCEPT_ICV BIT(9) /* Accept ICV error packet */ | 572 | #define RCR_ACCEPT_ICV BIT(9) /* Accept ICV error packet */ |
562 | #define RCR_ACCEPT_DATA_FRAME BIT(11) | 573 | #define RCR_ACCEPT_DATA_FRAME BIT(11) /* Accept all data pkt or use |
563 | #define RCR_ACCEPT_CTRL_FRAME BIT(12) | 574 | REG_RXFLTMAP2 */ |
564 | #define RCR_ACCEPT_MGMT_FRAME BIT(13) | 575 | #define RCR_ACCEPT_CTRL_FRAME BIT(12) /* Accept all control pkt or use |
576 | REG_RXFLTMAP1 */ | ||
577 | #define RCR_ACCEPT_MGMT_FRAME BIT(13) /* Accept all mgmt pkt or use | ||
578 | REG_RXFLTMAP0 */ | ||
565 | #define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */ | 579 | #define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */ |
580 | #define RCR_UC_DATA_PKT_INT_ENABLE BIT(16) /* Enable unicast data packet | ||
581 | interrupt */ | ||
582 | #define RCR_BM_DATA_PKT_INT_ENABLE BIT(17) /* Enable broadcast data packet | ||
583 | interrupt */ | ||
584 | #define RCR_TIM_PARSER_ENABLE BIT(18) /* Enable RX beacon TIM parser*/ | ||
566 | #define RCR_MFBEN BIT(22) | 585 | #define RCR_MFBEN BIT(22) |
567 | #define RCR_LSIGEN BIT(23) | 586 | #define RCR_LSIG_ENABLE BIT(23) /* Enable LSIG TXOP Protection |
587 | function. Search KEYCAM for | ||
588 | each rx packet to check if | ||
589 | LSIGEN bit is set. */ | ||
568 | #define RCR_MULTI_BSSID_ENABLE BIT(24) /* Enable Multiple BssId */ | 590 | #define RCR_MULTI_BSSID_ENABLE BIT(24) /* Enable Multiple BssId */ |
591 | #define RCR_FORCE_ACK BIT(26) | ||
569 | #define RCR_ACCEPT_BA_SSN BIT(27) /* Accept BA SSN */ | 592 | #define RCR_ACCEPT_BA_SSN BIT(27) /* Accept BA SSN */ |
570 | #define RCR_APPEND_PHYSTAT BIT(28) | 593 | #define RCR_APPEND_PHYSTAT BIT(28) |
571 | #define RCR_APPEND_ICV BIT(29) | 594 | #define RCR_APPEND_ICV BIT(29) |
@@ -632,9 +655,20 @@ | |||
632 | #define REG_LPNAV_CTRL 0x0694 | 655 | #define REG_LPNAV_CTRL 0x0694 |
633 | #define REG_WKFMCAM_CMD 0x0698 | 656 | #define REG_WKFMCAM_CMD 0x0698 |
634 | #define REG_WKFMCAM_RWD 0x069c | 657 | #define REG_WKFMCAM_RWD 0x069c |
635 | #define REG_RXFLTMAP0 0x06a0 | 658 | |
636 | #define REG_RXFLTMAP1 0x06a2 | 659 | /* |
637 | #define REG_RXFLTMAP2 0x06a4 | 660 | * RX Filters: each bit corresponds to the numerical value of the subtype. |
661 | * If it is set the subtype frame type is passed. The filter is only used when | ||
662 | * the RCR_ACCEPT_DATA_FRAME, RCR_ACCEPT_CTRL_FRAME, RCR_ACCEPT_MGMT_FRAME bit | ||
663 | * in the RCR are low. | ||
664 | * | ||
665 | * Example: Beacon subtype is binary 1000 which is decimal 8 so we have to set | ||
666 | * bit 8 (0x100) in REG_RXFLTMAP0 to enable reception. | ||
667 | */ | ||
668 | #define REG_RXFLTMAP0 0x06a0 /* Management frames */ | ||
669 | #define REG_RXFLTMAP1 0x06a2 /* Control frames */ | ||
670 | #define REG_RXFLTMAP2 0x06a4 /* Data frames */ | ||
671 | |||
638 | #define REG_BCN_PSR_RPT 0x06a8 | 672 | #define REG_BCN_PSR_RPT 0x06a8 |
639 | #define REG_CALB32K_CTRL 0x06ac | 673 | #define REG_CALB32K_CTRL 0x06ac |
640 | #define REG_PKT_MON_CTRL 0x06b4 | 674 | #define REG_PKT_MON_CTRL 0x06b4 |
@@ -742,6 +776,10 @@ | |||
742 | #define REG_FPGA1_RF_MODE 0x0900 | 776 | #define REG_FPGA1_RF_MODE 0x0900 |
743 | 777 | ||
744 | #define REG_FPGA1_TX_INFO 0x090c | 778 | #define REG_FPGA1_TX_INFO 0x090c |
779 | #define REG_DPDT_CTRL 0x092c /* 8723BU */ | ||
780 | #define REG_RFE_CTRL_ANTA_SRC 0x0930 /* 8723BU */ | ||
781 | #define REG_RFE_PATH_SELECT 0x0940 /* 8723BU */ | ||
782 | #define REG_RFE_BUFFER 0x0944 /* 8723BU */ | ||
745 | 783 | ||
746 | #define REG_CCK0_SYSTEM 0x0a00 | 784 | #define REG_CCK0_SYSTEM 0x0a00 |
747 | #define CCK0_SIDEBAND BIT(4) | 785 | #define CCK0_SIDEBAND BIT(4) |
@@ -770,6 +808,9 @@ | |||
770 | 808 | ||
771 | #define REG_OFDM0_ENERGY_CCA_THRES 0x0c4c | 809 | #define REG_OFDM0_ENERGY_CCA_THRES 0x0c4c |
772 | 810 | ||
811 | #define REG_OFDM0_RX_D_SYNC_PATH 0x0c40 | ||
812 | #define OFDM0_SYNC_PATH_NOTCH_FILTER BIT(1) | ||
813 | |||
773 | #define REG_OFDM0_XA_AGC_CORE1 0x0c50 | 814 | #define REG_OFDM0_XA_AGC_CORE1 0x0c50 |
774 | #define REG_OFDM0_XA_AGC_CORE2 0x0c54 | 815 | #define REG_OFDM0_XA_AGC_CORE2 0x0c54 |
775 | #define REG_OFDM0_XB_AGC_CORE1 0x0c58 | 816 | #define REG_OFDM0_XB_AGC_CORE1 0x0c58 |
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index f2507610314b..0f48048b8654 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c | |||
@@ -35,62 +35,58 @@ | |||
35 | #include <linux/export.h> | 35 | #include <linux/export.h> |
36 | #include <net/cfg80211.h> | 36 | #include <net/cfg80211.h> |
37 | 37 | ||
38 | u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { | ||
39 | 36, 38, 40, 42, 44, 46, 48, /* Band 1 */ | ||
40 | 52, 54, 56, 58, 60, 62, 64, /* Band 2 */ | ||
41 | 100, 102, 104, 106, 108, 110, 112, /* Band 3 */ | ||
42 | 116, 118, 120, 122, 124, 126, 128, /* Band 3 */ | ||
43 | 132, 134, 136, 138, 140, 142, 144, /* Band 3 */ | ||
44 | 149, 151, 153, 155, 157, 159, 161, /* Band 4 */ | ||
45 | 165, 167, 169, 171, 173, 175, 177 /* Band 4 */ | ||
46 | }; | ||
47 | EXPORT_SYMBOL(channel5g); | ||
48 | |||
49 | u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { | ||
50 | 42, 58, 106, 122, 138, 155, 171 | ||
51 | }; | ||
52 | EXPORT_SYMBOL(channel5g_80m); | ||
53 | |||
38 | void rtl_addr_delay(u32 addr) | 54 | void rtl_addr_delay(u32 addr) |
39 | { | 55 | { |
40 | if (addr == 0xfe) | 56 | if (addr == 0xfe) |
41 | mdelay(50); | 57 | msleep(50); |
42 | else if (addr == 0xfd) | 58 | else if (addr == 0xfd) |
43 | mdelay(5); | 59 | msleep(5); |
44 | else if (addr == 0xfc) | 60 | else if (addr == 0xfc) |
45 | mdelay(1); | 61 | msleep(1); |
46 | else if (addr == 0xfb) | 62 | else if (addr == 0xfb) |
47 | udelay(50); | 63 | usleep_range(50, 100); |
48 | else if (addr == 0xfa) | 64 | else if (addr == 0xfa) |
49 | udelay(5); | 65 | usleep_range(5, 10); |
50 | else if (addr == 0xf9) | 66 | else if (addr == 0xf9) |
51 | udelay(1); | 67 | usleep_range(1, 2); |
52 | } | 68 | } |
53 | EXPORT_SYMBOL(rtl_addr_delay); | 69 | EXPORT_SYMBOL(rtl_addr_delay); |
54 | 70 | ||
55 | void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, | 71 | void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, |
56 | u32 mask, u32 data) | 72 | u32 mask, u32 data) |
57 | { | 73 | { |
58 | if (addr == 0xfe) { | 74 | if (addr >= 0xf9 && addr <= 0xfe) { |
59 | mdelay(50); | 75 | rtl_addr_delay(addr); |
60 | } else if (addr == 0xfd) { | ||
61 | mdelay(5); | ||
62 | } else if (addr == 0xfc) { | ||
63 | mdelay(1); | ||
64 | } else if (addr == 0xfb) { | ||
65 | udelay(50); | ||
66 | } else if (addr == 0xfa) { | ||
67 | udelay(5); | ||
68 | } else if (addr == 0xf9) { | ||
69 | udelay(1); | ||
70 | } else { | 76 | } else { |
71 | rtl_set_rfreg(hw, rfpath, addr, mask, data); | 77 | rtl_set_rfreg(hw, rfpath, addr, mask, data); |
72 | udelay(1); | 78 | usleep_range(1, 2); |
73 | } | 79 | } |
74 | } | 80 | } |
75 | EXPORT_SYMBOL(rtl_rfreg_delay); | 81 | EXPORT_SYMBOL(rtl_rfreg_delay); |
76 | 82 | ||
77 | void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data) | 83 | void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data) |
78 | { | 84 | { |
79 | if (addr == 0xfe) { | 85 | if (addr >= 0xf9 && addr <= 0xfe) { |
80 | mdelay(50); | 86 | rtl_addr_delay(addr); |
81 | } else if (addr == 0xfd) { | ||
82 | mdelay(5); | ||
83 | } else if (addr == 0xfc) { | ||
84 | mdelay(1); | ||
85 | } else if (addr == 0xfb) { | ||
86 | udelay(50); | ||
87 | } else if (addr == 0xfa) { | ||
88 | udelay(5); | ||
89 | } else if (addr == 0xf9) { | ||
90 | udelay(1); | ||
91 | } else { | 87 | } else { |
92 | rtl_set_bbreg(hw, addr, MASKDWORD, data); | 88 | rtl_set_bbreg(hw, addr, MASKDWORD, data); |
93 | udelay(1); | 89 | usleep_range(1, 2); |
94 | } | 90 | } |
95 | } | 91 | } |
96 | EXPORT_SYMBOL(rtl_bb_delay); | 92 | EXPORT_SYMBOL(rtl_bb_delay); |
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 7f471bff435c..283d608b9973 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c | |||
@@ -855,7 +855,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
855 | } | 855 | } |
856 | /* handle command packet here */ | 856 | /* handle command packet here */ |
857 | if (rtlpriv->cfg->ops->rx_command_packet && | 857 | if (rtlpriv->cfg->ops->rx_command_packet && |
858 | rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { | 858 | rtlpriv->cfg->ops->rx_command_packet(hw, &stats, skb)) { |
859 | dev_kfree_skb_any(skb); | 859 | dev_kfree_skb_any(skb); |
860 | goto new_trx_end; | 860 | goto new_trx_end; |
861 | } | 861 | } |
@@ -2392,7 +2392,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) | |||
2392 | rtlpriv->cfg->ops->deinit_sw_vars(hw); | 2392 | rtlpriv->cfg->ops->deinit_sw_vars(hw); |
2393 | 2393 | ||
2394 | if (rtlpci->irq_alloc) { | 2394 | if (rtlpci->irq_alloc) { |
2395 | synchronize_irq(rtlpci->pdev->irq); | ||
2396 | free_irq(rtlpci->pdev->irq, hw); | 2395 | free_irq(rtlpci->pdev->irq, hw); |
2397 | rtlpci->irq_alloc = 0; | 2396 | rtlpci->irq_alloc = 0; |
2398 | } | 2397 | } |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 28f7010e7108..1aca77719521 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c | |||
@@ -41,7 +41,7 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, | |||
41 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | 41 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
42 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | 42 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
43 | struct rtl_sta_info *sta_entry = NULL; | 43 | struct rtl_sta_info *sta_entry = NULL; |
44 | u8 wireless_mode = 0; | 44 | u16 wireless_mode = 0; |
45 | 45 | ||
46 | /* | 46 | /* |
47 | *this rate is no use for true rate, firmware | 47 | *this rate is no use for true rate, firmware |
@@ -99,7 +99,7 @@ static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, | |||
99 | { | 99 | { |
100 | struct rtl_mac *mac = rtl_mac(rtlpriv); | 100 | struct rtl_mac *mac = rtl_mac(rtlpriv); |
101 | struct rtl_sta_info *sta_entry = NULL; | 101 | struct rtl_sta_info *sta_entry = NULL; |
102 | u8 wireless_mode = 0; | 102 | u16 wireless_mode = 0; |
103 | u8 sgi_20 = 0, sgi_40 = 0, sgi_80 = 0; | 103 | u8 sgi_20 = 0, sgi_40 = 0, sgi_80 = 0; |
104 | 104 | ||
105 | if (sta) { | 105 | if (sta) { |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 791efbe6b18c..11701064b0e1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c | |||
@@ -851,7 +851,7 @@ void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | |||
851 | } | 851 | } |
852 | 852 | ||
853 | u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, | 853 | u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, |
854 | struct rtl_stats status, | 854 | const struct rtl_stats *status, |
855 | struct sk_buff *skb) | 855 | struct sk_buff *skb) |
856 | { | 856 | { |
857 | return 0; | 857 | return 0; |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index eab5ae0eb46c..5a24d194ac76 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h | |||
@@ -790,7 +790,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | |||
790 | bool firstseg, bool lastseg, | 790 | bool firstseg, bool lastseg, |
791 | struct sk_buff *skb); | 791 | struct sk_buff *skb); |
792 | u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, | 792 | u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, |
793 | struct rtl_stats status, | 793 | const struct rtl_stats *status, |
794 | struct sk_buff *skb); | 794 | struct sk_buff *skb); |
795 | 795 | ||
796 | #endif | 796 | #endif |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c index bb06fe836fe7..7810fe87dca7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c | |||
@@ -924,19 +924,11 @@ static void _rtl92d_ccxpower_index_check(struct ieee80211_hw *hw, | |||
924 | 924 | ||
925 | static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl) | 925 | static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl) |
926 | { | 926 | { |
927 | u8 channel_5g[59] = { | ||
928 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | ||
929 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, | ||
930 | 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, | ||
931 | 114, 116, 118, 120, 122, 124, 126, 128, | ||
932 | 130, 132, 134, 136, 138, 140, 149, 151, | ||
933 | 153, 155, 157, 159, 161, 163, 165 | ||
934 | }; | ||
935 | u8 place = chnl; | 927 | u8 place = chnl; |
936 | 928 | ||
937 | if (chnl > 14) { | 929 | if (chnl > 14) { |
938 | for (place = 14; place < sizeof(channel_5g); place++) { | 930 | for (place = 14; place < sizeof(channel5g); place++) { |
939 | if (channel_5g[place] == chnl) { | 931 | if (channel5g[place] == chnl) { |
940 | place++; | 932 | place++; |
941 | break; | 933 | break; |
942 | } | 934 | } |
@@ -2471,16 +2463,9 @@ static bool _rtl92d_is_legal_5g_channel(struct ieee80211_hw *hw, u8 channel) | |||
2471 | { | 2463 | { |
2472 | 2464 | ||
2473 | int i; | 2465 | int i; |
2474 | u8 channel_5g[45] = { | ||
2475 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, | ||
2476 | 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, | ||
2477 | 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, | ||
2478 | 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, | ||
2479 | 161, 163, 165 | ||
2480 | }; | ||
2481 | 2466 | ||
2482 | for (i = 0; i < sizeof(channel_5g); i++) | 2467 | for (i = 0; i < sizeof(channel5g); i++) |
2483 | if (channel == channel_5g[i]) | 2468 | if (channel == channel5g[i]) |
2484 | return true; | 2469 | return true; |
2485 | return false; | 2470 | return false; |
2486 | } | 2471 | } |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c index 5f14308e8eb3..9fd3f1b6e4a8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c | |||
@@ -2018,18 +2018,6 @@ static void _rtl92ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
2018 | struct rtl_efuse *efu = rtl_efuse(rtl_priv(hw)); | 2018 | struct rtl_efuse *efu = rtl_efuse(rtl_priv(hw)); |
2019 | struct txpower_info_2g pwr2g; | 2019 | struct txpower_info_2g pwr2g; |
2020 | struct txpower_info_5g pwr5g; | 2020 | struct txpower_info_5g pwr5g; |
2021 | u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { | ||
2022 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, | ||
2023 | 56, 58, 60, 62, 64, 100, 102, 104, 106, | ||
2024 | 108, 110, 112, 114, 116, 118, 120, 122, | ||
2025 | 124, 126, 128, 130, 132, 134, 136, 138, | ||
2026 | 140, 142, 144, 149, 151, 153, 155, 157, | ||
2027 | 159, 161, 163, 165, 167, 168, 169, 171, | ||
2028 | 173, 175, 177 | ||
2029 | }; | ||
2030 | u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { | ||
2031 | 42, 58, 106, 122, 138, 155, 171 | ||
2032 | }; | ||
2033 | u8 rf, idx; | 2021 | u8 rf, idx; |
2034 | u8 i; | 2022 | u8 i; |
2035 | 2023 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index d39ee67f6113..24eff8ea4c2e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c | |||
@@ -1105,13 +1105,13 @@ void rtl92ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | |||
1105 | } | 1105 | } |
1106 | 1106 | ||
1107 | u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, | 1107 | u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, |
1108 | struct rtl_stats status, | 1108 | const struct rtl_stats *status, |
1109 | struct sk_buff *skb) | 1109 | struct sk_buff *skb) |
1110 | { | 1110 | { |
1111 | u32 result = 0; | 1111 | u32 result = 0; |
1112 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1112 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1113 | 1113 | ||
1114 | switch (status.packet_report_type) { | 1114 | switch (status->packet_report_type) { |
1115 | case NORMAL_RX: | 1115 | case NORMAL_RX: |
1116 | result = 0; | 1116 | result = 0; |
1117 | break; | 1117 | break; |
@@ -1121,7 +1121,7 @@ u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, | |||
1121 | break; | 1121 | break; |
1122 | default: | 1122 | default: |
1123 | RT_TRACE(rtlpriv, COMP_RECV, DBG_TRACE, | 1123 | RT_TRACE(rtlpriv, COMP_RECV, DBG_TRACE, |
1124 | "Unknown packet type %d\n", status.packet_report_type); | 1124 | "Unknown packet type %d\n", status->packet_report_type); |
1125 | break; | 1125 | break; |
1126 | } | 1126 | } |
1127 | 1127 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h index 8f78ac9e6040..a4c38345233e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h | |||
@@ -857,6 +857,6 @@ void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | |||
857 | bool firstseg, bool lastseg, | 857 | bool firstseg, bool lastseg, |
858 | struct sk_buff *skb); | 858 | struct sk_buff *skb); |
859 | u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, | 859 | u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, |
860 | struct rtl_stats status, | 860 | const struct rtl_stats *status, |
861 | struct sk_buff *skb); | 861 | struct sk_buff *skb); |
862 | #endif | 862 | #endif |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c index 2f7c144d7980..7b4a9b63583b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c | |||
@@ -710,7 +710,7 @@ void rtl8723e_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | |||
710 | } | 710 | } |
711 | 711 | ||
712 | u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, | 712 | u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, |
713 | struct rtl_stats status, | 713 | const struct rtl_stats *status, |
714 | struct sk_buff *skb) | 714 | struct sk_buff *skb) |
715 | { | 715 | { |
716 | return 0; | 716 | return 0; |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h index 017da7e194d8..32970bf18856 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h | |||
@@ -716,6 +716,6 @@ void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | |||
716 | bool firstseg, bool lastseg, | 716 | bool firstseg, bool lastseg, |
717 | struct sk_buff *skb); | 717 | struct sk_buff *skb); |
718 | u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, | 718 | u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, |
719 | struct rtl_stats status, | 719 | const struct rtl_stats *status, |
720 | struct sk_buff *skb); | 720 | struct sk_buff *skb); |
721 | #endif | 721 | #endif |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c index 338ec9a9d09b..60345975f9fd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c | |||
@@ -758,13 +758,13 @@ void rtl8723be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | |||
758 | } | 758 | } |
759 | 759 | ||
760 | u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, | 760 | u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, |
761 | struct rtl_stats status, | 761 | const struct rtl_stats *status, |
762 | struct sk_buff *skb) | 762 | struct sk_buff *skb) |
763 | { | 763 | { |
764 | u32 result = 0; | 764 | u32 result = 0; |
765 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 765 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
766 | 766 | ||
767 | switch (status.packet_report_type) { | 767 | switch (status->packet_report_type) { |
768 | case NORMAL_RX: | 768 | case NORMAL_RX: |
769 | result = 0; | 769 | result = 0; |
770 | break; | 770 | break; |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h index 45949ac4854c..40c36607b8b9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h | |||
@@ -620,6 +620,6 @@ void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | |||
620 | bool firstseg, bool lastseg, | 620 | bool firstseg, bool lastseg, |
621 | struct sk_buff *skb); | 621 | struct sk_buff *skb); |
622 | u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, | 622 | u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, |
623 | struct rtl_stats status, | 623 | const struct rtl_stats *status, |
624 | struct sk_buff *skb); | 624 | struct sk_buff *skb); |
625 | #endif | 625 | #endif |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c index 525eb234627c..a4fc70e8c9c0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c | |||
@@ -271,7 +271,7 @@ int rtl8821ae_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) | |||
271 | 271 | ||
272 | err = _rtl8821ae_fw_free_to_go(hw); | 272 | err = _rtl8821ae_fw_free_to_go(hw); |
273 | if (err) { | 273 | if (err) { |
274 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 274 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, |
275 | "Firmware is not ready to run!\n"); | 275 | "Firmware is not ready to run!\n"); |
276 | } else { | 276 | } else { |
277 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | 277 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index bbb789f8990b..fe900badd468 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | |||
@@ -2786,14 +2786,6 @@ static void _rtl8812ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
2786 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 2786 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
2787 | struct txpower_info_2g pwrinfo24g; | 2787 | struct txpower_info_2g pwrinfo24g; |
2788 | struct txpower_info_5g pwrinfo5g; | 2788 | struct txpower_info_5g pwrinfo5g; |
2789 | u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { | ||
2790 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, | ||
2791 | 56, 58, 60, 62, 64, 100, 102, 104, 106, | ||
2792 | 108, 110, 112, 114, 116, 118, 120, 122, | ||
2793 | 124, 126, 128, 130, 132, 134, 136, 138, | ||
2794 | 140, 142, 144, 149, 151, 153, 155, 157, | ||
2795 | 159, 161, 163, 165, 167, 168, 169, 171, 173, 175, 177}; | ||
2796 | u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = {42, 58, 106, 122, 138, 155, 171}; | ||
2797 | u8 rf_path, index; | 2789 | u8 rf_path, index; |
2798 | u8 i; | 2790 | u8 i; |
2799 | 2791 | ||
@@ -2872,16 +2864,6 @@ static void _rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
2872 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 2864 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
2873 | struct txpower_info_2g pwrinfo24g; | 2865 | struct txpower_info_2g pwrinfo24g; |
2874 | struct txpower_info_5g pwrinfo5g; | 2866 | struct txpower_info_5g pwrinfo5g; |
2875 | u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { | ||
2876 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, | ||
2877 | 56, 58, 60, 62, 64, 100, 102, 104, 106, | ||
2878 | 108, 110, 112, 114, 116, 118, 120, 122, | ||
2879 | 124, 126, 128, 130, 132, 134, 136, 138, | ||
2880 | 140, 142, 144, 149, 151, 153, 155, 157, | ||
2881 | 159, 161, 163, 165, 167, 168, 169, 171, | ||
2882 | 173, 175, 177}; | ||
2883 | u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { | ||
2884 | 42, 58, 106, 122, 138, 155, 171}; | ||
2885 | u8 rf_path, index; | 2867 | u8 rf_path, index; |
2886 | u8 i; | 2868 | u8 i; |
2887 | 2869 | ||
@@ -3855,7 +3837,7 @@ void rtl8821ae_update_channel_access_setting(struct ieee80211_hw *hw) | |||
3855 | { | 3837 | { |
3856 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 3838 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
3857 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 3839 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
3858 | u8 wireless_mode = mac->mode; | 3840 | u16 wireless_mode = mac->mode; |
3859 | u8 sifs_timer, r2t_sifs; | 3841 | u8 sifs_timer, r2t_sifs; |
3860 | 3842 | ||
3861 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, | 3843 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 9b4d8a637915..74165b3eb362 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | |||
@@ -1472,18 +1472,13 @@ static char _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(struct ieee80211_hw *hw, | |||
1472 | { | 1472 | { |
1473 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1473 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1474 | char channel_index = -1; | 1474 | char channel_index = -1; |
1475 | u8 channel_5g[CHANNEL_MAX_NUMBER_5G] = { | ||
1476 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, | ||
1477 | 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, | ||
1478 | 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 149, | ||
1479 | 151, 153, 155, 157, 159, 161, 163, 165, 167, 168, 169, 171, | ||
1480 | 173, 175, 177}; | ||
1481 | u8 i = 0; | 1475 | u8 i = 0; |
1476 | |||
1482 | if (band == BAND_ON_2_4G) | 1477 | if (band == BAND_ON_2_4G) |
1483 | channel_index = channel - 1; | 1478 | channel_index = channel - 1; |
1484 | else if (band == BAND_ON_5G) { | 1479 | else if (band == BAND_ON_5G) { |
1485 | for (i = 0; i < sizeof(channel_5g)/sizeof(u8); ++i) { | 1480 | for (i = 0; i < sizeof(channel5g)/sizeof(u8); ++i) { |
1486 | if (channel_5g[i] == channel) | 1481 | if (channel5g[i] == channel) |
1487 | channel_index = i; | 1482 | channel_index = i; |
1488 | } | 1483 | } |
1489 | } else | 1484 | } else |
@@ -2240,13 +2235,6 @@ void rtl8821ae_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) | |||
2240 | 2235 | ||
2241 | static bool _rtl8821ae_phy_get_chnl_index(u8 channel, u8 *chnl_index) | 2236 | static bool _rtl8821ae_phy_get_chnl_index(u8 channel, u8 *chnl_index) |
2242 | { | 2237 | { |
2243 | u8 channel_5g[CHANNEL_MAX_NUMBER_5G] = { | ||
2244 | 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, | ||
2245 | 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, | ||
2246 | 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, | ||
2247 | 142, 144, 149, 151, 153, 155, 157, 159, 161, 163, 165, | ||
2248 | 167, 168, 169, 171, 173, 175, 177 | ||
2249 | }; | ||
2250 | u8 i = 0; | 2238 | u8 i = 0; |
2251 | bool in_24g = true; | 2239 | bool in_24g = true; |
2252 | 2240 | ||
@@ -2257,7 +2245,7 @@ static bool _rtl8821ae_phy_get_chnl_index(u8 channel, u8 *chnl_index) | |||
2257 | in_24g = false; | 2245 | in_24g = false; |
2258 | 2246 | ||
2259 | for (i = 0; i < CHANNEL_MAX_NUMBER_5G; ++i) { | 2247 | for (i = 0; i < CHANNEL_MAX_NUMBER_5G; ++i) { |
2260 | if (channel_5g[i] == channel) { | 2248 | if (channel5g[i] == channel) { |
2261 | *chnl_index = i; | 2249 | *chnl_index = i; |
2262 | return in_24g; | 2250 | return in_24g; |
2263 | } | 2251 | } |
@@ -2728,13 +2716,10 @@ static u8 _rtl8821ae_get_txpower_index(struct ieee80211_hw *hw, u8 path, | |||
2728 | rate <= DESC_RATEVHT2SS_MCS9)) | 2716 | rate <= DESC_RATEVHT2SS_MCS9)) |
2729 | txpower += rtlefuse->txpwr_5g_bw40diff[path][TX_2S]; | 2717 | txpower += rtlefuse->txpwr_5g_bw40diff[path][TX_2S]; |
2730 | } else if (bandwidth == HT_CHANNEL_WIDTH_80) { | 2718 | } else if (bandwidth == HT_CHANNEL_WIDTH_80) { |
2731 | u8 channel_5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { | ||
2732 | 42, 58, 106, 122, 138, 155, 171 | ||
2733 | }; | ||
2734 | u8 i; | 2719 | u8 i; |
2735 | 2720 | ||
2736 | for (i = 0; i < sizeof(channel_5g_80m) / sizeof(u8); ++i) | 2721 | for (i = 0; i < sizeof(channel5g_80m) / sizeof(u8); ++i) |
2737 | if (channel_5g_80m[i] == channel) | 2722 | if (channel5g_80m[i] == channel) |
2738 | index = i; | 2723 | index = i; |
2739 | 2724 | ||
2740 | if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || | 2725 | if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c index 174743aef943..41efaa148d13 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c | |||
@@ -998,13 +998,13 @@ void rtl8821ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | |||
998 | } | 998 | } |
999 | 999 | ||
1000 | u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, | 1000 | u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, |
1001 | struct rtl_stats status, | 1001 | const struct rtl_stats *status, |
1002 | struct sk_buff *skb) | 1002 | struct sk_buff *skb) |
1003 | { | 1003 | { |
1004 | u32 result = 0; | 1004 | u32 result = 0; |
1005 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1005 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1006 | 1006 | ||
1007 | switch (status.packet_report_type) { | 1007 | switch (status->packet_report_type) { |
1008 | case NORMAL_RX: | 1008 | case NORMAL_RX: |
1009 | result = 0; | 1009 | result = 0; |
1010 | break; | 1010 | break; |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h index 31409042d8dd..ad565bebf1d5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h | |||
@@ -615,6 +615,6 @@ void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | |||
615 | bool firstseg, bool lastseg, | 615 | bool firstseg, bool lastseg, |
616 | struct sk_buff *skb); | 616 | struct sk_buff *skb); |
617 | u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, | 617 | u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, |
618 | struct rtl_stats status, | 618 | const struct rtl_stats *status, |
619 | struct sk_buff *skb); | 619 | struct sk_buff *skb); |
620 | #endif | 620 | #endif |
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 4544752a2ba8..554d81420f19 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h | |||
@@ -116,17 +116,12 @@ | |||
116 | 116 | ||
117 | #define CHANNEL_MAX_NUMBER (14 + 24 + 21) /* 14 is the max channel no */ | 117 | #define CHANNEL_MAX_NUMBER (14 + 24 + 21) /* 14 is the max channel no */ |
118 | #define CHANNEL_MAX_NUMBER_2G 14 | 118 | #define CHANNEL_MAX_NUMBER_2G 14 |
119 | #define CHANNEL_MAX_NUMBER_5G 54 /* Please refer to | 119 | #define CHANNEL_MAX_NUMBER_5G 49 /* Please refer to |
120 | *"phy_GetChnlGroup8812A" and | 120 | *"phy_GetChnlGroup8812A" and |
121 | * "Hal_ReadTxPowerInfo8812A" | 121 | * "Hal_ReadTxPowerInfo8812A" |
122 | */ | 122 | */ |
123 | #define CHANNEL_MAX_NUMBER_5G_80M 7 | 123 | #define CHANNEL_MAX_NUMBER_5G_80M 7 |
124 | #define CHANNEL_GROUP_MAX (3 + 9) /* ch1~3, 4~9, 10~14 = three groups */ | 124 | #define CHANNEL_GROUP_MAX (3 + 9) /* ch1~3, 4~9, 10~14 = three groups */ |
125 | #define CHANNEL_MAX_NUMBER_5G 54 /* Please refer to | ||
126 | *"phy_GetChnlGroup8812A" and | ||
127 | * "Hal_ReadTxPowerInfo8812A" | ||
128 | */ | ||
129 | #define CHANNEL_MAX_NUMBER_5G_80M 7 | ||
130 | #define MAX_PG_GROUP 13 | 125 | #define MAX_PG_GROUP 13 |
131 | #define CHANNEL_GROUP_MAX_2G 3 | 126 | #define CHANNEL_GROUP_MAX_2G 3 |
132 | #define CHANNEL_GROUP_IDX_5GL 3 | 127 | #define CHANNEL_GROUP_IDX_5GL 3 |
@@ -1323,14 +1318,13 @@ struct rtl_tid_data { | |||
1323 | 1318 | ||
1324 | struct rtl_sta_info { | 1319 | struct rtl_sta_info { |
1325 | struct list_head list; | 1320 | struct list_head list; |
1326 | u8 ratr_index; | ||
1327 | u8 wireless_mode; | ||
1328 | u8 mimo_ps; | ||
1329 | u8 mac_addr[ETH_ALEN]; | ||
1330 | struct rtl_tid_data tids[MAX_TID_COUNT]; | 1321 | struct rtl_tid_data tids[MAX_TID_COUNT]; |
1331 | |||
1332 | /* just used for ap adhoc or mesh*/ | 1322 | /* just used for ap adhoc or mesh*/ |
1333 | struct rssi_sta rssi_stat; | 1323 | struct rssi_sta rssi_stat; |
1324 | u16 wireless_mode; | ||
1325 | u8 ratr_index; | ||
1326 | u8 mimo_ps; | ||
1327 | u8 mac_addr[ETH_ALEN]; | ||
1334 | } __packed; | 1328 | } __packed; |
1335 | 1329 | ||
1336 | struct rtl_priv; | 1330 | struct rtl_priv; |
@@ -2194,7 +2188,7 @@ struct rtl_hal_ops { | |||
2194 | bool (*get_btc_status) (void); | 2188 | bool (*get_btc_status) (void); |
2195 | bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); | 2189 | bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); |
2196 | u32 (*rx_command_packet)(struct ieee80211_hw *hw, | 2190 | u32 (*rx_command_packet)(struct ieee80211_hw *hw, |
2197 | struct rtl_stats status, struct sk_buff *skb); | 2191 | const struct rtl_stats *status, struct sk_buff *skb); |
2198 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, | 2192 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, |
2199 | struct rtl_wow_pattern *rtl_pattern, | 2193 | struct rtl_wow_pattern *rtl_pattern, |
2200 | u8 index); | 2194 | u8 index); |
@@ -2904,6 +2898,10 @@ value to host byte ordering.*/ | |||
2904 | #define STBC_VHT_TEST_TX_ENABLE BIT(2) | 2898 | #define STBC_VHT_TEST_TX_ENABLE BIT(2) |
2905 | #define STBC_VHT_CAP_TX BIT(3) | 2899 | #define STBC_VHT_CAP_TX BIT(3) |
2906 | 2900 | ||
2901 | extern u8 channel5g[CHANNEL_MAX_NUMBER_5G]; | ||
2902 | |||
2903 | extern u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M]; | ||
2904 | |||
2907 | static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) | 2905 | static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) |
2908 | { | 2906 | { |
2909 | return rtlpriv->io.read8_sync(rtlpriv, addr); | 2907 | return rtlpriv->io.read8_sync(rtlpriv, addr); |
diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c index a740083634d8..63f95e9c2992 100644 --- a/drivers/net/wireless/st/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c | |||
@@ -446,8 +446,7 @@ static int cw1200_spi_disconnect(struct spi_device *func) | |||
446 | return 0; | 446 | return 0; |
447 | } | 447 | } |
448 | 448 | ||
449 | #ifdef CONFIG_PM | 449 | static int __maybe_unused cw1200_spi_suspend(struct device *dev) |
450 | static int cw1200_spi_suspend(struct device *dev) | ||
451 | { | 450 | { |
452 | struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev)); | 451 | struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev)); |
453 | 452 | ||
@@ -460,16 +459,12 @@ static int cw1200_spi_suspend(struct device *dev) | |||
460 | 459 | ||
461 | static SIMPLE_DEV_PM_OPS(cw1200_pm_ops, cw1200_spi_suspend, NULL); | 460 | static SIMPLE_DEV_PM_OPS(cw1200_pm_ops, cw1200_spi_suspend, NULL); |
462 | 461 | ||
463 | #endif | ||
464 | |||
465 | static struct spi_driver spi_driver = { | 462 | static struct spi_driver spi_driver = { |
466 | .probe = cw1200_spi_probe, | 463 | .probe = cw1200_spi_probe, |
467 | .remove = cw1200_spi_disconnect, | 464 | .remove = cw1200_spi_disconnect, |
468 | .driver = { | 465 | .driver = { |
469 | .name = "cw1200_wlan_spi", | 466 | .name = "cw1200_wlan_spi", |
470 | #ifdef CONFIG_PM | 467 | .pm = IS_ENABLED(CONFIG_PM) ? &cw1200_pm_ops : NULL, |
471 | .pm = &cw1200_pm_ops, | ||
472 | #endif | ||
473 | }, | 468 | }, |
474 | }; | 469 | }; |
475 | 470 | ||
diff --git a/drivers/net/wireless/st/cw1200/pm.h b/drivers/net/wireless/st/cw1200/pm.h index 3ed90ff22bb8..534548470ebc 100644 --- a/drivers/net/wireless/st/cw1200/pm.h +++ b/drivers/net/wireless/st/cw1200/pm.h | |||
@@ -31,13 +31,18 @@ int cw1200_pm_init(struct cw1200_pm_state *pm, | |||
31 | void cw1200_pm_deinit(struct cw1200_pm_state *pm); | 31 | void cw1200_pm_deinit(struct cw1200_pm_state *pm); |
32 | int cw1200_wow_suspend(struct ieee80211_hw *hw, | 32 | int cw1200_wow_suspend(struct ieee80211_hw *hw, |
33 | struct cfg80211_wowlan *wowlan); | 33 | struct cfg80211_wowlan *wowlan); |
34 | int cw1200_wow_resume(struct ieee80211_hw *hw); | ||
35 | int cw1200_can_suspend(struct cw1200_common *priv); | 34 | int cw1200_can_suspend(struct cw1200_common *priv); |
35 | int cw1200_wow_resume(struct ieee80211_hw *hw); | ||
36 | void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, | 36 | void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, |
37 | unsigned long tmo); | 37 | unsigned long tmo); |
38 | #else | 38 | #else |
39 | static inline void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, | 39 | static inline void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, |
40 | unsigned long tmo) { | 40 | unsigned long tmo) |
41 | { | ||
42 | } | ||
43 | static inline int cw1200_can_suspend(struct cw1200_common *priv) | ||
44 | { | ||
45 | return 0; | ||
41 | } | 46 | } |
42 | #endif | 47 | #endif |
43 | #endif | 48 | #endif |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 700d0c6f7480..846513c73606 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -576,13 +576,11 @@ struct bcma_chipcommon_pmu { | |||
576 | u32 crystalfreq; /* The active crystal frequency (in kHz) */ | 576 | u32 crystalfreq; /* The active crystal frequency (in kHz) */ |
577 | }; | 577 | }; |
578 | 578 | ||
579 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 579 | #ifdef CONFIG_BCMA_PFLASH |
580 | struct bcma_pflash { | 580 | struct bcma_pflash { |
581 | bool present; | 581 | bool present; |
582 | u8 buswidth; | ||
583 | u32 window; | ||
584 | u32 window_size; | ||
585 | }; | 582 | }; |
583 | #endif | ||
586 | 584 | ||
587 | #ifdef CONFIG_BCMA_SFLASH | 585 | #ifdef CONFIG_BCMA_SFLASH |
588 | struct mtd_info; | 586 | struct mtd_info; |
@@ -606,6 +604,7 @@ struct bcma_nflash { | |||
606 | }; | 604 | }; |
607 | #endif | 605 | #endif |
608 | 606 | ||
607 | #ifdef CONFIG_BCMA_DRIVER_MIPS | ||
609 | struct bcma_serial_port { | 608 | struct bcma_serial_port { |
610 | void *regs; | 609 | void *regs; |
611 | unsigned long clockspeed; | 610 | unsigned long clockspeed; |
@@ -625,8 +624,9 @@ struct bcma_drv_cc { | |||
625 | /* Fast Powerup Delay constant */ | 624 | /* Fast Powerup Delay constant */ |
626 | u16 fast_pwrup_delay; | 625 | u16 fast_pwrup_delay; |
627 | struct bcma_chipcommon_pmu pmu; | 626 | struct bcma_chipcommon_pmu pmu; |
628 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 627 | #ifdef CONFIG_BCMA_PFLASH |
629 | struct bcma_pflash pflash; | 628 | struct bcma_pflash pflash; |
629 | #endif | ||
630 | #ifdef CONFIG_BCMA_SFLASH | 630 | #ifdef CONFIG_BCMA_SFLASH |
631 | struct bcma_sflash sflash; | 631 | struct bcma_sflash sflash; |
632 | #endif | 632 | #endif |
@@ -634,6 +634,7 @@ struct bcma_drv_cc { | |||
634 | struct bcma_nflash nflash; | 634 | struct bcma_nflash nflash; |
635 | #endif | 635 | #endif |
636 | 636 | ||
637 | #ifdef CONFIG_BCMA_DRIVER_MIPS | ||
637 | int nr_serial_ports; | 638 | int nr_serial_ports; |
638 | struct bcma_serial_port serial_ports[4]; | 639 | struct bcma_serial_port serial_ports[4]; |
639 | #endif /* CONFIG_BCMA_DRIVER_MIPS */ | 640 | #endif /* CONFIG_BCMA_DRIVER_MIPS */ |
diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h deleted file mode 100644 index e75dcbf2b230..000000000000 --- a/include/linux/platform_data/brcmfmac-sdio.h +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _LINUX_BRCMFMAC_PLATFORM_H | ||
18 | #define _LINUX_BRCMFMAC_PLATFORM_H | ||
19 | |||
20 | /* | ||
21 | * Platform specific driver functions and data. Through the platform specific | ||
22 | * device data functions can be provided to help the brcmfmac driver to | ||
23 | * operate with the device in combination with the used platform. | ||
24 | * | ||
25 | * Use the platform data in the following (similar) way: | ||
26 | * | ||
27 | * | ||
28 | #include <brcmfmac_platform.h> | ||
29 | |||
30 | |||
31 | static void brcmfmac_power_on(void) | ||
32 | { | ||
33 | } | ||
34 | |||
35 | static void brcmfmac_power_off(void) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | static void brcmfmac_reset(void) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | static struct brcmfmac_sdio_platform_data brcmfmac_sdio_pdata = { | ||
44 | .power_on = brcmfmac_power_on, | ||
45 | .power_off = brcmfmac_power_off, | ||
46 | .reset = brcmfmac_reset | ||
47 | }; | ||
48 | |||
49 | static struct platform_device brcmfmac_device = { | ||
50 | .name = BRCMFMAC_SDIO_PDATA_NAME, | ||
51 | .id = PLATFORM_DEVID_NONE, | ||
52 | .dev.platform_data = &brcmfmac_sdio_pdata | ||
53 | }; | ||
54 | |||
55 | void __init brcmfmac_init_pdata(void) | ||
56 | { | ||
57 | brcmfmac_sdio_pdata.oob_irq_supported = true; | ||
58 | brcmfmac_sdio_pdata.oob_irq_nr = gpio_to_irq(GPIO_BRCMF_SDIO_OOB); | ||
59 | brcmfmac_sdio_pdata.oob_irq_flags = IORESOURCE_IRQ | | ||
60 | IORESOURCE_IRQ_HIGHLEVEL; | ||
61 | platform_device_register(&brcmfmac_device); | ||
62 | } | ||
63 | * | ||
64 | * | ||
65 | * Note: the brcmfmac can be loaded as module or be statically built-in into | ||
66 | * the kernel. If built-in then do note that it uses module_init (and | ||
67 | * module_exit) routines which equal device_initcall. So if you intend to | ||
68 | * create a module with the platform specific data for the brcmfmac and have | ||
69 | * it built-in to the kernel then use a higher initcall then device_initcall | ||
70 | * (see init.h). If this is not done then brcmfmac will load without problems | ||
71 | * but will not pickup the platform data. | ||
72 | * | ||
73 | * When the driver does not "detect" platform driver data then it will continue | ||
74 | * without reporting anything and just assume there is no data needed. Which is | ||
75 | * probably true for most platforms. | ||
76 | * | ||
77 | * Explanation of the platform_data fields: | ||
78 | * | ||
79 | * drive_strength: is the preferred drive_strength to be used for the SDIO | ||
80 | * pins. If 0 then a default value will be used. This is the target drive | ||
81 | * strength, the exact drive strength which will be used depends on the | ||
82 | * capabilities of the device. | ||
83 | * | ||
84 | * oob_irq_supported: does the board have support for OOB interrupts. SDIO | ||
85 | * in-band interrupts are relatively slow and for having less overhead on | ||
86 | * interrupt processing an out of band interrupt can be used. If the HW | ||
87 | * supports this then enable this by setting this field to true and configure | ||
88 | * the oob related fields. | ||
89 | * | ||
90 | * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are | ||
91 | * used for registering the irq using request_irq function. | ||
92 | * | ||
93 | * broken_sg_support: flag for broken sg list support of SDIO host controller. | ||
94 | * Set this to true if the SDIO host controller has higher align requirement | ||
95 | * than 32 bytes for each scatterlist item. | ||
96 | * | ||
97 | * sd_head_align: alignment requirement for start of data buffer | ||
98 | * | ||
99 | * sd_sgentry_align: length alignment requirement for each sg entry | ||
100 | * | ||
101 | * power_on: This function is called by the brcmfmac when the module gets | ||
102 | * loaded. This can be particularly useful for low power devices. The platform | ||
103 | * spcific routine may for example decide to power up the complete device. | ||
104 | * If there is no use-case for this function then provide NULL. | ||
105 | * | ||
106 | * power_off: This function is called by the brcmfmac when the module gets | ||
107 | * unloaded. At this point the device can be powered down or otherwise be reset. | ||
108 | * So if an actual power_off is not supported but reset is then reset the device | ||
109 | * when this function gets called. This can be particularly useful for low power | ||
110 | * devices. If there is no use-case for this function (either power-down or | ||
111 | * reset) then provide NULL. | ||
112 | * | ||
113 | * reset: This function can get called if the device communication broke down. | ||
114 | * This functionality is particularly useful in case of SDIO type devices. It is | ||
115 | * possible to reset a dongle via sdio data interface, but it requires that | ||
116 | * this is fully functional. This function is chip/module specific and this | ||
117 | * function should return only after the complete reset has completed. | ||
118 | */ | ||
119 | |||
120 | #define BRCMFMAC_SDIO_PDATA_NAME "brcmfmac_sdio" | ||
121 | |||
122 | struct brcmfmac_sdio_platform_data { | ||
123 | unsigned int drive_strength; | ||
124 | bool oob_irq_supported; | ||
125 | unsigned int oob_irq_nr; | ||
126 | unsigned long oob_irq_flags; | ||
127 | bool broken_sg_support; | ||
128 | unsigned short sd_head_align; | ||
129 | unsigned short sd_sgentry_align; | ||
130 | void (*power_on)(void); | ||
131 | void (*power_off)(void); | ||
132 | void (*reset)(void); | ||
133 | }; | ||
134 | |||
135 | #endif /* _LINUX_BRCMFMAC_PLATFORM_H */ | ||
diff --git a/include/linux/platform_data/brcmfmac.h b/include/linux/platform_data/brcmfmac.h new file mode 100644 index 000000000000..1d30bf278231 --- /dev/null +++ b/include/linux/platform_data/brcmfmac.h | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Copyright (c) 201 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _LINUX_BRCMFMAC_PLATFORM_H | ||
18 | #define _LINUX_BRCMFMAC_PLATFORM_H | ||
19 | |||
20 | |||
21 | #define BRCMFMAC_PDATA_NAME "brcmfmac" | ||
22 | |||
23 | #define BRCMFMAC_COUNTRY_BUF_SZ 4 | ||
24 | |||
25 | |||
26 | /* | ||
27 | * Platform specific driver functions and data. Through the platform specific | ||
28 | * device data functions and data can be provided to help the brcmfmac driver to | ||
29 | * operate with the device in combination with the used platform. | ||
30 | */ | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Note: the brcmfmac can be loaded as module or be statically built-in into | ||
35 | * the kernel. If built-in then do note that it uses module_init (and | ||
36 | * module_exit) routines which equal device_initcall. So if you intend to | ||
37 | * create a module with the platform specific data for the brcmfmac and have | ||
38 | * it built-in to the kernel then use a higher initcall then device_initcall | ||
39 | * (see init.h). If this is not done then brcmfmac will load without problems | ||
40 | * but will not pickup the platform data. | ||
41 | * | ||
42 | * When the driver does not "detect" platform driver data then it will continue | ||
43 | * without reporting anything and just assume there is no data needed. Which is | ||
44 | * probably true for most platforms. | ||
45 | */ | ||
46 | |||
47 | /** | ||
48 | * enum brcmf_bus_type - Bus type identifier. Currently SDIO, USB and PCIE are | ||
49 | * supported. | ||
50 | */ | ||
51 | enum brcmf_bus_type { | ||
52 | BRCMF_BUSTYPE_SDIO, | ||
53 | BRCMF_BUSTYPE_USB, | ||
54 | BRCMF_BUSTYPE_PCIE | ||
55 | }; | ||
56 | |||
57 | |||
58 | /** | ||
59 | * struct brcmfmac_sdio_pd - SDIO Device specific platform data. | ||
60 | * | ||
61 | * @txglomsz: SDIO txglom size. Use 0 if default of driver is to be | ||
62 | * used. | ||
63 | * @drive_strength: is the preferred drive_strength to be used for the SDIO | ||
64 | * pins. If 0 then a default value will be used. This is | ||
65 | * the target drive strength, the exact drive strength | ||
66 | * which will be used depends on the capabilities of the | ||
67 | * device. | ||
68 | * @oob_irq_supported: does the board have support for OOB interrupts. SDIO | ||
69 | * in-band interrupts are relatively slow and for having | ||
70 | * less overhead on interrupt processing an out of band | ||
71 | * interrupt can be used. If the HW supports this then | ||
72 | * enable this by setting this field to true and configure | ||
73 | * the oob related fields. | ||
74 | * @oob_irq_nr, | ||
75 | * @oob_irq_flags: the OOB interrupt information. The values are used for | ||
76 | * registering the irq using request_irq function. | ||
77 | * @broken_sg_support: flag for broken sg list support of SDIO host controller. | ||
78 | * Set this to true if the SDIO host controller has higher | ||
79 | * align requirement than 32 bytes for each scatterlist | ||
80 | * item. | ||
81 | * @sd_head_align: alignment requirement for start of data buffer. | ||
82 | * @sd_sgentry_align: length alignment requirement for each sg entry. | ||
83 | * @reset: This function can get called if the device communication | ||
84 | * broke down. This functionality is particularly useful in | ||
85 | * case of SDIO type devices. It is possible to reset a | ||
86 | * dongle via sdio data interface, but it requires that | ||
87 | * this is fully functional. This function is chip/module | ||
88 | * specific and this function should return only after the | ||
89 | * complete reset has completed. | ||
90 | */ | ||
91 | struct brcmfmac_sdio_pd { | ||
92 | int txglomsz; | ||
93 | unsigned int drive_strength; | ||
94 | bool oob_irq_supported; | ||
95 | unsigned int oob_irq_nr; | ||
96 | unsigned long oob_irq_flags; | ||
97 | bool broken_sg_support; | ||
98 | unsigned short sd_head_align; | ||
99 | unsigned short sd_sgentry_align; | ||
100 | void (*reset)(void); | ||
101 | }; | ||
102 | |||
103 | /** | ||
104 | * struct brcmfmac_pd_cc_entry - Struct for translating user space country code | ||
105 | * (iso3166) to firmware country code and | ||
106 | * revision. | ||
107 | * | ||
108 | * @iso3166: iso3166 alpha 2 country code string. | ||
109 | * @cc: firmware country code string. | ||
110 | * @rev: firmware country code revision. | ||
111 | */ | ||
112 | struct brcmfmac_pd_cc_entry { | ||
113 | char iso3166[BRCMFMAC_COUNTRY_BUF_SZ]; | ||
114 | char cc[BRCMFMAC_COUNTRY_BUF_SZ]; | ||
115 | s32 rev; | ||
116 | }; | ||
117 | |||
118 | /** | ||
119 | * struct brcmfmac_pd_cc - Struct for translating country codes as set by user | ||
120 | * space to a country code and rev which can be used by | ||
121 | * firmware. | ||
122 | * | ||
123 | * @table_size: number of entries in table (> 0) | ||
124 | * @table: array of 1 or more elements with translation information. | ||
125 | */ | ||
126 | struct brcmfmac_pd_cc { | ||
127 | int table_size; | ||
128 | struct brcmfmac_pd_cc_entry table[0]; | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * struct brcmfmac_pd_device - Device specific platform data. (id/rev/bus_type) | ||
133 | * is the unique identifier of the device. | ||
134 | * | ||
135 | * @id: ID of the device for which this data is. In case of SDIO | ||
136 | * or PCIE this is the chipid as identified by chip.c In | ||
137 | * case of USB this is the chipid as identified by the | ||
138 | * device query. | ||
139 | * @rev: chip revision, see id. | ||
140 | * @bus_type: The type of bus. Some chipid/rev exist for different bus | ||
141 | * types. Each bus type has its own set of settings. | ||
142 | * @feature_disable: Bitmask of features to disable (override), See feature.c | ||
143 | * in brcmfmac for details. | ||
144 | * @country_codes: If available, pointer to struct for translating country | ||
145 | * codes. | ||
146 | * @bus: Bus specific (union) device settings. Currently only | ||
147 | * SDIO. | ||
148 | */ | ||
149 | struct brcmfmac_pd_device { | ||
150 | unsigned int id; | ||
151 | unsigned int rev; | ||
152 | enum brcmf_bus_type bus_type; | ||
153 | unsigned int feature_disable; | ||
154 | struct brcmfmac_pd_cc *country_codes; | ||
155 | union { | ||
156 | struct brcmfmac_sdio_pd sdio; | ||
157 | } bus; | ||
158 | }; | ||
159 | |||
160 | /** | ||
161 | * struct brcmfmac_platform_data - BRCMFMAC specific platform data. | ||
162 | * | ||
163 | * @power_on: This function is called by the brcmfmac driver when the module | ||
164 | * gets loaded. This can be particularly useful for low power | ||
165 | * devices. The platform spcific routine may for example decide to | ||
166 | * power up the complete device. If there is no use-case for this | ||
167 | * function then provide NULL. | ||
168 | * @power_off: This function is called by the brcmfmac when the module gets | ||
169 | * unloaded. At this point the devices can be powered down or | ||
170 | * otherwise be reset. So if an actual power_off is not supported | ||
171 | * but reset is supported by the devices then reset the devices | ||
172 | * when this function gets called. This can be particularly useful | ||
173 | * for low power devices. If there is no use-case for this | ||
174 | * function then provide NULL. | ||
175 | */ | ||
176 | struct brcmfmac_platform_data { | ||
177 | void (*power_on)(void); | ||
178 | void (*power_off)(void); | ||
179 | char *fw_alternative_path; | ||
180 | int device_count; | ||
181 | struct brcmfmac_pd_device devices[0]; | ||
182 | }; | ||
183 | |||
184 | |||
185 | #endif /* _LINUX_BRCMFMAC_PLATFORM_H */ | ||