diff options
270 files changed, 9402 insertions, 3754 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index d9b9416c989f..49b8b8907f36 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
| @@ -113,7 +113,6 @@ | |||
| 113 | !Finclude/net/cfg80211.h cfg80211_beacon_data | 113 | !Finclude/net/cfg80211.h cfg80211_beacon_data |
| 114 | !Finclude/net/cfg80211.h cfg80211_ap_settings | 114 | !Finclude/net/cfg80211.h cfg80211_ap_settings |
| 115 | !Finclude/net/cfg80211.h station_parameters | 115 | !Finclude/net/cfg80211.h station_parameters |
| 116 | !Finclude/net/cfg80211.h station_info_flags | ||
| 117 | !Finclude/net/cfg80211.h rate_info_flags | 116 | !Finclude/net/cfg80211.h rate_info_flags |
| 118 | !Finclude/net/cfg80211.h rate_info | 117 | !Finclude/net/cfg80211.h rate_info |
| 119 | !Finclude/net/cfg80211.h station_info | 118 | !Finclude/net/cfg80211.h station_info |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4df73da11adc..cdb815e833b5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -3206,6 +3206,18 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 3206 | 3206 | ||
| 3207 | retain_initrd [RAM] Keep initrd memory after extraction | 3207 | retain_initrd [RAM] Keep initrd memory after extraction |
| 3208 | 3208 | ||
| 3209 | rfkill.default_state= | ||
| 3210 | 0 "airplane mode". All wifi, bluetooth, wimax, gps, fm, | ||
| 3211 | etc. communication is blocked by default. | ||
| 3212 | 1 Unblocked. | ||
| 3213 | |||
| 3214 | rfkill.master_switch_mode= | ||
| 3215 | 0 The "airplane mode" button does nothing. | ||
| 3216 | 1 The "airplane mode" button toggles between everything | ||
| 3217 | blocked and the previous configuration. | ||
| 3218 | 2 The "airplane mode" button toggles between everything | ||
| 3219 | blocked and everything unblocked. | ||
| 3220 | |||
| 3209 | rhash_entries= [KNL,NET] | 3221 | rhash_entries= [KNL,NET] |
| 3210 | Set number of hash buckets for route cache | 3222 | Set number of hash buckets for route cache |
| 3211 | 3223 | ||
diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index 427e89712f4a..2ee6ef9a6554 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt | |||
| @@ -25,6 +25,9 @@ whether they can be changed or not: | |||
| 25 | - soft block: writable radio block (need not be readable) that is set by | 25 | - soft block: writable radio block (need not be readable) that is set by |
| 26 | the system software. | 26 | the system software. |
| 27 | 27 | ||
| 28 | The rfkill subsystem has two parameters, rfkill.default_state and | ||
| 29 | rfkill.master_switch_mode, which are documented in kernel-parameters.txt. | ||
| 30 | |||
| 28 | 31 | ||
| 29 | 2. Implementation details | 32 | 2. Implementation details |
| 30 | 33 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 33098956d930..788d3a1fc723 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -1657,7 +1657,6 @@ M: Jiri Slaby <jirislaby@gmail.com> | |||
| 1657 | M: Nick Kossifidis <mickflemm@gmail.com> | 1657 | M: Nick Kossifidis <mickflemm@gmail.com> |
| 1658 | M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> | 1658 | M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com> |
| 1659 | L: linux-wireless@vger.kernel.org | 1659 | L: linux-wireless@vger.kernel.org |
| 1660 | L: ath5k-devel@lists.ath5k.org | ||
| 1661 | W: http://wireless.kernel.org/en/users/Drivers/ath5k | 1660 | W: http://wireless.kernel.org/en/users/Drivers/ath5k |
| 1662 | S: Maintained | 1661 | S: Maintained |
| 1663 | F: drivers/net/wireless/ath/ath5k/ | 1662 | F: drivers/net/wireless/ath/ath5k/ |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 314ae4032f3e..ac6c5fca906d 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
| @@ -25,22 +25,18 @@ struct bcma_bus; | |||
| 25 | bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, | 25 | bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, |
| 26 | int timeout); | 26 | int timeout); |
| 27 | void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core); | 27 | void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core); |
| 28 | void bcma_init_bus(struct bcma_bus *bus); | ||
| 28 | int bcma_bus_register(struct bcma_bus *bus); | 29 | int bcma_bus_register(struct bcma_bus *bus); |
| 29 | void bcma_bus_unregister(struct bcma_bus *bus); | 30 | void bcma_bus_unregister(struct bcma_bus *bus); |
| 30 | int __init bcma_bus_early_register(struct bcma_bus *bus, | 31 | int __init bcma_bus_early_register(struct bcma_bus *bus); |
| 31 | struct bcma_device *core_cc, | ||
| 32 | struct bcma_device *core_mips); | ||
| 33 | #ifdef CONFIG_PM | 32 | #ifdef CONFIG_PM |
| 34 | int bcma_bus_suspend(struct bcma_bus *bus); | 33 | int bcma_bus_suspend(struct bcma_bus *bus); |
| 35 | int bcma_bus_resume(struct bcma_bus *bus); | 34 | int bcma_bus_resume(struct bcma_bus *bus); |
| 36 | #endif | 35 | #endif |
| 37 | 36 | ||
| 38 | /* scan.c */ | 37 | /* scan.c */ |
| 38 | void bcma_detect_chip(struct bcma_bus *bus); | ||
| 39 | int bcma_bus_scan(struct bcma_bus *bus); | 39 | int bcma_bus_scan(struct bcma_bus *bus); |
| 40 | int __init bcma_bus_scan_early(struct bcma_bus *bus, | ||
| 41 | struct bcma_device_id *match, | ||
| 42 | struct bcma_device *core); | ||
| 43 | void bcma_init_bus(struct bcma_bus *bus); | ||
| 44 | 40 | ||
| 45 | /* sprom.c */ | 41 | /* sprom.c */ |
| 46 | int bcma_sprom_get(struct bcma_bus *bus); | 42 | int bcma_sprom_get(struct bcma_bus *bus); |
| @@ -111,6 +107,14 @@ extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc); | |||
| 111 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 107 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE |
| 112 | bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); | 108 | bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); |
| 113 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | 109 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); |
| 110 | #else | ||
| 111 | static inline bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) | ||
| 112 | { | ||
| 113 | return false; | ||
| 114 | } | ||
| 115 | static inline void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | ||
| 116 | { | ||
| 117 | } | ||
| 114 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 118 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ |
| 115 | 119 | ||
| 116 | #ifdef CONFIG_BCMA_DRIVER_GPIO | 120 | #ifdef CONFIG_BCMA_DRIVER_GPIO |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 19f679667ca4..b7c8a8d4e6d1 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
| @@ -79,7 +79,9 @@ static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc) | |||
| 79 | 79 | ||
| 80 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | 80 | if (cc->capabilities & BCMA_CC_CAP_PMU) { |
| 81 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) | 81 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) |
| 82 | /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */ | 82 | /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP |
| 83 | * clock | ||
| 84 | */ | ||
| 83 | return bcma_chipco_get_alp_clock(cc) / 4000; | 85 | return bcma_chipco_get_alp_clock(cc) / 4000; |
| 84 | else | 86 | else |
| 85 | /* based on 32KHz ILP clock */ | 87 | /* based on 32KHz ILP clock */ |
| @@ -97,7 +99,8 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) | |||
| 97 | wdt.driver_data = cc; | 99 | wdt.driver_data = cc; |
| 98 | wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt; | 100 | wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt; |
| 99 | wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt; | 101 | wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt; |
| 100 | wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; | 102 | wdt.max_timer_ms = |
| 103 | bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; | ||
| 101 | 104 | ||
| 102 | pdev = platform_device_register_data(NULL, "bcm47xx-wdt", | 105 | pdev = platform_device_register_data(NULL, "bcm47xx-wdt", |
| 103 | cc->core->bus->num, &wdt, | 106 | cc->core->bus->num, &wdt, |
| @@ -175,7 +178,6 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |||
| 175 | u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) | 178 | u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) |
| 176 | { | 179 | { |
| 177 | u32 maxt; | 180 | u32 maxt; |
| 178 | enum bcma_clkmode clkmode; | ||
| 179 | 181 | ||
| 180 | maxt = bcma_chipco_watchdog_get_max_timer(cc); | 182 | maxt = bcma_chipco_watchdog_get_max_timer(cc); |
| 181 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | 183 | if (cc->capabilities & BCMA_CC_CAP_PMU) { |
| @@ -185,8 +187,13 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) | |||
| 185 | ticks = maxt; | 187 | ticks = maxt; |
| 186 | bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); | 188 | bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); |
| 187 | } else { | 189 | } else { |
| 188 | clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC; | 190 | struct bcma_bus *bus = cc->core->bus; |
| 189 | bcma_core_set_clockmode(cc->core, clkmode); | 191 | |
| 192 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 && | ||
| 193 | bus->chipinfo.id != BCMA_CHIP_ID_BCM53018) | ||
| 194 | bcma_core_set_clockmode(cc->core, | ||
| 195 | ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC); | ||
| 196 | |||
| 190 | if (ticks > maxt) | 197 | if (ticks > maxt) |
| 191 | ticks = maxt; | 198 | ticks = maxt; |
| 192 | /* instant NMI */ | 199 | /* instant NMI */ |
| @@ -335,7 +342,8 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) | |||
| 335 | | BCMA_CC_CORECTL_UARTCLKEN); | 342 | | BCMA_CC_CORECTL_UARTCLKEN); |
| 336 | } | 343 | } |
| 337 | } else { | 344 | } else { |
| 338 | bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev); | 345 | bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", |
| 346 | ccrev); | ||
| 339 | return; | 347 | return; |
| 340 | } | 348 | } |
| 341 | 349 | ||
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 50329d1057ed..786666488a2d 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c | |||
| @@ -145,6 +145,47 @@ static u16 bcma_pcie_mdio_writeread(struct bcma_drv_pci *pc, u16 device, | |||
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | /************************************************** | 147 | /************************************************** |
| 148 | * Early init. | ||
| 149 | **************************************************/ | ||
| 150 | |||
| 151 | static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) | ||
| 152 | { | ||
| 153 | struct bcma_device *core = pc->core; | ||
| 154 | u16 val16, core_index; | ||
| 155 | uint regoff; | ||
| 156 | |||
| 157 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); | ||
| 158 | core_index = (u16)core->core_index; | ||
| 159 | |||
| 160 | val16 = pcicore_read16(pc, regoff); | ||
| 161 | if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) | ||
| 162 | != core_index) { | ||
| 163 | val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | | ||
| 164 | (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); | ||
| 165 | pcicore_write16(pc, regoff, val16); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * Apply some early fixes required before accessing SPROM. | ||
| 171 | * See also si_pci_fixcfg. | ||
| 172 | */ | ||
| 173 | void bcma_core_pci_early_init(struct bcma_drv_pci *pc) | ||
| 174 | { | ||
| 175 | if (pc->early_setup_done) | ||
| 176 | return; | ||
| 177 | |||
| 178 | pc->hostmode = bcma_core_pci_is_in_hostmode(pc); | ||
| 179 | if (pc->hostmode) | ||
| 180 | goto out; | ||
| 181 | |||
| 182 | bcma_core_pci_fixcfg(pc); | ||
| 183 | |||
| 184 | out: | ||
| 185 | pc->early_setup_done = true; | ||
| 186 | } | ||
| 187 | |||
| 188 | /************************************************** | ||
| 148 | * Workarounds. | 189 | * Workarounds. |
| 149 | **************************************************/ | 190 | **************************************************/ |
| 150 | 191 | ||
| @@ -175,24 +216,6 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) | |||
| 175 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); | 216 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); |
| 176 | } | 217 | } |
| 177 | 218 | ||
| 178 | static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) | ||
| 179 | { | ||
| 180 | struct bcma_device *core = pc->core; | ||
| 181 | u16 val16, core_index; | ||
| 182 | uint regoff; | ||
| 183 | |||
| 184 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); | ||
| 185 | core_index = (u16)core->core_index; | ||
| 186 | |||
| 187 | val16 = pcicore_read16(pc, regoff); | ||
| 188 | if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) | ||
| 189 | != core_index) { | ||
| 190 | val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | | ||
| 191 | (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); | ||
| 192 | pcicore_write16(pc, regoff, val16); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ | 219 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ |
| 197 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | 220 | /* Needs to happen when coming out of 'standby'/'hibernate' */ |
| 198 | static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) | 221 | static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) |
| @@ -216,7 +239,6 @@ static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) | |||
| 216 | 239 | ||
| 217 | static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) | 240 | static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) |
| 218 | { | 241 | { |
| 219 | bcma_core_pci_fixcfg(pc); | ||
| 220 | bcma_pcicore_serdes_workaround(pc); | 242 | bcma_pcicore_serdes_workaround(pc); |
| 221 | bcma_core_pci_config_fixup(pc); | 243 | bcma_core_pci_config_fixup(pc); |
| 222 | } | 244 | } |
| @@ -226,13 +248,11 @@ void bcma_core_pci_init(struct bcma_drv_pci *pc) | |||
| 226 | if (pc->setup_done) | 248 | if (pc->setup_done) |
| 227 | return; | 249 | return; |
| 228 | 250 | ||
| 229 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 251 | bcma_core_pci_early_init(pc); |
| 230 | pc->hostmode = bcma_core_pci_is_in_hostmode(pc); | 252 | |
| 231 | if (pc->hostmode) | 253 | if (pc->hostmode) |
| 232 | bcma_core_pci_hostmode_init(pc); | 254 | bcma_core_pci_hostmode_init(pc); |
| 233 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 255 | else |
| 234 | |||
| 235 | if (!pc->hostmode) | ||
| 236 | bcma_core_pci_clientmode_init(pc); | 256 | bcma_core_pci_clientmode_init(pc); |
| 237 | } | 257 | } |
| 238 | 258 | ||
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index cd9161a8b3a1..53c6a8a58859 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
| @@ -13,10 +13,12 @@ | |||
| 13 | 13 | ||
| 14 | static void bcma_host_pci_switch_core(struct bcma_device *core) | 14 | static void bcma_host_pci_switch_core(struct bcma_device *core) |
| 15 | { | 15 | { |
| 16 | int win2 = core->bus->host_is_pcie2 ? | ||
| 17 | BCMA_PCIE2_BAR0_WIN2 : BCMA_PCI_BAR0_WIN2; | ||
| 18 | |||
| 16 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, | 19 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, |
| 17 | core->addr); | 20 | core->addr); |
| 18 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, | 21 | pci_write_config_dword(core->bus->host_pci, win2, core->wrap); |
| 19 | core->wrap); | ||
| 20 | core->bus->mapped_core = core; | 22 | core->bus->mapped_core = core; |
| 21 | bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); | 23 | bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); |
| 22 | } | 24 | } |
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c index 335cbcfd945b..2dce34789329 100644 --- a/drivers/bcma/host_soc.c +++ b/drivers/bcma/host_soc.c | |||
| @@ -193,7 +193,7 @@ int __init bcma_host_soc_init(struct bcma_soc *soc) | |||
| 193 | int err; | 193 | int err; |
| 194 | 194 | ||
| 195 | /* Scan bus and initialize it */ | 195 | /* Scan bus and initialize it */ |
| 196 | err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips); | 196 | err = bcma_bus_early_register(bus); |
| 197 | if (err) | 197 | if (err) |
| 198 | iounmap(bus->mmio); | 198 | iounmap(bus->mmio); |
| 199 | 199 | ||
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 534e1337766d..38bde6eab8a4 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
| @@ -268,6 +268,18 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) | |||
| 268 | } | 268 | } |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | void bcma_init_bus(struct bcma_bus *bus) | ||
| 272 | { | ||
| 273 | mutex_lock(&bcma_buses_mutex); | ||
| 274 | bus->num = bcma_bus_next_num++; | ||
| 275 | mutex_unlock(&bcma_buses_mutex); | ||
| 276 | |||
| 277 | INIT_LIST_HEAD(&bus->cores); | ||
| 278 | bus->nr_cores = 0; | ||
| 279 | |||
| 280 | bcma_detect_chip(bus); | ||
| 281 | } | ||
| 282 | |||
| 271 | static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core) | 283 | static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core) |
| 272 | { | 284 | { |
| 273 | int err; | 285 | int err; |
| @@ -356,12 +368,19 @@ static void bcma_unregister_cores(struct bcma_bus *bus) | |||
| 356 | struct bcma_device *core, *tmp; | 368 | struct bcma_device *core, *tmp; |
| 357 | 369 | ||
| 358 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { | 370 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { |
| 371 | if (!core->dev_registered) | ||
| 372 | continue; | ||
| 359 | list_del(&core->list); | 373 | list_del(&core->list); |
| 360 | if (core->dev_registered) | 374 | device_unregister(&core->dev); |
| 361 | device_unregister(&core->dev); | ||
| 362 | } | 375 | } |
| 363 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | 376 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) |
| 364 | platform_device_unregister(bus->drv_cc.watchdog); | 377 | platform_device_unregister(bus->drv_cc.watchdog); |
| 378 | |||
| 379 | /* Now noone uses internally-handled cores, we can free them */ | ||
| 380 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { | ||
| 381 | list_del(&core->list); | ||
| 382 | kfree(core); | ||
| 383 | } | ||
| 365 | } | 384 | } |
| 366 | 385 | ||
| 367 | int bcma_bus_register(struct bcma_bus *bus) | 386 | int bcma_bus_register(struct bcma_bus *bus) |
| @@ -369,10 +388,6 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
| 369 | int err; | 388 | int err; |
| 370 | struct bcma_device *core; | 389 | struct bcma_device *core; |
| 371 | 390 | ||
| 372 | mutex_lock(&bcma_buses_mutex); | ||
| 373 | bus->num = bcma_bus_next_num++; | ||
| 374 | mutex_unlock(&bcma_buses_mutex); | ||
| 375 | |||
| 376 | /* Scan for devices (cores) */ | 391 | /* Scan for devices (cores) */ |
| 377 | err = bcma_bus_scan(bus); | 392 | err = bcma_bus_scan(bus); |
| 378 | if (err) { | 393 | if (err) { |
| @@ -387,6 +402,13 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
| 387 | bcma_core_chipcommon_early_init(&bus->drv_cc); | 402 | bcma_core_chipcommon_early_init(&bus->drv_cc); |
| 388 | } | 403 | } |
| 389 | 404 | ||
| 405 | /* Early init PCIE core */ | ||
| 406 | core = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
| 407 | if (core) { | ||
| 408 | bus->drv_pci[0].core = core; | ||
| 409 | bcma_core_pci_early_init(&bus->drv_pci[0]); | ||
| 410 | } | ||
| 411 | |||
| 390 | /* Cores providing flash access go before SPROM init */ | 412 | /* Cores providing flash access go before SPROM init */ |
| 391 | list_for_each_entry(core, &bus->cores, list) { | 413 | list_for_each_entry(core, &bus->cores, list) { |
| 392 | if (bcma_is_core_needed_early(core->id.id)) | 414 | if (bcma_is_core_needed_early(core->id.id)) |
| @@ -459,7 +481,6 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
| 459 | 481 | ||
| 460 | void bcma_bus_unregister(struct bcma_bus *bus) | 482 | void bcma_bus_unregister(struct bcma_bus *bus) |
| 461 | { | 483 | { |
| 462 | struct bcma_device *cores[3]; | ||
| 463 | int err; | 484 | int err; |
| 464 | 485 | ||
| 465 | err = bcma_gpio_unregister(&bus->drv_cc); | 486 | err = bcma_gpio_unregister(&bus->drv_cc); |
| @@ -470,46 +491,23 @@ void bcma_bus_unregister(struct bcma_bus *bus) | |||
| 470 | 491 | ||
| 471 | bcma_core_chipcommon_b_free(&bus->drv_cc_b); | 492 | bcma_core_chipcommon_b_free(&bus->drv_cc_b); |
| 472 | 493 | ||
| 473 | cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | ||
| 474 | cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
| 475 | cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); | ||
| 476 | |||
| 477 | bcma_unregister_cores(bus); | 494 | bcma_unregister_cores(bus); |
| 478 | |||
| 479 | kfree(cores[2]); | ||
| 480 | kfree(cores[1]); | ||
| 481 | kfree(cores[0]); | ||
| 482 | } | 495 | } |
| 483 | 496 | ||
| 484 | int __init bcma_bus_early_register(struct bcma_bus *bus, | 497 | /* |
| 485 | struct bcma_device *core_cc, | 498 | * This is a special version of bus registration function designed for SoCs. |
| 486 | struct bcma_device *core_mips) | 499 | * It scans bus and performs basic initialization of main cores only. |
| 500 | * Please note it requires memory allocation, however it won't try to sleep. | ||
| 501 | */ | ||
| 502 | int __init bcma_bus_early_register(struct bcma_bus *bus) | ||
| 487 | { | 503 | { |
| 488 | int err; | 504 | int err; |
| 489 | struct bcma_device *core; | 505 | struct bcma_device *core; |
| 490 | struct bcma_device_id match; | ||
| 491 | 506 | ||
| 492 | match.manuf = BCMA_MANUF_BCM; | 507 | /* Scan for devices (cores) */ |
| 493 | match.id = bcma_cc_core_id(bus); | 508 | err = bcma_bus_scan(bus); |
| 494 | match.class = BCMA_CL_SIM; | ||
| 495 | match.rev = BCMA_ANY_REV; | ||
| 496 | |||
| 497 | /* Scan for chip common core */ | ||
| 498 | err = bcma_bus_scan_early(bus, &match, core_cc); | ||
| 499 | if (err) { | ||
| 500 | bcma_err(bus, "Failed to scan for common core: %d\n", err); | ||
| 501 | return -1; | ||
| 502 | } | ||
| 503 | |||
| 504 | match.manuf = BCMA_MANUF_MIPS; | ||
| 505 | match.id = BCMA_CORE_MIPS_74K; | ||
| 506 | match.class = BCMA_CL_SIM; | ||
| 507 | match.rev = BCMA_ANY_REV; | ||
| 508 | |||
| 509 | /* Scan for mips core */ | ||
| 510 | err = bcma_bus_scan_early(bus, &match, core_mips); | ||
| 511 | if (err) { | 509 | if (err) { |
| 512 | bcma_err(bus, "Failed to scan for mips core: %d\n", err); | 510 | bcma_err(bus, "Failed to scan bus: %d\n", err); |
| 513 | return -1; | 511 | return -1; |
| 514 | } | 512 | } |
| 515 | 513 | ||
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 917520776879..df806b9c5490 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
| @@ -435,15 +435,12 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, | |||
| 435 | return 0; | 435 | return 0; |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | void bcma_init_bus(struct bcma_bus *bus) | 438 | void bcma_detect_chip(struct bcma_bus *bus) |
| 439 | { | 439 | { |
| 440 | s32 tmp; | 440 | s32 tmp; |
| 441 | struct bcma_chipinfo *chipinfo = &(bus->chipinfo); | 441 | struct bcma_chipinfo *chipinfo = &(bus->chipinfo); |
| 442 | char chip_id[8]; | 442 | char chip_id[8]; |
| 443 | 443 | ||
| 444 | INIT_LIST_HEAD(&bus->cores); | ||
| 445 | bus->nr_cores = 0; | ||
| 446 | |||
| 447 | bcma_scan_switch_core(bus, BCMA_ADDR_BASE); | 444 | bcma_scan_switch_core(bus, BCMA_ADDR_BASE); |
| 448 | 445 | ||
| 449 | tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); | 446 | tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); |
| @@ -464,6 +461,10 @@ int bcma_bus_scan(struct bcma_bus *bus) | |||
| 464 | 461 | ||
| 465 | int err, core_num = 0; | 462 | int err, core_num = 0; |
| 466 | 463 | ||
| 464 | /* Skip if bus was already scanned (e.g. during early register) */ | ||
| 465 | if (bus->nr_cores) | ||
| 466 | return 0; | ||
| 467 | |||
| 467 | erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); | 468 | erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); |
| 468 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | 469 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { |
| 469 | eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); | 470 | eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); |
| @@ -522,61 +523,3 @@ out: | |||
| 522 | 523 | ||
| 523 | return err; | 524 | return err; |
| 524 | } | 525 | } |
| 525 | |||
| 526 | int __init bcma_bus_scan_early(struct bcma_bus *bus, | ||
| 527 | struct bcma_device_id *match, | ||
| 528 | struct bcma_device *core) | ||
| 529 | { | ||
| 530 | u32 erombase; | ||
| 531 | u32 __iomem *eromptr, *eromend; | ||
| 532 | |||
| 533 | int err = -ENODEV; | ||
| 534 | int core_num = 0; | ||
| 535 | |||
| 536 | erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); | ||
| 537 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | ||
| 538 | eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); | ||
| 539 | if (!eromptr) | ||
| 540 | return -ENOMEM; | ||
| 541 | } else { | ||
| 542 | eromptr = bus->mmio; | ||
| 543 | } | ||
| 544 | |||
| 545 | eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); | ||
| 546 | |||
| 547 | bcma_scan_switch_core(bus, erombase); | ||
| 548 | |||
| 549 | while (eromptr < eromend) { | ||
| 550 | memset(core, 0, sizeof(*core)); | ||
| 551 | INIT_LIST_HEAD(&core->list); | ||
| 552 | core->bus = bus; | ||
| 553 | |||
| 554 | err = bcma_get_next_core(bus, &eromptr, match, core_num, core); | ||
| 555 | if (err == -ENODEV) { | ||
| 556 | core_num++; | ||
| 557 | continue; | ||
| 558 | } else if (err == -ENXIO) | ||
| 559 | continue; | ||
| 560 | else if (err == -ESPIPE) | ||
| 561 | break; | ||
| 562 | else if (err < 0) | ||
| 563 | goto out; | ||
| 564 | |||
| 565 | core->core_index = core_num++; | ||
| 566 | bus->nr_cores++; | ||
| 567 | bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", | ||
| 568 | core->core_index, bcma_device_name(&core->id), | ||
| 569 | core->id.manuf, core->id.id, core->id.rev, | ||
| 570 | core->id.class); | ||
| 571 | |||
| 572 | list_add_tail(&core->list, &bus->cores); | ||
| 573 | err = 0; | ||
| 574 | break; | ||
| 575 | } | ||
| 576 | |||
| 577 | out: | ||
| 578 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | ||
| 579 | iounmap(eromptr); | ||
| 580 | |||
| 581 | return err; | ||
| 582 | } | ||
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index efb037f9c98a..206edd3ba668 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
| @@ -579,7 +579,8 @@ int bcma_sprom_get(struct bcma_bus *bus) | |||
| 579 | u16 offset = BCMA_CC_SPROM; | 579 | u16 offset = BCMA_CC_SPROM; |
| 580 | u16 *sprom; | 580 | u16 *sprom; |
| 581 | size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, | 581 | size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, |
| 582 | SSB_SPROMSIZE_WORDS_R10, }; | 582 | SSB_SPROMSIZE_WORDS_R10, |
| 583 | SSB_SPROMSIZE_WORDS_R11, }; | ||
| 583 | int i, err = 0; | 584 | int i, err = 0; |
| 584 | 585 | ||
| 585 | if (!bus->drv_cc.core) | 586 | if (!bus->drv_cc.core) |
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 17fcaabb2687..f07a61899545 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
| @@ -1837,6 +1837,7 @@ static int adm8211_probe(struct pci_dev *pdev, | |||
| 1837 | if (!priv->map) { | 1837 | if (!priv->map) { |
| 1838 | printk(KERN_ERR "%s (adm8211): Cannot map device memory\n", | 1838 | printk(KERN_ERR "%s (adm8211): Cannot map device memory\n", |
| 1839 | pci_name(pdev)); | 1839 | pci_name(pdev)); |
| 1840 | err = -ENOMEM; | ||
| 1840 | goto err_free_dev; | 1841 | goto err_free_dev; |
| 1841 | } | 1842 | } |
| 1842 | 1843 | ||
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index ccba4fea7269..1eebe2ea3dfb 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
| @@ -64,6 +64,7 @@ enum ath_op_flags { | |||
| 64 | ATH_OP_HW_RESET, | 64 | ATH_OP_HW_RESET, |
| 65 | ATH_OP_SCANNING, | 65 | ATH_OP_SCANNING, |
| 66 | ATH_OP_MULTI_CHANNEL, | 66 | ATH_OP_MULTI_CHANNEL, |
| 67 | ATH_OP_WOW_ENABLED, | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | enum ath_bus_type { | 70 | enum ath_bus_type { |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d0d882d632d1..1cebd3219068 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
| @@ -3078,6 +3078,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 3078 | int bit; | 3078 | int bit; |
| 3079 | u32 vdev_param; | 3079 | u32 vdev_param; |
| 3080 | 3080 | ||
| 3081 | vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; | ||
| 3082 | |||
| 3081 | mutex_lock(&ar->conf_mutex); | 3083 | mutex_lock(&ar->conf_mutex); |
| 3082 | 3084 | ||
| 3083 | memset(arvif, 0, sizeof(*arvif)); | 3085 | memset(arvif, 0, sizeof(*arvif)); |
| @@ -5336,7 +5338,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
| 5336 | ar->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 5338 | ar->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
| 5337 | IEEE80211_HW_SUPPORTS_PS | | 5339 | IEEE80211_HW_SUPPORTS_PS | |
| 5338 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 5340 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
| 5339 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
| 5340 | IEEE80211_HW_MFP_CAPABLE | | 5341 | IEEE80211_HW_MFP_CAPABLE | |
| 5341 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 5342 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
| 5342 | IEEE80211_HW_HAS_RATE_CONTROL | | 5343 | IEEE80211_HW_HAS_RATE_CONTROL | |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index fd213d9e4214..aeea1c793943 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
| @@ -1670,11 +1670,11 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) | |||
| 1670 | rx_clear_count -= ar->survey_last_rx_clear_count; | 1670 | rx_clear_count -= ar->survey_last_rx_clear_count; |
| 1671 | 1671 | ||
| 1672 | survey = &ar->survey[idx]; | 1672 | survey = &ar->survey[idx]; |
| 1673 | survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count); | 1673 | survey->time = WMI_CHAN_INFO_MSEC(cycle_count); |
| 1674 | survey->channel_time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count); | 1674 | survey->time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count); |
| 1675 | survey->noise = noise_floor; | 1675 | survey->noise = noise_floor; |
| 1676 | survey->filled = SURVEY_INFO_CHANNEL_TIME | | 1676 | survey->filled = SURVEY_INFO_TIME | |
| 1677 | SURVEY_INFO_CHANNEL_TIME_RX | | 1677 | SURVEY_INFO_TIME_RX | |
| 1678 | SURVEY_INFO_NOISE_DBM; | 1678 | SURVEY_INFO_NOISE_DBM; |
| 1679 | } | 1679 | } |
| 1680 | 1680 | ||
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 19eab2a69ad5..3b4a6463d87a 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
| @@ -672,10 +672,10 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) | |||
| 672 | spin_lock_bh(&common->cc_lock); | 672 | spin_lock_bh(&common->cc_lock); |
| 673 | ath_hw_cycle_counters_update(common); | 673 | ath_hw_cycle_counters_update(common); |
| 674 | if (cc->cycles > 0) { | 674 | if (cc->cycles > 0) { |
| 675 | ah->survey.channel_time += cc->cycles / div; | 675 | ah->survey.time += cc->cycles / div; |
| 676 | ah->survey.channel_time_busy += cc->rx_busy / div; | 676 | ah->survey.time_busy += cc->rx_busy / div; |
| 677 | ah->survey.channel_time_rx += cc->rx_frame / div; | 677 | ah->survey.time_rx += cc->rx_frame / div; |
| 678 | ah->survey.channel_time_tx += cc->tx_frame / div; | 678 | ah->survey.time_tx += cc->tx_frame / div; |
| 679 | } | 679 | } |
| 680 | memset(cc, 0, sizeof(*cc)); | 680 | memset(cc, 0, sizeof(*cc)); |
| 681 | spin_unlock_bh(&common->cc_lock); | 681 | spin_unlock_bh(&common->cc_lock); |
| @@ -686,10 +686,10 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) | |||
| 686 | survey->noise = ah->ah_noise_floor; | 686 | survey->noise = ah->ah_noise_floor; |
| 687 | survey->filled = SURVEY_INFO_NOISE_DBM | | 687 | survey->filled = SURVEY_INFO_NOISE_DBM | |
| 688 | SURVEY_INFO_IN_USE | | 688 | SURVEY_INFO_IN_USE | |
| 689 | SURVEY_INFO_CHANNEL_TIME | | 689 | SURVEY_INFO_TIME | |
| 690 | SURVEY_INFO_CHANNEL_TIME_BUSY | | 690 | SURVEY_INFO_TIME_BUSY | |
| 691 | SURVEY_INFO_CHANNEL_TIME_RX | | 691 | SURVEY_INFO_TIME_RX | |
| 692 | SURVEY_INFO_CHANNEL_TIME_TX; | 692 | SURVEY_INFO_TIME_TX; |
| 693 | 693 | ||
| 694 | return 0; | 694 | return 0; |
| 695 | } | 695 | } |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index c60d36aa13e2..bf29da5e90da 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
| @@ -912,6 +912,7 @@ ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | |||
| 912 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | 912 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
| 913 | | (ah->ah_version == AR5K_AR5210 ? | 913 | | (ah->ah_version == AR5K_AR5210 ? |
| 914 | AR5K_STA_ID1_PWR_SV : 0); | 914 | AR5K_STA_ID1_PWR_SV : 0); |
| 915 | /* fall through */ | ||
| 915 | case NL80211_IFTYPE_MONITOR: | 916 | case NL80211_IFTYPE_MONITOR: |
| 916 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | 917 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
| 917 | | (ah->ah_version == AR5K_AR5210 ? | 918 | | (ah->ah_version == AR5K_AR5210 ? |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index a3399c4f13a9..b9b651ea9851 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
| @@ -478,7 +478,7 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | |||
| 478 | regval = ioread32(reg); | 478 | regval = ioread32(reg); |
| 479 | iowrite32(regval | val, reg); | 479 | iowrite32(regval | val, reg); |
| 480 | regval = ioread32(reg); | 480 | regval = ioread32(reg); |
| 481 | usleep_range(100, 150); | 481 | udelay(100); /* NB: should be atomic */ |
| 482 | 482 | ||
| 483 | /* Bring BB/MAC out of reset */ | 483 | /* Bring BB/MAC out of reset */ |
| 484 | iowrite32(regval & ~val, reg); | 484 | iowrite32(regval & ~val, reg); |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7a5337877a0c..85da63a67faf 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
| @@ -1799,20 +1799,20 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1799 | 1799 | ||
| 1800 | if (vif->target_stats.rx_byte) { | 1800 | if (vif->target_stats.rx_byte) { |
| 1801 | sinfo->rx_bytes = vif->target_stats.rx_byte; | 1801 | sinfo->rx_bytes = vif->target_stats.rx_byte; |
| 1802 | sinfo->filled |= STATION_INFO_RX_BYTES64; | 1802 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); |
| 1803 | sinfo->rx_packets = vif->target_stats.rx_pkt; | 1803 | sinfo->rx_packets = vif->target_stats.rx_pkt; |
| 1804 | sinfo->filled |= STATION_INFO_RX_PACKETS; | 1804 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); |
| 1805 | } | 1805 | } |
| 1806 | 1806 | ||
| 1807 | if (vif->target_stats.tx_byte) { | 1807 | if (vif->target_stats.tx_byte) { |
| 1808 | sinfo->tx_bytes = vif->target_stats.tx_byte; | 1808 | sinfo->tx_bytes = vif->target_stats.tx_byte; |
| 1809 | sinfo->filled |= STATION_INFO_TX_BYTES64; | 1809 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); |
| 1810 | sinfo->tx_packets = vif->target_stats.tx_pkt; | 1810 | sinfo->tx_packets = vif->target_stats.tx_pkt; |
| 1811 | sinfo->filled |= STATION_INFO_TX_PACKETS; | 1811 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); |
| 1812 | } | 1812 | } |
| 1813 | 1813 | ||
| 1814 | sinfo->signal = vif->target_stats.cs_rssi; | 1814 | sinfo->signal = vif->target_stats.cs_rssi; |
| 1815 | sinfo->filled |= STATION_INFO_SIGNAL; | 1815 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 1816 | 1816 | ||
| 1817 | rate = vif->target_stats.tx_ucast_rate; | 1817 | rate = vif->target_stats.tx_ucast_rate; |
| 1818 | 1818 | ||
| @@ -1827,6 +1827,7 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1827 | } | 1827 | } |
| 1828 | 1828 | ||
| 1829 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | 1829 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; |
| 1830 | sinfo->txrate.bw = RATE_INFO_BW_20; | ||
| 1830 | } else if (is_rate_ht40(rate, &mcs, &sgi)) { | 1831 | } else if (is_rate_ht40(rate, &mcs, &sgi)) { |
| 1831 | if (sgi) { | 1832 | if (sgi) { |
| 1832 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | 1833 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| @@ -1835,7 +1836,7 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1835 | sinfo->txrate.mcs = mcs; | 1836 | sinfo->txrate.mcs = mcs; |
| 1836 | } | 1837 | } |
| 1837 | 1838 | ||
| 1838 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 1839 | sinfo->txrate.bw = RATE_INFO_BW_40; |
| 1839 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | 1840 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; |
| 1840 | } else { | 1841 | } else { |
| 1841 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 1842 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
| @@ -1844,12 +1845,12 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1844 | return 0; | 1845 | return 0; |
| 1845 | } | 1846 | } |
| 1846 | 1847 | ||
| 1847 | sinfo->filled |= STATION_INFO_TX_BITRATE; | 1848 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
| 1848 | 1849 | ||
| 1849 | if (test_bit(CONNECTED, &vif->flags) && | 1850 | if (test_bit(CONNECTED, &vif->flags) && |
| 1850 | test_bit(DTIM_PERIOD_AVAIL, &vif->flags) && | 1851 | test_bit(DTIM_PERIOD_AVAIL, &vif->flags) && |
| 1851 | vif->nw_type == INFRA_NETWORK) { | 1852 | vif->nw_type == INFRA_NETWORK) { |
| 1852 | sinfo->filled |= STATION_INFO_BSS_PARAM; | 1853 | sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); |
| 1853 | sinfo->bss_param.flags = 0; | 1854 | sinfo->bss_param.flags = 0; |
| 1854 | sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period; | 1855 | sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period; |
| 1855 | sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int; | 1856 | sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int; |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 933aef025698..b42ba46b5030 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
| @@ -488,7 +488,6 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, | |||
| 488 | 488 | ||
| 489 | sinfo.assoc_req_ies = ies; | 489 | sinfo.assoc_req_ies = ies; |
| 490 | sinfo.assoc_req_ies_len = ies_len; | 490 | sinfo.assoc_req_ies_len = ies_len; |
| 491 | sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; | ||
| 492 | 491 | ||
| 493 | cfg80211_new_sta(vif->ndev, mac_addr, &sinfo, GFP_KERNEL); | 492 | cfg80211_new_sta(vif->ndev, mac_addr, &sinfo, GFP_KERNEL); |
| 494 | 493 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index e000c4c27881..bd4a1a655f42 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
| @@ -43,6 +43,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = { | |||
| 43 | .name = "qca953x_wmac", | 43 | .name = "qca953x_wmac", |
| 44 | .driver_data = AR9300_DEVID_AR953X, | 44 | .driver_data = AR9300_DEVID_AR953X, |
| 45 | }, | 45 | }, |
| 46 | { | ||
| 47 | .name = "qca956x_wmac", | ||
| 48 | .driver_data = AR9300_DEVID_QCA956X, | ||
| 49 | }, | ||
| 46 | {}, | 50 | {}, |
| 47 | }; | 51 | }; |
| 48 | 52 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index ba502a2d199b..ca01d17d130f 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
| @@ -259,7 +259,8 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, | |||
| 259 | entry_cck->fir_step_level); | 259 | entry_cck->fir_step_level); |
| 260 | 260 | ||
| 261 | /* Skip MRC CCK for pre AR9003 families */ | 261 | /* Skip MRC CCK for pre AR9003 families */ |
| 262 | if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) | 262 | if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) || |
| 263 | AR_SREV_9565(ah) || AR_SREV_9561(ah)) | ||
| 263 | return; | 264 | return; |
| 264 | 265 | ||
| 265 | if (aniState->mrcCCK != entry_cck->mrc_cck_on) | 266 | if (aniState->mrcCCK != entry_cck->mrc_cck_on) |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 5829074208fa..f273427fdd29 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
| @@ -22,6 +22,21 @@ | |||
| 22 | 22 | ||
| 23 | /* All code below is for AR5008, AR9001, AR9002 */ | 23 | /* All code below is for AR5008, AR9001, AR9002 */ |
| 24 | 24 | ||
| 25 | #define AR5008_OFDM_RATES 8 | ||
| 26 | #define AR5008_HT_SS_RATES 8 | ||
| 27 | #define AR5008_HT_DS_RATES 8 | ||
| 28 | |||
| 29 | #define AR5008_HT20_SHIFT 16 | ||
| 30 | #define AR5008_HT40_SHIFT 24 | ||
| 31 | |||
| 32 | #define AR5008_11NA_OFDM_SHIFT 0 | ||
| 33 | #define AR5008_11NA_HT_SS_SHIFT 8 | ||
| 34 | #define AR5008_11NA_HT_DS_SHIFT 16 | ||
| 35 | |||
| 36 | #define AR5008_11NG_OFDM_SHIFT 4 | ||
| 37 | #define AR5008_11NG_HT_SS_SHIFT 12 | ||
| 38 | #define AR5008_11NG_HT_DS_SHIFT 20 | ||
| 39 | |||
| 25 | static const int firstep_table[] = | 40 | static const int firstep_table[] = |
| 26 | /* level: 0 1 2 3 4 5 6 7 8 */ | 41 | /* level: 0 1 2 3 4 5 6 7 8 */ |
| 27 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ | 42 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ |
| @@ -1235,6 +1250,71 @@ static void ar5008_hw_set_radar_conf(struct ath_hw *ah) | |||
| 1235 | conf->radar_inband = 8; | 1250 | conf->radar_inband = 8; |
| 1236 | } | 1251 | } |
| 1237 | 1252 | ||
| 1253 | static void ar5008_hw_init_txpower_cck(struct ath_hw *ah, int16_t *rate_array) | ||
| 1254 | { | ||
| 1255 | #define CCK_DELTA(x) ((OLC_FOR_AR9280_20_LATER) ? max((x) - 2, 0) : (x)) | ||
| 1256 | ah->tx_power[0] = CCK_DELTA(rate_array[rate1l]); | ||
| 1257 | ah->tx_power[1] = CCK_DELTA(min(rate_array[rate2l], | ||
| 1258 | rate_array[rate2s])); | ||
| 1259 | ah->tx_power[2] = CCK_DELTA(min(rate_array[rate5_5l], | ||
| 1260 | rate_array[rate5_5s])); | ||
| 1261 | ah->tx_power[3] = CCK_DELTA(min(rate_array[rate11l], | ||
| 1262 | rate_array[rate11s])); | ||
| 1263 | #undef CCK_DELTA | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | static void ar5008_hw_init_txpower_ofdm(struct ath_hw *ah, int16_t *rate_array, | ||
| 1267 | int offset) | ||
| 1268 | { | ||
| 1269 | int i, idx = 0; | ||
| 1270 | |||
| 1271 | for (i = offset; i < offset + AR5008_OFDM_RATES; i++) { | ||
| 1272 | ah->tx_power[i] = rate_array[idx]; | ||
| 1273 | idx++; | ||
| 1274 | } | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | static void ar5008_hw_init_txpower_ht(struct ath_hw *ah, int16_t *rate_array, | ||
| 1278 | int ss_offset, int ds_offset, | ||
| 1279 | bool is_40, int ht40_delta) | ||
| 1280 | { | ||
| 1281 | int i, mcs_idx = (is_40) ? AR5008_HT40_SHIFT : AR5008_HT20_SHIFT; | ||
| 1282 | |||
| 1283 | for (i = ss_offset; i < ss_offset + AR5008_HT_SS_RATES; i++) { | ||
| 1284 | ah->tx_power[i] = rate_array[mcs_idx] + ht40_delta; | ||
| 1285 | mcs_idx++; | ||
| 1286 | } | ||
| 1287 | memcpy(&ah->tx_power[ds_offset], &ah->tx_power[ss_offset], | ||
| 1288 | AR5008_HT_SS_RATES); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | void ar5008_hw_init_rate_txpower(struct ath_hw *ah, int16_t *rate_array, | ||
| 1292 | struct ath9k_channel *chan, int ht40_delta) | ||
| 1293 | { | ||
| 1294 | if (IS_CHAN_5GHZ(chan)) { | ||
| 1295 | ar5008_hw_init_txpower_ofdm(ah, rate_array, | ||
| 1296 | AR5008_11NA_OFDM_SHIFT); | ||
| 1297 | if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) { | ||
| 1298 | ar5008_hw_init_txpower_ht(ah, rate_array, | ||
| 1299 | AR5008_11NA_HT_SS_SHIFT, | ||
| 1300 | AR5008_11NA_HT_DS_SHIFT, | ||
| 1301 | IS_CHAN_HT40(chan), | ||
| 1302 | ht40_delta); | ||
| 1303 | } | ||
| 1304 | } else { | ||
| 1305 | ar5008_hw_init_txpower_cck(ah, rate_array); | ||
| 1306 | ar5008_hw_init_txpower_ofdm(ah, rate_array, | ||
| 1307 | AR5008_11NG_OFDM_SHIFT); | ||
| 1308 | if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) { | ||
| 1309 | ar5008_hw_init_txpower_ht(ah, rate_array, | ||
| 1310 | AR5008_11NG_HT_SS_SHIFT, | ||
| 1311 | AR5008_11NG_HT_DS_SHIFT, | ||
| 1312 | IS_CHAN_HT40(chan), | ||
| 1313 | ht40_delta); | ||
| 1314 | } | ||
| 1315 | } | ||
| 1316 | } | ||
| 1317 | |||
| 1238 | int ar5008_hw_attach_phy_ops(struct ath_hw *ah) | 1318 | int ar5008_hw_attach_phy_ops(struct ath_hw *ah) |
| 1239 | { | 1319 | { |
| 1240 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1320 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 06ab71db6e80..174442beb952 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
| @@ -1203,24 +1203,41 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) | |||
| 1203 | static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | 1203 | static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) |
| 1204 | { | 1204 | { |
| 1205 | int offset[8] = {0}, total = 0, test; | 1205 | int offset[8] = {0}, total = 0, test; |
| 1206 | int agc_out, i; | 1206 | int agc_out, i, peak_detect_threshold; |
| 1207 | 1207 | ||
| 1208 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) | ||
| 1209 | peak_detect_threshold = 8; | ||
| 1210 | else | ||
| 1211 | peak_detect_threshold = 0; | ||
| 1212 | |||
| 1213 | /* | ||
| 1214 | * Turn off LNA/SW. | ||
| 1215 | */ | ||
| 1208 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | 1216 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), |
| 1209 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1); | 1217 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1); |
| 1210 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | 1218 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), |
| 1211 | AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0); | 1219 | AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0); |
| 1212 | if (is_2g) | ||
| 1213 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
| 1214 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0); | ||
| 1215 | else | ||
| 1216 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
| 1217 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0); | ||
| 1218 | 1220 | ||
| 1221 | if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9330_11(ah)) { | ||
| 1222 | if (is_2g) | ||
| 1223 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
| 1224 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0); | ||
| 1225 | else | ||
| 1226 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | ||
| 1227 | AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | /* | ||
| 1231 | * Turn off RXON. | ||
| 1232 | */ | ||
| 1219 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), | 1233 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), |
| 1220 | AR_PHY_65NM_RXTX2_RXON_OVR, 0x1); | 1234 | AR_PHY_65NM_RXTX2_RXON_OVR, 0x1); |
| 1221 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), | 1235 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), |
| 1222 | AR_PHY_65NM_RXTX2_RXON, 0x0); | 1236 | AR_PHY_65NM_RXTX2_RXON, 0x0); |
| 1223 | 1237 | ||
| 1238 | /* | ||
| 1239 | * Turn on AGC for cal. | ||
| 1240 | */ | ||
| 1224 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1241 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| 1225 | AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1); | 1242 | AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1); |
| 1226 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1243 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| @@ -1228,16 +1245,19 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | |||
| 1228 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1245 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| 1229 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1); | 1246 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1); |
| 1230 | 1247 | ||
| 1231 | if (AR_SREV_9330_11(ah)) { | 1248 | if (AR_SREV_9330_11(ah)) |
| 1232 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1249 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| 1233 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); | 1250 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); |
| 1234 | } else { | 1251 | |
| 1252 | if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | ||
| 1235 | if (is_2g) | 1253 | if (is_2g) |
| 1236 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1254 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| 1237 | AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0); | 1255 | AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, |
| 1256 | peak_detect_threshold); | ||
| 1238 | else | 1257 | else |
| 1239 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1258 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| 1240 | AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0); | 1259 | AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, |
| 1260 | peak_detect_threshold); | ||
| 1241 | } | 1261 | } |
| 1242 | 1262 | ||
| 1243 | for (i = 6; i > 0; i--) { | 1263 | for (i = 6; i > 0; i--) { |
| @@ -1266,10 +1286,19 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | |||
| 1266 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1286 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| 1267 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total); | 1287 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total); |
| 1268 | 1288 | ||
| 1289 | /* | ||
| 1290 | * Turn on LNA. | ||
| 1291 | */ | ||
| 1269 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), | 1292 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), |
| 1270 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0); | 1293 | AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0); |
| 1294 | /* | ||
| 1295 | * Turn off RXON. | ||
| 1296 | */ | ||
| 1271 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), | 1297 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), |
| 1272 | AR_PHY_65NM_RXTX2_RXON_OVR, 0); | 1298 | AR_PHY_65NM_RXTX2_RXON_OVR, 0); |
| 1299 | /* | ||
| 1300 | * Turn off peak detect calibration. | ||
| 1301 | */ | ||
| 1273 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | 1302 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), |
| 1274 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); | 1303 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); |
| 1275 | } | 1304 | } |
| @@ -1611,8 +1640,14 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, | |||
| 1611 | 1640 | ||
| 1612 | skip_tx_iqcal: | 1641 | skip_tx_iqcal: |
| 1613 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { | 1642 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { |
| 1614 | if (AR_SREV_9330_11(ah)) | 1643 | if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { |
| 1615 | ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); | 1644 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
| 1645 | if (!(ah->rxchainmask & (1 << i))) | ||
| 1646 | continue; | ||
| 1647 | ar9003_hw_manual_peak_cal(ah, i, | ||
| 1648 | IS_CHAN_2GHZ(chan)); | ||
| 1649 | } | ||
| 1650 | } | ||
| 1616 | 1651 | ||
| 1617 | /* | 1652 | /* |
| 1618 | * For non-AR9550 chips, we just trigger AGC calibration | 1653 | * For non-AR9550 chips, we just trigger AGC calibration |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 08225a0067c2..8b4561e8ce1a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
| @@ -3536,7 +3536,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) | |||
| 3536 | int bias = ar9003_modal_header(ah, is2ghz)->xpaBiasLvl; | 3536 | int bias = ar9003_modal_header(ah, is2ghz)->xpaBiasLvl; |
| 3537 | 3537 | ||
| 3538 | if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah) || | 3538 | if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah) || |
| 3539 | AR_SREV_9531(ah)) | 3539 | AR_SREV_9531(ah) || AR_SREV_9561(ah)) |
| 3540 | REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); | 3540 | REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); |
| 3541 | else if (AR_SREV_9462(ah) || AR_SREV_9550(ah) || AR_SREV_9565(ah)) | 3541 | else if (AR_SREV_9462(ah) || AR_SREV_9550(ah) || AR_SREV_9565(ah)) |
| 3542 | REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); | 3542 | REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); |
| @@ -3599,7 +3599,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
| 3599 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | 3599 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { |
| 3600 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, | 3600 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, |
| 3601 | AR_SWITCH_TABLE_COM_AR9462_ALL, value); | 3601 | AR_SWITCH_TABLE_COM_AR9462_ALL, value); |
| 3602 | } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | 3602 | } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) { |
| 3603 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, | 3603 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, |
| 3604 | AR_SWITCH_TABLE_COM_AR9550_ALL, value); | 3604 | AR_SWITCH_TABLE_COM_AR9550_ALL, value); |
| 3605 | } else | 3605 | } else |
| @@ -3929,9 +3929,13 @@ void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) | |||
| 3929 | REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); | 3929 | REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); |
| 3930 | if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) | 3930 | if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) |
| 3931 | return; | 3931 | return; |
| 3932 | } else if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | 3932 | } else if (AR_SREV_9462(ah) || AR_SREV_9565(ah) || |
| 3933 | AR_SREV_9561(ah)) { | ||
| 3933 | reg_val = le32_to_cpu(pBase->swreg); | 3934 | reg_val = le32_to_cpu(pBase->swreg); |
| 3934 | REG_WRITE(ah, AR_PHY_PMU1, reg_val); | 3935 | REG_WRITE(ah, AR_PHY_PMU1, reg_val); |
| 3936 | |||
| 3937 | if (AR_SREV_9561(ah)) | ||
| 3938 | REG_WRITE(ah, AR_PHY_PMU2, 0x10200000); | ||
| 3935 | } else { | 3939 | } else { |
| 3936 | /* Internal regulator is ON. Write swreg register. */ | 3940 | /* Internal regulator is ON. Write swreg register. */ |
| 3937 | reg_val = le32_to_cpu(pBase->swreg); | 3941 | reg_val = le32_to_cpu(pBase->swreg); |
| @@ -4034,7 +4038,8 @@ static void ar9003_hw_xpa_timing_control_apply(struct ath_hw *ah, bool is2ghz) | |||
| 4034 | if (!AR_SREV_9300(ah) && | 4038 | if (!AR_SREV_9300(ah) && |
| 4035 | !AR_SREV_9340(ah) && | 4039 | !AR_SREV_9340(ah) && |
| 4036 | !AR_SREV_9580(ah) && | 4040 | !AR_SREV_9580(ah) && |
| 4037 | !AR_SREV_9531(ah)) | 4041 | !AR_SREV_9531(ah) && |
| 4042 | !AR_SREV_9561(ah)) | ||
| 4038 | return; | 4043 | return; |
| 4039 | 4044 | ||
| 4040 | xpa_ctl = ar9003_modal_header(ah, is2ghz)->txFrameToXpaOn; | 4045 | xpa_ctl = ar9003_modal_header(ah, is2ghz)->txFrameToXpaOn; |
| @@ -4812,7 +4817,7 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah, | |||
| 4812 | } | 4817 | } |
| 4813 | 4818 | ||
| 4814 | tempslope: | 4819 | tempslope: |
| 4815 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | 4820 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) { |
| 4816 | u8 txmask = (eep->baseEepHeader.txrxMask & 0xf0) >> 4; | 4821 | u8 txmask = (eep->baseEepHeader.txrxMask & 0xf0) >> 4; |
| 4817 | 4822 | ||
| 4818 | /* | 4823 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 06ad2172030e..4335ccbe7d7e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "ar9565_1p0_initvals.h" | 29 | #include "ar9565_1p0_initvals.h" |
| 30 | #include "ar9565_1p1_initvals.h" | 30 | #include "ar9565_1p1_initvals.h" |
| 31 | #include "ar953x_initvals.h" | 31 | #include "ar953x_initvals.h" |
| 32 | #include "ar956x_initvals.h" | ||
| 32 | 33 | ||
| 33 | /* General hardware code for the AR9003 hadware family */ | 34 | /* General hardware code for the AR9003 hadware family */ |
| 34 | 35 | ||
| @@ -358,6 +359,40 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
| 358 | 359 | ||
| 359 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 360 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
| 360 | qca953x_1p0_modes_fast_clock); | 361 | qca953x_1p0_modes_fast_clock); |
| 362 | } else if (AR_SREV_9561(ah)) { | ||
| 363 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
| 364 | qca956x_1p0_mac_core); | ||
| 365 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
| 366 | qca956x_1p0_mac_postamble); | ||
| 367 | |||
| 368 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
| 369 | qca956x_1p0_baseband_core); | ||
| 370 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
| 371 | qca956x_1p0_baseband_postamble); | ||
| 372 | |||
| 373 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
| 374 | qca956x_1p0_radio_core); | ||
| 375 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
| 376 | qca956x_1p0_radio_postamble); | ||
| 377 | |||
| 378 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
| 379 | qca956x_1p0_soc_preamble); | ||
| 380 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
| 381 | qca956x_1p0_soc_postamble); | ||
| 382 | |||
| 383 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
| 384 | qca956x_1p0_common_wo_xlna_rx_gain_table); | ||
| 385 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
| 386 | qca956x_1p0_common_wo_xlna_rx_gain_bounds); | ||
| 387 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 388 | qca956x_1p0_modes_no_xpa_tx_gain_table); | ||
| 389 | |||
| 390 | INIT_INI_ARRAY(&ah->ini_dfs, | ||
| 391 | qca956x_1p0_baseband_postamble_dfs_channel); | ||
| 392 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | ||
| 393 | qca956x_1p0_baseband_core_txfir_coeff_japan_2484); | ||
| 394 | INIT_INI_ARRAY(&ah->iniModesFastClock, | ||
| 395 | qca956x_1p0_modes_fast_clock); | ||
| 361 | } else if (AR_SREV_9580(ah)) { | 396 | } else if (AR_SREV_9580(ah)) { |
| 362 | /* mac */ | 397 | /* mac */ |
| 363 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | 398 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], |
| @@ -544,6 +579,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) | |||
| 544 | else if (AR_SREV_9531_20(ah)) | 579 | else if (AR_SREV_9531_20(ah)) |
| 545 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 580 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 546 | qca953x_2p0_modes_xpa_tx_gain_table); | 581 | qca953x_2p0_modes_xpa_tx_gain_table); |
| 582 | else if (AR_SREV_9561(ah)) | ||
| 583 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 584 | qca956x_1p0_modes_xpa_tx_gain_table); | ||
| 547 | else if (AR_SREV_9580(ah)) | 585 | else if (AR_SREV_9580(ah)) |
| 548 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 586 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 549 | ar9580_1p0_lowest_ob_db_tx_gain_table); | 587 | ar9580_1p0_lowest_ob_db_tx_gain_table); |
| @@ -594,7 +632,10 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) | |||
| 594 | else | 632 | else |
| 595 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 633 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 596 | qca953x_1p0_modes_no_xpa_tx_gain_table); | 634 | qca953x_1p0_modes_no_xpa_tx_gain_table); |
| 597 | } else if (AR_SREV_9462_21(ah)) | 635 | } else if (AR_SREV_9561(ah)) |
| 636 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 637 | qca956x_1p0_modes_no_xpa_tx_gain_table); | ||
| 638 | else if (AR_SREV_9462_21(ah)) | ||
| 598 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 639 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 599 | ar9462_2p1_modes_high_ob_db_tx_gain); | 640 | ar9462_2p1_modes_high_ob_db_tx_gain); |
| 600 | else if (AR_SREV_9462_20(ah)) | 641 | else if (AR_SREV_9462_20(ah)) |
| @@ -628,6 +669,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah) | |||
| 628 | else if (AR_SREV_9580(ah)) | 669 | else if (AR_SREV_9580(ah)) |
| 629 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 670 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 630 | ar9580_1p0_low_ob_db_tx_gain_table); | 671 | ar9580_1p0_low_ob_db_tx_gain_table); |
| 672 | else if (AR_SREV_9561(ah)) | ||
| 673 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 674 | qca956x_1p0_modes_no_xpa_low_ob_db_tx_gain_table); | ||
| 631 | else if (AR_SREV_9565_11(ah)) | 675 | else if (AR_SREV_9565_11(ah)) |
| 632 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 676 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 633 | ar9565_1p1_modes_low_ob_db_tx_gain_table); | 677 | ar9565_1p1_modes_low_ob_db_tx_gain_table); |
| @@ -699,6 +743,9 @@ static void ar9003_tx_gain_table_mode5(struct ath_hw *ah) | |||
| 699 | else if (AR_SREV_9580(ah)) | 743 | else if (AR_SREV_9580(ah)) |
| 700 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 744 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 701 | ar9580_1p0_type5_tx_gain_table); | 745 | ar9580_1p0_type5_tx_gain_table); |
| 746 | else if (AR_SREV_9561(ah)) | ||
| 747 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
| 748 | qca956x_1p0_modes_no_xpa_green_tx_gain_table); | ||
| 702 | else if (AR_SREV_9300_22(ah)) | 749 | else if (AR_SREV_9300_22(ah)) |
| 703 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 750 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 704 | ar9300Modes_type5_tx_gain_table_2p2); | 751 | ar9300Modes_type5_tx_gain_table_2p2); |
| @@ -770,6 +817,13 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) | |||
| 770 | qca953x_1p0_common_rx_gain_table); | 817 | qca953x_1p0_common_rx_gain_table); |
| 771 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | 818 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, |
| 772 | qca953x_1p0_common_rx_gain_bounds); | 819 | qca953x_1p0_common_rx_gain_bounds); |
| 820 | } else if (AR_SREV_9561(ah)) { | ||
| 821 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
| 822 | qca956x_1p0_common_rx_gain_table); | ||
| 823 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
| 824 | qca956x_1p0_common_rx_gain_bounds); | ||
| 825 | INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, | ||
| 826 | qca956x_1p0_xlna_only); | ||
| 773 | } else if (AR_SREV_9580(ah)) | 827 | } else if (AR_SREV_9580(ah)) |
| 774 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 828 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 775 | ar9580_1p0_rx_gain_table); | 829 | ar9580_1p0_rx_gain_table); |
| @@ -825,6 +879,11 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) | |||
| 825 | qca953x_2p0_common_wo_xlna_rx_gain_table); | 879 | qca953x_2p0_common_wo_xlna_rx_gain_table); |
| 826 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | 880 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, |
| 827 | qca953x_2p0_common_wo_xlna_rx_gain_bounds); | 881 | qca953x_2p0_common_wo_xlna_rx_gain_bounds); |
| 882 | } else if (AR_SREV_9561(ah)) { | ||
| 883 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
| 884 | qca956x_1p0_common_wo_xlna_rx_gain_table); | ||
| 885 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
| 886 | qca956x_1p0_common_wo_xlna_rx_gain_bounds); | ||
| 828 | } else if (AR_SREV_9580(ah)) | 887 | } else if (AR_SREV_9580(ah)) |
| 829 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 888 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 830 | ar9580_1p0_wo_xlna_rx_gain_table); | 889 | ar9580_1p0_wo_xlna_rx_gain_table); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index ae6cde273414..1ad66b76749b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
| @@ -183,7 +183,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 183 | } else { | 183 | } else { |
| 184 | channelSel = CHANSEL_2G(freq) >> 1; | 184 | channelSel = CHANSEL_2G(freq) >> 1; |
| 185 | } | 185 | } |
| 186 | } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | 186 | } else if (AR_SREV_9550(ah) || AR_SREV_9531(ah) || |
| 187 | AR_SREV_9561(ah)) { | ||
| 187 | if (ah->is_clk_25mhz) | 188 | if (ah->is_clk_25mhz) |
| 188 | div = 75; | 189 | div = 75; |
| 189 | else | 190 | else |
| @@ -198,7 +199,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 198 | /* Set to 2G mode */ | 199 | /* Set to 2G mode */ |
| 199 | bMode = 1; | 200 | bMode = 1; |
| 200 | } else { | 201 | } else { |
| 201 | if ((AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) && | 202 | if ((AR_SREV_9340(ah) || AR_SREV_9550(ah) || |
| 203 | AR_SREV_9531(ah) || AR_SREV_9561(ah)) && | ||
| 202 | ah->is_clk_25mhz) { | 204 | ah->is_clk_25mhz) { |
| 203 | channelSel = freq / 75; | 205 | channelSel = freq / 75; |
| 204 | chan_frac = ((freq % 75) * 0x20000) / 75; | 206 | chan_frac = ((freq % 75) * 0x20000) / 75; |
| @@ -265,7 +267,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, | |||
| 265 | */ | 267 | */ |
| 266 | 268 | ||
| 267 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || | 269 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || |
| 268 | AR_SREV_9550(ah)) { | 270 | AR_SREV_9550(ah) || AR_SREV_9561(ah)) { |
| 269 | if (spur_fbin_ptr[0] == 0) /* No spur */ | 271 | if (spur_fbin_ptr[0] == 0) /* No spur */ |
| 270 | return; | 272 | return; |
| 271 | max_spur_cnts = 5; | 273 | max_spur_cnts = 5; |
| @@ -292,7 +294,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, | |||
| 292 | 294 | ||
| 293 | negative = 0; | 295 | negative = 0; |
| 294 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || | 296 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || |
| 295 | AR_SREV_9550(ah)) | 297 | AR_SREV_9550(ah) || AR_SREV_9561(ah)) |
| 296 | cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i], | 298 | cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i], |
| 297 | IS_CHAN_2GHZ(chan)); | 299 | IS_CHAN_2GHZ(chan)); |
| 298 | else | 300 | else |
| @@ -641,8 +643,10 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, | |||
| 641 | (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO); | 643 | (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO); |
| 642 | 644 | ||
| 643 | /* Enable 11n HT, 20 MHz */ | 645 | /* Enable 11n HT, 20 MHz */ |
| 644 | phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | | 646 | phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SHORT_GI_40 | enableDacFifo; |
| 645 | AR_PHY_GC_SHORT_GI_40 | enableDacFifo; | 647 | |
| 648 | if (!AR_SREV_9561(ah)) | ||
| 649 | phymode |= AR_PHY_GC_SINGLE_HT_LTF1; | ||
| 646 | 650 | ||
| 647 | /* Configure baseband for dynamic 20/40 operation */ | 651 | /* Configure baseband for dynamic 20/40 operation */ |
| 648 | if (IS_CHAN_HT40(chan)) { | 652 | if (IS_CHAN_HT40(chan)) { |
| @@ -745,7 +749,8 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) | |||
| 745 | else | 749 | else |
| 746 | ah->enabled_cals &= ~TX_CL_CAL; | 750 | ah->enabled_cals &= ~TX_CL_CAL; |
| 747 | 751 | ||
| 748 | if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { | 752 | if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) || |
| 753 | AR_SREV_9561(ah)) { | ||
| 749 | if (ah->is_clk_25mhz) { | 754 | if (ah->is_clk_25mhz) { |
| 750 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); | 755 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); |
| 751 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); | 756 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); |
| @@ -812,6 +817,19 @@ static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah, | |||
| 812 | return ret; | 817 | return ret; |
| 813 | } | 818 | } |
| 814 | 819 | ||
| 820 | static int ar9561_hw_get_modes_txgain_index(struct ath_hw *ah, | ||
| 821 | struct ath9k_channel *chan) | ||
| 822 | { | ||
| 823 | if (IS_CHAN_2GHZ(chan)) { | ||
| 824 | if (IS_CHAN_HT40(chan)) | ||
| 825 | return 1; | ||
| 826 | else | ||
| 827 | return 2; | ||
| 828 | } | ||
| 829 | |||
| 830 | return 0; | ||
| 831 | } | ||
| 832 | |||
| 815 | static void ar9003_doubler_fix(struct ath_hw *ah) | 833 | static void ar9003_doubler_fix(struct ath_hw *ah) |
| 816 | { | 834 | { |
| 817 | if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { | 835 | if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { |
| @@ -911,21 +929,29 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
| 911 | REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, | 929 | REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, |
| 912 | modesIndex, regWrites); | 930 | modesIndex, regWrites); |
| 913 | } | 931 | } |
| 932 | |||
| 933 | if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) | ||
| 934 | REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, | ||
| 935 | modesIndex, regWrites); | ||
| 914 | } | 936 | } |
| 915 | 937 | ||
| 916 | if (AR_SREV_9550(ah)) | 938 | if (AR_SREV_9550(ah) || AR_SREV_9561(ah)) |
| 917 | REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex, | 939 | REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex, |
| 918 | regWrites); | 940 | regWrites); |
| 919 | 941 | ||
| 920 | /* | 942 | /* |
| 921 | * TXGAIN initvals. | 943 | * TXGAIN initvals. |
| 922 | */ | 944 | */ |
| 923 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | 945 | if (AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) { |
| 924 | int modes_txgain_index = 1; | 946 | int modes_txgain_index = 1; |
| 925 | 947 | ||
| 926 | if (AR_SREV_9550(ah)) | 948 | if (AR_SREV_9550(ah)) |
| 927 | modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan); | 949 | modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan); |
| 928 | 950 | ||
| 951 | if (AR_SREV_9561(ah)) | ||
| 952 | modes_txgain_index = | ||
| 953 | ar9561_hw_get_modes_txgain_index(ah, chan); | ||
| 954 | |||
| 929 | if (modes_txgain_index < 0) | 955 | if (modes_txgain_index < 0) |
| 930 | return -EINVAL; | 956 | return -EINVAL; |
| 931 | 957 | ||
| @@ -1989,7 +2015,8 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
| 1989 | priv_ops->rf_set_freq = ar9003_hw_set_channel; | 2015 | priv_ops->rf_set_freq = ar9003_hw_set_channel; |
| 1990 | priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate; | 2016 | priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate; |
| 1991 | 2017 | ||
| 1992 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) | 2018 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || |
| 2019 | AR_SREV_9561(ah)) | ||
| 1993 | priv_ops->compute_pll_control = ar9003_hw_compute_pll_control_soc; | 2020 | priv_ops->compute_pll_control = ar9003_hw_compute_pll_control_soc; |
| 1994 | else | 2021 | else |
| 1995 | priv_ops->compute_pll_control = ar9003_hw_compute_pll_control; | 2022 | priv_ops->compute_pll_control = ar9003_hw_compute_pll_control; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index fd090b1f2d0f..c311b2bfdb00 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
| @@ -454,7 +454,7 @@ | |||
| 454 | #define AR_PHY_GEN_CTRL (AR_SM_BASE + 0x4) | 454 | #define AR_PHY_GEN_CTRL (AR_SM_BASE + 0x4) |
| 455 | #define AR_PHY_MODE (AR_SM_BASE + 0x8) | 455 | #define AR_PHY_MODE (AR_SM_BASE + 0x8) |
| 456 | #define AR_PHY_ACTIVE (AR_SM_BASE + 0xc) | 456 | #define AR_PHY_ACTIVE (AR_SM_BASE + 0xc) |
| 457 | #define AR_PHY_SPUR_MASK_A (AR_SM_BASE + 0x20) | 457 | #define AR_PHY_SPUR_MASK_A (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x18 : 0x20)) |
| 458 | #define AR_PHY_SPUR_MASK_B (AR_SM_BASE + 0x24) | 458 | #define AR_PHY_SPUR_MASK_B (AR_SM_BASE + 0x24) |
| 459 | #define AR_PHY_SPECTRAL_SCAN (AR_SM_BASE + 0x28) | 459 | #define AR_PHY_SPECTRAL_SCAN (AR_SM_BASE + 0x28) |
| 460 | #define AR_PHY_RADAR_BW_FILTER (AR_SM_BASE + 0x2c) | 460 | #define AR_PHY_RADAR_BW_FILTER (AR_SM_BASE + 0x2c) |
| @@ -506,7 +506,7 @@ | |||
| 506 | #define AR_PHY_TEST_CHAIN_SEL 0xC0000000 | 506 | #define AR_PHY_TEST_CHAIN_SEL 0xC0000000 |
| 507 | #define AR_PHY_TEST_CHAIN_SEL_S 30 | 507 | #define AR_PHY_TEST_CHAIN_SEL_S 30 |
| 508 | 508 | ||
| 509 | #define AR_PHY_TEST_CTL_STATUS (AR_SM_BASE + 0x164) | 509 | #define AR_PHY_TEST_CTL_STATUS (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x160 : 0x164)) |
| 510 | #define AR_PHY_TEST_CTL_TSTDAC_EN 0x1 | 510 | #define AR_PHY_TEST_CTL_TSTDAC_EN 0x1 |
| 511 | #define AR_PHY_TEST_CTL_TSTDAC_EN_S 0 | 511 | #define AR_PHY_TEST_CTL_TSTDAC_EN_S 0 |
| 512 | #define AR_PHY_TEST_CTL_TX_OBS_SEL 0x1C | 512 | #define AR_PHY_TEST_CTL_TX_OBS_SEL 0x1C |
| @@ -525,7 +525,7 @@ | |||
| 525 | 525 | ||
| 526 | #define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) | 526 | #define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) |
| 527 | 527 | ||
| 528 | #define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) | 528 | #define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x16c : 0x170)) |
| 529 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ 0x00000008 | 529 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ 0x00000008 |
| 530 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S 3 | 530 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S 3 |
| 531 | 531 | ||
| @@ -536,7 +536,7 @@ | |||
| 536 | #define AR_PHY_SCRAMBLER_SEED (AR_SM_BASE + 0x190) | 536 | #define AR_PHY_SCRAMBLER_SEED (AR_SM_BASE + 0x190) |
| 537 | #define AR_PHY_CCK_TX_CTRL (AR_SM_BASE + 0x194) | 537 | #define AR_PHY_CCK_TX_CTRL (AR_SM_BASE + 0x194) |
| 538 | 538 | ||
| 539 | #define AR_PHY_HEAVYCLIP_CTL (AR_SM_BASE + 0x1a4) | 539 | #define AR_PHY_HEAVYCLIP_CTL (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x198 : 0x1a4)) |
| 540 | #define AR_PHY_HEAVYCLIP_20 (AR_SM_BASE + 0x1a8) | 540 | #define AR_PHY_HEAVYCLIP_20 (AR_SM_BASE + 0x1a8) |
| 541 | #define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac) | 541 | #define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac) |
| 542 | #define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0) | 542 | #define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0) |
| @@ -726,21 +726,24 @@ | |||
| 726 | 726 | ||
| 727 | #define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \ | 727 | #define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \ |
| 728 | (AR_SREV_9462(ah) ? 0x16290 : 0x16284)) | 728 | (AR_SREV_9462(ah) ? 0x16290 : 0x16284)) |
| 729 | #define AR_CH0_TOP2_XPABIASLVL 0xf000 | 729 | #define AR_CH0_TOP2_XPABIASLVL (AR_SREV_9561(ah) ? 0x1e00 : 0xf000) |
| 730 | #define AR_CH0_TOP2_XPABIASLVL_S 12 | 730 | #define AR_CH0_TOP2_XPABIASLVL_S 12 |
| 731 | 731 | ||
| 732 | #define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \ | 732 | #define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \ |
| 733 | ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16298 : 0x16290)) | 733 | ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16298 : \ |
| 734 | (AR_SREV_9561(ah) ? 0x162c0 : 0x16290))) | ||
| 734 | #define AR_CH0_XTAL_CAPINDAC 0x7f000000 | 735 | #define AR_CH0_XTAL_CAPINDAC 0x7f000000 |
| 735 | #define AR_CH0_XTAL_CAPINDAC_S 24 | 736 | #define AR_CH0_XTAL_CAPINDAC_S 24 |
| 736 | #define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000 | 737 | #define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000 |
| 737 | #define AR_CH0_XTAL_CAPOUTDAC_S 17 | 738 | #define AR_CH0_XTAL_CAPOUTDAC_S 17 |
| 738 | 739 | ||
| 739 | #define AR_PHY_PMU1 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16340 : 0x16c40) | 740 | #define AR_PHY_PMU1 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16340 : \ |
| 741 | (AR_SREV_9561(ah) ? 0x16cc0 : 0x16c40)) | ||
| 740 | #define AR_PHY_PMU1_PWD 0x1 | 742 | #define AR_PHY_PMU1_PWD 0x1 |
| 741 | #define AR_PHY_PMU1_PWD_S 0 | 743 | #define AR_PHY_PMU1_PWD_S 0 |
| 742 | 744 | ||
| 743 | #define AR_PHY_PMU2 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16344 : 0x16c44) | 745 | #define AR_PHY_PMU2 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16344 : \ |
| 746 | (AR_SREV_9561(ah) ? 0x16cc4 : 0x16c44)) | ||
| 744 | #define AR_PHY_PMU2_PGM 0x00200000 | 747 | #define AR_PHY_PMU2_PGM 0x00200000 |
| 745 | #define AR_PHY_PMU2_PGM_S 21 | 748 | #define AR_PHY_PMU2_PGM_S 21 |
| 746 | 749 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c index 81c88dd606dc..86bfc9604dca 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c | |||
| @@ -17,23 +17,9 @@ | |||
| 17 | #include <linux/export.h> | 17 | #include <linux/export.h> |
| 18 | #include "ath9k.h" | 18 | #include "ath9k.h" |
| 19 | #include "reg.h" | 19 | #include "reg.h" |
| 20 | #include "reg_wow.h" | ||
| 20 | #include "hw-ops.h" | 21 | #include "hw-ops.h" |
| 21 | 22 | ||
| 22 | const char *ath9k_hw_wow_event_to_string(u32 wow_event) | ||
| 23 | { | ||
| 24 | if (wow_event & AH_WOW_MAGIC_PATTERN_EN) | ||
| 25 | return "Magic pattern"; | ||
| 26 | if (wow_event & AH_WOW_USER_PATTERN_EN) | ||
| 27 | return "User pattern"; | ||
| 28 | if (wow_event & AH_WOW_LINK_CHANGE) | ||
| 29 | return "Link change"; | ||
| 30 | if (wow_event & AH_WOW_BEACON_MISS) | ||
| 31 | return "Beacon miss"; | ||
| 32 | |||
| 33 | return "unknown reason"; | ||
| 34 | } | ||
| 35 | EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); | ||
| 36 | |||
| 37 | static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) | 23 | static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) |
| 38 | { | 24 | { |
| 39 | struct ath_common *common = ath9k_hw_common(ah); | 25 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -49,6 +35,15 @@ static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) | |||
| 49 | return; | 35 | return; |
| 50 | } | 36 | } |
| 51 | 37 | ||
| 38 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
| 39 | if (!REG_READ(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL)) | ||
| 40 | REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE); | ||
| 41 | } else if (AR_SREV_9485(ah)){ | ||
| 42 | if (!(REG_READ(ah, AR_NDP2_TIMER_MODE) & | ||
| 43 | AR_GEN_TIMERS2_MODE_ENABLE_MASK)) | ||
| 44 | REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE); | ||
| 45 | } | ||
| 46 | |||
| 52 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); | 47 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); |
| 53 | } | 48 | } |
| 54 | 49 | ||
| @@ -67,11 +62,15 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) | |||
| 67 | /* set the transmit buffer */ | 62 | /* set the transmit buffer */ |
| 68 | ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); | 63 | ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); |
| 69 | ctl[1] = 0; | 64 | ctl[1] = 0; |
| 70 | ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ | ||
| 71 | ctl[4] = 0; | 65 | ctl[4] = 0; |
| 72 | ctl[7] = (ah->txchainmask) << 2; | 66 | ctl[7] = (ah->txchainmask) << 2; |
| 73 | ctl[2] = 0xf << 16; /* tx_tries 0 */ | 67 | ctl[2] = 0xf << 16; /* tx_tries 0 */ |
| 74 | 68 | ||
| 69 | if (IS_CHAN_2GHZ(ah->curchan)) | ||
| 70 | ctl[3] = 0x1b; /* CCK_1M */ | ||
| 71 | else | ||
| 72 | ctl[3] = 0xb; /* OFDM_6M */ | ||
| 73 | |||
| 75 | for (i = 0; i < KAL_NUM_DESC_WORDS; i++) | 74 | for (i = 0; i < KAL_NUM_DESC_WORDS; i++) |
| 76 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); | 75 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); |
| 77 | 76 | ||
| @@ -103,21 +102,22 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) | |||
| 103 | 102 | ||
| 104 | } | 103 | } |
| 105 | 104 | ||
| 106 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | 105 | int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, |
| 107 | u8 *user_mask, int pattern_count, | 106 | u8 *user_mask, int pattern_count, |
| 108 | int pattern_len) | 107 | int pattern_len) |
| 109 | { | 108 | { |
| 110 | int i; | 109 | int i; |
| 111 | u32 pattern_val, mask_val; | 110 | u32 pattern_val, mask_val; |
| 112 | u32 set, clr; | 111 | u32 set, clr; |
| 113 | 112 | ||
| 114 | /* FIXME: should check count by querying the hardware capability */ | 113 | if (pattern_count >= ah->wow.max_patterns) |
| 115 | if (pattern_count >= MAX_NUM_PATTERN) | 114 | return -ENOSPC; |
| 116 | return; | ||
| 117 | 115 | ||
| 118 | REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); | 116 | if (pattern_count < MAX_NUM_PATTERN_LEGACY) |
| 117 | REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); | ||
| 118 | else | ||
| 119 | REG_SET_BIT(ah, AR_MAC_PCU_WOW4, BIT(pattern_count - 8)); | ||
| 119 | 120 | ||
| 120 | /* set the registers for pattern */ | ||
| 121 | for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { | 121 | for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { |
| 122 | memcpy(&pattern_val, user_pattern, 4); | 122 | memcpy(&pattern_val, user_pattern, 4); |
| 123 | REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), | 123 | REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), |
| @@ -125,49 +125,42 @@ void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | |||
| 125 | user_pattern += 4; | 125 | user_pattern += 4; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | /* set the registers for mask */ | ||
| 129 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { | 128 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { |
| 130 | memcpy(&mask_val, user_mask, 4); | 129 | memcpy(&mask_val, user_mask, 4); |
| 131 | REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); | 130 | REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); |
| 132 | user_mask += 4; | 131 | user_mask += 4; |
| 133 | } | 132 | } |
| 134 | 133 | ||
| 135 | /* set the pattern length to be matched | 134 | if (pattern_count < MAX_NUM_PATTERN_LEGACY) |
| 136 | * | 135 | ah->wow.wow_event_mask |= |
| 137 | * AR_WOW_LENGTH1_REG1 | 136 | BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); |
| 138 | * bit 31:24 pattern 0 length | 137 | else |
| 139 | * bit 23:16 pattern 1 length | 138 | ah->wow.wow_event_mask2 |= |
| 140 | * bit 15:8 pattern 2 length | 139 | BIT((pattern_count - 8) + AR_WOW_PAT_FOUND_SHIFT); |
| 141 | * bit 7:0 pattern 3 length | ||
| 142 | * | ||
| 143 | * AR_WOW_LENGTH1_REG2 | ||
| 144 | * bit 31:24 pattern 4 length | ||
| 145 | * bit 23:16 pattern 5 length | ||
| 146 | * bit 15:8 pattern 6 length | ||
| 147 | * bit 7:0 pattern 7 length | ||
| 148 | * | ||
| 149 | * the below logic writes out the new | ||
| 150 | * pattern length for the corresponding | ||
| 151 | * pattern_count, while masking out the | ||
| 152 | * other fields | ||
| 153 | */ | ||
| 154 | |||
| 155 | ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); | ||
| 156 | 140 | ||
| 157 | if (pattern_count < 4) { | 141 | if (pattern_count < 4) { |
| 158 | /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ | ||
| 159 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | 142 | set = (pattern_len & AR_WOW_LENGTH_MAX) << |
| 160 | AR_WOW_LEN1_SHIFT(pattern_count); | 143 | AR_WOW_LEN1_SHIFT(pattern_count); |
| 161 | clr = AR_WOW_LENGTH1_MASK(pattern_count); | 144 | clr = AR_WOW_LENGTH1_MASK(pattern_count); |
| 162 | REG_RMW(ah, AR_WOW_LENGTH1, set, clr); | 145 | REG_RMW(ah, AR_WOW_LENGTH1, set, clr); |
| 163 | } else { | 146 | } else if (pattern_count < 8) { |
| 164 | /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ | ||
| 165 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | 147 | set = (pattern_len & AR_WOW_LENGTH_MAX) << |
| 166 | AR_WOW_LEN2_SHIFT(pattern_count); | 148 | AR_WOW_LEN2_SHIFT(pattern_count); |
| 167 | clr = AR_WOW_LENGTH2_MASK(pattern_count); | 149 | clr = AR_WOW_LENGTH2_MASK(pattern_count); |
| 168 | REG_RMW(ah, AR_WOW_LENGTH2, set, clr); | 150 | REG_RMW(ah, AR_WOW_LENGTH2, set, clr); |
| 151 | } else if (pattern_count < 12) { | ||
| 152 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
| 153 | AR_WOW_LEN3_SHIFT(pattern_count); | ||
| 154 | clr = AR_WOW_LENGTH3_MASK(pattern_count); | ||
| 155 | REG_RMW(ah, AR_WOW_LENGTH3, set, clr); | ||
| 156 | } else if (pattern_count < MAX_NUM_PATTERN) { | ||
| 157 | set = (pattern_len & AR_WOW_LENGTH_MAX) << | ||
| 158 | AR_WOW_LEN4_SHIFT(pattern_count); | ||
| 159 | clr = AR_WOW_LENGTH4_MASK(pattern_count); | ||
| 160 | REG_RMW(ah, AR_WOW_LENGTH4, set, clr); | ||
| 169 | } | 161 | } |
| 170 | 162 | ||
| 163 | return 0; | ||
| 171 | } | 164 | } |
| 172 | EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); | 165 | EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); |
| 173 | 166 | ||
| @@ -189,7 +182,7 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | |||
| 189 | * register. This mask will clean it up. | 182 | * register. This mask will clean it up. |
| 190 | */ | 183 | */ |
| 191 | 184 | ||
| 192 | val &= ah->wow_event_mask; | 185 | val &= ah->wow.wow_event_mask; |
| 193 | 186 | ||
| 194 | if (val) { | 187 | if (val) { |
| 195 | if (val & AR_WOW_MAGIC_PAT_FOUND) | 188 | if (val & AR_WOW_MAGIC_PAT_FOUND) |
| @@ -233,190 +226,192 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | |||
| 233 | if (ah->is_pciexpress) | 226 | if (ah->is_pciexpress) |
| 234 | ath9k_hw_configpcipowersave(ah, false); | 227 | ath9k_hw_configpcipowersave(ah, false); |
| 235 | 228 | ||
| 236 | ah->wow_event_mask = 0; | 229 | ah->wow.wow_event_mask = 0; |
| 237 | 230 | ||
| 238 | return wow_status; | 231 | return wow_status; |
| 239 | } | 232 | } |
| 240 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); | 233 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); |
| 241 | 234 | ||
| 242 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) | 235 | static void ath9k_hw_wow_set_arwr_reg(struct ath_hw *ah) |
| 243 | { | 236 | { |
| 244 | u32 wow_event_mask; | 237 | u32 wa_reg; |
| 245 | u32 set, clr; | ||
| 246 | 238 | ||
| 247 | /* | 239 | if (!ah->is_pciexpress) |
| 248 | * wow_event_mask is a mask to the AR_WOW_PATTERN register to | 240 | return; |
| 249 | * indicate which WoW events we have enabled. The WoW events | ||
| 250 | * are from the 'pattern_enable' in this function and | ||
| 251 | * 'pattern_count' of ath9k_hw_wow_apply_pattern() | ||
| 252 | */ | ||
| 253 | wow_event_mask = ah->wow_event_mask; | ||
| 254 | 241 | ||
| 255 | /* | 242 | /* |
| 256 | * Untie Power-on-Reset from the PCI-E-Reset. When we are in | 243 | * We need to untie the internal POR (power-on-reset) |
| 257 | * WOW sleep, we do want the Reset from the PCI-E to disturb | 244 | * to the external PCI-E reset. We also need to tie |
| 258 | * our hw state | 245 | * the PCI-E Phy reset to the PCI-E reset. |
| 259 | */ | 246 | */ |
| 260 | if (ah->is_pciexpress) { | 247 | wa_reg = REG_READ(ah, AR_WA); |
| 261 | /* | 248 | wa_reg &= ~AR_WA_UNTIE_RESET_EN; |
| 262 | * we need to untie the internal POR (power-on-reset) | 249 | wa_reg |= AR_WA_RESET_EN; |
| 263 | * to the external PCI-E reset. We also need to tie | 250 | wa_reg |= AR_WA_POR_SHORT; |
| 264 | * the PCI-E Phy reset to the PCI-E reset. | ||
| 265 | */ | ||
| 266 | set = AR_WA_RESET_EN | AR_WA_POR_SHORT; | ||
| 267 | clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; | ||
| 268 | REG_RMW(ah, AR_WA, set, clr); | ||
| 269 | } | ||
| 270 | 251 | ||
| 271 | /* | 252 | REG_WRITE(ah, AR_WA, wa_reg); |
| 272 | * set the power states appropriately and enable PME | 253 | } |
| 273 | */ | 254 | |
| 274 | set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | | 255 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) |
| 275 | AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; | 256 | { |
| 257 | u32 wow_event_mask; | ||
| 258 | u32 keep_alive, magic_pattern, host_pm_ctrl; | ||
| 259 | |||
| 260 | wow_event_mask = ah->wow.wow_event_mask; | ||
| 276 | 261 | ||
| 277 | /* | 262 | /* |
| 278 | * set and clear WOW_PME_CLEAR registers for the chip | 263 | * AR_PMCTRL_HOST_PME_EN - Override PME enable in configuration |
| 264 | * space and allow MAC to generate WoW anyway. | ||
| 265 | * | ||
| 266 | * AR_PMCTRL_PWR_PM_CTRL_ENA - ??? | ||
| 267 | * | ||
| 268 | * AR_PMCTRL_AUX_PWR_DET - PCI core SYS_AUX_PWR_DET signal, | ||
| 269 | * needs to be set for WoW in PCI mode. | ||
| 270 | * | ||
| 271 | * AR_PMCTRL_WOW_PME_CLR - WoW Clear Signal going to the MAC. | ||
| 272 | * | ||
| 273 | * Set the power states appropriately and enable PME. | ||
| 274 | * | ||
| 275 | * Set and clear WOW_PME_CLEAR for the chip | ||
| 279 | * to generate next wow signal. | 276 | * to generate next wow signal. |
| 280 | */ | 277 | */ |
| 281 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | 278 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_HOST_PME_EN | |
| 282 | clr = AR_PMCTRL_WOW_PME_CLR; | 279 | AR_PMCTRL_PWR_PM_CTRL_ENA | |
| 283 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | 280 | AR_PMCTRL_AUX_PWR_DET | |
| 281 | AR_PMCTRL_WOW_PME_CLR); | ||
| 282 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR); | ||
| 284 | 283 | ||
| 285 | /* | 284 | /* |
| 286 | * Setup for: | 285 | * Random Backoff. |
| 287 | * - beacon misses | 286 | * |
| 288 | * - magic pattern | 287 | * 31:28 in AR_WOW_PATTERN : Indicates the number of bits used in the |
| 289 | * - keep alive timeout | 288 | * contention window. For value N, |
| 290 | * - pattern matching | 289 | * the random backoff will be selected between |
| 290 | * 0 and (2 ^ N) - 1. | ||
| 291 | */ | 291 | */ |
| 292 | REG_SET_BIT(ah, AR_WOW_PATTERN, | ||
| 293 | AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF)); | ||
| 292 | 294 | ||
| 293 | /* | 295 | /* |
| 294 | * Program default values for pattern backoff, aifs/slot/KAL count, | 296 | * AIFS time, Slot time, Keep Alive count. |
| 295 | * beacon miss timeout, KAL timeout, etc. | 297 | */ |
| 298 | REG_SET_BIT(ah, AR_WOW_COUNT, AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | | ||
| 299 | AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | | ||
| 300 | AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT)); | ||
| 301 | /* | ||
| 302 | * Beacon timeout. | ||
| 296 | */ | 303 | */ |
| 297 | set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); | ||
| 298 | REG_SET_BIT(ah, AR_WOW_PATTERN, set); | ||
| 299 | |||
| 300 | set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | | ||
| 301 | AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | | ||
| 302 | AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); | ||
| 303 | REG_SET_BIT(ah, AR_WOW_COUNT, set); | ||
| 304 | |||
| 305 | if (pattern_enable & AH_WOW_BEACON_MISS) | 304 | if (pattern_enable & AH_WOW_BEACON_MISS) |
| 306 | set = AR_WOW_BEACON_TIMO; | 305 | REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO); |
| 307 | /* We are not using beacon miss, program a large value */ | ||
| 308 | else | 306 | else |
| 309 | set = AR_WOW_BEACON_TIMO_MAX; | 307 | REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO_MAX); |
| 310 | |||
| 311 | REG_WRITE(ah, AR_WOW_BCN_TIMO, set); | ||
| 312 | 308 | ||
| 313 | /* | 309 | /* |
| 314 | * Keep alive timo in ms except AR9280 | 310 | * Keep alive timeout in ms. |
| 315 | */ | 311 | */ |
| 316 | if (!pattern_enable) | 312 | if (!pattern_enable) |
| 317 | set = AR_WOW_KEEP_ALIVE_NEVER; | 313 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, AR_WOW_KEEP_ALIVE_NEVER); |
| 318 | else | 314 | else |
| 319 | set = KAL_TIMEOUT * 32; | 315 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, KAL_TIMEOUT * 32); |
| 320 | |||
| 321 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); | ||
| 322 | 316 | ||
| 323 | /* | 317 | /* |
| 324 | * Keep alive delay in us. based on 'power on clock', | 318 | * Keep alive delay in us. |
| 325 | * therefore in usec | ||
| 326 | */ | 319 | */ |
| 327 | set = KAL_DELAY * 1000; | 320 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, KAL_DELAY * 1000); |
| 328 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); | ||
| 329 | 321 | ||
| 330 | /* | 322 | /* |
| 331 | * Create keep alive pattern to respond to beacons | 323 | * Create keep alive pattern to respond to beacons. |
| 332 | */ | 324 | */ |
| 333 | ath9k_wow_create_keep_alive_pattern(ah); | 325 | ath9k_wow_create_keep_alive_pattern(ah); |
| 334 | 326 | ||
| 335 | /* | 327 | /* |
| 336 | * Configure MAC WoW Registers | 328 | * Configure keep alive register. |
| 337 | */ | 329 | */ |
| 338 | set = 0; | 330 | keep_alive = REG_READ(ah, AR_WOW_KEEP_ALIVE); |
| 331 | |||
| 339 | /* Send keep alive timeouts anyway */ | 332 | /* Send keep alive timeouts anyway */ |
| 340 | clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; | 333 | keep_alive &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS; |
| 341 | 334 | ||
| 342 | if (pattern_enable & AH_WOW_LINK_CHANGE) | 335 | if (pattern_enable & AH_WOW_LINK_CHANGE) { |
| 336 | keep_alive &= ~AR_WOW_KEEP_ALIVE_FAIL_DIS; | ||
| 343 | wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; | 337 | wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; |
| 344 | else | 338 | } else { |
| 345 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | 339 | keep_alive |= AR_WOW_KEEP_ALIVE_FAIL_DIS; |
| 340 | } | ||
| 346 | 341 | ||
| 347 | set = AR_WOW_KEEP_ALIVE_FAIL_DIS; | 342 | REG_WRITE(ah, AR_WOW_KEEP_ALIVE, keep_alive); |
| 348 | REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); | ||
| 349 | 343 | ||
| 350 | /* | 344 | /* |
| 351 | * we are relying on a bmiss failure. ensure we have | 345 | * We are relying on a bmiss failure, ensure we have |
| 352 | * enough threshold to prevent false positives | 346 | * enough threshold to prevent false positives. |
| 353 | */ | 347 | */ |
| 354 | REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, | 348 | REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, |
| 355 | AR_WOW_BMISSTHRESHOLD); | 349 | AR_WOW_BMISSTHRESHOLD); |
| 356 | 350 | ||
| 357 | set = 0; | ||
| 358 | clr = 0; | ||
| 359 | |||
| 360 | if (pattern_enable & AH_WOW_BEACON_MISS) { | 351 | if (pattern_enable & AH_WOW_BEACON_MISS) { |
| 361 | set = AR_WOW_BEACON_FAIL_EN; | ||
| 362 | wow_event_mask |= AR_WOW_BEACON_FAIL; | 352 | wow_event_mask |= AR_WOW_BEACON_FAIL; |
| 353 | REG_SET_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN); | ||
| 363 | } else { | 354 | } else { |
| 364 | clr = AR_WOW_BEACON_FAIL_EN; | 355 | REG_CLR_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN); |
| 365 | } | 356 | } |
| 366 | 357 | ||
| 367 | REG_RMW(ah, AR_WOW_BCN_EN, set, clr); | ||
| 368 | |||
| 369 | set = 0; | ||
| 370 | clr = 0; | ||
| 371 | /* | 358 | /* |
| 372 | * Enable the magic packet registers | 359 | * Enable the magic packet registers. |
| 373 | */ | 360 | */ |
| 361 | magic_pattern = REG_READ(ah, AR_WOW_PATTERN); | ||
| 362 | magic_pattern |= AR_WOW_MAC_INTR_EN; | ||
| 363 | |||
| 374 | if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { | 364 | if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { |
| 375 | set = AR_WOW_MAGIC_EN; | 365 | magic_pattern |= AR_WOW_MAGIC_EN; |
| 376 | wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; | 366 | wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; |
| 377 | } else { | 367 | } else { |
| 378 | clr = AR_WOW_MAGIC_EN; | 368 | magic_pattern &= ~AR_WOW_MAGIC_EN; |
| 379 | } | 369 | } |
| 380 | set |= AR_WOW_MAC_INTR_EN; | ||
| 381 | REG_RMW(ah, AR_WOW_PATTERN, set, clr); | ||
| 382 | 370 | ||
| 371 | REG_WRITE(ah, AR_WOW_PATTERN, magic_pattern); | ||
| 372 | |||
| 373 | /* | ||
| 374 | * Enable pattern matching for packets which are less | ||
| 375 | * than 256 bytes. | ||
| 376 | */ | ||
| 383 | REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, | 377 | REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, |
| 384 | AR_WOW_PATTERN_SUPPORTED); | 378 | AR_WOW_PATTERN_SUPPORTED); |
| 385 | 379 | ||
| 386 | /* | 380 | /* |
| 387 | * Set the power states appropriately and enable PME | 381 | * Set the power states appropriately and enable PME. |
| 388 | */ | 382 | */ |
| 389 | clr = 0; | 383 | host_pm_ctrl = REG_READ(ah, AR_PCIE_PM_CTRL); |
| 390 | set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | | 384 | host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3 | |
| 391 | AR_PMCTRL_PWR_PM_CTRL_ENA; | 385 | AR_PMCTRL_HOST_PME_EN | |
| 386 | AR_PMCTRL_PWR_PM_CTRL_ENA; | ||
| 387 | host_pm_ctrl &= ~AR_PCIE_PM_CTRL_ENA; | ||
| 392 | 388 | ||
| 393 | clr = AR_PCIE_PM_CTRL_ENA; | 389 | if (AR_SREV_9462(ah)) { |
| 394 | REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); | 390 | /* |
| 391 | * This is needed to prevent the chip waking up | ||
| 392 | * the host within 3-4 seconds with certain | ||
| 393 | * platform/BIOS. | ||
| 394 | */ | ||
| 395 | host_pm_ctrl &= ~AR_PMCTRL_PWR_STATE_D1D3; | ||
| 396 | host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3_REAL; | ||
| 397 | } | ||
| 398 | |||
| 399 | REG_WRITE(ah, AR_PCIE_PM_CTRL, host_pm_ctrl); | ||
| 395 | 400 | ||
| 396 | /* | 401 | /* |
| 397 | * this is needed to prevent the chip waking up | 402 | * Enable sequence number generation when asleep. |
| 398 | * the host within 3-4 seconds with certain | ||
| 399 | * platform/BIOS. The fix is to enable | ||
| 400 | * D1 & D3 to match original definition and | ||
| 401 | * also match the OTP value. Anyway this | ||
| 402 | * is more related to SW WOW. | ||
| 403 | */ | 403 | */ |
| 404 | clr = AR_PMCTRL_PWR_STATE_D1D3; | 404 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); |
| 405 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); | ||
| 406 | 405 | ||
| 407 | set = AR_PMCTRL_PWR_STATE_D1D3_REAL; | 406 | /* To bring down WOW power low margin */ |
| 408 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); | 407 | REG_SET_BIT(ah, AR_PCIE_PHY_REG3, BIT(13)); |
| 409 | 408 | ||
| 410 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); | 409 | ath9k_hw_wow_set_arwr_reg(ah); |
| 411 | 410 | ||
| 412 | /* to bring down WOW power low margin */ | ||
| 413 | set = BIT(13); | ||
| 414 | REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); | ||
| 415 | /* HW WoW */ | 411 | /* HW WoW */ |
| 416 | clr = BIT(5); | 412 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, BIT(5)); |
| 417 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); | ||
| 418 | 413 | ||
| 419 | ath9k_hw_set_powermode_wow_sleep(ah); | 414 | ath9k_hw_set_powermode_wow_sleep(ah); |
| 420 | ah->wow_event_mask = wow_event_mask; | 415 | ah->wow.wow_event_mask = wow_event_mask; |
| 421 | } | 416 | } |
| 422 | EXPORT_SYMBOL(ath9k_hw_wow_enable); | 417 | EXPORT_SYMBOL(ath9k_hw_wow_enable); |
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 159cc6fd2362..6fc0d07e5ec6 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h | |||
| @@ -358,7 +358,7 @@ static const u32 qca953x_1p0_baseband_postamble[][5] = { | |||
| 358 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 358 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
| 359 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 359 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
| 360 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 360 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
| 361 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, | 361 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10820, 0xcfa10820}, |
| 362 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | 362 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, |
| 363 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 363 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
| 364 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 364 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
| @@ -378,7 +378,7 @@ static const u32 qca953x_1p0_baseband_postamble[][5] = { | |||
| 378 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | 378 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, |
| 379 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 379 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, |
| 380 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 380 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, |
| 381 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 381 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, |
| 382 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, | 382 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, |
| 383 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, | 383 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, |
| 384 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 384 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h index fd6a84ccd49e..148562addd38 100644 --- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h | |||
| @@ -63,7 +63,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = { | |||
| 63 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 63 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
| 64 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 64 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
| 65 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 65 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
| 66 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, | 66 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10820, 0xcfa10820}, |
| 67 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | 67 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, |
| 68 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 68 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
| 69 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 69 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
| @@ -83,7 +83,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = { | |||
| 83 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | 83 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, |
| 84 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 84 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, |
| 85 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 85 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, |
| 86 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 86 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, |
| 87 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, | 87 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, |
| 88 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, | 88 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, |
| 89 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | 89 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar956x_initvals.h b/drivers/net/wireless/ath/ath9k/ar956x_initvals.h new file mode 100644 index 000000000000..c3a47eaaf0c0 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar956x_initvals.h | |||
| @@ -0,0 +1,1046 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
| 3 | * Copyright (c) 2011-2012 Qualcomm Atheros Inc. | ||
| 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 INITVALS_956X_H | ||
| 19 | #define INITVALS_956X_H | ||
| 20 | |||
| 21 | #define qca956x_1p0_mac_core ar955x_1p0_mac_core | ||
| 22 | |||
| 23 | #define qca956x_1p0_mac_postamble ar9331_1p1_mac_postamble | ||
| 24 | |||
| 25 | #define qca956x_1p0_soc_preamble ar955x_1p0_soc_preamble | ||
| 26 | |||
| 27 | #define qca956x_1p0_soc_postamble ar9300_2p2_soc_postamble | ||
| 28 | |||
| 29 | #define qca956x_1p0_common_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2 | ||
| 30 | |||
| 31 | #define qca956x_1p0_baseband_postamble_dfs_channel ar9300_2p2_baseband_postamble_dfs_channel | ||
| 32 | |||
| 33 | #define qca956x_1p0_common_wo_xlna_rx_gain_bounds ar955x_1p0_common_wo_xlna_rx_gain_bounds | ||
| 34 | |||
| 35 | #define qca956x_1p0_common_rx_gain_bounds ar955x_1p0_common_rx_gain_bounds | ||
| 36 | |||
| 37 | #define qca956x_1p0_modes_fast_clock ar9462_2p0_modes_fast_clock | ||
| 38 | |||
| 39 | static const u32 qca956x_1p0_baseband_core[][2] = { | ||
| 40 | /* Addr allmodes */ | ||
| 41 | {0x00009800, 0xafe68e30}, | ||
| 42 | {0x00009804, 0xfd14e000}, | ||
| 43 | {0x00009808, 0x9c0a9f6b}, | ||
| 44 | {0x0000980c, 0x04900000}, | ||
| 45 | {0x00009814, 0x0280c00a}, | ||
| 46 | {0x00009818, 0x00000000}, | ||
| 47 | {0x0000981c, 0x00020028}, | ||
| 48 | {0x00009834, 0x6400a190}, | ||
| 49 | {0x00009838, 0x0108ecff}, | ||
| 50 | {0x0000983c, 0x14000600}, | ||
| 51 | {0x00009880, 0x201fff00}, | ||
| 52 | {0x00009884, 0x00001042}, | ||
| 53 | {0x000098a4, 0x00200400}, | ||
| 54 | {0x000098b0, 0x32840cbf}, | ||
| 55 | {0x000098bc, 0x00000002}, | ||
| 56 | {0x000098d0, 0x004b6a8e}, | ||
| 57 | {0x000098d4, 0x00000820}, | ||
| 58 | {0x000098dc, 0x00000000}, | ||
| 59 | {0x000098f0, 0x00000000}, | ||
| 60 | {0x000098f4, 0x00000000}, | ||
| 61 | {0x00009c04, 0xff55ff55}, | ||
| 62 | {0x00009c08, 0x0320ff55}, | ||
| 63 | {0x00009c0c, 0x00000000}, | ||
| 64 | {0x00009c10, 0x00000000}, | ||
| 65 | {0x00009c14, 0x00046384}, | ||
| 66 | {0x00009c18, 0x05b6b440}, | ||
| 67 | {0x00009c1c, 0x00b6b440}, | ||
| 68 | {0x00009d00, 0xc080a333}, | ||
| 69 | {0x00009d04, 0x40206c10}, | ||
| 70 | {0x00009d08, 0x009c4060}, | ||
| 71 | {0x00009d0c, 0x9883800a}, | ||
| 72 | {0x00009d10, 0x01834061}, | ||
| 73 | {0x00009d14, 0x00c0040b}, | ||
| 74 | {0x00009d18, 0x00000000}, | ||
| 75 | {0x00009e08, 0x0038230c}, | ||
| 76 | {0x00009e24, 0x990bb514}, | ||
| 77 | {0x00009e28, 0x0c6f0000}, | ||
| 78 | {0x00009e30, 0x06336f77}, | ||
| 79 | {0x00009e34, 0x6af6532f}, | ||
| 80 | {0x00009e38, 0x0cc80c00}, | ||
| 81 | {0x00009e40, 0x0d261820}, | ||
| 82 | {0x00009e4c, 0x00001004}, | ||
| 83 | {0x00009e50, 0x00ff03f1}, | ||
| 84 | {0x00009fc0, 0x813e4789}, | ||
| 85 | {0x00009fc4, 0x0001efb5}, | ||
| 86 | {0x00009fcc, 0x40000014}, | ||
| 87 | {0x00009fd0, 0x02993b93}, | ||
| 88 | {0x0000a20c, 0x00000000}, | ||
| 89 | {0x0000a218, 0x00000000}, | ||
| 90 | {0x0000a21c, 0x00000000}, | ||
| 91 | {0x0000a228, 0x10002310}, | ||
| 92 | {0x0000a23c, 0x00000000}, | ||
| 93 | {0x0000a244, 0x0c000000}, | ||
| 94 | {0x0000a248, 0x00000140}, | ||
| 95 | {0x0000a2a0, 0x00000007}, | ||
| 96 | {0x0000a2c0, 0x00000007}, | ||
| 97 | {0x0000a2c8, 0x00000000}, | ||
| 98 | {0x0000a2d4, 0x00000000}, | ||
| 99 | {0x0000a2ec, 0x00000000}, | ||
| 100 | {0x0000a2f0, 0x00000000}, | ||
| 101 | {0x0000a2f4, 0x00000000}, | ||
| 102 | {0x0000a2f8, 0x00000000}, | ||
| 103 | {0x0000a344, 0x00000000}, | ||
| 104 | {0x0000a34c, 0x00000000}, | ||
| 105 | {0x0000a350, 0x0000a000}, | ||
| 106 | {0x0000a360, 0x00000000}, | ||
| 107 | {0x0000a36c, 0x00000000}, | ||
| 108 | {0x0000a384, 0x00000001}, | ||
| 109 | {0x0000a388, 0x00000444}, | ||
| 110 | {0x0000a38c, 0x00000000}, | ||
| 111 | {0x0000a390, 0x210d0401}, | ||
| 112 | {0x0000a394, 0xab9a7144}, | ||
| 113 | {0x0000a398, 0x00000201}, | ||
| 114 | {0x0000a39c, 0x42424848}, | ||
| 115 | {0x0000a3a0, 0x3c466478}, | ||
| 116 | {0x0000a3a4, 0x3a363600}, | ||
| 117 | {0x0000a3a8, 0x0000003a}, | ||
| 118 | {0x0000a3ac, 0x00000000}, | ||
| 119 | {0x0000a3b0, 0x009011fe}, | ||
| 120 | {0x0000a3b4, 0x00000034}, | ||
| 121 | {0x0000a3b8, 0x00b3ec0a}, | ||
| 122 | {0x0000a3bc, 0x00000036}, | ||
| 123 | {0x0000a3c0, 0x20202020}, | ||
| 124 | {0x0000a3c4, 0x22222220}, | ||
| 125 | {0x0000a3c8, 0x20200020}, | ||
| 126 | {0x0000a3cc, 0x20202020}, | ||
| 127 | {0x0000a3d0, 0x20202020}, | ||
| 128 | {0x0000a3d4, 0x20202020}, | ||
| 129 | {0x0000a3d8, 0x20202020}, | ||
| 130 | {0x0000a3dc, 0x20202020}, | ||
| 131 | {0x0000a3e0, 0x20202020}, | ||
| 132 | {0x0000a3e4, 0x20202020}, | ||
| 133 | {0x0000a3e8, 0x20202020}, | ||
| 134 | {0x0000a3ec, 0x20202020}, | ||
| 135 | {0x0000a3f0, 0x00000000}, | ||
| 136 | {0x0000a3f4, 0x00000000}, | ||
| 137 | {0x0000a3f8, 0x0c9bd380}, | ||
| 138 | {0x0000a3fc, 0x000f0f01}, | ||
| 139 | {0x0000a400, 0x8fa91f01}, | ||
| 140 | {0x0000a404, 0x00000000}, | ||
| 141 | {0x0000a408, 0x0e79e5c6}, | ||
| 142 | {0x0000a40c, 0x00820820}, | ||
| 143 | {0x0000a414, 0x1ce739ce}, | ||
| 144 | {0x0000a418, 0x2d0019ce}, | ||
| 145 | {0x0000a41c, 0x1ce739ce}, | ||
| 146 | {0x0000a420, 0x000001ce}, | ||
| 147 | {0x0000a424, 0x1ce739ce}, | ||
| 148 | {0x0000a428, 0x000001ce}, | ||
| 149 | {0x0000a42c, 0x1ce739ce}, | ||
| 150 | {0x0000a430, 0x1ce739ce}, | ||
| 151 | {0x0000a434, 0x00000000}, | ||
| 152 | {0x0000a438, 0x00001801}, | ||
| 153 | {0x0000a43c, 0x00100000}, | ||
| 154 | {0x0000a444, 0x00000000}, | ||
| 155 | {0x0000a448, 0x05000080}, | ||
| 156 | {0x0000a44c, 0x00000001}, | ||
| 157 | {0x0000a450, 0x00010000}, | ||
| 158 | {0x0000a454, 0x05000000}, | ||
| 159 | {0x0000a458, 0x00000000}, | ||
| 160 | {0x0000a644, 0xbfad9fee}, | ||
| 161 | {0x0000a648, 0x0048660d}, | ||
| 162 | {0x0000a64c, 0x00003c37}, | ||
| 163 | {0x0000a670, 0x03020100}, | ||
| 164 | {0x0000a674, 0x21200504}, | ||
| 165 | {0x0000a678, 0x61602322}, | ||
| 166 | {0x0000a67c, 0x65646362}, | ||
| 167 | {0x0000a680, 0x6b6a6968}, | ||
| 168 | {0x0000a684, 0xe2706d6c}, | ||
| 169 | {0x0000a688, 0x000000e3}, | ||
| 170 | {0x0000a690, 0x00000838}, | ||
| 171 | {0x0000a7cc, 0x00000000}, | ||
| 172 | {0x0000a7d0, 0x00000000}, | ||
| 173 | {0x0000a7d4, 0x00000004}, | ||
| 174 | {0x0000a7dc, 0x00000000}, | ||
| 175 | {0x0000a8d0, 0x004b6a8e}, | ||
| 176 | {0x0000a8d4, 0x00000820}, | ||
| 177 | {0x0000a8dc, 0x00000000}, | ||
| 178 | {0x0000a8f0, 0x00000000}, | ||
| 179 | {0x0000a8f4, 0x00000000}, | ||
| 180 | {0x0000b2d0, 0x00000080}, | ||
| 181 | {0x0000b2d4, 0x00000000}, | ||
| 182 | {0x0000b2ec, 0x00000000}, | ||
| 183 | {0x0000b2f0, 0x00000000}, | ||
| 184 | {0x0000b2f4, 0x00000000}, | ||
| 185 | {0x0000b2f8, 0x00000000}, | ||
| 186 | {0x0000b408, 0x0e79e5c0}, | ||
| 187 | {0x0000b40c, 0x00820820}, | ||
| 188 | {0x0000b420, 0x00000000}, | ||
| 189 | {0x0000b8d0, 0x004b6a8e}, | ||
| 190 | {0x0000b8d4, 0x00000820}, | ||
| 191 | {0x0000b8dc, 0x00000000}, | ||
| 192 | {0x0000b8f0, 0x00000000}, | ||
| 193 | {0x0000b8f4, 0x00000000}, | ||
| 194 | {0x0000c2d0, 0x00000080}, | ||
| 195 | {0x0000c2d4, 0x00000000}, | ||
| 196 | {0x0000c2ec, 0x00000000}, | ||
| 197 | {0x0000c2f0, 0x00000000}, | ||
| 198 | {0x0000c2f4, 0x00000000}, | ||
| 199 | {0x0000c2f8, 0x00000000}, | ||
| 200 | {0x0000c408, 0x0e79e5c0}, | ||
| 201 | {0x0000c40c, 0x00820820}, | ||
| 202 | {0x0000c420, 0x00000000}, | ||
| 203 | }; | ||
| 204 | |||
| 205 | static const u32 qca956x_1p0_baseband_postamble[][5] = { | ||
| 206 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 207 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, | ||
| 208 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae}, | ||
| 209 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac621f1, 0x5ac621f1}, | ||
| 210 | {0x00009828, 0x06903081, 0x06903081, 0x07d43881, 0x07d43881}, | ||
| 211 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | ||
| 212 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | ||
| 213 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | ||
| 214 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, | ||
| 215 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, | ||
| 216 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000de, 0x6c4000de}, | ||
| 217 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, | ||
| 218 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x337d605e, 0x337d5d5e}, | ||
| 219 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 220 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | ||
| 221 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a6, 0x000003a6}, | ||
| 222 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | ||
| 223 | {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222}, | ||
| 224 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | ||
| 225 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | ||
| 226 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | ||
| 227 | {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x045c0cc4, 0x045c0cc0}, | ||
| 228 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | ||
| 229 | {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, | ||
| 230 | {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, | ||
| 231 | {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, | ||
| 232 | {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, | ||
| 233 | {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, | ||
| 234 | {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, | ||
| 235 | {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, | ||
| 236 | {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01010e0e, 0x01010e0e}, | ||
| 237 | {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, | ||
| 238 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x01000e0e, 0x01000e0e}, | ||
| 239 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, | ||
| 240 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | ||
| 241 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | ||
| 242 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | ||
| 243 | {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, | ||
| 244 | {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, | ||
| 245 | {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, | ||
| 246 | {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, | ||
| 247 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 248 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
| 249 | {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, | ||
| 250 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 251 | {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
| 252 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001a6, 0x000001a6}, | ||
| 253 | {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | ||
| 254 | {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
| 255 | {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, | ||
| 256 | {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 257 | {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
| 258 | {0x0000be20, 0x000001b5, 0x000001b5, 0x000001a6, 0x000001a6}, | ||
| 259 | {0x0000c284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | ||
| 260 | }; | ||
| 261 | |||
| 262 | static const u32 qca956x_1p0_radio_core[][2] = { | ||
| 263 | /* Addr allmodes */ | ||
| 264 | {0x00016000, 0x36db6db6}, | ||
| 265 | {0x00016004, 0x6db6db40}, | ||
| 266 | {0x00016008, 0x73f00000}, | ||
| 267 | {0x0001600c, 0x00000000}, | ||
| 268 | {0x00016040, 0x3f80fff8}, | ||
| 269 | {0x0001604c, 0x000f0278}, | ||
| 270 | {0x00016050, 0x8036db6c}, | ||
| 271 | {0x00016054, 0x6db60000}, | ||
| 272 | {0x00016080, 0x00080000}, | ||
| 273 | {0x00016084, 0x0e48048c}, | ||
| 274 | {0x00016088, 0x14214514}, | ||
| 275 | {0x0001608c, 0x119f080a}, | ||
| 276 | {0x00016090, 0x24926490}, | ||
| 277 | {0x00016094, 0x00000000}, | ||
| 278 | {0x000160a0, 0xc2108ffe}, | ||
| 279 | {0x000160a4, 0x812fc370}, | ||
| 280 | {0x000160a8, 0x423c8000}, | ||
| 281 | {0x000160b4, 0x92480000}, | ||
| 282 | {0x000160c0, 0x006db6d8}, | ||
| 283 | {0x000160c4, 0x24b6db6c}, | ||
| 284 | {0x000160c8, 0x6db6db6c}, | ||
| 285 | {0x000160cc, 0x6db6fb7c}, | ||
| 286 | {0x000160d0, 0x6db6da44}, | ||
| 287 | {0x00016100, 0x07ff8001}, | ||
| 288 | {0x00016108, 0x00080010}, | ||
| 289 | {0x00016144, 0x01884080}, | ||
| 290 | {0x00016148, 0x00008058}, | ||
| 291 | {0x00016288, 0x001c6000}, | ||
| 292 | {0x0001628c, 0x50000000}, | ||
| 293 | {0x000162c0, 0x4b962100}, | ||
| 294 | {0x000162c4, 0x00000480}, | ||
| 295 | {0x000162c8, 0x04000144}, | ||
| 296 | {0x00016380, 0x00000000}, | ||
| 297 | {0x00016384, 0x00000000}, | ||
| 298 | {0x00016388, 0x00800700}, | ||
| 299 | {0x0001638c, 0x00800700}, | ||
| 300 | {0x00016390, 0x00800700}, | ||
| 301 | {0x00016394, 0x00000000}, | ||
| 302 | {0x00016398, 0x00000000}, | ||
| 303 | {0x0001639c, 0x00000000}, | ||
| 304 | {0x000163a0, 0x00000001}, | ||
| 305 | {0x000163a4, 0x00000001}, | ||
| 306 | {0x000163a8, 0x00000000}, | ||
| 307 | {0x000163ac, 0x00000000}, | ||
| 308 | {0x000163b0, 0x00000000}, | ||
| 309 | {0x000163b4, 0x00000000}, | ||
| 310 | {0x000163b8, 0x00000000}, | ||
| 311 | {0x000163bc, 0x00000000}, | ||
| 312 | {0x000163c0, 0x000000a0}, | ||
| 313 | {0x000163c4, 0x000c0000}, | ||
| 314 | {0x000163c8, 0x14021402}, | ||
| 315 | {0x000163cc, 0x00001402}, | ||
| 316 | {0x000163d0, 0x00000000}, | ||
| 317 | {0x000163d4, 0x00000000}, | ||
| 318 | {0x00016400, 0x36db6db6}, | ||
| 319 | {0x00016404, 0x6db6db40}, | ||
| 320 | {0x00016408, 0x73f00000}, | ||
| 321 | {0x0001640c, 0x00000000}, | ||
| 322 | {0x00016440, 0x3f80fff8}, | ||
| 323 | {0x0001644c, 0x000f0278}, | ||
| 324 | {0x00016450, 0x8036db6c}, | ||
| 325 | {0x00016454, 0x6db60000}, | ||
| 326 | {0x00016500, 0x07ff8001}, | ||
| 327 | {0x00016508, 0x00080010}, | ||
| 328 | {0x00016544, 0x01884080}, | ||
| 329 | {0x00016548, 0x00008058}, | ||
| 330 | {0x00016780, 0x00000000}, | ||
| 331 | {0x00016784, 0x00000000}, | ||
| 332 | {0x00016788, 0x00800700}, | ||
| 333 | {0x0001678c, 0x00800700}, | ||
| 334 | {0x00016790, 0x00800700}, | ||
| 335 | {0x00016794, 0x00000000}, | ||
| 336 | {0x00016798, 0x00000000}, | ||
| 337 | {0x0001679c, 0x00000000}, | ||
| 338 | {0x000167a0, 0x00000001}, | ||
| 339 | {0x000167a4, 0x00000001}, | ||
| 340 | {0x000167a8, 0x00000000}, | ||
| 341 | {0x000167ac, 0x00000000}, | ||
| 342 | {0x000167b0, 0x00000000}, | ||
| 343 | {0x000167b4, 0x00000000}, | ||
| 344 | {0x000167b8, 0x00000000}, | ||
| 345 | {0x000167bc, 0x00000000}, | ||
| 346 | {0x000167c0, 0x000000a0}, | ||
| 347 | {0x000167c4, 0x000c0000}, | ||
| 348 | {0x000167c8, 0x14021402}, | ||
| 349 | {0x000167cc, 0x00001402}, | ||
| 350 | {0x000167d0, 0x00000000}, | ||
| 351 | {0x000167d4, 0x00000000}, | ||
| 352 | {0x00016800, 0x36db6db6}, | ||
| 353 | {0x00016804, 0x6db6db40}, | ||
| 354 | {0x00016808, 0x73f00000}, | ||
| 355 | {0x0001680c, 0x00000000}, | ||
| 356 | {0x00016840, 0x3f80fff8}, | ||
| 357 | {0x0001684c, 0x000f0278}, | ||
| 358 | {0x00016850, 0x8036db6c}, | ||
| 359 | {0x00016854, 0x6db60000}, | ||
| 360 | {0x00016900, 0x07ff8001}, | ||
| 361 | {0x00016908, 0x00080010}, | ||
| 362 | {0x00016944, 0x01884080}, | ||
| 363 | {0x00016948, 0x00008058}, | ||
| 364 | {0x00016b80, 0x00000000}, | ||
| 365 | {0x00016b84, 0x00000000}, | ||
| 366 | {0x00016b88, 0x00800700}, | ||
| 367 | {0x00016b8c, 0x00800700}, | ||
| 368 | {0x00016b90, 0x00800700}, | ||
| 369 | {0x00016b94, 0x00000000}, | ||
| 370 | {0x00016b98, 0x00000000}, | ||
| 371 | {0x00016b9c, 0x00000000}, | ||
| 372 | {0x00016ba0, 0x00000001}, | ||
| 373 | {0x00016ba4, 0x00000001}, | ||
| 374 | {0x00016ba8, 0x00000000}, | ||
| 375 | {0x00016bac, 0x00000000}, | ||
| 376 | {0x00016bb0, 0x00000000}, | ||
| 377 | {0x00016bb4, 0x00000000}, | ||
| 378 | {0x00016bb8, 0x00000000}, | ||
| 379 | {0x00016bbc, 0x00000000}, | ||
| 380 | {0x00016bc0, 0x000000a0}, | ||
| 381 | {0x00016bc4, 0x000c0000}, | ||
| 382 | {0x00016bc8, 0x14021402}, | ||
| 383 | {0x00016bcc, 0x00001402}, | ||
| 384 | {0x00016bd0, 0x00000000}, | ||
| 385 | {0x00016bd4, 0x00000000}, | ||
| 386 | }; | ||
| 387 | |||
| 388 | static const u32 qca956x_1p0_radio_postamble[][5] = { | ||
| 389 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 390 | {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xc4128f5c, 0xc4128f5c}, | ||
| 391 | {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x0fd08f25, 0x0fd08f25}, | ||
| 392 | {0x000160ac, 0xa4647c00, 0xa4647c00, 0x24646800, 0x24646800}, | ||
| 393 | {0x000160b0, 0x01885f52, 0x01885f52, 0x00fe7f46, 0x00fe7f46}, | ||
| 394 | {0x00016104, 0xb7a00000, 0xb7a00000, 0xfff80001, 0xfff80001}, | ||
| 395 | {0x0001610c, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000}, | ||
| 396 | {0x00016140, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, | ||
| 397 | {0x00016504, 0xb7a00000, 0xb7a00000, 0xfff80001, 0xfff80001}, | ||
| 398 | {0x0001650c, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000}, | ||
| 399 | {0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, | ||
| 400 | {0x00016904, 0xb7a00000, 0xb7a00000, 0xfff80001, 0xfff80001}, | ||
| 401 | {0x0001690c, 0xc0000000, 0xc0000000, 0x00000000, 0x00000000}, | ||
| 402 | {0x00016940, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, | ||
| 403 | }; | ||
| 404 | |||
| 405 | static const u32 qca956x_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { | ||
| 406 | /* Addr allmodes */ | ||
| 407 | {0x0000a38c, 0x00000000}, | ||
| 408 | {0x0000a390, 0x6f7f0301}, | ||
| 409 | {0x0000a394, 0xca9228ee}, | ||
| 410 | }; | ||
| 411 | |||
| 412 | static const u32 qca956x_1p0_modes_no_xpa_tx_gain_table[][3] = { | ||
| 413 | /* Addr 5G 2G */ | ||
| 414 | {0x0000a2dc, 0xffa9ac94, 0xffa9ac94}, | ||
| 415 | {0x0000a2e0, 0xff323118, 0xff323118}, | ||
| 416 | {0x0000a2e4, 0xff3ffe00, 0xff3ffe00}, | ||
| 417 | {0x0000a2e8, 0xffc00000, 0xffc00000}, | ||
| 418 | {0x0000a39c, 0x42424242, 0x42424242}, | ||
| 419 | {0x0000a3a4, 0x3a3e3e00, 0x3a3e3e00}, | ||
| 420 | {0x0000a3b0, 0x00a01404, 0x00a01404}, | ||
| 421 | {0x0000a3b4, 0x00000034, 0x00000034}, | ||
| 422 | {0x0000a3b8, 0x00800408, 0x00800408}, | ||
| 423 | {0x0000a3bc, 0x00000036, 0x00000036}, | ||
| 424 | {0x0000a410, 0x000050dc, 0x000050dc}, | ||
| 425 | {0x0000a500, 0x09000040, 0x09000040}, | ||
| 426 | {0x0000a504, 0x0b000041, 0x0b000041}, | ||
| 427 | {0x0000a508, 0x0d000042, 0x0d000042}, | ||
| 428 | {0x0000a50c, 0x11000044, 0x11000044}, | ||
| 429 | {0x0000a510, 0x15000046, 0x15000046}, | ||
| 430 | {0x0000a514, 0x1d000440, 0x1d000440}, | ||
| 431 | {0x0000a518, 0x1f000441, 0x1f000441}, | ||
| 432 | {0x0000a51c, 0x23000443, 0x23000443}, | ||
| 433 | {0x0000a520, 0x25000444, 0x25000444}, | ||
| 434 | {0x0000a524, 0x280004e0, 0x280004e0}, | ||
| 435 | {0x0000a528, 0x2c0004e2, 0x2c0004e2}, | ||
| 436 | {0x0000a52c, 0x2e0004e3, 0x2e0004e3}, | ||
| 437 | {0x0000a530, 0x300004e4, 0x300004e4}, | ||
| 438 | {0x0000a534, 0x340004e6, 0x340004e6}, | ||
| 439 | {0x0000a538, 0x37000ce0, 0x37000ce0}, | ||
| 440 | {0x0000a53c, 0x3b000ce2, 0x3b000ce2}, | ||
| 441 | {0x0000a540, 0x3d000ce3, 0x3d000ce3}, | ||
| 442 | {0x0000a544, 0x3f000ce4, 0x3f000ce4}, | ||
| 443 | {0x0000a548, 0x45001ee0, 0x45001ee0}, | ||
| 444 | {0x0000a54c, 0x49001ee2, 0x49001ee2}, | ||
| 445 | {0x0000a550, 0x4d001ee4, 0x4d001ee4}, | ||
| 446 | {0x0000a554, 0x51001ee6, 0x51001ee6}, | ||
| 447 | {0x0000a558, 0x55001eea, 0x55001eea}, | ||
| 448 | {0x0000a55c, 0x59001eec, 0x59001eec}, | ||
| 449 | {0x0000a560, 0x5d001ef0, 0x5d001ef0}, | ||
| 450 | {0x0000a564, 0x5f001ef1, 0x5f001ef1}, | ||
| 451 | {0x0000a568, 0x60001ef2, 0x60001ef2}, | ||
| 452 | {0x0000a56c, 0x61001ef3, 0x61001ef3}, | ||
| 453 | {0x0000a570, 0x62001ef4, 0x62001ef4}, | ||
| 454 | {0x0000a574, 0x63001ef5, 0x63001ef5}, | ||
| 455 | {0x0000a578, 0x64001ffc, 0x64001ffc}, | ||
| 456 | {0x0000a57c, 0x64001ffc, 0x64001ffc}, | ||
| 457 | {0x0000a600, 0x00000000, 0x00000000}, | ||
| 458 | {0x0000a604, 0x00000000, 0x00000000}, | ||
| 459 | {0x0000a608, 0x00000000, 0x00000000}, | ||
| 460 | {0x0000a60c, 0x00000000, 0x00000000}, | ||
| 461 | {0x0000a610, 0x00804000, 0x00804000}, | ||
| 462 | {0x0000a614, 0x00804201, 0x00804201}, | ||
| 463 | {0x0000a618, 0x00804201, 0x00804201}, | ||
| 464 | {0x0000a61c, 0x00804201, 0x00804201}, | ||
| 465 | {0x0000a620, 0x00804201, 0x00804201}, | ||
| 466 | {0x0000a624, 0x00804201, 0x00804201}, | ||
| 467 | {0x0000a628, 0x00804201, 0x00804201}, | ||
| 468 | {0x0000a62c, 0x02808a02, 0x02808a02}, | ||
| 469 | {0x0000a630, 0x0340cd03, 0x0340cd03}, | ||
| 470 | {0x0000a634, 0x0340cd03, 0x0340cd03}, | ||
| 471 | {0x0000a638, 0x0340cd03, 0x0340cd03}, | ||
| 472 | {0x0000a63c, 0x05011404, 0x05011404}, | ||
| 473 | {0x0000b2dc, 0xffa9ac94, 0xffa9ac94}, | ||
| 474 | {0x0000b2e0, 0xff323118, 0xff323118}, | ||
| 475 | {0x0000b2e4, 0xff3ffe00, 0xff3ffe00}, | ||
| 476 | {0x0000b2e8, 0xffc00000, 0xffc00000}, | ||
| 477 | {0x0000c2dc, 0xffa9ac94, 0xffa9ac94}, | ||
| 478 | {0x0000c2e0, 0xff323118, 0xff323118}, | ||
| 479 | {0x0000c2e4, 0xff3ffe00, 0xff3ffe00}, | ||
| 480 | {0x0000c2e8, 0xffc00000, 0xffc00000}, | ||
| 481 | {0x00016044, 0x049242db, 0x049242db}, | ||
| 482 | {0x00016048, 0x64925a70, 0x64925a70}, | ||
| 483 | {0x00016148, 0x00008050, 0x00008050}, | ||
| 484 | {0x00016280, 0x41110005, 0x41110005}, | ||
| 485 | {0x00016284, 0x453a6000, 0x453a6000}, | ||
| 486 | {0x00016444, 0x049242db, 0x049242db}, | ||
| 487 | {0x00016448, 0x6c925a70, 0x6c925a70}, | ||
| 488 | {0x00016548, 0x00008050, 0x00008050}, | ||
| 489 | {0x00016844, 0x049242db, 0x049242db}, | ||
| 490 | {0x00016848, 0x6c925a70, 0x6c925a70}, | ||
| 491 | {0x00016948, 0x00008050, 0x00008050}, | ||
| 492 | }; | ||
| 493 | |||
| 494 | static const u32 qca956x_1p0_modes_xpa_tx_gain_table[][3] = { | ||
| 495 | /* Addr 5G 2G */ | ||
| 496 | {0x0000a2dc, 0xcc69ac94, 0xcc69ac94}, | ||
| 497 | {0x0000a2e0, 0xf0b23118, 0xf0b23118}, | ||
| 498 | {0x0000a2e4, 0xffffc000, 0xffffc000}, | ||
| 499 | {0x0000a2e8, 0xc0000000, 0xc0000000}, | ||
| 500 | {0x0000a410, 0x000050d2, 0x000050d2}, | ||
| 501 | {0x0000a500, 0x0a000040, 0x0a000040}, | ||
| 502 | {0x0000a504, 0x0c000041, 0x0c000041}, | ||
| 503 | {0x0000a508, 0x0e000042, 0x0e000042}, | ||
| 504 | {0x0000a50c, 0x12000044, 0x12000044}, | ||
| 505 | {0x0000a510, 0x16000046, 0x16000046}, | ||
| 506 | {0x0000a514, 0x1d000440, 0x1d000440}, | ||
| 507 | {0x0000a518, 0x1f000441, 0x1f000441}, | ||
| 508 | {0x0000a51c, 0x23000443, 0x23000443}, | ||
| 509 | {0x0000a520, 0x25000444, 0x25000444}, | ||
| 510 | {0x0000a524, 0x29000a40, 0x29000a40}, | ||
| 511 | {0x0000a528, 0x2d000a42, 0x2d000a42}, | ||
| 512 | {0x0000a52c, 0x2f000a43, 0x2f000a43}, | ||
| 513 | {0x0000a530, 0x31000a44, 0x31000a44}, | ||
| 514 | {0x0000a534, 0x35000a46, 0x35000a46}, | ||
| 515 | {0x0000a538, 0x38000ce0, 0x38000ce0}, | ||
| 516 | {0x0000a53c, 0x3c000ce2, 0x3c000ce2}, | ||
| 517 | {0x0000a540, 0x3e000ce3, 0x3e000ce3}, | ||
| 518 | {0x0000a544, 0x40000ce4, 0x40000ce4}, | ||
| 519 | {0x0000a548, 0x46001ee0, 0x46001ee0}, | ||
| 520 | {0x0000a54c, 0x4a001ee2, 0x4a001ee2}, | ||
| 521 | {0x0000a550, 0x4e001ee4, 0x4e001ee4}, | ||
| 522 | {0x0000a554, 0x52001ee6, 0x52001ee6}, | ||
| 523 | {0x0000a558, 0x56001eea, 0x56001eea}, | ||
| 524 | {0x0000a55c, 0x5a001eec, 0x5a001eec}, | ||
| 525 | {0x0000a560, 0x5e001ef0, 0x5e001ef0}, | ||
| 526 | {0x0000a564, 0x60001ef1, 0x60001ef1}, | ||
| 527 | {0x0000a568, 0x61001ef2, 0x61001ef2}, | ||
| 528 | {0x0000a56c, 0x62001ef3, 0x62001ef3}, | ||
| 529 | {0x0000a570, 0x63001ef4, 0x63001ef4}, | ||
| 530 | {0x0000a574, 0x64001ef5, 0x64001ef5}, | ||
| 531 | {0x0000a578, 0x65001ffc, 0x65001ffc}, | ||
| 532 | {0x0000a57c, 0x65001ffc, 0x65001ffc}, | ||
| 533 | {0x0000a600, 0x00000000, 0x00000000}, | ||
| 534 | {0x0000a604, 0x00000000, 0x00000000}, | ||
| 535 | {0x0000a608, 0x00000000, 0x00000000}, | ||
| 536 | {0x0000a60c, 0x00000000, 0x00000000}, | ||
| 537 | {0x0000a610, 0x00000000, 0x00000000}, | ||
| 538 | {0x0000a614, 0x00000000, 0x00000000}, | ||
| 539 | {0x0000a618, 0x00000000, 0x00000000}, | ||
| 540 | {0x0000a61c, 0x00804201, 0x00804201}, | ||
| 541 | {0x0000a620, 0x00804201, 0x00804201}, | ||
| 542 | {0x0000a624, 0x00804201, 0x00804201}, | ||
| 543 | {0x0000a628, 0x00804201, 0x00804201}, | ||
| 544 | {0x0000a62c, 0x02808a02, 0x02808a02}, | ||
| 545 | {0x0000a630, 0x0340cd03, 0x0340cd03}, | ||
| 546 | {0x0000a634, 0x0340cd03, 0x0340cd03}, | ||
| 547 | {0x0000a638, 0x0340cd03, 0x0340cd03}, | ||
| 548 | {0x0000a63c, 0x05011404, 0x05011404}, | ||
| 549 | {0x0000b2dc, 0xcc69ac94, 0xcc69ac94}, | ||
| 550 | {0x0000b2e0, 0xf0b23118, 0xf0b23118}, | ||
| 551 | {0x0000b2e4, 0xffffc000, 0xffffc000}, | ||
| 552 | {0x0000b2e8, 0xc0000000, 0xc0000000}, | ||
| 553 | {0x0000c2dc, 0xcc69ac94, 0xcc69ac94}, | ||
| 554 | {0x0000c2e0, 0xf0b23118, 0xf0b23118}, | ||
| 555 | {0x0000c2e4, 0xffffc000, 0xffffc000}, | ||
| 556 | {0x0000c2e8, 0xc0000000, 0xc0000000}, | ||
| 557 | {0x00016044, 0x012492db, 0x012492db}, | ||
| 558 | {0x00016048, 0x6c927a70, 0x6c927a70}, | ||
| 559 | {0x00016050, 0x8036d36c, 0x8036d36c}, | ||
| 560 | {0x00016280, 0x41110005, 0x41110005}, | ||
| 561 | {0x00016284, 0x453a7e00, 0x453a7e00}, | ||
| 562 | {0x00016444, 0x012492db, 0x012492db}, | ||
| 563 | {0x00016448, 0x6c927a70, 0x6c927a70}, | ||
| 564 | {0x00016450, 0x8036d36c, 0x8036d36c}, | ||
| 565 | {0x00016844, 0x012492db, 0x012492db}, | ||
| 566 | {0x00016848, 0x6c927a70, 0x6c927a70}, | ||
| 567 | {0x00016850, 0x8036d36c, 0x8036d36c}, | ||
| 568 | }; | ||
| 569 | |||
| 570 | static const u32 qca956x_1p0_modes_no_xpa_low_ob_db_tx_gain_table[][3] = { | ||
| 571 | /* Addr 5G 2G */ | ||
| 572 | {0x0000a2dc, 0xffa9ac94, 0xffa9ac94}, | ||
| 573 | {0x0000a2e0, 0xff323118, 0xff323118}, | ||
| 574 | {0x0000a2e4, 0xff3ffe00, 0xff3ffe00}, | ||
| 575 | {0x0000a2e8, 0xffc00000, 0xffc00000}, | ||
| 576 | {0x0000a39c, 0x42424242, 0x42424242}, | ||
| 577 | {0x0000a3a4, 0x3a3e3e00, 0x3a3e3e00}, | ||
| 578 | {0x0000a3b0, 0x00a01404, 0x00a01404}, | ||
| 579 | {0x0000a3b4, 0x00000034, 0x00000034}, | ||
| 580 | {0x0000a3b8, 0x00800408, 0x00800408}, | ||
| 581 | {0x0000a3bc, 0x00000036, 0x00000036}, | ||
| 582 | {0x0000a410, 0x000050dc, 0x000050dc}, | ||
| 583 | {0x0000a414, 0x16b739ce, 0x16b739ce}, | ||
| 584 | {0x0000a418, 0x2d00198b, 0x2d00198b}, | ||
| 585 | {0x0000a41c, 0x16b5adce, 0x16b5adce}, | ||
| 586 | {0x0000a420, 0x0000014a, 0x0000014a}, | ||
| 587 | {0x0000a424, 0x14a525cc, 0x14a525cc}, | ||
| 588 | {0x0000a428, 0x0000012a, 0x0000012a}, | ||
| 589 | {0x0000a42c, 0x14a5294a, 0x14a5294a}, | ||
| 590 | {0x0000a430, 0x1294a929, 0x1294a929}, | ||
| 591 | {0x0000a500, 0x09000040, 0x09000040}, | ||
| 592 | {0x0000a504, 0x0b000041, 0x0b000041}, | ||
| 593 | {0x0000a508, 0x0d000042, 0x0d000042}, | ||
| 594 | {0x0000a50c, 0x11000044, 0x11000044}, | ||
| 595 | {0x0000a510, 0x15000046, 0x15000046}, | ||
| 596 | {0x0000a514, 0x1d000440, 0x1d000440}, | ||
| 597 | {0x0000a518, 0x1f000441, 0x1f000441}, | ||
| 598 | {0x0000a51c, 0x23000443, 0x23000443}, | ||
| 599 | {0x0000a520, 0x25000444, 0x25000444}, | ||
| 600 | {0x0000a524, 0x280004e0, 0x280004e0}, | ||
| 601 | {0x0000a528, 0x2c0004e2, 0x2c0004e2}, | ||
| 602 | {0x0000a52c, 0x2e0004e3, 0x2e0004e3}, | ||
| 603 | {0x0000a530, 0x300004e4, 0x300004e4}, | ||
| 604 | {0x0000a534, 0x340004e6, 0x340004e6}, | ||
| 605 | {0x0000a538, 0x37000ce0, 0x37000ce0}, | ||
| 606 | {0x0000a53c, 0x3b000ce2, 0x3b000ce2}, | ||
| 607 | {0x0000a540, 0x3d000ce3, 0x3d000ce3}, | ||
| 608 | {0x0000a544, 0x3f000ce4, 0x3f000ce4}, | ||
| 609 | {0x0000a548, 0x45001ee0, 0x45001ee0}, | ||
| 610 | {0x0000a54c, 0x49001ee2, 0x49001ee2}, | ||
| 611 | {0x0000a550, 0x4d001ee4, 0x4d001ee4}, | ||
| 612 | {0x0000a554, 0x51001ee6, 0x51001ee6}, | ||
| 613 | {0x0000a558, 0x55001eea, 0x55001eea}, | ||
| 614 | {0x0000a55c, 0x59001eec, 0x59001eec}, | ||
| 615 | {0x0000a560, 0x5d001ef0, 0x5d001ef0}, | ||
| 616 | {0x0000a564, 0x5f001ef1, 0x5f001ef1}, | ||
| 617 | {0x0000a568, 0x60001ef2, 0x60001ef2}, | ||
| 618 | {0x0000a56c, 0x61001ef3, 0x61001ef3}, | ||
| 619 | {0x0000a570, 0x62001ef4, 0x62001ef4}, | ||
| 620 | {0x0000a574, 0x63001ef5, 0x63001ef5}, | ||
| 621 | {0x0000a578, 0x64001ffc, 0x64001ffc}, | ||
| 622 | {0x0000a57c, 0x64001ffc, 0x64001ffc}, | ||
| 623 | {0x0000a600, 0x00000000, 0x00000000}, | ||
| 624 | {0x0000a604, 0x00000000, 0x00000000}, | ||
| 625 | {0x0000a608, 0x00000000, 0x00000000}, | ||
| 626 | {0x0000a60c, 0x00000000, 0x00000000}, | ||
| 627 | {0x0000a610, 0x00804000, 0x00804000}, | ||
| 628 | {0x0000a614, 0x00804201, 0x00804201}, | ||
| 629 | {0x0000a618, 0x00804201, 0x00804201}, | ||
| 630 | {0x0000a61c, 0x00804201, 0x00804201}, | ||
| 631 | {0x0000a620, 0x00804201, 0x00804201}, | ||
| 632 | {0x0000a624, 0x00804201, 0x00804201}, | ||
| 633 | {0x0000a628, 0x00804201, 0x00804201}, | ||
| 634 | {0x0000a62c, 0x02808a02, 0x02808a02}, | ||
| 635 | {0x0000a630, 0x0340cd03, 0x0340cd03}, | ||
| 636 | {0x0000a634, 0x0340cd03, 0x0340cd03}, | ||
| 637 | {0x0000a638, 0x0340cd03, 0x0340cd03}, | ||
| 638 | {0x0000a63c, 0x05011404, 0x05011404}, | ||
| 639 | {0x0000b2dc, 0xffa9ac94, 0xffa9ac94}, | ||
| 640 | {0x0000b2e0, 0xff323118, 0xff323118}, | ||
| 641 | {0x0000b2e4, 0xff3ffe00, 0xff3ffe00}, | ||
| 642 | {0x0000b2e8, 0xffc00000, 0xffc00000}, | ||
| 643 | {0x0000c2dc, 0xffa9ac94, 0xffa9ac94}, | ||
| 644 | {0x0000c2e0, 0xff323118, 0xff323118}, | ||
| 645 | {0x0000c2e4, 0xff3ffe00, 0xff3ffe00}, | ||
| 646 | {0x0000c2e8, 0xffc00000, 0xffc00000}, | ||
| 647 | {0x00016044, 0x046e42db, 0x046e42db}, | ||
| 648 | {0x00016048, 0x64925a70, 0x64925a70}, | ||
| 649 | {0x00016148, 0x00008050, 0x00008050}, | ||
| 650 | {0x00016280, 0x41110005, 0x41110005}, | ||
| 651 | {0x00016284, 0x453a6000, 0x453a6000}, | ||
| 652 | {0x00016444, 0x046e42db, 0x046e42db}, | ||
| 653 | {0x00016448, 0x6c925a70, 0x6c925a70}, | ||
| 654 | {0x00016548, 0x00008050, 0x00008050}, | ||
| 655 | {0x00016844, 0x046e42db, 0x046e42db}, | ||
| 656 | {0x00016848, 0x6c925a70, 0x6c925a70}, | ||
| 657 | {0x00016948, 0x00008050, 0x00008050}, | ||
| 658 | }; | ||
| 659 | |||
| 660 | static const u32 qca956x_1p0_modes_no_xpa_green_tx_gain_table[][3] = { | ||
| 661 | /* Addr 5G 2G */ | ||
| 662 | {0x000098bc, 0x00000001, 0x00000001}, | ||
| 663 | {0x0000a2dc, 0xd3555284, 0xd3555284}, | ||
| 664 | {0x0000a2e0, 0x1c666318, 0x1c666318}, | ||
| 665 | {0x0000a2e4, 0xe07bbc00, 0xe07bbc00}, | ||
| 666 | {0x0000a2e8, 0xff800000, 0xff800000}, | ||
| 667 | {0x0000a3a4, 0x3a3e3e00, 0x3a3e3e00}, | ||
| 668 | {0x0000a410, 0x000050dc, 0x000050dc}, | ||
| 669 | {0x0000a500, 0x02000040, 0x02000040}, | ||
| 670 | {0x0000a504, 0x04000041, 0x04000041}, | ||
| 671 | {0x0000a508, 0x06000042, 0x06000042}, | ||
| 672 | {0x0000a50c, 0x0a000044, 0x0a000044}, | ||
| 673 | {0x0000a510, 0x0c000045, 0x0c000045}, | ||
| 674 | {0x0000a514, 0x13000440, 0x13000440}, | ||
| 675 | {0x0000a518, 0x15000441, 0x15000441}, | ||
| 676 | {0x0000a51c, 0x19000443, 0x19000443}, | ||
| 677 | {0x0000a520, 0x1b000444, 0x1b000444}, | ||
| 678 | {0x0000a524, 0x1e0004e0, 0x1e0004e0}, | ||
| 679 | {0x0000a528, 0x220004e2, 0x220004e2}, | ||
| 680 | {0x0000a52c, 0x240004e3, 0x240004e3}, | ||
| 681 | {0x0000a530, 0x260004e4, 0x260004e4}, | ||
| 682 | {0x0000a534, 0x2a0004e6, 0x2a0004e6}, | ||
| 683 | {0x0000a538, 0x32000ce0, 0x32000ce0}, | ||
| 684 | {0x0000a53c, 0x36000ce2, 0x36000ce2}, | ||
| 685 | {0x0000a540, 0x3a000ce4, 0x3a000ce4}, | ||
| 686 | {0x0000a544, 0x3e000ce6, 0x3e000ce6}, | ||
| 687 | {0x0000a548, 0x45001ee0, 0x45001ee0}, | ||
| 688 | {0x0000a54c, 0x49001ee2, 0x49001ee2}, | ||
| 689 | {0x0000a550, 0x4d001ee4, 0x4d001ee4}, | ||
| 690 | {0x0000a554, 0x51001ee6, 0x51001ee6}, | ||
| 691 | {0x0000a558, 0x55001eea, 0x55001eea}, | ||
| 692 | {0x0000a55c, 0x59001eec, 0x59001eec}, | ||
| 693 | {0x0000a560, 0x5d001ef0, 0x5d001ef0}, | ||
| 694 | {0x0000a564, 0x5f001ef1, 0x5f001ef1}, | ||
| 695 | {0x0000a568, 0x60001ef2, 0x60001ef2}, | ||
| 696 | {0x0000a56c, 0x61001ef3, 0x61001ef3}, | ||
| 697 | {0x0000a570, 0x62001ef4, 0x62001ef4}, | ||
| 698 | {0x0000a574, 0x63001ff5, 0x63001ff5}, | ||
| 699 | {0x0000a578, 0x64001ffc, 0x64001ffc}, | ||
| 700 | {0x0000a57c, 0x64001ffc, 0x64001ffc}, | ||
| 701 | {0x0000a600, 0x00000000, 0x00000000}, | ||
| 702 | {0x0000a604, 0x00000000, 0x00000000}, | ||
| 703 | {0x0000a608, 0x00000000, 0x00000000}, | ||
| 704 | {0x0000a60c, 0x00000000, 0x00000000}, | ||
| 705 | {0x0000a610, 0x00804000, 0x00804000}, | ||
| 706 | {0x0000a614, 0x00804201, 0x00804201}, | ||
| 707 | {0x0000a618, 0x00804201, 0x00804201}, | ||
| 708 | {0x0000a61c, 0x00804201, 0x00804201}, | ||
| 709 | {0x0000a620, 0x00804201, 0x00804201}, | ||
| 710 | {0x0000a624, 0x00804201, 0x00804201}, | ||
| 711 | {0x0000a628, 0x00804201, 0x00804201}, | ||
| 712 | {0x0000a62c, 0x02808a02, 0x02808a02}, | ||
| 713 | {0x0000a630, 0x0340cd03, 0x0340cd03}, | ||
| 714 | {0x0000a634, 0x0340cd03, 0x0340cd03}, | ||
| 715 | {0x0000a638, 0x0340cd03, 0x0340cd03}, | ||
| 716 | {0x0000a63c, 0x05011404, 0x05011404}, | ||
| 717 | {0x0000b2dc, 0xd3555284, 0xd3555284}, | ||
| 718 | {0x0000b2e0, 0x1c666318, 0x1c666318}, | ||
| 719 | {0x0000b2e4, 0xe07bbc00, 0xe07bbc00}, | ||
| 720 | {0x0000b2e8, 0xff800000, 0xff800000}, | ||
| 721 | {0x0000c2dc, 0xd3555284, 0xd3555284}, | ||
| 722 | {0x0000c2e0, 0x1c666318, 0x1c666318}, | ||
| 723 | {0x0000c2e4, 0xe07bbc00, 0xe07bbc00}, | ||
| 724 | {0x0000c2e8, 0xff800000, 0xff800000}, | ||
| 725 | {0x00016044, 0x849242db, 0x849242db}, | ||
| 726 | {0x00016048, 0x64925a70, 0x64925a70}, | ||
| 727 | {0x00016280, 0x41110005, 0x41110005}, | ||
| 728 | {0x00016284, 0x453a6000, 0x453a6000}, | ||
| 729 | {0x00016444, 0x849242db, 0x849242db}, | ||
| 730 | {0x00016448, 0x6c925a70, 0x6c925a70}, | ||
| 731 | {0x00016844, 0x849242db, 0x849242db}, | ||
| 732 | {0x00016848, 0x6c925a70, 0x6c925a70}, | ||
| 733 | {0x0000a7f0, 0x800002cc, 0x800002cc}, | ||
| 734 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 735 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 736 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 737 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 738 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 739 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 740 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 741 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 742 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 743 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 744 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 745 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 746 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 747 | {0x0000a7f4, 0x00000018, 0x00000018}, | ||
| 748 | {0x0000a7f4, 0x00000028, 0x00000028}, | ||
| 749 | {0x0000a7f4, 0x00000028, 0x00000028}, | ||
| 750 | {0x0000a7f4, 0x00000028, 0x00000028}, | ||
| 751 | {0x0000a7f4, 0x00000028, 0x00000028}, | ||
| 752 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 753 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 754 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 755 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 756 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 757 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 758 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 759 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 760 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 761 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 762 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 763 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 764 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 765 | {0x0000a7f4, 0x00000048, 0x00000048}, | ||
| 766 | }; | ||
| 767 | |||
| 768 | static const u32 qca956x_1p0_common_rx_gain_table[][2] = { | ||
| 769 | /* Addr allmodes */ | ||
| 770 | {0x0000a000, 0x00010000}, | ||
| 771 | {0x0000a004, 0x00030002}, | ||
| 772 | {0x0000a008, 0x00050004}, | ||
| 773 | {0x0000a00c, 0x00810080}, | ||
| 774 | {0x0000a010, 0x00830082}, | ||
| 775 | {0x0000a014, 0x01810180}, | ||
| 776 | {0x0000a018, 0x01830182}, | ||
| 777 | {0x0000a01c, 0x01850184}, | ||
| 778 | {0x0000a020, 0x01890188}, | ||
| 779 | {0x0000a024, 0x018b018a}, | ||
| 780 | {0x0000a028, 0x018d018c}, | ||
| 781 | {0x0000a02c, 0x01910190}, | ||
| 782 | {0x0000a030, 0x01930192}, | ||
| 783 | {0x0000a034, 0x01950194}, | ||
| 784 | {0x0000a038, 0x038a0196}, | ||
| 785 | {0x0000a03c, 0x038c038b}, | ||
| 786 | {0x0000a040, 0x0390038d}, | ||
| 787 | {0x0000a044, 0x03920391}, | ||
| 788 | {0x0000a048, 0x03940393}, | ||
| 789 | {0x0000a04c, 0x03960395}, | ||
| 790 | {0x0000a050, 0x00000000}, | ||
| 791 | {0x0000a054, 0x00000000}, | ||
| 792 | {0x0000a058, 0x00000000}, | ||
| 793 | {0x0000a05c, 0x00000000}, | ||
| 794 | {0x0000a060, 0x00000000}, | ||
| 795 | {0x0000a064, 0x00000000}, | ||
| 796 | {0x0000a068, 0x00000000}, | ||
| 797 | {0x0000a06c, 0x00000000}, | ||
| 798 | {0x0000a070, 0x00000000}, | ||
| 799 | {0x0000a074, 0x00000000}, | ||
| 800 | {0x0000a078, 0x00000000}, | ||
| 801 | {0x0000a07c, 0x00000000}, | ||
| 802 | {0x0000a080, 0x22222222}, | ||
| 803 | {0x0000a084, 0x1d1d1d1d}, | ||
| 804 | {0x0000a088, 0x1d1d1d1d}, | ||
| 805 | {0x0000a08c, 0x1d1d1d1d}, | ||
| 806 | {0x0000a090, 0x17171717}, | ||
| 807 | {0x0000a094, 0x11111717}, | ||
| 808 | {0x0000a098, 0x00030311}, | ||
| 809 | {0x0000a09c, 0x00000000}, | ||
| 810 | {0x0000a0a0, 0x00000000}, | ||
| 811 | {0x0000a0a4, 0x00000000}, | ||
| 812 | {0x0000a0a8, 0x00000000}, | ||
| 813 | {0x0000a0ac, 0x00000000}, | ||
| 814 | {0x0000a0b0, 0x00000000}, | ||
| 815 | {0x0000a0b4, 0x00000000}, | ||
| 816 | {0x0000a0b8, 0x00000000}, | ||
| 817 | {0x0000a0bc, 0x00000000}, | ||
| 818 | {0x0000a0c0, 0x001f0000}, | ||
| 819 | {0x0000a0c4, 0x01000101}, | ||
| 820 | {0x0000a0c8, 0x011e011f}, | ||
| 821 | {0x0000a0cc, 0x011c011d}, | ||
| 822 | {0x0000a0d0, 0x02030204}, | ||
| 823 | {0x0000a0d4, 0x02010202}, | ||
| 824 | {0x0000a0d8, 0x021f0200}, | ||
| 825 | {0x0000a0dc, 0x0302021e}, | ||
| 826 | {0x0000a0e0, 0x03000301}, | ||
| 827 | {0x0000a0e4, 0x031e031f}, | ||
| 828 | {0x0000a0e8, 0x0402031d}, | ||
| 829 | {0x0000a0ec, 0x04000401}, | ||
| 830 | {0x0000a0f0, 0x041e041f}, | ||
| 831 | {0x0000a0f4, 0x0502041d}, | ||
| 832 | {0x0000a0f8, 0x05000501}, | ||
| 833 | {0x0000a0fc, 0x051e051f}, | ||
| 834 | {0x0000a100, 0x06010602}, | ||
| 835 | {0x0000a104, 0x061f0600}, | ||
| 836 | {0x0000a108, 0x061d061e}, | ||
| 837 | {0x0000a10c, 0x07020703}, | ||
| 838 | {0x0000a110, 0x07000701}, | ||
| 839 | {0x0000a114, 0x00000000}, | ||
| 840 | {0x0000a118, 0x00000000}, | ||
| 841 | {0x0000a11c, 0x00000000}, | ||
| 842 | {0x0000a120, 0x00000000}, | ||
| 843 | {0x0000a124, 0x00000000}, | ||
| 844 | {0x0000a128, 0x00000000}, | ||
| 845 | {0x0000a12c, 0x00000000}, | ||
| 846 | {0x0000a130, 0x00000000}, | ||
| 847 | {0x0000a134, 0x00000000}, | ||
| 848 | {0x0000a138, 0x00000000}, | ||
| 849 | {0x0000a13c, 0x00000000}, | ||
| 850 | {0x0000a140, 0x001f0000}, | ||
| 851 | {0x0000a144, 0x01000101}, | ||
| 852 | {0x0000a148, 0x011e011f}, | ||
| 853 | {0x0000a14c, 0x011c011d}, | ||
| 854 | {0x0000a150, 0x02030204}, | ||
| 855 | {0x0000a154, 0x02010202}, | ||
| 856 | {0x0000a158, 0x021f0200}, | ||
| 857 | {0x0000a15c, 0x0302021e}, | ||
| 858 | {0x0000a160, 0x03000301}, | ||
| 859 | {0x0000a164, 0x031e031f}, | ||
| 860 | {0x0000a168, 0x0402031d}, | ||
| 861 | {0x0000a16c, 0x04000401}, | ||
| 862 | {0x0000a170, 0x041e041f}, | ||
| 863 | {0x0000a174, 0x0502041d}, | ||
| 864 | {0x0000a178, 0x05000501}, | ||
| 865 | {0x0000a17c, 0x051e051f}, | ||
| 866 | {0x0000a180, 0x06010602}, | ||
| 867 | {0x0000a184, 0x061f0600}, | ||
| 868 | {0x0000a188, 0x061d061e}, | ||
| 869 | {0x0000a18c, 0x07020703}, | ||
| 870 | {0x0000a190, 0x07000701}, | ||
| 871 | {0x0000a194, 0x00000000}, | ||
| 872 | {0x0000a198, 0x00000000}, | ||
| 873 | {0x0000a19c, 0x00000000}, | ||
| 874 | {0x0000a1a0, 0x00000000}, | ||
| 875 | {0x0000a1a4, 0x00000000}, | ||
| 876 | {0x0000a1a8, 0x00000000}, | ||
| 877 | {0x0000a1ac, 0x00000000}, | ||
| 878 | {0x0000a1b0, 0x00000000}, | ||
| 879 | {0x0000a1b4, 0x00000000}, | ||
| 880 | {0x0000a1b8, 0x00000000}, | ||
| 881 | {0x0000a1bc, 0x00000000}, | ||
| 882 | {0x0000a1c0, 0x00000000}, | ||
| 883 | {0x0000a1c4, 0x00000000}, | ||
| 884 | {0x0000a1c8, 0x00000000}, | ||
| 885 | {0x0000a1cc, 0x00000000}, | ||
| 886 | {0x0000a1d0, 0x00000000}, | ||
| 887 | {0x0000a1d4, 0x00000000}, | ||
| 888 | {0x0000a1d8, 0x00000000}, | ||
| 889 | {0x0000a1dc, 0x00000000}, | ||
| 890 | {0x0000a1e0, 0x00000000}, | ||
| 891 | {0x0000a1e4, 0x00000000}, | ||
| 892 | {0x0000a1e8, 0x00000000}, | ||
| 893 | {0x0000a1ec, 0x00000000}, | ||
| 894 | {0x0000a1f0, 0x00000396}, | ||
| 895 | {0x0000a1f4, 0x00000396}, | ||
| 896 | {0x0000a1f8, 0x00000396}, | ||
| 897 | {0x0000a1fc, 0x00000196}, | ||
| 898 | {0x0000b000, 0x00010000}, | ||
| 899 | {0x0000b004, 0x00030002}, | ||
| 900 | {0x0000b008, 0x00050004}, | ||
| 901 | {0x0000b00c, 0x00810080}, | ||
| 902 | {0x0000b010, 0x00830082}, | ||
| 903 | {0x0000b014, 0x01810180}, | ||
| 904 | {0x0000b018, 0x01830182}, | ||
| 905 | {0x0000b01c, 0x01850184}, | ||
| 906 | {0x0000b020, 0x02810280}, | ||
| 907 | {0x0000b024, 0x02830282}, | ||
| 908 | {0x0000b028, 0x02850284}, | ||
| 909 | {0x0000b02c, 0x02890288}, | ||
| 910 | {0x0000b030, 0x028b028a}, | ||
| 911 | {0x0000b034, 0x0388028c}, | ||
| 912 | {0x0000b038, 0x038a0389}, | ||
| 913 | {0x0000b03c, 0x038c038b}, | ||
| 914 | {0x0000b040, 0x0390038d}, | ||
| 915 | {0x0000b044, 0x03920391}, | ||
| 916 | {0x0000b048, 0x03940393}, | ||
| 917 | {0x0000b04c, 0x03960395}, | ||
| 918 | {0x0000b050, 0x00000000}, | ||
| 919 | {0x0000b054, 0x00000000}, | ||
| 920 | {0x0000b058, 0x00000000}, | ||
| 921 | {0x0000b05c, 0x00000000}, | ||
| 922 | {0x0000b060, 0x00000000}, | ||
| 923 | {0x0000b064, 0x00000000}, | ||
| 924 | {0x0000b068, 0x00000000}, | ||
| 925 | {0x0000b06c, 0x00000000}, | ||
| 926 | {0x0000b070, 0x00000000}, | ||
| 927 | {0x0000b074, 0x00000000}, | ||
| 928 | {0x0000b078, 0x00000000}, | ||
| 929 | {0x0000b07c, 0x00000000}, | ||
| 930 | {0x0000b080, 0x23232323}, | ||
| 931 | {0x0000b084, 0x21232323}, | ||
| 932 | {0x0000b088, 0x19191c1e}, | ||
| 933 | {0x0000b08c, 0x12141417}, | ||
| 934 | {0x0000b090, 0x07070e0e}, | ||
| 935 | {0x0000b094, 0x03030305}, | ||
| 936 | {0x0000b098, 0x00000003}, | ||
| 937 | {0x0000b09c, 0x00000000}, | ||
| 938 | {0x0000b0a0, 0x00000000}, | ||
| 939 | {0x0000b0a4, 0x00000000}, | ||
| 940 | {0x0000b0a8, 0x00000000}, | ||
| 941 | {0x0000b0ac, 0x00000000}, | ||
| 942 | {0x0000b0b0, 0x00000000}, | ||
| 943 | {0x0000b0b4, 0x00000000}, | ||
| 944 | {0x0000b0b8, 0x00000000}, | ||
| 945 | {0x0000b0bc, 0x00000000}, | ||
| 946 | {0x0000b0c0, 0x003f0020}, | ||
| 947 | {0x0000b0c4, 0x00400041}, | ||
| 948 | {0x0000b0c8, 0x0140005f}, | ||
| 949 | {0x0000b0cc, 0x0160015f}, | ||
| 950 | {0x0000b0d0, 0x017e017f}, | ||
| 951 | {0x0000b0d4, 0x02410242}, | ||
| 952 | {0x0000b0d8, 0x025f0240}, | ||
| 953 | {0x0000b0dc, 0x027f0260}, | ||
| 954 | {0x0000b0e0, 0x0341027e}, | ||
| 955 | {0x0000b0e4, 0x035f0340}, | ||
| 956 | {0x0000b0e8, 0x037f0360}, | ||
| 957 | {0x0000b0ec, 0x04400441}, | ||
| 958 | {0x0000b0f0, 0x0460045f}, | ||
| 959 | {0x0000b0f4, 0x0541047f}, | ||
| 960 | {0x0000b0f8, 0x055f0540}, | ||
| 961 | {0x0000b0fc, 0x057f0560}, | ||
| 962 | {0x0000b100, 0x06400641}, | ||
| 963 | {0x0000b104, 0x0660065f}, | ||
| 964 | {0x0000b108, 0x067e067f}, | ||
| 965 | {0x0000b10c, 0x07410742}, | ||
| 966 | {0x0000b110, 0x075f0740}, | ||
| 967 | {0x0000b114, 0x077f0760}, | ||
| 968 | {0x0000b118, 0x07800781}, | ||
| 969 | {0x0000b11c, 0x07a0079f}, | ||
| 970 | {0x0000b120, 0x07c107bf}, | ||
| 971 | {0x0000b124, 0x000007c0}, | ||
| 972 | {0x0000b128, 0x00000000}, | ||
| 973 | {0x0000b12c, 0x00000000}, | ||
| 974 | {0x0000b130, 0x00000000}, | ||
| 975 | {0x0000b134, 0x00000000}, | ||
| 976 | {0x0000b138, 0x00000000}, | ||
| 977 | {0x0000b13c, 0x00000000}, | ||
| 978 | {0x0000b140, 0x003f0020}, | ||
| 979 | {0x0000b144, 0x00400041}, | ||
| 980 | {0x0000b148, 0x0140005f}, | ||
| 981 | {0x0000b14c, 0x0160015f}, | ||
| 982 | {0x0000b150, 0x017e017f}, | ||
| 983 | {0x0000b154, 0x02410242}, | ||
| 984 | {0x0000b158, 0x025f0240}, | ||
| 985 | {0x0000b15c, 0x027f0260}, | ||
| 986 | {0x0000b160, 0x0341027e}, | ||
| 987 | {0x0000b164, 0x035f0340}, | ||
| 988 | {0x0000b168, 0x037f0360}, | ||
| 989 | {0x0000b16c, 0x04400441}, | ||
| 990 | {0x0000b170, 0x0460045f}, | ||
| 991 | {0x0000b174, 0x0541047f}, | ||
| 992 | {0x0000b178, 0x055f0540}, | ||
| 993 | {0x0000b17c, 0x057f0560}, | ||
| 994 | {0x0000b180, 0x06400641}, | ||
| 995 | {0x0000b184, 0x0660065f}, | ||
| 996 | {0x0000b188, 0x067e067f}, | ||
| 997 | {0x0000b18c, 0x07410742}, | ||
| 998 | {0x0000b190, 0x075f0740}, | ||
| 999 | {0x0000b194, 0x077f0760}, | ||
| 1000 | {0x0000b198, 0x07800781}, | ||
| 1001 | {0x0000b19c, 0x07a0079f}, | ||
| 1002 | {0x0000b1a0, 0x07c107bf}, | ||
| 1003 | {0x0000b1a4, 0x000007c0}, | ||
| 1004 | {0x0000b1a8, 0x00000000}, | ||
| 1005 | {0x0000b1ac, 0x00000000}, | ||
| 1006 | {0x0000b1b0, 0x00000000}, | ||
| 1007 | {0x0000b1b4, 0x00000000}, | ||
| 1008 | {0x0000b1b8, 0x00000000}, | ||
| 1009 | {0x0000b1bc, 0x00000000}, | ||
| 1010 | {0x0000b1c0, 0x00000000}, | ||
| 1011 | {0x0000b1c4, 0x00000000}, | ||
| 1012 | {0x0000b1c8, 0x00000000}, | ||
| 1013 | {0x0000b1cc, 0x00000000}, | ||
| 1014 | {0x0000b1d0, 0x00000000}, | ||
| 1015 | {0x0000b1d4, 0x00000000}, | ||
| 1016 | {0x0000b1d8, 0x00000000}, | ||
| 1017 | {0x0000b1dc, 0x00000000}, | ||
| 1018 | {0x0000b1e0, 0x00000000}, | ||
| 1019 | {0x0000b1e4, 0x00000000}, | ||
| 1020 | {0x0000b1e8, 0x00000000}, | ||
| 1021 | {0x0000b1ec, 0x00000000}, | ||
| 1022 | {0x0000b1f0, 0x00000396}, | ||
| 1023 | {0x0000b1f4, 0x00000396}, | ||
| 1024 | {0x0000b1f8, 0x00000396}, | ||
| 1025 | {0x0000b1fc, 0x00000196}, | ||
| 1026 | }; | ||
| 1027 | |||
| 1028 | static const u32 qca956x_1p0_xlna_only[][5] = { | ||
| 1029 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 1030 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae}, | ||
| 1031 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac621f1, 0x5ac621f1}, | ||
| 1032 | {0x00009828, 0x06903081, 0x06903081, 0x07d43881, 0x07d43881}, | ||
| 1033 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x03721720}, | ||
| 1034 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000de, 0x6c4000da}, | ||
| 1035 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec86d2e, 0x7ec8ad2e}, | ||
| 1036 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x317a6062, 0x317a5ae2}, | ||
| 1037 | {0x00009e18, 0x00000000, 0x00000000, 0x03c00000, 0x03c00000}, | ||
| 1038 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003b2, 0x000003b2}, | ||
| 1039 | {0x00009fc0, 0x813e4788, 0x813e4788, 0x813e4789, 0x813e4789}, | ||
| 1040 | {0x0000ae18, 0x00000000, 0x00000000, 0x03c00000, 0x03c00000}, | ||
| 1041 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001b2, 0x000001b2}, | ||
| 1042 | {0x0000be18, 0x00000000, 0x00000000, 0x03c00000, 0x03c00000}, | ||
| 1043 | {0x0000be20, 0x000001b5, 0x000001b5, 0x000001b2, 0x000001b2}, | ||
| 1044 | }; | ||
| 1045 | |||
| 1046 | #endif /* INITVALS_956X_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1a9fe0983a6b..0f8e9464e4ab 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
| @@ -34,7 +34,7 @@ struct ath_vif; | |||
| 34 | 34 | ||
| 35 | extern struct ieee80211_ops ath9k_ops; | 35 | extern struct ieee80211_ops ath9k_ops; |
| 36 | extern int ath9k_modparam_nohwcrypt; | 36 | extern int ath9k_modparam_nohwcrypt; |
| 37 | extern int led_blink; | 37 | extern int ath9k_led_blink; |
| 38 | extern bool is_ath9k_unloaded; | 38 | extern bool is_ath9k_unloaded; |
| 39 | extern int ath9k_use_chanctx; | 39 | extern int ath9k_use_chanctx; |
| 40 | 40 | ||
| @@ -830,14 +830,9 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) | |||
| 830 | /* Wake on Wireless LAN */ | 830 | /* Wake on Wireless LAN */ |
| 831 | /************************/ | 831 | /************************/ |
| 832 | 832 | ||
| 833 | struct ath9k_wow_pattern { | ||
| 834 | u8 pattern_bytes[MAX_PATTERN_SIZE]; | ||
| 835 | u8 mask_bytes[MAX_PATTERN_SIZE]; | ||
| 836 | u32 pattern_len; | ||
| 837 | }; | ||
| 838 | |||
| 839 | #ifdef CONFIG_ATH9K_WOW | 833 | #ifdef CONFIG_ATH9K_WOW |
| 840 | void ath9k_init_wow(struct ieee80211_hw *hw); | 834 | void ath9k_init_wow(struct ieee80211_hw *hw); |
| 835 | void ath9k_deinit_wow(struct ieee80211_hw *hw); | ||
| 841 | int ath9k_suspend(struct ieee80211_hw *hw, | 836 | int ath9k_suspend(struct ieee80211_hw *hw, |
| 842 | struct cfg80211_wowlan *wowlan); | 837 | struct cfg80211_wowlan *wowlan); |
| 843 | int ath9k_resume(struct ieee80211_hw *hw); | 838 | int ath9k_resume(struct ieee80211_hw *hw); |
| @@ -846,6 +841,9 @@ void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled); | |||
| 846 | static inline void ath9k_init_wow(struct ieee80211_hw *hw) | 841 | static inline void ath9k_init_wow(struct ieee80211_hw *hw) |
| 847 | { | 842 | { |
| 848 | } | 843 | } |
| 844 | static inline void ath9k_deinit_wow(struct ieee80211_hw *hw) | ||
| 845 | { | ||
| 846 | } | ||
| 849 | static inline int ath9k_suspend(struct ieee80211_hw *hw, | 847 | static inline int ath9k_suspend(struct ieee80211_hw *hw, |
| 850 | struct cfg80211_wowlan *wowlan) | 848 | struct cfg80211_wowlan *wowlan) |
| 851 | { | 849 | { |
| @@ -1039,9 +1037,8 @@ struct ath_softc { | |||
| 1039 | s16 tx99_power; | 1037 | s16 tx99_power; |
| 1040 | 1038 | ||
| 1041 | #ifdef CONFIG_ATH9K_WOW | 1039 | #ifdef CONFIG_ATH9K_WOW |
| 1042 | atomic_t wow_got_bmiss_intr; | ||
| 1043 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ | ||
| 1044 | u32 wow_intr_before_sleep; | 1040 | u32 wow_intr_before_sleep; |
| 1041 | bool force_wow; | ||
| 1045 | #endif | 1042 | #endif |
| 1046 | }; | 1043 | }; |
| 1047 | 1044 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index ec93ddf0863a..5cee231cca1f 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c | |||
| @@ -582,7 +582,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = { | |||
| 582 | 582 | ||
| 583 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) | 583 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) |
| 584 | { | 584 | { |
| 585 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { | 585 | if (config_enabled(CONFIG_ATH9K_DEBUGFS)) { |
| 586 | relay_close(spec_priv->rfs_chan_spec_scan); | 586 | relay_close(spec_priv->rfs_chan_spec_scan); |
| 587 | spec_priv->rfs_chan_spec_scan = NULL; | 587 | spec_priv->rfs_chan_spec_scan = NULL; |
| 588 | } | 588 | } |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index c43e2ad36587..50a2e0ac3b8b 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
| @@ -403,7 +403,8 @@ static const struct file_operations fops_antenna_diversity = { | |||
| 403 | 403 | ||
| 404 | static int read_file_dma(struct seq_file *file, void *data) | 404 | static int read_file_dma(struct seq_file *file, void *data) |
| 405 | { | 405 | { |
| 406 | struct ath_softc *sc = file->private; | 406 | struct ieee80211_hw *hw = dev_get_drvdata(file->private); |
| 407 | struct ath_softc *sc = hw->priv; | ||
| 407 | struct ath_hw *ah = sc->sc_ah; | 408 | struct ath_hw *ah = sc->sc_ah; |
| 408 | u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; | 409 | u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; |
| 409 | int i, qcuOffset = 0, dcuOffset = 0; | 410 | int i, qcuOffset = 0, dcuOffset = 0; |
| @@ -470,20 +471,6 @@ static int read_file_dma(struct seq_file *file, void *data) | |||
| 470 | return 0; | 471 | return 0; |
| 471 | } | 472 | } |
| 472 | 473 | ||
| 473 | static int open_file_dma(struct inode *inode, struct file *f) | ||
| 474 | { | ||
| 475 | return single_open(f, read_file_dma, inode->i_private); | ||
| 476 | } | ||
| 477 | |||
| 478 | static const struct file_operations fops_dma = { | ||
| 479 | .open = open_file_dma, | ||
| 480 | .read = seq_read, | ||
| 481 | .owner = THIS_MODULE, | ||
| 482 | .llseek = seq_lseek, | ||
| 483 | .release = single_release, | ||
| 484 | }; | ||
| 485 | |||
| 486 | |||
| 487 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) | 474 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) |
| 488 | { | 475 | { |
| 489 | if (status) | 476 | if (status) |
| @@ -539,7 +526,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) | |||
| 539 | 526 | ||
| 540 | static int read_file_interrupt(struct seq_file *file, void *data) | 527 | static int read_file_interrupt(struct seq_file *file, void *data) |
| 541 | { | 528 | { |
| 542 | struct ath_softc *sc = file->private; | 529 | struct ieee80211_hw *hw = dev_get_drvdata(file->private); |
| 530 | struct ath_softc *sc = hw->priv; | ||
| 543 | 531 | ||
| 544 | #define PR_IS(a, s) \ | 532 | #define PR_IS(a, s) \ |
| 545 | do { \ | 533 | do { \ |
| @@ -600,22 +588,10 @@ static int read_file_interrupt(struct seq_file *file, void *data) | |||
| 600 | return 0; | 588 | return 0; |
| 601 | } | 589 | } |
| 602 | 590 | ||
| 603 | static int open_file_interrupt(struct inode *inode, struct file *f) | ||
| 604 | { | ||
| 605 | return single_open(f, read_file_interrupt, inode->i_private); | ||
| 606 | } | ||
| 607 | |||
| 608 | static const struct file_operations fops_interrupt = { | ||
| 609 | .read = seq_read, | ||
| 610 | .open = open_file_interrupt, | ||
| 611 | .owner = THIS_MODULE, | ||
| 612 | .llseek = seq_lseek, | ||
| 613 | .release = single_release, | ||
| 614 | }; | ||
| 615 | |||
| 616 | static int read_file_xmit(struct seq_file *file, void *data) | 591 | static int read_file_xmit(struct seq_file *file, void *data) |
| 617 | { | 592 | { |
| 618 | struct ath_softc *sc = file->private; | 593 | struct ieee80211_hw *hw = dev_get_drvdata(file->private); |
| 594 | struct ath_softc *sc = hw->priv; | ||
| 619 | 595 | ||
| 620 | seq_printf(file, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); | 596 | seq_printf(file, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); |
| 621 | 597 | ||
| @@ -661,7 +637,8 @@ static void print_queue(struct ath_softc *sc, struct ath_txq *txq, | |||
| 661 | 637 | ||
| 662 | static int read_file_queues(struct seq_file *file, void *data) | 638 | static int read_file_queues(struct seq_file *file, void *data) |
| 663 | { | 639 | { |
| 664 | struct ath_softc *sc = file->private; | 640 | struct ieee80211_hw *hw = dev_get_drvdata(file->private); |
| 641 | struct ath_softc *sc = hw->priv; | ||
| 665 | struct ath_txq *txq; | 642 | struct ath_txq *txq; |
| 666 | int i; | 643 | int i; |
| 667 | static const char *qname[4] = { | 644 | static const char *qname[4] = { |
| @@ -682,7 +659,8 @@ static int read_file_queues(struct seq_file *file, void *data) | |||
| 682 | 659 | ||
| 683 | static int read_file_misc(struct seq_file *file, void *data) | 660 | static int read_file_misc(struct seq_file *file, void *data) |
| 684 | { | 661 | { |
| 685 | struct ath_softc *sc = file->private; | 662 | struct ieee80211_hw *hw = dev_get_drvdata(file->private); |
| 663 | struct ath_softc *sc = hw->priv; | ||
| 686 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 664 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 687 | struct ath9k_vif_iter_data iter_data; | 665 | struct ath9k_vif_iter_data iter_data; |
| 688 | struct ath_chanctx *ctx; | 666 | struct ath_chanctx *ctx; |
| @@ -773,7 +751,8 @@ static int read_file_misc(struct seq_file *file, void *data) | |||
| 773 | 751 | ||
| 774 | static int read_file_reset(struct seq_file *file, void *data) | 752 | static int read_file_reset(struct seq_file *file, void *data) |
| 775 | { | 753 | { |
| 776 | struct ath_softc *sc = file->private; | 754 | struct ieee80211_hw *hw = dev_get_drvdata(file->private); |
| 755 | struct ath_softc *sc = hw->priv; | ||
| 777 | static const char * const reset_cause[__RESET_TYPE_MAX] = { | 756 | static const char * const reset_cause[__RESET_TYPE_MAX] = { |
| 778 | [RESET_TYPE_BB_HANG] = "Baseband Hang", | 757 | [RESET_TYPE_BB_HANG] = "Baseband Hang", |
| 779 | [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog", | 758 | [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog", |
| @@ -837,58 +816,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | |||
| 837 | TX_STAT_INC(qnum, delim_underrun); | 816 | TX_STAT_INC(qnum, delim_underrun); |
| 838 | } | 817 | } |
| 839 | 818 | ||
| 840 | static int open_file_xmit(struct inode *inode, struct file *f) | ||
| 841 | { | ||
| 842 | return single_open(f, read_file_xmit, inode->i_private); | ||
| 843 | } | ||
| 844 | |||
| 845 | static const struct file_operations fops_xmit = { | ||
| 846 | .read = seq_read, | ||
| 847 | .open = open_file_xmit, | ||
| 848 | .owner = THIS_MODULE, | ||
| 849 | .llseek = seq_lseek, | ||
| 850 | .release = single_release, | ||
| 851 | }; | ||
| 852 | |||
| 853 | static int open_file_queues(struct inode *inode, struct file *f) | ||
| 854 | { | ||
| 855 | return single_open(f, read_file_queues, inode->i_private); | ||
| 856 | } | ||
| 857 | |||
| 858 | static const struct file_operations fops_queues = { | ||
| 859 | .read = seq_read, | ||
| 860 | .open = open_file_queues, | ||
| 861 | .owner = THIS_MODULE, | ||
| 862 | .llseek = seq_lseek, | ||
| 863 | .release = single_release, | ||
| 864 | }; | ||
| 865 | |||
| 866 | static int open_file_misc(struct inode *inode, struct file *f) | ||
| 867 | { | ||
| 868 | return single_open(f, read_file_misc, inode->i_private); | ||
| 869 | } | ||
| 870 | |||
| 871 | static const struct file_operations fops_misc = { | ||
| 872 | .read = seq_read, | ||
| 873 | .open = open_file_misc, | ||
| 874 | .owner = THIS_MODULE, | ||
| 875 | .llseek = seq_lseek, | ||
| 876 | .release = single_release, | ||
| 877 | }; | ||
| 878 | |||
| 879 | static int open_file_reset(struct inode *inode, struct file *f) | ||
| 880 | { | ||
| 881 | return single_open(f, read_file_reset, inode->i_private); | ||
| 882 | } | ||
| 883 | |||
| 884 | static const struct file_operations fops_reset = { | ||
| 885 | .read = seq_read, | ||
| 886 | .open = open_file_reset, | ||
| 887 | .owner = THIS_MODULE, | ||
| 888 | .llseek = seq_lseek, | ||
| 889 | .release = single_release, | ||
| 890 | }; | ||
| 891 | |||
| 892 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | 819 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) |
| 893 | { | 820 | { |
| 894 | ath9k_cmn_debug_stat_rx(&sc->debug.stats.rxstats, rs); | 821 | ath9k_cmn_debug_stat_rx(&sc->debug.stats.rxstats, rs); |
| @@ -1018,7 +945,8 @@ static const struct file_operations fops_regdump = { | |||
| 1018 | 945 | ||
| 1019 | static int read_file_dump_nfcal(struct seq_file *file, void *data) | 946 | static int read_file_dump_nfcal(struct seq_file *file, void *data) |
| 1020 | { | 947 | { |
| 1021 | struct ath_softc *sc = file->private; | 948 | struct ieee80211_hw *hw = dev_get_drvdata(file->private); |
| 949 | struct ath_softc *sc = hw->priv; | ||
| 1022 | struct ath_hw *ah = sc->sc_ah; | 950 | struct ath_hw *ah = sc->sc_ah; |
| 1023 | struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist; | 951 | struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist; |
| 1024 | struct ath_common *common = ath9k_hw_common(ah); | 952 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -1115,6 +1043,69 @@ static const struct file_operations fops_ackto = { | |||
| 1115 | }; | 1043 | }; |
| 1116 | #endif | 1044 | #endif |
| 1117 | 1045 | ||
| 1046 | #ifdef CONFIG_ATH9K_WOW | ||
| 1047 | |||
| 1048 | static ssize_t read_file_wow(struct file *file, char __user *user_buf, | ||
| 1049 | size_t count, loff_t *ppos) | ||
| 1050 | { | ||
| 1051 | struct ath_softc *sc = file->private_data; | ||
| 1052 | unsigned int len = 0, size = 32; | ||
| 1053 | ssize_t retval; | ||
| 1054 | char *buf; | ||
| 1055 | |||
| 1056 | buf = kzalloc(size, GFP_KERNEL); | ||
| 1057 | if (!buf) | ||
| 1058 | return -ENOMEM; | ||
| 1059 | |||
| 1060 | len += scnprintf(buf + len, size - len, "WOW: %s\n", | ||
| 1061 | sc->force_wow ? "ENABLED" : "DISABLED"); | ||
| 1062 | |||
| 1063 | if (len > size) | ||
| 1064 | len = size; | ||
| 1065 | |||
| 1066 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1067 | kfree(buf); | ||
| 1068 | |||
| 1069 | return retval; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | static ssize_t write_file_wow(struct file *file, const char __user *user_buf, | ||
| 1073 | size_t count, loff_t *ppos) | ||
| 1074 | { | ||
| 1075 | struct ath_softc *sc = file->private_data; | ||
| 1076 | unsigned long val; | ||
| 1077 | char buf[32]; | ||
| 1078 | ssize_t len; | ||
| 1079 | |||
| 1080 | len = min(count, sizeof(buf) - 1); | ||
| 1081 | if (copy_from_user(buf, user_buf, len)) | ||
| 1082 | return -EFAULT; | ||
| 1083 | |||
| 1084 | buf[len] = '\0'; | ||
| 1085 | if (kstrtoul(buf, 0, &val)) | ||
| 1086 | return -EINVAL; | ||
| 1087 | |||
| 1088 | if (val != 1) | ||
| 1089 | return -EINVAL; | ||
| 1090 | |||
| 1091 | if (!sc->force_wow) { | ||
| 1092 | sc->force_wow = true; | ||
| 1093 | ath9k_init_wow(sc->hw); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | return count; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | static const struct file_operations fops_wow = { | ||
| 1100 | .read = read_file_wow, | ||
| 1101 | .write = write_file_wow, | ||
| 1102 | .open = simple_open, | ||
| 1103 | .owner = THIS_MODULE, | ||
| 1104 | .llseek = default_llseek, | ||
| 1105 | }; | ||
| 1106 | |||
| 1107 | #endif | ||
| 1108 | |||
| 1118 | static ssize_t read_file_tpc(struct file *file, char __user *user_buf, | 1109 | static ssize_t read_file_tpc(struct file *file, char __user *user_buf, |
| 1119 | size_t count, loff_t *ppos) | 1110 | size_t count, loff_t *ppos) |
| 1120 | { | 1111 | { |
| @@ -1150,11 +1141,6 @@ static ssize_t write_file_tpc(struct file *file, const char __user *user_buf, | |||
| 1150 | ssize_t len; | 1141 | ssize_t len; |
| 1151 | bool tpc_enabled; | 1142 | bool tpc_enabled; |
| 1152 | 1143 | ||
| 1153 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | ||
| 1154 | /* ar9002 does not support TPC for the moment */ | ||
| 1155 | return -EOPNOTSUPP; | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | len = min(count, sizeof(buf) - 1); | 1144 | len = min(count, sizeof(buf) - 1); |
| 1159 | if (copy_from_user(buf, user_buf, len)) | 1145 | if (copy_from_user(buf, user_buf, len)) |
| 1160 | return -EFAULT; | 1146 | return -EFAULT; |
| @@ -1329,14 +1315,14 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1329 | ath9k_tx99_init_debug(sc); | 1315 | ath9k_tx99_init_debug(sc); |
| 1330 | ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); | 1316 | ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); |
| 1331 | 1317 | ||
| 1332 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, | 1318 | debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, |
| 1333 | &fops_dma); | 1319 | read_file_dma); |
| 1334 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, | 1320 | debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, |
| 1335 | &fops_interrupt); | 1321 | read_file_interrupt); |
| 1336 | debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc, | 1322 | debugfs_create_devm_seqfile(sc->dev, "xmit", sc->debug.debugfs_phy, |
| 1337 | &fops_xmit); | 1323 | read_file_xmit); |
| 1338 | debugfs_create_file("queues", S_IRUSR, sc->debug.debugfs_phy, sc, | 1324 | debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy, |
| 1339 | &fops_queues); | 1325 | read_file_queues); |
| 1340 | debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1326 | debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
| 1341 | &sc->tx.txq_max_pending[IEEE80211_AC_BK]); | 1327 | &sc->tx.txq_max_pending[IEEE80211_AC_BK]); |
| 1342 | debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1328 | debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
| @@ -1345,10 +1331,10 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1345 | &sc->tx.txq_max_pending[IEEE80211_AC_VI]); | 1331 | &sc->tx.txq_max_pending[IEEE80211_AC_VI]); |
| 1346 | debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1332 | debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
| 1347 | &sc->tx.txq_max_pending[IEEE80211_AC_VO]); | 1333 | &sc->tx.txq_max_pending[IEEE80211_AC_VO]); |
| 1348 | debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc, | 1334 | debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy, |
| 1349 | &fops_misc); | 1335 | read_file_misc); |
| 1350 | debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc, | 1336 | debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy, |
| 1351 | &fops_reset); | 1337 | read_file_reset); |
| 1352 | 1338 | ||
| 1353 | ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); | 1339 | ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); |
| 1354 | ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); | 1340 | ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); |
| @@ -1370,8 +1356,9 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1370 | &ah->config.cwm_ignore_extcca); | 1356 | &ah->config.cwm_ignore_extcca); |
| 1371 | debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, | 1357 | debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, |
| 1372 | &fops_regdump); | 1358 | &fops_regdump); |
| 1373 | debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc, | 1359 | debugfs_create_devm_seqfile(sc->dev, "dump_nfcal", |
| 1374 | &fops_dump_nfcal); | 1360 | sc->debug.debugfs_phy, |
| 1361 | read_file_dump_nfcal); | ||
| 1375 | 1362 | ||
| 1376 | ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); | 1363 | ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); |
| 1377 | ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); | 1364 | ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); |
| @@ -1389,6 +1376,11 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1389 | &fops_btcoex); | 1376 | &fops_btcoex); |
| 1390 | #endif | 1377 | #endif |
| 1391 | 1378 | ||
| 1379 | #ifdef CONFIG_ATH9K_WOW | ||
| 1380 | debugfs_create_file("wow", S_IRUSR | S_IWUSR, | ||
| 1381 | sc->debug.debugfs_phy, sc, &fops_wow); | ||
| 1382 | #endif | ||
| 1383 | |||
| 1392 | #ifdef CONFIG_ATH9K_DYNACK | 1384 | #ifdef CONFIG_ATH9K_DYNACK |
| 1393 | debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | 1385 | debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
| 1394 | sc, &fops_ackto); | 1386 | sc, &fops_ackto); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 07b806c56c56..e5a78d4fd66e 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
| @@ -748,6 +748,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
| 748 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | 748 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); |
| 749 | } | 749 | } |
| 750 | 750 | ||
| 751 | /* TPC initializations */ | ||
| 752 | if (ah->tpc_enabled) { | ||
| 753 | int ht40_delta; | ||
| 754 | |||
| 755 | ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0; | ||
| 756 | ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta); | ||
| 757 | /* Enable TPC */ | ||
| 758 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, | ||
| 759 | MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE); | ||
| 760 | } else { | ||
| 761 | /* Disable TPC */ | ||
| 762 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER); | ||
| 763 | } | ||
| 764 | |||
| 751 | REGWRITE_BUFFER_FLUSH(ah); | 765 | REGWRITE_BUFFER_FLUSH(ah); |
| 752 | } | 766 | } |
| 753 | 767 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 5ba1385c9838..6ca33dfde1fd 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
| @@ -886,6 +886,21 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
| 886 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | 886 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
| 887 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | 887 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); |
| 888 | } | 888 | } |
| 889 | |||
| 890 | /* TPC initializations */ | ||
| 891 | if (ah->tpc_enabled) { | ||
| 892 | int ht40_delta; | ||
| 893 | |||
| 894 | ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0; | ||
| 895 | ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta); | ||
| 896 | /* Enable TPC */ | ||
| 897 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, | ||
| 898 | MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE); | ||
| 899 | } else { | ||
| 900 | /* Disable TPC */ | ||
| 901 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER); | ||
| 902 | } | ||
| 903 | |||
| 889 | REGWRITE_BUFFER_FLUSH(ah); | 904 | REGWRITE_BUFFER_FLUSH(ah); |
| 890 | } | 905 | } |
| 891 | 906 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 122b846b8ec0..098059039351 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
| @@ -1332,6 +1332,20 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
| 1332 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | 1332 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) |
| 1333 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); | 1333 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); |
| 1334 | 1334 | ||
| 1335 | /* TPC initializations */ | ||
| 1336 | if (ah->tpc_enabled) { | ||
| 1337 | int ht40_delta; | ||
| 1338 | |||
| 1339 | ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0; | ||
| 1340 | ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta); | ||
| 1341 | /* Enable TPC */ | ||
| 1342 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, | ||
| 1343 | MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE); | ||
| 1344 | } else { | ||
| 1345 | /* Disable TPC */ | ||
| 1346 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER); | ||
| 1347 | } | ||
| 1348 | |||
| 1335 | REGWRITE_BUFFER_FLUSH(ah); | 1349 | REGWRITE_BUFFER_FLUSH(ah); |
| 1336 | } | 1350 | } |
| 1337 | 1351 | ||
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 2fef7a480fec..da344b27326c 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
| @@ -49,7 +49,7 @@ void ath_init_leds(struct ath_softc *sc) | |||
| 49 | if (AR_SREV_9100(sc->sc_ah)) | 49 | if (AR_SREV_9100(sc->sc_ah)) |
| 50 | return; | 50 | return; |
| 51 | 51 | ||
| 52 | if (!led_blink) | 52 | if (!ath9k_led_blink) |
| 53 | sc->led_cdev.default_trigger = | 53 | sc->led_cdev.default_trigger = |
| 54 | ieee80211_get_radio_led_name(sc->hw); | 54 | ieee80211_get_radio_led_name(sc->hw); |
| 55 | 55 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 9dde265d3f84..300d3671d0ef 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
| @@ -44,6 +44,9 @@ | |||
| 44 | 44 | ||
| 45 | extern struct ieee80211_ops ath9k_htc_ops; | 45 | extern struct ieee80211_ops ath9k_htc_ops; |
| 46 | extern int htc_modparam_nohwcrypt; | 46 | extern int htc_modparam_nohwcrypt; |
| 47 | #ifdef CONFIG_MAC80211_LEDS | ||
| 48 | extern int ath9k_htc_led_blink; | ||
| 49 | #endif | ||
| 47 | 50 | ||
| 48 | enum htc_phymode { | 51 | enum htc_phymode { |
| 49 | HTC_MODE_11NA = 0, | 52 | HTC_MODE_11NA = 0, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 50f74a2a4cf8..2aabcbdaba4e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
| @@ -279,6 +279,10 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) | |||
| 279 | else | 279 | else |
| 280 | priv->ah->led_pin = ATH_LED_PIN_DEF; | 280 | priv->ah->led_pin = ATH_LED_PIN_DEF; |
| 281 | 281 | ||
| 282 | if (!ath9k_htc_led_blink) | ||
| 283 | priv->led_cdev.default_trigger = | ||
| 284 | ieee80211_get_radio_led_name(priv->hw); | ||
| 285 | |||
| 282 | ath9k_configure_leds(priv); | 286 | ath9k_configure_leds(priv); |
| 283 | 287 | ||
| 284 | snprintf(priv->led_name, sizeof(priv->led_name), | 288 | snprintf(priv->led_name, sizeof(priv->led_name), |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index e8fa9448da24..fd229409f676 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
| @@ -39,6 +39,10 @@ module_param_named(ps_enable, ath9k_ps_enable, int, 0444); | |||
| 39 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); | 39 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); |
| 40 | 40 | ||
| 41 | #ifdef CONFIG_MAC80211_LEDS | 41 | #ifdef CONFIG_MAC80211_LEDS |
| 42 | int ath9k_htc_led_blink = 1; | ||
| 43 | module_param_named(blink, ath9k_htc_led_blink, int, 0444); | ||
| 44 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | ||
| 45 | |||
| 42 | static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { | 46 | static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { |
| 43 | { .throughput = 0 * 1024, .blink_time = 334 }, | 47 | { .throughput = 0 * 1024, .blink_time = 334 }, |
| 44 | { .throughput = 1 * 1024, .blink_time = 260 }, | 48 | { .throughput = 1 * 1024, .blink_time = 260 }, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index a0ff5b637054..d2408da38c1c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
| @@ -351,11 +351,7 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | |||
| 351 | 351 | ||
| 352 | return; | 352 | return; |
| 353 | ret: | 353 | ret: |
| 354 | /* HTC-generated packets are freed here. */ | 354 | kfree_skb(skb); |
| 355 | if (htc_hdr && htc_hdr->endpoint_id != ENDPOINT0) | ||
| 356 | dev_kfree_skb_any(skb); | ||
| 357 | else | ||
| 358 | kfree_skb(skb); | ||
| 359 | } | 355 | } |
| 360 | 356 | ||
| 361 | static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle, | 357 | static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle, |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 258c4d236cbe..60aa8d71e753 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -246,6 +246,8 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) | |||
| 246 | case AR9300_DEVID_AR953X: | 246 | case AR9300_DEVID_AR953X: |
| 247 | ah->hw_version.macVersion = AR_SREV_VERSION_9531; | 247 | ah->hw_version.macVersion = AR_SREV_VERSION_9531; |
| 248 | return; | 248 | return; |
| 249 | case AR9300_DEVID_QCA956X: | ||
| 250 | ah->hw_version.macVersion = AR_SREV_VERSION_9561; | ||
| 249 | } | 251 | } |
| 250 | 252 | ||
| 251 | val = REG_READ(ah, AR_SREV) & AR_SREV_ID; | 253 | val = REG_READ(ah, AR_SREV) & AR_SREV_ID; |
| @@ -422,8 +424,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
| 422 | ah->power_mode = ATH9K_PM_UNDEFINED; | 424 | ah->power_mode = ATH9K_PM_UNDEFINED; |
| 423 | ah->htc_reset_init = true; | 425 | ah->htc_reset_init = true; |
| 424 | 426 | ||
| 425 | /* ar9002 does not support TPC for the moment */ | 427 | ah->tpc_enabled = true; |
| 426 | ah->tpc_enabled = !!AR_SREV_9300_20_OR_LATER(ah); | ||
| 427 | 428 | ||
| 428 | ah->ani_function = ATH9K_ANI_ALL; | 429 | ah->ani_function = ATH9K_ANI_ALL; |
| 429 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 430 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
| @@ -539,6 +540,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
| 539 | case AR_SREV_VERSION_9550: | 540 | case AR_SREV_VERSION_9550: |
| 540 | case AR_SREV_VERSION_9565: | 541 | case AR_SREV_VERSION_9565: |
| 541 | case AR_SREV_VERSION_9531: | 542 | case AR_SREV_VERSION_9531: |
| 543 | case AR_SREV_VERSION_9561: | ||
| 542 | break; | 544 | break; |
| 543 | default: | 545 | default: |
| 544 | ath_err(common, | 546 | ath_err(common, |
| @@ -639,6 +641,7 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
| 639 | case AR9485_DEVID_AR1111: | 641 | case AR9485_DEVID_AR1111: |
| 640 | case AR9300_DEVID_AR9565: | 642 | case AR9300_DEVID_AR9565: |
| 641 | case AR9300_DEVID_AR953X: | 643 | case AR9300_DEVID_AR953X: |
| 644 | case AR9300_DEVID_QCA956X: | ||
| 642 | break; | 645 | break; |
| 643 | default: | 646 | default: |
| 644 | if (common->bus_ops->ath_bus_type == ATH_USB) | 647 | if (common->bus_ops->ath_bus_type == ATH_USB) |
| @@ -779,7 +782,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 779 | /* program BB PLL phase_shift */ | 782 | /* program BB PLL phase_shift */ |
| 780 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, | 783 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, |
| 781 | AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); | 784 | AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); |
| 782 | } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) { | 785 | } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || |
| 786 | AR_SREV_9561(ah)) { | ||
| 783 | u32 regval, pll2_divint, pll2_divfrac, refdiv; | 787 | u32 regval, pll2_divint, pll2_divfrac, refdiv; |
| 784 | 788 | ||
| 785 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, | 789 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, |
| @@ -790,7 +794,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 790 | udelay(100); | 794 | udelay(100); |
| 791 | 795 | ||
| 792 | if (ah->is_clk_25mhz) { | 796 | if (ah->is_clk_25mhz) { |
| 793 | if (AR_SREV_9531(ah)) { | 797 | if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) { |
| 794 | pll2_divint = 0x1c; | 798 | pll2_divint = 0x1c; |
| 795 | pll2_divfrac = 0xa3d2; | 799 | pll2_divfrac = 0xa3d2; |
| 796 | refdiv = 1; | 800 | refdiv = 1; |
| @@ -806,14 +810,15 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 806 | refdiv = 5; | 810 | refdiv = 5; |
| 807 | } else { | 811 | } else { |
| 808 | pll2_divint = 0x11; | 812 | pll2_divint = 0x11; |
| 809 | pll2_divfrac = | 813 | pll2_divfrac = (AR_SREV_9531(ah) || |
| 810 | AR_SREV_9531(ah) ? 0x26665 : 0x26666; | 814 | AR_SREV_9561(ah)) ? |
| 815 | 0x26665 : 0x26666; | ||
| 811 | refdiv = 1; | 816 | refdiv = 1; |
| 812 | } | 817 | } |
| 813 | } | 818 | } |
| 814 | 819 | ||
| 815 | regval = REG_READ(ah, AR_PHY_PLL_MODE); | 820 | regval = REG_READ(ah, AR_PHY_PLL_MODE); |
| 816 | if (AR_SREV_9531(ah)) | 821 | if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) |
| 817 | regval |= (0x1 << 22); | 822 | regval |= (0x1 << 22); |
| 818 | else | 823 | else |
| 819 | regval |= (0x1 << 16); | 824 | regval |= (0x1 << 16); |
| @@ -831,14 +836,16 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 831 | (0x1 << 13) | | 836 | (0x1 << 13) | |
| 832 | (0x4 << 26) | | 837 | (0x4 << 26) | |
| 833 | (0x18 << 19); | 838 | (0x18 << 19); |
| 834 | else if (AR_SREV_9531(ah)) | 839 | else if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) { |
| 835 | regval = (regval & 0x01c00fff) | | 840 | regval = (regval & 0x01c00fff) | |
| 836 | (0x1 << 31) | | 841 | (0x1 << 31) | |
| 837 | (0x2 << 29) | | 842 | (0x2 << 29) | |
| 838 | (0xa << 25) | | 843 | (0xa << 25) | |
| 839 | (0x1 << 19) | | 844 | (0x1 << 19); |
| 840 | (0x6 << 12); | 845 | |
| 841 | else | 846 | if (AR_SREV_9531(ah)) |
| 847 | regval |= (0x6 << 12); | ||
| 848 | } else | ||
| 842 | regval = (regval & 0x80071fff) | | 849 | regval = (regval & 0x80071fff) | |
| 843 | (0x3 << 30) | | 850 | (0x3 << 30) | |
| 844 | (0x1 << 13) | | 851 | (0x1 << 13) | |
| @@ -846,7 +853,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
| 846 | (0x60 << 19); | 853 | (0x60 << 19); |
| 847 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); | 854 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); |
| 848 | 855 | ||
| 849 | if (AR_SREV_9531(ah)) | 856 | if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) |
| 850 | REG_WRITE(ah, AR_PHY_PLL_MODE, | 857 | REG_WRITE(ah, AR_PHY_PLL_MODE, |
| 851 | REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff); | 858 | REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff); |
| 852 | else | 859 | else |
| @@ -885,7 +892,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
| 885 | AR_IMR_RXORN | | 892 | AR_IMR_RXORN | |
| 886 | AR_IMR_BCNMISC; | 893 | AR_IMR_BCNMISC; |
| 887 | 894 | ||
| 888 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) | 895 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || |
| 896 | AR_SREV_9561(ah)) | ||
| 889 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; | 897 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; |
| 890 | 898 | ||
| 891 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 899 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
| @@ -1674,7 +1682,8 @@ static void ath9k_hw_init_desc(struct ath_hw *ah) | |||
| 1674 | } | 1682 | } |
| 1675 | #ifdef __BIG_ENDIAN | 1683 | #ifdef __BIG_ENDIAN |
| 1676 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || | 1684 | else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || |
| 1677 | AR_SREV_9550(ah) || AR_SREV_9531(ah)) | 1685 | AR_SREV_9550(ah) || AR_SREV_9531(ah) || |
| 1686 | AR_SREV_9561(ah)) | ||
| 1678 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | 1687 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); |
| 1679 | else | 1688 | else |
| 1680 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | 1689 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); |
| @@ -2462,7 +2471,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
| 2462 | 2471 | ||
| 2463 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 2472 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
| 2464 | pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK; | 2473 | pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK; |
| 2465 | if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) && !AR_SREV_9565(ah)) | 2474 | if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) && |
| 2475 | !AR_SREV_9561(ah) && !AR_SREV_9565(ah)) | ||
| 2466 | pCap->hw_caps |= ATH9K_HW_CAP_LDPC; | 2476 | pCap->hw_caps |= ATH9K_HW_CAP_LDPC; |
| 2467 | 2477 | ||
| 2468 | pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; | 2478 | pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; |
| @@ -2479,7 +2489,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
| 2479 | if (AR_SREV_9300_20_OR_LATER(ah)) | 2489 | if (AR_SREV_9300_20_OR_LATER(ah)) |
| 2480 | pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; | 2490 | pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; |
| 2481 | 2491 | ||
| 2482 | if (AR_SREV_9300_20_OR_LATER(ah)) | 2492 | if (AR_SREV_9561(ah)) |
| 2493 | ah->ent_mode = 0x3BDA000; | ||
| 2494 | else if (AR_SREV_9300_20_OR_LATER(ah)) | ||
| 2483 | ah->ent_mode = REG_READ(ah, AR_ENT_OTP); | 2495 | ah->ent_mode = REG_READ(ah, AR_ENT_OTP); |
| 2484 | 2496 | ||
| 2485 | if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) | 2497 | if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) |
| @@ -2532,13 +2544,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
| 2532 | pCap->hw_caps |= ATH9K_HW_CAP_RTT; | 2544 | pCap->hw_caps |= ATH9K_HW_CAP_RTT; |
| 2533 | } | 2545 | } |
| 2534 | 2546 | ||
| 2535 | if (AR_SREV_9462(ah)) | ||
| 2536 | pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE; | ||
| 2537 | |||
| 2538 | if (AR_SREV_9300_20_OR_LATER(ah) && | 2547 | if (AR_SREV_9300_20_OR_LATER(ah) && |
| 2539 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | 2548 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) |
| 2540 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; | 2549 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; |
| 2541 | 2550 | ||
| 2551 | #ifdef CONFIG_ATH9K_WOW | ||
| 2552 | if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah)) | ||
| 2553 | ah->wow.max_patterns = MAX_NUM_PATTERN; | ||
| 2554 | else | ||
| 2555 | ah->wow.max_patterns = MAX_NUM_PATTERN_LEGACY; | ||
| 2556 | #endif | ||
| 2557 | |||
| 2542 | return 0; | 2558 | return 0; |
| 2543 | } | 2559 | } |
| 2544 | 2560 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 1cbd33551513..e82e570de330 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #define AR9485_DEVID_AR1111 0x0037 | 54 | #define AR9485_DEVID_AR1111 0x0037 |
| 55 | #define AR9300_DEVID_AR9565 0x0036 | 55 | #define AR9300_DEVID_AR9565 0x0036 |
| 56 | #define AR9300_DEVID_AR953X 0x003d | 56 | #define AR9300_DEVID_AR953X 0x003d |
| 57 | #define AR9300_DEVID_QCA956X 0x003f | ||
| 57 | 58 | ||
| 58 | #define AR5416_AR9100_DEVID 0x000b | 59 | #define AR5416_AR9100_DEVID 0x000b |
| 59 | 60 | ||
| @@ -198,12 +199,13 @@ | |||
| 198 | #define KAL_NUM_DESC_WORDS 12 | 199 | #define KAL_NUM_DESC_WORDS 12 |
| 199 | #define KAL_ANTENNA_MODE 1 | 200 | #define KAL_ANTENNA_MODE 1 |
| 200 | #define KAL_TO_DS 1 | 201 | #define KAL_TO_DS 1 |
| 201 | #define KAL_DELAY 4 /*delay of 4ms between 2 KAL frames */ | 202 | #define KAL_DELAY 4 /* delay of 4ms between 2 KAL frames */ |
| 202 | #define KAL_TIMEOUT 900 | 203 | #define KAL_TIMEOUT 900 |
| 203 | 204 | ||
| 204 | #define MAX_PATTERN_SIZE 256 | 205 | #define MAX_PATTERN_SIZE 256 |
| 205 | #define MAX_PATTERN_MASK_SIZE 32 | 206 | #define MAX_PATTERN_MASK_SIZE 32 |
| 206 | #define MAX_NUM_PATTERN 8 | 207 | #define MAX_NUM_PATTERN 16 |
| 208 | #define MAX_NUM_PATTERN_LEGACY 8 | ||
| 207 | #define MAX_NUM_USER_PATTERN 6 /* deducting the disassociate and | 209 | #define MAX_NUM_USER_PATTERN 6 /* deducting the disassociate and |
| 208 | deauthenticate packets */ | 210 | deauthenticate packets */ |
| 209 | 211 | ||
| @@ -247,12 +249,10 @@ enum ath9k_hw_caps { | |||
| 247 | #ifdef CONFIG_ATH9K_PCOEM | 249 | #ifdef CONFIG_ATH9K_PCOEM |
| 248 | ATH9K_HW_CAP_RTT = BIT(14), | 250 | ATH9K_HW_CAP_RTT = BIT(14), |
| 249 | ATH9K_HW_CAP_MCI = BIT(15), | 251 | ATH9K_HW_CAP_MCI = BIT(15), |
| 250 | ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16), | ||
| 251 | ATH9K_HW_CAP_BT_ANT_DIV = BIT(17), | 252 | ATH9K_HW_CAP_BT_ANT_DIV = BIT(17), |
| 252 | #else | 253 | #else |
| 253 | ATH9K_HW_CAP_RTT = 0, | 254 | ATH9K_HW_CAP_RTT = 0, |
| 254 | ATH9K_HW_CAP_MCI = 0, | 255 | ATH9K_HW_CAP_MCI = 0, |
| 255 | ATH9K_HW_WOW_DEVICE_CAPABLE = 0, | ||
| 256 | ATH9K_HW_CAP_BT_ANT_DIV = 0, | 256 | ATH9K_HW_CAP_BT_ANT_DIV = 0, |
| 257 | #endif | 257 | #endif |
| 258 | ATH9K_HW_CAP_DFS = BIT(18), | 258 | ATH9K_HW_CAP_DFS = BIT(18), |
| @@ -271,6 +271,12 @@ enum ath9k_hw_caps { | |||
| 271 | * of those types. | 271 | * of those types. |
| 272 | */ | 272 | */ |
| 273 | 273 | ||
| 274 | struct ath9k_hw_wow { | ||
| 275 | u32 wow_event_mask; | ||
| 276 | u32 wow_event_mask2; | ||
| 277 | u8 max_patterns; | ||
| 278 | }; | ||
| 279 | |||
| 274 | struct ath9k_hw_capabilities { | 280 | struct ath9k_hw_capabilities { |
| 275 | u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ | 281 | u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ |
| 276 | u16 rts_aggr_limit; | 282 | u16 rts_aggr_limit; |
| @@ -929,7 +935,7 @@ struct ath_hw { | |||
| 929 | u32 ent_mode; | 935 | u32 ent_mode; |
| 930 | 936 | ||
| 931 | #ifdef CONFIG_ATH9K_WOW | 937 | #ifdef CONFIG_ATH9K_WOW |
| 932 | u32 wow_event_mask; | 938 | struct ath9k_hw_wow wow; |
| 933 | #endif | 939 | #endif |
| 934 | bool is_clk_25mhz; | 940 | bool is_clk_25mhz; |
| 935 | int (*get_mac_revision)(void); | 941 | int (*get_mac_revision)(void); |
| @@ -1086,6 +1092,8 @@ bool ar9003_is_paprd_enabled(struct ath_hw *ah); | |||
| 1086 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); | 1092 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); |
| 1087 | void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array, | 1093 | void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array, |
| 1088 | struct ath9k_channel *chan); | 1094 | struct ath9k_channel *chan); |
| 1095 | void ar5008_hw_init_rate_txpower(struct ath_hw *ah, int16_t *rate_array, | ||
| 1096 | struct ath9k_channel *chan, int ht40_delta); | ||
| 1089 | 1097 | ||
| 1090 | /* Hardware family op attach helpers */ | 1098 | /* Hardware family op attach helpers */ |
| 1091 | int ar5008_hw_attach_phy_ops(struct ath_hw *ah); | 1099 | int ar5008_hw_attach_phy_ops(struct ath_hw *ah); |
| @@ -1145,23 +1153,19 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) | |||
| 1145 | 1153 | ||
| 1146 | 1154 | ||
| 1147 | #ifdef CONFIG_ATH9K_WOW | 1155 | #ifdef CONFIG_ATH9K_WOW |
| 1148 | const char *ath9k_hw_wow_event_to_string(u32 wow_event); | 1156 | int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, |
| 1149 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | 1157 | u8 *user_mask, int pattern_count, |
| 1150 | u8 *user_mask, int pattern_count, | 1158 | int pattern_len); |
| 1151 | int pattern_len); | ||
| 1152 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah); | 1159 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah); |
| 1153 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable); | 1160 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable); |
| 1154 | #else | 1161 | #else |
| 1155 | static inline const char *ath9k_hw_wow_event_to_string(u32 wow_event) | 1162 | static inline int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, |
| 1156 | { | 1163 | u8 *user_pattern, |
| 1157 | return NULL; | 1164 | u8 *user_mask, |
| 1158 | } | 1165 | int pattern_count, |
| 1159 | static inline void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, | 1166 | int pattern_len) |
| 1160 | u8 *user_pattern, | ||
| 1161 | u8 *user_mask, | ||
| 1162 | int pattern_count, | ||
| 1163 | int pattern_len) | ||
| 1164 | { | 1167 | { |
| 1168 | return 0; | ||
| 1165 | } | 1169 | } |
| 1166 | static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | 1170 | static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) |
| 1167 | { | 1171 | { |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d1c39346b264..6c6e88495394 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
| @@ -45,8 +45,8 @@ int ath9k_modparam_nohwcrypt; | |||
| 45 | module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); | 45 | module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); |
| 46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | 46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); |
| 47 | 47 | ||
| 48 | int led_blink; | 48 | int ath9k_led_blink; |
| 49 | module_param_named(blink, led_blink, int, 0444); | 49 | module_param_named(blink, ath9k_led_blink, int, 0444); |
| 50 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | 50 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); |
| 51 | 51 | ||
| 52 | static int ath9k_btcoex_enable; | 52 | static int ath9k_btcoex_enable; |
| @@ -996,6 +996,7 @@ void ath9k_deinit_device(struct ath_softc *sc) | |||
| 996 | ath9k_ps_restore(sc); | 996 | ath9k_ps_restore(sc); |
| 997 | 997 | ||
| 998 | ath9k_deinit_debug(sc); | 998 | ath9k_deinit_debug(sc); |
| 999 | ath9k_deinit_wow(hw); | ||
| 999 | ieee80211_unregister_hw(hw); | 1000 | ieee80211_unregister_hw(hw); |
| 1000 | ath_rx_cleanup(sc); | 1001 | ath_rx_cleanup(sc); |
| 1001 | ath9k_deinit_softc(sc); | 1002 | ath9k_deinit_softc(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index b829263e3d0a..90631d768a60 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
| @@ -516,14 +516,14 @@ int ath_update_survey_stats(struct ath_softc *sc) | |||
| 516 | ath_hw_cycle_counters_update(common); | 516 | ath_hw_cycle_counters_update(common); |
| 517 | 517 | ||
| 518 | if (cc->cycles > 0) { | 518 | if (cc->cycles > 0) { |
| 519 | survey->filled |= SURVEY_INFO_CHANNEL_TIME | | 519 | survey->filled |= SURVEY_INFO_TIME | |
| 520 | SURVEY_INFO_CHANNEL_TIME_BUSY | | 520 | SURVEY_INFO_TIME_BUSY | |
| 521 | SURVEY_INFO_CHANNEL_TIME_RX | | 521 | SURVEY_INFO_TIME_RX | |
| 522 | SURVEY_INFO_CHANNEL_TIME_TX; | 522 | SURVEY_INFO_TIME_TX; |
| 523 | survey->channel_time += cc->cycles / div; | 523 | survey->time += cc->cycles / div; |
| 524 | survey->channel_time_busy += cc->rx_busy / div; | 524 | survey->time_busy += cc->rx_busy / div; |
| 525 | survey->channel_time_rx += cc->rx_frame / div; | 525 | survey->time_rx += cc->rx_frame / div; |
| 526 | survey->channel_time_tx += cc->tx_frame / div; | 526 | survey->time_tx += cc->tx_frame / div; |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | if (cc->cycles < div) | 529 | if (cc->cycles < div) |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 3e58bfa0c1fd..bba85d1a6cd1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
| @@ -820,7 +820,8 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) | |||
| 820 | return; | 820 | return; |
| 821 | } | 821 | } |
| 822 | 822 | ||
| 823 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) | 823 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || |
| 824 | AR_SREV_9561(ah)) | ||
| 824 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; | 825 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; |
| 825 | 826 | ||
| 826 | async_mask = AR_INTR_MAC_IRQ; | 827 | async_mask = AR_INTR_MAC_IRQ; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9a72640237cb..98b1e4aa1506 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -556,15 +556,6 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
| 556 | (status & ATH9K_INT_BB_WATCHDOG)) | 556 | (status & ATH9K_INT_BB_WATCHDOG)) |
| 557 | goto chip_reset; | 557 | goto chip_reset; |
| 558 | 558 | ||
| 559 | #ifdef CONFIG_ATH9K_WOW | ||
| 560 | if (status & ATH9K_INT_BMISS) { | ||
| 561 | if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { | ||
| 562 | atomic_inc(&sc->wow_got_bmiss_intr); | ||
| 563 | atomic_dec(&sc->wow_sleep_proc_intr); | ||
| 564 | } | ||
| 565 | } | ||
| 566 | #endif | ||
| 567 | |||
| 568 | if (status & ATH9K_INT_SWBA) | 559 | if (status & ATH9K_INT_SWBA) |
| 569 | tasklet_schedule(&sc->bcon_tasklet); | 560 | tasklet_schedule(&sc->bcon_tasklet); |
| 570 | 561 | ||
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index f009b5b57e5e..e6fef1be9977 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
| @@ -427,6 +427,11 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 427 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 427 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 428 | 0x0036, | 428 | 0x0036, |
| 429 | 0x11AD, /* LITEON */ | 429 | 0x11AD, /* LITEON */ |
| 430 | 0x1842), | ||
| 431 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 432 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 433 | 0x0036, | ||
| 434 | 0x11AD, /* LITEON */ | ||
| 430 | 0x6671), | 435 | 0x6671), |
| 431 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | 436 | .driver_data = ATH9K_PCI_AR9565_1ANT }, |
| 432 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 437 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| @@ -446,9 +451,19 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 446 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | 451 | .driver_data = ATH9K_PCI_AR9565_1ANT }, |
| 447 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 452 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 448 | 0x0036, | 453 | 0x0036, |
| 454 | 0x1B9A, /* XAVI */ | ||
| 455 | 0x28A3), | ||
| 456 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 457 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 458 | 0x0036, | ||
| 449 | PCI_VENDOR_ID_AZWAVE, | 459 | PCI_VENDOR_ID_AZWAVE, |
| 450 | 0x218A), | 460 | 0x218A), |
| 451 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | 461 | .driver_data = ATH9K_PCI_AR9565_1ANT }, |
| 462 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 463 | 0x0036, | ||
| 464 | PCI_VENDOR_ID_AZWAVE, | ||
| 465 | 0x2F8A), | ||
| 466 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 452 | 467 | ||
| 453 | /* WB335 1-ANT / Antenna Diversity */ | 468 | /* WB335 1-ANT / Antenna Diversity */ |
| 454 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 469 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| @@ -508,6 +523,11 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 508 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 523 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 509 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 524 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 510 | 0x0036, | 525 | 0x0036, |
| 526 | PCI_VENDOR_ID_AZWAVE, | ||
| 527 | 0x213C), | ||
| 528 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 529 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 530 | 0x0036, | ||
| 511 | PCI_VENDOR_ID_HP, | 531 | PCI_VENDOR_ID_HP, |
| 512 | 0x18E3), | 532 | 0x18E3), |
| 513 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | 533 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -555,6 +575,16 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 555 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 575 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 556 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 576 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 557 | 0x0036, | 577 | 0x0036, |
| 578 | PCI_VENDOR_ID_SAMSUNG, | ||
| 579 | 0x4129), | ||
| 580 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 581 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 582 | 0x0036, | ||
| 583 | PCI_VENDOR_ID_SAMSUNG, | ||
| 584 | 0x412A), | ||
| 585 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 586 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 587 | 0x0036, | ||
| 558 | PCI_VENDOR_ID_ATHEROS, | 588 | PCI_VENDOR_ID_ATHEROS, |
| 559 | 0x3027), | 589 | 0x3027), |
| 560 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 590 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -586,10 +616,25 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 586 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 616 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 587 | 0x0036, | 617 | 0x0036, |
| 588 | 0x11AD, /* LITEON */ | 618 | 0x11AD, /* LITEON */ |
| 619 | 0x1832), | ||
| 620 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 621 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 622 | 0x0036, | ||
| 623 | 0x11AD, /* LITEON */ | ||
| 589 | 0x0692), | 624 | 0x0692), |
| 590 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 625 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 591 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 626 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 592 | 0x0036, | 627 | 0x0036, |
| 628 | 0x11AD, /* LITEON */ | ||
| 629 | 0x0803), | ||
| 630 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 631 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 632 | 0x0036, | ||
| 633 | 0x11AD, /* LITEON */ | ||
| 634 | 0x0813), | ||
| 635 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 636 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 637 | 0x0036, | ||
| 593 | PCI_VENDOR_ID_AZWAVE, | 638 | PCI_VENDOR_ID_AZWAVE, |
| 594 | 0x2130), | 639 | 0x2130), |
| 595 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 640 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -605,6 +650,21 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 605 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 650 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 606 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 651 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 607 | 0x0036, | 652 | 0x0036, |
| 653 | PCI_VENDOR_ID_AZWAVE, | ||
| 654 | 0x218B), | ||
| 655 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 656 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 657 | 0x0036, | ||
| 658 | PCI_VENDOR_ID_AZWAVE, | ||
| 659 | 0x218C), | ||
| 660 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 661 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 662 | 0x0036, | ||
| 663 | PCI_VENDOR_ID_AZWAVE, | ||
| 664 | 0x2F82), | ||
| 665 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 666 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 667 | 0x0036, | ||
| 608 | 0x144F, /* ASKEY */ | 668 | 0x144F, /* ASKEY */ |
| 609 | 0x7202), | 669 | 0x7202), |
| 610 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 670 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -616,10 +676,20 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 616 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 676 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 617 | 0x0036, | 677 | 0x0036, |
| 618 | 0x1B9A, /* XAVI */ | 678 | 0x1B9A, /* XAVI */ |
| 679 | 0x2813), | ||
| 680 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 681 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 682 | 0x0036, | ||
| 683 | 0x1B9A, /* XAVI */ | ||
| 619 | 0x28A2), | 684 | 0x28A2), |
| 620 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 685 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 621 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 686 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 622 | 0x0036, | 687 | 0x0036, |
| 688 | 0x1B9A, /* XAVI */ | ||
| 689 | 0x28A4), | ||
| 690 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 691 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 692 | 0x0036, | ||
| 623 | 0x185F, /* WNC */ | 693 | 0x185F, /* WNC */ |
| 624 | 0x3027), | 694 | 0x3027), |
| 625 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 695 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -636,10 +706,25 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
| 636 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 706 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 637 | 0x0036, | 707 | 0x0036, |
| 638 | PCI_VENDOR_ID_FOXCONN, | 708 | PCI_VENDOR_ID_FOXCONN, |
| 709 | 0xE08F), | ||
| 710 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 711 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 712 | 0x0036, | ||
| 713 | PCI_VENDOR_ID_FOXCONN, | ||
| 639 | 0xE081), | 714 | 0xE081), |
| 640 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 715 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| 641 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 716 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
| 642 | 0x0036, | 717 | 0x0036, |
| 718 | PCI_VENDOR_ID_FOXCONN, | ||
| 719 | 0xE091), | ||
| 720 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 721 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 722 | 0x0036, | ||
| 723 | PCI_VENDOR_ID_FOXCONN, | ||
| 724 | 0xE099), | ||
| 725 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 726 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 727 | 0x0036, | ||
| 643 | PCI_VENDOR_ID_LENOVO, | 728 | PCI_VENDOR_ID_LENOVO, |
| 644 | 0x3026), | 729 | 0x3026), |
| 645 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 730 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, |
| @@ -913,9 +998,12 @@ static int ath_pci_suspend(struct device *device) | |||
| 913 | struct pci_dev *pdev = to_pci_dev(device); | 998 | struct pci_dev *pdev = to_pci_dev(device); |
| 914 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 999 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
| 915 | struct ath_softc *sc = hw->priv; | 1000 | struct ath_softc *sc = hw->priv; |
| 1001 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 916 | 1002 | ||
| 917 | if (sc->wow_enabled) | 1003 | if (test_bit(ATH_OP_WOW_ENABLED, &common->op_flags)) { |
| 1004 | dev_info(&pdev->dev, "WOW is enabled, bypassing PCI suspend\n"); | ||
| 918 | return 0; | 1005 | return 0; |
| 1006 | } | ||
| 919 | 1007 | ||
| 920 | /* The device has to be moved to FULLSLEEP forcibly. | 1008 | /* The device has to be moved to FULLSLEEP forcibly. |
| 921 | * Otherwise the chip never moved to full sleep, | 1009 | * Otherwise the chip never moved to full sleep, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 7395afbc5124..6fb40ef86fd6 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -425,7 +425,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
| 425 | rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; | 425 | rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah)) | 428 | if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah) || |
| 429 | AR_SREV_9561(sc->sc_ah)) | ||
| 429 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; | 430 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; |
| 430 | 431 | ||
| 431 | if (ath9k_is_chanctx_enabled() && | 432 | if (ath9k_is_chanctx_enabled() && |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index fb11a9172f38..9587ec655680 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
| @@ -814,6 +814,7 @@ | |||
| 814 | #define AR_SREV_REVISION_9531_10 0 | 814 | #define AR_SREV_REVISION_9531_10 0 |
| 815 | #define AR_SREV_REVISION_9531_11 1 | 815 | #define AR_SREV_REVISION_9531_11 1 |
| 816 | #define AR_SREV_REVISION_9531_20 2 | 816 | #define AR_SREV_REVISION_9531_20 2 |
| 817 | #define AR_SREV_VERSION_9561 0x600 | ||
| 817 | 818 | ||
| 818 | #define AR_SREV_5416(_ah) \ | 819 | #define AR_SREV_5416(_ah) \ |
| 819 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ | 820 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
| @@ -899,10 +900,13 @@ | |||
| 899 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) | 900 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) |
| 900 | #define AR_SREV_9565(_ah) \ | 901 | #define AR_SREV_9565(_ah) \ |
| 901 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) | 902 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) |
| 903 | #define AR_SREV_9003_PCOEM(_ah) \ | ||
| 904 | (AR_SREV_9462(_ah) || AR_SREV_9485(_ah) || AR_SREV_9565(_ah)) | ||
| 902 | #else | 905 | #else |
| 903 | #define AR_SREV_9462(_ah) 0 | 906 | #define AR_SREV_9462(_ah) 0 |
| 904 | #define AR_SREV_9485(_ah) 0 | 907 | #define AR_SREV_9485(_ah) 0 |
| 905 | #define AR_SREV_9565(_ah) 0 | 908 | #define AR_SREV_9565(_ah) 0 |
| 909 | #define AR_SREV_9003_PCOEM(_ah) 0 | ||
| 906 | #endif | 910 | #endif |
| 907 | 911 | ||
| 908 | #define AR_SREV_9485_11_OR_LATER(_ah) \ | 912 | #define AR_SREV_9485_11_OR_LATER(_ah) \ |
| @@ -974,6 +978,9 @@ | |||
| 974 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \ | 978 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \ |
| 975 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_20)) | 979 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_20)) |
| 976 | 980 | ||
| 981 | #define AR_SREV_9561(_ah) \ | ||
| 982 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9561)) | ||
| 983 | |||
| 977 | /* NOTE: When adding chips newer than Peacock, add chip check here */ | 984 | /* NOTE: When adding chips newer than Peacock, add chip check here */ |
| 978 | #define AR_SREV_9580_10_OR_LATER(_ah) \ | 985 | #define AR_SREV_9580_10_OR_LATER(_ah) \ |
| 979 | (AR_SREV_9580(_ah)) | 986 | (AR_SREV_9580(_ah)) |
| @@ -1876,6 +1883,7 @@ enum { | |||
| 1876 | #define AR_FIRST_NDP_TIMER 7 | 1883 | #define AR_FIRST_NDP_TIMER 7 |
| 1877 | #define AR_NDP2_PERIOD 0x81a0 | 1884 | #define AR_NDP2_PERIOD 0x81a0 |
| 1878 | #define AR_NDP2_TIMER_MODE 0x81c0 | 1885 | #define AR_NDP2_TIMER_MODE 0x81c0 |
| 1886 | #define AR_GEN_TIMERS2_MODE_ENABLE_MASK 0x000000FF | ||
| 1879 | 1887 | ||
| 1880 | #define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2)) | 1888 | #define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2)) |
| 1881 | #define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0) | 1889 | #define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0) |
| @@ -1971,6 +1979,7 @@ enum { | |||
| 1971 | 1979 | ||
| 1972 | #define AR_DIRECT_CONNECT 0x83a0 | 1980 | #define AR_DIRECT_CONNECT 0x83a0 |
| 1973 | #define AR_DC_AP_STA_EN 0x00000001 | 1981 | #define AR_DC_AP_STA_EN 0x00000001 |
| 1982 | #define AR_DC_TSF2_ENABLE 0x00000001 | ||
| 1974 | 1983 | ||
| 1975 | #define AR_AES_MUTE_MASK0 0x805c | 1984 | #define AR_AES_MUTE_MASK0 0x805c |
| 1976 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF | 1985 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF |
| @@ -2003,126 +2012,6 @@ enum { | |||
| 2003 | 2012 | ||
| 2004 | #define AR_WOW_BEACON_TIMO_MAX 0xffffffff | 2013 | #define AR_WOW_BEACON_TIMO_MAX 0xffffffff |
| 2005 | 2014 | ||
| 2006 | /* | ||
| 2007 | * MAC WoW Registers | ||
| 2008 | */ | ||
| 2009 | |||
| 2010 | #define AR_WOW_PATTERN 0x825C | ||
| 2011 | #define AR_WOW_COUNT 0x8260 | ||
| 2012 | #define AR_WOW_BCN_EN 0x8270 | ||
| 2013 | #define AR_WOW_BCN_TIMO 0x8274 | ||
| 2014 | #define AR_WOW_KEEP_ALIVE_TIMO 0x8278 | ||
| 2015 | #define AR_WOW_KEEP_ALIVE 0x827c | ||
| 2016 | #define AR_WOW_US_SCALAR 0x8284 | ||
| 2017 | #define AR_WOW_KEEP_ALIVE_DELAY 0x8288 | ||
| 2018 | #define AR_WOW_PATTERN_MATCH 0x828c | ||
| 2019 | #define AR_WOW_PATTERN_OFF1 0x8290 /* pattern bytes 0 -> 3 */ | ||
| 2020 | #define AR_WOW_PATTERN_OFF2 0x8294 /* pattern bytes 4 -> 7 */ | ||
| 2021 | |||
| 2022 | /* for AR9285 or later version of chips */ | ||
| 2023 | #define AR_WOW_EXACT 0x829c | ||
| 2024 | #define AR_WOW_LENGTH1 0x8360 | ||
| 2025 | #define AR_WOW_LENGTH2 0X8364 | ||
| 2026 | /* register to enable match for less than 256 bytes packets */ | ||
| 2027 | #define AR_WOW_PATTERN_MATCH_LT_256B 0x8368 | ||
| 2028 | |||
| 2029 | #define AR_SW_WOW_CONTROL 0x20018 | ||
| 2030 | #define AR_SW_WOW_ENABLE 0x1 | ||
| 2031 | #define AR_SWITCH_TO_REFCLK 0x2 | ||
| 2032 | #define AR_RESET_CONTROL 0x4 | ||
| 2033 | #define AR_RESET_VALUE_MASK 0x8 | ||
| 2034 | #define AR_HW_WOW_DISABLE 0x10 | ||
| 2035 | #define AR_CLR_MAC_INTERRUPT 0x20 | ||
| 2036 | #define AR_CLR_KA_INTERRUPT 0x40 | ||
| 2037 | |||
| 2038 | /* AR_WOW_PATTERN register values */ | ||
| 2039 | #define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 28) /* in usecs */ | ||
| 2040 | #define AR_WOW_MAC_INTR_EN 0x00040000 | ||
| 2041 | #define AR_WOW_MAGIC_EN 0x00010000 | ||
| 2042 | #define AR_WOW_PATTERN_EN(x) (x & 0xff) | ||
| 2043 | #define AR_WOW_PAT_FOUND_SHIFT 8 | ||
| 2044 | #define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT)) | ||
| 2045 | #define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT) | ||
| 2046 | #define AR_WOW_MAGIC_PAT_FOUND 0x00020000 | ||
| 2047 | #define AR_WOW_MAC_INTR 0x00080000 | ||
| 2048 | #define AR_WOW_KEEP_ALIVE_FAIL 0x00100000 | ||
| 2049 | #define AR_WOW_BEACON_FAIL 0x00200000 | ||
| 2050 | |||
| 2051 | #define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | \ | ||
| 2052 | AR_WOW_MAGIC_PAT_FOUND | \ | ||
| 2053 | AR_WOW_KEEP_ALIVE_FAIL | \ | ||
| 2054 | AR_WOW_BEACON_FAIL)) | ||
| 2055 | #define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \ | ||
| 2056 | AR_WOW_MAGIC_EN | \ | ||
| 2057 | AR_WOW_MAC_INTR_EN | \ | ||
| 2058 | AR_WOW_BEACON_FAIL | \ | ||
| 2059 | AR_WOW_KEEP_ALIVE_FAIL)) | ||
| 2060 | |||
| 2061 | /* AR_WOW_COUNT register values */ | ||
| 2062 | #define AR_WOW_AIFS_CNT(x) (x & 0xff) | ||
| 2063 | #define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8) | ||
| 2064 | #define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16) | ||
| 2065 | |||
| 2066 | /* AR_WOW_BCN_EN register */ | ||
| 2067 | #define AR_WOW_BEACON_FAIL_EN 0x00000001 | ||
| 2068 | |||
| 2069 | /* AR_WOW_BCN_TIMO rgister */ | ||
| 2070 | #define AR_WOW_BEACON_TIMO 0x40000000 /* valid if BCN_EN is set */ | ||
| 2071 | |||
| 2072 | /* AR_WOW_KEEP_ALIVE_TIMO register */ | ||
| 2073 | #define AR_WOW_KEEP_ALIVE_TIMO_VALUE | ||
| 2074 | #define AR_WOW_KEEP_ALIVE_NEVER 0xffffffff | ||
| 2075 | |||
| 2076 | /* AR_WOW_KEEP_ALIVE register */ | ||
| 2077 | #define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001 | ||
| 2078 | #define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002 | ||
| 2079 | |||
| 2080 | /* AR_WOW_KEEP_ALIVE_DELAY register */ | ||
| 2081 | #define AR_WOW_KEEP_ALIVE_DELAY_VALUE 0x000003e8 /* 1 msec */ | ||
| 2082 | |||
| 2083 | |||
| 2084 | /* | ||
| 2085 | * keep it long for beacon workaround - ensure no false alarm | ||
| 2086 | */ | ||
| 2087 | #define AR_WOW_BMISSTHRESHOLD 0x20 | ||
| 2088 | |||
| 2089 | /* AR_WOW_PATTERN_MATCH register */ | ||
| 2090 | #define AR_WOW_PAT_END_OF_PKT(x) (x & 0xf) | ||
| 2091 | #define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8) | ||
| 2092 | |||
| 2093 | /* | ||
| 2094 | * default values for Wow Configuration for backoff, aifs, slot, keep-alive | ||
| 2095 | * to be programmed into various registers. | ||
| 2096 | */ | ||
| 2097 | #define AR_WOW_PAT_BACKOFF 0x00000004 /* AR_WOW_PATTERN_REG */ | ||
| 2098 | #define AR_WOW_CNT_AIFS_CNT 0x00000022 /* AR_WOW_COUNT_REG */ | ||
| 2099 | #define AR_WOW_CNT_SLOT_CNT 0x00000009 /* AR_WOW_COUNT_REG */ | ||
| 2100 | /* | ||
| 2101 | * Keepalive count applicable for AR9280 2.0 and above. | ||
| 2102 | */ | ||
| 2103 | #define AR_WOW_CNT_KA_CNT 0x00000008 /* AR_WOW_COUNT register */ | ||
| 2104 | |||
| 2105 | /* WoW - Transmit buffer for keep alive frames */ | ||
| 2106 | #define AR_WOW_TRANSMIT_BUFFER 0xe000 /* E000 - EFFC */ | ||
| 2107 | |||
| 2108 | #define AR_WOW_TXBUF(i) (AR_WOW_TRANSMIT_BUFFER + ((i) << 2)) | ||
| 2109 | |||
| 2110 | #define AR_WOW_KA_DESC_WORD2 0xe000 | ||
| 2111 | |||
| 2112 | #define AR_WOW_KA_DATA_WORD0 0xe030 | ||
| 2113 | |||
| 2114 | /* WoW Transmit Buffer for patterns */ | ||
| 2115 | #define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8)) | ||
| 2116 | #define AR_WOW_TB_MASK(i) (0xec00 + (i << 5)) | ||
| 2117 | |||
| 2118 | /* Currently Pattern 0-7 are supported - so bit 0-7 are set */ | ||
| 2119 | #define AR_WOW_PATTERN_SUPPORTED 0xff | ||
| 2120 | #define AR_WOW_LENGTH_MAX 0xff | ||
| 2121 | #define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3) | ||
| 2122 | #define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i)) | ||
| 2123 | #define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3) | ||
| 2124 | #define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i)) | ||
| 2125 | |||
| 2126 | #define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ | 2015 | #define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ |
| 2127 | #define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ | 2016 | #define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ |
| 2128 | 2017 | ||
diff --git a/drivers/net/wireless/ath/ath9k/reg_wow.h b/drivers/net/wireless/ath/ath9k/reg_wow.h new file mode 100644 index 000000000000..3abfca56ca58 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/reg_wow.h | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Qualcomm Atheros Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef REG_WOW_H | ||
| 18 | #define REG_WOW_H | ||
| 19 | |||
| 20 | #define AR_WOW_PATTERN 0x825C | ||
| 21 | #define AR_WOW_COUNT 0x8260 | ||
| 22 | #define AR_WOW_BCN_EN 0x8270 | ||
| 23 | #define AR_WOW_BCN_TIMO 0x8274 | ||
| 24 | #define AR_WOW_KEEP_ALIVE_TIMO 0x8278 | ||
| 25 | #define AR_WOW_KEEP_ALIVE 0x827c | ||
| 26 | #define AR_WOW_KEEP_ALIVE_DELAY 0x8288 | ||
| 27 | #define AR_WOW_PATTERN_MATCH 0x828c | ||
| 28 | |||
| 29 | /* | ||
| 30 | * AR_WOW_LENGTH1 | ||
| 31 | * bit 31:24 pattern 0 length | ||
| 32 | * bit 23:16 pattern 1 length | ||
| 33 | * bit 15:8 pattern 2 length | ||
| 34 | * bit 7:0 pattern 3 length | ||
| 35 | * | ||
| 36 | * AR_WOW_LENGTH2 | ||
| 37 | * bit 31:24 pattern 4 length | ||
| 38 | * bit 23:16 pattern 5 length | ||
| 39 | * bit 15:8 pattern 6 length | ||
| 40 | * bit 7:0 pattern 7 length | ||
| 41 | * | ||
| 42 | * AR_WOW_LENGTH3 | ||
| 43 | * bit 31:24 pattern 8 length | ||
| 44 | * bit 23:16 pattern 9 length | ||
| 45 | * bit 15:8 pattern 10 length | ||
| 46 | * bit 7:0 pattern 11 length | ||
| 47 | * | ||
| 48 | * AR_WOW_LENGTH4 | ||
| 49 | * bit 31:24 pattern 12 length | ||
| 50 | * bit 23:16 pattern 13 length | ||
| 51 | * bit 15:8 pattern 14 length | ||
| 52 | * bit 7:0 pattern 15 length | ||
| 53 | */ | ||
| 54 | #define AR_WOW_LENGTH1 0x8360 | ||
| 55 | #define AR_WOW_LENGTH2 0X8364 | ||
| 56 | #define AR_WOW_LENGTH3 0X8380 | ||
| 57 | #define AR_WOW_LENGTH4 0X8384 | ||
| 58 | |||
| 59 | #define AR_WOW_PATTERN_MATCH_LT_256B 0x8368 | ||
| 60 | #define AR_MAC_PCU_WOW4 0x8370 | ||
| 61 | |||
| 62 | #define AR_SW_WOW_CONTROL 0x20018 | ||
| 63 | #define AR_SW_WOW_ENABLE 0x1 | ||
| 64 | #define AR_SWITCH_TO_REFCLK 0x2 | ||
| 65 | #define AR_RESET_CONTROL 0x4 | ||
| 66 | #define AR_RESET_VALUE_MASK 0x8 | ||
| 67 | #define AR_HW_WOW_DISABLE 0x10 | ||
| 68 | #define AR_CLR_MAC_INTERRUPT 0x20 | ||
| 69 | #define AR_CLR_KA_INTERRUPT 0x40 | ||
| 70 | |||
| 71 | #define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 27) /* in usecs */ | ||
| 72 | #define AR_WOW_MAC_INTR_EN 0x00040000 | ||
| 73 | #define AR_WOW_MAGIC_EN 0x00010000 | ||
| 74 | #define AR_WOW_PATTERN_EN(x) (x & 0xff) | ||
| 75 | #define AR_WOW_PAT_FOUND_SHIFT 8 | ||
| 76 | #define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT)) | ||
| 77 | #define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT) | ||
| 78 | #define AR_WOW_MAGIC_PAT_FOUND 0x00020000 | ||
| 79 | #define AR_WOW_MAC_INTR 0x00080000 | ||
| 80 | #define AR_WOW_KEEP_ALIVE_FAIL 0x00100000 | ||
| 81 | #define AR_WOW_BEACON_FAIL 0x00200000 | ||
| 82 | |||
| 83 | #define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | \ | ||
| 84 | AR_WOW_MAGIC_PAT_FOUND | \ | ||
| 85 | AR_WOW_KEEP_ALIVE_FAIL | \ | ||
| 86 | AR_WOW_BEACON_FAIL)) | ||
| 87 | #define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \ | ||
| 88 | AR_WOW_MAGIC_EN | \ | ||
| 89 | AR_WOW_MAC_INTR_EN | \ | ||
| 90 | AR_WOW_BEACON_FAIL | \ | ||
| 91 | AR_WOW_KEEP_ALIVE_FAIL)) | ||
| 92 | |||
| 93 | #define AR_WOW_AIFS_CNT(x) (x & 0xff) | ||
| 94 | #define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8) | ||
| 95 | #define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16) | ||
| 96 | |||
| 97 | #define AR_WOW_BEACON_FAIL_EN 0x00000001 | ||
| 98 | #define AR_WOW_BEACON_TIMO 0x40000000 | ||
| 99 | #define AR_WOW_KEEP_ALIVE_NEVER 0xffffffff | ||
| 100 | #define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001 | ||
| 101 | #define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002 | ||
| 102 | #define AR_WOW_KEEP_ALIVE_DELAY_VALUE 0x000003e8 /* 1 msec */ | ||
| 103 | #define AR_WOW_BMISSTHRESHOLD 0x20 | ||
| 104 | #define AR_WOW_PAT_END_OF_PKT(x) (x & 0xf) | ||
| 105 | #define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8) | ||
| 106 | #define AR_WOW_PAT_BACKOFF 0x00000004 | ||
| 107 | #define AR_WOW_CNT_AIFS_CNT 0x00000022 | ||
| 108 | #define AR_WOW_CNT_SLOT_CNT 0x00000009 | ||
| 109 | #define AR_WOW_CNT_KA_CNT 0x00000008 | ||
| 110 | |||
| 111 | #define AR_WOW_TRANSMIT_BUFFER 0xe000 | ||
| 112 | #define AR_WOW_TXBUF(i) (AR_WOW_TRANSMIT_BUFFER + ((i) << 2)) | ||
| 113 | #define AR_WOW_KA_DESC_WORD2 0xe000 | ||
| 114 | #define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8)) | ||
| 115 | #define AR_WOW_TB_MASK(i) (0xec00 + (i << 5)) | ||
| 116 | #define AR_WOW_PATTERN_SUPPORTED_LEGACY 0xff | ||
| 117 | #define AR_WOW_PATTERN_SUPPORTED 0xffff | ||
| 118 | #define AR_WOW_LENGTH_MAX 0xff | ||
| 119 | #define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3) | ||
| 120 | #define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i)) | ||
| 121 | #define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3) | ||
| 122 | #define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i)) | ||
| 123 | #define AR_WOW_LEN3_SHIFT(_i) ((0xb - ((_i) & 0xb)) << 0x3) | ||
| 124 | #define AR_WOW_LENGTH3_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN3_SHIFT(_i)) | ||
| 125 | #define AR_WOW_LEN4_SHIFT(_i) ((0xf - ((_i) & 0xf)) << 0x3) | ||
| 126 | #define AR_WOW_LENGTH4_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN4_SHIFT(_i)) | ||
| 127 | |||
| 128 | #endif /* REG_WOW_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index 5f30e580d942..8d0b1730a9d5 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c | |||
| @@ -16,36 +16,43 @@ | |||
| 16 | 16 | ||
| 17 | #include "ath9k.h" | 17 | #include "ath9k.h" |
| 18 | 18 | ||
| 19 | static const struct wiphy_wowlan_support ath9k_wowlan_support = { | 19 | static const struct wiphy_wowlan_support ath9k_wowlan_support_legacy = { |
| 20 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, | 20 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, |
| 21 | .n_patterns = MAX_NUM_USER_PATTERN, | 21 | .n_patterns = MAX_NUM_USER_PATTERN, |
| 22 | .pattern_min_len = 1, | 22 | .pattern_min_len = 1, |
| 23 | .pattern_max_len = MAX_PATTERN_SIZE, | 23 | .pattern_max_len = MAX_PATTERN_SIZE, |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | static void ath9k_wow_map_triggers(struct ath_softc *sc, | 26 | static const struct wiphy_wowlan_support ath9k_wowlan_support = { |
| 27 | struct cfg80211_wowlan *wowlan, | 27 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, |
| 28 | u32 *wow_triggers) | 28 | .n_patterns = MAX_NUM_PATTERN - 2, |
| 29 | .pattern_min_len = 1, | ||
| 30 | .pattern_max_len = MAX_PATTERN_SIZE, | ||
| 31 | }; | ||
| 32 | |||
| 33 | static u8 ath9k_wow_map_triggers(struct ath_softc *sc, | ||
| 34 | struct cfg80211_wowlan *wowlan) | ||
| 29 | { | 35 | { |
| 36 | u8 wow_triggers = 0; | ||
| 37 | |||
| 30 | if (wowlan->disconnect) | 38 | if (wowlan->disconnect) |
| 31 | *wow_triggers |= AH_WOW_LINK_CHANGE | | 39 | wow_triggers |= AH_WOW_LINK_CHANGE | |
| 32 | AH_WOW_BEACON_MISS; | 40 | AH_WOW_BEACON_MISS; |
| 33 | if (wowlan->magic_pkt) | 41 | if (wowlan->magic_pkt) |
| 34 | *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; | 42 | wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; |
| 35 | 43 | ||
| 36 | if (wowlan->n_patterns) | 44 | if (wowlan->n_patterns) |
| 37 | *wow_triggers |= AH_WOW_USER_PATTERN_EN; | 45 | wow_triggers |= AH_WOW_USER_PATTERN_EN; |
| 38 | |||
| 39 | sc->wow_enabled = *wow_triggers; | ||
| 40 | 46 | ||
| 47 | return wow_triggers; | ||
| 41 | } | 48 | } |
| 42 | 49 | ||
| 43 | static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | 50 | static int ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) |
| 44 | { | 51 | { |
| 45 | struct ath_hw *ah = sc->sc_ah; | 52 | struct ath_hw *ah = sc->sc_ah; |
| 46 | struct ath_common *common = ath9k_hw_common(ah); | 53 | struct ath_common *common = ath9k_hw_common(ah); |
| 47 | int pattern_count = 0; | 54 | int pattern_count = 0; |
| 48 | int i, byte_cnt; | 55 | int ret, i, byte_cnt = 0; |
| 49 | u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; | 56 | u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; |
| 50 | u8 dis_deauth_mask[MAX_PATTERN_SIZE]; | 57 | u8 dis_deauth_mask[MAX_PATTERN_SIZE]; |
| 51 | 58 | ||
| @@ -80,12 +87,7 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | |||
| 80 | * | x:x:x:x:x:x -- 22 bytes | 87 | * | x:x:x:x:x:x -- 22 bytes |
| 81 | */ | 88 | */ |
| 82 | 89 | ||
| 83 | /* Create Disassociate Pattern first */ | ||
| 84 | |||
| 85 | byte_cnt = 0; | ||
| 86 | |||
| 87 | /* Fill out the mask with all FF's */ | 90 | /* Fill out the mask with all FF's */ |
| 88 | |||
| 89 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) | 91 | for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) |
| 90 | dis_deauth_mask[i] = 0xff; | 92 | dis_deauth_mask[i] = 0xff; |
| 91 | 93 | ||
| @@ -108,19 +110,17 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | |||
| 108 | byte_cnt += 6; | 110 | byte_cnt += 6; |
| 109 | 111 | ||
| 110 | /* copy the bssid, its same as the source mac address */ | 112 | /* copy the bssid, its same as the source mac address */ |
| 111 | |||
| 112 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); | 113 | memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); |
| 113 | 114 | ||
| 114 | /* Create Disassociate pattern mask */ | 115 | /* Create Disassociate pattern mask */ |
| 115 | |||
| 116 | dis_deauth_mask[0] = 0xfe; | 116 | dis_deauth_mask[0] = 0xfe; |
| 117 | dis_deauth_mask[1] = 0x03; | 117 | dis_deauth_mask[1] = 0x03; |
| 118 | dis_deauth_mask[2] = 0xc0; | 118 | dis_deauth_mask[2] = 0xc0; |
| 119 | 119 | ||
| 120 | ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); | 120 | ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, |
| 121 | 121 | pattern_count, byte_cnt); | |
| 122 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, | 122 | if (ret) |
| 123 | pattern_count, byte_cnt); | 123 | goto exit; |
| 124 | 124 | ||
| 125 | pattern_count++; | 125 | pattern_count++; |
| 126 | /* | 126 | /* |
| @@ -129,59 +129,39 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | |||
| 129 | */ | 129 | */ |
| 130 | dis_deauth_pattern[0] = 0xC0; | 130 | dis_deauth_pattern[0] = 0xC0; |
| 131 | 131 | ||
| 132 | ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, | 132 | ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, |
| 133 | pattern_count, byte_cnt); | 133 | pattern_count, byte_cnt); |
| 134 | 134 | exit: | |
| 135 | return ret; | ||
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | static void ath9k_wow_add_pattern(struct ath_softc *sc, | 138 | static int ath9k_wow_add_pattern(struct ath_softc *sc, |
| 138 | struct cfg80211_wowlan *wowlan) | 139 | struct cfg80211_wowlan *wowlan) |
| 139 | { | 140 | { |
| 140 | struct ath_hw *ah = sc->sc_ah; | 141 | struct ath_hw *ah = sc->sc_ah; |
| 141 | struct ath9k_wow_pattern *wow_pattern = NULL; | ||
| 142 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; | 142 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; |
| 143 | int mask_len; | 143 | u8 wow_pattern[MAX_PATTERN_SIZE]; |
| 144 | u8 wow_mask[MAX_PATTERN_SIZE]; | ||
| 145 | int mask_len, ret = 0; | ||
| 144 | s8 i = 0; | 146 | s8 i = 0; |
| 145 | 147 | ||
| 146 | if (!wowlan->n_patterns) | ||
| 147 | return; | ||
| 148 | |||
| 149 | /* | ||
| 150 | * Add the new user configured patterns | ||
| 151 | */ | ||
| 152 | for (i = 0; i < wowlan->n_patterns; i++) { | 148 | for (i = 0; i < wowlan->n_patterns; i++) { |
| 153 | 149 | mask_len = DIV_ROUND_UP(patterns[i].pattern_len, 8); | |
| 154 | wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); | 150 | memset(wow_pattern, 0, MAX_PATTERN_SIZE); |
| 155 | 151 | memset(wow_mask, 0, MAX_PATTERN_SIZE); | |
| 156 | if (!wow_pattern) | 152 | memcpy(wow_pattern, patterns[i].pattern, patterns[i].pattern_len); |
| 157 | return; | 153 | memcpy(wow_mask, patterns[i].mask, mask_len); |
| 158 | 154 | ||
| 159 | /* | 155 | ret = ath9k_hw_wow_apply_pattern(ah, |
| 160 | * TODO: convert the generic user space pattern to | 156 | wow_pattern, |
| 161 | * appropriate chip specific/802.11 pattern. | 157 | wow_mask, |
| 162 | */ | 158 | i + 2, |
| 163 | 159 | patterns[i].pattern_len); | |
| 164 | mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); | 160 | if (ret) |
| 165 | memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); | 161 | break; |
| 166 | memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); | ||
| 167 | memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, | ||
| 168 | patterns[i].pattern_len); | ||
| 169 | memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); | ||
| 170 | wow_pattern->pattern_len = patterns[i].pattern_len; | ||
| 171 | |||
| 172 | /* | ||
| 173 | * just need to take care of deauth and disssoc pattern, | ||
| 174 | * make sure we don't overwrite them. | ||
| 175 | */ | ||
| 176 | |||
| 177 | ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, | ||
| 178 | wow_pattern->mask_bytes, | ||
| 179 | i + 2, | ||
| 180 | wow_pattern->pattern_len); | ||
| 181 | kfree(wow_pattern); | ||
| 182 | |||
| 183 | } | 162 | } |
| 184 | 163 | ||
| 164 | return ret; | ||
| 185 | } | 165 | } |
| 186 | 166 | ||
| 187 | int ath9k_suspend(struct ieee80211_hw *hw, | 167 | int ath9k_suspend(struct ieee80211_hw *hw, |
| @@ -190,41 +170,39 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
| 190 | struct ath_softc *sc = hw->priv; | 170 | struct ath_softc *sc = hw->priv; |
| 191 | struct ath_hw *ah = sc->sc_ah; | 171 | struct ath_hw *ah = sc->sc_ah; |
| 192 | struct ath_common *common = ath9k_hw_common(ah); | 172 | struct ath_common *common = ath9k_hw_common(ah); |
| 193 | u32 wow_triggers_enabled = 0; | 173 | u8 triggers; |
| 194 | int ret = 0; | 174 | int ret = 0; |
| 195 | 175 | ||
| 196 | ath9k_deinit_channel_context(sc); | 176 | ath9k_deinit_channel_context(sc); |
| 197 | 177 | ||
| 198 | mutex_lock(&sc->mutex); | 178 | mutex_lock(&sc->mutex); |
| 199 | 179 | ||
| 200 | ath_cancel_work(sc); | ||
| 201 | ath_stop_ani(sc); | ||
| 202 | |||
| 203 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { | 180 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
| 204 | ath_dbg(common, ANY, "Device not present\n"); | 181 | ath_err(common, "Device not present\n"); |
| 205 | ret = -EINVAL; | 182 | ret = -ENODEV; |
| 206 | goto fail_wow; | 183 | goto fail_wow; |
| 207 | } | 184 | } |
| 208 | 185 | ||
| 209 | if (WARN_ON(!wowlan)) { | 186 | if (WARN_ON(!wowlan)) { |
| 210 | ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); | 187 | ath_err(common, "None of the WoW triggers enabled\n"); |
| 211 | ret = -EINVAL; | 188 | ret = -EINVAL; |
| 212 | goto fail_wow; | 189 | goto fail_wow; |
| 213 | } | 190 | } |
| 214 | 191 | ||
| 215 | if (!device_can_wakeup(sc->dev)) { | 192 | if (sc->cur_chan->nvifs > 1) { |
| 216 | ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); | 193 | ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); |
| 217 | ret = 1; | 194 | ret = 1; |
| 218 | goto fail_wow; | 195 | goto fail_wow; |
| 219 | } | 196 | } |
| 220 | 197 | ||
| 221 | /* | 198 | if (ath9k_is_chanctx_enabled()) { |
| 222 | * none of the sta vifs are associated | 199 | if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) { |
| 223 | * and we are not currently handling multivif | 200 | ath_dbg(common, WOW, |
| 224 | * cases, for instance we have to seperately | 201 | "Multi-channel WOW is not supported\n"); |
| 225 | * configure 'keep alive frame' for each | 202 | ret = 1; |
| 226 | * STA. | 203 | goto fail_wow; |
| 227 | */ | 204 | } |
| 205 | } | ||
| 228 | 206 | ||
| 229 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { | 207 | if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { |
| 230 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); | 208 | ath_dbg(common, WOW, "None of the STA vifs are associated\n"); |
| @@ -232,16 +210,15 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
| 232 | goto fail_wow; | 210 | goto fail_wow; |
| 233 | } | 211 | } |
| 234 | 212 | ||
| 235 | if (sc->cur_chan->nvifs > 1) { | 213 | triggers = ath9k_wow_map_triggers(sc, wowlan); |
| 236 | ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); | 214 | if (!triggers) { |
| 215 | ath_dbg(common, WOW, "No valid WoW triggers\n"); | ||
| 237 | ret = 1; | 216 | ret = 1; |
| 238 | goto fail_wow; | 217 | goto fail_wow; |
| 239 | } | 218 | } |
| 240 | 219 | ||
| 241 | ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); | 220 | ath_cancel_work(sc); |
| 242 | 221 | ath_stop_ani(sc); | |
| 243 | ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", | ||
| 244 | wow_triggers_enabled); | ||
| 245 | 222 | ||
| 246 | ath9k_ps_wakeup(sc); | 223 | ath9k_ps_wakeup(sc); |
| 247 | 224 | ||
| @@ -251,10 +228,21 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
| 251 | * Enable wake up on recieving disassoc/deauth | 228 | * Enable wake up on recieving disassoc/deauth |
| 252 | * frame by default. | 229 | * frame by default. |
| 253 | */ | 230 | */ |
| 254 | ath9k_wow_add_disassoc_deauth_pattern(sc); | 231 | ret = ath9k_wow_add_disassoc_deauth_pattern(sc); |
| 232 | if (ret) { | ||
| 233 | ath_err(common, | ||
| 234 | "Unable to add disassoc/deauth pattern: %d\n", ret); | ||
| 235 | goto fail_wow; | ||
| 236 | } | ||
| 255 | 237 | ||
| 256 | if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) | 238 | if (triggers & AH_WOW_USER_PATTERN_EN) { |
| 257 | ath9k_wow_add_pattern(sc, wowlan); | 239 | ret = ath9k_wow_add_pattern(sc, wowlan); |
| 240 | if (ret) { | ||
| 241 | ath_err(common, | ||
| 242 | "Unable to add user pattern: %d\n", ret); | ||
| 243 | goto fail_wow; | ||
| 244 | } | ||
| 245 | } | ||
| 258 | 246 | ||
| 259 | spin_lock_bh(&sc->sc_pcu_lock); | 247 | spin_lock_bh(&sc->sc_pcu_lock); |
| 260 | /* | 248 | /* |
| @@ -278,12 +266,12 @@ int ath9k_suspend(struct ieee80211_hw *hw, | |||
| 278 | synchronize_irq(sc->irq); | 266 | synchronize_irq(sc->irq); |
| 279 | tasklet_kill(&sc->intr_tq); | 267 | tasklet_kill(&sc->intr_tq); |
| 280 | 268 | ||
| 281 | ath9k_hw_wow_enable(ah, wow_triggers_enabled); | 269 | ath9k_hw_wow_enable(ah, triggers); |
| 282 | 270 | ||
| 283 | ath9k_ps_restore(sc); | 271 | ath9k_ps_restore(sc); |
| 284 | ath_dbg(common, ANY, "WoW enabled in ath9k\n"); | 272 | ath_dbg(common, WOW, "Suspend with WoW triggers: 0x%x\n", triggers); |
| 285 | atomic_inc(&sc->wow_sleep_proc_intr); | ||
| 286 | 273 | ||
| 274 | set_bit(ATH_OP_WOW_ENABLED, &common->op_flags); | ||
| 287 | fail_wow: | 275 | fail_wow: |
| 288 | mutex_unlock(&sc->mutex); | 276 | mutex_unlock(&sc->mutex); |
| 289 | return ret; | 277 | return ret; |
| @@ -294,7 +282,7 @@ int ath9k_resume(struct ieee80211_hw *hw) | |||
| 294 | struct ath_softc *sc = hw->priv; | 282 | struct ath_softc *sc = hw->priv; |
| 295 | struct ath_hw *ah = sc->sc_ah; | 283 | struct ath_hw *ah = sc->sc_ah; |
| 296 | struct ath_common *common = ath9k_hw_common(ah); | 284 | struct ath_common *common = ath9k_hw_common(ah); |
| 297 | u32 wow_status; | 285 | u8 status; |
| 298 | 286 | ||
| 299 | mutex_lock(&sc->mutex); | 287 | mutex_lock(&sc->mutex); |
| 300 | 288 | ||
| @@ -309,29 +297,14 @@ int ath9k_resume(struct ieee80211_hw *hw) | |||
| 309 | 297 | ||
| 310 | spin_unlock_bh(&sc->sc_pcu_lock); | 298 | spin_unlock_bh(&sc->sc_pcu_lock); |
| 311 | 299 | ||
| 312 | wow_status = ath9k_hw_wow_wakeup(ah); | 300 | status = ath9k_hw_wow_wakeup(ah); |
| 313 | 301 | ath_dbg(common, WOW, "Resume with WoW status: 0x%x\n", status); | |
| 314 | if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { | ||
| 315 | /* | ||
| 316 | * some devices may not pick beacon miss | ||
| 317 | * as the reason they woke up so we add | ||
| 318 | * that here for that shortcoming. | ||
| 319 | */ | ||
| 320 | wow_status |= AH_WOW_BEACON_MISS; | ||
| 321 | atomic_dec(&sc->wow_got_bmiss_intr); | ||
| 322 | ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); | ||
| 323 | } | ||
| 324 | |||
| 325 | atomic_dec(&sc->wow_sleep_proc_intr); | ||
| 326 | |||
| 327 | if (wow_status) { | ||
| 328 | ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", | ||
| 329 | ath9k_hw_wow_event_to_string(wow_status), wow_status); | ||
| 330 | } | ||
| 331 | 302 | ||
| 332 | ath_restart_work(sc); | 303 | ath_restart_work(sc); |
| 333 | ath9k_start_btcoex(sc); | 304 | ath9k_start_btcoex(sc); |
| 334 | 305 | ||
| 306 | clear_bit(ATH_OP_WOW_ENABLED, &common->op_flags); | ||
| 307 | |||
| 335 | ath9k_ps_restore(sc); | 308 | ath9k_ps_restore(sc); |
| 336 | mutex_unlock(&sc->mutex); | 309 | mutex_unlock(&sc->mutex); |
| 337 | 310 | ||
| @@ -341,22 +314,35 @@ int ath9k_resume(struct ieee80211_hw *hw) | |||
| 341 | void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) | 314 | void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) |
| 342 | { | 315 | { |
| 343 | struct ath_softc *sc = hw->priv; | 316 | struct ath_softc *sc = hw->priv; |
| 317 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 344 | 318 | ||
| 345 | mutex_lock(&sc->mutex); | 319 | mutex_lock(&sc->mutex); |
| 346 | device_init_wakeup(sc->dev, 1); | ||
| 347 | device_set_wakeup_enable(sc->dev, enabled); | 320 | device_set_wakeup_enable(sc->dev, enabled); |
| 348 | mutex_unlock(&sc->mutex); | 321 | mutex_unlock(&sc->mutex); |
| 322 | |||
| 323 | ath_dbg(common, WOW, "WoW wakeup source is %s\n", | ||
| 324 | (enabled) ? "enabled" : "disabled"); | ||
| 349 | } | 325 | } |
| 350 | 326 | ||
| 351 | void ath9k_init_wow(struct ieee80211_hw *hw) | 327 | void ath9k_init_wow(struct ieee80211_hw *hw) |
| 352 | { | 328 | { |
| 353 | struct ath_softc *sc = hw->priv; | 329 | struct ath_softc *sc = hw->priv; |
| 330 | struct ath_hw *ah = sc->sc_ah; | ||
| 331 | |||
| 332 | if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) { | ||
| 333 | if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah)) | ||
| 334 | hw->wiphy->wowlan = &ath9k_wowlan_support; | ||
| 335 | else | ||
| 336 | hw->wiphy->wowlan = &ath9k_wowlan_support_legacy; | ||
| 354 | 337 | ||
| 355 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && | 338 | device_init_wakeup(sc->dev, 1); |
| 356 | (sc->driver_data & ATH9K_PCI_WOW) && | 339 | } |
| 357 | device_can_wakeup(sc->dev)) | 340 | } |
| 358 | hw->wiphy->wowlan = &ath9k_wowlan_support; | 341 | |
| 342 | void ath9k_deinit_wow(struct ieee80211_hw *hw) | ||
| 343 | { | ||
| 344 | struct ath_softc *sc = hw->priv; | ||
| 359 | 345 | ||
| 360 | atomic_set(&sc->wow_sleep_proc_intr, -1); | 346 | if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) |
| 361 | atomic_set(&sc->wow_got_bmiss_intr, -1); | 347 | device_init_wakeup(sc->dev, 0); |
| 362 | } | 348 | } |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 52d63de4a93d..1b8e75c4d2c2 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -1097,24 +1097,65 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop) | |||
| 1097 | } | 1097 | } |
| 1098 | 1098 | ||
| 1099 | static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, | 1099 | static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, |
| 1100 | u8 rateidx) | 1100 | u8 rateidx, bool is_40, bool is_cck) |
| 1101 | { | 1101 | { |
| 1102 | u8 max_power; | 1102 | u8 max_power; |
| 1103 | struct sk_buff *skb; | ||
| 1104 | struct ath_frame_info *fi; | ||
| 1105 | struct ieee80211_tx_info *info; | ||
| 1103 | struct ath_hw *ah = sc->sc_ah; | 1106 | struct ath_hw *ah = sc->sc_ah; |
| 1104 | 1107 | ||
| 1105 | if (sc->tx99_state) | 1108 | if (sc->tx99_state || !ah->tpc_enabled) |
| 1106 | return MAX_RATE_POWER; | 1109 | return MAX_RATE_POWER; |
| 1107 | 1110 | ||
| 1111 | skb = bf->bf_mpdu; | ||
| 1112 | fi = get_frame_info(skb); | ||
| 1113 | info = IEEE80211_SKB_CB(skb); | ||
| 1114 | |||
| 1108 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | 1115 | if (!AR_SREV_9300_20_OR_LATER(ah)) { |
| 1109 | /* ar9002 does not support TPC for the moment */ | 1116 | int txpower = fi->tx_power; |
| 1110 | return MAX_RATE_POWER; | ||
| 1111 | } | ||
| 1112 | 1117 | ||
| 1113 | if (!bf->bf_state.bfs_paprd) { | 1118 | if (is_40) { |
| 1114 | struct sk_buff *skb = bf->bf_mpdu; | 1119 | u8 power_ht40delta; |
| 1115 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1120 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
| 1116 | struct ath_frame_info *fi = get_frame_info(skb); | 1121 | |
| 1122 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { | ||
| 1123 | bool is_2ghz; | ||
| 1124 | struct modal_eep_header *pmodal; | ||
| 1117 | 1125 | ||
| 1126 | is_2ghz = info->band == IEEE80211_BAND_2GHZ; | ||
| 1127 | pmodal = &eep->modalHeader[is_2ghz]; | ||
| 1128 | power_ht40delta = pmodal->ht40PowerIncForPdadc; | ||
| 1129 | } else { | ||
| 1130 | power_ht40delta = 2; | ||
| 1131 | } | ||
| 1132 | txpower += power_ht40delta; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | if (AR_SREV_9287(ah) || AR_SREV_9285(ah) || | ||
| 1136 | AR_SREV_9271(ah)) { | ||
| 1137 | txpower -= 2 * AR9287_PWR_TABLE_OFFSET_DB; | ||
| 1138 | } else if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
| 1139 | s8 power_offset; | ||
| 1140 | |||
| 1141 | power_offset = ah->eep_ops->get_eeprom(ah, | ||
| 1142 | EEP_PWR_TABLE_OFFSET); | ||
| 1143 | txpower -= 2 * power_offset; | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | if (OLC_FOR_AR9280_20_LATER && is_cck) | ||
| 1147 | txpower -= 2; | ||
| 1148 | |||
| 1149 | txpower = max(txpower, 0); | ||
| 1150 | max_power = min_t(u8, ah->tx_power[rateidx], txpower); | ||
| 1151 | |||
| 1152 | /* XXX: clamp minimum TX power at 1 for AR9160 since if | ||
| 1153 | * max_power is set to 0, frames are transmitted at max | ||
| 1154 | * TX power | ||
| 1155 | */ | ||
| 1156 | if (!max_power && !AR_SREV_9280_20_OR_LATER(ah)) | ||
| 1157 | max_power = 1; | ||
| 1158 | } else if (!bf->bf_state.bfs_paprd) { | ||
| 1118 | if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC)) | 1159 | if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC)) |
| 1119 | max_power = min(ah->tx_power_stbc[rateidx], | 1160 | max_power = min(ah->tx_power_stbc[rateidx], |
| 1120 | fi->tx_power); | 1161 | fi->tx_power); |
| @@ -1152,7 +1193,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
| 1152 | info->rtscts_rate = fi->rtscts_rate; | 1193 | info->rtscts_rate = fi->rtscts_rate; |
| 1153 | 1194 | ||
| 1154 | for (i = 0; i < ARRAY_SIZE(bf->rates); i++) { | 1195 | for (i = 0; i < ARRAY_SIZE(bf->rates); i++) { |
| 1155 | bool is_40, is_sgi, is_sp; | 1196 | bool is_40, is_sgi, is_sp, is_cck; |
| 1156 | int phy; | 1197 | int phy; |
| 1157 | 1198 | ||
| 1158 | if (!rates[i].count || (rates[i].idx < 0)) | 1199 | if (!rates[i].count || (rates[i].idx < 0)) |
| @@ -1198,7 +1239,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
| 1198 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) | 1239 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) |
| 1199 | info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; | 1240 | info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; |
| 1200 | 1241 | ||
| 1201 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix); | 1242 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, |
| 1243 | is_40, false); | ||
| 1202 | continue; | 1244 | continue; |
| 1203 | } | 1245 | } |
| 1204 | 1246 | ||
| @@ -1227,7 +1269,9 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
| 1227 | info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, | 1269 | info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, |
| 1228 | phy, rate->bitrate * 100, len, rix, is_sp); | 1270 | phy, rate->bitrate * 100, len, rix, is_sp); |
| 1229 | 1271 | ||
| 1230 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix); | 1272 | is_cck = IS_CCK_RATE(info->rates[i].Rate); |
| 1273 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, false, | ||
| 1274 | is_cck); | ||
| 1231 | } | 1275 | } |
| 1232 | 1276 | ||
| 1233 | /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ | 1277 | /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ |
| @@ -2259,7 +2303,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 2259 | struct ath_txq *txq = txctl->txq; | 2303 | struct ath_txq *txq = txctl->txq; |
| 2260 | struct ath_atx_tid *tid = NULL; | 2304 | struct ath_atx_tid *tid = NULL; |
| 2261 | struct ath_buf *bf; | 2305 | struct ath_buf *bf; |
| 2262 | bool queue, skip_uapsd = false; | 2306 | bool queue, skip_uapsd = false, ps_resp; |
| 2263 | int q, ret; | 2307 | int q, ret; |
| 2264 | 2308 | ||
| 2265 | if (vif) | 2309 | if (vif) |
| @@ -2268,6 +2312,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 2268 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | 2312 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) |
| 2269 | txctl->force_channel = true; | 2313 | txctl->force_channel = true; |
| 2270 | 2314 | ||
| 2315 | ps_resp = !!(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE); | ||
| 2316 | |||
| 2271 | ret = ath_tx_prepare(hw, skb, txctl); | 2317 | ret = ath_tx_prepare(hw, skb, txctl); |
| 2272 | if (ret) | 2318 | if (ret) |
| 2273 | return ret; | 2319 | return ret; |
| @@ -2310,7 +2356,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 2310 | if (txctl->an && queue) | 2356 | if (txctl->an && queue) |
| 2311 | tid = ath_get_skb_tid(sc, txctl->an, skb); | 2357 | tid = ath_get_skb_tid(sc, txctl->an, skb); |
| 2312 | 2358 | ||
| 2313 | if (!skip_uapsd && (info->flags & IEEE80211_TX_CTL_PS_RESPONSE)) { | 2359 | if (!skip_uapsd && ps_resp) { |
| 2314 | ath_txq_unlock(sc, txq); | 2360 | ath_txq_unlock(sc, txq); |
| 2315 | txq = sc->tx.uapsdq; | 2361 | txq = sc->tx.uapsdq; |
| 2316 | ath_txq_lock(sc, txq); | 2362 | ath_txq_lock(sc, txq); |
| @@ -2443,9 +2489,12 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
| 2443 | if (sc->sc_ah->caldata) | 2489 | if (sc->sc_ah->caldata) |
| 2444 | set_bit(PAPRD_PACKET_SENT, &sc->sc_ah->caldata->cal_flags); | 2490 | set_bit(PAPRD_PACKET_SENT, &sc->sc_ah->caldata->cal_flags); |
| 2445 | 2491 | ||
| 2446 | if (!(tx_flags & ATH_TX_ERROR)) | 2492 | if (!(tx_flags & ATH_TX_ERROR)) { |
| 2447 | /* Frame was ACKed */ | 2493 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) |
| 2448 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 2494 | tx_info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
| 2495 | else | ||
| 2496 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
| 2497 | } | ||
| 2449 | 2498 | ||
| 2450 | padpos = ieee80211_hdrlen(hdr->frame_control); | 2499 | padpos = ieee80211_hdrlen(hdr->frame_control); |
| 2451 | padsize = padpos & 3; | 2500 | padsize = padpos & 3; |
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index 39a63874b275..f2b4f537e4c1 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c | |||
| @@ -188,12 +188,12 @@ int carl9170_collect_tally(struct ar9170 *ar) | |||
| 188 | 188 | ||
| 189 | if (ar->channel) { | 189 | if (ar->channel) { |
| 190 | info = &ar->survey[ar->channel->hw_value]; | 190 | info = &ar->survey[ar->channel->hw_value]; |
| 191 | info->channel_time = ar->tally.active; | 191 | info->time = ar->tally.active; |
| 192 | info->channel_time_busy = ar->tally.cca; | 192 | info->time_busy = ar->tally.cca; |
| 193 | info->channel_time_tx = ar->tally.tx_time; | 193 | info->time_tx = ar->tally.tx_time; |
| 194 | do_div(info->channel_time, 1000); | 194 | do_div(info->time, 1000); |
| 195 | do_div(info->channel_time_busy, 1000); | 195 | do_div(info->time_busy, 1000); |
| 196 | do_div(info->channel_time_tx, 1000); | 196 | do_div(info->time_tx, 1000); |
| 197 | } | 197 | } |
| 198 | } | 198 | } |
| 199 | return 0; | 199 | return 0; |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index ef5b6dc7b7f1..f1455a04cb62 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
| @@ -1690,9 +1690,9 @@ found: | |||
| 1690 | survey->filled |= SURVEY_INFO_IN_USE; | 1690 | survey->filled |= SURVEY_INFO_IN_USE; |
| 1691 | 1691 | ||
| 1692 | if (ar->fw.hw_counters) { | 1692 | if (ar->fw.hw_counters) { |
| 1693 | survey->filled |= SURVEY_INFO_CHANNEL_TIME | | 1693 | survey->filled |= SURVEY_INFO_TIME | |
| 1694 | SURVEY_INFO_CHANNEL_TIME_BUSY | | 1694 | SURVEY_INFO_TIME_BUSY | |
| 1695 | SURVEY_INFO_CHANNEL_TIME_TX; | 1695 | SURVEY_INFO_TIME_TX; |
| 1696 | } | 1696 | } |
| 1697 | 1697 | ||
| 1698 | return 0; | 1698 | return 0; |
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 73f12f196f14..086549b732b9 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c | |||
| @@ -84,6 +84,7 @@ static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) | |||
| 84 | if (!cur_ctl) | 84 | if (!cur_ctl) |
| 85 | goto out_fail; | 85 | goto out_fail; |
| 86 | 86 | ||
| 87 | spin_lock_init(&cur_ctl->skb_lock); | ||
| 87 | cur_ctl->ctl_blk_order = i; | 88 | cur_ctl->ctl_blk_order = i; |
| 88 | if (i == 0) { | 89 | if (i == 0) { |
| 89 | ch->head_blk_ctl = cur_ctl; | 90 | ch->head_blk_ctl = cur_ctl; |
| @@ -354,6 +355,8 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | |||
| 354 | * and while-do will not make any cycles. | 355 | * and while-do will not make any cycles. |
| 355 | */ | 356 | */ |
| 356 | do { | 357 | do { |
| 358 | if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) | ||
| 359 | break; | ||
| 357 | if (ctl->skb) { | 360 | if (ctl->skb) { |
| 358 | dma_unmap_single(NULL, ctl->desc->src_addr_l, | 361 | dma_unmap_single(NULL, ctl->desc->src_addr_l, |
| 359 | ctl->skb->len, DMA_TO_DEVICE); | 362 | ctl->skb->len, DMA_TO_DEVICE); |
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7dd8873f757e..0783d2ed8238 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c | |||
| @@ -298,6 +298,8 @@ static int wcn36xx_start(struct ieee80211_hw *hw) | |||
| 298 | wcn36xx_debugfs_init(wcn); | 298 | wcn36xx_debugfs_init(wcn); |
| 299 | 299 | ||
| 300 | INIT_LIST_HEAD(&wcn->vif_list); | 300 | INIT_LIST_HEAD(&wcn->vif_list); |
| 301 | spin_lock_init(&wcn->dxe_lock); | ||
| 302 | |||
| 301 | return 0; | 303 | return 0; |
| 302 | 304 | ||
| 303 | out_smd_stop: | 305 | out_smd_stop: |
| @@ -795,6 +797,7 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
| 795 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", | 797 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", |
| 796 | vif, sta->addr); | 798 | vif, sta->addr); |
| 797 | 799 | ||
| 800 | spin_lock_init(&sta_priv->ampdu_lock); | ||
| 798 | vif_priv->sta = sta_priv; | 801 | vif_priv->sta = sta_priv; |
| 799 | sta_priv->vif = vif_priv; | 802 | sta_priv->vif = vif_priv; |
| 800 | /* | 803 | /* |
| @@ -873,21 +876,32 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, | |||
| 873 | get_sta_index(vif, sta_priv)); | 876 | get_sta_index(vif, sta_priv)); |
| 874 | wcn36xx_smd_add_ba(wcn); | 877 | wcn36xx_smd_add_ba(wcn); |
| 875 | wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); | 878 | wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); |
| 876 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
| 877 | break; | 879 | break; |
| 878 | case IEEE80211_AMPDU_RX_STOP: | 880 | case IEEE80211_AMPDU_RX_STOP: |
| 879 | wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); | 881 | wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); |
| 880 | break; | 882 | break; |
| 881 | case IEEE80211_AMPDU_TX_START: | 883 | case IEEE80211_AMPDU_TX_START: |
| 884 | spin_lock_bh(&sta_priv->ampdu_lock); | ||
| 885 | sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START; | ||
| 886 | spin_unlock_bh(&sta_priv->ampdu_lock); | ||
| 887 | |||
| 882 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 888 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
| 883 | break; | 889 | break; |
| 884 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 890 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
| 891 | spin_lock_bh(&sta_priv->ampdu_lock); | ||
| 892 | sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL; | ||
| 893 | spin_unlock_bh(&sta_priv->ampdu_lock); | ||
| 894 | |||
| 885 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, | 895 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, |
| 886 | get_sta_index(vif, sta_priv)); | 896 | get_sta_index(vif, sta_priv)); |
| 887 | break; | 897 | break; |
| 888 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | 898 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
| 889 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 899 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
| 890 | case IEEE80211_AMPDU_TX_STOP_CONT: | 900 | case IEEE80211_AMPDU_TX_STOP_CONT: |
| 901 | spin_lock_bh(&sta_priv->ampdu_lock); | ||
| 902 | sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE; | ||
| 903 | spin_unlock_bh(&sta_priv->ampdu_lock); | ||
| 904 | |||
| 891 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 905 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
| 892 | break; | 906 | break; |
| 893 | default: | 907 | default: |
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 63986931829e..69ed39731902 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c | |||
| @@ -21,6 +21,61 @@ | |||
| 21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
| 22 | #include "smd.h" | 22 | #include "smd.h" |
| 23 | 23 | ||
| 24 | struct wcn36xx_cfg_val { | ||
| 25 | u32 cfg_id; | ||
| 26 | u32 value; | ||
| 27 | }; | ||
| 28 | |||
| 29 | #define WCN36XX_CFG_VAL(id, val) \ | ||
| 30 | { \ | ||
| 31 | .cfg_id = WCN36XX_HAL_CFG_ ## id, \ | ||
| 32 | .value = val \ | ||
| 33 | } | ||
| 34 | |||
| 35 | static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = { | ||
| 36 | WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1), | ||
| 37 | WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1), | ||
| 38 | WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0), | ||
| 39 | WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785), | ||
| 40 | WCN36XX_CFG_VAL(CAL_PERIOD, 5), | ||
| 41 | WCN36XX_CFG_VAL(CAL_CONTROL, 1), | ||
| 42 | WCN36XX_CFG_VAL(PROXIMITY, 0), | ||
| 43 | WCN36XX_CFG_VAL(NETWORK_DENSITY, 3), | ||
| 44 | WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000), | ||
| 45 | WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64), | ||
| 46 | WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347), | ||
| 47 | WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 6), | ||
| 48 | WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 6), | ||
| 49 | WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000), | ||
| 50 | WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5), | ||
| 51 | WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10), | ||
| 52 | WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15), | ||
| 53 | WCN36XX_CFG_VAL(FIXED_RATE, 0), | ||
| 54 | WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4), | ||
| 55 | WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0), | ||
| 56 | WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0), | ||
| 57 | WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5), | ||
| 58 | WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1), | ||
| 59 | WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5), | ||
| 60 | WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5), | ||
| 61 | WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40), | ||
| 62 | WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200), | ||
| 63 | WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1), | ||
| 64 | WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1), | ||
| 65 | WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20), | ||
| 66 | WCN36XX_CFG_VAL(STATS_PERIOD, 10), | ||
| 67 | WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000), | ||
| 68 | WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0), | ||
| 69 | WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128), | ||
| 70 | WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560), | ||
| 71 | WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0), | ||
| 72 | WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1), | ||
| 73 | WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1), | ||
| 74 | WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), | ||
| 75 | WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), | ||
| 76 | WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), | ||
| 77 | }; | ||
| 78 | |||
| 24 | static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) | 79 | static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) |
| 25 | { | 80 | { |
| 26 | struct wcn36xx_hal_cfg *entry; | 81 | struct wcn36xx_hal_cfg *entry; |
| @@ -357,8 +412,10 @@ static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) | |||
| 357 | 412 | ||
| 358 | int wcn36xx_smd_start(struct wcn36xx *wcn) | 413 | int wcn36xx_smd_start(struct wcn36xx *wcn) |
| 359 | { | 414 | { |
| 360 | struct wcn36xx_hal_mac_start_req_msg msg_body; | 415 | struct wcn36xx_hal_mac_start_req_msg msg_body, *body; |
| 361 | int ret = 0; | 416 | int ret = 0; |
| 417 | int i; | ||
| 418 | size_t len; | ||
| 362 | 419 | ||
| 363 | mutex_lock(&wcn->hal_mutex); | 420 | mutex_lock(&wcn->hal_mutex); |
| 364 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); | 421 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); |
| @@ -368,10 +425,22 @@ int wcn36xx_smd_start(struct wcn36xx *wcn) | |||
| 368 | 425 | ||
| 369 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | 426 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); |
| 370 | 427 | ||
| 428 | body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf; | ||
| 429 | len = body->header.len; | ||
| 430 | |||
| 431 | for (i = 0; i < ARRAY_SIZE(wcn36xx_cfg_vals); i++) { | ||
| 432 | ret = put_cfg_tlv_u32(wcn, &len, wcn36xx_cfg_vals[i].cfg_id, | ||
| 433 | wcn36xx_cfg_vals[i].value); | ||
| 434 | if (ret) | ||
| 435 | goto out; | ||
| 436 | } | ||
| 437 | body->header.len = len; | ||
| 438 | body->params.len = len - sizeof(*body); | ||
| 439 | |||
| 371 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n", | 440 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n", |
| 372 | msg_body.params.type); | 441 | msg_body.params.type); |
| 373 | 442 | ||
| 374 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | 443 | ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); |
| 375 | if (ret) { | 444 | if (ret) { |
| 376 | wcn36xx_err("Sending hal_start failed\n"); | 445 | wcn36xx_err("Sending hal_start failed\n"); |
| 377 | goto out; | 446 | goto out; |
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 32bb26a0db2a..9bec8237231d 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c | |||
| @@ -93,6 +93,7 @@ static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, | |||
| 93 | bd->pdu.mpdu_header_off; | 93 | bd->pdu.mpdu_header_off; |
| 94 | bd->pdu.mpdu_len = len; | 94 | bd->pdu.mpdu_len = len; |
| 95 | bd->pdu.tid = tid; | 95 | bd->pdu.tid = tid; |
| 96 | bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS; | ||
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, | 99 | static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, |
| @@ -110,15 +111,54 @@ static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, | |||
| 110 | wcn36xx_warn("vif %pM not found\n", addr); | 111 | wcn36xx_warn("vif %pM not found\n", addr); |
| 111 | return NULL; | 112 | return NULL; |
| 112 | } | 113 | } |
| 114 | |||
| 115 | static void wcn36xx_tx_start_ampdu(struct wcn36xx *wcn, | ||
| 116 | struct wcn36xx_sta *sta_priv, | ||
| 117 | struct sk_buff *skb) | ||
| 118 | { | ||
| 119 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
| 120 | struct ieee80211_sta *sta; | ||
| 121 | u8 *qc, tid; | ||
| 122 | |||
| 123 | if (!conf_is_ht(&wcn->hw->conf)) | ||
| 124 | return; | ||
| 125 | |||
| 126 | sta = wcn36xx_priv_to_sta(sta_priv); | ||
| 127 | |||
| 128 | if (WARN_ON(!ieee80211_is_data_qos(hdr->frame_control))) | ||
| 129 | return; | ||
| 130 | |||
| 131 | if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) | ||
| 132 | return; | ||
| 133 | |||
| 134 | qc = ieee80211_get_qos_ctl(hdr); | ||
| 135 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
| 136 | |||
| 137 | spin_lock(&sta_priv->ampdu_lock); | ||
| 138 | if (sta_priv->ampdu_state[tid] != WCN36XX_AMPDU_NONE) | ||
| 139 | goto out_unlock; | ||
| 140 | |||
| 141 | if (sta_priv->non_agg_frame_ct++ >= WCN36XX_AMPDU_START_THRESH) { | ||
| 142 | sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START; | ||
| 143 | sta_priv->non_agg_frame_ct = 0; | ||
| 144 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
| 145 | } | ||
| 146 | out_unlock: | ||
| 147 | spin_unlock(&sta_priv->ampdu_lock); | ||
| 148 | } | ||
| 149 | |||
| 113 | static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, | 150 | static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, |
| 114 | struct wcn36xx *wcn, | 151 | struct wcn36xx *wcn, |
| 115 | struct wcn36xx_vif **vif_priv, | 152 | struct wcn36xx_vif **vif_priv, |
| 116 | struct wcn36xx_sta *sta_priv, | 153 | struct wcn36xx_sta *sta_priv, |
| 117 | struct ieee80211_hdr *hdr, | 154 | struct sk_buff *skb, |
| 118 | bool bcast) | 155 | bool bcast) |
| 119 | { | 156 | { |
| 157 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
| 120 | struct ieee80211_vif *vif = NULL; | 158 | struct ieee80211_vif *vif = NULL; |
| 121 | struct wcn36xx_vif *__vif_priv = NULL; | 159 | struct wcn36xx_vif *__vif_priv = NULL; |
| 160 | bool is_data_qos; | ||
| 161 | |||
| 122 | bd->bd_rate = WCN36XX_BD_RATE_DATA; | 162 | bd->bd_rate = WCN36XX_BD_RATE_DATA; |
| 123 | 163 | ||
| 124 | /* | 164 | /* |
| @@ -157,14 +197,26 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, | |||
| 157 | bd->ack_policy = 1; | 197 | bd->ack_policy = 1; |
| 158 | } | 198 | } |
| 159 | *vif_priv = __vif_priv; | 199 | *vif_priv = __vif_priv; |
| 200 | |||
| 201 | is_data_qos = ieee80211_is_data_qos(hdr->frame_control); | ||
| 202 | |||
| 203 | wcn36xx_set_tx_pdu(bd, | ||
| 204 | is_data_qos ? | ||
| 205 | sizeof(struct ieee80211_qos_hdr) : | ||
| 206 | sizeof(struct ieee80211_hdr_3addr), | ||
| 207 | skb->len, sta_priv ? sta_priv->tid : 0); | ||
| 208 | |||
| 209 | if (sta_priv && is_data_qos) | ||
| 210 | wcn36xx_tx_start_ampdu(wcn, sta_priv, skb); | ||
| 160 | } | 211 | } |
| 161 | 212 | ||
| 162 | static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, | 213 | static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, |
| 163 | struct wcn36xx *wcn, | 214 | struct wcn36xx *wcn, |
| 164 | struct wcn36xx_vif **vif_priv, | 215 | struct wcn36xx_vif **vif_priv, |
| 165 | struct ieee80211_hdr *hdr, | 216 | struct sk_buff *skb, |
| 166 | bool bcast) | 217 | bool bcast) |
| 167 | { | 218 | { |
| 219 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
| 168 | struct wcn36xx_vif *__vif_priv = | 220 | struct wcn36xx_vif *__vif_priv = |
| 169 | get_vif_by_addr(wcn, hdr->addr2); | 221 | get_vif_by_addr(wcn, hdr->addr2); |
| 170 | bd->sta_index = __vif_priv->self_sta_index; | 222 | bd->sta_index = __vif_priv->self_sta_index; |
| @@ -198,6 +250,12 @@ static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, | |||
| 198 | } else | 250 | } else |
| 199 | bd->queue_id = WCN36XX_TX_U_WQ_ID; | 251 | bd->queue_id = WCN36XX_TX_U_WQ_ID; |
| 200 | *vif_priv = __vif_priv; | 252 | *vif_priv = __vif_priv; |
| 253 | |||
| 254 | wcn36xx_set_tx_pdu(bd, | ||
| 255 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
| 256 | sizeof(struct ieee80211_qos_hdr) : | ||
| 257 | sizeof(struct ieee80211_hdr_3addr), | ||
| 258 | skb->len, WCN36XX_TID); | ||
| 201 | } | 259 | } |
| 202 | 260 | ||
| 203 | int wcn36xx_start_tx(struct wcn36xx *wcn, | 261 | int wcn36xx_start_tx(struct wcn36xx *wcn, |
| @@ -237,7 +295,7 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, | |||
| 237 | 295 | ||
| 238 | bd->dpu_rf = WCN36XX_BMU_WQ_TX; | 296 | bd->dpu_rf = WCN36XX_BMU_WQ_TX; |
| 239 | 297 | ||
| 240 | bd->tx_comp = info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS; | 298 | bd->tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS); |
| 241 | if (bd->tx_comp) { | 299 | if (bd->tx_comp) { |
| 242 | wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); | 300 | wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); |
| 243 | spin_lock_irqsave(&wcn->dxe_lock, flags); | 301 | spin_lock_irqsave(&wcn->dxe_lock, flags); |
| @@ -259,22 +317,11 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, | |||
| 259 | } | 317 | } |
| 260 | 318 | ||
| 261 | /* Data frames served first*/ | 319 | /* Data frames served first*/ |
| 262 | if (is_low) { | 320 | if (is_low) |
| 263 | wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, hdr, bcast); | 321 | wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, skb, bcast); |
| 264 | wcn36xx_set_tx_pdu(bd, | 322 | else |
| 265 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
| 266 | sizeof(struct ieee80211_qos_hdr) : | ||
| 267 | sizeof(struct ieee80211_hdr_3addr), | ||
| 268 | skb->len, sta_priv ? sta_priv->tid : 0); | ||
| 269 | } else { | ||
| 270 | /* MGMT and CTRL frames are handeld here*/ | 323 | /* MGMT and CTRL frames are handeld here*/ |
| 271 | wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, hdr, bcast); | 324 | wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, skb, bcast); |
| 272 | wcn36xx_set_tx_pdu(bd, | ||
| 273 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
| 274 | sizeof(struct ieee80211_qos_hdr) : | ||
| 275 | sizeof(struct ieee80211_hdr_3addr), | ||
| 276 | skb->len, WCN36XX_TID); | ||
| 277 | } | ||
| 278 | 325 | ||
| 279 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); | 326 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); |
| 280 | bd->tx_bd_sign = 0xbdbdbdbd; | 327 | bd->tx_bd_sign = 0xbdbdbdbd; |
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h index bbfbcf808c77..032216e82b2b 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.h +++ b/drivers/net/wireless/ath/wcn36xx/txrx.h | |||
| @@ -32,6 +32,12 @@ | |||
| 32 | #define WCN36XX_BD_RATE_MGMT 2 | 32 | #define WCN36XX_BD_RATE_MGMT 2 |
| 33 | #define WCN36XX_BD_RATE_CTRL 3 | 33 | #define WCN36XX_BD_RATE_CTRL 3 |
| 34 | 34 | ||
| 35 | enum wcn36xx_txbd_ssn_type { | ||
| 36 | WCN36XX_TXBD_SSN_FILL_HOST = 0, | ||
| 37 | WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS = 1, | ||
| 38 | WCN36XX_TXBD_SSN_FILL_DPU_QOS = 2, | ||
| 39 | }; | ||
| 40 | |||
| 35 | struct wcn36xx_pdu { | 41 | struct wcn36xx_pdu { |
| 36 | u32 dpu_fb:8; | 42 | u32 dpu_fb:8; |
| 37 | u32 adu_fb:8; | 43 | u32 adu_fb:8; |
| @@ -50,7 +56,8 @@ struct wcn36xx_pdu { | |||
| 50 | /* 0x0c*/ | 56 | /* 0x0c*/ |
| 51 | u32 reserved4:8; | 57 | u32 reserved4:8; |
| 52 | u32 tid:4; | 58 | u32 tid:4; |
| 53 | u32 reserved3:4; | 59 | u32 bd_ssn:2; |
| 60 | u32 reserved3:2; | ||
| 54 | u32 mpdu_len:16; | 61 | u32 mpdu_len:16; |
| 55 | }; | 62 | }; |
| 56 | 63 | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index f0fb81dfd17b..7b41e833e18c 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h | |||
| @@ -32,6 +32,9 @@ | |||
| 32 | #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" | 32 | #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" |
| 33 | #define WCN36XX_AGGR_BUFFER_SIZE 64 | 33 | #define WCN36XX_AGGR_BUFFER_SIZE 64 |
| 34 | 34 | ||
| 35 | /* How many frames until we start a-mpdu TX session */ | ||
| 36 | #define WCN36XX_AMPDU_START_THRESH 20 | ||
| 37 | |||
| 35 | extern unsigned int wcn36xx_dbg_mask; | 38 | extern unsigned int wcn36xx_dbg_mask; |
| 36 | 39 | ||
| 37 | enum wcn36xx_debug_mask { | 40 | enum wcn36xx_debug_mask { |
| @@ -74,6 +77,13 @@ enum wcn36xx_debug_mask { | |||
| 74 | buf, len, false); \ | 77 | buf, len, false); \ |
| 75 | } while (0) | 78 | } while (0) |
| 76 | 79 | ||
| 80 | enum wcn36xx_ampdu_state { | ||
| 81 | WCN36XX_AMPDU_NONE, | ||
| 82 | WCN36XX_AMPDU_INIT, | ||
| 83 | WCN36XX_AMPDU_START, | ||
| 84 | WCN36XX_AMPDU_OPERATIONAL, | ||
| 85 | }; | ||
| 86 | |||
| 77 | #define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value) | 87 | #define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value) |
| 78 | #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) | 88 | #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) |
| 79 | #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) | 89 | #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) |
| @@ -165,6 +175,10 @@ struct wcn36xx_sta { | |||
| 165 | bool is_data_encrypted; | 175 | bool is_data_encrypted; |
| 166 | /* Rates */ | 176 | /* Rates */ |
| 167 | struct wcn36xx_hal_supported_rates supported_rates; | 177 | struct wcn36xx_hal_supported_rates supported_rates; |
| 178 | |||
| 179 | spinlock_t ampdu_lock; /* protects next two fields */ | ||
| 180 | enum wcn36xx_ampdu_state ampdu_state[16]; | ||
| 181 | int non_agg_frame_ct; | ||
| 168 | }; | 182 | }; |
| 169 | struct wcn36xx_dxe_ch; | 183 | struct wcn36xx_dxe_ch; |
| 170 | struct wcn36xx { | 184 | struct wcn36xx { |
| @@ -243,4 +257,10 @@ static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn, | |||
| 243 | } | 257 | } |
| 244 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); | 258 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); |
| 245 | 259 | ||
| 260 | static inline | ||
| 261 | struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv) | ||
| 262 | { | ||
| 263 | return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv); | ||
| 264 | } | ||
| 265 | |||
| 246 | #endif /* _WCN36XX_H_ */ | 266 | #endif /* _WCN36XX_H_ */ |
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index 481680a3aa55..ce8c0381825e 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig | |||
| @@ -39,12 +39,3 @@ config WIL6210_TRACING | |||
| 39 | option if you are interested in debugging the driver. | 39 | option if you are interested in debugging the driver. |
| 40 | 40 | ||
| 41 | If unsure, say Y to make it easier to debug problems. | 41 | If unsure, say Y to make it easier to debug problems. |
| 42 | |||
| 43 | config WIL6210_PLATFORM_MSM | ||
| 44 | bool "wil6210 MSM platform specific support" | ||
| 45 | depends on WIL6210 | ||
| 46 | depends on ARCH_MSM | ||
| 47 | default y | ||
| 48 | ---help--- | ||
| 49 | Say Y here to enable wil6210 driver support for MSM | ||
| 50 | platform specific features | ||
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index 8ad4b5f97e04..caa717bf52f3 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile | |||
| @@ -14,7 +14,6 @@ wil6210-y += ioctl.o | |||
| 14 | wil6210-y += fw.o | 14 | wil6210-y += fw.o |
| 15 | wil6210-$(CONFIG_WIL6210_TRACING) += trace.o | 15 | wil6210-$(CONFIG_WIL6210_TRACING) += trace.o |
| 16 | wil6210-y += wil_platform.o | 16 | wil6210-y += wil_platform.o |
| 17 | wil6210-$(CONFIG_WIL6210_PLATFORM_MSM) += wil_platform_msm.o | ||
| 18 | wil6210-y += ethtool.o | 17 | wil6210-y += ethtool.o |
| 19 | 18 | ||
| 20 | # for tracing framework to find trace.h | 19 | # for tracing framework to find trace.h |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 38332a6dfb3a..2d5ea21be47e 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
| 3 | * | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -142,14 +142,14 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, | |||
| 142 | 142 | ||
| 143 | sinfo->generation = wil->sinfo_gen; | 143 | sinfo->generation = wil->sinfo_gen; |
| 144 | 144 | ||
| 145 | sinfo->filled = STATION_INFO_RX_BYTES | | 145 | sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | |
| 146 | STATION_INFO_TX_BYTES | | 146 | BIT(NL80211_STA_INFO_TX_BYTES) | |
| 147 | STATION_INFO_RX_PACKETS | | 147 | BIT(NL80211_STA_INFO_RX_PACKETS) | |
| 148 | STATION_INFO_TX_PACKETS | | 148 | BIT(NL80211_STA_INFO_TX_PACKETS) | |
| 149 | STATION_INFO_RX_BITRATE | | 149 | BIT(NL80211_STA_INFO_RX_BITRATE) | |
| 150 | STATION_INFO_TX_BITRATE | | 150 | BIT(NL80211_STA_INFO_TX_BITRATE) | |
| 151 | STATION_INFO_RX_DROP_MISC | | 151 | BIT(NL80211_STA_INFO_RX_DROP_MISC) | |
| 152 | STATION_INFO_TX_FAILED; | 152 | BIT(NL80211_STA_INFO_TX_FAILED); |
| 153 | 153 | ||
| 154 | sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | 154 | sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; |
| 155 | sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); | 155 | sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); |
| @@ -162,8 +162,8 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, | |||
| 162 | sinfo->tx_packets = stats->tx_packets; | 162 | sinfo->tx_packets = stats->tx_packets; |
| 163 | sinfo->tx_failed = stats->tx_errors; | 163 | sinfo->tx_failed = stats->tx_errors; |
| 164 | 164 | ||
| 165 | if (test_bit(wil_status_fwconnected, &wil->status)) { | 165 | if (test_bit(wil_status_fwconnected, wil->status)) { |
| 166 | sinfo->filled |= STATION_INFO_SIGNAL; | 166 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 167 | sinfo->signal = reply.evt.sqi; | 167 | sinfo->signal = reply.evt.sqi; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| @@ -282,7 +282,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, | |||
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | /* FW don't support scan after connection attempt */ | 284 | /* FW don't support scan after connection attempt */ |
| 285 | if (test_bit(wil_status_dontscan, &wil->status)) { | 285 | if (test_bit(wil_status_dontscan, wil->status)) { |
| 286 | wil_err(wil, "Can't scan now\n"); | 286 | wil_err(wil, "Can't scan now\n"); |
| 287 | return -EBUSY; | 287 | return -EBUSY; |
| 288 | } | 288 | } |
| @@ -334,6 +334,30 @@ out: | |||
| 334 | return rc; | 334 | return rc; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static void wil_print_crypto(struct wil6210_priv *wil, | ||
| 338 | struct cfg80211_crypto_settings *c) | ||
| 339 | { | ||
| 340 | int i, n; | ||
| 341 | |||
| 342 | wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n", | ||
| 343 | c->wpa_versions, c->cipher_group); | ||
| 344 | wil_dbg_misc(wil, "Pairwise ciphers [%d] {\n", c->n_ciphers_pairwise); | ||
| 345 | n = min_t(int, c->n_ciphers_pairwise, ARRAY_SIZE(c->ciphers_pairwise)); | ||
| 346 | for (i = 0; i < n; i++) | ||
| 347 | wil_dbg_misc(wil, " [%d] = 0x%08x\n", i, | ||
| 348 | c->ciphers_pairwise[i]); | ||
| 349 | wil_dbg_misc(wil, "}\n"); | ||
| 350 | wil_dbg_misc(wil, "AKM suites [%d] {\n", c->n_akm_suites); | ||
| 351 | n = min_t(int, c->n_akm_suites, ARRAY_SIZE(c->akm_suites)); | ||
| 352 | for (i = 0; i < n; i++) | ||
| 353 | wil_dbg_misc(wil, " [%d] = 0x%08x\n", i, | ||
| 354 | c->akm_suites[i]); | ||
| 355 | wil_dbg_misc(wil, "}\n"); | ||
| 356 | wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n", | ||
| 357 | c->control_port, be16_to_cpu(c->control_port_ethertype), | ||
| 358 | c->control_port_no_encrypt); | ||
| 359 | } | ||
| 360 | |||
| 337 | static void wil_print_connect_params(struct wil6210_priv *wil, | 361 | static void wil_print_connect_params(struct wil6210_priv *wil, |
| 338 | struct cfg80211_connect_params *sme) | 362 | struct cfg80211_connect_params *sme) |
| 339 | { | 363 | { |
| @@ -348,6 +372,7 @@ static void wil_print_connect_params(struct wil6210_priv *wil, | |||
| 348 | print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, | 372 | print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, |
| 349 | 16, 1, sme->ssid, sme->ssid_len, true); | 373 | 16, 1, sme->ssid, sme->ssid_len, true); |
| 350 | wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); | 374 | wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); |
| 375 | wil_print_crypto(wil, &sme->crypto); | ||
| 351 | } | 376 | } |
| 352 | 377 | ||
| 353 | static int wil_cfg80211_connect(struct wiphy *wiphy, | 378 | static int wil_cfg80211_connect(struct wiphy *wiphy, |
| @@ -362,8 +387,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 362 | int ch; | 387 | int ch; |
| 363 | int rc = 0; | 388 | int rc = 0; |
| 364 | 389 | ||
| 365 | if (test_bit(wil_status_fwconnecting, &wil->status) || | 390 | if (test_bit(wil_status_fwconnecting, wil->status) || |
| 366 | test_bit(wil_status_fwconnected, &wil->status)) | 391 | test_bit(wil_status_fwconnected, wil->status)) |
| 367 | return -EALREADY; | 392 | return -EALREADY; |
| 368 | 393 | ||
| 369 | wil_print_connect_params(wil, sme); | 394 | wil_print_connect_params(wil, sme); |
| @@ -450,15 +475,16 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 450 | memcpy(conn.bssid, bss->bssid, ETH_ALEN); | 475 | memcpy(conn.bssid, bss->bssid, ETH_ALEN); |
| 451 | memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); | 476 | memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); |
| 452 | 477 | ||
| 453 | set_bit(wil_status_fwconnecting, &wil->status); | 478 | set_bit(wil_status_fwconnecting, wil->status); |
| 454 | 479 | ||
| 455 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); | 480 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); |
| 456 | if (rc == 0) { | 481 | if (rc == 0) { |
| 482 | netif_carrier_on(ndev); | ||
| 457 | /* Connect can take lots of time */ | 483 | /* Connect can take lots of time */ |
| 458 | mod_timer(&wil->connect_timer, | 484 | mod_timer(&wil->connect_timer, |
| 459 | jiffies + msecs_to_jiffies(2000)); | 485 | jiffies + msecs_to_jiffies(2000)); |
| 460 | } else { | 486 | } else { |
| 461 | clear_bit(wil_status_fwconnecting, &wil->status); | 487 | clear_bit(wil_status_fwconnecting, wil->status); |
| 462 | } | 488 | } |
| 463 | 489 | ||
| 464 | out: | 490 | out: |
| @@ -618,18 +644,6 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) | |||
| 618 | b->assocresp_ies, b->assocresp_ies_len); | 644 | b->assocresp_ies, b->assocresp_ies_len); |
| 619 | } | 645 | } |
| 620 | 646 | ||
| 621 | static void wil_print_crypto(struct wil6210_priv *wil, | ||
| 622 | struct cfg80211_crypto_settings *c) | ||
| 623 | { | ||
| 624 | wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n", | ||
| 625 | c->wpa_versions, c->cipher_group); | ||
| 626 | wil_dbg_misc(wil, "Pairwise ciphers [%d]\n", c->n_ciphers_pairwise); | ||
| 627 | wil_dbg_misc(wil, "AKM suites [%d]\n", c->n_akm_suites); | ||
| 628 | wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n", | ||
| 629 | c->control_port, be16_to_cpu(c->control_port_ethertype), | ||
| 630 | c->control_port_no_encrypt); | ||
| 631 | } | ||
| 632 | |||
| 633 | static int wil_fix_bcon(struct wil6210_priv *wil, | 647 | static int wil_fix_bcon(struct wil6210_priv *wil, |
| 634 | struct cfg80211_beacon_data *bcon) | 648 | struct cfg80211_beacon_data *bcon) |
| 635 | { | 649 | { |
| @@ -757,12 +771,12 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
| 757 | 771 | ||
| 758 | wil->secure_pcp = info->privacy; | 772 | wil->secure_pcp = info->privacy; |
| 759 | 773 | ||
| 774 | netif_carrier_on(ndev); | ||
| 775 | |||
| 760 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, | 776 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, |
| 761 | channel->hw_value); | 777 | channel->hw_value); |
| 762 | if (rc) | 778 | if (rc) |
| 763 | goto out; | 779 | netif_carrier_off(ndev); |
| 764 | |||
| 765 | netif_carrier_on(ndev); | ||
| 766 | 780 | ||
| 767 | out: | 781 | out: |
| 768 | mutex_unlock(&wil->mutex); | 782 | mutex_unlock(&wil->mutex); |
| @@ -772,23 +786,26 @@ out: | |||
| 772 | static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | 786 | static int wil_cfg80211_stop_ap(struct wiphy *wiphy, |
| 773 | struct net_device *ndev) | 787 | struct net_device *ndev) |
| 774 | { | 788 | { |
| 775 | int rc, rc1; | ||
| 776 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 789 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| 777 | 790 | ||
| 778 | wil_dbg_misc(wil, "%s()\n", __func__); | 791 | wil_dbg_misc(wil, "%s()\n", __func__); |
| 779 | 792 | ||
| 793 | netif_carrier_off(ndev); | ||
| 780 | wil_set_recovery_state(wil, fw_recovery_idle); | 794 | wil_set_recovery_state(wil, fw_recovery_idle); |
| 781 | 795 | ||
| 782 | mutex_lock(&wil->mutex); | 796 | mutex_lock(&wil->mutex); |
| 783 | 797 | ||
| 784 | rc = wmi_pcp_stop(wil); | 798 | wmi_pcp_stop(wil); |
| 785 | 799 | ||
| 786 | __wil_down(wil); | 800 | __wil_down(wil); |
| 787 | rc1 = __wil_up(wil); | 801 | __wil_up(wil); |
| 788 | 802 | ||
| 789 | mutex_unlock(&wil->mutex); | 803 | mutex_unlock(&wil->mutex); |
| 790 | 804 | ||
| 791 | return min(rc, rc1); | 805 | /* some functions above might fail (e.g. __wil_up). Nevertheless, we |
| 806 | * return success because AP has stopped | ||
| 807 | */ | ||
| 808 | return 0; | ||
| 792 | } | 809 | } |
| 793 | 810 | ||
| 794 | static int wil_cfg80211_del_station(struct wiphy *wiphy, | 811 | static int wil_cfg80211_del_station(struct wiphy *wiphy, |
| @@ -804,6 +821,96 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, | |||
| 804 | return 0; | 821 | return 0; |
| 805 | } | 822 | } |
| 806 | 823 | ||
| 824 | /* probe_client handling */ | ||
| 825 | static void wil_probe_client_handle(struct wil6210_priv *wil, | ||
| 826 | struct wil_probe_client_req *req) | ||
| 827 | { | ||
| 828 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 829 | struct wil_sta_info *sta = &wil->sta[req->cid]; | ||
| 830 | /* assume STA is alive if it is still connected, | ||
| 831 | * else FW will disconnect it | ||
| 832 | */ | ||
| 833 | bool alive = (sta->status == wil_sta_connected); | ||
| 834 | |||
| 835 | cfg80211_probe_status(ndev, sta->addr, req->cookie, alive, GFP_KERNEL); | ||
| 836 | } | ||
| 837 | |||
| 838 | static struct list_head *next_probe_client(struct wil6210_priv *wil) | ||
| 839 | { | ||
| 840 | struct list_head *ret = NULL; | ||
| 841 | |||
| 842 | mutex_lock(&wil->probe_client_mutex); | ||
| 843 | |||
| 844 | if (!list_empty(&wil->probe_client_pending)) { | ||
| 845 | ret = wil->probe_client_pending.next; | ||
| 846 | list_del(ret); | ||
| 847 | } | ||
| 848 | |||
| 849 | mutex_unlock(&wil->probe_client_mutex); | ||
| 850 | |||
| 851 | return ret; | ||
| 852 | } | ||
| 853 | |||
| 854 | void wil_probe_client_worker(struct work_struct *work) | ||
| 855 | { | ||
| 856 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
| 857 | probe_client_worker); | ||
| 858 | struct wil_probe_client_req *req; | ||
| 859 | struct list_head *lh; | ||
| 860 | |||
| 861 | while ((lh = next_probe_client(wil)) != NULL) { | ||
| 862 | req = list_entry(lh, struct wil_probe_client_req, list); | ||
| 863 | |||
| 864 | wil_probe_client_handle(wil, req); | ||
| 865 | kfree(req); | ||
| 866 | } | ||
| 867 | } | ||
| 868 | |||
| 869 | void wil_probe_client_flush(struct wil6210_priv *wil) | ||
| 870 | { | ||
| 871 | struct wil_probe_client_req *req, *t; | ||
| 872 | |||
| 873 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
| 874 | |||
| 875 | mutex_lock(&wil->probe_client_mutex); | ||
| 876 | |||
| 877 | list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) { | ||
| 878 | list_del(&req->list); | ||
| 879 | kfree(req); | ||
| 880 | } | ||
| 881 | |||
| 882 | mutex_unlock(&wil->probe_client_mutex); | ||
| 883 | } | ||
| 884 | |||
| 885 | static int wil_cfg80211_probe_client(struct wiphy *wiphy, | ||
| 886 | struct net_device *dev, | ||
| 887 | const u8 *peer, u64 *cookie) | ||
| 888 | { | ||
| 889 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 890 | struct wil_probe_client_req *req; | ||
| 891 | int cid = wil_find_cid(wil, peer); | ||
| 892 | |||
| 893 | wil_dbg_misc(wil, "%s(%pM => CID %d)\n", __func__, peer, cid); | ||
| 894 | |||
| 895 | if (cid < 0) | ||
| 896 | return -ENOLINK; | ||
| 897 | |||
| 898 | req = kzalloc(sizeof(*req), GFP_KERNEL); | ||
| 899 | if (!req) | ||
| 900 | return -ENOMEM; | ||
| 901 | |||
| 902 | req->cid = cid; | ||
| 903 | req->cookie = cid; | ||
| 904 | |||
| 905 | mutex_lock(&wil->probe_client_mutex); | ||
| 906 | list_add_tail(&req->list, &wil->probe_client_pending); | ||
| 907 | mutex_unlock(&wil->probe_client_mutex); | ||
| 908 | |||
| 909 | *cookie = req->cookie; | ||
| 910 | queue_work(wil->wq_service, &wil->probe_client_worker); | ||
| 911 | return 0; | ||
| 912 | } | ||
| 913 | |||
| 807 | static struct cfg80211_ops wil_cfg80211_ops = { | 914 | static struct cfg80211_ops wil_cfg80211_ops = { |
| 808 | .scan = wil_cfg80211_scan, | 915 | .scan = wil_cfg80211_scan, |
| 809 | .connect = wil_cfg80211_connect, | 916 | .connect = wil_cfg80211_connect, |
| @@ -823,6 +930,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { | |||
| 823 | .start_ap = wil_cfg80211_start_ap, | 930 | .start_ap = wil_cfg80211_start_ap, |
| 824 | .stop_ap = wil_cfg80211_stop_ap, | 931 | .stop_ap = wil_cfg80211_stop_ap, |
| 825 | .del_station = wil_cfg80211_del_station, | 932 | .del_station = wil_cfg80211_del_station, |
| 933 | .probe_client = wil_cfg80211_probe_client, | ||
| 826 | }; | 934 | }; |
| 827 | 935 | ||
| 828 | static void wil_wiphy_init(struct wiphy *wiphy) | 936 | static void wil_wiphy_init(struct wiphy *wiphy) |
| @@ -854,6 +962,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) | |||
| 854 | wiphy->cipher_suites = wil_cipher_suites; | 962 | wiphy->cipher_suites = wil_cipher_suites; |
| 855 | wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); | 963 | wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); |
| 856 | wiphy->mgmt_stypes = wil_mgmt_stypes; | 964 | wiphy->mgmt_stypes = wil_mgmt_stypes; |
| 965 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS; | ||
| 857 | } | 966 | } |
| 858 | 967 | ||
| 859 | struct wireless_dev *wil_cfg80211_init(struct device *dev) | 968 | struct wireless_dev *wil_cfg80211_init(struct device *dev) |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index cd991fa1cc3f..45c3558ec804 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
| @@ -50,6 +50,7 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, | |||
| 50 | char _s, char _h) | 50 | char _s, char _h) |
| 51 | { | 51 | { |
| 52 | void __iomem *x = wmi_addr(wil, vring->hwtail); | 52 | void __iomem *x = wmi_addr(wil, vring->hwtail); |
| 53 | u32 v; | ||
| 53 | 54 | ||
| 54 | seq_printf(s, "VRING %s = {\n", name); | 55 | seq_printf(s, "VRING %s = {\n", name); |
| 55 | seq_printf(s, " pa = %pad\n", &vring->pa); | 56 | seq_printf(s, " pa = %pad\n", &vring->pa); |
| @@ -58,10 +59,12 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, | |||
| 58 | seq_printf(s, " swtail = %d\n", vring->swtail); | 59 | seq_printf(s, " swtail = %d\n", vring->swtail); |
| 59 | seq_printf(s, " swhead = %d\n", vring->swhead); | 60 | seq_printf(s, " swhead = %d\n", vring->swhead); |
| 60 | seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); | 61 | seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); |
| 61 | if (x) | 62 | if (x) { |
| 62 | seq_printf(s, "0x%08x\n", ioread32(x)); | 63 | v = ioread32(x); |
| 63 | else | 64 | seq_printf(s, "0x%08x = %d\n", v, v); |
| 65 | } else { | ||
| 64 | seq_puts(s, "???\n"); | 66 | seq_puts(s, "???\n"); |
| 67 | } | ||
| 65 | 68 | ||
| 66 | if (vring->va && (vring->size < 1025)) { | 69 | if (vring->va && (vring->size < 1025)) { |
| 67 | uint i; | 70 | uint i; |
| @@ -110,9 +113,12 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data) | |||
| 110 | 113 | ||
| 111 | snprintf(name, sizeof(name), "tx_%2d", i); | 114 | snprintf(name, sizeof(name), "tx_%2d", i); |
| 112 | 115 | ||
| 113 | seq_printf(s, "\n%pM CID %d TID %d [%3d|%3d] idle %3d%%\n", | 116 | seq_printf(s, |
| 114 | wil->sta[cid].addr, cid, tid, used, avail, | 117 | "\n%pM CID %d TID %d BACK([%d] %d TU A%s) [%3d|%3d] idle %3d%%\n", |
| 115 | (int)idle); | 118 | wil->sta[cid].addr, cid, tid, |
| 119 | txdata->agg_wsize, txdata->agg_timeout, | ||
| 120 | txdata->agg_amsdu ? "+" : "-", | ||
| 121 | used, avail, (int)idle); | ||
| 116 | 122 | ||
| 117 | wil_print_vring(s, wil, name, vring, '_', 'H'); | 123 | wil_print_vring(s, wil, name, vring, '_', 'H'); |
| 118 | } | 124 | } |
| @@ -384,24 +390,67 @@ static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, | |||
| 384 | return 0; | 390 | return 0; |
| 385 | } | 391 | } |
| 386 | 392 | ||
| 387 | static const struct dbg_off itr_cnt_off[] = { | 393 | static const struct dbg_off lgc_itr_cnt_off[] = { |
| 388 | {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, | 394 | {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, |
| 389 | {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, | 395 | {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, |
| 390 | {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, | 396 | {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, |
| 391 | {}, | 397 | {}, |
| 392 | }; | 398 | }; |
| 393 | 399 | ||
| 400 | static const struct dbg_off tx_itr_cnt_off[] = { | ||
| 401 | {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH), | ||
| 402 | doff_io32}, | ||
| 403 | {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA), | ||
| 404 | doff_io32}, | ||
| 405 | {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL), | ||
| 406 | doff_io32}, | ||
| 407 | {"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH), | ||
| 408 | doff_io32}, | ||
| 409 | {"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA), | ||
| 410 | doff_io32}, | ||
| 411 | {"IDL_CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_CTL), | ||
| 412 | doff_io32}, | ||
| 413 | {}, | ||
| 414 | }; | ||
| 415 | |||
| 416 | static const struct dbg_off rx_itr_cnt_off[] = { | ||
| 417 | {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH), | ||
| 418 | doff_io32}, | ||
| 419 | {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA), | ||
| 420 | doff_io32}, | ||
| 421 | {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL), | ||
| 422 | doff_io32}, | ||
| 423 | {"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH), | ||
| 424 | doff_io32}, | ||
| 425 | {"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA), | ||
| 426 | doff_io32}, | ||
| 427 | {"IDL_CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL), | ||
| 428 | doff_io32}, | ||
| 429 | {}, | ||
| 430 | }; | ||
| 431 | |||
| 394 | static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, | 432 | static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, |
| 395 | struct dentry *parent) | 433 | struct dentry *parent) |
| 396 | { | 434 | { |
| 397 | struct dentry *d = debugfs_create_dir("ITR_CNT", parent); | 435 | struct dentry *d, *dtx, *drx; |
| 398 | 436 | ||
| 437 | d = debugfs_create_dir("ITR_CNT", parent); | ||
| 399 | if (IS_ERR_OR_NULL(d)) | 438 | if (IS_ERR_OR_NULL(d)) |
| 400 | return -ENODEV; | 439 | return -ENODEV; |
| 401 | 440 | ||
| 441 | dtx = debugfs_create_dir("TX", d); | ||
| 442 | drx = debugfs_create_dir("RX", d); | ||
| 443 | if (IS_ERR_OR_NULL(dtx) || IS_ERR_OR_NULL(drx)) | ||
| 444 | return -ENODEV; | ||
| 445 | |||
| 402 | wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, | 446 | wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, |
| 403 | itr_cnt_off); | 447 | lgc_itr_cnt_off); |
| 448 | |||
| 449 | wil6210_debugfs_init_offset(wil, dtx, (void * __force)wil->csr, | ||
| 450 | tx_itr_cnt_off); | ||
| 404 | 451 | ||
| 452 | wil6210_debugfs_init_offset(wil, drx, (void * __force)wil->csr, | ||
| 453 | rx_itr_cnt_off); | ||
| 405 | return 0; | 454 | return 0; |
| 406 | } | 455 | } |
| 407 | 456 | ||
| @@ -558,6 +607,87 @@ static const struct file_operations fops_rxon = { | |||
| 558 | .open = simple_open, | 607 | .open = simple_open, |
| 559 | }; | 608 | }; |
| 560 | 609 | ||
| 610 | /* block ack control, write: | ||
| 611 | * - "add <ringid> <agg_size> <timeout>" to trigger ADDBA | ||
| 612 | * - "del_tx <ringid> <reason>" to trigger DELBA for Tx side | ||
| 613 | * - "del_rx <CID> <TID> <reason>" to trigger DELBA for Rx side | ||
| 614 | */ | ||
| 615 | static ssize_t wil_write_back(struct file *file, const char __user *buf, | ||
| 616 | size_t len, loff_t *ppos) | ||
| 617 | { | ||
| 618 | struct wil6210_priv *wil = file->private_data; | ||
| 619 | int rc; | ||
| 620 | char *kbuf = kmalloc(len + 1, GFP_KERNEL); | ||
| 621 | char cmd[8]; | ||
| 622 | int p1, p2, p3; | ||
| 623 | |||
| 624 | if (!kbuf) | ||
| 625 | return -ENOMEM; | ||
| 626 | |||
| 627 | rc = simple_write_to_buffer(kbuf, len, ppos, buf, len); | ||
| 628 | if (rc != len) { | ||
| 629 | kfree(kbuf); | ||
| 630 | return rc >= 0 ? -EIO : rc; | ||
| 631 | } | ||
| 632 | |||
| 633 | kbuf[len] = '\0'; | ||
| 634 | rc = sscanf(kbuf, "%8s %d %d %d", cmd, &p1, &p2, &p3); | ||
| 635 | kfree(kbuf); | ||
| 636 | |||
| 637 | if (rc < 0) | ||
| 638 | return rc; | ||
| 639 | if (rc < 2) | ||
| 640 | return -EINVAL; | ||
| 641 | |||
| 642 | if (0 == strcmp(cmd, "add")) { | ||
| 643 | if (rc < 3) { | ||
| 644 | wil_err(wil, "BACK: add require at least 2 params\n"); | ||
| 645 | return -EINVAL; | ||
| 646 | } | ||
| 647 | if (rc < 4) | ||
| 648 | p3 = 0; | ||
| 649 | wmi_addba(wil, p1, p2, p3); | ||
| 650 | } else if (0 == strcmp(cmd, "del_tx")) { | ||
| 651 | if (rc < 3) | ||
| 652 | p2 = WLAN_REASON_QSTA_LEAVE_QBSS; | ||
| 653 | wmi_delba_tx(wil, p1, p2); | ||
| 654 | } else if (0 == strcmp(cmd, "del_rx")) { | ||
| 655 | if (rc < 3) { | ||
| 656 | wil_err(wil, | ||
| 657 | "BACK: del_rx require at least 2 params\n"); | ||
| 658 | return -EINVAL; | ||
| 659 | } | ||
| 660 | if (rc < 4) | ||
| 661 | p3 = WLAN_REASON_QSTA_LEAVE_QBSS; | ||
| 662 | wmi_delba_rx(wil, mk_cidxtid(p1, p2), p3); | ||
| 663 | } else { | ||
| 664 | wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); | ||
| 665 | return -EINVAL; | ||
| 666 | } | ||
| 667 | |||
| 668 | return len; | ||
| 669 | } | ||
| 670 | |||
| 671 | static ssize_t wil_read_back(struct file *file, char __user *user_buf, | ||
| 672 | size_t count, loff_t *ppos) | ||
| 673 | { | ||
| 674 | static const char text[] = "block ack control, write:\n" | ||
| 675 | " - \"add <ringid> <agg_size> <timeout>\" to trigger ADDBA\n" | ||
| 676 | "If missing, <timeout> defaults to 0\n" | ||
| 677 | " - \"del_tx <ringid> <reason>\" to trigger DELBA for Tx side\n" | ||
| 678 | " - \"del_rx <CID> <TID> <reason>\" to trigger DELBA for Rx side\n" | ||
| 679 | "If missing, <reason> set to \"STA_LEAVING\" (36)\n"; | ||
| 680 | |||
| 681 | return simple_read_from_buffer(user_buf, count, ppos, text, | ||
| 682 | sizeof(text)); | ||
| 683 | } | ||
| 684 | |||
| 685 | static const struct file_operations fops_back = { | ||
| 686 | .read = wil_read_back, | ||
| 687 | .write = wil_write_back, | ||
| 688 | .open = simple_open, | ||
| 689 | }; | ||
| 690 | |||
| 561 | /*---tx_mgmt---*/ | 691 | /*---tx_mgmt---*/ |
| 562 | /* Write mgmt frame to this file to send it */ | 692 | /* Write mgmt frame to this file to send it */ |
| 563 | static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, | 693 | static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, |
| @@ -1116,7 +1246,8 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) | |||
| 1116 | int i; | 1246 | int i; |
| 1117 | u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; | 1247 | u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; |
| 1118 | 1248 | ||
| 1119 | seq_printf(s, "0x%03x [", r->head_seq_num); | 1249 | seq_printf(s, "([%2d] %3d TU) 0x%03x [", r->buf_size, r->timeout, |
| 1250 | r->head_seq_num); | ||
| 1120 | for (i = 0; i < r->buf_size; i++) { | 1251 | for (i = 0; i < r->buf_size; i++) { |
| 1121 | if (i == index) | 1252 | if (i == index) |
| 1122 | seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|'); | 1253 | seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|'); |
| @@ -1127,10 +1258,10 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) | |||
| 1127 | } | 1258 | } |
| 1128 | 1259 | ||
| 1129 | static int wil_sta_debugfs_show(struct seq_file *s, void *data) | 1260 | static int wil_sta_debugfs_show(struct seq_file *s, void *data) |
| 1261 | __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) | ||
| 1130 | { | 1262 | { |
| 1131 | struct wil6210_priv *wil = s->private; | 1263 | struct wil6210_priv *wil = s->private; |
| 1132 | int i, tid; | 1264 | int i, tid; |
| 1133 | unsigned long flags; | ||
| 1134 | 1265 | ||
| 1135 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1266 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { |
| 1136 | struct wil_sta_info *p = &wil->sta[i]; | 1267 | struct wil_sta_info *p = &wil->sta[i]; |
| @@ -1151,7 +1282,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) | |||
| 1151 | (p->data_port_open ? " data_port_open" : "")); | 1282 | (p->data_port_open ? " data_port_open" : "")); |
| 1152 | 1283 | ||
| 1153 | if (p->status == wil_sta_connected) { | 1284 | if (p->status == wil_sta_connected) { |
| 1154 | spin_lock_irqsave(&p->tid_rx_lock, flags); | 1285 | spin_lock_bh(&p->tid_rx_lock); |
| 1155 | for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { | 1286 | for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { |
| 1156 | struct wil_tid_ampdu_rx *r = p->tid_rx[tid]; | 1287 | struct wil_tid_ampdu_rx *r = p->tid_rx[tid]; |
| 1157 | 1288 | ||
| @@ -1160,7 +1291,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) | |||
| 1160 | wil_print_rxtid(s, r); | 1291 | wil_print_rxtid(s, r); |
| 1161 | } | 1292 | } |
| 1162 | } | 1293 | } |
| 1163 | spin_unlock_irqrestore(&p->tid_rx_lock, flags); | 1294 | spin_unlock_bh(&p->tid_rx_lock); |
| 1164 | } | 1295 | } |
| 1165 | } | 1296 | } |
| 1166 | 1297 | ||
| @@ -1217,6 +1348,7 @@ static const struct { | |||
| 1217 | {"rxon", S_IWUSR, &fops_rxon}, | 1348 | {"rxon", S_IWUSR, &fops_rxon}, |
| 1218 | {"tx_mgmt", S_IWUSR, &fops_txmgmt}, | 1349 | {"tx_mgmt", S_IWUSR, &fops_txmgmt}, |
| 1219 | {"wmi_send", S_IWUSR, &fops_wmi}, | 1350 | {"wmi_send", S_IWUSR, &fops_wmi}, |
| 1351 | {"back", S_IRUGO | S_IWUSR, &fops_back}, | ||
| 1220 | {"temp", S_IRUGO, &fops_temp}, | 1352 | {"temp", S_IRUGO, &fops_temp}, |
| 1221 | {"freq", S_IRUGO, &fops_freq}, | 1353 | {"freq", S_IRUGO, &fops_freq}, |
| 1222 | {"link", S_IRUGO, &fops_link}, | 1354 | {"link", S_IRUGO, &fops_link}, |
| @@ -1261,7 +1393,7 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, | |||
| 1261 | /* fields in struct wil6210_priv */ | 1393 | /* fields in struct wil6210_priv */ |
| 1262 | static const struct dbg_off dbg_wil_off[] = { | 1394 | static const struct dbg_off dbg_wil_off[] = { |
| 1263 | WIL_FIELD(secure_pcp, S_IRUGO | S_IWUSR, doff_u32), | 1395 | WIL_FIELD(secure_pcp, S_IRUGO | S_IWUSR, doff_u32), |
| 1264 | WIL_FIELD(status, S_IRUGO | S_IWUSR, doff_ulong), | 1396 | WIL_FIELD(status[0], S_IRUGO | S_IWUSR, doff_ulong), |
| 1265 | WIL_FIELD(fw_version, S_IRUGO, doff_u32), | 1397 | WIL_FIELD(fw_version, S_IRUGO, doff_u32), |
| 1266 | WIL_FIELD(hw_version, S_IRUGO, doff_x32), | 1398 | WIL_FIELD(hw_version, S_IRUGO, doff_x32), |
| 1267 | WIL_FIELD(recovery_count, S_IRUGO, doff_u32), | 1399 | WIL_FIELD(recovery_count, S_IRUGO, doff_u32), |
diff --git a/drivers/net/wireless/ath/wil6210/ethtool.c b/drivers/net/wireless/ath/wil6210/ethtool.c index d686638972be..4c44a82c34d7 100644 --- a/drivers/net/wireless/ath/wil6210/ethtool.c +++ b/drivers/net/wireless/ath/wil6210/ethtool.c | |||
| @@ -45,16 +45,35 @@ static int wil_ethtoolops_get_coalesce(struct net_device *ndev, | |||
| 45 | struct ethtool_coalesce *cp) | 45 | struct ethtool_coalesce *cp) |
| 46 | { | 46 | { |
| 47 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 47 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
| 48 | u32 itr_en, itr_val = 0; | 48 | u32 tx_itr_en, tx_itr_val = 0; |
| 49 | u32 rx_itr_en, rx_itr_val = 0; | ||
| 49 | 50 | ||
| 50 | wil_dbg_misc(wil, "%s()\n", __func__); | 51 | wil_dbg_misc(wil, "%s()\n", __func__); |
| 51 | 52 | ||
| 52 | itr_en = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); | 53 | if (test_bit(hw_capability_advanced_itr_moderation, |
| 53 | if (itr_en & BIT_DMA_ITR_CNT_CRL_EN) | 54 | wil->hw_capabilities)) { |
| 54 | itr_val = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); | 55 | tx_itr_en = ioread32(wil->csr + |
| 55 | 56 | HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL)); | |
| 56 | cp->rx_coalesce_usecs = itr_val; | 57 | if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN) |
| 58 | tx_itr_val = | ||
| 59 | ioread32(wil->csr + | ||
| 60 | HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH)); | ||
| 61 | |||
| 62 | rx_itr_en = ioread32(wil->csr + | ||
| 63 | HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL)); | ||
| 64 | if (rx_itr_en & BIT_DMA_ITR_RX_CNT_CTL_EN) | ||
| 65 | rx_itr_val = | ||
| 66 | ioread32(wil->csr + | ||
| 67 | HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH)); | ||
| 68 | } else { | ||
| 69 | rx_itr_en = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); | ||
| 70 | if (rx_itr_en & BIT_DMA_ITR_CNT_CRL_EN) | ||
| 71 | rx_itr_val = ioread32(wil->csr + | ||
| 72 | HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); | ||
| 73 | } | ||
| 57 | 74 | ||
| 75 | cp->tx_coalesce_usecs = tx_itr_val; | ||
| 76 | cp->rx_coalesce_usecs = rx_itr_val; | ||
| 58 | return 0; | 77 | return 0; |
| 59 | } | 78 | } |
| 60 | 79 | ||
| @@ -63,22 +82,25 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev, | |||
| 63 | { | 82 | { |
| 64 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 83 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
| 65 | 84 | ||
| 66 | wil_dbg_misc(wil, "%s(%d usec)\n", __func__, cp->rx_coalesce_usecs); | 85 | wil_dbg_misc(wil, "%s(rx %d usec, tx %d usec)\n", __func__, |
| 86 | cp->rx_coalesce_usecs, cp->tx_coalesce_usecs); | ||
| 67 | 87 | ||
| 68 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | 88 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { |
| 69 | wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n"); | 89 | wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n"); |
| 70 | return -EINVAL; | 90 | return -EINVAL; |
| 71 | } | 91 | } |
| 72 | 92 | ||
| 73 | /* only @rx_coalesce_usecs supported, ignore | 93 | /* only @rx_coalesce_usecs and @tx_coalesce_usecs supported, |
| 74 | * other parameters | 94 | * ignore other parameters |
| 75 | */ | 95 | */ |
| 76 | 96 | ||
| 77 | if (cp->rx_coalesce_usecs > WIL6210_ITR_TRSH_MAX) | 97 | if (cp->rx_coalesce_usecs > WIL6210_ITR_TRSH_MAX || |
| 98 | cp->tx_coalesce_usecs > WIL6210_ITR_TRSH_MAX) | ||
| 78 | goto out_bad; | 99 | goto out_bad; |
| 79 | 100 | ||
| 80 | wil->itr_trsh = cp->rx_coalesce_usecs; | 101 | wil->tx_max_burst_duration = cp->tx_coalesce_usecs; |
| 81 | wil_set_itr_trsh(wil); | 102 | wil->rx_max_burst_duration = cp->rx_coalesce_usecs; |
| 103 | wil_configure_interrupt_moderation(wil); | ||
| 82 | 104 | ||
| 83 | return 0; | 105 | return 0; |
| 84 | 106 | ||
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 4bcbd6297b3e..a6f923086f31 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
| @@ -102,7 +102,7 @@ static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) | |||
| 102 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | 102 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + |
| 103 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | 103 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); |
| 104 | 104 | ||
| 105 | clear_bit(wil_status_irqen, &wil->status); | 105 | clear_bit(wil_status_irqen, wil->status); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil) | 108 | void wil6210_unmask_irq_tx(struct wil6210_priv *wil) |
| @@ -130,7 +130,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) | |||
| 130 | { | 130 | { |
| 131 | wil_dbg_irq(wil, "%s()\n", __func__); | 131 | wil_dbg_irq(wil, "%s()\n", __func__); |
| 132 | 132 | ||
| 133 | set_bit(wil_status_irqen, &wil->status); | 133 | set_bit(wil_status_irqen, wil->status); |
| 134 | 134 | ||
| 135 | iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + | 135 | iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + |
| 136 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | 136 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); |
| @@ -157,15 +157,91 @@ void wil_unmask_irq(struct wil6210_priv *wil) | |||
| 157 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + | 157 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + |
| 158 | offsetof(struct RGF_ICR, ICC)); | 158 | offsetof(struct RGF_ICR, ICC)); |
| 159 | 159 | ||
| 160 | /* interrupt moderation parameters */ | ||
| 161 | wil_set_itr_trsh(wil); | ||
| 162 | |||
| 163 | wil6210_unmask_irq_pseudo(wil); | 160 | wil6210_unmask_irq_pseudo(wil); |
| 164 | wil6210_unmask_irq_tx(wil); | 161 | wil6210_unmask_irq_tx(wil); |
| 165 | wil6210_unmask_irq_rx(wil); | 162 | wil6210_unmask_irq_rx(wil); |
| 166 | wil6210_unmask_irq_misc(wil); | 163 | wil6210_unmask_irq_misc(wil); |
| 167 | } | 164 | } |
| 168 | 165 | ||
| 166 | /* target write operation */ | ||
| 167 | #define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0) | ||
| 168 | |||
| 169 | static | ||
| 170 | void wil_configure_interrupt_moderation_new(struct wil6210_priv *wil) | ||
| 171 | { | ||
| 172 | /* Disable and clear tx counter before (re)configuration */ | ||
| 173 | W(RGF_DMA_ITR_TX_CNT_CTL, BIT_DMA_ITR_TX_CNT_CTL_CLR); | ||
| 174 | W(RGF_DMA_ITR_TX_CNT_TRSH, wil->tx_max_burst_duration); | ||
| 175 | wil_info(wil, "set ITR_TX_CNT_TRSH = %d usec\n", | ||
| 176 | wil->tx_max_burst_duration); | ||
| 177 | /* Configure TX max burst duration timer to use usec units */ | ||
| 178 | W(RGF_DMA_ITR_TX_CNT_CTL, | ||
| 179 | BIT_DMA_ITR_TX_CNT_CTL_EN | BIT_DMA_ITR_TX_CNT_CTL_EXT_TIC_SEL); | ||
| 180 | |||
| 181 | /* Disable and clear tx idle counter before (re)configuration */ | ||
| 182 | W(RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_CLR); | ||
| 183 | W(RGF_DMA_ITR_TX_IDL_CNT_TRSH, wil->tx_interframe_timeout); | ||
| 184 | wil_info(wil, "set ITR_TX_IDL_CNT_TRSH = %d usec\n", | ||
| 185 | wil->tx_interframe_timeout); | ||
| 186 | /* Configure TX max burst duration timer to use usec units */ | ||
| 187 | W(RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_EN | | ||
| 188 | BIT_DMA_ITR_TX_IDL_CNT_CTL_EXT_TIC_SEL); | ||
| 189 | |||
| 190 | /* Disable and clear rx counter before (re)configuration */ | ||
| 191 | W(RGF_DMA_ITR_RX_CNT_CTL, BIT_DMA_ITR_RX_CNT_CTL_CLR); | ||
| 192 | W(RGF_DMA_ITR_RX_CNT_TRSH, wil->rx_max_burst_duration); | ||
| 193 | wil_info(wil, "set ITR_RX_CNT_TRSH = %d usec\n", | ||
| 194 | wil->rx_max_burst_duration); | ||
| 195 | /* Configure TX max burst duration timer to use usec units */ | ||
| 196 | W(RGF_DMA_ITR_RX_CNT_CTL, | ||
| 197 | BIT_DMA_ITR_RX_CNT_CTL_EN | BIT_DMA_ITR_RX_CNT_CTL_EXT_TIC_SEL); | ||
| 198 | |||
| 199 | /* Disable and clear rx idle counter before (re)configuration */ | ||
| 200 | W(RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR); | ||
| 201 | W(RGF_DMA_ITR_RX_IDL_CNT_TRSH, wil->rx_interframe_timeout); | ||
| 202 | wil_info(wil, "set ITR_RX_IDL_CNT_TRSH = %d usec\n", | ||
| 203 | wil->rx_interframe_timeout); | ||
| 204 | /* Configure TX max burst duration timer to use usec units */ | ||
| 205 | W(RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_EN | | ||
| 206 | BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL); | ||
| 207 | } | ||
| 208 | |||
| 209 | static | ||
| 210 | void wil_configure_interrupt_moderation_lgc(struct wil6210_priv *wil) | ||
| 211 | { | ||
| 212 | /* disable, use usec resolution */ | ||
| 213 | W(RGF_DMA_ITR_CNT_CRL, BIT_DMA_ITR_CNT_CRL_CLR); | ||
| 214 | |||
| 215 | wil_info(wil, "set ITR_TRSH = %d usec\n", wil->rx_max_burst_duration); | ||
| 216 | W(RGF_DMA_ITR_CNT_TRSH, wil->rx_max_burst_duration); | ||
| 217 | /* start it */ | ||
| 218 | W(RGF_DMA_ITR_CNT_CRL, | ||
| 219 | BIT_DMA_ITR_CNT_CRL_EN | BIT_DMA_ITR_CNT_CRL_EXT_TICK); | ||
| 220 | } | ||
| 221 | |||
| 222 | #undef W | ||
| 223 | |||
| 224 | void wil_configure_interrupt_moderation(struct wil6210_priv *wil) | ||
| 225 | { | ||
| 226 | wil_dbg_irq(wil, "%s()\n", __func__); | ||
| 227 | |||
| 228 | /* disable interrupt moderation for monitor | ||
| 229 | * to get better timestamp precision | ||
| 230 | */ | ||
| 231 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
| 232 | return; | ||
| 233 | |||
| 234 | if (test_bit(hw_capability_advanced_itr_moderation, | ||
| 235 | wil->hw_capabilities)) | ||
| 236 | wil_configure_interrupt_moderation_new(wil); | ||
| 237 | else { | ||
| 238 | /* Advanced interrupt moderation is not available before | ||
| 239 | * Sparrow v2. Will use legacy interrupt moderation | ||
| 240 | */ | ||
| 241 | wil_configure_interrupt_moderation_lgc(wil); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 169 | static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | 245 | static irqreturn_t wil6210_irq_rx(int irq, void *cookie) |
| 170 | { | 246 | { |
| 171 | struct wil6210_priv *wil = cookie; | 247 | struct wil6210_priv *wil = cookie; |
| @@ -194,18 +270,19 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | |||
| 194 | wil_dbg_irq(wil, "RX done\n"); | 270 | wil_dbg_irq(wil, "RX done\n"); |
| 195 | 271 | ||
| 196 | if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH) | 272 | if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH) |
| 197 | wil_err_ratelimited(wil, "Received \"Rx buffer is in risk " | 273 | wil_err_ratelimited(wil, |
| 198 | "of overflow\" interrupt\n"); | 274 | "Received \"Rx buffer is in risk of overflow\" interrupt\n"); |
| 199 | 275 | ||
| 200 | isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH); | 276 | isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | |
| 201 | if (test_bit(wil_status_reset_done, &wil->status)) { | 277 | BIT_DMA_EP_RX_ICR_RX_HTRSH); |
| 202 | if (test_bit(wil_status_napi_en, &wil->status)) { | 278 | if (test_bit(wil_status_reset_done, wil->status)) { |
| 279 | if (test_bit(wil_status_napi_en, wil->status)) { | ||
| 203 | wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); | 280 | wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); |
| 204 | need_unmask = false; | 281 | need_unmask = false; |
| 205 | napi_schedule(&wil->napi_rx); | 282 | napi_schedule(&wil->napi_rx); |
| 206 | } else { | 283 | } else { |
| 207 | wil_err(wil, "Got Rx interrupt while " | 284 | wil_err(wil, |
| 208 | "stopping interface\n"); | 285 | "Got Rx interrupt while stopping interface\n"); |
| 209 | } | 286 | } |
| 210 | } else { | 287 | } else { |
| 211 | wil_err(wil, "Got Rx interrupt while in reset\n"); | 288 | wil_err(wil, "Got Rx interrupt while in reset\n"); |
| @@ -248,7 +325,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | |||
| 248 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; | 325 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; |
| 249 | /* clear also all VRING interrupts */ | 326 | /* clear also all VRING interrupts */ |
| 250 | isr &= ~(BIT(25) - 1UL); | 327 | isr &= ~(BIT(25) - 1UL); |
| 251 | if (test_bit(wil_status_reset_done, &wil->status)) { | 328 | if (test_bit(wil_status_reset_done, wil->status)) { |
| 252 | wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); | 329 | wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); |
| 253 | need_unmask = false; | 330 | need_unmask = false; |
| 254 | napi_schedule(&wil->napi_tx); | 331 | napi_schedule(&wil->napi_tx); |
| @@ -310,7 +387,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | |||
| 310 | 387 | ||
| 311 | if (isr & ISR_MISC_FW_ERROR) { | 388 | if (isr & ISR_MISC_FW_ERROR) { |
| 312 | wil_err(wil, "Firmware error detected\n"); | 389 | wil_err(wil, "Firmware error detected\n"); |
| 313 | clear_bit(wil_status_fwready, &wil->status); | 390 | clear_bit(wil_status_fwready, wil->status); |
| 314 | /* | 391 | /* |
| 315 | * do not clear @isr here - we do 2-nd part in thread | 392 | * do not clear @isr here - we do 2-nd part in thread |
| 316 | * there, user space get notified, and it should be done | 393 | * there, user space get notified, and it should be done |
| @@ -321,7 +398,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | |||
| 321 | if (isr & ISR_MISC_FW_READY) { | 398 | if (isr & ISR_MISC_FW_READY) { |
| 322 | wil_dbg_irq(wil, "IRQ: FW ready\n"); | 399 | wil_dbg_irq(wil, "IRQ: FW ready\n"); |
| 323 | wil_cache_mbox_regs(wil); | 400 | wil_cache_mbox_regs(wil); |
| 324 | set_bit(wil_status_reset_done, &wil->status); | 401 | set_bit(wil_status_reset_done, wil->status); |
| 325 | /** | 402 | /** |
| 326 | * Actual FW ready indicated by the | 403 | * Actual FW ready indicated by the |
| 327 | * WMI_FW_READY_EVENTID | 404 | * WMI_FW_READY_EVENTID |
| @@ -394,7 +471,7 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie) | |||
| 394 | */ | 471 | */ |
| 395 | static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) | 472 | static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) |
| 396 | { | 473 | { |
| 397 | if (!test_bit(wil_status_irqen, &wil->status)) { | 474 | if (!test_bit(wil_status_irqen, wil->status)) { |
| 398 | u32 icm_rx = wil_ioread32_and_clear(wil->csr + | 475 | u32 icm_rx = wil_ioread32_and_clear(wil->csr + |
| 399 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | 476 | HOSTADDR(RGF_DMA_EP_RX_ICR) + |
| 400 | offsetof(struct RGF_ICR, ICM)); | 477 | offsetof(struct RGF_ICR, ICM)); |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 8ff3fe34fe05..b04e0afdcb21 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
| 3 | * | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -33,15 +33,18 @@ static bool no_fw_load = true; | |||
| 33 | module_param(no_fw_load, bool, S_IRUGO | S_IWUSR); | 33 | module_param(no_fw_load, bool, S_IRUGO | S_IWUSR); |
| 34 | MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash."); | 34 | MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash."); |
| 35 | 35 | ||
| 36 | static unsigned int itr_trsh = WIL6210_ITR_TRSH_DEFAULT; | 36 | /* if not set via modparam, will be set to default value of 1/8 of |
| 37 | 37 | * rx ring size during init flow | |
| 38 | module_param(itr_trsh, uint, S_IRUGO); | 38 | */ |
| 39 | MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs."); | 39 | unsigned short rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_INIT; |
| 40 | module_param(rx_ring_overflow_thrsh, ushort, S_IRUGO); | ||
| 41 | MODULE_PARM_DESC(rx_ring_overflow_thrsh, | ||
| 42 | " RX ring overflow threshold in descriptors."); | ||
| 40 | 43 | ||
| 41 | /* We allow allocation of more than 1 page buffers to support large packets. | 44 | /* We allow allocation of more than 1 page buffers to support large packets. |
| 42 | * It is suboptimal behavior performance wise in case MTU above page size. | 45 | * It is suboptimal behavior performance wise in case MTU above page size. |
| 43 | */ | 46 | */ |
| 44 | unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - ETH_HLEN; | 47 | unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - WIL_MAX_MPDU_OVERHEAD; |
| 45 | static int mtu_max_set(const char *val, const struct kernel_param *kp) | 48 | static int mtu_max_set(const char *val, const struct kernel_param *kp) |
| 46 | { | 49 | { |
| 47 | int ret; | 50 | int ret; |
| @@ -53,7 +56,7 @@ static int mtu_max_set(const char *val, const struct kernel_param *kp) | |||
| 53 | if (ret) | 56 | if (ret) |
| 54 | return ret; | 57 | return ret; |
| 55 | 58 | ||
| 56 | if (mtu_max < 68 || mtu_max > IEEE80211_MAX_DATA_LEN_DMG) | 59 | if (mtu_max < 68 || mtu_max > WIL_MAX_ETH_MTU) |
| 57 | ret = -EINVAL; | 60 | ret = -EINVAL; |
| 58 | 61 | ||
| 59 | return ret; | 62 | return ret; |
| @@ -135,12 +138,14 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | |||
| 135 | 138 | ||
| 136 | static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, | 139 | static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, |
| 137 | u16 reason_code, bool from_event) | 140 | u16 reason_code, bool from_event) |
| 141 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | ||
| 138 | { | 142 | { |
| 139 | uint i; | 143 | uint i; |
| 140 | struct net_device *ndev = wil_to_ndev(wil); | 144 | struct net_device *ndev = wil_to_ndev(wil); |
| 141 | struct wireless_dev *wdev = wil->wdev; | 145 | struct wireless_dev *wdev = wil->wdev; |
| 142 | struct wil_sta_info *sta = &wil->sta[cid]; | 146 | struct wil_sta_info *sta = &wil->sta[cid]; |
| 143 | 147 | ||
| 148 | might_sleep(); | ||
| 144 | wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid, | 149 | wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid, |
| 145 | sta->status); | 150 | sta->status); |
| 146 | 151 | ||
| @@ -163,15 +168,14 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, | |||
| 163 | 168 | ||
| 164 | for (i = 0; i < WIL_STA_TID_NUM; i++) { | 169 | for (i = 0; i < WIL_STA_TID_NUM; i++) { |
| 165 | struct wil_tid_ampdu_rx *r; | 170 | struct wil_tid_ampdu_rx *r; |
| 166 | unsigned long flags; | ||
| 167 | 171 | ||
| 168 | spin_lock_irqsave(&sta->tid_rx_lock, flags); | 172 | spin_lock_bh(&sta->tid_rx_lock); |
| 169 | 173 | ||
| 170 | r = sta->tid_rx[i]; | 174 | r = sta->tid_rx[i]; |
| 171 | sta->tid_rx[i] = NULL; | 175 | sta->tid_rx[i] = NULL; |
| 172 | wil_tid_ampdu_rx_free(wil, r); | 176 | wil_tid_ampdu_rx_free(wil, r); |
| 173 | 177 | ||
| 174 | spin_unlock_irqrestore(&sta->tid_rx_lock, flags); | 178 | spin_unlock_bh(&sta->tid_rx_lock); |
| 175 | } | 179 | } |
| 176 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { | 180 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { |
| 177 | if (wil->vring2cid_tid[i][0] == cid) | 181 | if (wil->vring2cid_tid[i][0] == cid) |
| @@ -188,34 +192,47 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
| 188 | struct wireless_dev *wdev = wil->wdev; | 192 | struct wireless_dev *wdev = wil->wdev; |
| 189 | 193 | ||
| 190 | might_sleep(); | 194 | might_sleep(); |
| 191 | if (bssid) { | 195 | wil_dbg_misc(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, |
| 196 | reason_code, from_event ? "+" : "-"); | ||
| 197 | |||
| 198 | /* Cases are: | ||
| 199 | * - disconnect single STA, still connected | ||
| 200 | * - disconnect single STA, already disconnected | ||
| 201 | * - disconnect all | ||
| 202 | * | ||
| 203 | * For "disconnect all", there are 2 options: | ||
| 204 | * - bssid == NULL | ||
| 205 | * - bssid is our MAC address | ||
| 206 | */ | ||
| 207 | if (bssid && memcmp(ndev->dev_addr, bssid, ETH_ALEN)) { | ||
| 192 | cid = wil_find_cid(wil, bssid); | 208 | cid = wil_find_cid(wil, bssid); |
| 193 | wil_dbg_misc(wil, "%s(%pM, CID %d)\n", __func__, bssid, cid); | 209 | wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", |
| 194 | } else { | 210 | bssid, cid, reason_code); |
| 195 | wil_dbg_misc(wil, "%s(all)\n", __func__); | 211 | if (cid >= 0) /* disconnect 1 peer */ |
| 196 | } | 212 | wil_disconnect_cid(wil, cid, reason_code, from_event); |
| 197 | 213 | } else { /* all */ | |
| 198 | if (cid >= 0) /* disconnect 1 peer */ | 214 | wil_dbg_misc(wil, "Disconnect all\n"); |
| 199 | wil_disconnect_cid(wil, cid, reason_code, from_event); | ||
| 200 | else /* disconnect all */ | ||
| 201 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) | 215 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) |
| 202 | wil_disconnect_cid(wil, cid, reason_code, from_event); | 216 | wil_disconnect_cid(wil, cid, reason_code, from_event); |
| 217 | } | ||
| 203 | 218 | ||
| 204 | /* link state */ | 219 | /* link state */ |
| 205 | switch (wdev->iftype) { | 220 | switch (wdev->iftype) { |
| 206 | case NL80211_IFTYPE_STATION: | 221 | case NL80211_IFTYPE_STATION: |
| 207 | case NL80211_IFTYPE_P2P_CLIENT: | 222 | case NL80211_IFTYPE_P2P_CLIENT: |
| 208 | wil_link_off(wil); | 223 | netif_tx_stop_all_queues(ndev); |
| 209 | if (test_bit(wil_status_fwconnected, &wil->status)) { | 224 | netif_carrier_off(ndev); |
| 210 | clear_bit(wil_status_fwconnected, &wil->status); | 225 | |
| 226 | if (test_bit(wil_status_fwconnected, wil->status)) { | ||
| 227 | clear_bit(wil_status_fwconnected, wil->status); | ||
| 211 | cfg80211_disconnected(ndev, reason_code, | 228 | cfg80211_disconnected(ndev, reason_code, |
| 212 | NULL, 0, GFP_KERNEL); | 229 | NULL, 0, GFP_KERNEL); |
| 213 | } else if (test_bit(wil_status_fwconnecting, &wil->status)) { | 230 | } else if (test_bit(wil_status_fwconnecting, wil->status)) { |
| 214 | cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, | 231 | cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, |
| 215 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 232 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
| 216 | GFP_KERNEL); | 233 | GFP_KERNEL); |
| 217 | } | 234 | } |
| 218 | clear_bit(wil_status_fwconnecting, &wil->status); | 235 | clear_bit(wil_status_fwconnecting, wil->status); |
| 219 | break; | 236 | break; |
| 220 | default: | 237 | default: |
| 221 | break; | 238 | break; |
| @@ -248,7 +265,7 @@ static void wil_scan_timer_fn(ulong x) | |||
| 248 | { | 265 | { |
| 249 | struct wil6210_priv *wil = (void *)x; | 266 | struct wil6210_priv *wil = (void *)x; |
| 250 | 267 | ||
| 251 | clear_bit(wil_status_fwready, &wil->status); | 268 | clear_bit(wil_status_fwready, wil->status); |
| 252 | wil_err(wil, "Scan timeout detected, start fw error recovery\n"); | 269 | wil_err(wil, "Scan timeout detected, start fw error recovery\n"); |
| 253 | wil->recovery_state = fw_recovery_pending; | 270 | wil->recovery_state = fw_recovery_pending; |
| 254 | schedule_work(&wil->fw_error_worker); | 271 | schedule_work(&wil->fw_error_worker); |
| @@ -352,6 +369,8 @@ static void wil_connect_worker(struct work_struct *work) | |||
| 352 | int rc; | 369 | int rc; |
| 353 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | 370 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, |
| 354 | connect_worker); | 371 | connect_worker); |
| 372 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 373 | |||
| 355 | int cid = wil->pending_connect_cid; | 374 | int cid = wil->pending_connect_cid; |
| 356 | int ringid = wil_find_free_vring(wil); | 375 | int ringid = wil_find_free_vring(wil); |
| 357 | 376 | ||
| @@ -366,7 +385,7 @@ static void wil_connect_worker(struct work_struct *work) | |||
| 366 | wil->pending_connect_cid = -1; | 385 | wil->pending_connect_cid = -1; |
| 367 | if (rc == 0) { | 386 | if (rc == 0) { |
| 368 | wil->sta[cid].status = wil_sta_connected; | 387 | wil->sta[cid].status = wil_sta_connected; |
| 369 | wil_link_on(wil); | 388 | netif_tx_wake_all_queues(ndev); |
| 370 | } else { | 389 | } else { |
| 371 | wil->sta[cid].status = wil_sta_unused; | 390 | wil->sta[cid].status = wil_sta_unused; |
| 372 | } | 391 | } |
| @@ -384,6 +403,9 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
| 384 | 403 | ||
| 385 | mutex_init(&wil->mutex); | 404 | mutex_init(&wil->mutex); |
| 386 | mutex_init(&wil->wmi_mutex); | 405 | mutex_init(&wil->wmi_mutex); |
| 406 | mutex_init(&wil->back_rx_mutex); | ||
| 407 | mutex_init(&wil->back_tx_mutex); | ||
| 408 | mutex_init(&wil->probe_client_mutex); | ||
| 387 | 409 | ||
| 388 | init_completion(&wil->wmi_ready); | 410 | init_completion(&wil->wmi_ready); |
| 389 | init_completion(&wil->wmi_call); | 411 | init_completion(&wil->wmi_call); |
| @@ -396,25 +418,39 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
| 396 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | 418 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); |
| 397 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | 419 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); |
| 398 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); | 420 | INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); |
| 421 | INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker); | ||
| 422 | INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker); | ||
| 423 | INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); | ||
| 399 | 424 | ||
| 400 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | 425 | INIT_LIST_HEAD(&wil->pending_wmi_ev); |
| 426 | INIT_LIST_HEAD(&wil->back_rx_pending); | ||
| 427 | INIT_LIST_HEAD(&wil->back_tx_pending); | ||
| 428 | INIT_LIST_HEAD(&wil->probe_client_pending); | ||
| 401 | spin_lock_init(&wil->wmi_ev_lock); | 429 | spin_lock_init(&wil->wmi_ev_lock); |
| 402 | init_waitqueue_head(&wil->wq); | 430 | init_waitqueue_head(&wil->wq); |
| 403 | 431 | ||
| 404 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); | 432 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); |
| 405 | if (!wil->wmi_wq) | 433 | if (!wil->wmi_wq) |
| 406 | return -EAGAIN; | 434 | return -EAGAIN; |
| 407 | 435 | ||
| 408 | wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); | 436 | wil->wq_service = create_singlethread_workqueue(WIL_NAME "_service"); |
| 409 | if (!wil->wmi_wq_conn) { | 437 | if (!wil->wq_service) |
| 410 | destroy_workqueue(wil->wmi_wq); | 438 | goto out_wmi_wq; |
| 411 | return -EAGAIN; | ||
| 412 | } | ||
| 413 | 439 | ||
| 414 | wil->last_fw_recovery = jiffies; | 440 | wil->last_fw_recovery = jiffies; |
| 415 | wil->itr_trsh = itr_trsh; | 441 | wil->tx_interframe_timeout = WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT; |
| 442 | wil->rx_interframe_timeout = WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT; | ||
| 443 | wil->tx_max_burst_duration = WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT; | ||
| 444 | wil->rx_max_burst_duration = WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT; | ||
| 416 | 445 | ||
| 446 | if (rx_ring_overflow_thrsh == WIL6210_RX_HIGH_TRSH_INIT) | ||
| 447 | rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_DEFAULT; | ||
| 417 | return 0; | 448 | return 0; |
| 449 | |||
| 450 | out_wmi_wq: | ||
| 451 | destroy_workqueue(wil->wmi_wq); | ||
| 452 | |||
| 453 | return -EAGAIN; | ||
| 418 | } | 454 | } |
| 419 | 455 | ||
| 420 | /** | 456 | /** |
| @@ -448,7 +484,13 @@ void wil_priv_deinit(struct wil6210_priv *wil) | |||
| 448 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | 484 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); |
| 449 | mutex_unlock(&wil->mutex); | 485 | mutex_unlock(&wil->mutex); |
| 450 | wmi_event_flush(wil); | 486 | wmi_event_flush(wil); |
| 451 | destroy_workqueue(wil->wmi_wq_conn); | 487 | wil_back_rx_flush(wil); |
| 488 | cancel_work_sync(&wil->back_rx_worker); | ||
| 489 | wil_back_tx_flush(wil); | ||
| 490 | cancel_work_sync(&wil->back_tx_worker); | ||
| 491 | wil_probe_client_flush(wil); | ||
| 492 | cancel_work_sync(&wil->probe_client_worker); | ||
| 493 | destroy_workqueue(wil->wq_service); | ||
| 452 | destroy_workqueue(wil->wmi_wq); | 494 | destroy_workqueue(wil->wmi_wq); |
| 453 | } | 495 | } |
| 454 | 496 | ||
| @@ -478,13 +520,10 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
| 478 | { | 520 | { |
| 479 | int delay = 0; | 521 | int delay = 0; |
| 480 | u32 x; | 522 | u32 x; |
| 481 | u32 rev_id; | 523 | bool is_reset_v2 = test_bit(hw_capability_reset_v2, |
| 482 | bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW); | 524 | wil->hw_capabilities); |
| 483 | 525 | ||
| 484 | wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name); | 526 | wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name); |
| 485 | |||
| 486 | wil->hw_version = R(RGF_USER_FW_REV_ID); | ||
| 487 | rev_id = wil->hw_version & 0xff; | ||
| 488 | 527 | ||
| 489 | /* Clear MAC link up */ | 528 | /* Clear MAC link up */ |
| 490 | S(RGF_HP_CTRL, BIT(15)); | 529 | S(RGF_HP_CTRL, BIT(15)); |
| @@ -496,7 +535,7 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
| 496 | /* Clear Fw Download notification */ | 535 | /* Clear Fw Download notification */ |
| 497 | C(RGF_USER_USAGE_6, BIT(0)); | 536 | C(RGF_USER_USAGE_6, BIT(0)); |
| 498 | 537 | ||
| 499 | if (is_sparrow) { | 538 | if (is_reset_v2) { |
| 500 | S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN); | 539 | S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN); |
| 501 | /* XTAL stabilization should take about 3ms */ | 540 | /* XTAL stabilization should take about 3ms */ |
| 502 | usleep_range(5000, 7000); | 541 | usleep_range(5000, 7000); |
| @@ -517,10 +556,11 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
| 517 | 556 | ||
| 518 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | 557 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); |
| 519 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | 558 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); |
| 520 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000f0 : 0x00000170); | 559 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, |
| 560 | is_reset_v2 ? 0x000000f0 : 0x00000170); | ||
| 521 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00); | 561 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00); |
| 522 | 562 | ||
| 523 | if (is_sparrow) { | 563 | if (is_reset_v2) { |
| 524 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0); | 564 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0); |
| 525 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0); | 565 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0); |
| 526 | } | 566 | } |
| @@ -530,19 +570,14 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
| 530 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | 570 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); |
| 531 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | 571 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); |
| 532 | 572 | ||
| 533 | if (is_sparrow) { | 573 | if (is_reset_v2) { |
| 534 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003); | 574 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003); |
| 535 | /* reset A2 PCIE AHB */ | 575 | /* reset A2 PCIE AHB */ |
| 536 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); | 576 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); |
| 537 | } else { | 577 | } else { |
| 538 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); | 578 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); |
| 539 | if (rev_id == 1) { | 579 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8)); |
| 540 | /* reset A1 BOTH PCIE AHB & PCIE RGF */ | 580 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); |
| 541 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | ||
| 542 | } else { | ||
| 543 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8)); | ||
| 544 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); | ||
| 545 | } | ||
| 546 | } | 581 | } |
| 547 | 582 | ||
| 548 | /* TODO: check order here!!! Erez code is different */ | 583 | /* TODO: check order here!!! Erez code is different */ |
| @@ -559,8 +594,7 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
| 559 | } | 594 | } |
| 560 | } while (x != HW_MACHINE_BOOT_DONE); | 595 | } while (x != HW_MACHINE_BOOT_DONE); |
| 561 | 596 | ||
| 562 | /* TODO: Erez check rev_id != 1 */ | 597 | if (!is_reset_v2) |
| 563 | if (!is_sparrow && (rev_id != 1)) | ||
| 564 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8)); | 598 | W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8)); |
| 565 | 599 | ||
| 566 | C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); | 600 | C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); |
| @@ -569,26 +603,6 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
| 569 | return 0; | 603 | return 0; |
| 570 | } | 604 | } |
| 571 | 605 | ||
| 572 | /** | ||
| 573 | * wil_set_itr_trsh: - apply interrupt coalescing params | ||
| 574 | */ | ||
| 575 | void wil_set_itr_trsh(struct wil6210_priv *wil) | ||
| 576 | { | ||
| 577 | /* disable, use usec resolution */ | ||
| 578 | W(RGF_DMA_ITR_CNT_CRL, BIT_DMA_ITR_CNT_CRL_EXT_TICK); | ||
| 579 | |||
| 580 | /* disable interrupt moderation for monitor | ||
| 581 | * to get better timestamp precision | ||
| 582 | */ | ||
| 583 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
| 584 | return; | ||
| 585 | |||
| 586 | wil_info(wil, "set ITR_TRSH = %d usec\n", wil->itr_trsh); | ||
| 587 | W(RGF_DMA_ITR_CNT_TRSH, wil->itr_trsh); | ||
| 588 | W(RGF_DMA_ITR_CNT_CRL, BIT_DMA_ITR_CNT_CRL_EN | | ||
| 589 | BIT_DMA_ITR_CNT_CRL_EXT_TICK); /* start it */ | ||
| 590 | } | ||
| 591 | |||
| 592 | #undef R | 606 | #undef R |
| 593 | #undef W | 607 | #undef W |
| 594 | #undef S | 608 | #undef S |
| @@ -629,13 +643,17 @@ int wil_reset(struct wil6210_priv *wil) | |||
| 629 | 643 | ||
| 630 | wil_dbg_misc(wil, "%s()\n", __func__); | 644 | wil_dbg_misc(wil, "%s()\n", __func__); |
| 631 | 645 | ||
| 646 | if (wil->hw_version == HW_VER_UNKNOWN) | ||
| 647 | return -ENODEV; | ||
| 648 | |||
| 632 | WARN_ON(!mutex_is_locked(&wil->mutex)); | 649 | WARN_ON(!mutex_is_locked(&wil->mutex)); |
| 633 | WARN_ON(test_bit(wil_status_napi_en, &wil->status)); | 650 | WARN_ON(test_bit(wil_status_napi_en, wil->status)); |
| 634 | 651 | ||
| 635 | cancel_work_sync(&wil->disconnect_worker); | 652 | cancel_work_sync(&wil->disconnect_worker); |
| 636 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | 653 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); |
| 637 | 654 | ||
| 638 | wil->status = 0; /* prevent NAPI from being scheduled */ | 655 | /* prevent NAPI from being scheduled */ |
| 656 | bitmap_zero(wil->status, wil_status_last); | ||
| 639 | 657 | ||
| 640 | if (wil->scan_request) { | 658 | if (wil->scan_request) { |
| 641 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", | 659 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", |
| @@ -649,7 +667,7 @@ int wil_reset(struct wil6210_priv *wil) | |||
| 649 | 667 | ||
| 650 | wmi_event_flush(wil); | 668 | wmi_event_flush(wil); |
| 651 | 669 | ||
| 652 | flush_workqueue(wil->wmi_wq_conn); | 670 | flush_workqueue(wil->wq_service); |
| 653 | flush_workqueue(wil->wmi_wq); | 671 | flush_workqueue(wil->wmi_wq); |
| 654 | 672 | ||
| 655 | rc = wil_target_reset(wil); | 673 | rc = wil_target_reset(wil); |
| @@ -688,6 +706,7 @@ int wil_reset(struct wil6210_priv *wil) | |||
| 688 | reinit_completion(&wil->wmi_ready); | 706 | reinit_completion(&wil->wmi_ready); |
| 689 | reinit_completion(&wil->wmi_call); | 707 | reinit_completion(&wil->wmi_call); |
| 690 | 708 | ||
| 709 | wil_configure_interrupt_moderation(wil); | ||
| 691 | wil_unmask_irq(wil); | 710 | wil_unmask_irq(wil); |
| 692 | 711 | ||
| 693 | /* we just started MAC, wait for FW ready */ | 712 | /* we just started MAC, wait for FW ready */ |
| @@ -703,28 +722,6 @@ void wil_fw_error_recovery(struct wil6210_priv *wil) | |||
| 703 | schedule_work(&wil->fw_error_worker); | 722 | schedule_work(&wil->fw_error_worker); |
| 704 | } | 723 | } |
| 705 | 724 | ||
| 706 | void wil_link_on(struct wil6210_priv *wil) | ||
| 707 | { | ||
| 708 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 709 | |||
| 710 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
| 711 | |||
| 712 | netif_carrier_on(ndev); | ||
| 713 | wil_dbg_misc(wil, "netif_tx_wake : link on\n"); | ||
| 714 | netif_tx_wake_all_queues(ndev); | ||
| 715 | } | ||
| 716 | |||
| 717 | void wil_link_off(struct wil6210_priv *wil) | ||
| 718 | { | ||
| 719 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 720 | |||
| 721 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
| 722 | |||
| 723 | netif_tx_stop_all_queues(ndev); | ||
| 724 | wil_dbg_misc(wil, "netif_tx_stop : link off\n"); | ||
| 725 | netif_carrier_off(ndev); | ||
| 726 | } | ||
| 727 | |||
| 728 | int __wil_up(struct wil6210_priv *wil) | 725 | int __wil_up(struct wil6210_priv *wil) |
| 729 | { | 726 | { |
| 730 | struct net_device *ndev = wil_to_ndev(wil); | 727 | struct net_device *ndev = wil_to_ndev(wil); |
| @@ -774,7 +771,7 @@ int __wil_up(struct wil6210_priv *wil) | |||
| 774 | wil_dbg_misc(wil, "NAPI enable\n"); | 771 | wil_dbg_misc(wil, "NAPI enable\n"); |
| 775 | napi_enable(&wil->napi_rx); | 772 | napi_enable(&wil->napi_rx); |
| 776 | napi_enable(&wil->napi_tx); | 773 | napi_enable(&wil->napi_tx); |
| 777 | set_bit(wil_status_napi_en, &wil->status); | 774 | set_bit(wil_status_napi_en, wil->status); |
| 778 | 775 | ||
| 779 | if (wil->platform_ops.bus_request) | 776 | if (wil->platform_ops.bus_request) |
| 780 | wil->platform_ops.bus_request(wil->platform_handle, | 777 | wil->platform_ops.bus_request(wil->platform_handle, |
| @@ -807,7 +804,7 @@ int __wil_down(struct wil6210_priv *wil) | |||
| 807 | wil->platform_ops.bus_request(wil->platform_handle, 0); | 804 | wil->platform_ops.bus_request(wil->platform_handle, 0); |
| 808 | 805 | ||
| 809 | wil_disable_irq(wil); | 806 | wil_disable_irq(wil); |
| 810 | if (test_and_clear_bit(wil_status_napi_en, &wil->status)) { | 807 | if (test_and_clear_bit(wil_status_napi_en, wil->status)) { |
| 811 | napi_disable(&wil->napi_rx); | 808 | napi_disable(&wil->napi_rx); |
| 812 | napi_disable(&wil->napi_tx); | 809 | napi_disable(&wil->napi_tx); |
| 813 | wil_dbg_misc(wil, "NAPI disable\n"); | 810 | wil_dbg_misc(wil, "NAPI disable\n"); |
| @@ -822,15 +819,15 @@ int __wil_down(struct wil6210_priv *wil) | |||
| 822 | wil->scan_request = NULL; | 819 | wil->scan_request = NULL; |
| 823 | } | 820 | } |
| 824 | 821 | ||
| 825 | if (test_bit(wil_status_fwconnected, &wil->status) || | 822 | if (test_bit(wil_status_fwconnected, wil->status) || |
| 826 | test_bit(wil_status_fwconnecting, &wil->status)) | 823 | test_bit(wil_status_fwconnecting, wil->status)) |
| 827 | wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); | 824 | wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); |
| 828 | 825 | ||
| 829 | /* make sure wil is idle (not connected) */ | 826 | /* make sure wil is idle (not connected) */ |
| 830 | mutex_unlock(&wil->mutex); | 827 | mutex_unlock(&wil->mutex); |
| 831 | while (iter--) { | 828 | while (iter--) { |
| 832 | int idle = !test_bit(wil_status_fwconnected, &wil->status) && | 829 | int idle = !test_bit(wil_status_fwconnected, wil->status) && |
| 833 | !test_bit(wil_status_fwconnecting, &wil->status); | 830 | !test_bit(wil_status_fwconnecting, wil->status); |
| 834 | if (idle) | 831 | if (idle) |
| 835 | break; | 832 | break; |
| 836 | msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS); | 833 | msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS); |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index e81703ca7701..ace30c1b5c64 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
| 3 | * | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -15,7 +15,6 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
| 18 | |||
| 19 | #include "wil6210.h" | 18 | #include "wil6210.h" |
| 20 | #include "txrx.h" | 19 | #include "txrx.h" |
| 21 | 20 | ||
| @@ -122,6 +121,12 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) | |||
| 122 | return min(tx_done, budget); | 121 | return min(tx_done, budget); |
| 123 | } | 122 | } |
| 124 | 123 | ||
| 124 | static void wil_dev_setup(struct net_device *dev) | ||
| 125 | { | ||
| 126 | ether_setup(dev); | ||
| 127 | dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; | ||
| 128 | } | ||
| 129 | |||
| 125 | void *wil_if_alloc(struct device *dev, void __iomem *csr) | 130 | void *wil_if_alloc(struct device *dev, void __iomem *csr) |
| 126 | { | 131 | { |
| 127 | struct net_device *ndev; | 132 | struct net_device *ndev; |
| @@ -153,7 +158,7 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) | |||
| 153 | ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; | 158 | ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; |
| 154 | cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); | 159 | cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); |
| 155 | 160 | ||
| 156 | ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup); | 161 | ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, wil_dev_setup); |
| 157 | if (!ndev) { | 162 | if (!ndev) { |
| 158 | dev_err(dev, "alloc_netdev_mqs failed\n"); | 163 | dev_err(dev, "alloc_netdev_mqs failed\n"); |
| 159 | rc = -ENOMEM; | 164 | rc = -ENOMEM; |
| @@ -174,7 +179,7 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) | |||
| 174 | netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, | 179 | netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, |
| 175 | WIL6210_NAPI_BUDGET); | 180 | WIL6210_NAPI_BUDGET); |
| 176 | 181 | ||
| 177 | wil_link_off(wil); | 182 | netif_tx_stop_all_queues(ndev); |
| 178 | 183 | ||
| 179 | return wil; | 184 | return wil; |
| 180 | 185 | ||
| @@ -217,8 +222,6 @@ int wil_if_add(struct wil6210_priv *wil) | |||
| 217 | return rc; | 222 | return rc; |
| 218 | } | 223 | } |
| 219 | 224 | ||
| 220 | wil_link_off(wil); | ||
| 221 | |||
| 222 | return 0; | 225 | return 0; |
| 223 | } | 226 | } |
| 224 | 227 | ||
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 66626a8ee728..3dd26709ccb2 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
| @@ -31,6 +31,46 @@ static bool debug_fw; /* = false; */ | |||
| 31 | module_param(debug_fw, bool, S_IRUGO); | 31 | module_param(debug_fw, bool, S_IRUGO); |
| 32 | MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug"); | 32 | MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug"); |
| 33 | 33 | ||
| 34 | static | ||
| 35 | void wil_set_capabilities(struct wil6210_priv *wil) | ||
| 36 | { | ||
| 37 | u32 rev_id = ioread32(wil->csr + HOSTADDR(RGF_USER_JTAG_DEV_ID)); | ||
| 38 | |||
| 39 | bitmap_zero(wil->hw_capabilities, hw_capability_last); | ||
| 40 | |||
| 41 | switch (rev_id) { | ||
| 42 | case JTAG_DEV_ID_MARLON_B0: | ||
| 43 | wil->hw_name = "Marlon B0"; | ||
| 44 | wil->hw_version = HW_VER_MARLON_B0; | ||
| 45 | break; | ||
| 46 | case JTAG_DEV_ID_SPARROW_A0: | ||
| 47 | wil->hw_name = "Sparrow A0"; | ||
| 48 | wil->hw_version = HW_VER_SPARROW_A0; | ||
| 49 | break; | ||
| 50 | case JTAG_DEV_ID_SPARROW_A1: | ||
| 51 | wil->hw_name = "Sparrow A1"; | ||
| 52 | wil->hw_version = HW_VER_SPARROW_A1; | ||
| 53 | break; | ||
| 54 | case JTAG_DEV_ID_SPARROW_B0: | ||
| 55 | wil->hw_name = "Sparrow B0"; | ||
| 56 | wil->hw_version = HW_VER_SPARROW_B0; | ||
| 57 | break; | ||
| 58 | default: | ||
| 59 | wil_err(wil, "Unknown board hardware 0x%08x\n", rev_id); | ||
| 60 | wil->hw_name = "Unknown"; | ||
| 61 | wil->hw_version = HW_VER_UNKNOWN; | ||
| 62 | } | ||
| 63 | |||
| 64 | wil_info(wil, "Board hardware is %s\n", wil->hw_name); | ||
| 65 | |||
| 66 | if (wil->hw_version >= HW_VER_SPARROW_A0) | ||
| 67 | set_bit(hw_capability_reset_v2, wil->hw_capabilities); | ||
| 68 | |||
| 69 | if (wil->hw_version >= HW_VER_SPARROW_B0) | ||
| 70 | set_bit(hw_capability_advanced_itr_moderation, | ||
| 71 | wil->hw_capabilities); | ||
| 72 | } | ||
| 73 | |||
| 34 | void wil_disable_irq(struct wil6210_priv *wil) | 74 | void wil_disable_irq(struct wil6210_priv *wil) |
| 35 | { | 75 | { |
| 36 | int irq = wil->pdev->irq; | 76 | int irq = wil->pdev->irq; |
| @@ -149,12 +189,11 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 149 | struct wil6210_priv *wil; | 189 | struct wil6210_priv *wil; |
| 150 | struct device *dev = &pdev->dev; | 190 | struct device *dev = &pdev->dev; |
| 151 | void __iomem *csr; | 191 | void __iomem *csr; |
| 152 | struct wil_board *board = (struct wil_board *)id->driver_data; | ||
| 153 | int rc; | 192 | int rc; |
| 154 | 193 | ||
| 155 | /* check HW */ | 194 | /* check HW */ |
| 156 | dev_info(&pdev->dev, WIL_NAME | 195 | dev_info(&pdev->dev, WIL_NAME |
| 157 | " \"%s\" device found [%04x:%04x] (rev %x)\n", board->name, | 196 | " device found [%04x:%04x] (rev %x)\n", |
| 158 | (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); | 197 | (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); |
| 159 | 198 | ||
| 160 | if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { | 199 | if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { |
| @@ -204,8 +243,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 204 | 243 | ||
| 205 | pci_set_drvdata(pdev, wil); | 244 | pci_set_drvdata(pdev, wil); |
| 206 | wil->pdev = pdev; | 245 | wil->pdev = pdev; |
| 207 | wil->board = board; | 246 | wil_set_capabilities(wil); |
| 208 | |||
| 209 | wil6210_clear_irq(wil); | 247 | wil6210_clear_irq(wil); |
| 210 | 248 | ||
| 211 | wil->platform_handle = | 249 | wil->platform_handle = |
| @@ -266,23 +304,10 @@ static void wil_pcie_remove(struct pci_dev *pdev) | |||
| 266 | pci_disable_device(pdev); | 304 | pci_disable_device(pdev); |
| 267 | } | 305 | } |
| 268 | 306 | ||
| 269 | static const struct wil_board wil_board_marlon = { | ||
| 270 | .board = WIL_BOARD_MARLON, | ||
| 271 | .name = "marlon", | ||
| 272 | }; | ||
| 273 | |||
| 274 | static const struct wil_board wil_board_sparrow = { | ||
| 275 | .board = WIL_BOARD_SPARROW, | ||
| 276 | .name = "sparrow", | ||
| 277 | }; | ||
| 278 | |||
| 279 | static const struct pci_device_id wil6210_pcie_ids[] = { | 307 | static const struct pci_device_id wil6210_pcie_ids[] = { |
| 280 | { PCI_DEVICE(0x1ae9, 0x0301), | 308 | { PCI_DEVICE(0x1ae9, 0x0301) }, |
| 281 | .driver_data = (kernel_ulong_t)&wil_board_marlon }, | 309 | { PCI_DEVICE(0x1ae9, 0x0310) }, |
| 282 | { PCI_DEVICE(0x1ae9, 0x0310), | 310 | { PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */ |
| 283 | .driver_data = (kernel_ulong_t)&wil_board_sparrow }, | ||
| 284 | { PCI_DEVICE(0x1ae9, 0x0302), /* same as above, firmware broken */ | ||
| 285 | .driver_data = (kernel_ulong_t)&wil_board_sparrow }, | ||
| 286 | { /* end: all zeroes */ }, | 311 | { /* end: all zeroes */ }, |
| 287 | }; | 312 | }; |
| 288 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); | 313 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); |
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 489cb73d139b..ca10dcf0986e 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. |
| 3 | * | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -89,7 +89,9 @@ static void wil_reorder_release(struct wil6210_priv *wil, | |||
| 89 | } | 89 | } |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | /* called in NAPI context */ | ||
| 92 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) | 93 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) |
| 94 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | ||
| 93 | { | 95 | { |
| 94 | struct net_device *ndev = wil_to_ndev(wil); | 96 | struct net_device *ndev = wil_to_ndev(wil); |
| 95 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 97 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
| @@ -97,22 +99,26 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) | |||
| 97 | int cid = wil_rxdesc_cid(d); | 99 | int cid = wil_rxdesc_cid(d); |
| 98 | int mid = wil_rxdesc_mid(d); | 100 | int mid = wil_rxdesc_mid(d); |
| 99 | u16 seq = wil_rxdesc_seq(d); | 101 | u16 seq = wil_rxdesc_seq(d); |
| 102 | int mcast = wil_rxdesc_mcast(d); | ||
| 100 | struct wil_sta_info *sta = &wil->sta[cid]; | 103 | struct wil_sta_info *sta = &wil->sta[cid]; |
| 101 | struct wil_tid_ampdu_rx *r; | 104 | struct wil_tid_ampdu_rx *r; |
| 102 | u16 hseq; | 105 | u16 hseq; |
| 103 | int index; | 106 | int index; |
| 104 | unsigned long flags; | ||
| 105 | 107 | ||
| 106 | wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x\n", | 108 | wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n", |
| 107 | mid, cid, tid, seq); | 109 | mid, cid, tid, seq, mcast); |
| 108 | 110 | ||
| 109 | spin_lock_irqsave(&sta->tid_rx_lock, flags); | 111 | if (unlikely(mcast)) { |
| 112 | wil_netif_rx_any(skb, ndev); | ||
| 113 | return; | ||
| 114 | } | ||
| 115 | |||
| 116 | spin_lock(&sta->tid_rx_lock); | ||
| 110 | 117 | ||
| 111 | r = sta->tid_rx[tid]; | 118 | r = sta->tid_rx[tid]; |
| 112 | if (!r) { | 119 | if (!r) { |
| 113 | spin_unlock_irqrestore(&sta->tid_rx_lock, flags); | ||
| 114 | wil_netif_rx_any(skb, ndev); | 120 | wil_netif_rx_any(skb, ndev); |
| 115 | return; | 121 | goto out; |
| 116 | } | 122 | } |
| 117 | 123 | ||
| 118 | hseq = r->head_seq_num; | 124 | hseq = r->head_seq_num; |
| @@ -121,13 +127,24 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) | |||
| 121 | * reported, and data Rx, few packets may be pass up before reorder | 127 | * reported, and data Rx, few packets may be pass up before reorder |
| 122 | * buffer get allocated. Catch up by pretending SSN is what we | 128 | * buffer get allocated. Catch up by pretending SSN is what we |
| 123 | * see in the 1-st Rx packet | 129 | * see in the 1-st Rx packet |
| 130 | * | ||
| 131 | * Another scenario, Rx get delayed and we got packet from before | ||
| 132 | * BACK. Pass it to the stack and wait. | ||
| 124 | */ | 133 | */ |
| 125 | if (r->first_time) { | 134 | if (r->first_time) { |
| 126 | r->first_time = false; | 135 | r->first_time = false; |
| 127 | if (seq != r->head_seq_num) { | 136 | if (seq != r->head_seq_num) { |
| 128 | wil_err(wil, "Error: 1-st frame with wrong sequence" | 137 | if (seq_less(seq, r->head_seq_num)) { |
| 129 | " %d, should be %d. Fixing...\n", seq, | 138 | wil_err(wil, |
| 130 | r->head_seq_num); | 139 | "Error: frame with early sequence 0x%03x, should be 0x%03x. Waiting...\n", |
| 140 | seq, r->head_seq_num); | ||
| 141 | r->first_time = true; | ||
| 142 | wil_netif_rx_any(skb, ndev); | ||
| 143 | goto out; | ||
| 144 | } | ||
| 145 | wil_err(wil, | ||
| 146 | "Error: 1-st frame with wrong sequence 0x%03x, should be 0x%03x. Fixing...\n", | ||
| 147 | seq, r->head_seq_num); | ||
| 131 | r->head_seq_num = seq; | 148 | r->head_seq_num = seq; |
| 132 | r->ssn = seq; | 149 | r->ssn = seq; |
| 133 | } | 150 | } |
| @@ -179,7 +196,7 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb) | |||
| 179 | wil_reorder_release(wil, r); | 196 | wil_reorder_release(wil, r); |
| 180 | 197 | ||
| 181 | out: | 198 | out: |
| 182 | spin_unlock_irqrestore(&sta->tid_rx_lock, flags); | 199 | spin_unlock(&sta->tid_rx_lock); |
| 183 | } | 200 | } |
| 184 | 201 | ||
| 185 | struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, | 202 | struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, |
| @@ -219,3 +236,241 @@ void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, | |||
| 219 | kfree(r->reorder_time); | 236 | kfree(r->reorder_time); |
| 220 | kfree(r); | 237 | kfree(r); |
| 221 | } | 238 | } |
| 239 | |||
| 240 | /* ADDBA processing */ | ||
| 241 | static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize) | ||
| 242 | { | ||
| 243 | u16 max_agg_size = min_t(u16, WIL_MAX_AGG_WSIZE, WIL_MAX_AMPDU_SIZE / | ||
| 244 | (mtu_max + WIL_MAX_MPDU_OVERHEAD)); | ||
| 245 | |||
| 246 | if (!req_agg_wsize) | ||
| 247 | return max_agg_size; | ||
| 248 | |||
| 249 | return min(max_agg_size, req_agg_wsize); | ||
| 250 | } | ||
| 251 | |||
| 252 | /* Block Ack - Rx side (recipient */ | ||
| 253 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, | ||
| 254 | u8 dialog_token, __le16 ba_param_set, | ||
| 255 | __le16 ba_timeout, __le16 ba_seq_ctrl) | ||
| 256 | { | ||
| 257 | struct wil_back_rx *req = kzalloc(sizeof(*req), GFP_KERNEL); | ||
| 258 | |||
| 259 | if (!req) | ||
| 260 | return -ENOMEM; | ||
| 261 | |||
| 262 | req->cidxtid = cidxtid; | ||
| 263 | req->dialog_token = dialog_token; | ||
| 264 | req->ba_param_set = le16_to_cpu(ba_param_set); | ||
| 265 | req->ba_timeout = le16_to_cpu(ba_timeout); | ||
| 266 | req->ba_seq_ctrl = le16_to_cpu(ba_seq_ctrl); | ||
| 267 | |||
| 268 | mutex_lock(&wil->back_rx_mutex); | ||
| 269 | list_add_tail(&req->list, &wil->back_rx_pending); | ||
| 270 | mutex_unlock(&wil->back_rx_mutex); | ||
| 271 | |||
| 272 | queue_work(wil->wq_service, &wil->back_rx_worker); | ||
| 273 | |||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | static void wil_back_rx_handle(struct wil6210_priv *wil, | ||
| 278 | struct wil_back_rx *req) | ||
| 279 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | ||
| 280 | { | ||
| 281 | struct wil_sta_info *sta; | ||
| 282 | u8 cid, tid; | ||
| 283 | u16 agg_wsize = 0; | ||
| 284 | /* bit 0: A-MSDU supported | ||
| 285 | * bit 1: policy (should be 0 for us) | ||
| 286 | * bits 2..5: TID | ||
| 287 | * bits 6..15: buffer size | ||
| 288 | */ | ||
| 289 | u16 req_agg_wsize = WIL_GET_BITS(req->ba_param_set, 6, 15); | ||
| 290 | bool agg_amsdu = !!(req->ba_param_set & BIT(0)); | ||
| 291 | int ba_policy = req->ba_param_set & BIT(1); | ||
| 292 | u16 agg_timeout = req->ba_timeout; | ||
| 293 | u16 status = WLAN_STATUS_SUCCESS; | ||
| 294 | u16 ssn = req->ba_seq_ctrl >> 4; | ||
| 295 | struct wil_tid_ampdu_rx *r; | ||
| 296 | int rc; | ||
| 297 | |||
| 298 | might_sleep(); | ||
| 299 | parse_cidxtid(req->cidxtid, &cid, &tid); | ||
| 300 | |||
| 301 | /* sanity checks */ | ||
| 302 | if (cid >= WIL6210_MAX_CID) { | ||
| 303 | wil_err(wil, "BACK: invalid CID %d\n", cid); | ||
| 304 | return; | ||
| 305 | } | ||
| 306 | |||
| 307 | sta = &wil->sta[cid]; | ||
| 308 | if (sta->status != wil_sta_connected) { | ||
| 309 | wil_err(wil, "BACK: CID %d not connected\n", cid); | ||
| 310 | return; | ||
| 311 | } | ||
| 312 | |||
| 313 | wil_dbg_wmi(wil, | ||
| 314 | "ADDBA request for CID %d %pM TID %d size %d timeout %d AMSDU%s policy %d token %d SSN 0x%03x\n", | ||
| 315 | cid, sta->addr, tid, req_agg_wsize, req->ba_timeout, | ||
| 316 | agg_amsdu ? "+" : "-", !!ba_policy, req->dialog_token, ssn); | ||
| 317 | |||
| 318 | /* apply policies */ | ||
| 319 | if (ba_policy) { | ||
| 320 | wil_err(wil, "BACK requested unsupported ba_policy == 1\n"); | ||
| 321 | status = WLAN_STATUS_INVALID_QOS_PARAM; | ||
| 322 | } | ||
| 323 | if (status == WLAN_STATUS_SUCCESS) | ||
| 324 | agg_wsize = wil_agg_size(wil, req_agg_wsize); | ||
| 325 | |||
| 326 | rc = wmi_addba_rx_resp(wil, cid, tid, req->dialog_token, status, | ||
| 327 | agg_amsdu, agg_wsize, agg_timeout); | ||
| 328 | if (rc || (status != WLAN_STATUS_SUCCESS)) | ||
| 329 | return; | ||
| 330 | |||
| 331 | /* apply */ | ||
| 332 | r = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn); | ||
| 333 | spin_lock_bh(&sta->tid_rx_lock); | ||
| 334 | wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]); | ||
| 335 | sta->tid_rx[tid] = r; | ||
| 336 | spin_unlock_bh(&sta->tid_rx_lock); | ||
| 337 | } | ||
| 338 | |||
| 339 | void wil_back_rx_flush(struct wil6210_priv *wil) | ||
| 340 | { | ||
| 341 | struct wil_back_rx *evt, *t; | ||
| 342 | |||
| 343 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
| 344 | |||
| 345 | mutex_lock(&wil->back_rx_mutex); | ||
| 346 | |||
| 347 | list_for_each_entry_safe(evt, t, &wil->back_rx_pending, list) { | ||
| 348 | list_del(&evt->list); | ||
| 349 | kfree(evt); | ||
| 350 | } | ||
| 351 | |||
| 352 | mutex_unlock(&wil->back_rx_mutex); | ||
| 353 | } | ||
| 354 | |||
| 355 | /* Retrieve next ADDBA request from the pending list */ | ||
| 356 | static struct list_head *next_back_rx(struct wil6210_priv *wil) | ||
| 357 | { | ||
| 358 | struct list_head *ret = NULL; | ||
| 359 | |||
| 360 | mutex_lock(&wil->back_rx_mutex); | ||
| 361 | |||
| 362 | if (!list_empty(&wil->back_rx_pending)) { | ||
| 363 | ret = wil->back_rx_pending.next; | ||
| 364 | list_del(ret); | ||
| 365 | } | ||
| 366 | |||
| 367 | mutex_unlock(&wil->back_rx_mutex); | ||
| 368 | |||
| 369 | return ret; | ||
| 370 | } | ||
| 371 | |||
| 372 | void wil_back_rx_worker(struct work_struct *work) | ||
| 373 | { | ||
| 374 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
| 375 | back_rx_worker); | ||
| 376 | struct wil_back_rx *evt; | ||
| 377 | struct list_head *lh; | ||
| 378 | |||
| 379 | while ((lh = next_back_rx(wil)) != NULL) { | ||
| 380 | evt = list_entry(lh, struct wil_back_rx, list); | ||
| 381 | |||
| 382 | wil_back_rx_handle(wil, evt); | ||
| 383 | kfree(evt); | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | /* BACK - Tx (originator) side */ | ||
| 388 | static void wil_back_tx_handle(struct wil6210_priv *wil, | ||
| 389 | struct wil_back_tx *req) | ||
| 390 | { | ||
| 391 | struct vring_tx_data *txdata = &wil->vring_tx_data[req->ringid]; | ||
| 392 | int rc; | ||
| 393 | |||
| 394 | if (txdata->addba_in_progress) { | ||
| 395 | wil_dbg_misc(wil, "ADDBA for vring[%d] already in progress\n", | ||
| 396 | req->ringid); | ||
| 397 | return; | ||
| 398 | } | ||
| 399 | if (txdata->agg_wsize) { | ||
| 400 | wil_dbg_misc(wil, | ||
| 401 | "ADDBA for vring[%d] already established wsize %d\n", | ||
| 402 | req->ringid, txdata->agg_wsize); | ||
| 403 | return; | ||
| 404 | } | ||
| 405 | txdata->addba_in_progress = true; | ||
| 406 | rc = wmi_addba(wil, req->ringid, req->agg_wsize, req->agg_timeout); | ||
| 407 | if (rc) | ||
| 408 | txdata->addba_in_progress = false; | ||
| 409 | } | ||
| 410 | |||
| 411 | static struct list_head *next_back_tx(struct wil6210_priv *wil) | ||
| 412 | { | ||
| 413 | struct list_head *ret = NULL; | ||
| 414 | |||
| 415 | mutex_lock(&wil->back_tx_mutex); | ||
| 416 | |||
| 417 | if (!list_empty(&wil->back_tx_pending)) { | ||
| 418 | ret = wil->back_tx_pending.next; | ||
| 419 | list_del(ret); | ||
| 420 | } | ||
| 421 | |||
| 422 | mutex_unlock(&wil->back_tx_mutex); | ||
| 423 | |||
| 424 | return ret; | ||
| 425 | } | ||
| 426 | |||
| 427 | void wil_back_tx_worker(struct work_struct *work) | ||
| 428 | { | ||
| 429 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
| 430 | back_tx_worker); | ||
| 431 | struct wil_back_tx *evt; | ||
| 432 | struct list_head *lh; | ||
| 433 | |||
| 434 | while ((lh = next_back_tx(wil)) != NULL) { | ||
| 435 | evt = list_entry(lh, struct wil_back_tx, list); | ||
| 436 | |||
| 437 | wil_back_tx_handle(wil, evt); | ||
| 438 | kfree(evt); | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | void wil_back_tx_flush(struct wil6210_priv *wil) | ||
| 443 | { | ||
| 444 | struct wil_back_tx *evt, *t; | ||
| 445 | |||
| 446 | wil_dbg_misc(wil, "%s()\n", __func__); | ||
| 447 | |||
| 448 | mutex_lock(&wil->back_tx_mutex); | ||
| 449 | |||
| 450 | list_for_each_entry_safe(evt, t, &wil->back_tx_pending, list) { | ||
| 451 | list_del(&evt->list); | ||
| 452 | kfree(evt); | ||
| 453 | } | ||
| 454 | |||
| 455 | mutex_unlock(&wil->back_tx_mutex); | ||
| 456 | } | ||
| 457 | |||
| 458 | int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) | ||
| 459 | { | ||
| 460 | struct wil_back_tx *req = kzalloc(sizeof(*req), GFP_KERNEL); | ||
| 461 | |||
| 462 | if (!req) | ||
| 463 | return -ENOMEM; | ||
| 464 | |||
| 465 | req->ringid = ringid; | ||
| 466 | req->agg_wsize = wil_agg_size(wil, wsize); | ||
| 467 | req->agg_timeout = 0; | ||
| 468 | |||
| 469 | mutex_lock(&wil->back_tx_mutex); | ||
| 470 | list_add_tail(&req->list, &wil->back_tx_pending); | ||
| 471 | mutex_unlock(&wil->back_tx_mutex); | ||
| 472 | |||
| 473 | queue_work(wil->wq_service, &wil->back_tx_worker); | ||
| 474 | |||
| 475 | return 0; | ||
| 476 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index e3f8bdce5abc..8439f65db259 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
| @@ -463,7 +463,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
| 463 | * and in case of error drop the packet | 463 | * and in case of error drop the packet |
| 464 | * higher stack layers will handle retransmission (if required) | 464 | * higher stack layers will handle retransmission (if required) |
| 465 | */ | 465 | */ |
| 466 | if (d->dma.status & RX_DMA_STATUS_L4_IDENT) { | 466 | if (d->dma.status & RX_DMA_STATUS_L4I) { |
| 467 | /* L4 protocol identified, csum calculated */ | 467 | /* L4 protocol identified, csum calculated */ |
| 468 | if ((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0) | 468 | if ((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0) |
| 469 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 469 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| @@ -581,14 +581,8 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) | |||
| 581 | skb->protocol = htons(ETH_P_802_2); | 581 | skb->protocol = htons(ETH_P_802_2); |
| 582 | wil_netif_rx_any(skb, ndev); | 582 | wil_netif_rx_any(skb, ndev); |
| 583 | } else { | 583 | } else { |
| 584 | struct ethhdr *eth = (void *)skb->data; | ||
| 585 | |||
| 586 | skb->protocol = eth_type_trans(skb, ndev); | 584 | skb->protocol = eth_type_trans(skb, ndev); |
| 587 | 585 | wil_rx_reorder(wil, skb); | |
| 588 | if (is_unicast_ether_addr(eth->h_dest)) | ||
| 589 | wil_rx_reorder(wil, skb); | ||
| 590 | else | ||
| 591 | wil_netif_rx_any(skb, ndev); | ||
| 592 | } | 586 | } |
| 593 | } | 587 | } |
| 594 | wil_rx_refill(wil, v->size); | 588 | wil_rx_refill(wil, v->size); |
| @@ -645,7 +639,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
| 645 | .vring_cfg = { | 639 | .vring_cfg = { |
| 646 | .tx_sw_ring = { | 640 | .tx_sw_ring = { |
| 647 | .max_mpdu_size = | 641 | .max_mpdu_size = |
| 648 | cpu_to_le16(mtu_max + ETH_HLEN), | 642 | cpu_to_le16(wil_mtu2macbuf(mtu_max)), |
| 649 | .ring_size = cpu_to_le16(size), | 643 | .ring_size = cpu_to_le16(size), |
| 650 | }, | 644 | }, |
| 651 | .ringid = id, | 645 | .ringid = id, |
| @@ -653,7 +647,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
| 653 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, | 647 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, |
| 654 | .mac_ctrl = 0, | 648 | .mac_ctrl = 0, |
| 655 | .to_resolution = 0, | 649 | .to_resolution = 0, |
| 656 | .agg_max_wsize = 16, | 650 | .agg_max_wsize = 0, |
| 657 | .schd_params = { | 651 | .schd_params = { |
| 658 | .priority = cpu_to_le16(0), | 652 | .priority = cpu_to_le16(0), |
| 659 | .timeslot_us = cpu_to_le16(0xfff), | 653 | .timeslot_us = cpu_to_le16(0xfff), |
| @@ -677,6 +671,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
| 677 | } | 671 | } |
| 678 | 672 | ||
| 679 | memset(txdata, 0, sizeof(*txdata)); | 673 | memset(txdata, 0, sizeof(*txdata)); |
| 674 | spin_lock_init(&txdata->lock); | ||
| 680 | vring->size = size; | 675 | vring->size = size; |
| 681 | rc = wil_vring_alloc(wil, vring); | 676 | rc = wil_vring_alloc(wil, vring); |
| 682 | if (rc) | 677 | if (rc) |
| @@ -701,6 +696,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
| 701 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | 696 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); |
| 702 | 697 | ||
| 703 | txdata->enabled = 1; | 698 | txdata->enabled = 1; |
| 699 | if (wil->sta[cid].data_port_open && (agg_wsize >= 0)) | ||
| 700 | wil_addba_tx_request(wil, id, agg_wsize); | ||
| 704 | 701 | ||
| 705 | return 0; | 702 | return 0; |
| 706 | out_free: | 703 | out_free: |
| @@ -713,6 +710,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
| 713 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | 710 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id) |
| 714 | { | 711 | { |
| 715 | struct vring *vring = &wil->vring_tx[id]; | 712 | struct vring *vring = &wil->vring_tx[id]; |
| 713 | struct vring_tx_data *txdata = &wil->vring_tx_data[id]; | ||
| 716 | 714 | ||
| 717 | WARN_ON(!mutex_is_locked(&wil->mutex)); | 715 | WARN_ON(!mutex_is_locked(&wil->mutex)); |
| 718 | 716 | ||
| @@ -721,12 +719,15 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | |||
| 721 | 719 | ||
| 722 | wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); | 720 | wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); |
| 723 | 721 | ||
| 722 | spin_lock_bh(&txdata->lock); | ||
| 723 | txdata->enabled = 0; /* no Tx can be in progress or start anew */ | ||
| 724 | spin_unlock_bh(&txdata->lock); | ||
| 724 | /* make sure NAPI won't touch this vring */ | 725 | /* make sure NAPI won't touch this vring */ |
| 725 | wil->vring_tx_data[id].enabled = 0; | 726 | if (test_bit(wil_status_napi_en, wil->status)) |
| 726 | if (test_bit(wil_status_napi_en, &wil->status)) | ||
| 727 | napi_synchronize(&wil->napi_tx); | 727 | napi_synchronize(&wil->napi_tx); |
| 728 | 728 | ||
| 729 | wil_vring_free(wil, vring, 1); | 729 | wil_vring_free(wil, vring, 1); |
| 730 | memset(txdata, 0, sizeof(*txdata)); | ||
| 730 | } | 731 | } |
| 731 | 732 | ||
| 732 | static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, | 733 | static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, |
| @@ -773,6 +774,38 @@ static void wil_set_da_for_vring(struct wil6210_priv *wil, | |||
| 773 | 774 | ||
| 774 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 775 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, |
| 775 | struct sk_buff *skb); | 776 | struct sk_buff *skb); |
| 777 | |||
| 778 | static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | ||
| 779 | struct sk_buff *skb) | ||
| 780 | { | ||
| 781 | struct vring *v; | ||
| 782 | int i; | ||
| 783 | u8 cid; | ||
| 784 | |||
| 785 | /* In the STA mode, it is expected to have only 1 VRING | ||
| 786 | * for the AP we connected to. | ||
| 787 | * find 1-st vring and see whether it is eligible for data | ||
| 788 | */ | ||
| 789 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | ||
| 790 | v = &wil->vring_tx[i]; | ||
| 791 | if (!v->va) | ||
| 792 | continue; | ||
| 793 | |||
| 794 | cid = wil->vring2cid_tid[i][0]; | ||
| 795 | if (!wil->sta[cid].data_port_open && | ||
| 796 | (skb->protocol != cpu_to_be16(ETH_P_PAE))) | ||
| 797 | break; | ||
| 798 | |||
| 799 | wil_dbg_txrx(wil, "Tx -> ring %d\n", i); | ||
| 800 | |||
| 801 | return v; | ||
| 802 | } | ||
| 803 | |||
| 804 | wil_dbg_txrx(wil, "Tx while no vrings active?\n"); | ||
| 805 | |||
| 806 | return NULL; | ||
| 807 | } | ||
| 808 | |||
| 776 | /* | 809 | /* |
| 777 | * Find 1-st vring and return it; set dest address for this vring in skb | 810 | * Find 1-st vring and return it; set dest address for this vring in skb |
| 778 | * duplicate skb and send it to other active vrings | 811 | * duplicate skb and send it to other active vrings |
| @@ -843,9 +876,6 @@ static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, | |||
| 843 | d->mac.d[1] = 0; | 876 | d->mac.d[1] = 0; |
| 844 | d->mac.d[2] = 0; | 877 | d->mac.d[2] = 0; |
| 845 | d->mac.ucode_cmd = 0; | 878 | d->mac.ucode_cmd = 0; |
| 846 | /* use dst index 0 */ | ||
| 847 | d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | | ||
| 848 | (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); | ||
| 849 | /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ | 879 | /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ |
| 850 | d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | | 880 | d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | |
| 851 | (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); | 881 | (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); |
| @@ -908,8 +938,8 @@ static int wil_tx_desc_offload_cksum_set(struct wil6210_priv *wil, | |||
| 908 | return 0; | 938 | return 0; |
| 909 | } | 939 | } |
| 910 | 940 | ||
| 911 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 941 | static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, |
| 912 | struct sk_buff *skb) | 942 | struct sk_buff *skb) |
| 913 | { | 943 | { |
| 914 | struct device *dev = wil_to_dev(wil); | 944 | struct device *dev = wil_to_dev(wil); |
| 915 | struct vring_tx_desc dd, *d = ⅆ | 945 | struct vring_tx_desc dd, *d = ⅆ |
| @@ -925,18 +955,21 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
| 925 | 955 | ||
| 926 | wil_dbg_txrx(wil, "%s()\n", __func__); | 956 | wil_dbg_txrx(wil, "%s()\n", __func__); |
| 927 | 957 | ||
| 958 | if (unlikely(!txdata->enabled)) | ||
| 959 | return -EINVAL; | ||
| 960 | |||
| 928 | if (avail < 1 + nr_frags) { | 961 | if (avail < 1 + nr_frags) { |
| 929 | wil_err_ratelimited(wil, | 962 | wil_err_ratelimited(wil, |
| 930 | "Tx ring full. No space for %d fragments\n", | 963 | "Tx ring[%2d] full. No space for %d fragments\n", |
| 931 | 1 + nr_frags); | 964 | vring_index, 1 + nr_frags); |
| 932 | return -ENOMEM; | 965 | return -ENOMEM; |
| 933 | } | 966 | } |
| 934 | _d = &vring->va[i].tx; | 967 | _d = &vring->va[i].tx; |
| 935 | 968 | ||
| 936 | pa = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); | 969 | pa = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); |
| 937 | 970 | ||
| 938 | wil_dbg_txrx(wil, "Tx skb %d bytes 0x%p -> %pad\n", skb_headlen(skb), | 971 | wil_dbg_txrx(wil, "Tx[%2d] skb %d bytes 0x%p -> %pad\n", vring_index, |
| 939 | skb->data, &pa); | 972 | skb_headlen(skb), skb->data, &pa); |
| 940 | wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1, | 973 | wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1, |
| 941 | skb->data, skb_headlen(skb), false); | 974 | skb->data, skb_headlen(skb), false); |
| 942 | 975 | ||
| @@ -947,15 +980,13 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
| 947 | wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); | 980 | wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); |
| 948 | /* Process TCP/UDP checksum offloading */ | 981 | /* Process TCP/UDP checksum offloading */ |
| 949 | if (wil_tx_desc_offload_cksum_set(wil, d, skb)) { | 982 | if (wil_tx_desc_offload_cksum_set(wil, d, skb)) { |
| 950 | wil_err(wil, "VRING #%d Failed to set cksum, drop packet\n", | 983 | wil_err(wil, "Tx[%2d] Failed to set cksum, drop packet\n", |
| 951 | vring_index); | 984 | vring_index); |
| 952 | goto dma_error; | 985 | goto dma_error; |
| 953 | } | 986 | } |
| 954 | 987 | ||
| 955 | vring->ctx[i].nr_frags = nr_frags; | 988 | vring->ctx[i].nr_frags = nr_frags; |
| 956 | wil_tx_desc_set_nr_frags(d, nr_frags); | 989 | wil_tx_desc_set_nr_frags(d, nr_frags); |
| 957 | if (nr_frags) | ||
| 958 | *_d = *d; | ||
| 959 | 990 | ||
| 960 | /* middle segments */ | 991 | /* middle segments */ |
| 961 | for (; f < nr_frags; f++) { | 992 | for (; f < nr_frags; f++) { |
| @@ -963,6 +994,10 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
| 963 | &skb_shinfo(skb)->frags[f]; | 994 | &skb_shinfo(skb)->frags[f]; |
| 964 | int len = skb_frag_size(frag); | 995 | int len = skb_frag_size(frag); |
| 965 | 996 | ||
| 997 | *_d = *d; | ||
| 998 | wil_dbg_txrx(wil, "Tx[%2d] desc[%4d]\n", vring_index, i); | ||
| 999 | wil_hex_dump_txrx("TxD ", DUMP_PREFIX_NONE, 32, 4, | ||
| 1000 | (const void *)d, sizeof(*d), false); | ||
| 966 | i = (swhead + f + 1) % vring->size; | 1001 | i = (swhead + f + 1) % vring->size; |
| 967 | _d = &vring->va[i].tx; | 1002 | _d = &vring->va[i].tx; |
| 968 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | 1003 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), |
| @@ -976,13 +1011,15 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
| 976 | * it will succeed here too | 1011 | * it will succeed here too |
| 977 | */ | 1012 | */ |
| 978 | wil_tx_desc_offload_cksum_set(wil, d, skb); | 1013 | wil_tx_desc_offload_cksum_set(wil, d, skb); |
| 979 | *_d = *d; | ||
| 980 | } | 1014 | } |
| 981 | /* for the last seg only */ | 1015 | /* for the last seg only */ |
| 982 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); | 1016 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); |
| 983 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS); | 1017 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS); |
| 984 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); | 1018 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); |
| 985 | *_d = *d; | 1019 | *_d = *d; |
| 1020 | wil_dbg_txrx(wil, "Tx[%2d] desc[%4d]\n", vring_index, i); | ||
| 1021 | wil_hex_dump_txrx("TxD ", DUMP_PREFIX_NONE, 32, 4, | ||
| 1022 | (const void *)d, sizeof(*d), false); | ||
| 986 | 1023 | ||
| 987 | /* hold reference to skb | 1024 | /* hold reference to skb |
| 988 | * to prevent skb release before accounting | 1025 | * to prevent skb release before accounting |
| @@ -990,15 +1027,13 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
| 990 | */ | 1027 | */ |
| 991 | vring->ctx[i].skb = skb_get(skb); | 1028 | vring->ctx[i].skb = skb_get(skb); |
| 992 | 1029 | ||
| 993 | wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4, | ||
| 994 | (const void *)d, sizeof(*d), false); | ||
| 995 | |||
| 996 | if (wil_vring_is_empty(vring)) /* performance monitoring */ | 1030 | if (wil_vring_is_empty(vring)) /* performance monitoring */ |
| 997 | txdata->idle += get_cycles() - txdata->last_idle; | 1031 | txdata->idle += get_cycles() - txdata->last_idle; |
| 998 | 1032 | ||
| 999 | /* advance swhead */ | 1033 | /* advance swhead */ |
| 1000 | wil_vring_advance_head(vring, nr_frags + 1); | 1034 | wil_vring_advance_head(vring, nr_frags + 1); |
| 1001 | wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); | 1035 | wil_dbg_txrx(wil, "Tx[%2d] swhead %d -> %d\n", vring_index, swhead, |
| 1036 | vring->swhead); | ||
| 1002 | trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags); | 1037 | trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags); |
| 1003 | iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); | 1038 | iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); |
| 1004 | 1039 | ||
| @@ -1025,6 +1060,19 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
| 1025 | return -EINVAL; | 1060 | return -EINVAL; |
| 1026 | } | 1061 | } |
| 1027 | 1062 | ||
| 1063 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | ||
| 1064 | struct sk_buff *skb) | ||
| 1065 | { | ||
| 1066 | int vring_index = vring - wil->vring_tx; | ||
| 1067 | struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; | ||
| 1068 | int rc; | ||
| 1069 | |||
| 1070 | spin_lock(&txdata->lock); | ||
| 1071 | rc = __wil_tx_vring(wil, vring, skb); | ||
| 1072 | spin_unlock(&txdata->lock); | ||
| 1073 | return rc; | ||
| 1074 | } | ||
| 1075 | |||
| 1028 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 1076 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
| 1029 | { | 1077 | { |
| 1030 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 1078 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
| @@ -1034,14 +1082,14 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
| 1034 | int rc; | 1082 | int rc; |
| 1035 | 1083 | ||
| 1036 | wil_dbg_txrx(wil, "%s()\n", __func__); | 1084 | wil_dbg_txrx(wil, "%s()\n", __func__); |
| 1037 | if (!test_bit(wil_status_fwready, &wil->status)) { | 1085 | if (!test_bit(wil_status_fwready, wil->status)) { |
| 1038 | if (!pr_once_fw) { | 1086 | if (!pr_once_fw) { |
| 1039 | wil_err(wil, "FW not ready\n"); | 1087 | wil_err(wil, "FW not ready\n"); |
| 1040 | pr_once_fw = true; | 1088 | pr_once_fw = true; |
| 1041 | } | 1089 | } |
| 1042 | goto drop; | 1090 | goto drop; |
| 1043 | } | 1091 | } |
| 1044 | if (!test_bit(wil_status_fwconnected, &wil->status)) { | 1092 | if (!test_bit(wil_status_fwconnected, wil->status)) { |
| 1045 | wil_err(wil, "FW not connected\n"); | 1093 | wil_err(wil, "FW not connected\n"); |
| 1046 | goto drop; | 1094 | goto drop; |
| 1047 | } | 1095 | } |
| @@ -1052,15 +1100,19 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
| 1052 | pr_once_fw = false; | 1100 | pr_once_fw = false; |
| 1053 | 1101 | ||
| 1054 | /* find vring */ | 1102 | /* find vring */ |
| 1055 | if (is_unicast_ether_addr(eth->h_dest)) | 1103 | if (wil->wdev->iftype == NL80211_IFTYPE_STATION) { |
| 1056 | vring = wil_find_tx_vring(wil, skb); | 1104 | /* in STA mode (ESS), all to same VRING */ |
| 1057 | else | 1105 | vring = wil_find_tx_vring_sta(wil, skb); |
| 1058 | vring = wil_tx_bcast(wil, skb); | 1106 | } else { /* direct communication, find matching VRING */ |
| 1107 | if (is_unicast_ether_addr(eth->h_dest)) | ||
| 1108 | vring = wil_find_tx_vring(wil, skb); | ||
| 1109 | else | ||
| 1110 | vring = wil_tx_bcast(wil, skb); | ||
| 1111 | } | ||
| 1059 | if (!vring) { | 1112 | if (!vring) { |
| 1060 | wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); | 1113 | wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); |
| 1061 | goto drop; | 1114 | goto drop; |
| 1062 | } | 1115 | } |
| 1063 | |||
| 1064 | /* set up vring entry */ | 1116 | /* set up vring entry */ |
| 1065 | rc = wil_tx_vring(wil, vring, skb); | 1117 | rc = wil_tx_vring(wil, vring, skb); |
| 1066 | 1118 | ||
| @@ -1087,6 +1139,22 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
| 1087 | return NET_XMIT_DROP; | 1139 | return NET_XMIT_DROP; |
| 1088 | } | 1140 | } |
| 1089 | 1141 | ||
| 1142 | static inline bool wil_need_txstat(struct sk_buff *skb) | ||
| 1143 | { | ||
| 1144 | struct ethhdr *eth = (void *)skb->data; | ||
| 1145 | |||
| 1146 | return is_unicast_ether_addr(eth->h_dest) && skb->sk && | ||
| 1147 | (skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS); | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | static inline void wil_consume_skb(struct sk_buff *skb, bool acked) | ||
| 1151 | { | ||
| 1152 | if (unlikely(wil_need_txstat(skb))) | ||
| 1153 | skb_complete_wifi_ack(skb, acked); | ||
| 1154 | else | ||
| 1155 | acked ? dev_consume_skb_any(skb) : dev_kfree_skb_any(skb); | ||
| 1156 | } | ||
| 1157 | |||
| 1090 | /** | 1158 | /** |
| 1091 | * Clean up transmitted skb's from the Tx VRING | 1159 | * Clean up transmitted skb's from the Tx VRING |
| 1092 | * | 1160 | * |
| @@ -1147,10 +1215,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
| 1147 | trace_wil6210_tx_done(ringid, vring->swtail, dmalen, | 1215 | trace_wil6210_tx_done(ringid, vring->swtail, dmalen, |
| 1148 | d->dma.error); | 1216 | d->dma.error); |
| 1149 | wil_dbg_txrx(wil, | 1217 | wil_dbg_txrx(wil, |
| 1150 | "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", | 1218 | "TxC[%2d][%3d] : %d bytes, status 0x%02x err 0x%02x\n", |
| 1151 | vring->swtail, dmalen, d->dma.status, | 1219 | ringid, vring->swtail, dmalen, |
| 1152 | d->dma.error); | 1220 | d->dma.status, d->dma.error); |
| 1153 | wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4, | 1221 | wil_hex_dump_txrx("TxCD ", DUMP_PREFIX_NONE, 32, 4, |
| 1154 | (const void *)d, sizeof(*d), false); | 1222 | (const void *)d, sizeof(*d), false); |
| 1155 | 1223 | ||
| 1156 | wil_txdesc_unmap(dev, d, ctx); | 1224 | wil_txdesc_unmap(dev, d, ctx); |
| @@ -1165,8 +1233,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
| 1165 | ndev->stats.tx_errors++; | 1233 | ndev->stats.tx_errors++; |
| 1166 | stats->tx_errors++; | 1234 | stats->tx_errors++; |
| 1167 | } | 1235 | } |
| 1168 | 1236 | wil_consume_skb(skb, d->dma.error == 0); | |
| 1169 | dev_kfree_skb_any(skb); | ||
| 1170 | } | 1237 | } |
| 1171 | memset(ctx, 0, sizeof(*ctx)); | 1238 | memset(ctx, 0, sizeof(*ctx)); |
| 1172 | /* There is no need to touch HW descriptor: | 1239 | /* There is no need to touch HW descriptor: |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 630aeb5fa7f4..d90c8aa20c15 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h | |||
| @@ -20,17 +20,15 @@ | |||
| 20 | #define BUF_SW_OWNED (1) | 20 | #define BUF_SW_OWNED (1) |
| 21 | #define BUF_HW_OWNED (0) | 21 | #define BUF_HW_OWNED (0) |
| 22 | 22 | ||
| 23 | /* size of max. Tx/Rx buffers, as supported by FW */ | 23 | /* default size of MAC Tx/Rx buffers */ |
| 24 | #define TXRX_BUF_LEN_DEFAULT (2242) | 24 | #define TXRX_BUF_LEN_DEFAULT (2048) |
| 25 | 25 | ||
| 26 | /* how many bytes to reserve for rtap header? */ | 26 | /* how many bytes to reserve for rtap header? */ |
| 27 | #define WIL6210_RTAP_SIZE (128) | 27 | #define WIL6210_RTAP_SIZE (128) |
| 28 | 28 | ||
| 29 | /* Tx/Rx path */ | 29 | /* Tx/Rx path */ |
| 30 | 30 | ||
| 31 | /* | 31 | /* Common representation of physical address in Vring */ |
| 32 | * Common representation of physical address in Vring | ||
| 33 | */ | ||
| 34 | struct vring_dma_addr { | 32 | struct vring_dma_addr { |
| 35 | __le32 addr_low; | 33 | __le32 addr_low; |
| 36 | __le16 addr_high; | 34 | __le16 addr_high; |
| @@ -49,11 +47,10 @@ static inline void wil_desc_addr_set(struct vring_dma_addr *addr, | |||
| 49 | addr->addr_high = cpu_to_le16((u16)upper_32_bits(pa)); | 47 | addr->addr_high = cpu_to_le16((u16)upper_32_bits(pa)); |
| 50 | } | 48 | } |
| 51 | 49 | ||
| 52 | /* | 50 | /* Tx descriptor - MAC part |
| 53 | * Tx descriptor - MAC part | ||
| 54 | * [dword 0] | 51 | * [dword 0] |
| 55 | * bit 0.. 9 : lifetime_expiry_value:10 | 52 | * bit 0.. 9 : lifetime_expiry_value:10 |
| 56 | * bit 10 : interrup_en:1 | 53 | * bit 10 : interrupt_en:1 |
| 57 | * bit 11 : status_en:1 | 54 | * bit 11 : status_en:1 |
| 58 | * bit 12..13 : txss_override:2 | 55 | * bit 12..13 : txss_override:2 |
| 59 | * bit 14 : timestamp_insertion:1 | 56 | * bit 14 : timestamp_insertion:1 |
| @@ -61,15 +58,12 @@ static inline void wil_desc_addr_set(struct vring_dma_addr *addr, | |||
| 61 | * bit 16..21 : reserved0:6 | 58 | * bit 16..21 : reserved0:6 |
| 62 | * bit 22..26 : mcs_index:5 | 59 | * bit 22..26 : mcs_index:5 |
| 63 | * bit 27 : mcs_en:1 | 60 | * bit 27 : mcs_en:1 |
| 64 | * bit 28..29 : reserved1:2 | 61 | * bit 28..30 : reserved1:3 |
| 65 | * bit 30 : reserved2:1 | ||
| 66 | * bit 31 : sn_preserved:1 | 62 | * bit 31 : sn_preserved:1 |
| 67 | * [dword 1] | 63 | * [dword 1] |
| 68 | * bit 0.. 3 : pkt_mode:4 | 64 | * bit 0.. 3 : pkt_mode:4 |
| 69 | * bit 4 : pkt_mode_en:1 | 65 | * bit 4 : pkt_mode_en:1 |
| 70 | * bit 5.. 7 : reserved0:3 | 66 | * bit 5..14 : reserved0:10 |
| 71 | * bit 8..13 : reserved1:6 | ||
| 72 | * bit 14 : reserved2:1 | ||
| 73 | * bit 15 : ack_policy_en:1 | 67 | * bit 15 : ack_policy_en:1 |
| 74 | * bit 16..19 : dst_index:4 | 68 | * bit 16..19 : dst_index:4 |
| 75 | * bit 20 : dst_index_en:1 | 69 | * bit 20 : dst_index_en:1 |
| @@ -80,7 +74,7 @@ static inline void wil_desc_addr_set(struct vring_dma_addr *addr, | |||
| 80 | * [dword 2] | 74 | * [dword 2] |
| 81 | * bit 0.. 7 : num_of_descriptors:8 | 75 | * bit 0.. 7 : num_of_descriptors:8 |
| 82 | * bit 8..17 : reserved:10 | 76 | * bit 8..17 : reserved:10 |
| 83 | * bit 18..19 : l2_translation_type:2 | 77 | * bit 18..19 : l2_translation_type:2 00 - bypass, 01 - 802.3, 10 - 802.11 |
| 84 | * bit 20 : snap_hdr_insertion_en:1 | 78 | * bit 20 : snap_hdr_insertion_en:1 |
| 85 | * bit 21 : vlan_removal_en:1 | 79 | * bit 21 : vlan_removal_en:1 |
| 86 | * bit 22..31 : reserved0:10 | 80 | * bit 22..31 : reserved0:10 |
| @@ -247,6 +241,46 @@ struct vring_tx_mac { | |||
| 247 | 241 | ||
| 248 | #define TX_DMA_STATUS_DU BIT(0) | 242 | #define TX_DMA_STATUS_DU BIT(0) |
| 249 | 243 | ||
| 244 | /* Tx descriptor - DMA part | ||
| 245 | * [dword 0] | ||
| 246 | * bit 0.. 7 : l4_length:8 layer 4 length | ||
| 247 | * bit 8 : cmd_eop:1 This descriptor is the last one in the packet | ||
| 248 | * bit 9 : reserved | ||
| 249 | * bit 10 : cmd_dma_it:1 immediate interrupt | ||
| 250 | * bit 11..12 : SBD - Segment Buffer Details | ||
| 251 | * 00 - Header Segment | ||
| 252 | * 01 - First Data Segment | ||
| 253 | * 10 - Medium Data Segment | ||
| 254 | * 11 - Last Data Segment | ||
| 255 | * bit 13 : TSE - TCP Segmentation Enable | ||
| 256 | * bit 14 : IIC - Directs the HW to Insert IPv4 Checksum | ||
| 257 | * bit 15 : ITC - Directs the HW to Insert TCP/UDP Checksum | ||
| 258 | * bit 16..20 : QID - The target QID that the packet should be stored | ||
| 259 | * in the MAC. | ||
| 260 | * bit 21 : PO - Pseudo header Offload: | ||
| 261 | * 0 - Use the pseudo header value from the TCP checksum field | ||
| 262 | * 1- Calculate Pseudo header Checksum | ||
| 263 | * bit 22 : NC - No UDP Checksum | ||
| 264 | * bit 23..29 : reserved | ||
| 265 | * bit 30..31 : L4T - Layer 4 Type: 00 - UDP , 10 - TCP , 10, 11 - Reserved | ||
| 266 | * If L4Len equal 0, no L4 at all | ||
| 267 | * [dword 1] | ||
| 268 | * bit 0..31 : addr_low:32 The payload buffer low address | ||
| 269 | * [dword 2] | ||
| 270 | * bit 0..15 : addr_high:16 The payload buffer high address | ||
| 271 | * bit 16..23 : ip_length:8 The IP header length for the TX IP checksum | ||
| 272 | * offload feature | ||
| 273 | * bit 24..30 : mac_length:7 | ||
| 274 | * bit 31 : ip_version:1 1 - IPv4, 0 - IPv6 | ||
| 275 | * [dword 3] | ||
| 276 | * [byte 12] error | ||
| 277 | * bit 0 2 : mac_status:3 | ||
| 278 | * bit 3 7 : reserved:5 | ||
| 279 | * [byte 13] status | ||
| 280 | * bit 0 : DU:1 Descriptor Used | ||
| 281 | * bit 1 7 : reserved:7 | ||
| 282 | * [word 7] length | ||
| 283 | */ | ||
| 250 | struct vring_tx_dma { | 284 | struct vring_tx_dma { |
| 251 | u32 d0; | 285 | u32 d0; |
| 252 | struct vring_dma_addr addr; | 286 | struct vring_dma_addr addr; |
| @@ -257,45 +291,45 @@ struct vring_tx_dma { | |||
| 257 | __le16 length; | 291 | __le16 length; |
| 258 | } __packed; | 292 | } __packed; |
| 259 | 293 | ||
| 260 | /* | 294 | /* Rx descriptor - MAC part |
| 261 | * Rx descriptor - MAC part | ||
| 262 | * [dword 0] | 295 | * [dword 0] |
| 263 | * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field | 296 | * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field |
| 264 | * bit 4.. 6 : connection_id:3 :The Source index that was found during | 297 | * bit 4.. 6 : cid:3 The Source index that was found during parsing the TA. |
| 265 | * Parsing the TA. This field is used to define the source of the packet | 298 | * This field is used to define the source of the packet |
| 266 | * bit 7 : reserved:1 | 299 | * bit 7 : reserved:1 |
| 267 | * bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero) | 300 | * bit 8.. 9 : mid:2 The MAC virtual number |
| 268 | * bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type | 301 | * bit 10..11 : frame_type:2 : The FC (b3-2) - MPDU Type |
| 269 | * (management, data, control and extension) | 302 | * (management, data, control and extension) |
| 270 | * bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype | 303 | * bit 12..15 : frame_subtype:4 : The FC (b7-4) - Frame Subtype |
| 271 | * bit 16..27 : seq_number:12 The received Sequence number field | 304 | * bit 16..27 : seq_number:12 The received Sequence number field |
| 272 | * bit 28..31 : extended:4 extended subtype | 305 | * bit 28..31 : extended:4 extended subtype |
| 273 | * [dword 1] | 306 | * [dword 1] |
| 274 | * bit 0.. 3 : reserved | 307 | * bit 0.. 3 : reserved |
| 275 | * bit 4.. 5 : key_id:2 | 308 | * bit 4.. 5 : key_id:2 |
| 276 | * bit 6 : decrypt_bypass:1 | 309 | * bit 6 : decrypt_bypass:1 |
| 277 | * bit 7 : security:1 | 310 | * bit 7 : security:1 FC (b14) |
| 278 | * bit 8.. 9 : ds_bits:2 | 311 | * bit 8.. 9 : ds_bits:2 FC (b9-8) |
| 279 | * bit 10 : a_msdu_present:1 from qos header | 312 | * bit 10 : a_msdu_present:1 QoS (b7) |
| 280 | * bit 11 : a_msdu_type:1 from qos header | 313 | * bit 11 : a_msdu_type:1 QoS (b8) |
| 281 | * bit 12 : a_mpdu:1 part of AMPDU aggregation | 314 | * bit 12 : a_mpdu:1 part of AMPDU aggregation |
| 282 | * bit 13 : broadcast:1 | 315 | * bit 13 : broadcast:1 |
| 283 | * bit 14 : mutlicast:1 | 316 | * bit 14 : mutlicast:1 |
| 284 | * bit 15 : reserved:1 | 317 | * bit 15 : reserved:1 |
| 285 | * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet | 318 | * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet |
| 286 | * is received from | 319 | * is received from |
| 287 | * bit 21..24 : mcs:4 | 320 | * bit 21..24 : mcs:4 |
| 288 | * bit 25..28 : mic_icr:4 | 321 | * bit 25..28 : mic_icr:4 this signal tells the DMA to assert an interrupt |
| 322 | * after it writes the packet | ||
| 289 | * bit 29..31 : reserved:3 | 323 | * bit 29..31 : reserved:3 |
| 290 | * [dword 2] | 324 | * [dword 2] |
| 291 | * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received | 325 | * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received |
| 292 | * bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version | 326 | * bit 3.. 4 : fc_protocol_ver:1 The FC (b1-0) - Protocol Version |
| 293 | * bit 4 : fc_order:1 The FC Control (b15) -Order | 327 | * bit 5 : fc_order:1 The FC Control (b15) -Order |
| 294 | * bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field | 328 | * bit 6.. 7 : qos_ack_policy:2 The QoS (b6-5) ack policy Field |
| 295 | * bit 8 : esop:1 The QoS (b4) ESOP field | 329 | * bit 8 : esop:1 The QoS (b4) ESOP field |
| 296 | * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field | 330 | * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field |
| 297 | * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field | 331 | * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field |
| 298 | * bit 15 : qos_ac_constraint:1 | 332 | * bit 15 : qos_ac_constraint:1 QoS (b15) |
| 299 | * bit 16..31 : pn_15_0:16 low 2 bytes of PN | 333 | * bit 16..31 : pn_15_0:16 low 2 bytes of PN |
| 300 | * [dword 3] | 334 | * [dword 3] |
| 301 | * bit 0..31 : pn_47_16:32 high 4 bytes of PN | 335 | * bit 0..31 : pn_47_16:32 high 4 bytes of PN |
| @@ -308,35 +342,46 @@ struct vring_rx_mac { | |||
| 308 | u32 pn_47_16; | 342 | u32 pn_47_16; |
| 309 | } __packed; | 343 | } __packed; |
| 310 | 344 | ||
| 311 | /* | 345 | /* Rx descriptor - DMA part |
| 312 | * Rx descriptor - DMA part | ||
| 313 | * [dword 0] | 346 | * [dword 0] |
| 314 | * bit 0.. 7 : l4_length:8 layer 4 length | 347 | * bit 0.. 7 : l4_length:8 layer 4 length. The field is only valid if |
| 315 | * bit 8.. 9 : reserved:2 | 348 | * L4I bit is set |
| 316 | * bit 10 : cmd_dma_it:1 | 349 | * bit 8 : cmd_eop:1 set to 1 |
| 350 | * bit 9 : cmd_rt:1 set to 1 | ||
| 351 | * bit 10 : cmd_dma_it:1 immediate interrupt | ||
| 317 | * bit 11..15 : reserved:5 | 352 | * bit 11..15 : reserved:5 |
| 318 | * bit 16..29 : phy_info_length:14 | 353 | * bit 16..29 : phy_info_length:14 It is valid when the PII is set. |
| 354 | * When the FFM bit is set bits 29-27 are used for for | ||
| 355 | * Flex Filter Match. Matching Index to one of the L2 | ||
| 356 | * EtherType Flex Filter | ||
| 319 | * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field | 357 | * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field |
| 358 | * 00 - UDP, 01 - TCP, 10, 11 - reserved | ||
| 320 | * [dword 1] | 359 | * [dword 1] |
| 321 | * bit 0..31 : addr_low:32 The payload buffer low address | 360 | * bit 0..31 : addr_low:32 The payload buffer low address |
| 322 | * [dword 2] | 361 | * [dword 2] |
| 323 | * bit 0..15 : addr_high:16 The payload buffer high address | 362 | * bit 0..15 : addr_high:16 The payload buffer high address |
| 324 | * bit 16..23 : ip_length:8 | 363 | * bit 16..23 : ip_length:8 The filed is valid only if the L3I bit is set |
| 325 | * bit 24..30 : mac_length:7 | 364 | * bit 24..30 : mac_length:7 |
| 326 | * bit 31 : ip_version:1 | 365 | * bit 31 : ip_version:1 1 - IPv4, 0 - IPv6 |
| 327 | * [dword 3] | 366 | * [dword 3] |
| 328 | * [byte 12] error | 367 | * [byte 12] error |
| 368 | * bit 0 : FCS:1 | ||
| 369 | * bit 1 : MIC:1 | ||
| 370 | * bit 2 : Key miss:1 | ||
| 371 | * bit 3 : Replay:1 | ||
| 372 | * bit 4 : L3:1 IPv4 checksum | ||
| 373 | * bit 5 : L4:1 TCP/UDP checksum | ||
| 374 | * bit 6 7 : reserved:2 | ||
| 329 | * [byte 13] status | 375 | * [byte 13] status |
| 330 | * bit 0 : du:1 | 376 | * bit 0 : DU:1 Descriptor Used |
| 331 | * bit 1 : eop:1 | 377 | * bit 1 : EOP:1 The descriptor indicates the End of Packet |
| 332 | * bit 2 : error:1 | 378 | * bit 2 : error:1 |
| 333 | * bit 3 : mi:1 | 379 | * bit 3 : MI:1 MAC Interrupt is asserted (according to parser decision) |
| 334 | * bit 4 : l3_identified:1 | 380 | * bit 4 : L3I:1 L3 identified and checksum calculated |
| 335 | * bit 5 : l4_identified:1 | 381 | * bit 5 : L4I:1 L4 identified and checksum calculated |
| 336 | * bit 6 : phy_info_included:1 | 382 | * bit 6 : PII:1 PHY Info Included in the packet |
| 337 | * bit 7 : reserved:1 | 383 | * bit 7 : FFM:1 EtherType Flex Filter Match |
| 338 | * [word 7] length | 384 | * [word 7] length |
| 339 | * | ||
| 340 | */ | 385 | */ |
| 341 | 386 | ||
| 342 | #define RX_DMA_D0_CMD_DMA_IT BIT(10) | 387 | #define RX_DMA_D0_CMD_DMA_IT BIT(10) |
| @@ -349,9 +394,9 @@ struct vring_rx_mac { | |||
| 349 | #define RX_DMA_STATUS_DU BIT(0) | 394 | #define RX_DMA_STATUS_DU BIT(0) |
| 350 | #define RX_DMA_STATUS_ERROR BIT(2) | 395 | #define RX_DMA_STATUS_ERROR BIT(2) |
| 351 | 396 | ||
| 352 | #define RX_DMA_STATUS_L3_IDENT BIT(4) | 397 | #define RX_DMA_STATUS_L3I BIT(4) |
| 353 | #define RX_DMA_STATUS_L4_IDENT BIT(5) | 398 | #define RX_DMA_STATUS_L4I BIT(5) |
| 354 | #define RX_DMA_STATUS_PHY_INFO BIT(6) | 399 | #define RX_DMA_STATUS_PHY_INFO BIT(6) |
| 355 | 400 | ||
| 356 | struct vring_rx_dma { | 401 | struct vring_rx_dma { |
| 357 | u32 d0; | 402 | u32 d0; |
| @@ -423,6 +468,11 @@ static inline int wil_rxdesc_mcs(struct vring_rx_desc *d) | |||
| 423 | return WIL_GET_BITS(d->mac.d1, 21, 24); | 468 | return WIL_GET_BITS(d->mac.d1, 21, 24); |
| 424 | } | 469 | } |
| 425 | 470 | ||
| 471 | static inline int wil_rxdesc_mcast(struct vring_rx_desc *d) | ||
| 472 | { | ||
| 473 | return WIL_GET_BITS(d->mac.d1, 13, 14); | ||
| 474 | } | ||
| 475 | |||
| 426 | static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d) | 476 | static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d) |
| 427 | { | 477 | { |
| 428 | return WIL_GET_BITS(d->dma.d0, 16, 29); | 478 | return WIL_GET_BITS(d->dma.d0, 16, 29); |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index c6ec5b99ac7d..94611568fc9a 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. |
| 3 | * | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -25,19 +25,14 @@ | |||
| 25 | 25 | ||
| 26 | extern bool no_fw_recovery; | 26 | extern bool no_fw_recovery; |
| 27 | extern unsigned int mtu_max; | 27 | extern unsigned int mtu_max; |
| 28 | extern unsigned short rx_ring_overflow_thrsh; | ||
| 29 | extern int agg_wsize; | ||
| 28 | 30 | ||
| 29 | #define WIL_NAME "wil6210" | 31 | #define WIL_NAME "wil6210" |
| 30 | #define WIL_FW_NAME "wil6210.fw" | 32 | #define WIL_FW_NAME "wil6210.fw" |
| 31 | 33 | ||
| 32 | #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */ | 34 | #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */ |
| 33 | 35 | ||
| 34 | struct wil_board { | ||
| 35 | int board; | ||
| 36 | #define WIL_BOARD_MARLON (1) | ||
| 37 | #define WIL_BOARD_SPARROW (2) | ||
| 38 | const char * const name; | ||
| 39 | }; | ||
| 40 | |||
| 41 | /** | 36 | /** |
| 42 | * extract bits [@b0:@b1] (inclusive) from the value @x | 37 | * extract bits [@b0:@b1] (inclusive) from the value @x |
| 43 | * it should be @b0 <= @b1, or result is incorrect | 38 | * it should be @b0 <= @b1, or result is incorrect |
| @@ -49,21 +44,50 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
| 49 | 44 | ||
| 50 | #define WIL6210_MEM_SIZE (2*1024*1024UL) | 45 | #define WIL6210_MEM_SIZE (2*1024*1024UL) |
| 51 | 46 | ||
| 52 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (9) | 47 | #define WIL_TX_Q_LEN_DEFAULT (4000) |
| 53 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (9) | 48 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) |
| 49 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (10) | ||
| 54 | /* limit ring size in range [32..32k] */ | 50 | /* limit ring size in range [32..32k] */ |
| 55 | #define WIL_RING_SIZE_ORDER_MIN (5) | 51 | #define WIL_RING_SIZE_ORDER_MIN (5) |
| 56 | #define WIL_RING_SIZE_ORDER_MAX (15) | 52 | #define WIL_RING_SIZE_ORDER_MAX (15) |
| 57 | #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ | 53 | #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ |
| 58 | #define WIL6210_MAX_CID (8) /* HW limit */ | 54 | #define WIL6210_MAX_CID (8) /* HW limit */ |
| 59 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ | 55 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ |
| 56 | #define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */ | ||
| 57 | #define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */ | ||
| 58 | /* Hardware offload block adds the following: | ||
| 59 | * 26 bytes - 3-address QoS data header | ||
| 60 | * 8 bytes - IV + EIV (for GCMP) | ||
| 61 | * 8 bytes - SNAP | ||
| 62 | * 16 bytes - MIC (for GCMP) | ||
| 63 | * 4 bytes - CRC | ||
| 64 | */ | ||
| 65 | #define WIL_MAX_MPDU_OVERHEAD (62) | ||
| 66 | |||
| 67 | /* Calculate MAC buffer size for the firmware. It includes all overhead, | ||
| 68 | * as it will go over the air, and need to be 8 byte aligned | ||
| 69 | */ | ||
| 70 | static inline u32 wil_mtu2macbuf(u32 mtu) | ||
| 71 | { | ||
| 72 | return ALIGN(mtu + WIL_MAX_MPDU_OVERHEAD, 8); | ||
| 73 | } | ||
| 74 | |||
| 75 | /* MTU for Ethernet need to take into account 8-byte SNAP header | ||
| 76 | * to be added when encapsulating Ethernet frame into 802.11 | ||
| 77 | */ | ||
| 78 | #define WIL_MAX_ETH_MTU (IEEE80211_MAX_DATA_LEN_DMG - 8) | ||
| 60 | /* Max supported by wil6210 value for interrupt threshold is 5sec. */ | 79 | /* Max supported by wil6210 value for interrupt threshold is 5sec. */ |
| 61 | #define WIL6210_ITR_TRSH_MAX (5000000) | 80 | #define WIL6210_ITR_TRSH_MAX (5000000) |
| 62 | #define WIL6210_ITR_TRSH_DEFAULT (300) /* usec */ | 81 | #define WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT (13) /* usec */ |
| 82 | #define WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT (13) /* usec */ | ||
| 83 | #define WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ | ||
| 84 | #define WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT (500) /* usec */ | ||
| 63 | #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ | 85 | #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ |
| 64 | #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) | 86 | #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) |
| 65 | #define WIL6210_SCAN_TO msecs_to_jiffies(10000) | 87 | #define WIL6210_SCAN_TO msecs_to_jiffies(10000) |
| 66 | 88 | #define WIL6210_RX_HIGH_TRSH_INIT (0) | |
| 89 | #define WIL6210_RX_HIGH_TRSH_DEFAULT \ | ||
| 90 | (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) | ||
| 67 | /* Hardware definitions begin */ | 91 | /* Hardware definitions begin */ |
| 68 | 92 | ||
| 69 | /* | 93 | /* |
| @@ -135,7 +159,7 @@ struct RGF_ICR { | |||
| 135 | #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) | 159 | #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) |
| 136 | #define BIT_DMA_EP_MISC_ICR_FW_INT(n) BIT(28+n) /* n = [0..3] */ | 160 | #define BIT_DMA_EP_MISC_ICR_FW_INT(n) BIT(28+n) /* n = [0..3] */ |
| 137 | 161 | ||
| 138 | /* Interrupt moderation control */ | 162 | /* Legacy interrupt moderation control (before Sparrow v2)*/ |
| 139 | #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) | 163 | #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) |
| 140 | #define RGF_DMA_ITR_CNT_DATA (0x881c60) | 164 | #define RGF_DMA_ITR_CNT_DATA (0x881c60) |
| 141 | #define RGF_DMA_ITR_CNT_CRL (0x881c64) | 165 | #define RGF_DMA_ITR_CNT_CRL (0x881c64) |
| @@ -145,6 +169,46 @@ struct RGF_ICR { | |||
| 145 | #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) | 169 | #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) |
| 146 | #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) | 170 | #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) |
| 147 | 171 | ||
| 172 | /* New (sparrow v2+) interrupt moderation control */ | ||
| 173 | #define RGF_DMA_ITR_TX_DESQ_NO_MOD (0x881d40) | ||
| 174 | #define RGF_DMA_ITR_TX_CNT_TRSH (0x881d34) | ||
| 175 | #define RGF_DMA_ITR_TX_CNT_DATA (0x881d38) | ||
| 176 | #define RGF_DMA_ITR_TX_CNT_CTL (0x881d3c) | ||
| 177 | #define BIT_DMA_ITR_TX_CNT_CTL_EN BIT(0) | ||
| 178 | #define BIT_DMA_ITR_TX_CNT_CTL_EXT_TIC_SEL BIT(1) | ||
| 179 | #define BIT_DMA_ITR_TX_CNT_CTL_FOREVER BIT(2) | ||
| 180 | #define BIT_DMA_ITR_TX_CNT_CTL_CLR BIT(3) | ||
| 181 | #define BIT_DMA_ITR_TX_CNT_CTL_REACHED_TRESH BIT(4) | ||
| 182 | #define BIT_DMA_ITR_TX_CNT_CTL_CROSS_EN BIT(5) | ||
| 183 | #define BIT_DMA_ITR_TX_CNT_CTL_FREE_RUNNIG BIT(6) | ||
| 184 | #define RGF_DMA_ITR_TX_IDL_CNT_TRSH (0x881d60) | ||
| 185 | #define RGF_DMA_ITR_TX_IDL_CNT_DATA (0x881d64) | ||
| 186 | #define RGF_DMA_ITR_TX_IDL_CNT_CTL (0x881d68) | ||
| 187 | #define BIT_DMA_ITR_TX_IDL_CNT_CTL_EN BIT(0) | ||
| 188 | #define BIT_DMA_ITR_TX_IDL_CNT_CTL_EXT_TIC_SEL BIT(1) | ||
| 189 | #define BIT_DMA_ITR_TX_IDL_CNT_CTL_FOREVER BIT(2) | ||
| 190 | #define BIT_DMA_ITR_TX_IDL_CNT_CTL_CLR BIT(3) | ||
| 191 | #define BIT_DMA_ITR_TX_IDL_CNT_CTL_REACHED_TRESH BIT(4) | ||
| 192 | #define RGF_DMA_ITR_RX_DESQ_NO_MOD (0x881d50) | ||
| 193 | #define RGF_DMA_ITR_RX_CNT_TRSH (0x881d44) | ||
| 194 | #define RGF_DMA_ITR_RX_CNT_DATA (0x881d48) | ||
| 195 | #define RGF_DMA_ITR_RX_CNT_CTL (0x881d4c) | ||
| 196 | #define BIT_DMA_ITR_RX_CNT_CTL_EN BIT(0) | ||
| 197 | #define BIT_DMA_ITR_RX_CNT_CTL_EXT_TIC_SEL BIT(1) | ||
| 198 | #define BIT_DMA_ITR_RX_CNT_CTL_FOREVER BIT(2) | ||
| 199 | #define BIT_DMA_ITR_RX_CNT_CTL_CLR BIT(3) | ||
| 200 | #define BIT_DMA_ITR_RX_CNT_CTL_REACHED_TRESH BIT(4) | ||
| 201 | #define BIT_DMA_ITR_RX_CNT_CTL_CROSS_EN BIT(5) | ||
| 202 | #define BIT_DMA_ITR_RX_CNT_CTL_FREE_RUNNIG BIT(6) | ||
| 203 | #define RGF_DMA_ITR_RX_IDL_CNT_TRSH (0x881d54) | ||
| 204 | #define RGF_DMA_ITR_RX_IDL_CNT_DATA (0x881d58) | ||
| 205 | #define RGF_DMA_ITR_RX_IDL_CNT_CTL (0x881d5c) | ||
| 206 | #define BIT_DMA_ITR_RX_IDL_CNT_CTL_EN BIT(0) | ||
| 207 | #define BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL BIT(1) | ||
| 208 | #define BIT_DMA_ITR_RX_IDL_CNT_CTL_FOREVER BIT(2) | ||
| 209 | #define BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR BIT(3) | ||
| 210 | #define BIT_DMA_ITR_RX_IDL_CNT_CTL_REACHED_TRESH BIT(4) | ||
| 211 | |||
| 148 | #define RGF_DMA_PSEUDO_CAUSE (0x881c68) | 212 | #define RGF_DMA_PSEUDO_CAUSE (0x881c68) |
| 149 | #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) | 213 | #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) |
| 150 | #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) | 214 | #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) |
| @@ -164,6 +228,20 @@ struct RGF_ICR { | |||
| 164 | #define RGF_CAF_PLL_LOCK_STATUS (0x88afec) | 228 | #define RGF_CAF_PLL_LOCK_STATUS (0x88afec) |
| 165 | #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) | 229 | #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) |
| 166 | 230 | ||
| 231 | #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ | ||
| 232 | #define JTAG_DEV_ID_MARLON_B0 (0x0612072f) | ||
| 233 | #define JTAG_DEV_ID_SPARROW_A0 (0x0632072f) | ||
| 234 | #define JTAG_DEV_ID_SPARROW_A1 (0x1632072f) | ||
| 235 | #define JTAG_DEV_ID_SPARROW_B0 (0x2632072f) | ||
| 236 | |||
| 237 | enum { | ||
| 238 | HW_VER_UNKNOWN, | ||
| 239 | HW_VER_MARLON_B0, /* JTAG_DEV_ID_MARLON_B0 */ | ||
| 240 | HW_VER_SPARROW_A0, /* JTAG_DEV_ID_SPARROW_A0 */ | ||
| 241 | HW_VER_SPARROW_A1, /* JTAG_DEV_ID_SPARROW_A1 */ | ||
| 242 | HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */ | ||
| 243 | }; | ||
| 244 | |||
| 167 | /* popular locations */ | 245 | /* popular locations */ |
| 168 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) | 246 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) |
| 169 | #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ | 247 | #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ |
| @@ -303,6 +381,11 @@ struct vring { | |||
| 303 | struct vring_tx_data { | 381 | struct vring_tx_data { |
| 304 | int enabled; | 382 | int enabled; |
| 305 | cycles_t idle, last_idle, begin; | 383 | cycles_t idle, last_idle, begin; |
| 384 | u8 agg_wsize; /* agreed aggregation window, 0 - no agg */ | ||
| 385 | u16 agg_timeout; | ||
| 386 | u8 agg_amsdu; | ||
| 387 | bool addba_in_progress; /* if set, agg_xxx is for request in progress */ | ||
| 388 | spinlock_t lock; | ||
| 306 | }; | 389 | }; |
| 307 | 390 | ||
| 308 | enum { /* for wil6210_priv.status */ | 391 | enum { /* for wil6210_priv.status */ |
| @@ -313,6 +396,7 @@ enum { /* for wil6210_priv.status */ | |||
| 313 | wil_status_reset_done, | 396 | wil_status_reset_done, |
| 314 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | 397 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ |
| 315 | wil_status_napi_en, /* NAPI enabled protected by wil->mutex */ | 398 | wil_status_napi_en, /* NAPI enabled protected by wil->mutex */ |
| 399 | wil_status_last /* keep last */ | ||
| 316 | }; | 400 | }; |
| 317 | 401 | ||
| 318 | struct pci_dev; | 402 | struct pci_dev; |
| @@ -397,15 +481,46 @@ enum { | |||
| 397 | fw_recovery_running = 2, | 481 | fw_recovery_running = 2, |
| 398 | }; | 482 | }; |
| 399 | 483 | ||
| 484 | enum { | ||
| 485 | hw_capability_reset_v2 = 0, | ||
| 486 | hw_capability_advanced_itr_moderation = 1, | ||
| 487 | hw_capability_last | ||
| 488 | }; | ||
| 489 | |||
| 490 | struct wil_back_rx { | ||
| 491 | struct list_head list; | ||
| 492 | /* request params, converted to CPU byte order - what we asked for */ | ||
| 493 | u8 cidxtid; | ||
| 494 | u8 dialog_token; | ||
| 495 | u16 ba_param_set; | ||
| 496 | u16 ba_timeout; | ||
| 497 | u16 ba_seq_ctrl; | ||
| 498 | }; | ||
| 499 | |||
| 500 | struct wil_back_tx { | ||
| 501 | struct list_head list; | ||
| 502 | /* request params, converted to CPU byte order - what we asked for */ | ||
| 503 | u8 ringid; | ||
| 504 | u8 agg_wsize; | ||
| 505 | u16 agg_timeout; | ||
| 506 | }; | ||
| 507 | |||
| 508 | struct wil_probe_client_req { | ||
| 509 | struct list_head list; | ||
| 510 | u64 cookie; | ||
| 511 | u8 cid; | ||
| 512 | }; | ||
| 513 | |||
| 400 | struct wil6210_priv { | 514 | struct wil6210_priv { |
| 401 | struct pci_dev *pdev; | 515 | struct pci_dev *pdev; |
| 402 | int n_msi; | 516 | int n_msi; |
| 403 | struct wireless_dev *wdev; | 517 | struct wireless_dev *wdev; |
| 404 | void __iomem *csr; | 518 | void __iomem *csr; |
| 405 | ulong status; | 519 | DECLARE_BITMAP(status, wil_status_last); |
| 406 | u32 fw_version; | 520 | u32 fw_version; |
| 407 | u32 hw_version; | 521 | u32 hw_version; |
| 408 | struct wil_board *board; | 522 | const char *hw_name; |
| 523 | DECLARE_BITMAP(hw_capabilities, hw_capability_last); | ||
| 409 | u8 n_mids; /* number of additional MIDs as reported by FW */ | 524 | u8 n_mids; /* number of additional MIDs as reported by FW */ |
| 410 | u32 recovery_count; /* num of FW recovery attempts in a short time */ | 525 | u32 recovery_count; /* num of FW recovery attempts in a short time */ |
| 411 | u32 recovery_state; /* FW recovery state machine */ | 526 | u32 recovery_state; /* FW recovery state machine */ |
| @@ -415,7 +530,11 @@ struct wil6210_priv { | |||
| 415 | u32 monitor_flags; | 530 | u32 monitor_flags; |
| 416 | u32 secure_pcp; /* create secure PCP? */ | 531 | u32 secure_pcp; /* create secure PCP? */ |
| 417 | int sinfo_gen; | 532 | int sinfo_gen; |
| 418 | u32 itr_trsh; | 533 | /* interrupt moderation */ |
| 534 | u32 tx_max_burst_duration; | ||
| 535 | u32 tx_interframe_timeout; | ||
| 536 | u32 rx_max_burst_duration; | ||
| 537 | u32 rx_interframe_timeout; | ||
| 419 | /* cached ISR registers */ | 538 | /* cached ISR registers */ |
| 420 | u32 isr_misc; | 539 | u32 isr_misc; |
| 421 | /* mailbox related */ | 540 | /* mailbox related */ |
| @@ -429,7 +548,7 @@ struct wil6210_priv { | |||
| 429 | u16 reply_size; | 548 | u16 reply_size; |
| 430 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | 549 | struct workqueue_struct *wmi_wq; /* for deferred calls */ |
| 431 | struct work_struct wmi_event_worker; | 550 | struct work_struct wmi_event_worker; |
| 432 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ | 551 | struct workqueue_struct *wq_service; |
| 433 | struct work_struct connect_worker; | 552 | struct work_struct connect_worker; |
| 434 | struct work_struct disconnect_worker; | 553 | struct work_struct disconnect_worker; |
| 435 | struct work_struct fw_error_worker; /* for FW error recovery */ | 554 | struct work_struct fw_error_worker; /* for FW error recovery */ |
| @@ -445,6 +564,17 @@ struct wil6210_priv { | |||
| 445 | spinlock_t wmi_ev_lock; | 564 | spinlock_t wmi_ev_lock; |
| 446 | struct napi_struct napi_rx; | 565 | struct napi_struct napi_rx; |
| 447 | struct napi_struct napi_tx; | 566 | struct napi_struct napi_tx; |
| 567 | /* BACK */ | ||
| 568 | struct list_head back_rx_pending; | ||
| 569 | struct mutex back_rx_mutex; /* protect @back_rx_pending */ | ||
| 570 | struct work_struct back_rx_worker; | ||
| 571 | struct list_head back_tx_pending; | ||
| 572 | struct mutex back_tx_mutex; /* protect @back_tx_pending */ | ||
| 573 | struct work_struct back_tx_worker; | ||
| 574 | /* keep alive */ | ||
| 575 | struct list_head probe_client_pending; | ||
| 576 | struct mutex probe_client_mutex; /* protect @probe_client_pending */ | ||
| 577 | struct work_struct probe_client_worker; | ||
| 448 | /* DMA related */ | 578 | /* DMA related */ |
| 449 | struct vring vring_rx; | 579 | struct vring vring_rx; |
| 450 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; | 580 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; |
| @@ -529,11 +659,8 @@ void wil_if_remove(struct wil6210_priv *wil); | |||
| 529 | int wil_priv_init(struct wil6210_priv *wil); | 659 | int wil_priv_init(struct wil6210_priv *wil); |
| 530 | void wil_priv_deinit(struct wil6210_priv *wil); | 660 | void wil_priv_deinit(struct wil6210_priv *wil); |
| 531 | int wil_reset(struct wil6210_priv *wil); | 661 | int wil_reset(struct wil6210_priv *wil); |
| 532 | void wil_set_itr_trsh(struct wil6210_priv *wil); | ||
| 533 | void wil_fw_error_recovery(struct wil6210_priv *wil); | 662 | void wil_fw_error_recovery(struct wil6210_priv *wil); |
| 534 | void wil_set_recovery_state(struct wil6210_priv *wil, int state); | 663 | void wil_set_recovery_state(struct wil6210_priv *wil, int state); |
| 535 | void wil_link_on(struct wil6210_priv *wil); | ||
| 536 | void wil_link_off(struct wil6210_priv *wil); | ||
| 537 | int wil_up(struct wil6210_priv *wil); | 664 | int wil_up(struct wil6210_priv *wil); |
| 538 | int __wil_up(struct wil6210_priv *wil); | 665 | int __wil_up(struct wil6210_priv *wil); |
| 539 | int wil_down(struct wil6210_priv *wil); | 666 | int wil_down(struct wil6210_priv *wil); |
| @@ -567,12 +694,26 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel); | |||
| 567 | int wmi_rxon(struct wil6210_priv *wil, bool on); | 694 | int wmi_rxon(struct wil6210_priv *wil, bool on); |
| 568 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); | 695 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); |
| 569 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason); | 696 | int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason); |
| 697 | int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); | ||
| 698 | int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); | ||
| 699 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); | ||
| 700 | int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | ||
| 701 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout); | ||
| 702 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, | ||
| 703 | u8 dialog_token, __le16 ba_param_set, | ||
| 704 | __le16 ba_timeout, __le16 ba_seq_ctrl); | ||
| 705 | void wil_back_rx_worker(struct work_struct *work); | ||
| 706 | void wil_back_rx_flush(struct wil6210_priv *wil); | ||
| 707 | int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); | ||
| 708 | void wil_back_tx_worker(struct work_struct *work); | ||
| 709 | void wil_back_tx_flush(struct wil6210_priv *wil); | ||
| 570 | 710 | ||
| 571 | void wil6210_clear_irq(struct wil6210_priv *wil); | 711 | void wil6210_clear_irq(struct wil6210_priv *wil); |
| 572 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); | 712 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); |
| 573 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); | 713 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); |
| 574 | void wil_mask_irq(struct wil6210_priv *wil); | 714 | void wil_mask_irq(struct wil6210_priv *wil); |
| 575 | void wil_unmask_irq(struct wil6210_priv *wil); | 715 | void wil_unmask_irq(struct wil6210_priv *wil); |
| 716 | void wil_configure_interrupt_moderation(struct wil6210_priv *wil); | ||
| 576 | void wil_disable_irq(struct wil6210_priv *wil); | 717 | void wil_disable_irq(struct wil6210_priv *wil); |
| 577 | void wil_enable_irq(struct wil6210_priv *wil); | 718 | void wil_enable_irq(struct wil6210_priv *wil); |
| 578 | int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 719 | int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
| @@ -592,6 +733,8 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); | |||
| 592 | int wmi_pcp_stop(struct wil6210_priv *wil); | 733 | int wmi_pcp_stop(struct wil6210_priv *wil); |
| 593 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | 734 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, |
| 594 | u16 reason_code, bool from_event); | 735 | u16 reason_code, bool from_event); |
| 736 | void wil_probe_client_flush(struct wil6210_priv *wil); | ||
| 737 | void wil_probe_client_worker(struct work_struct *work); | ||
| 595 | 738 | ||
| 596 | int wil_rx_init(struct wil6210_priv *wil, u16 size); | 739 | int wil_rx_init(struct wil6210_priv *wil, u16 size); |
| 597 | void wil_rx_fini(struct wil6210_priv *wil); | 740 | void wil_rx_fini(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.c b/drivers/net/wireless/ath/wil6210/wil_platform.c index 8f1d78f8a74d..976a071ba74e 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.c +++ b/drivers/net/wireless/ath/wil6210/wil_platform.c | |||
| @@ -17,10 +17,6 @@ | |||
| 17 | #include "linux/device.h" | 17 | #include "linux/device.h" |
| 18 | #include "wil_platform.h" | 18 | #include "wil_platform.h" |
| 19 | 19 | ||
| 20 | #ifdef CONFIG_WIL6210_PLATFORM_MSM | ||
| 21 | #include "wil_platform_msm.h" | ||
| 22 | #endif | ||
| 23 | |||
| 24 | /** | 20 | /** |
| 25 | * wil_platform_init() - wil6210 platform module init | 21 | * wil_platform_init() - wil6210 platform module init |
| 26 | * | 22 | * |
| @@ -37,13 +33,7 @@ void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops) | |||
| 37 | return NULL; | 33 | return NULL; |
| 38 | } | 34 | } |
| 39 | 35 | ||
| 40 | #ifdef CONFIG_WIL6210_PLATFORM_MSM | 36 | /* platform specific init functions should be called here */ |
| 41 | handle = wil_platform_msm_init(dev, ops); | ||
| 42 | if (handle) | ||
| 43 | return handle; | ||
| 44 | #endif | ||
| 45 | |||
| 46 | /* other platform specific init functions should be called here */ | ||
| 47 | 37 | ||
| 48 | return handle; | 38 | return handle; |
| 49 | } | 39 | } |
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform_msm.c b/drivers/net/wireless/ath/wil6210/wil_platform_msm.c deleted file mode 100644 index b354a743240d..000000000000 --- a/drivers/net/wireless/ath/wil6210/wil_platform_msm.c +++ /dev/null | |||
| @@ -1,257 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/msm-bus.h> | ||
| 20 | |||
| 21 | #include "wil_platform.h" | ||
| 22 | #include "wil_platform_msm.h" | ||
| 23 | |||
| 24 | /** | ||
| 25 | * struct wil_platform_msm - wil6210 msm platform module info | ||
| 26 | * | ||
| 27 | * @dev: device object | ||
| 28 | * @msm_bus_handle: handle for using msm_bus API | ||
| 29 | * @pdata: bus scale info retrieved from DT | ||
| 30 | */ | ||
| 31 | struct wil_platform_msm { | ||
| 32 | struct device *dev; | ||
| 33 | uint32_t msm_bus_handle; | ||
| 34 | struct msm_bus_scale_pdata *pdata; | ||
| 35 | }; | ||
| 36 | |||
| 37 | #define KBTOB(a) (a * 1000ULL) | ||
| 38 | |||
| 39 | /** | ||
| 40 | * wil_platform_get_pdata() - Generate bus client data from device tree | ||
| 41 | * provided by clients. | ||
| 42 | * | ||
| 43 | * dev: device object | ||
| 44 | * of_node: Device tree node to extract information from | ||
| 45 | * | ||
| 46 | * The function returns a valid pointer to the allocated bus-scale-pdata | ||
| 47 | * if the vectors were correctly read from the client's device node. | ||
| 48 | * Any error in reading or parsing the device node will return NULL | ||
| 49 | * to the caller. | ||
| 50 | */ | ||
| 51 | static struct msm_bus_scale_pdata *wil_platform_get_pdata( | ||
| 52 | struct device *dev, | ||
| 53 | struct device_node *of_node) | ||
| 54 | { | ||
| 55 | struct msm_bus_scale_pdata *pdata; | ||
| 56 | struct msm_bus_paths *usecase; | ||
| 57 | int i, j, ret, len; | ||
| 58 | unsigned int num_usecases, num_paths, mem_size; | ||
| 59 | const uint32_t *vec_arr; | ||
| 60 | struct msm_bus_vectors *vectors; | ||
| 61 | |||
| 62 | /* first read num_usecases and num_paths so we can calculate | ||
| 63 | * amount of memory to allocate | ||
| 64 | */ | ||
| 65 | ret = of_property_read_u32(of_node, "qcom,msm-bus,num-cases", | ||
| 66 | &num_usecases); | ||
| 67 | if (ret) { | ||
| 68 | dev_err(dev, "Error: num-usecases not found\n"); | ||
| 69 | return NULL; | ||
| 70 | } | ||
| 71 | |||
| 72 | ret = of_property_read_u32(of_node, "qcom,msm-bus,num-paths", | ||
| 73 | &num_paths); | ||
| 74 | if (ret) { | ||
| 75 | dev_err(dev, "Error: num_paths not found\n"); | ||
| 76 | return NULL; | ||
| 77 | } | ||
| 78 | |||
| 79 | /* pdata memory layout: | ||
| 80 | * msm_bus_scale_pdata | ||
| 81 | * msm_bus_paths[num_usecases] | ||
| 82 | * msm_bus_vectors[num_usecases][num_paths] | ||
| 83 | */ | ||
| 84 | mem_size = sizeof(struct msm_bus_scale_pdata) + | ||
| 85 | sizeof(struct msm_bus_paths) * num_usecases + | ||
| 86 | sizeof(struct msm_bus_vectors) * num_usecases * num_paths; | ||
| 87 | |||
| 88 | pdata = kzalloc(mem_size, GFP_KERNEL); | ||
| 89 | if (!pdata) | ||
| 90 | return NULL; | ||
| 91 | |||
| 92 | ret = of_property_read_string(of_node, "qcom,msm-bus,name", | ||
| 93 | &pdata->name); | ||
| 94 | if (ret) { | ||
| 95 | dev_err(dev, "Error: Client name not found\n"); | ||
| 96 | goto err; | ||
| 97 | } | ||
| 98 | |||
| 99 | if (of_property_read_bool(of_node, "qcom,msm-bus,active-only")) { | ||
| 100 | pdata->active_only = 1; | ||
| 101 | } else { | ||
| 102 | dev_info(dev, "active_only flag absent.\n"); | ||
| 103 | dev_info(dev, "Using dual context by default\n"); | ||
| 104 | } | ||
| 105 | |||
| 106 | pdata->num_usecases = num_usecases; | ||
| 107 | pdata->usecase = (struct msm_bus_paths *)(pdata + 1); | ||
| 108 | |||
| 109 | vec_arr = of_get_property(of_node, "qcom,msm-bus,vectors-KBps", &len); | ||
| 110 | if (vec_arr == NULL) { | ||
| 111 | dev_err(dev, "Error: Vector array not found\n"); | ||
| 112 | goto err; | ||
| 113 | } | ||
| 114 | |||
| 115 | if (len != num_usecases * num_paths * sizeof(uint32_t) * 4) { | ||
| 116 | dev_err(dev, "Error: Length-error on getting vectors\n"); | ||
| 117 | goto err; | ||
| 118 | } | ||
| 119 | |||
| 120 | vectors = (struct msm_bus_vectors *)(pdata->usecase + num_usecases); | ||
| 121 | for (i = 0; i < num_usecases; i++) { | ||
| 122 | usecase = &pdata->usecase[i]; | ||
| 123 | usecase->num_paths = num_paths; | ||
| 124 | usecase->vectors = &vectors[i]; | ||
| 125 | |||
| 126 | for (j = 0; j < num_paths; j++) { | ||
| 127 | int index = ((i * num_paths) + j) * 4; | ||
| 128 | |||
| 129 | usecase->vectors[j].src = be32_to_cpu(vec_arr[index]); | ||
| 130 | usecase->vectors[j].dst = | ||
| 131 | be32_to_cpu(vec_arr[index + 1]); | ||
| 132 | usecase->vectors[j].ab = (uint64_t) | ||
| 133 | KBTOB(be32_to_cpu(vec_arr[index + 2])); | ||
| 134 | usecase->vectors[j].ib = (uint64_t) | ||
| 135 | KBTOB(be32_to_cpu(vec_arr[index + 3])); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | return pdata; | ||
| 140 | |||
| 141 | err: | ||
| 142 | kfree(pdata); | ||
| 143 | |||
| 144 | return NULL; | ||
| 145 | } | ||
| 146 | |||
| 147 | /* wil_platform API (callbacks) */ | ||
| 148 | |||
| 149 | static int wil_platform_bus_request(void *handle, | ||
| 150 | uint32_t kbps /* KBytes/Sec */) | ||
| 151 | { | ||
| 152 | int rc, i; | ||
| 153 | struct wil_platform_msm *msm = (struct wil_platform_msm *)handle; | ||
| 154 | int vote = 0; /* vote 0 in case requested kbps cannot be satisfied */ | ||
| 155 | struct msm_bus_paths *usecase; | ||
| 156 | uint32_t usecase_kbps; | ||
| 157 | uint32_t min_kbps = ~0; | ||
| 158 | |||
| 159 | /* find the lowest usecase that is bigger than requested kbps */ | ||
| 160 | for (i = 0; i < msm->pdata->num_usecases; i++) { | ||
| 161 | usecase = &msm->pdata->usecase[i]; | ||
| 162 | /* assume we have single path (vectors[0]). If we ever | ||
| 163 | * have multiple paths, need to define the behavior */ | ||
| 164 | usecase_kbps = div64_u64(usecase->vectors[0].ib, 1000); | ||
| 165 | if (usecase_kbps >= kbps && usecase_kbps < min_kbps) { | ||
| 166 | min_kbps = usecase_kbps; | ||
| 167 | vote = i; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | rc = msm_bus_scale_client_update_request(msm->msm_bus_handle, vote); | ||
| 172 | if (rc) | ||
| 173 | dev_err(msm->dev, "Failed msm_bus voting. kbps=%d vote=%d, rc=%d\n", | ||
| 174 | kbps, vote, rc); | ||
| 175 | else | ||
| 176 | /* TOOD: remove */ | ||
| 177 | dev_info(msm->dev, "msm_bus_scale_client_update_request succeeded. kbps=%d vote=%d\n", | ||
| 178 | kbps, vote); | ||
| 179 | |||
| 180 | return rc; | ||
| 181 | } | ||
| 182 | |||
| 183 | static void wil_platform_uninit(void *handle) | ||
| 184 | { | ||
| 185 | struct wil_platform_msm *msm = (struct wil_platform_msm *)handle; | ||
| 186 | |||
| 187 | dev_info(msm->dev, "wil_platform_uninit\n"); | ||
| 188 | |||
| 189 | if (msm->msm_bus_handle) | ||
| 190 | msm_bus_scale_unregister_client(msm->msm_bus_handle); | ||
| 191 | |||
| 192 | kfree(msm->pdata); | ||
| 193 | kfree(msm); | ||
| 194 | } | ||
| 195 | |||
| 196 | static int wil_platform_msm_bus_register(struct wil_platform_msm *msm, | ||
| 197 | struct device_node *node) | ||
| 198 | { | ||
| 199 | msm->pdata = wil_platform_get_pdata(msm->dev, node); | ||
| 200 | if (!msm->pdata) { | ||
| 201 | dev_err(msm->dev, "Failed getting DT info\n"); | ||
| 202 | return -EINVAL; | ||
| 203 | } | ||
| 204 | |||
| 205 | msm->msm_bus_handle = msm_bus_scale_register_client(msm->pdata); | ||
| 206 | if (!msm->msm_bus_handle) { | ||
| 207 | dev_err(msm->dev, "Failed msm_bus registration\n"); | ||
| 208 | return -EINVAL; | ||
| 209 | } | ||
| 210 | |||
| 211 | dev_info(msm->dev, "msm_bus registration succeeded! handle 0x%x\n", | ||
| 212 | msm->msm_bus_handle); | ||
| 213 | |||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | /** | ||
| 218 | * wil_platform_msm_init() - wil6210 msm platform module init | ||
| 219 | * | ||
| 220 | * The function must be called before all other functions in this module. | ||
| 221 | * It returns a handle which is used with the rest of the API | ||
| 222 | * | ||
| 223 | */ | ||
| 224 | void *wil_platform_msm_init(struct device *dev, struct wil_platform_ops *ops) | ||
| 225 | { | ||
| 226 | struct device_node *of_node; | ||
| 227 | struct wil_platform_msm *msm; | ||
| 228 | int rc; | ||
| 229 | |||
| 230 | of_node = of_find_compatible_node(NULL, NULL, "qcom,wil6210"); | ||
| 231 | if (!of_node) { | ||
| 232 | /* this could mean non-msm platform */ | ||
| 233 | dev_err(dev, "DT node not found\n"); | ||
| 234 | return NULL; | ||
| 235 | } | ||
| 236 | |||
| 237 | msm = kzalloc(sizeof(*msm), GFP_KERNEL); | ||
| 238 | if (!msm) | ||
| 239 | return NULL; | ||
| 240 | |||
| 241 | msm->dev = dev; | ||
| 242 | |||
| 243 | /* register with msm_bus module for scaling requests */ | ||
| 244 | rc = wil_platform_msm_bus_register(msm, of_node); | ||
| 245 | if (rc) | ||
| 246 | goto cleanup; | ||
| 247 | |||
| 248 | memset(ops, 0, sizeof(*ops)); | ||
| 249 | ops->bus_request = wil_platform_bus_request; | ||
| 250 | ops->uninit = wil_platform_uninit; | ||
| 251 | |||
| 252 | return (void *)msm; | ||
| 253 | |||
| 254 | cleanup: | ||
| 255 | kfree(msm); | ||
| 256 | return NULL; | ||
| 257 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform_msm.h b/drivers/net/wireless/ath/wil6210/wil_platform_msm.h deleted file mode 100644 index 2f2229edb498..000000000000 --- a/drivers/net/wireless/ath/wil6210/wil_platform_msm.h +++ /dev/null | |||
| @@ -1,24 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef __WIL_PLATFORM__MSM_H__ | ||
| 18 | #define __WIL_PLATFORM_MSM_H__ | ||
| 19 | |||
| 20 | #include "wil_platform.h" | ||
| 21 | |||
| 22 | void *wil_platform_msm_init(struct device *dev, struct wil_platform_ops *ops); | ||
| 23 | |||
| 24 | #endif /* __WIL_PLATFORM__MSM_H__ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 63476c86cd0e..0f3e4334c8e3 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
| @@ -23,10 +23,15 @@ | |||
| 23 | #include "wmi.h" | 23 | #include "wmi.h" |
| 24 | #include "trace.h" | 24 | #include "trace.h" |
| 25 | 25 | ||
| 26 | static uint max_assoc_sta = 1; | 26 | static uint max_assoc_sta = WIL6210_MAX_CID; |
| 27 | module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR); | 27 | module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR); |
| 28 | MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); | 28 | MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); |
| 29 | 29 | ||
| 30 | int agg_wsize; /* = 0; */ | ||
| 31 | module_param(agg_wsize, int, S_IRUGO | S_IWUSR); | ||
| 32 | MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;" | ||
| 33 | " 0 - use default; < 0 - don't auto-establish"); | ||
| 34 | |||
| 30 | /** | 35 | /** |
| 31 | * WMI event receiving - theory of operations | 36 | * WMI event receiving - theory of operations |
| 32 | * | 37 | * |
| @@ -197,7 +202,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | |||
| 197 | 202 | ||
| 198 | might_sleep(); | 203 | might_sleep(); |
| 199 | 204 | ||
| 200 | if (!test_bit(wil_status_fwready, &wil->status)) { | 205 | if (!test_bit(wil_status_fwready, wil->status)) { |
| 201 | wil_err(wil, "WMI: cannot send command while FW not ready\n"); | 206 | wil_err(wil, "WMI: cannot send command while FW not ready\n"); |
| 202 | return -EAGAIN; | 207 | return -EAGAIN; |
| 203 | } | 208 | } |
| @@ -300,7 +305,7 @@ static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, | |||
| 300 | wil_dbg_wmi(wil, "WMI: got FW ready event\n"); | 305 | wil_dbg_wmi(wil, "WMI: got FW ready event\n"); |
| 301 | 306 | ||
| 302 | wil_set_recovery_state(wil, fw_recovery_idle); | 307 | wil_set_recovery_state(wil, fw_recovery_idle); |
| 303 | set_bit(wil_status_fwready, &wil->status); | 308 | set_bit(wil_status_fwready, wil->status); |
| 304 | /* let the reset sequence continue */ | 309 | /* let the reset sequence continue */ |
| 305 | complete(&wil->wmi_ready); | 310 | complete(&wil->wmi_ready); |
| 306 | } | 311 | } |
| @@ -438,7 +443,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
| 438 | 443 | ||
| 439 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | 444 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || |
| 440 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | 445 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { |
| 441 | if (!test_bit(wil_status_fwconnecting, &wil->status)) { | 446 | if (!test_bit(wil_status_fwconnecting, wil->status)) { |
| 442 | wil_err(wil, "Not in connecting state\n"); | 447 | wil_err(wil, "Not in connecting state\n"); |
| 443 | return; | 448 | return; |
| 444 | } | 449 | } |
| @@ -457,13 +462,12 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
| 457 | if (assoc_req_ie) { | 462 | if (assoc_req_ie) { |
| 458 | sinfo.assoc_req_ies = assoc_req_ie; | 463 | sinfo.assoc_req_ies = assoc_req_ie; |
| 459 | sinfo.assoc_req_ies_len = assoc_req_ielen; | 464 | sinfo.assoc_req_ies_len = assoc_req_ielen; |
| 460 | sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; | ||
| 461 | } | 465 | } |
| 462 | 466 | ||
| 463 | cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); | 467 | cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); |
| 464 | } | 468 | } |
| 465 | clear_bit(wil_status_fwconnecting, &wil->status); | 469 | clear_bit(wil_status_fwconnecting, wil->status); |
| 466 | set_bit(wil_status_fwconnected, &wil->status); | 470 | set_bit(wil_status_fwconnected, wil->status); |
| 467 | 471 | ||
| 468 | /* FIXME FW can transmit only ucast frames to peer */ | 472 | /* FIXME FW can transmit only ucast frames to peer */ |
| 469 | /* FIXME real ring_id instead of hard coded 0 */ | 473 | /* FIXME real ring_id instead of hard coded 0 */ |
| @@ -471,7 +475,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
| 471 | wil->sta[evt->cid].status = wil_sta_conn_pending; | 475 | wil->sta[evt->cid].status = wil_sta_conn_pending; |
| 472 | 476 | ||
| 473 | wil->pending_connect_cid = evt->cid; | 477 | wil->pending_connect_cid = evt->cid; |
| 474 | queue_work(wil->wmi_wq_conn, &wil->connect_worker); | 478 | queue_work(wil->wq_service, &wil->connect_worker); |
| 475 | } | 479 | } |
| 476 | 480 | ||
| 477 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | 481 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, |
| @@ -544,9 +548,24 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | |||
| 544 | } | 548 | } |
| 545 | } | 549 | } |
| 546 | 550 | ||
| 551 | static void wil_addba_tx_cid(struct wil6210_priv *wil, u8 cid, u16 wsize) | ||
| 552 | { | ||
| 553 | struct vring_tx_data *t; | ||
| 554 | int i; | ||
| 555 | |||
| 556 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | ||
| 557 | if (cid != wil->vring2cid_tid[i][0]) | ||
| 558 | continue; | ||
| 559 | t = &wil->vring_tx_data[i]; | ||
| 560 | if (!t->enabled) | ||
| 561 | continue; | ||
| 562 | |||
| 563 | wil_addba_tx_request(wil, i, wsize); | ||
| 564 | } | ||
| 565 | } | ||
| 566 | |||
| 547 | static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) | 567 | static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) |
| 548 | { | 568 | { |
| 549 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 550 | struct wmi_data_port_open_event *evt = d; | 569 | struct wmi_data_port_open_event *evt = d; |
| 551 | u8 cid = evt->cid; | 570 | u8 cid = evt->cid; |
| 552 | 571 | ||
| @@ -558,7 +577,8 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len) | |||
| 558 | } | 577 | } |
| 559 | 578 | ||
| 560 | wil->sta[cid].data_port_open = true; | 579 | wil->sta[cid].data_port_open = true; |
| 561 | netif_carrier_on(ndev); | 580 | if (agg_wsize >= 0) |
| 581 | wil_addba_tx_cid(wil, cid, agg_wsize); | ||
| 562 | } | 582 | } |
| 563 | 583 | ||
| 564 | static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) | 584 | static void wmi_evt_linkdown(struct wil6210_priv *wil, int id, void *d, int len) |
| @@ -583,55 +603,89 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d, | |||
| 583 | int len) | 603 | int len) |
| 584 | { | 604 | { |
| 585 | struct wmi_vring_ba_status_event *evt = d; | 605 | struct wmi_vring_ba_status_event *evt = d; |
| 586 | struct wil_sta_info *sta; | 606 | struct vring_tx_data *txdata; |
| 587 | uint i, cid; | ||
| 588 | 607 | ||
| 589 | /* TODO: use Rx BA status, not Tx one */ | 608 | wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n", |
| 590 | |||
| 591 | wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n", | ||
| 592 | evt->ringid, | 609 | evt->ringid, |
| 593 | evt->status == WMI_BA_AGREED ? "OK" : "N/A", | 610 | evt->status == WMI_BA_AGREED ? "OK" : "N/A", |
| 594 | evt->agg_wsize, __le16_to_cpu(evt->ba_timeout)); | 611 | evt->agg_wsize, __le16_to_cpu(evt->ba_timeout), |
| 612 | evt->amsdu ? "+" : "-"); | ||
| 595 | 613 | ||
| 596 | if (evt->ringid >= WIL6210_MAX_TX_RINGS) { | 614 | if (evt->ringid >= WIL6210_MAX_TX_RINGS) { |
| 597 | wil_err(wil, "invalid ring id %d\n", evt->ringid); | 615 | wil_err(wil, "invalid ring id %d\n", evt->ringid); |
| 598 | return; | 616 | return; |
| 599 | } | 617 | } |
| 600 | 618 | ||
| 601 | mutex_lock(&wil->mutex); | 619 | if (evt->status != WMI_BA_AGREED) { |
| 602 | 620 | evt->ba_timeout = 0; | |
| 603 | cid = wil->vring2cid_tid[evt->ringid][0]; | 621 | evt->agg_wsize = 0; |
| 604 | if (cid >= WIL6210_MAX_CID) { | 622 | evt->amsdu = 0; |
| 605 | wil_err(wil, "invalid CID %d for vring %d\n", cid, evt->ringid); | ||
| 606 | goto out; | ||
| 607 | } | 623 | } |
| 608 | 624 | ||
| 609 | sta = &wil->sta[cid]; | 625 | txdata = &wil->vring_tx_data[evt->ringid]; |
| 610 | if (sta->status == wil_sta_unused) { | ||
| 611 | wil_err(wil, "CID %d unused\n", cid); | ||
| 612 | goto out; | ||
| 613 | } | ||
| 614 | 626 | ||
| 615 | wil_dbg_wmi(wil, "BACK for CID %d %pM\n", cid, sta->addr); | 627 | txdata->agg_timeout = le16_to_cpu(evt->ba_timeout); |
| 616 | for (i = 0; i < WIL_STA_TID_NUM; i++) { | 628 | txdata->agg_wsize = evt->agg_wsize; |
| 617 | struct wil_tid_ampdu_rx *r; | 629 | txdata->agg_amsdu = evt->amsdu; |
| 618 | unsigned long flags; | 630 | txdata->addba_in_progress = false; |
| 631 | } | ||
| 619 | 632 | ||
| 620 | spin_lock_irqsave(&sta->tid_rx_lock, flags); | 633 | static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d, |
| 634 | int len) | ||
| 635 | { | ||
| 636 | struct wmi_rcp_addba_req_event *evt = d; | ||
| 621 | 637 | ||
| 622 | r = sta->tid_rx[i]; | 638 | wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token, |
| 623 | sta->tid_rx[i] = NULL; | 639 | evt->ba_param_set, evt->ba_timeout, |
| 624 | wil_tid_ampdu_rx_free(wil, r); | 640 | evt->ba_seq_ctrl); |
| 641 | } | ||
| 625 | 642 | ||
| 626 | spin_unlock_irqrestore(&sta->tid_rx_lock, flags); | 643 | static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len) |
| 644 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | ||
| 645 | { | ||
| 646 | struct wmi_delba_event *evt = d; | ||
| 647 | u8 cid, tid; | ||
| 648 | u16 reason = __le16_to_cpu(evt->reason); | ||
| 649 | struct wil_sta_info *sta; | ||
| 650 | struct wil_tid_ampdu_rx *r; | ||
| 627 | 651 | ||
| 628 | if ((evt->status == WMI_BA_AGREED) && evt->agg_wsize) | 652 | might_sleep(); |
| 629 | sta->tid_rx[i] = wil_tid_ampdu_rx_alloc(wil, | 653 | parse_cidxtid(evt->cidxtid, &cid, &tid); |
| 630 | evt->agg_wsize, 0); | 654 | wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n", |
| 655 | cid, tid, | ||
| 656 | evt->from_initiator ? "originator" : "recipient", | ||
| 657 | reason); | ||
| 658 | if (!evt->from_initiator) { | ||
| 659 | int i; | ||
| 660 | /* find Tx vring it belongs to */ | ||
| 661 | for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) { | ||
| 662 | if ((wil->vring2cid_tid[i][0] == cid) && | ||
| 663 | (wil->vring2cid_tid[i][1] == tid)) { | ||
| 664 | struct vring_tx_data *txdata = | ||
| 665 | &wil->vring_tx_data[i]; | ||
| 666 | |||
| 667 | wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i); | ||
| 668 | txdata->agg_timeout = 0; | ||
| 669 | txdata->agg_wsize = 0; | ||
| 670 | txdata->addba_in_progress = false; | ||
| 671 | |||
| 672 | break; /* max. 1 matching ring */ | ||
| 673 | } | ||
| 674 | } | ||
| 675 | if (i >= ARRAY_SIZE(wil->vring2cid_tid)) | ||
| 676 | wil_err(wil, "DELBA: unable to find Tx vring\n"); | ||
| 677 | return; | ||
| 631 | } | 678 | } |
| 632 | 679 | ||
| 633 | out: | 680 | sta = &wil->sta[cid]; |
| 634 | mutex_unlock(&wil->mutex); | 681 | |
| 682 | spin_lock_bh(&sta->tid_rx_lock); | ||
| 683 | |||
| 684 | r = sta->tid_rx[tid]; | ||
| 685 | sta->tid_rx[tid] = NULL; | ||
| 686 | wil_tid_ampdu_rx_free(wil, r); | ||
| 687 | |||
| 688 | spin_unlock_bh(&sta->tid_rx_lock); | ||
| 635 | } | 689 | } |
| 636 | 690 | ||
| 637 | static const struct { | 691 | static const struct { |
| @@ -649,6 +703,8 @@ static const struct { | |||
| 649 | {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_linkup}, | 703 | {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_linkup}, |
| 650 | {WMI_WBE_LINKDOWN_EVENTID, wmi_evt_linkdown}, | 704 | {WMI_WBE_LINKDOWN_EVENTID, wmi_evt_linkdown}, |
| 651 | {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status}, | 705 | {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status}, |
| 706 | {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req}, | ||
| 707 | {WMI_DELBA_EVENTID, wmi_evt_delba}, | ||
| 652 | }; | 708 | }; |
| 653 | 709 | ||
| 654 | /* | 710 | /* |
| @@ -668,7 +724,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
| 668 | ulong flags; | 724 | ulong flags; |
| 669 | unsigned n; | 725 | unsigned n; |
| 670 | 726 | ||
| 671 | if (!test_bit(wil_status_reset_done, &wil->status)) { | 727 | if (!test_bit(wil_status_reset_done, wil->status)) { |
| 672 | wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); | 728 | wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); |
| 673 | return; | 729 | return; |
| 674 | } | 730 | } |
| @@ -1025,13 +1081,14 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
| 1025 | struct wmi_cfg_rx_chain_cmd cmd = { | 1081 | struct wmi_cfg_rx_chain_cmd cmd = { |
| 1026 | .action = WMI_RX_CHAIN_ADD, | 1082 | .action = WMI_RX_CHAIN_ADD, |
| 1027 | .rx_sw_ring = { | 1083 | .rx_sw_ring = { |
| 1028 | .max_mpdu_size = cpu_to_le16(mtu_max + ETH_HLEN), | 1084 | .max_mpdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)), |
| 1029 | .ring_mem_base = cpu_to_le64(vring->pa), | 1085 | .ring_mem_base = cpu_to_le64(vring->pa), |
| 1030 | .ring_size = cpu_to_le16(vring->size), | 1086 | .ring_size = cpu_to_le16(vring->size), |
| 1031 | }, | 1087 | }, |
| 1032 | .mid = 0, /* TODO - what is it? */ | 1088 | .mid = 0, /* TODO - what is it? */ |
| 1033 | .decap_trans_type = WMI_DECAP_TYPE_802_3, | 1089 | .decap_trans_type = WMI_DECAP_TYPE_802_3, |
| 1034 | .reorder_type = WMI_RX_SW_REORDER, | 1090 | .reorder_type = WMI_RX_SW_REORDER, |
| 1091 | .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh), | ||
| 1035 | }; | 1092 | }; |
| 1036 | struct { | 1093 | struct { |
| 1037 | struct wil6210_mbox_hdr_wmi wmi; | 1094 | struct wil6210_mbox_hdr_wmi wmi; |
| @@ -1074,12 +1131,13 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
| 1074 | return rc; | 1131 | return rc; |
| 1075 | } | 1132 | } |
| 1076 | 1133 | ||
| 1077 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r) | 1134 | int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) |
| 1078 | { | 1135 | { |
| 1079 | int rc; | 1136 | int rc; |
| 1080 | struct wmi_temp_sense_cmd cmd = { | 1137 | struct wmi_temp_sense_cmd cmd = { |
| 1081 | .measure_marlon_m_en = cpu_to_le32(!!t_m), | 1138 | .measure_baseband_en = cpu_to_le32(!!t_bb), |
| 1082 | .measure_marlon_r_en = cpu_to_le32(!!t_r), | 1139 | .measure_rf_en = cpu_to_le32(!!t_rf), |
| 1140 | .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW), | ||
| 1083 | }; | 1141 | }; |
| 1084 | struct { | 1142 | struct { |
| 1085 | struct wil6210_mbox_hdr_wmi wmi; | 1143 | struct wil6210_mbox_hdr_wmi wmi; |
| @@ -1091,10 +1149,10 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r) | |||
| 1091 | if (rc) | 1149 | if (rc) |
| 1092 | return rc; | 1150 | return rc; |
| 1093 | 1151 | ||
| 1094 | if (t_m) | 1152 | if (t_bb) |
| 1095 | *t_m = le32_to_cpu(reply.evt.marlon_m_t1000); | 1153 | *t_bb = le32_to_cpu(reply.evt.baseband_t1000); |
| 1096 | if (t_r) | 1154 | if (t_rf) |
| 1097 | *t_r = le32_to_cpu(reply.evt.marlon_r_t1000); | 1155 | *t_rf = le32_to_cpu(reply.evt.rf_t1000); |
| 1098 | 1156 | ||
| 1099 | return 0; | 1157 | return 0; |
| 1100 | } | 1158 | } |
| @@ -1111,6 +1169,87 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) | |||
| 1111 | return wmi_send(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd)); | 1169 | return wmi_send(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd)); |
| 1112 | } | 1170 | } |
| 1113 | 1171 | ||
| 1172 | int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout) | ||
| 1173 | { | ||
| 1174 | struct wmi_vring_ba_en_cmd cmd = { | ||
| 1175 | .ringid = ringid, | ||
| 1176 | .agg_max_wsize = size, | ||
| 1177 | .ba_timeout = cpu_to_le16(timeout), | ||
| 1178 | .amsdu = 0, | ||
| 1179 | }; | ||
| 1180 | |||
| 1181 | wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__, | ||
| 1182 | ringid, size, timeout); | ||
| 1183 | |||
| 1184 | return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd)); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason) | ||
| 1188 | { | ||
| 1189 | struct wmi_vring_ba_dis_cmd cmd = { | ||
| 1190 | .ringid = ringid, | ||
| 1191 | .reason = cpu_to_le16(reason), | ||
| 1192 | }; | ||
| 1193 | |||
| 1194 | wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__, | ||
| 1195 | ringid, reason); | ||
| 1196 | |||
| 1197 | return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd)); | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason) | ||
| 1201 | { | ||
| 1202 | struct wmi_rcp_delba_cmd cmd = { | ||
| 1203 | .cidxtid = cidxtid, | ||
| 1204 | .reason = cpu_to_le16(reason), | ||
| 1205 | }; | ||
| 1206 | |||
| 1207 | wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__, | ||
| 1208 | cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason); | ||
| 1209 | |||
| 1210 | return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd)); | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token, | ||
| 1214 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout) | ||
| 1215 | { | ||
| 1216 | int rc; | ||
| 1217 | struct wmi_rcp_addba_resp_cmd cmd = { | ||
| 1218 | .cidxtid = mk_cidxtid(cid, tid), | ||
| 1219 | .dialog_token = token, | ||
| 1220 | .status_code = cpu_to_le16(status), | ||
| 1221 | /* bit 0: A-MSDU supported | ||
| 1222 | * bit 1: policy (should be 0 for us) | ||
| 1223 | * bits 2..5: TID | ||
| 1224 | * bits 6..15: buffer size | ||
| 1225 | */ | ||
| 1226 | .ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) | | ||
| 1227 | (agg_wsize << 6)), | ||
| 1228 | .ba_timeout = cpu_to_le16(timeout), | ||
| 1229 | }; | ||
| 1230 | struct { | ||
| 1231 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 1232 | struct wmi_rcp_addba_resp_sent_event evt; | ||
| 1233 | } __packed reply; | ||
| 1234 | |||
| 1235 | wil_dbg_wmi(wil, | ||
| 1236 | "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n", | ||
| 1237 | cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-"); | ||
| 1238 | |||
| 1239 | rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd), | ||
| 1240 | WMI_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply), 100); | ||
| 1241 | if (rc) | ||
| 1242 | return rc; | ||
| 1243 | |||
| 1244 | if (reply.evt.status) { | ||
| 1245 | wil_err(wil, "ADDBA response failed with status %d\n", | ||
| 1246 | le16_to_cpu(reply.evt.status)); | ||
| 1247 | rc = -EINVAL; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | return rc; | ||
| 1251 | } | ||
| 1252 | |||
| 1114 | void wmi_event_flush(struct wil6210_priv *wil) | 1253 | void wmi_event_flush(struct wil6210_priv *wil) |
| 1115 | { | 1254 | { |
| 1116 | struct pending_wmi_event *evt, *t; | 1255 | struct pending_wmi_event *evt, *t; |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 27b97432d1c2..8a4af613e191 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
| @@ -29,8 +29,10 @@ | |||
| 29 | 29 | ||
| 30 | /* General */ | 30 | /* General */ |
| 31 | #define WILOCITY_MAX_ASSOC_STA (8) | 31 | #define WILOCITY_MAX_ASSOC_STA (8) |
| 32 | #define WILOCITY_DEFAULT_ASSOC_STA (1) | ||
| 32 | #define WMI_MAC_LEN (6) | 33 | #define WMI_MAC_LEN (6) |
| 33 | #define WMI_PROX_RANGE_NUM (3) | 34 | #define WMI_PROX_RANGE_NUM (3) |
| 35 | #define WMI_MAX_LOSS_DMG_BEACONS (32) | ||
| 34 | 36 | ||
| 35 | /* List of Commands */ | 37 | /* List of Commands */ |
| 36 | enum wmi_command_id { | 38 | enum wmi_command_id { |
| @@ -48,7 +50,7 @@ enum wmi_command_id { | |||
| 48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, | 50 | WMI_SET_WSC_STATUS_CMDID = 0x0041, |
| 49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, | 51 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, |
| 50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, | 52 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, |
| 51 | WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, | 53 | /* WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, */ |
| 52 | WMI_MEM_READ_CMDID = 0x0800, | 54 | WMI_MEM_READ_CMDID = 0x0800, |
| 53 | WMI_MEM_WR_CMDID = 0x0801, | 55 | WMI_MEM_WR_CMDID = 0x0801, |
| 54 | WMI_ECHO_CMDID = 0x0803, | 56 | WMI_ECHO_CMDID = 0x0803, |
| @@ -102,6 +104,8 @@ enum wmi_command_id { | |||
| 102 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, | 104 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, |
| 103 | WMI_RS_MGMT_CMDID = 0x0852, | 105 | WMI_RS_MGMT_CMDID = 0x0852, |
| 104 | WMI_RF_MGMT_CMDID = 0x0853, | 106 | WMI_RF_MGMT_CMDID = 0x0853, |
| 107 | WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x0854, | ||
| 108 | WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x0855, | ||
| 105 | /* Performance monitoring commands */ | 109 | /* Performance monitoring commands */ |
| 106 | WMI_BF_CTRL_CMDID = 0x0862, | 110 | WMI_BF_CTRL_CMDID = 0x0862, |
| 107 | WMI_NOTIFY_REQ_CMDID = 0x0863, | 111 | WMI_NOTIFY_REQ_CMDID = 0x0863, |
| @@ -136,6 +140,7 @@ enum wmi_command_id { | |||
| 136 | WMI_EAPOL_TX_CMDID = 0xf04c, | 140 | WMI_EAPOL_TX_CMDID = 0xf04c, |
| 137 | WMI_MAC_ADDR_REQ_CMDID = 0xf04d, | 141 | WMI_MAC_ADDR_REQ_CMDID = 0xf04d, |
| 138 | WMI_FW_VER_CMDID = 0xf04e, | 142 | WMI_FW_VER_CMDID = 0xf04e, |
| 143 | WMI_PMC_CMDID = 0xf04f, | ||
| 139 | }; | 144 | }; |
| 140 | 145 | ||
| 141 | /* | 146 | /* |
| @@ -283,8 +288,8 @@ enum wmi_scan_type { | |||
| 283 | WMI_LONG_SCAN = 0, | 288 | WMI_LONG_SCAN = 0, |
| 284 | WMI_SHORT_SCAN = 1, | 289 | WMI_SHORT_SCAN = 1, |
| 285 | WMI_PBC_SCAN = 2, | 290 | WMI_PBC_SCAN = 2, |
| 286 | WMI_ACTIVE_SCAN = 3, | 291 | WMI_DIRECT_SCAN = 3, |
| 287 | WMI_DIRECT_SCAN = 4, | 292 | WMI_ACTIVE_SCAN = 4, |
| 288 | }; | 293 | }; |
| 289 | 294 | ||
| 290 | struct wmi_start_scan_cmd { | 295 | struct wmi_start_scan_cmd { |
| @@ -375,6 +380,17 @@ struct wmi_rf_mgmt_cmd { | |||
| 375 | } __packed; | 380 | } __packed; |
| 376 | 381 | ||
| 377 | /* | 382 | /* |
| 383 | * WMI_THERMAL_THROTTLING_CTRL_CMDID | ||
| 384 | */ | ||
| 385 | #define THERMAL_THROTTLING_USE_DEFAULT_MAX_TXOP_LENGTH (0xFFFFFFFF) | ||
| 386 | |||
| 387 | struct wmi_thermal_throttling_ctrl_cmd { | ||
| 388 | __le32 time_on_usec; | ||
| 389 | __le32 time_off_usec; | ||
| 390 | __le32 max_txop_length_usec; | ||
| 391 | } __packed; | ||
| 392 | |||
| 393 | /* | ||
| 378 | * WMI_RF_RX_TEST_CMDID | 394 | * WMI_RF_RX_TEST_CMDID |
| 379 | */ | 395 | */ |
| 380 | struct wmi_rf_rx_test_cmd { | 396 | struct wmi_rf_rx_test_cmd { |
| @@ -586,6 +602,7 @@ struct wmi_vring_ba_en_cmd { | |||
| 586 | u8 ringid; | 602 | u8 ringid; |
| 587 | u8 agg_max_wsize; | 603 | u8 agg_max_wsize; |
| 588 | __le16 ba_timeout; | 604 | __le16 ba_timeout; |
| 605 | u8 amsdu; | ||
| 589 | } __packed; | 606 | } __packed; |
| 590 | 607 | ||
| 591 | /* | 608 | /* |
| @@ -647,6 +664,7 @@ enum wmi_cfg_rx_chain_cmd_action { | |||
| 647 | enum wmi_cfg_rx_chain_cmd_decap_trans_type { | 664 | enum wmi_cfg_rx_chain_cmd_decap_trans_type { |
| 648 | WMI_DECAP_TYPE_802_3 = 0, | 665 | WMI_DECAP_TYPE_802_3 = 0, |
| 649 | WMI_DECAP_TYPE_NATIVE_WIFI = 1, | 666 | WMI_DECAP_TYPE_NATIVE_WIFI = 1, |
| 667 | WMI_DECAP_TYPE_NONE = 2, | ||
| 650 | }; | 668 | }; |
| 651 | 669 | ||
| 652 | enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { | 670 | enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { |
| @@ -784,9 +802,17 @@ struct wmi_echo_cmd { | |||
| 784 | * | 802 | * |
| 785 | * Measure MAC and radio temperatures | 803 | * Measure MAC and radio temperatures |
| 786 | */ | 804 | */ |
| 805 | |||
| 806 | /* Possible modes for temperature measurement */ | ||
| 807 | enum wmi_temperature_measure_mode { | ||
| 808 | TEMPERATURE_USE_OLD_VALUE = 0x1, | ||
| 809 | TEMPERATURE_MEASURE_NOW = 0x2, | ||
| 810 | }; | ||
| 811 | |||
| 787 | struct wmi_temp_sense_cmd { | 812 | struct wmi_temp_sense_cmd { |
| 788 | __le32 measure_marlon_m_en; | 813 | __le32 measure_baseband_en; |
| 789 | __le32 measure_marlon_r_en; | 814 | __le32 measure_rf_en; |
| 815 | __le32 measure_mode; | ||
| 790 | } __packed; | 816 | } __packed; |
| 791 | 817 | ||
| 792 | /* | 818 | /* |
| @@ -842,6 +868,7 @@ enum wmi_event_id { | |||
| 842 | WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, | 868 | WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, |
| 843 | WMI_RS_MGMT_DONE_EVENTID = 0x1852, | 869 | WMI_RS_MGMT_DONE_EVENTID = 0x1852, |
| 844 | WMI_RF_MGMT_STATUS_EVENTID = 0x1853, | 870 | WMI_RF_MGMT_STATUS_EVENTID = 0x1853, |
| 871 | WMI_THERMAL_THROTTLING_STATUS_EVENTID = 0x1855, | ||
| 845 | WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, | 872 | WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, |
| 846 | WMI_RX_MGMT_PACKET_EVENTID = 0x1840, | 873 | WMI_RX_MGMT_PACKET_EVENTID = 0x1840, |
| 847 | WMI_TX_MGMT_PACKET_EVENTID = 0x1841, | 874 | WMI_TX_MGMT_PACKET_EVENTID = 0x1841, |
| @@ -858,6 +885,7 @@ enum wmi_event_id { | |||
| 858 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, | 885 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, |
| 859 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, | 886 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, |
| 860 | /*P2P*/ | 887 | /*P2P*/ |
| 888 | WMI_P2P_CFG_DONE_EVENTID = 0x1910, | ||
| 861 | WMI_PORT_ALLOCATED_EVENTID = 0x1911, | 889 | WMI_PORT_ALLOCATED_EVENTID = 0x1911, |
| 862 | WMI_PORT_DELETED_EVENTID = 0x1912, | 890 | WMI_PORT_DELETED_EVENTID = 0x1912, |
| 863 | WMI_LISTEN_STARTED_EVENTID = 0x1914, | 891 | WMI_LISTEN_STARTED_EVENTID = 0x1914, |
| @@ -898,6 +926,15 @@ struct wmi_rf_mgmt_status_event { | |||
| 898 | } __packed; | 926 | } __packed; |
| 899 | 927 | ||
| 900 | /* | 928 | /* |
| 929 | * WMI_THERMAL_THROTTLING_STATUS_EVENTID | ||
| 930 | */ | ||
| 931 | struct wmi_thermal_throttling_status_event { | ||
| 932 | __le32 time_on_usec; | ||
| 933 | __le32 time_off_usec; | ||
| 934 | __le32 max_txop_length_usec; | ||
| 935 | } __packed; | ||
| 936 | |||
| 937 | /* | ||
| 901 | * WMI_GET_STATUS_DONE_EVENTID | 938 | * WMI_GET_STATUS_DONE_EVENTID |
| 902 | */ | 939 | */ |
| 903 | struct wmi_get_status_done_event { | 940 | struct wmi_get_status_done_event { |
| @@ -1052,14 +1089,23 @@ struct wmi_scan_complete_event { | |||
| 1052 | enum wmi_vring_ba_status { | 1089 | enum wmi_vring_ba_status { |
| 1053 | WMI_BA_AGREED = 0, | 1090 | WMI_BA_AGREED = 0, |
| 1054 | WMI_BA_NON_AGREED = 1, | 1091 | WMI_BA_NON_AGREED = 1, |
| 1092 | /* BA_EN in middle of teardown flow */ | ||
| 1093 | WMI_BA_TD_WIP = 2, | ||
| 1094 | /* BA_DIS or BA_EN in middle of BA SETUP flow */ | ||
| 1095 | WMI_BA_SETUP_WIP = 3, | ||
| 1096 | /* BA_EN when the BA session is already active */ | ||
| 1097 | WMI_BA_SESSION_ACTIVE = 4, | ||
| 1098 | /* BA_DIS when the BA session is not active */ | ||
| 1099 | WMI_BA_SESSION_NOT_ACTIVE = 5, | ||
| 1055 | }; | 1100 | }; |
| 1056 | 1101 | ||
| 1057 | struct wmi_vring_ba_status_event { | 1102 | struct wmi_vring_ba_status_event { |
| 1058 | __le16 status; | 1103 | __le16 status; /* enum wmi_vring_ba_status */ |
| 1059 | u8 reserved[2]; | 1104 | u8 reserved[2]; |
| 1060 | u8 ringid; | 1105 | u8 ringid; |
| 1061 | u8 agg_wsize; | 1106 | u8 agg_wsize; |
| 1062 | __le16 ba_timeout; | 1107 | __le16 ba_timeout; |
| 1108 | u8 amsdu; | ||
| 1063 | } __packed; | 1109 | } __packed; |
| 1064 | 1110 | ||
| 1065 | /* | 1111 | /* |
| @@ -1145,6 +1191,14 @@ struct wmi_get_pcp_channel_event { | |||
| 1145 | } __packed; | 1191 | } __packed; |
| 1146 | 1192 | ||
| 1147 | /* | 1193 | /* |
| 1194 | * WMI_P2P_CFG_DONE_EVENTID | ||
| 1195 | */ | ||
| 1196 | struct wmi_p2p_cfg_done_event { | ||
| 1197 | u8 status; /* wmi_fw_status */ | ||
| 1198 | u8 reserved[3]; | ||
| 1199 | } __packed; | ||
| 1200 | |||
| 1201 | /* | ||
| 1148 | * WMI_PORT_ALLOCATED_EVENTID | 1202 | * WMI_PORT_ALLOCATED_EVENTID |
| 1149 | */ | 1203 | */ |
| 1150 | struct wmi_port_allocated_event { | 1204 | struct wmi_port_allocated_event { |
| @@ -1272,8 +1326,8 @@ struct wmi_echo_event { | |||
| 1272 | * Measure MAC and radio temperatures | 1326 | * Measure MAC and radio temperatures |
| 1273 | */ | 1327 | */ |
| 1274 | struct wmi_temp_sense_done_event { | 1328 | struct wmi_temp_sense_done_event { |
| 1275 | __le32 marlon_m_t1000; | 1329 | __le32 baseband_t1000; |
| 1276 | __le32 marlon_r_t1000; | 1330 | __le32 rf_t1000; |
| 1277 | } __packed; | 1331 | } __packed; |
| 1278 | 1332 | ||
| 1279 | #endif /* __WILOCITY_WMI_H__ */ | 1333 | #endif /* __WILOCITY_WMI_H__ */ |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 9183f1cf89a7..55db9f03eb2a 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
| @@ -45,7 +45,6 @@ | |||
| 45 | #include <linux/ptrace.h> | 45 | #include <linux/ptrace.h> |
| 46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
| 47 | #include <linux/string.h> | 47 | #include <linux/string.h> |
| 48 | #include <linux/ctype.h> | ||
| 49 | #include <linux/timer.h> | 48 | #include <linux/timer.h> |
| 50 | #include <asm/byteorder.h> | 49 | #include <asm/byteorder.h> |
| 51 | #include <asm/io.h> | 50 | #include <asm/io.h> |
| @@ -2699,16 +2698,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
| 2699 | domain[REGDOMAINSZ] = 0; | 2698 | domain[REGDOMAINSZ] = 0; |
| 2700 | rc = -EINVAL; | 2699 | rc = -EINVAL; |
| 2701 | for (i = 0; i < ARRAY_SIZE(channel_table); i++) { | 2700 | for (i = 0; i < ARRAY_SIZE(channel_table); i++) { |
| 2702 | /* strcasecmp doesn't exist in the library */ | 2701 | if (!strcasecmp(channel_table[i].name, domain)) { |
| 2703 | char *a = channel_table[i].name; | ||
| 2704 | char *b = domain; | ||
| 2705 | while (*a) { | ||
| 2706 | char c1 = *a++; | ||
| 2707 | char c2 = *b++; | ||
| 2708 | if (tolower(c1) != tolower(c2)) | ||
| 2709 | break; | ||
| 2710 | } | ||
| 2711 | if (!*a && !*b) { | ||
| 2712 | priv->config_reg_domain = channel_table[i].reg_domain; | 2702 | priv->config_reg_domain = channel_table[i].reg_domain; |
| 2713 | rc = 0; | 2703 | rc = 0; |
| 2714 | } | 2704 | } |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 64a5b672e30a..759fb8d41fc9 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
| @@ -166,6 +166,15 @@ config B43_PHY_LCN | |||
| 166 | 166 | ||
| 167 | Say N, this is BROKEN and crashes driver. | 167 | Say N, this is BROKEN and crashes driver. |
| 168 | 168 | ||
| 169 | config B43_PHY_AC | ||
| 170 | bool "Support for AC-PHY (802.11ac) devices (BROKEN)" | ||
| 171 | depends on B43 && B43_BCMA && BROKEN | ||
| 172 | ---help--- | ||
| 173 | This PHY type can be found in the following chipsets: | ||
| 174 | PCI: BCM4352, BCM4360 | ||
| 175 | |||
| 176 | Say N, this is BROKEN and crashes driver. | ||
| 177 | |||
| 169 | # This config option automatically enables b43 LEDS support, | 178 | # This config option automatically enables b43 LEDS support, |
| 170 | # if it's possible. | 179 | # if it's possible. |
| 171 | config B43_LEDS | 180 | config B43_LEDS |
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 9f7965aae93d..c624d4d90e4f 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
| @@ -13,6 +13,7 @@ b43-$(CONFIG_B43_PHY_HT) += phy_ht.o | |||
| 13 | b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o | 13 | b43-$(CONFIG_B43_PHY_HT) += tables_phy_ht.o |
| 14 | b43-$(CONFIG_B43_PHY_HT) += radio_2059.o | 14 | b43-$(CONFIG_B43_PHY_HT) += radio_2059.o |
| 15 | b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o | 15 | b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o |
| 16 | b43-$(CONFIG_B43_PHY_AC) += phy_ac.o | ||
| 16 | b43-y += sysfs.o | 17 | b43-y += sysfs.o |
| 17 | b43-y += xmit.o | 18 | b43-y += xmit.o |
| 18 | b43-y += dma.o | 19 | b43-y += dma.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index bb12586cd7cd..036552439816 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
| @@ -500,6 +500,8 @@ enum { | |||
| 500 | #define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */ | 500 | #define B43_BCMA_IOCTL_PHY_BW_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */ |
| 501 | #define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */ | 501 | #define B43_BCMA_IOCTL_PHY_BW_20MHZ 0x00000040 /* 20 MHz bandwidth, 80 MHz PHY */ |
| 502 | #define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */ | 502 | #define B43_BCMA_IOCTL_PHY_BW_40MHZ 0x00000080 /* 40 MHz bandwidth, 160 MHz PHY */ |
| 503 | #define B43_BCMA_IOCTL_PHY_BW_80MHZ 0x000000C0 /* 80 MHz bandwidth */ | ||
| 504 | #define B43_BCMA_IOCTL_DAC 0x00000300 /* Highspeed DAC mode control field */ | ||
| 503 | #define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */ | 505 | #define B43_BCMA_IOCTL_GMODE 0x00002000 /* G Mode Enable */ |
| 504 | 506 | ||
| 505 | /* BCMA 802.11 core specific IO status (BCMA_IOST) flags */ | 507 | /* BCMA 802.11 core specific IO status (BCMA_IOST) flags */ |
| @@ -941,6 +943,7 @@ struct b43_wl { | |||
| 941 | bool beacon1_uploaded; | 943 | bool beacon1_uploaded; |
| 942 | bool beacon_templates_virgin; /* Never wrote the templates? */ | 944 | bool beacon_templates_virgin; /* Never wrote the templates? */ |
| 943 | struct work_struct beacon_update_trigger; | 945 | struct work_struct beacon_update_trigger; |
| 946 | spinlock_t beacon_lock; | ||
| 944 | 947 | ||
| 945 | /* The current QOS parameters for the 4 queues. */ | 948 | /* The current QOS parameters for the 4 queues. */ |
| 946 | struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM]; | 949 | struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM]; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 47731cb0d815..2c9088633ec6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -1262,6 +1262,23 @@ static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) | |||
| 1262 | flags |= B43_BCMA_IOCTL_GMODE; | 1262 | flags |= B43_BCMA_IOCTL_GMODE; |
| 1263 | b43_device_enable(dev, flags); | 1263 | b43_device_enable(dev, flags); |
| 1264 | 1264 | ||
| 1265 | if (dev->phy.type == B43_PHYTYPE_AC) { | ||
| 1266 | u16 tmp; | ||
| 1267 | |||
| 1268 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 1269 | tmp &= ~B43_BCMA_IOCTL_DAC; | ||
| 1270 | tmp |= 0x100; | ||
| 1271 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 1272 | |||
| 1273 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 1274 | tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN; | ||
| 1275 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 1276 | |||
| 1277 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 1278 | tmp |= B43_BCMA_IOCTL_PHY_CLKEN; | ||
| 1279 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 1280 | } | ||
| 1281 | |||
| 1265 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); | 1282 | bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); |
| 1266 | b43_bcma_phy_reset(dev); | 1283 | b43_bcma_phy_reset(dev); |
| 1267 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); | 1284 | bcma_core_pll_ctl(dev->dev->bdev, req, status, true); |
| @@ -1601,12 +1618,26 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
| 1601 | unsigned int rate; | 1618 | unsigned int rate; |
| 1602 | u16 ctl; | 1619 | u16 ctl; |
| 1603 | int antenna; | 1620 | int antenna; |
| 1604 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); | 1621 | struct ieee80211_tx_info *info; |
| 1622 | unsigned long flags; | ||
| 1623 | struct sk_buff *beacon_skb; | ||
| 1605 | 1624 | ||
| 1606 | bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); | 1625 | spin_lock_irqsave(&dev->wl->beacon_lock, flags); |
| 1607 | len = min_t(size_t, dev->wl->current_beacon->len, | 1626 | info = IEEE80211_SKB_CB(dev->wl->current_beacon); |
| 1608 | 0x200 - sizeof(struct b43_plcp_hdr6)); | ||
| 1609 | rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; | 1627 | rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; |
| 1628 | /* Clone the beacon, so it cannot go away, while we write it to hw. */ | ||
| 1629 | beacon_skb = skb_clone(dev->wl->current_beacon, GFP_ATOMIC); | ||
| 1630 | spin_unlock_irqrestore(&dev->wl->beacon_lock, flags); | ||
| 1631 | |||
| 1632 | if (!beacon_skb) { | ||
| 1633 | b43dbg(dev->wl, "Could not upload beacon. " | ||
| 1634 | "Failed to clone beacon skb."); | ||
| 1635 | return; | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | bcn = (const struct ieee80211_mgmt *)(beacon_skb->data); | ||
| 1639 | len = min_t(size_t, beacon_skb->len, | ||
| 1640 | 0x200 - sizeof(struct b43_plcp_hdr6)); | ||
| 1610 | 1641 | ||
| 1611 | b43_write_template_common(dev, (const u8 *)bcn, | 1642 | b43_write_template_common(dev, (const u8 *)bcn, |
| 1612 | len, ram_offset, shm_size_offset, rate); | 1643 | len, ram_offset, shm_size_offset, rate); |
| @@ -1674,6 +1705,8 @@ static void b43_write_beacon_template(struct b43_wldev *dev, | |||
| 1674 | B43_SHM_SH_DTIMPER, 0); | 1705 | B43_SHM_SH_DTIMPER, 0); |
| 1675 | } | 1706 | } |
| 1676 | b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); | 1707 | b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); |
| 1708 | |||
| 1709 | dev_kfree_skb_any(beacon_skb); | ||
| 1677 | } | 1710 | } |
| 1678 | 1711 | ||
| 1679 | static void b43_upload_beacon0(struct b43_wldev *dev) | 1712 | static void b43_upload_beacon0(struct b43_wldev *dev) |
| @@ -1790,13 +1823,13 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) | |||
| 1790 | mutex_unlock(&wl->mutex); | 1823 | mutex_unlock(&wl->mutex); |
| 1791 | } | 1824 | } |
| 1792 | 1825 | ||
| 1793 | /* Asynchronously update the packet templates in template RAM. | 1826 | /* Asynchronously update the packet templates in template RAM. */ |
| 1794 | * Locking: Requires wl->mutex to be locked. */ | ||
| 1795 | static void b43_update_templates(struct b43_wl *wl) | 1827 | static void b43_update_templates(struct b43_wl *wl) |
| 1796 | { | 1828 | { |
| 1797 | struct sk_buff *beacon; | 1829 | struct sk_buff *beacon, *old_beacon; |
| 1830 | unsigned long flags; | ||
| 1798 | 1831 | ||
| 1799 | /* This is the top half of the ansynchronous beacon update. | 1832 | /* This is the top half of the asynchronous beacon update. |
| 1800 | * The bottom half is the beacon IRQ. | 1833 | * The bottom half is the beacon IRQ. |
| 1801 | * Beacon update must be asynchronous to avoid sending an | 1834 | * Beacon update must be asynchronous to avoid sending an |
| 1802 | * invalid beacon. This can happen for example, if the firmware | 1835 | * invalid beacon. This can happen for example, if the firmware |
| @@ -1810,12 +1843,17 @@ static void b43_update_templates(struct b43_wl *wl) | |||
| 1810 | if (unlikely(!beacon)) | 1843 | if (unlikely(!beacon)) |
| 1811 | return; | 1844 | return; |
| 1812 | 1845 | ||
| 1813 | if (wl->current_beacon) | 1846 | spin_lock_irqsave(&wl->beacon_lock, flags); |
| 1814 | dev_kfree_skb_any(wl->current_beacon); | 1847 | old_beacon = wl->current_beacon; |
| 1815 | wl->current_beacon = beacon; | 1848 | wl->current_beacon = beacon; |
| 1816 | wl->beacon0_uploaded = false; | 1849 | wl->beacon0_uploaded = false; |
| 1817 | wl->beacon1_uploaded = false; | 1850 | wl->beacon1_uploaded = false; |
| 1851 | spin_unlock_irqrestore(&wl->beacon_lock, flags); | ||
| 1852 | |||
| 1818 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); | 1853 | ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); |
| 1854 | |||
| 1855 | if (old_beacon) | ||
| 1856 | dev_kfree_skb_any(old_beacon); | ||
| 1819 | } | 1857 | } |
| 1820 | 1858 | ||
| 1821 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) | 1859 | static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) |
| @@ -4318,6 +4356,7 @@ redo: | |||
| 4318 | mutex_unlock(&wl->mutex); | 4356 | mutex_unlock(&wl->mutex); |
| 4319 | cancel_delayed_work_sync(&dev->periodic_work); | 4357 | cancel_delayed_work_sync(&dev->periodic_work); |
| 4320 | cancel_work_sync(&wl->tx_work); | 4358 | cancel_work_sync(&wl->tx_work); |
| 4359 | b43_leds_stop(dev); | ||
| 4321 | mutex_lock(&wl->mutex); | 4360 | mutex_lock(&wl->mutex); |
| 4322 | dev = wl->current_dev; | 4361 | dev = wl->current_dev; |
| 4323 | if (!dev || b43_status(dev) < B43_STAT_STARTED) { | 4362 | if (!dev || b43_status(dev) < B43_STAT_STARTED) { |
| @@ -4505,6 +4544,12 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
| 4505 | unsupported = 1; | 4544 | unsupported = 1; |
| 4506 | break; | 4545 | break; |
| 4507 | #endif | 4546 | #endif |
| 4547 | #ifdef CONFIG_B43_PHY_AC | ||
| 4548 | case B43_PHYTYPE_AC: | ||
| 4549 | if (phy_rev > 1) | ||
| 4550 | unsupported = 1; | ||
| 4551 | break; | ||
| 4552 | #endif | ||
| 4508 | default: | 4553 | default: |
| 4509 | unsupported = 1; | 4554 | unsupported = 1; |
| 4510 | } | 4555 | } |
| @@ -4601,6 +4646,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
| 4601 | if (radio_id != 0x2064) | 4646 | if (radio_id != 0x2064) |
| 4602 | unsupported = 1; | 4647 | unsupported = 1; |
| 4603 | break; | 4648 | break; |
| 4649 | case B43_PHYTYPE_AC: | ||
| 4650 | if (radio_id != 0x2069) | ||
| 4651 | unsupported = 1; | ||
| 4652 | break; | ||
| 4604 | default: | 4653 | default: |
| 4605 | B43_WARN_ON(1); | 4654 | B43_WARN_ON(1); |
| 4606 | } | 4655 | } |
| @@ -5094,7 +5143,6 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, | |||
| 5094 | { | 5143 | { |
| 5095 | struct b43_wl *wl = hw_to_b43_wl(hw); | 5144 | struct b43_wl *wl = hw_to_b43_wl(hw); |
| 5096 | 5145 | ||
| 5097 | /* FIXME: add locking */ | ||
| 5098 | b43_update_templates(wl); | 5146 | b43_update_templates(wl); |
| 5099 | 5147 | ||
| 5100 | return 0; | 5148 | return 0; |
| @@ -5584,6 +5632,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) | |||
| 5584 | wl->hw = hw; | 5632 | wl->hw = hw; |
| 5585 | mutex_init(&wl->mutex); | 5633 | mutex_init(&wl->mutex); |
| 5586 | spin_lock_init(&wl->hardirq_lock); | 5634 | spin_lock_init(&wl->hardirq_lock); |
| 5635 | spin_lock_init(&wl->beacon_lock); | ||
| 5587 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); | 5636 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); |
| 5588 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); | 5637 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); |
| 5589 | INIT_WORK(&wl->tx_work, b43_tx_work); | 5638 | INIT_WORK(&wl->tx_work, b43_tx_work); |
diff --git a/drivers/net/wireless/b43/phy_ac.c b/drivers/net/wireless/b43/phy_ac.c new file mode 100644 index 000000000000..e75633d67938 --- /dev/null +++ b/drivers/net/wireless/b43/phy_ac.c | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | /* | ||
| 2 | * Broadcom B43 wireless driver | ||
| 3 | * IEEE 802.11ac AC-PHY support | ||
| 4 | * | ||
| 5 | * Copyright (c) 2015 Rafał Miłecki <zajec5@gmail.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "b43.h" | ||
| 14 | #include "phy_ac.h" | ||
| 15 | |||
| 16 | /************************************************** | ||
| 17 | * Basic PHY ops | ||
| 18 | **************************************************/ | ||
| 19 | |||
| 20 | static int b43_phy_ac_op_allocate(struct b43_wldev *dev) | ||
| 21 | { | ||
| 22 | struct b43_phy_ac *phy_ac; | ||
| 23 | |||
| 24 | phy_ac = kzalloc(sizeof(*phy_ac), GFP_KERNEL); | ||
| 25 | if (!phy_ac) | ||
| 26 | return -ENOMEM; | ||
| 27 | dev->phy.ac = phy_ac; | ||
| 28 | |||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | static void b43_phy_ac_op_free(struct b43_wldev *dev) | ||
| 33 | { | ||
| 34 | struct b43_phy *phy = &dev->phy; | ||
| 35 | struct b43_phy_ac *phy_ac = phy->ac; | ||
| 36 | |||
| 37 | kfree(phy_ac); | ||
| 38 | phy->ac = NULL; | ||
| 39 | } | ||
| 40 | |||
| 41 | static void b43_phy_ac_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, | ||
| 42 | u16 set) | ||
| 43 | { | ||
| 44 | b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); | ||
| 45 | b43_write16(dev, B43_MMIO_PHY_DATA, | ||
| 46 | (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); | ||
| 47 | } | ||
| 48 | |||
| 49 | static u16 b43_phy_ac_op_radio_read(struct b43_wldev *dev, u16 reg) | ||
| 50 | { | ||
| 51 | b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); | ||
| 52 | return b43_read16(dev, B43_MMIO_RADIO24_DATA); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void b43_phy_ac_op_radio_write(struct b43_wldev *dev, u16 reg, | ||
| 56 | u16 value) | ||
| 57 | { | ||
| 58 | b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); | ||
| 59 | b43_write16(dev, B43_MMIO_RADIO24_DATA, value); | ||
| 60 | } | ||
| 61 | |||
| 62 | static unsigned int b43_phy_ac_op_get_default_chan(struct b43_wldev *dev) | ||
| 63 | { | ||
| 64 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
| 65 | return 11; | ||
| 66 | return 36; | ||
| 67 | } | ||
| 68 | |||
| 69 | static enum b43_txpwr_result | ||
| 70 | b43_phy_ac_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) | ||
| 71 | { | ||
| 72 | return B43_TXPWR_RES_DONE; | ||
| 73 | } | ||
| 74 | |||
| 75 | static void b43_phy_ac_op_adjust_txpower(struct b43_wldev *dev) | ||
| 76 | { | ||
| 77 | } | ||
| 78 | |||
| 79 | /************************************************** | ||
| 80 | * PHY ops struct | ||
| 81 | **************************************************/ | ||
| 82 | |||
| 83 | const struct b43_phy_operations b43_phyops_ac = { | ||
| 84 | .allocate = b43_phy_ac_op_allocate, | ||
| 85 | .free = b43_phy_ac_op_free, | ||
| 86 | .phy_maskset = b43_phy_ac_op_maskset, | ||
| 87 | .radio_read = b43_phy_ac_op_radio_read, | ||
| 88 | .radio_write = b43_phy_ac_op_radio_write, | ||
| 89 | .get_default_chan = b43_phy_ac_op_get_default_chan, | ||
| 90 | .recalc_txpower = b43_phy_ac_op_recalc_txpower, | ||
| 91 | .adjust_txpower = b43_phy_ac_op_adjust_txpower, | ||
| 92 | }; | ||
diff --git a/drivers/net/wireless/b43/phy_ac.h b/drivers/net/wireless/b43/phy_ac.h new file mode 100644 index 000000000000..d1ca79e0eb24 --- /dev/null +++ b/drivers/net/wireless/b43/phy_ac.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | #ifndef B43_PHY_AC_H_ | ||
| 2 | #define B43_PHY_AC_H_ | ||
| 3 | |||
| 4 | #include "phy_common.h" | ||
| 5 | |||
| 6 | #define B43_PHY_AC_BBCFG 0x001 | ||
| 7 | #define B43_PHY_AC_BBCFG_RSTCCA 0x4000 /* Reset CCA */ | ||
| 8 | #define B43_PHY_AC_BANDCTL 0x003 /* Band control */ | ||
| 9 | #define B43_PHY_AC_BANDCTL_5GHZ 0x0001 | ||
| 10 | #define B43_PHY_AC_TABLE_ID 0x00d | ||
| 11 | #define B43_PHY_AC_TABLE_OFFSET 0x00e | ||
| 12 | #define B43_PHY_AC_TABLE_DATA1 0x00f | ||
| 13 | #define B43_PHY_AC_TABLE_DATA2 0x010 | ||
| 14 | #define B43_PHY_AC_TABLE_DATA3 0x011 | ||
| 15 | #define B43_PHY_AC_CLASSCTL 0x140 /* Classifier control */ | ||
| 16 | #define B43_PHY_AC_CLASSCTL_CCKEN 0x0001 /* CCK enable */ | ||
| 17 | #define B43_PHY_AC_CLASSCTL_OFDMEN 0x0002 /* OFDM enable */ | ||
| 18 | #define B43_PHY_AC_CLASSCTL_WAITEDEN 0x0004 /* Waited enable */ | ||
| 19 | #define B43_PHY_AC_BW1A 0x371 | ||
| 20 | #define B43_PHY_AC_BW2 0x372 | ||
| 21 | #define B43_PHY_AC_BW3 0x373 | ||
| 22 | #define B43_PHY_AC_BW4 0x374 | ||
| 23 | #define B43_PHY_AC_BW5 0x375 | ||
| 24 | #define B43_PHY_AC_BW6 0x376 | ||
| 25 | #define B43_PHY_AC_RFCTL_CMD 0x408 | ||
| 26 | #define B43_PHY_AC_C1_CLIP 0x6d4 | ||
| 27 | #define B43_PHY_AC_C1_CLIP_DIS 0x4000 | ||
| 28 | #define B43_PHY_AC_C2_CLIP 0x8d4 | ||
| 29 | #define B43_PHY_AC_C2_CLIP_DIS 0x4000 | ||
| 30 | #define B43_PHY_AC_C3_CLIP 0xad4 | ||
| 31 | #define B43_PHY_AC_C3_CLIP_DIS 0x4000 | ||
| 32 | |||
| 33 | struct b43_phy_ac { | ||
| 34 | }; | ||
| 35 | |||
| 36 | extern const struct b43_phy_operations b43_phyops_ac; | ||
| 37 | |||
| 38 | #endif /* B43_PHY_AC_H_ */ | ||
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index ee27b06074e1..ec2b9c577b90 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include "phy_lp.h" | 33 | #include "phy_lp.h" |
| 34 | #include "phy_ht.h" | 34 | #include "phy_ht.h" |
| 35 | #include "phy_lcn.h" | 35 | #include "phy_lcn.h" |
| 36 | #include "phy_ac.h" | ||
| 36 | #include "b43.h" | 37 | #include "b43.h" |
| 37 | #include "main.h" | 38 | #include "main.h" |
| 38 | 39 | ||
| @@ -70,6 +71,11 @@ int b43_phy_allocate(struct b43_wldev *dev) | |||
| 70 | phy->ops = &b43_phyops_lcn; | 71 | phy->ops = &b43_phyops_lcn; |
| 71 | #endif | 72 | #endif |
| 72 | break; | 73 | break; |
| 74 | case B43_PHYTYPE_AC: | ||
| 75 | #ifdef CONFIG_B43_PHY_AC | ||
| 76 | phy->ops = &b43_phyops_ac; | ||
| 77 | #endif | ||
| 78 | break; | ||
| 73 | } | 79 | } |
| 74 | if (B43_WARN_ON(!phy->ops)) | 80 | if (B43_WARN_ON(!phy->ops)) |
| 75 | return -ENODEV; | 81 | return -ENODEV; |
| @@ -572,7 +578,8 @@ void b43_phy_force_clock(struct b43_wldev *dev, bool force) | |||
| 572 | u32 tmp; | 578 | u32 tmp; |
| 573 | 579 | ||
| 574 | WARN_ON(dev->phy.type != B43_PHYTYPE_N && | 580 | WARN_ON(dev->phy.type != B43_PHYTYPE_N && |
| 575 | dev->phy.type != B43_PHYTYPE_HT); | 581 | dev->phy.type != B43_PHYTYPE_HT && |
| 582 | dev->phy.type != B43_PHYTYPE_AC); | ||
| 576 | 583 | ||
| 577 | switch (dev->dev->bus_type) { | 584 | switch (dev->dev->bus_type) { |
| 578 | #ifdef CONFIG_B43_BCMA | 585 | #ifdef CONFIG_B43_BCMA |
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 3912274f71e3..78d86526799e 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h | |||
| @@ -222,6 +222,8 @@ struct b43_phy { | |||
| 222 | struct b43_phy_ht *ht; | 222 | struct b43_phy_ht *ht; |
| 223 | /* LCN-PHY specific information */ | 223 | /* LCN-PHY specific information */ |
| 224 | struct b43_phy_lcn *lcn; | 224 | struct b43_phy_lcn *lcn; |
| 225 | /* AC-PHY specific information */ | ||
| 226 | struct b43_phy_ac *ac; | ||
| 225 | }; | 227 | }; |
| 226 | 228 | ||
| 227 | /* Band support flags. */ | 229 | /* Band support flags. */ |
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c index 896177690394..9501420340a9 100644 --- a/drivers/net/wireless/b43legacy/radio.c +++ b/drivers/net/wireless/b43legacy/radio.c | |||
| @@ -1743,25 +1743,6 @@ u16 freq_r3A_value(u16 frequency) | |||
| 1743 | return value; | 1743 | return value; |
| 1744 | } | 1744 | } |
| 1745 | 1745 | ||
| 1746 | void b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev) | ||
| 1747 | { | ||
| 1748 | static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; | ||
| 1749 | static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; | ||
| 1750 | u16 tmp = b43legacy_radio_read16(dev, 0x001E); | ||
| 1751 | int i; | ||
| 1752 | int j; | ||
| 1753 | |||
| 1754 | for (i = 0; i < 5; i++) { | ||
| 1755 | for (j = 0; j < 5; j++) { | ||
| 1756 | if (tmp == (data_high[i] | data_low[j])) { | ||
| 1757 | b43legacy_phy_write(dev, 0x0069, (i - j) << 8 | | ||
| 1758 | 0x00C0); | ||
| 1759 | return; | ||
| 1760 | } | ||
| 1761 | } | ||
| 1762 | } | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, | 1746 | int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, |
| 1766 | u8 channel, | 1747 | u8 channel, |
| 1767 | int synthetic_pu_workaround) | 1748 | int synthetic_pu_workaround) |
diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h index bccb3d7da682..dd2976d1d561 100644 --- a/drivers/net/wireless/b43legacy/radio.h +++ b/drivers/net/wireless/b43legacy/radio.h | |||
| @@ -92,7 +92,6 @@ void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val); | |||
| 92 | void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val); | 92 | void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val); |
| 93 | void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev); | 93 | void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev); |
| 94 | 94 | ||
| 95 | void b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev); | ||
| 96 | u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev); | 95 | u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev); |
| 97 | 96 | ||
| 98 | #endif /* B43legacy_RADIO_H_ */ | 97 | #endif /* B43legacy_RADIO_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 00ba90b89455..7944224e3fc9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
| @@ -97,25 +97,6 @@ static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func) | |||
| 97 | { | 97 | { |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static bool brcmf_sdiod_pm_resume_error(struct brcmf_sdio_dev *sdiodev) | ||
| 101 | { | ||
| 102 | bool is_err = false; | ||
| 103 | #ifdef CONFIG_PM_SLEEP | ||
| 104 | is_err = atomic_read(&sdiodev->suspend); | ||
| 105 | #endif | ||
| 106 | return is_err; | ||
| 107 | } | ||
| 108 | |||
| 109 | static void brcmf_sdiod_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, | ||
| 110 | wait_queue_head_t *wq) | ||
| 111 | { | ||
| 112 | #ifdef CONFIG_PM_SLEEP | ||
| 113 | int retry = 0; | ||
| 114 | while (atomic_read(&sdiodev->suspend) && retry++ != 30) | ||
| 115 | wait_event_timeout(*wq, false, HZ/100); | ||
| 116 | #endif | ||
| 117 | } | ||
| 118 | |||
| 119 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) | 100 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) |
| 120 | { | 101 | { |
| 121 | int ret = 0; | 102 | int ret = 0; |
| @@ -244,10 +225,6 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, | |||
| 244 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | 225 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", |
| 245 | write, fn, addr, regsz); | 226 | write, fn, addr, regsz); |
| 246 | 227 | ||
| 247 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | ||
| 248 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
| 249 | return -EIO; | ||
| 250 | |||
| 251 | /* only allow byte access on F0 */ | 228 | /* only allow byte access on F0 */ |
| 252 | if (WARN_ON(regsz > 1 && !fn)) | 229 | if (WARN_ON(regsz > 1 && !fn)) |
| 253 | return -EINVAL; | 230 | return -EINVAL; |
| @@ -292,6 +269,12 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, | |||
| 292 | return ret; | 269 | return ret; |
| 293 | } | 270 | } |
| 294 | 271 | ||
| 272 | static void brcmf_sdiod_nomedium_state(struct brcmf_sdio_dev *sdiodev) | ||
| 273 | { | ||
| 274 | sdiodev->state = BRCMF_STATE_NOMEDIUM; | ||
| 275 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN); | ||
| 276 | } | ||
| 277 | |||
| 295 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | 278 | static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
| 296 | u8 regsz, void *data, bool write) | 279 | u8 regsz, void *data, bool write) |
| 297 | { | 280 | { |
| @@ -299,7 +282,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 299 | s32 retry = 0; | 282 | s32 retry = 0; |
| 300 | int ret; | 283 | int ret; |
| 301 | 284 | ||
| 302 | if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM) | 285 | if (sdiodev->state == BRCMF_STATE_NOMEDIUM) |
| 303 | return -ENOMEDIUM; | 286 | return -ENOMEDIUM; |
| 304 | 287 | ||
| 305 | /* | 288 | /* |
| @@ -325,7 +308,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 325 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 308 | retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
| 326 | 309 | ||
| 327 | if (ret == -ENOMEDIUM) | 310 | if (ret == -ENOMEDIUM) |
| 328 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); | 311 | brcmf_sdiod_nomedium_state(sdiodev); |
| 329 | else if (ret != 0) { | 312 | else if (ret != 0) { |
| 330 | /* | 313 | /* |
| 331 | * SleepCSR register access can fail when | 314 | * SleepCSR register access can fail when |
| @@ -348,7 +331,7 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | |||
| 348 | int err = 0, i; | 331 | int err = 0, i; |
| 349 | u8 addr[3]; | 332 | u8 addr[3]; |
| 350 | 333 | ||
| 351 | if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM) | 334 | if (sdiodev->state == BRCMF_STATE_NOMEDIUM) |
| 352 | return -ENOMEDIUM; | 335 | return -ENOMEDIUM; |
| 353 | 336 | ||
| 354 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; | 337 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; |
| @@ -462,10 +445,6 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 462 | unsigned int req_sz; | 445 | unsigned int req_sz; |
| 463 | int err; | 446 | int err; |
| 464 | 447 | ||
| 465 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | ||
| 466 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
| 467 | return -EIO; | ||
| 468 | |||
| 469 | /* Single skb use the standard mmc interface */ | 448 | /* Single skb use the standard mmc interface */ |
| 470 | req_sz = pkt->len + 3; | 449 | req_sz = pkt->len + 3; |
| 471 | req_sz &= (uint)~3; | 450 | req_sz &= (uint)~3; |
| @@ -481,7 +460,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 481 | err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, | 460 | err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, |
| 482 | req_sz); | 461 | req_sz); |
| 483 | if (err == -ENOMEDIUM) | 462 | if (err == -ENOMEDIUM) |
| 484 | brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM); | 463 | brcmf_sdiod_nomedium_state(sdiodev); |
| 485 | return err; | 464 | return err; |
| 486 | } | 465 | } |
| 487 | 466 | ||
| @@ -516,10 +495,6 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 516 | if (!pktlist->qlen) | 495 | if (!pktlist->qlen) |
| 517 | return -EINVAL; | 496 | return -EINVAL; |
| 518 | 497 | ||
| 519 | brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | ||
| 520 | if (brcmf_sdiod_pm_resume_error(sdiodev)) | ||
| 521 | return -EIO; | ||
| 522 | |||
| 523 | target_list = pktlist; | 498 | target_list = pktlist; |
| 524 | /* for host with broken sg support, prepare a page aligned list */ | 499 | /* for host with broken sg support, prepare a page aligned list */ |
| 525 | __skb_queue_head_init(&local_list); | 500 | __skb_queue_head_init(&local_list); |
| @@ -620,8 +595,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 620 | 595 | ||
| 621 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; | 596 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; |
| 622 | if (ret == -ENOMEDIUM) { | 597 | if (ret == -ENOMEDIUM) { |
| 623 | brcmf_bus_change_state(sdiodev->bus_if, | 598 | brcmf_sdiod_nomedium_state(sdiodev); |
| 624 | BRCMF_BUS_NOMEDIUM); | ||
| 625 | break; | 599 | break; |
| 626 | } else if (ret != 0) { | 600 | } else if (ret != 0) { |
| 627 | brcmf_err("CMD53 sg block %s failed %d\n", | 601 | brcmf_err("CMD53 sg block %s failed %d\n", |
| @@ -1076,9 +1050,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
| 1076 | bus_if->wowl_supported = true; | 1050 | bus_if->wowl_supported = true; |
| 1077 | #endif | 1051 | #endif |
| 1078 | 1052 | ||
| 1053 | sdiodev->sleeping = false; | ||
| 1079 | atomic_set(&sdiodev->suspend, false); | 1054 | atomic_set(&sdiodev->suspend, false); |
| 1080 | init_waitqueue_head(&sdiodev->request_word_wait); | 1055 | init_waitqueue_head(&sdiodev->idle_wait); |
| 1081 | init_waitqueue_head(&sdiodev->request_buffer_wait); | ||
| 1082 | 1056 | ||
| 1083 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); | 1057 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n"); |
| 1084 | err = brcmf_sdiod_probe(sdiodev); | 1058 | err = brcmf_sdiod_probe(sdiodev); |
| @@ -1140,12 +1114,23 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled) | |||
| 1140 | #ifdef CONFIG_PM_SLEEP | 1114 | #ifdef CONFIG_PM_SLEEP |
| 1141 | static int brcmf_ops_sdio_suspend(struct device *dev) | 1115 | static int brcmf_ops_sdio_suspend(struct device *dev) |
| 1142 | { | 1116 | { |
| 1143 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 1117 | struct brcmf_bus *bus_if; |
| 1144 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 1118 | struct brcmf_sdio_dev *sdiodev; |
| 1145 | mmc_pm_flag_t sdio_flags; | 1119 | mmc_pm_flag_t sdio_flags; |
| 1146 | 1120 | ||
| 1147 | brcmf_dbg(SDIO, "Enter\n"); | 1121 | brcmf_dbg(SDIO, "Enter\n"); |
| 1148 | 1122 | ||
| 1123 | bus_if = dev_get_drvdata(dev); | ||
| 1124 | sdiodev = bus_if->bus_priv.sdio; | ||
| 1125 | |||
| 1126 | /* wait for watchdog to go idle */ | ||
| 1127 | if (wait_event_timeout(sdiodev->idle_wait, sdiodev->sleeping, | ||
| 1128 | msecs_to_jiffies(3 * BRCMF_WD_POLL_MS)) == 0) { | ||
| 1129 | brcmf_err("bus still active\n"); | ||
| 1130 | return -EBUSY; | ||
| 1131 | } | ||
| 1132 | /* disable watchdog */ | ||
| 1133 | brcmf_sdio_wd_timer(sdiodev->bus, 0); | ||
| 1149 | atomic_set(&sdiodev->suspend, true); | 1134 | atomic_set(&sdiodev->suspend, true); |
| 1150 | 1135 | ||
| 1151 | if (sdiodev->wowl_enabled) { | 1136 | if (sdiodev->wowl_enabled) { |
| @@ -1157,9 +1142,6 @@ static int brcmf_ops_sdio_suspend(struct device *dev) | |||
| 1157 | if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) | 1142 | if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) |
| 1158 | brcmf_err("Failed to set pm_flags %x\n", sdio_flags); | 1143 | brcmf_err("Failed to set pm_flags %x\n", sdio_flags); |
| 1159 | } | 1144 | } |
| 1160 | |||
| 1161 | brcmf_sdio_wd_timer(sdiodev->bus, 0); | ||
| 1162 | |||
| 1163 | return 0; | 1145 | return 0; |
| 1164 | } | 1146 | } |
| 1165 | 1147 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h index ef344e47218a..89e6a4dc105e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h | |||
| @@ -33,11 +33,8 @@ | |||
| 33 | 33 | ||
| 34 | /* The level of bus communication with the dongle */ | 34 | /* The level of bus communication with the dongle */ |
| 35 | enum brcmf_bus_state { | 35 | enum brcmf_bus_state { |
| 36 | BRCMF_BUS_UNKNOWN, /* Not determined yet */ | ||
| 37 | BRCMF_BUS_NOMEDIUM, /* No medium access to dongle */ | ||
| 38 | BRCMF_BUS_DOWN, /* Not ready for frame transfers */ | 36 | BRCMF_BUS_DOWN, /* Not ready for frame transfers */ |
| 39 | BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ | 37 | BRCMF_BUS_UP /* Ready for frame transfers */ |
| 40 | BRCMF_BUS_DATA /* Ready for frame transfers */ | ||
| 41 | }; | 38 | }; |
| 42 | 39 | ||
| 43 | /* The level of bus communication with the dongle */ | 40 | /* The level of bus communication with the dongle */ |
| @@ -188,22 +185,6 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled) | |||
| 188 | bus->ops->wowl_config(bus->dev, enabled); | 185 | bus->ops->wowl_config(bus->dev, enabled); |
| 189 | } | 186 | } |
| 190 | 187 | ||
| 191 | static inline bool brcmf_bus_ready(struct brcmf_bus *bus) | ||
| 192 | { | ||
| 193 | return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA; | ||
| 194 | } | ||
| 195 | |||
| 196 | static inline void brcmf_bus_change_state(struct brcmf_bus *bus, | ||
| 197 | enum brcmf_bus_state new_state) | ||
| 198 | { | ||
| 199 | /* NOMEDIUM is permanent */ | ||
| 200 | if (bus->state == BRCMF_BUS_NOMEDIUM) | ||
| 201 | return; | ||
| 202 | |||
| 203 | brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state); | ||
| 204 | bus->state = new_state; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* | 188 | /* |
| 208 | * interface functions from common layer | 189 | * interface functions from common layer |
| 209 | */ | 190 | */ |
| @@ -226,6 +207,9 @@ void brcmf_txflowblock(struct device *dev, bool state); | |||
| 226 | /* Notify the bus has transferred the tx packet to firmware */ | 207 | /* Notify the bus has transferred the tx packet to firmware */ |
| 227 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); | 208 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); |
| 228 | 209 | ||
| 210 | /* Configure the "global" bus state used by upper layers */ | ||
| 211 | void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state); | ||
| 212 | |||
| 229 | int brcmf_bus_start(struct device *dev); | 213 | int brcmf_bus_start(struct device *dev); |
| 230 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len); | 214 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len); |
| 231 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); | 215 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 1783c0350e1f..b59b8c6c42ab 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | |||
| @@ -1229,7 +1229,25 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) | |||
| 1229 | memset(prof, 0, sizeof(*prof)); | 1229 | memset(prof, 0, sizeof(*prof)); |
| 1230 | } | 1230 | } |
| 1231 | 1231 | ||
| 1232 | static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) | 1232 | static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e) |
| 1233 | { | ||
| 1234 | u16 reason; | ||
| 1235 | |||
| 1236 | switch (e->event_code) { | ||
| 1237 | case BRCMF_E_DEAUTH: | ||
| 1238 | case BRCMF_E_DEAUTH_IND: | ||
| 1239 | case BRCMF_E_DISASSOC_IND: | ||
| 1240 | reason = e->reason; | ||
| 1241 | break; | ||
| 1242 | case BRCMF_E_LINK: | ||
| 1243 | default: | ||
| 1244 | reason = 0; | ||
| 1245 | break; | ||
| 1246 | } | ||
| 1247 | return reason; | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) | ||
| 1233 | { | 1251 | { |
| 1234 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); | 1252 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); |
| 1235 | s32 err = 0; | 1253 | s32 err = 0; |
| @@ -1244,7 +1262,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) | |||
| 1244 | brcmf_err("WLC_DISASSOC failed (%d)\n", err); | 1262 | brcmf_err("WLC_DISASSOC failed (%d)\n", err); |
| 1245 | } | 1263 | } |
| 1246 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); | 1264 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); |
| 1247 | cfg80211_disconnected(vif->wdev.netdev, 0, NULL, 0, GFP_KERNEL); | 1265 | cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0, |
| 1266 | GFP_KERNEL); | ||
| 1248 | 1267 | ||
| 1249 | } | 1268 | } |
| 1250 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); | 1269 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); |
| @@ -1414,7 +1433,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) | |||
| 1414 | if (!check_vif_up(ifp->vif)) | 1433 | if (!check_vif_up(ifp->vif)) |
| 1415 | return -EIO; | 1434 | return -EIO; |
| 1416 | 1435 | ||
| 1417 | brcmf_link_down(ifp->vif); | 1436 | brcmf_link_down(ifp->vif, WLAN_REASON_DEAUTH_LEAVING); |
| 1418 | 1437 | ||
| 1419 | brcmf_dbg(TRACE, "Exit\n"); | 1438 | brcmf_dbg(TRACE, "Exit\n"); |
| 1420 | 1439 | ||
| @@ -2375,10 +2394,10 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
| 2375 | brcmf_err("GET STA INFO failed, %d\n", err); | 2394 | brcmf_err("GET STA INFO failed, %d\n", err); |
| 2376 | goto done; | 2395 | goto done; |
| 2377 | } | 2396 | } |
| 2378 | sinfo->filled = STATION_INFO_INACTIVE_TIME; | 2397 | sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME); |
| 2379 | sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; | 2398 | sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; |
| 2380 | if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) { | 2399 | if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) { |
| 2381 | sinfo->filled |= STATION_INFO_CONNECTED_TIME; | 2400 | sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); |
| 2382 | sinfo->connected_time = le32_to_cpu(sta_info_le.in); | 2401 | sinfo->connected_time = le32_to_cpu(sta_info_le.in); |
| 2383 | } | 2402 | } |
| 2384 | brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n", | 2403 | brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n", |
| @@ -2396,7 +2415,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
| 2396 | brcmf_err("Could not get rate (%d)\n", err); | 2415 | brcmf_err("Could not get rate (%d)\n", err); |
| 2397 | goto done; | 2416 | goto done; |
| 2398 | } else { | 2417 | } else { |
| 2399 | sinfo->filled |= STATION_INFO_TX_BITRATE; | 2418 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
| 2400 | sinfo->txrate.legacy = rate * 5; | 2419 | sinfo->txrate.legacy = rate * 5; |
| 2401 | brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2); | 2420 | brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2); |
| 2402 | } | 2421 | } |
| @@ -2411,7 +2430,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
| 2411 | goto done; | 2430 | goto done; |
| 2412 | } else { | 2431 | } else { |
| 2413 | rssi = le32_to_cpu(scb_val.val); | 2432 | rssi = le32_to_cpu(scb_val.val); |
| 2414 | sinfo->filled |= STATION_INFO_SIGNAL; | 2433 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 2415 | sinfo->signal = rssi; | 2434 | sinfo->signal = rssi; |
| 2416 | brcmf_dbg(CONN, "RSSI %d dBm\n", rssi); | 2435 | brcmf_dbg(CONN, "RSSI %d dBm\n", rssi); |
| 2417 | } | 2436 | } |
| @@ -2438,7 +2457,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
| 2438 | brcmf_dbg(CONN, "DTIM peroid %d\n", | 2457 | brcmf_dbg(CONN, "DTIM peroid %d\n", |
| 2439 | dtim_period); | 2458 | dtim_period); |
| 2440 | } | 2459 | } |
| 2441 | sinfo->filled |= STATION_INFO_BSS_PARAM; | 2460 | sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); |
| 2442 | } | 2461 | } |
| 2443 | } else | 2462 | } else |
| 2444 | err = -EPERM; | 2463 | err = -EPERM; |
| @@ -3041,7 +3060,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, | |||
| 3041 | * disassociate from AP to save power while system is | 3060 | * disassociate from AP to save power while system is |
| 3042 | * in suspended state | 3061 | * in suspended state |
| 3043 | */ | 3062 | */ |
| 3044 | brcmf_link_down(vif); | 3063 | brcmf_link_down(vif, WLAN_REASON_UNSPECIFIED); |
| 3045 | /* Make sure WPA_Supplicant receives all the event | 3064 | /* Make sure WPA_Supplicant receives all the event |
| 3046 | * generated due to DISASSOC call to the fw to keep | 3065 | * generated due to DISASSOC call to the fw to keep |
| 3047 | * the state fw and WPA_Supplicant state consistent | 3066 | * the state fw and WPA_Supplicant state consistent |
| @@ -3737,17 +3756,12 @@ static u32 | |||
| 3737 | brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) | 3756 | brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) |
| 3738 | { | 3757 | { |
| 3739 | 3758 | ||
| 3740 | __le32 iecount_le; | ||
| 3741 | __le32 pktflag_le; | ||
| 3742 | |||
| 3743 | strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1); | 3759 | strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1); |
| 3744 | iebuf[VNDR_IE_CMD_LEN - 1] = '\0'; | 3760 | iebuf[VNDR_IE_CMD_LEN - 1] = '\0'; |
| 3745 | 3761 | ||
| 3746 | iecount_le = cpu_to_le32(1); | 3762 | put_unaligned_le32(1, &iebuf[VNDR_IE_COUNT_OFFSET]); |
| 3747 | memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le)); | ||
| 3748 | 3763 | ||
| 3749 | pktflag_le = cpu_to_le32(pktflag); | 3764 | put_unaligned_le32(pktflag, &iebuf[VNDR_IE_PKTFLAG_OFFSET]); |
| 3750 | memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le)); | ||
| 3751 | 3765 | ||
| 3752 | memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len); | 3766 | memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len); |
| 3753 | 3767 | ||
| @@ -4878,7 +4892,6 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, | |||
| 4878 | if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) && | 4892 | if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) && |
| 4879 | (reason == BRCMF_E_STATUS_SUCCESS)) { | 4893 | (reason == BRCMF_E_STATUS_SUCCESS)) { |
| 4880 | memset(&sinfo, 0, sizeof(sinfo)); | 4894 | memset(&sinfo, 0, sizeof(sinfo)); |
| 4881 | sinfo.filled = STATION_INFO_ASSOC_REQ_IES; | ||
| 4882 | if (!data) { | 4895 | if (!data) { |
| 4883 | brcmf_err("No IEs present in ASSOC/REASSOC_IND"); | 4896 | brcmf_err("No IEs present in ASSOC/REASSOC_IND"); |
| 4884 | return -EINVAL; | 4897 | return -EINVAL; |
| @@ -4933,7 +4946,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
| 4933 | if (!brcmf_is_ibssmode(ifp->vif)) { | 4946 | if (!brcmf_is_ibssmode(ifp->vif)) { |
| 4934 | brcmf_bss_connect_done(cfg, ndev, e, false); | 4947 | brcmf_bss_connect_done(cfg, ndev, e, false); |
| 4935 | } | 4948 | } |
| 4936 | brcmf_link_down(ifp->vif); | 4949 | brcmf_link_down(ifp->vif, brcmf_map_fw_linkdown_reason(e)); |
| 4937 | brcmf_init_prof(ndev_to_prof(ndev)); | 4950 | brcmf_init_prof(ndev_to_prof(ndev)); |
| 4938 | if (ndev != cfg_to_ndev(cfg)) | 4951 | if (ndev != cfg_to_ndev(cfg)) |
| 4939 | complete(&cfg->vif_disabled); | 4952 | complete(&cfg->vif_disabled); |
| @@ -5874,7 +5887,7 @@ static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp) | |||
| 5874 | * from AP to save power | 5887 | * from AP to save power |
| 5875 | */ | 5888 | */ |
| 5876 | if (check_vif_up(ifp->vif)) { | 5889 | if (check_vif_up(ifp->vif)) { |
| 5877 | brcmf_link_down(ifp->vif); | 5890 | brcmf_link_down(ifp->vif, WLAN_REASON_UNSPECIFIED); |
| 5878 | 5891 | ||
| 5879 | /* Make sure WPA_Supplicant receives all the event | 5892 | /* Make sure WPA_Supplicant receives all the event |
| 5880 | generated due to DISASSOC call to the fw to keep | 5893 | generated due to DISASSOC call to the fw to keep |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c index ddf05af13d44..fe54844c75e0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c | |||
| @@ -41,6 +41,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
| 41 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | 41 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; |
| 42 | u8 buf[BRCMF_DCMD_SMLEN]; | 42 | u8 buf[BRCMF_DCMD_SMLEN]; |
| 43 | struct brcmf_join_pref_params join_pref_params[2]; | 43 | struct brcmf_join_pref_params join_pref_params[2]; |
| 44 | struct brcmf_rev_info_le revinfo; | ||
| 45 | struct brcmf_rev_info *ri; | ||
| 44 | char *ptr; | 46 | char *ptr; |
| 45 | s32 err; | 47 | s32 err; |
| 46 | 48 | ||
| @@ -48,12 +50,37 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
| 48 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | 50 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, |
| 49 | sizeof(ifp->mac_addr)); | 51 | sizeof(ifp->mac_addr)); |
| 50 | if (err < 0) { | 52 | if (err < 0) { |
| 51 | brcmf_err("Retreiving cur_etheraddr failed, %d\n", | 53 | brcmf_err("Retreiving cur_etheraddr failed, %d\n", err); |
| 52 | err); | ||
| 53 | goto done; | 54 | goto done; |
| 54 | } | 55 | } |
| 55 | memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); | 56 | memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); |
| 56 | 57 | ||
| 58 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, | ||
| 59 | &revinfo, sizeof(revinfo)); | ||
| 60 | ri = &ifp->drvr->revinfo; | ||
| 61 | if (err < 0) { | ||
| 62 | brcmf_err("retrieving revision info failed, %d\n", err); | ||
| 63 | } else { | ||
| 64 | ri->vendorid = le32_to_cpu(revinfo.vendorid); | ||
| 65 | ri->deviceid = le32_to_cpu(revinfo.deviceid); | ||
| 66 | ri->radiorev = le32_to_cpu(revinfo.radiorev); | ||
| 67 | ri->chiprev = le32_to_cpu(revinfo.chiprev); | ||
| 68 | ri->corerev = le32_to_cpu(revinfo.corerev); | ||
| 69 | ri->boardid = le32_to_cpu(revinfo.boardid); | ||
| 70 | ri->boardvendor = le32_to_cpu(revinfo.boardvendor); | ||
| 71 | ri->boardrev = le32_to_cpu(revinfo.boardrev); | ||
| 72 | ri->driverrev = le32_to_cpu(revinfo.driverrev); | ||
| 73 | ri->ucoderev = le32_to_cpu(revinfo.ucoderev); | ||
| 74 | ri->bus = le32_to_cpu(revinfo.bus); | ||
| 75 | ri->chipnum = le32_to_cpu(revinfo.chipnum); | ||
| 76 | ri->phytype = le32_to_cpu(revinfo.phytype); | ||
| 77 | ri->phyrev = le32_to_cpu(revinfo.phyrev); | ||
| 78 | ri->anarev = le32_to_cpu(revinfo.anarev); | ||
| 79 | ri->chippkg = le32_to_cpu(revinfo.chippkg); | ||
| 80 | ri->nvramrev = le32_to_cpu(revinfo.nvramrev); | ||
| 81 | } | ||
| 82 | ri->result = err; | ||
| 83 | |||
| 57 | /* query for 'ver' to get version info from firmware */ | 84 | /* query for 'ver' to get version info from firmware */ |
| 58 | memset(buf, 0, sizeof(buf)); | 85 | memset(buf, 0, sizeof(buf)); |
| 59 | strcpy(buf, "ver"); | 86 | strcpy(buf, "ver"); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h index 002336e35764..3d404016a92e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h | |||
| @@ -37,6 +37,8 @@ struct brcmf_commonring { | |||
| 37 | unsigned long flags; | 37 | unsigned long flags; |
| 38 | bool inited; | 38 | bool inited; |
| 39 | bool was_full; | 39 | bool was_full; |
| 40 | |||
| 41 | atomic_t outstanding_tx; | ||
| 40 | }; | 42 | }; |
| 41 | 43 | ||
| 42 | 44 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index e2a9e33f71ab..2d6e2cc1b12c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c | |||
| @@ -197,7 +197,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
| 197 | brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); | 197 | brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); |
| 198 | 198 | ||
| 199 | /* Can the device send data? */ | 199 | /* Can the device send data? */ |
| 200 | if (drvr->bus_if->state != BRCMF_BUS_DATA) { | 200 | if (drvr->bus_if->state != BRCMF_BUS_UP) { |
| 201 | brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state); | 201 | brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state); |
| 202 | netif_stop_queue(ndev); | 202 | netif_stop_queue(ndev); |
| 203 | dev_kfree_skb(skb); | 203 | dev_kfree_skb(skb); |
| @@ -601,9 +601,12 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, | |||
| 601 | { | 601 | { |
| 602 | struct brcmf_if *ifp = netdev_priv(ndev); | 602 | struct brcmf_if *ifp = netdev_priv(ndev); |
| 603 | struct brcmf_pub *drvr = ifp->drvr; | 603 | struct brcmf_pub *drvr = ifp->drvr; |
| 604 | char drev[BRCMU_DOTREV_LEN] = "n/a"; | ||
| 604 | 605 | ||
| 606 | if (drvr->revinfo.result == 0) | ||
| 607 | brcmu_dotrev_str(drvr->revinfo.driverrev, drev); | ||
| 605 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); | 608 | strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); |
| 606 | snprintf(info->version, sizeof(info->version), "n/a"); | 609 | strlcpy(info->version, drev, sizeof(info->version)); |
| 607 | strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version)); | 610 | strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version)); |
| 608 | strlcpy(info->bus_info, dev_name(drvr->bus_if->dev), | 611 | strlcpy(info->bus_info, dev_name(drvr->bus_if->dev), |
| 609 | sizeof(info->bus_info)); | 612 | sizeof(info->bus_info)); |
| @@ -637,7 +640,7 @@ static int brcmf_netdev_open(struct net_device *ndev) | |||
| 637 | brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); | 640 | brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); |
| 638 | 641 | ||
| 639 | /* If bus is not ready, can't continue */ | 642 | /* If bus is not ready, can't continue */ |
| 640 | if (bus_if->state != BRCMF_BUS_DATA) { | 643 | if (bus_if->state != BRCMF_BUS_UP) { |
| 641 | brcmf_err("failed bus is not ready\n"); | 644 | brcmf_err("failed bus is not ready\n"); |
| 642 | return -EAGAIN; | 645 | return -EAGAIN; |
| 643 | } | 646 | } |
| @@ -964,13 +967,20 @@ int brcmf_bus_start(struct device *dev) | |||
| 964 | p2p_ifp = NULL; | 967 | p2p_ifp = NULL; |
| 965 | 968 | ||
| 966 | /* signal bus ready */ | 969 | /* signal bus ready */ |
| 967 | brcmf_bus_change_state(bus_if, BRCMF_BUS_DATA); | 970 | brcmf_bus_change_state(bus_if, BRCMF_BUS_UP); |
| 968 | 971 | ||
| 969 | /* Bus is ready, do any initialization */ | 972 | /* Bus is ready, do any initialization */ |
| 970 | ret = brcmf_c_preinit_dcmds(ifp); | 973 | ret = brcmf_c_preinit_dcmds(ifp); |
| 971 | if (ret < 0) | 974 | if (ret < 0) |
| 972 | goto fail; | 975 | goto fail; |
| 973 | 976 | ||
| 977 | /* assure we have chipid before feature attach */ | ||
| 978 | if (!bus_if->chip) { | ||
| 979 | bus_if->chip = drvr->revinfo.chipnum; | ||
| 980 | bus_if->chiprev = drvr->revinfo.chiprev; | ||
| 981 | brcmf_dbg(INFO, "firmware revinfo: chip %x (%d) rev %d\n", | ||
| 982 | bus_if->chip, bus_if->chip, bus_if->chiprev); | ||
| 983 | } | ||
| 974 | brcmf_feat_attach(drvr); | 984 | brcmf_feat_attach(drvr); |
| 975 | 985 | ||
| 976 | ret = brcmf_fws_init(drvr); | 986 | ret = brcmf_fws_init(drvr); |
| @@ -1106,6 +1116,27 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp) | |||
| 1106 | return !err; | 1116 | return !err; |
| 1107 | } | 1117 | } |
| 1108 | 1118 | ||
| 1119 | void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state) | ||
| 1120 | { | ||
| 1121 | struct brcmf_pub *drvr = bus->drvr; | ||
| 1122 | struct net_device *ndev; | ||
| 1123 | int ifidx; | ||
| 1124 | |||
| 1125 | brcmf_dbg(TRACE, "%d -> %d\n", bus->state, state); | ||
| 1126 | bus->state = state; | ||
| 1127 | |||
| 1128 | if (state == BRCMF_BUS_UP) { | ||
| 1129 | for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) { | ||
| 1130 | if ((drvr->iflist[ifidx]) && | ||
| 1131 | (drvr->iflist[ifidx]->ndev)) { | ||
| 1132 | ndev = drvr->iflist[ifidx]->ndev; | ||
| 1133 | if (netif_queue_stopped(ndev)) | ||
| 1134 | netif_wake_queue(ndev); | ||
| 1135 | } | ||
| 1136 | } | ||
| 1137 | } | ||
| 1138 | } | ||
| 1139 | |||
| 1109 | static void brcmf_driver_register(struct work_struct *work) | 1140 | static void brcmf_driver_register(struct work_struct *work) |
| 1110 | { | 1141 | { |
| 1111 | #ifdef CONFIG_BRCMFMAC_SDIO | 1142 | #ifdef CONFIG_BRCMFMAC_SDIO |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index f2f7d3d1a8ef..fd74a9c6e9ac 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h | |||
| @@ -71,6 +71,35 @@ struct brcmf_proto; /* device communication protocol info */ | |||
| 71 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ | 71 | struct brcmf_cfg80211_dev; /* cfg80211 device info */ |
| 72 | struct brcmf_fws_info; /* firmware signalling info */ | 72 | struct brcmf_fws_info; /* firmware signalling info */ |
| 73 | 73 | ||
| 74 | /* | ||
| 75 | * struct brcmf_rev_info | ||
| 76 | * | ||
| 77 | * The result field stores the error code of the | ||
| 78 | * revision info request from firmware. For the | ||
| 79 | * other fields see struct brcmf_rev_info_le in | ||
| 80 | * fwil_types.h | ||
| 81 | */ | ||
| 82 | struct brcmf_rev_info { | ||
| 83 | int result; | ||
| 84 | u32 vendorid; | ||
| 85 | u32 deviceid; | ||
| 86 | u32 radiorev; | ||
| 87 | u32 chiprev; | ||
| 88 | u32 corerev; | ||
| 89 | u32 boardid; | ||
| 90 | u32 boardvendor; | ||
| 91 | u32 boardrev; | ||
| 92 | u32 driverrev; | ||
| 93 | u32 ucoderev; | ||
| 94 | u32 bus; | ||
| 95 | u32 chipnum; | ||
| 96 | u32 phytype; | ||
| 97 | u32 phyrev; | ||
| 98 | u32 anarev; | ||
| 99 | u32 chippkg; | ||
| 100 | u32 nvramrev; | ||
| 101 | }; | ||
| 102 | |||
| 74 | /* Common structure for module and instance linkage */ | 103 | /* Common structure for module and instance linkage */ |
| 75 | struct brcmf_pub { | 104 | struct brcmf_pub { |
| 76 | /* Linkage ponters */ | 105 | /* Linkage ponters */ |
| @@ -104,6 +133,7 @@ struct brcmf_pub { | |||
| 104 | u32 feat_flags; | 133 | u32 feat_flags; |
| 105 | u32 chip_quirks; | 134 | u32 chip_quirks; |
| 106 | 135 | ||
| 136 | struct brcmf_rev_info revinfo; | ||
| 107 | #ifdef DEBUG | 137 | #ifdef DEBUG |
| 108 | struct dentry *dbgfs_dir; | 138 | struct dentry *dbgfs_dir; |
| 109 | #endif | 139 | #endif |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 1ff787d1a36b..9cb99152ad17 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c | |||
| @@ -103,7 +103,11 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) | |||
| 103 | 103 | ||
| 104 | c = nvp->fwnv->data[nvp->pos]; | 104 | c = nvp->fwnv->data[nvp->pos]; |
| 105 | if (c == '=') { | 105 | if (c == '=') { |
| 106 | st = VALUE; | 106 | /* ignore RAW1 by treating as comment */ |
| 107 | if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0) | ||
| 108 | st = COMMENT; | ||
| 109 | else | ||
| 110 | st = VALUE; | ||
| 107 | } else if (!is_nvram_char(c)) { | 111 | } else if (!is_nvram_char(c)) { |
| 108 | brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", | 112 | brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", |
| 109 | nvp->line, nvp->column); | 113 | nvp->line, nvp->column); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 03f2c406a17b..dcfa0bb149ce 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
| @@ -109,7 +109,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | |||
| 109 | struct brcmf_pub *drvr = ifp->drvr; | 109 | struct brcmf_pub *drvr = ifp->drvr; |
| 110 | s32 err; | 110 | s32 err; |
| 111 | 111 | ||
| 112 | if (drvr->bus_if->state != BRCMF_BUS_DATA) { | 112 | if (drvr->bus_if->state != BRCMF_BUS_UP) { |
| 113 | brcmf_err("bus is down. we have nothing to do.\n"); | 113 | brcmf_err("bus is down. we have nothing to do.\n"); |
| 114 | return -EIO; | 114 | return -EIO; |
| 115 | } | 115 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h index 37345e7b873d..5434dcf64f7d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h | |||
| @@ -59,6 +59,7 @@ | |||
| 59 | #define BRCMF_C_SET_COUNTRY 84 | 59 | #define BRCMF_C_SET_COUNTRY 84 |
| 60 | #define BRCMF_C_GET_PM 85 | 60 | #define BRCMF_C_GET_PM 85 |
| 61 | #define BRCMF_C_SET_PM 86 | 61 | #define BRCMF_C_SET_PM 86 |
| 62 | #define BRCMF_C_GET_REVINFO 98 | ||
| 62 | #define BRCMF_C_GET_CURR_RATESET 114 | 63 | #define BRCMF_C_GET_CURR_RATESET 114 |
| 63 | #define BRCMF_C_GET_AP 117 | 64 | #define BRCMF_C_GET_AP 117 |
| 64 | #define BRCMF_C_SET_AP 118 | 65 | #define BRCMF_C_SET_AP 118 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 619669bbdb83..374920965108 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
| @@ -539,4 +539,45 @@ struct brcmf_fil_country_le { | |||
| 539 | char ccode[BRCMF_COUNTRY_BUF_SZ]; | 539 | char ccode[BRCMF_COUNTRY_BUF_SZ]; |
| 540 | }; | 540 | }; |
| 541 | 541 | ||
| 542 | /** | ||
| 543 | * struct brcmf_rev_info_le - device revision info. | ||
| 544 | * | ||
| 545 | * @vendorid: PCI vendor id. | ||
| 546 | * @deviceid: device id of chip. | ||
| 547 | * @radiorev: radio revision. | ||
| 548 | * @chiprev: chip revision. | ||
| 549 | * @corerev: core revision. | ||
| 550 | * @boardid: board identifier (usu. PCI sub-device id). | ||
| 551 | * @boardvendor: board vendor (usu. PCI sub-vendor id). | ||
| 552 | * @boardrev: board revision. | ||
| 553 | * @driverrev: driver version. | ||
| 554 | * @ucoderev: microcode version. | ||
| 555 | * @bus: bus type. | ||
| 556 | * @chipnum: chip number. | ||
| 557 | * @phytype: phy type. | ||
| 558 | * @phyrev: phy revision. | ||
| 559 | * @anarev: anacore rev. | ||
| 560 | * @chippkg: chip package info. | ||
| 561 | * @nvramrev: nvram revision number. | ||
| 562 | */ | ||
| 563 | struct brcmf_rev_info_le { | ||
| 564 | __le32 vendorid; | ||
| 565 | __le32 deviceid; | ||
| 566 | __le32 radiorev; | ||
| 567 | __le32 chiprev; | ||
| 568 | __le32 corerev; | ||
| 569 | __le32 boardid; | ||
| 570 | __le32 boardvendor; | ||
| 571 | __le32 boardrev; | ||
| 572 | __le32 driverrev; | ||
| 573 | __le32 ucoderev; | ||
| 574 | __le32 bus; | ||
| 575 | __le32 chipnum; | ||
| 576 | __le32 phytype; | ||
| 577 | __le32 phyrev; | ||
| 578 | __le32 anarev; | ||
| 579 | __le32 chippkg; | ||
| 580 | __le32 nvramrev; | ||
| 581 | }; | ||
| 582 | |||
| 542 | #endif /* FWIL_TYPES_H_ */ | 583 | #endif /* FWIL_TYPES_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index ee147f5c706a..6262612dec45 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | |||
| @@ -73,6 +73,8 @@ | |||
| 73 | #define BRCMF_MSGBUF_TX_FLUSH_CNT1 32 | 73 | #define BRCMF_MSGBUF_TX_FLUSH_CNT1 32 |
| 74 | #define BRCMF_MSGBUF_TX_FLUSH_CNT2 96 | 74 | #define BRCMF_MSGBUF_TX_FLUSH_CNT2 96 |
| 75 | 75 | ||
| 76 | #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 64 | ||
| 77 | #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32 | ||
| 76 | 78 | ||
| 77 | struct msgbuf_common_hdr { | 79 | struct msgbuf_common_hdr { |
| 78 | u8 msgtype; | 80 | u8 msgtype; |
| @@ -749,6 +751,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid) | |||
| 749 | tx_msghdr->metadata_buf_len = 0; | 751 | tx_msghdr->metadata_buf_len = 0; |
| 750 | tx_msghdr->metadata_buf_addr.high_addr = 0; | 752 | tx_msghdr->metadata_buf_addr.high_addr = 0; |
| 751 | tx_msghdr->metadata_buf_addr.low_addr = 0; | 753 | tx_msghdr->metadata_buf_addr.low_addr = 0; |
| 754 | atomic_inc(&commonring->outstanding_tx); | ||
| 752 | if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) { | 755 | if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) { |
| 753 | brcmf_commonring_write_complete(commonring); | 756 | brcmf_commonring_write_complete(commonring); |
| 754 | count = 0; | 757 | count = 0; |
| @@ -773,10 +776,16 @@ static void brcmf_msgbuf_txflow_worker(struct work_struct *worker) | |||
| 773 | } | 776 | } |
| 774 | 777 | ||
| 775 | 778 | ||
| 776 | static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid) | 779 | static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid, |
| 780 | bool force) | ||
| 777 | { | 781 | { |
| 782 | struct brcmf_commonring *commonring; | ||
| 783 | |||
| 778 | set_bit(flowid, msgbuf->flow_map); | 784 | set_bit(flowid, msgbuf->flow_map); |
| 779 | queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work); | 785 | commonring = msgbuf->flowrings[flowid]; |
| 786 | if ((force) || (atomic_read(&commonring->outstanding_tx) < | ||
| 787 | BRCMF_MSGBUF_DELAY_TXWORKER_THRS)) | ||
| 788 | queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work); | ||
| 780 | 789 | ||
| 781 | return 0; | 790 | return 0; |
| 782 | } | 791 | } |
| @@ -797,7 +806,7 @@ static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx, | |||
| 797 | return -ENOMEM; | 806 | return -ENOMEM; |
| 798 | } | 807 | } |
| 799 | brcmf_flowring_enqueue(flow, flowid, skb); | 808 | brcmf_flowring_enqueue(flow, flowid, skb); |
| 800 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid); | 809 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false); |
| 801 | 810 | ||
| 802 | return 0; | 811 | return 0; |
| 803 | } | 812 | } |
| @@ -854,6 +863,7 @@ brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf) | |||
| 854 | static void | 863 | static void |
| 855 | brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) | 864 | brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) |
| 856 | { | 865 | { |
| 866 | struct brcmf_commonring *commonring; | ||
| 857 | struct msgbuf_tx_status *tx_status; | 867 | struct msgbuf_tx_status *tx_status; |
| 858 | u32 idx; | 868 | u32 idx; |
| 859 | struct sk_buff *skb; | 869 | struct sk_buff *skb; |
| @@ -871,6 +881,8 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) | |||
| 871 | } | 881 | } |
| 872 | 882 | ||
| 873 | set_bit(flowid, msgbuf->txstatus_done_map); | 883 | set_bit(flowid, msgbuf->txstatus_done_map); |
| 884 | commonring = msgbuf->flowrings[flowid]; | ||
| 885 | atomic_dec(&commonring->outstanding_tx); | ||
| 874 | 886 | ||
| 875 | brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); | 887 | brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); |
| 876 | } | 888 | } |
| @@ -1181,7 +1193,7 @@ brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf, | |||
| 1181 | 1193 | ||
| 1182 | brcmf_flowring_open(msgbuf->flow, flowid); | 1194 | brcmf_flowring_open(msgbuf->flow, flowid); |
| 1183 | 1195 | ||
| 1184 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid); | 1196 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true); |
| 1185 | } | 1197 | } |
| 1186 | 1198 | ||
| 1187 | 1199 | ||
| @@ -1280,8 +1292,10 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) | |||
| 1280 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 1292 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
| 1281 | struct brcmf_pub *drvr = bus_if->drvr; | 1293 | struct brcmf_pub *drvr = bus_if->drvr; |
| 1282 | struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; | 1294 | struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; |
| 1295 | struct brcmf_commonring *commonring; | ||
| 1283 | void *buf; | 1296 | void *buf; |
| 1284 | u32 flowid; | 1297 | u32 flowid; |
| 1298 | int qlen; | ||
| 1285 | 1299 | ||
| 1286 | buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE]; | 1300 | buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE]; |
| 1287 | brcmf_msgbuf_process_rx(msgbuf, buf); | 1301 | brcmf_msgbuf_process_rx(msgbuf, buf); |
| @@ -1293,8 +1307,12 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) | |||
| 1293 | for_each_set_bit(flowid, msgbuf->txstatus_done_map, | 1307 | for_each_set_bit(flowid, msgbuf->txstatus_done_map, |
| 1294 | msgbuf->nrof_flowrings) { | 1308 | msgbuf->nrof_flowrings) { |
| 1295 | clear_bit(flowid, msgbuf->txstatus_done_map); | 1309 | clear_bit(flowid, msgbuf->txstatus_done_map); |
| 1296 | if (brcmf_flowring_qlen(msgbuf->flow, flowid)) | 1310 | commonring = msgbuf->flowrings[flowid]; |
| 1297 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid); | 1311 | qlen = brcmf_flowring_qlen(msgbuf->flow, flowid); |
| 1312 | if ((qlen > BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) || | ||
| 1313 | ((qlen) && (atomic_read(&commonring->outstanding_tx) < | ||
| 1314 | BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS))) | ||
| 1315 | brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true); | ||
| 1298 | } | 1316 | } |
| 1299 | 1317 | ||
| 1300 | return 0; | 1318 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index e91fa9a2c885..61c053a729be 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c | |||
| @@ -1828,7 +1828,7 @@ static int brcmf_pcie_resume(struct pci_dev *pdev) | |||
| 1828 | goto cleanup; | 1828 | goto cleanup; |
| 1829 | brcmf_dbg(PCIE, "Hot resume, continue....\n"); | 1829 | brcmf_dbg(PCIE, "Hot resume, continue....\n"); |
| 1830 | brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); | 1830 | brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); |
| 1831 | brcmf_bus_change_state(bus, BRCMF_BUS_DATA); | 1831 | brcmf_bus_change_state(bus, BRCMF_BUS_UP); |
| 1832 | brcmf_pcie_intr_enable(devinfo); | 1832 | brcmf_pcie_intr_enable(devinfo); |
| 1833 | return 0; | 1833 | return 0; |
| 1834 | } | 1834 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index 99a37765888d..faec35c899ec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c | |||
| @@ -44,7 +44,8 @@ | |||
| 44 | #include "chip.h" | 44 | #include "chip.h" |
| 45 | #include "firmware.h" | 45 | #include "firmware.h" |
| 46 | 46 | ||
| 47 | #define DCMD_RESP_TIMEOUT 2000 /* In milli second */ | 47 | #define DCMD_RESP_TIMEOUT 2000 /* In milli second */ |
| 48 | #define CTL_DONE_TIMEOUT 2000 /* In milli second */ | ||
| 48 | 49 | ||
| 49 | #ifdef DEBUG | 50 | #ifdef DEBUG |
| 50 | 51 | ||
| @@ -495,9 +496,9 @@ struct brcmf_sdio { | |||
| 495 | u8 *ctrl_frame_buf; | 496 | u8 *ctrl_frame_buf; |
| 496 | u16 ctrl_frame_len; | 497 | u16 ctrl_frame_len; |
| 497 | bool ctrl_frame_stat; | 498 | bool ctrl_frame_stat; |
| 499 | int ctrl_frame_err; | ||
| 498 | 500 | ||
| 499 | spinlock_t txq_lock; /* protect bus->txq */ | 501 | spinlock_t txq_lock; /* protect bus->txq */ |
| 500 | struct semaphore tx_seq_lock; /* protect bus->tx_seq */ | ||
| 501 | wait_queue_head_t ctrl_wait; | 502 | wait_queue_head_t ctrl_wait; |
| 502 | wait_queue_head_t dcmd_resp_wait; | 503 | wait_queue_head_t dcmd_resp_wait; |
| 503 | 504 | ||
| @@ -514,7 +515,6 @@ struct brcmf_sdio { | |||
| 514 | bool txoff; /* Transmit flow-controlled */ | 515 | bool txoff; /* Transmit flow-controlled */ |
| 515 | struct brcmf_sdio_count sdcnt; | 516 | struct brcmf_sdio_count sdcnt; |
| 516 | bool sr_enabled; /* SaveRestore enabled */ | 517 | bool sr_enabled; /* SaveRestore enabled */ |
| 517 | bool sleeping; /* SDIO bus sleeping */ | ||
| 518 | 518 | ||
| 519 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ | 519 | u8 tx_hdrlen; /* sdio bus header length for tx packet */ |
| 520 | bool txglom; /* host tx glomming enable flag */ | 520 | bool txglom; /* host tx glomming enable flag */ |
| @@ -1013,12 +1013,12 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
| 1013 | 1013 | ||
| 1014 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", | 1014 | brcmf_dbg(SDIO, "Enter: request %s currently %s\n", |
| 1015 | (sleep ? "SLEEP" : "WAKE"), | 1015 | (sleep ? "SLEEP" : "WAKE"), |
| 1016 | (bus->sleeping ? "SLEEP" : "WAKE")); | 1016 | (bus->sdiodev->sleeping ? "SLEEP" : "WAKE")); |
| 1017 | 1017 | ||
| 1018 | /* If SR is enabled control bus state with KSO */ | 1018 | /* If SR is enabled control bus state with KSO */ |
| 1019 | if (bus->sr_enabled) { | 1019 | if (bus->sr_enabled) { |
| 1020 | /* Done if we're already in the requested state */ | 1020 | /* Done if we're already in the requested state */ |
| 1021 | if (sleep == bus->sleeping) | 1021 | if (sleep == bus->sdiodev->sleeping) |
| 1022 | goto end; | 1022 | goto end; |
| 1023 | 1023 | ||
| 1024 | /* Going to sleep */ | 1024 | /* Going to sleep */ |
| @@ -1050,12 +1050,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
| 1050 | bus->idlecount = 0; | 1050 | bus->idlecount = 0; |
| 1051 | err = brcmf_sdio_kso_control(bus, true); | 1051 | err = brcmf_sdio_kso_control(bus, true); |
| 1052 | } | 1052 | } |
| 1053 | if (!err) { | 1053 | if (err) { |
| 1054 | /* Change state */ | ||
| 1055 | bus->sleeping = sleep; | ||
| 1056 | brcmf_dbg(SDIO, "new state %s\n", | ||
| 1057 | (sleep ? "SLEEP" : "WAKE")); | ||
| 1058 | } else { | ||
| 1059 | brcmf_err("error while changing bus sleep state %d\n", | 1054 | brcmf_err("error while changing bus sleep state %d\n", |
| 1060 | err); | 1055 | err); |
| 1061 | goto done; | 1056 | goto done; |
| @@ -1070,6 +1065,11 @@ end: | |||
| 1070 | } else { | 1065 | } else { |
| 1071 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); | 1066 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); |
| 1072 | } | 1067 | } |
| 1068 | bus->sdiodev->sleeping = sleep; | ||
| 1069 | if (sleep) | ||
| 1070 | wake_up(&bus->sdiodev->idle_wait); | ||
| 1071 | brcmf_dbg(SDIO, "new state %s\n", | ||
| 1072 | (sleep ? "SLEEP" : "WAKE")); | ||
| 1073 | done: | 1073 | done: |
| 1074 | brcmf_dbg(SDIO, "Exit: err=%d\n", err); | 1074 | brcmf_dbg(SDIO, "Exit: err=%d\n", err); |
| 1075 | return err; | 1075 | return err; |
| @@ -1909,7 +1909,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
| 1909 | bus->rxpending = true; | 1909 | bus->rxpending = true; |
| 1910 | 1910 | ||
| 1911 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; | 1911 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; |
| 1912 | !bus->rxskip && rxleft && brcmf_bus_ready(bus->sdiodev->bus_if); | 1912 | !bus->rxskip && rxleft && bus->sdiodev->state == BRCMF_STATE_DATA; |
| 1913 | rd->seq_num++, rxleft--) { | 1913 | rd->seq_num++, rxleft--) { |
| 1914 | 1914 | ||
| 1915 | /* Handle glomming separately */ | 1915 | /* Handle glomming separately */ |
| @@ -2376,8 +2376,6 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
| 2376 | /* Send frames until the limit or some other event */ | 2376 | /* Send frames until the limit or some other event */ |
| 2377 | for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { | 2377 | for (cnt = 0; (cnt < maxframes) && data_ok(bus);) { |
| 2378 | pkt_num = 1; | 2378 | pkt_num = 1; |
| 2379 | if (down_interruptible(&bus->tx_seq_lock)) | ||
| 2380 | return cnt; | ||
| 2381 | if (bus->txglom) | 2379 | if (bus->txglom) |
| 2382 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, | 2380 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, |
| 2383 | bus->sdiodev->txglomsz); | 2381 | bus->sdiodev->txglomsz); |
| @@ -2393,13 +2391,10 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
| 2393 | __skb_queue_tail(&pktq, pkt); | 2391 | __skb_queue_tail(&pktq, pkt); |
| 2394 | } | 2392 | } |
| 2395 | spin_unlock_bh(&bus->txq_lock); | 2393 | spin_unlock_bh(&bus->txq_lock); |
| 2396 | if (i == 0) { | 2394 | if (i == 0) |
| 2397 | up(&bus->tx_seq_lock); | ||
| 2398 | break; | 2395 | break; |
| 2399 | } | ||
| 2400 | 2396 | ||
| 2401 | ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); | 2397 | ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL); |
| 2402 | up(&bus->tx_seq_lock); | ||
| 2403 | 2398 | ||
| 2404 | cnt += i; | 2399 | cnt += i; |
| 2405 | 2400 | ||
| @@ -2420,7 +2415,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
| 2420 | } | 2415 | } |
| 2421 | 2416 | ||
| 2422 | /* Deflow-control stack if needed */ | 2417 | /* Deflow-control stack if needed */ |
| 2423 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) && | 2418 | if ((bus->sdiodev->state == BRCMF_STATE_DATA) && |
| 2424 | bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { | 2419 | bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { |
| 2425 | bus->txoff = false; | 2420 | bus->txoff = false; |
| 2426 | brcmf_txflowblock(bus->sdiodev->dev, false); | 2421 | brcmf_txflowblock(bus->sdiodev->dev, false); |
| @@ -2508,7 +2503,7 @@ static void brcmf_sdio_bus_stop(struct device *dev) | |||
| 2508 | bus->watchdog_tsk = NULL; | 2503 | bus->watchdog_tsk = NULL; |
| 2509 | } | 2504 | } |
| 2510 | 2505 | ||
| 2511 | if (bus_if->state == BRCMF_BUS_DOWN) { | 2506 | if (sdiodev->state != BRCMF_STATE_NOMEDIUM) { |
| 2512 | sdio_claim_host(sdiodev->func[1]); | 2507 | sdio_claim_host(sdiodev->func[1]); |
| 2513 | 2508 | ||
| 2514 | /* Enable clock for device interrupts */ | 2509 | /* Enable clock for device interrupts */ |
| @@ -2543,8 +2538,7 @@ static void brcmf_sdio_bus_stop(struct device *dev) | |||
| 2543 | brcmu_pktq_flush(&bus->txq, true, NULL, NULL); | 2538 | brcmu_pktq_flush(&bus->txq, true, NULL, NULL); |
| 2544 | 2539 | ||
| 2545 | /* Clear any held glomming stuff */ | 2540 | /* Clear any held glomming stuff */ |
| 2546 | if (bus->glomd) | 2541 | brcmu_pkt_buf_free_skb(bus->glomd); |
| 2547 | brcmu_pkt_buf_free_skb(bus->glomd); | ||
| 2548 | brcmf_sdio_free_glom(bus); | 2542 | brcmf_sdio_free_glom(bus); |
| 2549 | 2543 | ||
| 2550 | /* Clear rx control and wake any waiters */ | 2544 | /* Clear rx control and wake any waiters */ |
| @@ -2609,6 +2603,21 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | |||
| 2609 | return ret; | 2603 | return ret; |
| 2610 | } | 2604 | } |
| 2611 | 2605 | ||
| 2606 | static int brcmf_sdio_pm_resume_wait(struct brcmf_sdio_dev *sdiodev) | ||
| 2607 | { | ||
| 2608 | #ifdef CONFIG_PM_SLEEP | ||
| 2609 | int retry; | ||
| 2610 | |||
| 2611 | /* Wait for possible resume to complete */ | ||
| 2612 | retry = 0; | ||
| 2613 | while ((atomic_read(&sdiodev->suspend)) && (retry++ != 50)) | ||
| 2614 | msleep(20); | ||
| 2615 | if (atomic_read(&sdiodev->suspend)) | ||
| 2616 | return -EIO; | ||
| 2617 | #endif | ||
| 2618 | return 0; | ||
| 2619 | } | ||
| 2620 | |||
| 2612 | static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | 2621 | static void brcmf_sdio_dpc(struct brcmf_sdio *bus) |
| 2613 | { | 2622 | { |
| 2614 | u32 newstatus = 0; | 2623 | u32 newstatus = 0; |
| @@ -2619,6 +2628,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
| 2619 | 2628 | ||
| 2620 | brcmf_dbg(TRACE, "Enter\n"); | 2629 | brcmf_dbg(TRACE, "Enter\n"); |
| 2621 | 2630 | ||
| 2631 | if (brcmf_sdio_pm_resume_wait(bus->sdiodev)) | ||
| 2632 | return; | ||
| 2633 | |||
| 2622 | sdio_claim_host(bus->sdiodev->func[1]); | 2634 | sdio_claim_host(bus->sdiodev->func[1]); |
| 2623 | 2635 | ||
| 2624 | /* If waiting for HTAVAIL, check status */ | 2636 | /* If waiting for HTAVAIL, check status */ |
| @@ -2725,17 +2737,14 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
| 2725 | brcmf_sdio_clrintr(bus); | 2737 | brcmf_sdio_clrintr(bus); |
| 2726 | 2738 | ||
| 2727 | if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && | 2739 | if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && |
| 2728 | (down_interruptible(&bus->tx_seq_lock) == 0)) { | 2740 | data_ok(bus)) { |
| 2729 | if (data_ok(bus)) { | 2741 | sdio_claim_host(bus->sdiodev->func[1]); |
| 2730 | sdio_claim_host(bus->sdiodev->func[1]); | 2742 | err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, |
| 2731 | err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, | 2743 | bus->ctrl_frame_len); |
| 2732 | bus->ctrl_frame_len); | 2744 | sdio_release_host(bus->sdiodev->func[1]); |
| 2733 | sdio_release_host(bus->sdiodev->func[1]); | 2745 | bus->ctrl_frame_err = err; |
| 2734 | 2746 | bus->ctrl_frame_stat = false; | |
| 2735 | bus->ctrl_frame_stat = false; | 2747 | brcmf_sdio_wait_event_wakeup(bus); |
| 2736 | brcmf_sdio_wait_event_wakeup(bus); | ||
| 2737 | } | ||
| 2738 | up(&bus->tx_seq_lock); | ||
| 2739 | } | 2748 | } |
| 2740 | /* Send queued frames (limit 1 if rx may still be pending) */ | 2749 | /* Send queued frames (limit 1 if rx may still be pending) */ |
| 2741 | if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && | 2750 | if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && |
| @@ -2746,7 +2755,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
| 2746 | brcmf_sdio_sendfromq(bus, framecnt); | 2755 | brcmf_sdio_sendfromq(bus, framecnt); |
| 2747 | } | 2756 | } |
| 2748 | 2757 | ||
| 2749 | if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) { | 2758 | if ((bus->sdiodev->state != BRCMF_STATE_DATA) || (err != 0)) { |
| 2750 | brcmf_err("failed backplane access over SDIO, halting operation\n"); | 2759 | brcmf_err("failed backplane access over SDIO, halting operation\n"); |
| 2751 | atomic_set(&bus->intstatus, 0); | 2760 | atomic_set(&bus->intstatus, 0); |
| 2752 | } else if (atomic_read(&bus->intstatus) || | 2761 | } else if (atomic_read(&bus->intstatus) || |
| @@ -2947,43 +2956,30 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
| 2947 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2956 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
| 2948 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2957 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
| 2949 | struct brcmf_sdio *bus = sdiodev->bus; | 2958 | struct brcmf_sdio *bus = sdiodev->bus; |
| 2950 | int ret = -1; | 2959 | int ret; |
| 2951 | 2960 | ||
| 2952 | brcmf_dbg(TRACE, "Enter\n"); | 2961 | brcmf_dbg(TRACE, "Enter\n"); |
| 2953 | 2962 | ||
| 2954 | if (down_interruptible(&bus->tx_seq_lock)) | 2963 | /* Send from dpc */ |
| 2955 | return -EINTR; | 2964 | bus->ctrl_frame_buf = msg; |
| 2956 | 2965 | bus->ctrl_frame_len = msglen; | |
| 2957 | if (!data_ok(bus)) { | 2966 | bus->ctrl_frame_stat = true; |
| 2958 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", | 2967 | if (atomic_read(&bus->dpc_tskcnt) == 0) { |
| 2959 | bus->tx_max, bus->tx_seq); | 2968 | atomic_inc(&bus->dpc_tskcnt); |
| 2960 | up(&bus->tx_seq_lock); | 2969 | queue_work(bus->brcmf_wq, &bus->datawork); |
| 2961 | /* Send from dpc */ | ||
| 2962 | bus->ctrl_frame_buf = msg; | ||
| 2963 | bus->ctrl_frame_len = msglen; | ||
| 2964 | bus->ctrl_frame_stat = true; | ||
| 2965 | |||
| 2966 | wait_event_interruptible_timeout(bus->ctrl_wait, | ||
| 2967 | !bus->ctrl_frame_stat, | ||
| 2968 | msecs_to_jiffies(2000)); | ||
| 2969 | |||
| 2970 | if (!bus->ctrl_frame_stat) { | ||
| 2971 | brcmf_dbg(SDIO, "ctrl_frame_stat == false\n"); | ||
| 2972 | ret = 0; | ||
| 2973 | } else { | ||
| 2974 | brcmf_dbg(SDIO, "ctrl_frame_stat == true\n"); | ||
| 2975 | bus->ctrl_frame_stat = false; | ||
| 2976 | if (down_interruptible(&bus->tx_seq_lock)) | ||
| 2977 | return -EINTR; | ||
| 2978 | ret = -1; | ||
| 2979 | } | ||
| 2980 | } | 2970 | } |
| 2981 | if (ret == -1) { | 2971 | |
| 2982 | sdio_claim_host(bus->sdiodev->func[1]); | 2972 | wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, |
| 2983 | brcmf_sdio_bus_sleep(bus, false, false); | 2973 | msecs_to_jiffies(CTL_DONE_TIMEOUT)); |
| 2984 | ret = brcmf_sdio_tx_ctrlframe(bus, msg, msglen); | 2974 | |
| 2985 | sdio_release_host(bus->sdiodev->func[1]); | 2975 | if (!bus->ctrl_frame_stat) { |
| 2986 | up(&bus->tx_seq_lock); | 2976 | brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", |
| 2977 | bus->ctrl_frame_err); | ||
| 2978 | ret = bus->ctrl_frame_err; | ||
| 2979 | } else { | ||
| 2980 | brcmf_dbg(SDIO, "ctrl_frame timeout\n"); | ||
| 2981 | bus->ctrl_frame_stat = false; | ||
| 2982 | ret = -ETIMEDOUT; | ||
| 2987 | } | 2983 | } |
| 2988 | 2984 | ||
| 2989 | if (ret) | 2985 | if (ret) |
| @@ -2991,7 +2987,7 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
| 2991 | else | 2987 | else |
| 2992 | bus->sdcnt.tx_ctlpkts++; | 2988 | bus->sdcnt.tx_ctlpkts++; |
| 2993 | 2989 | ||
| 2994 | return ret ? -EIO : 0; | 2990 | return ret; |
| 2995 | } | 2991 | } |
| 2996 | 2992 | ||
| 2997 | #ifdef DEBUG | 2993 | #ifdef DEBUG |
| @@ -3414,8 +3410,8 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, | |||
| 3414 | goto err; | 3410 | goto err; |
| 3415 | } | 3411 | } |
| 3416 | 3412 | ||
| 3417 | /* Allow HT Clock now that the ARM is running. */ | 3413 | /* Allow full data communication using DPC from now on. */ |
| 3418 | brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_LOAD); | 3414 | bus->sdiodev->state = BRCMF_STATE_DATA; |
| 3419 | bcmerror = 0; | 3415 | bcmerror = 0; |
| 3420 | 3416 | ||
| 3421 | err: | 3417 | err: |
| @@ -3561,7 +3557,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
| 3561 | return; | 3557 | return; |
| 3562 | } | 3558 | } |
| 3563 | 3559 | ||
| 3564 | if (!brcmf_bus_ready(bus->sdiodev->bus_if)) { | 3560 | if (bus->sdiodev->state != BRCMF_STATE_DATA) { |
| 3565 | brcmf_err("bus is down. we have nothing to do\n"); | 3561 | brcmf_err("bus is down. we have nothing to do\n"); |
| 3566 | return; | 3562 | return; |
| 3567 | } | 3563 | } |
| @@ -3584,10 +3580,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
| 3584 | 3580 | ||
| 3585 | static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | 3581 | static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) |
| 3586 | { | 3582 | { |
| 3587 | #ifdef DEBUG | ||
| 3588 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); | ||
| 3589 | #endif /* DEBUG */ | ||
| 3590 | |||
| 3591 | brcmf_dbg(TIMER, "Enter\n"); | 3583 | brcmf_dbg(TIMER, "Enter\n"); |
| 3592 | 3584 | ||
| 3593 | /* Poll period: check device if appropriate. */ | 3585 | /* Poll period: check device if appropriate. */ |
| @@ -3631,7 +3623,7 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | |||
| 3631 | } | 3623 | } |
| 3632 | #ifdef DEBUG | 3624 | #ifdef DEBUG |
| 3633 | /* Poll for console output periodically */ | 3625 | /* Poll for console output periodically */ |
| 3634 | if (bus_if && bus_if->state == BRCMF_BUS_DATA && | 3626 | if (bus->sdiodev->state == BRCMF_STATE_DATA && |
| 3635 | bus->console_interval != 0) { | 3627 | bus->console_interval != 0) { |
| 3636 | bus->console.count += BRCMF_WD_POLL_MS; | 3628 | bus->console.count += BRCMF_WD_POLL_MS; |
| 3637 | if (bus->console.count >= bus->console_interval) { | 3629 | if (bus->console.count >= bus->console_interval) { |
| @@ -3872,11 +3864,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | |||
| 3872 | goto fail; | 3864 | goto fail; |
| 3873 | } | 3865 | } |
| 3874 | 3866 | ||
| 3875 | /* SDIO register access works so moving | ||
| 3876 | * state from UNKNOWN to DOWN. | ||
| 3877 | */ | ||
| 3878 | brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN); | ||
| 3879 | |||
| 3880 | bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops); | 3867 | bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops); |
| 3881 | if (IS_ERR(bus->ci)) { | 3868 | if (IS_ERR(bus->ci)) { |
| 3882 | brcmf_err("brcmf_chip_attach failed!\n"); | 3869 | brcmf_err("brcmf_chip_attach failed!\n"); |
| @@ -4010,18 +3997,16 @@ static void brcmf_sdio_firmware_callback(struct device *dev, | |||
| 4010 | 3997 | ||
| 4011 | brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev)); | 3998 | brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev)); |
| 4012 | 3999 | ||
| 4013 | /* try to download image and nvram to the dongle */ | ||
| 4014 | if (bus_if->state == BRCMF_BUS_DOWN) { | ||
| 4015 | bus->alp_only = true; | ||
| 4016 | err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); | ||
| 4017 | if (err) | ||
| 4018 | goto fail; | ||
| 4019 | bus->alp_only = false; | ||
| 4020 | } | ||
| 4021 | |||
| 4022 | if (!bus_if->drvr) | 4000 | if (!bus_if->drvr) |
| 4023 | return; | 4001 | return; |
| 4024 | 4002 | ||
| 4003 | /* try to download image and nvram to the dongle */ | ||
| 4004 | bus->alp_only = true; | ||
| 4005 | err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); | ||
| 4006 | if (err) | ||
| 4007 | goto fail; | ||
| 4008 | bus->alp_only = false; | ||
| 4009 | |||
| 4025 | /* Start the watchdog timer */ | 4010 | /* Start the watchdog timer */ |
| 4026 | bus->sdcnt.tickcnt = 0; | 4011 | bus->sdcnt.tickcnt = 0; |
| 4027 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); | 4012 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); |
| @@ -4147,7 +4132,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
| 4147 | 4132 | ||
| 4148 | spin_lock_init(&bus->rxctl_lock); | 4133 | spin_lock_init(&bus->rxctl_lock); |
| 4149 | spin_lock_init(&bus->txq_lock); | 4134 | spin_lock_init(&bus->txq_lock); |
| 4150 | sema_init(&bus->tx_seq_lock, 1); | ||
| 4151 | init_waitqueue_head(&bus->ctrl_wait); | 4135 | init_waitqueue_head(&bus->ctrl_wait); |
| 4152 | init_waitqueue_head(&bus->dcmd_resp_wait); | 4136 | init_waitqueue_head(&bus->dcmd_resp_wait); |
| 4153 | 4137 | ||
| @@ -4218,7 +4202,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
| 4218 | bus->idleclock = BRCMF_IDLE_ACTIVE; | 4202 | bus->idleclock = BRCMF_IDLE_ACTIVE; |
| 4219 | 4203 | ||
| 4220 | /* SR state */ | 4204 | /* SR state */ |
| 4221 | bus->sleeping = false; | ||
| 4222 | bus->sr_enabled = false; | 4205 | bus->sr_enabled = false; |
| 4223 | 4206 | ||
| 4224 | brcmf_sdio_debugfs_create(bus); | 4207 | brcmf_sdio_debugfs_create(bus); |
| @@ -4259,7 +4242,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) | |||
| 4259 | destroy_workqueue(bus->brcmf_wq); | 4242 | destroy_workqueue(bus->brcmf_wq); |
| 4260 | 4243 | ||
| 4261 | if (bus->ci) { | 4244 | if (bus->ci) { |
| 4262 | if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { | 4245 | if (bus->sdiodev->state != BRCMF_STATE_NOMEDIUM) { |
| 4263 | sdio_claim_host(bus->sdiodev->func[1]); | 4246 | sdio_claim_host(bus->sdiodev->func[1]); |
| 4264 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | 4247 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
| 4265 | /* Leave the device in state where it is | 4248 | /* Leave the device in state where it is |
| @@ -4294,7 +4277,7 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick) | |||
| 4294 | } | 4277 | } |
| 4295 | 4278 | ||
| 4296 | /* don't start the wd until fw is loaded */ | 4279 | /* don't start the wd until fw is loaded */ |
| 4297 | if (bus->sdiodev->bus_if->state != BRCMF_BUS_DATA) | 4280 | if (bus->sdiodev->state != BRCMF_STATE_DATA) |
| 4298 | return; | 4281 | return; |
| 4299 | 4282 | ||
| 4300 | if (wdtick) { | 4283 | if (wdtick) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h index 8eb42620129c..ec2586a8425c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h | |||
| @@ -155,6 +155,13 @@ | |||
| 155 | /* watchdog polling interval in ms */ | 155 | /* watchdog polling interval in ms */ |
| 156 | #define BRCMF_WD_POLL_MS 10 | 156 | #define BRCMF_WD_POLL_MS 10 |
| 157 | 157 | ||
| 158 | /* The state of the bus */ | ||
| 159 | enum brcmf_sdio_state { | ||
| 160 | BRCMF_STATE_DOWN, /* Device available, still initialising */ | ||
| 161 | BRCMF_STATE_DATA, /* Ready for data transfers, DPC enabled */ | ||
| 162 | BRCMF_STATE_NOMEDIUM /* No medium access to dongle possible */ | ||
| 163 | }; | ||
| 164 | |||
| 158 | struct brcmf_sdreg { | 165 | struct brcmf_sdreg { |
| 159 | int func; | 166 | int func; |
| 160 | int offset; | 167 | int offset; |
| @@ -169,8 +176,8 @@ struct brcmf_sdio_dev { | |||
| 169 | u32 sbwad; /* Save backplane window address */ | 176 | u32 sbwad; /* Save backplane window address */ |
| 170 | struct brcmf_sdio *bus; | 177 | struct brcmf_sdio *bus; |
| 171 | atomic_t suspend; /* suspend flag */ | 178 | atomic_t suspend; /* suspend flag */ |
| 172 | wait_queue_head_t request_word_wait; | 179 | bool sleeping; |
| 173 | wait_queue_head_t request_buffer_wait; | 180 | wait_queue_head_t idle_wait; |
| 174 | struct device *dev; | 181 | struct device *dev; |
| 175 | struct brcmf_bus *bus_if; | 182 | struct brcmf_bus *bus_if; |
| 176 | struct brcmfmac_sdio_platform_data *pdata; | 183 | struct brcmfmac_sdio_platform_data *pdata; |
| @@ -187,6 +194,7 @@ struct brcmf_sdio_dev { | |||
| 187 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 194 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
| 188 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 195 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
| 189 | bool wowl_enabled; | 196 | bool wowl_enabled; |
| 197 | enum brcmf_sdio_state state; | ||
| 190 | }; | 198 | }; |
| 191 | 199 | ||
| 192 | /* sdio core registers */ | 200 | /* sdio core registers */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 4572defc280f..5df6aa72cc2d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
| @@ -421,7 +421,7 @@ fail: | |||
| 421 | brcmf_err("fail!\n"); | 421 | brcmf_err("fail!\n"); |
| 422 | while (!list_empty(q)) { | 422 | while (!list_empty(q)) { |
| 423 | req = list_entry(q->next, struct brcmf_usbreq, list); | 423 | req = list_entry(q->next, struct brcmf_usbreq, list); |
| 424 | if (req && req->urb) | 424 | if (req) |
| 425 | usb_free_urb(req->urb); | 425 | usb_free_urb(req->urb); |
| 426 | list_del(q->next); | 426 | list_del(q->next); |
| 427 | } | 427 | } |
| @@ -576,7 +576,7 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) | |||
| 576 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN); | 576 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN); |
| 577 | } else if (state == BRCMFMAC_USB_STATE_UP) { | 577 | } else if (state == BRCMFMAC_USB_STATE_UP) { |
| 578 | brcmf_dbg(USB, "DBUS is up\n"); | 578 | brcmf_dbg(USB, "DBUS is up\n"); |
| 579 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DATA); | 579 | brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_UP); |
| 580 | } else { | 580 | } else { |
| 581 | brcmf_dbg(USB, "DBUS current state=%d\n", state); | 581 | brcmf_dbg(USB, "DBUS current state=%d\n", state); |
| 582 | } | 582 | } |
| @@ -1263,6 +1263,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) | |||
| 1263 | ret = brcmf_usb_bus_setup(devinfo); | 1263 | ret = brcmf_usb_bus_setup(devinfo); |
| 1264 | if (ret) | 1264 | if (ret) |
| 1265 | goto fail; | 1265 | goto fail; |
| 1266 | /* we are done */ | ||
| 1267 | return 0; | ||
| 1266 | } | 1268 | } |
| 1267 | bus->chip = bus_pub->devid; | 1269 | bus->chip = bus_pub->devid; |
| 1268 | bus->chiprev = bus_pub->chiprev; | 1270 | bus->chiprev = bus_pub->chiprev; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c index c9a8b9360ab1..7a1fbb2e3a71 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c | |||
| @@ -78,7 +78,7 @@ int brcms_debugfs_hardware_read(struct seq_file *s, void *data) | |||
| 78 | struct brcms_hardware *hw = drvr->wlc->hw; | 78 | struct brcms_hardware *hw = drvr->wlc->hw; |
| 79 | struct bcma_device *core = hw->d11core; | 79 | struct bcma_device *core = hw->d11core; |
| 80 | struct bcma_bus *bus = core->bus; | 80 | struct bcma_bus *bus = core->bus; |
| 81 | char boardrev[10]; | 81 | char boardrev[BRCMU_BOARDREV_LEN]; |
| 82 | 82 | ||
| 83 | seq_printf(s, "chipnum 0x%x\n" | 83 | seq_printf(s, "chipnum 0x%x\n" |
| 84 | "chiprev 0x%x\n" | 84 | "chiprev 0x%x\n" |
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index 906e89ddf319..0543607002fd 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c | |||
| @@ -267,15 +267,43 @@ char *brcmu_boardrev_str(u32 brev, char *buf) | |||
| 267 | char c; | 267 | char c; |
| 268 | 268 | ||
| 269 | if (brev < 0x100) { | 269 | if (brev < 0x100) { |
| 270 | snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); | 270 | snprintf(buf, BRCMU_BOARDREV_LEN, "%d.%d", |
| 271 | (brev & 0xf0) >> 4, brev & 0xf); | ||
| 271 | } else { | 272 | } else { |
| 272 | c = (brev & 0xf000) == 0x1000 ? 'P' : 'A'; | 273 | c = (brev & 0xf000) == 0x1000 ? 'P' : 'A'; |
| 273 | snprintf(buf, 8, "%c%03x", c, brev & 0xfff); | 274 | snprintf(buf, BRCMU_BOARDREV_LEN, "%c%03x", c, brev & 0xfff); |
| 274 | } | 275 | } |
| 275 | return buf; | 276 | return buf; |
| 276 | } | 277 | } |
| 277 | EXPORT_SYMBOL(brcmu_boardrev_str); | 278 | EXPORT_SYMBOL(brcmu_boardrev_str); |
| 278 | 279 | ||
| 280 | char *brcmu_dotrev_str(u32 dotrev, char *buf) | ||
| 281 | { | ||
| 282 | u8 dotval[4]; | ||
| 283 | |||
| 284 | if (!dotrev) { | ||
| 285 | snprintf(buf, BRCMU_DOTREV_LEN, "unknown"); | ||
| 286 | return buf; | ||
| 287 | } | ||
| 288 | dotval[0] = (dotrev >> 24) & 0xFF; | ||
| 289 | dotval[1] = (dotrev >> 16) & 0xFF; | ||
| 290 | dotval[2] = (dotrev >> 8) & 0xFF; | ||
| 291 | dotval[3] = dotrev & 0xFF; | ||
| 292 | |||
| 293 | if (dotval[3]) | ||
| 294 | snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d.%d", dotval[0], | ||
| 295 | dotval[1], dotval[2], dotval[3]); | ||
| 296 | else if (dotval[2]) | ||
| 297 | snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d", dotval[0], | ||
| 298 | dotval[1], dotval[2]); | ||
| 299 | else | ||
| 300 | snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d", dotval[0], | ||
| 301 | dotval[1]); | ||
| 302 | |||
| 303 | return buf; | ||
| 304 | } | ||
| 305 | EXPORT_SYMBOL(brcmu_dotrev_str); | ||
| 306 | |||
| 279 | #if defined(DEBUG) | 307 | #if defined(DEBUG) |
| 280 | /* pretty hex print a pkt buffer chain */ | 308 | /* pretty hex print a pkt buffer chain */ |
| 281 | void brcmu_prpkt(const char *msg, struct sk_buff *p0) | 309 | void brcmu_prpkt(const char *msg, struct sk_buff *p0) |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h index a043e29f07e2..41969527b459 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h | |||
| @@ -218,6 +218,10 @@ void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...) | |||
| 218 | } | 218 | } |
| 219 | #endif | 219 | #endif |
| 220 | 220 | ||
| 221 | #define BRCMU_BOARDREV_LEN 8 | ||
| 222 | #define BRCMU_DOTREV_LEN 16 | ||
| 223 | |||
| 221 | char *brcmu_boardrev_str(u32 brev, char *buf); | 224 | char *brcmu_boardrev_str(u32 brev, char *buf); |
| 225 | char *brcmu_dotrev_str(u32 dotrev, char *buf); | ||
| 222 | 226 | ||
| 223 | #endif /* _BRCMU_UTILS_H_ */ | 227 | #endif /* _BRCMU_UTILS_H_ */ |
diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c index 6f1b9aace8b3..30e7646d04af 100644 --- a/drivers/net/wireless/cw1200/fwio.c +++ b/drivers/net/wireless/cw1200/fwio.c | |||
| @@ -66,25 +66,31 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 66 | do { \ | 66 | do { \ |
| 67 | ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \ | 67 | ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \ |
| 68 | if (ret < 0) \ | 68 | if (ret < 0) \ |
| 69 | goto error; \ | 69 | goto exit; \ |
| 70 | } while (0) | ||
| 71 | #define APB_WRITE2(reg, val) \ | ||
| 72 | do { \ | ||
| 73 | ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \ | ||
| 74 | if (ret < 0) \ | ||
| 75 | goto free_buffer; \ | ||
| 70 | } while (0) | 76 | } while (0) |
| 71 | #define APB_READ(reg, val) \ | 77 | #define APB_READ(reg, val) \ |
| 72 | do { \ | 78 | do { \ |
| 73 | ret = cw1200_apb_read_32(priv, CW1200_APB(reg), &(val)); \ | 79 | ret = cw1200_apb_read_32(priv, CW1200_APB(reg), &(val)); \ |
| 74 | if (ret < 0) \ | 80 | if (ret < 0) \ |
| 75 | goto error; \ | 81 | goto free_buffer; \ |
| 76 | } while (0) | 82 | } while (0) |
| 77 | #define REG_WRITE(reg, val) \ | 83 | #define REG_WRITE(reg, val) \ |
| 78 | do { \ | 84 | do { \ |
| 79 | ret = cw1200_reg_write_32(priv, (reg), (val)); \ | 85 | ret = cw1200_reg_write_32(priv, (reg), (val)); \ |
| 80 | if (ret < 0) \ | 86 | if (ret < 0) \ |
| 81 | goto error; \ | 87 | goto exit; \ |
| 82 | } while (0) | 88 | } while (0) |
| 83 | #define REG_READ(reg, val) \ | 89 | #define REG_READ(reg, val) \ |
| 84 | do { \ | 90 | do { \ |
| 85 | ret = cw1200_reg_read_32(priv, (reg), &(val)); \ | 91 | ret = cw1200_reg_read_32(priv, (reg), &(val)); \ |
| 86 | if (ret < 0) \ | 92 | if (ret < 0) \ |
| 87 | goto error; \ | 93 | goto exit; \ |
| 88 | } while (0) | 94 | } while (0) |
| 89 | 95 | ||
| 90 | switch (priv->hw_revision) { | 96 | switch (priv->hw_revision) { |
| @@ -142,14 +148,14 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 142 | ret = request_firmware(&firmware, fw_path, priv->pdev); | 148 | ret = request_firmware(&firmware, fw_path, priv->pdev); |
| 143 | if (ret) { | 149 | if (ret) { |
| 144 | pr_err("Can't load firmware file %s.\n", fw_path); | 150 | pr_err("Can't load firmware file %s.\n", fw_path); |
| 145 | goto error; | 151 | goto exit; |
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL | GFP_DMA); | 154 | buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL | GFP_DMA); |
| 149 | if (!buf) { | 155 | if (!buf) { |
| 150 | pr_err("Can't allocate firmware load buffer.\n"); | 156 | pr_err("Can't allocate firmware load buffer.\n"); |
| 151 | ret = -ENOMEM; | 157 | ret = -ENOMEM; |
| 152 | goto error; | 158 | goto firmware_release; |
| 153 | } | 159 | } |
| 154 | 160 | ||
| 155 | /* Check if the bootloader is ready */ | 161 | /* Check if the bootloader is ready */ |
| @@ -163,7 +169,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 163 | if (val32 != DOWNLOAD_I_AM_HERE) { | 169 | if (val32 != DOWNLOAD_I_AM_HERE) { |
| 164 | pr_err("Bootloader is not ready.\n"); | 170 | pr_err("Bootloader is not ready.\n"); |
| 165 | ret = -ETIMEDOUT; | 171 | ret = -ETIMEDOUT; |
| 166 | goto error; | 172 | goto free_buffer; |
| 167 | } | 173 | } |
| 168 | 174 | ||
| 169 | /* Calculcate number of download blocks */ | 175 | /* Calculcate number of download blocks */ |
| @@ -171,7 +177,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 171 | 177 | ||
| 172 | /* Updating the length in Download Ctrl Area */ | 178 | /* Updating the length in Download Ctrl Area */ |
| 173 | val32 = firmware->size; /* Explicit cast from size_t to u32 */ | 179 | val32 = firmware->size; /* Explicit cast from size_t to u32 */ |
| 174 | APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, val32); | 180 | APB_WRITE2(DOWNLOAD_IMAGE_SIZE_REG, val32); |
| 175 | 181 | ||
| 176 | /* Firmware downloading loop */ | 182 | /* Firmware downloading loop */ |
| 177 | for (block = 0; block < num_blocks; block++) { | 183 | for (block = 0; block < num_blocks; block++) { |
| @@ -183,7 +189,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 183 | if (val32 != DOWNLOAD_PENDING) { | 189 | if (val32 != DOWNLOAD_PENDING) { |
| 184 | pr_err("Bootloader reported error %d.\n", val32); | 190 | pr_err("Bootloader reported error %d.\n", val32); |
| 185 | ret = -EIO; | 191 | ret = -EIO; |
| 186 | goto error; | 192 | goto free_buffer; |
| 187 | } | 193 | } |
| 188 | 194 | ||
| 189 | /* loop until put - get <= 24K */ | 195 | /* loop until put - get <= 24K */ |
| @@ -198,7 +204,7 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 198 | if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) { | 204 | if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) { |
| 199 | pr_err("Timeout waiting for FIFO.\n"); | 205 | pr_err("Timeout waiting for FIFO.\n"); |
| 200 | ret = -ETIMEDOUT; | 206 | ret = -ETIMEDOUT; |
| 201 | goto error; | 207 | goto free_buffer; |
| 202 | } | 208 | } |
| 203 | 209 | ||
| 204 | /* calculate the block size */ | 210 | /* calculate the block size */ |
| @@ -220,12 +226,12 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 220 | if (ret < 0) { | 226 | if (ret < 0) { |
| 221 | pr_err("Can't write firmware block @ %d!\n", | 227 | pr_err("Can't write firmware block @ %d!\n", |
| 222 | put & (DOWNLOAD_FIFO_SIZE - 1)); | 228 | put & (DOWNLOAD_FIFO_SIZE - 1)); |
| 223 | goto error; | 229 | goto free_buffer; |
| 224 | } | 230 | } |
| 225 | 231 | ||
| 226 | /* update the put register */ | 232 | /* update the put register */ |
| 227 | put += block_size; | 233 | put += block_size; |
| 228 | APB_WRITE(DOWNLOAD_PUT_REG, put); | 234 | APB_WRITE2(DOWNLOAD_PUT_REG, put); |
| 229 | } /* End of firmware download loop */ | 235 | } /* End of firmware download loop */ |
| 230 | 236 | ||
| 231 | /* Wait for the download completion */ | 237 | /* Wait for the download completion */ |
| @@ -238,19 +244,21 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) | |||
| 238 | if (val32 != DOWNLOAD_SUCCESS) { | 244 | if (val32 != DOWNLOAD_SUCCESS) { |
| 239 | pr_err("Wait for download completion failed: 0x%.8X\n", val32); | 245 | pr_err("Wait for download completion failed: 0x%.8X\n", val32); |
| 240 | ret = -ETIMEDOUT; | 246 | ret = -ETIMEDOUT; |
| 241 | goto error; | 247 | goto free_buffer; |
| 242 | } else { | 248 | } else { |
| 243 | pr_info("Firmware download completed.\n"); | 249 | pr_info("Firmware download completed.\n"); |
| 244 | ret = 0; | 250 | ret = 0; |
| 245 | } | 251 | } |
| 246 | 252 | ||
| 247 | error: | 253 | free_buffer: |
| 248 | kfree(buf); | 254 | kfree(buf); |
| 249 | if (firmware) | 255 | firmware_release: |
| 250 | release_firmware(firmware); | 256 | release_firmware(firmware); |
| 257 | exit: | ||
| 251 | return ret; | 258 | return ret; |
| 252 | 259 | ||
| 253 | #undef APB_WRITE | 260 | #undef APB_WRITE |
| 261 | #undef APB_WRITE2 | ||
| 254 | #undef APB_READ | 262 | #undef APB_READ |
| 255 | #undef REG_WRITE | 263 | #undef REG_WRITE |
| 256 | #undef REG_READ | 264 | #undef REG_READ |
diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c index fa965ee9f56b..3689dbbd10bd 100644 --- a/drivers/net/wireless/cw1200/main.c +++ b/drivers/net/wireless/cw1200/main.c | |||
| @@ -282,7 +282,6 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, | |||
| 282 | IEEE80211_HW_SUPPORTS_PS | | 282 | IEEE80211_HW_SUPPORTS_PS | |
| 283 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 283 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
| 284 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 284 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
| 285 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
| 286 | IEEE80211_HW_CONNECTION_MONITOR | | 285 | IEEE80211_HW_CONNECTION_MONITOR | |
| 287 | IEEE80211_HW_AMPDU_AGGREGATION | | 286 | IEEE80211_HW_AMPDU_AGGREGATION | |
| 288 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | | 287 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | |
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index f2e276faca70..bff81b8d4164 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c | |||
| @@ -39,9 +39,9 @@ static int cw1200_scan_start(struct cw1200_common *priv, struct wsm_scan *scan) | |||
| 39 | cancel_delayed_work_sync(&priv->clear_recent_scan_work); | 39 | cancel_delayed_work_sync(&priv->clear_recent_scan_work); |
| 40 | atomic_set(&priv->scan.in_progress, 1); | 40 | atomic_set(&priv->scan.in_progress, 1); |
| 41 | atomic_set(&priv->recent_scan, 1); | 41 | atomic_set(&priv->recent_scan, 1); |
| 42 | cw1200_pm_stay_awake(&priv->pm_state, tmo * HZ / 1000); | 42 | cw1200_pm_stay_awake(&priv->pm_state, msecs_to_jiffies(tmo)); |
| 43 | queue_delayed_work(priv->workqueue, &priv->scan.timeout, | 43 | queue_delayed_work(priv->workqueue, &priv->scan.timeout, |
| 44 | tmo * HZ / 1000); | 44 | msecs_to_jiffies(tmo)); |
| 45 | ret = wsm_scan(priv, scan); | 45 | ret = wsm_scan(priv, scan); |
| 46 | if (ret) { | 46 | if (ret) { |
| 47 | atomic_set(&priv->scan.in_progress, 0); | 47 | atomic_set(&priv->scan.in_progress, 0); |
| @@ -386,8 +386,8 @@ void cw1200_probe_work(struct work_struct *work) | |||
| 386 | if (down_trylock(&priv->scan.lock)) { | 386 | if (down_trylock(&priv->scan.lock)) { |
| 387 | /* Scan is already in progress. Requeue self. */ | 387 | /* Scan is already in progress. Requeue self. */ |
| 388 | schedule(); | 388 | schedule(); |
| 389 | queue_delayed_work(priv->workqueue, | 389 | queue_delayed_work(priv->workqueue, &priv->scan.probe_work, |
| 390 | &priv->scan.probe_work, HZ / 10); | 390 | msecs_to_jiffies(100)); |
| 391 | mutex_unlock(&priv->conf_mutex); | 391 | mutex_unlock(&priv->conf_mutex); |
| 392 | return; | 392 | return; |
| 393 | } | 393 | } |
diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index 5b84664db13b..4a47c7f8a246 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c | |||
| @@ -213,6 +213,7 @@ int cw1200_add_interface(struct ieee80211_hw *dev, | |||
| 213 | /* __le32 auto_calibration_mode = __cpu_to_le32(1); */ | 213 | /* __le32 auto_calibration_mode = __cpu_to_le32(1); */ |
| 214 | 214 | ||
| 215 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | | 215 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | |
| 216 | IEEE80211_VIF_SUPPORTS_UAPSD | | ||
| 216 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; | 217 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; |
| 217 | 218 | ||
| 218 | mutex_lock(&priv->conf_mutex); | 219 | mutex_lock(&priv->conf_mutex); |
| @@ -708,7 +709,8 @@ int cw1200_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
| 708 | if (sta) | 709 | if (sta) |
| 709 | peer_addr = sta->addr; | 710 | peer_addr = sta->addr; |
| 710 | 711 | ||
| 711 | key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; | 712 | key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE | |
| 713 | IEEE80211_KEY_FLAG_RESERVE_TAILROOM; | ||
| 712 | 714 | ||
| 713 | switch (key->cipher) { | 715 | switch (key->cipher) { |
| 714 | case WLAN_CIPHER_SUITE_WEP40: | 716 | case WLAN_CIPHER_SUITE_WEP40: |
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 596525528f50..fd8d83dd4f62 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
| @@ -145,7 +145,7 @@ static void ap_free_sta(struct ap_data *ap, struct sta_info *sta) | |||
| 145 | if (sta->aid > 0) | 145 | if (sta->aid > 0) |
| 146 | ap->sta_aid[sta->aid - 1] = NULL; | 146 | ap->sta_aid[sta->aid - 1] = NULL; |
| 147 | 147 | ||
| 148 | if (!sta->ap && sta->u.sta.challenge) | 148 | if (!sta->ap) |
| 149 | kfree(sta->u.sta.challenge); | 149 | kfree(sta->u.sta.challenge); |
| 150 | del_timer_sync(&sta->timer); | 150 | del_timer_sync(&sta->timer); |
| 151 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 151 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index de43dd7e170a..c4d6dd7402d9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
| @@ -1228,11 +1228,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
| 1228 | trans_cfg.no_reclaim_cmds = no_reclaim_cmds; | 1228 | trans_cfg.no_reclaim_cmds = no_reclaim_cmds; |
| 1229 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); | 1229 | trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); |
| 1230 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; | 1230 | trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K; |
| 1231 | if (!iwlwifi_mod_params.wd_disable) | 1231 | trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED; |
| 1232 | trans_cfg.queue_watchdog_timeout = | 1232 | |
| 1233 | priv->cfg->base_params->wd_timeout; | ||
| 1234 | else | ||
| 1235 | trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; | ||
| 1236 | trans_cfg.command_names = iwl_dvm_cmd_strings; | 1233 | trans_cfg.command_names = iwl_dvm_cmd_strings; |
| 1237 | trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM; | 1234 | trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM; |
| 1238 | 1235 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index d1ce3ce13591..1e40a12de077 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
| @@ -715,7 +715,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
| 715 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; | 715 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; |
| 716 | 716 | ||
| 717 | iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, | 717 | iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, |
| 718 | buf_size, ssn); | 718 | buf_size, ssn, 0); |
| 719 | 719 | ||
| 720 | /* | 720 | /* |
| 721 | * If the limit is 0, then it wasn't initialised yet, | 721 | * If the limit is 0, then it wasn't initialised yet, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index d5cee1530597..4dbef7e58c2e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
| @@ -267,7 +267,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
| 267 | for (i = 0; i < n_queues; i++) | 267 | for (i = 0; i < n_queues; i++) |
| 268 | if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED) | 268 | if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED) |
| 269 | iwl_trans_ac_txq_enable(priv->trans, i, | 269 | iwl_trans_ac_txq_enable(priv->trans, i, |
| 270 | queue_to_txf[i]); | 270 | queue_to_txf[i], 0); |
| 271 | 271 | ||
| 272 | priv->passive_no_rx = false; | 272 | priv->passive_no_rx = false; |
| 273 | priv->transport_queue_stop = 0; | 273 | priv->transport_queue_stop = 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 9e76799c4750..97e38d2e2983 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
| @@ -69,8 +69,8 @@ | |||
| 69 | #include "iwl-agn-hw.h" | 69 | #include "iwl-agn-hw.h" |
| 70 | 70 | ||
| 71 | /* Highest firmware API version supported */ | 71 | /* Highest firmware API version supported */ |
| 72 | #define IWL7260_UCODE_API_MAX 10 | 72 | #define IWL7260_UCODE_API_MAX 12 |
| 73 | #define IWL3160_UCODE_API_MAX 10 | 73 | #define IWL3160_UCODE_API_MAX 12 |
| 74 | 74 | ||
| 75 | /* Oldest version we won't warn about */ | 75 | /* Oldest version we won't warn about */ |
| 76 | #define IWL7260_UCODE_API_OK 10 | 76 | #define IWL7260_UCODE_API_OK 10 |
| @@ -111,7 +111,7 @@ | |||
| 111 | #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" | 111 | #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" |
| 112 | 112 | ||
| 113 | #define IWL7265D_FW_PRE "iwlwifi-7265D-" | 113 | #define IWL7265D_FW_PRE "iwlwifi-7265D-" |
| 114 | #define IWL7265D_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" | 114 | #define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE __stringify(api) ".ucode" |
| 115 | 115 | ||
| 116 | #define NVM_HW_SECTION_NUM_FAMILY_7000 0 | 116 | #define NVM_HW_SECTION_NUM_FAMILY_7000 0 |
| 117 | 117 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index 46e9c9ac6ba2..2f7fe8167dc9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c | |||
| @@ -69,7 +69,7 @@ | |||
| 69 | #include "iwl-agn-hw.h" | 69 | #include "iwl-agn-hw.h" |
| 70 | 70 | ||
| 71 | /* Highest firmware API version supported */ | 71 | /* Highest firmware API version supported */ |
| 72 | #define IWL8000_UCODE_API_MAX 10 | 72 | #define IWL8000_UCODE_API_MAX 12 |
| 73 | 73 | ||
| 74 | /* Oldest version we won't warn about */ | 74 | /* Oldest version we won't warn about */ |
| 75 | #define IWL8000_UCODE_API_OK 10 | 75 | #define IWL8000_UCODE_API_OK 10 |
| @@ -84,6 +84,8 @@ | |||
| 84 | /* Memory offsets and lengths */ | 84 | /* Memory offsets and lengths */ |
| 85 | #define IWL8260_DCCM_OFFSET 0x800000 | 85 | #define IWL8260_DCCM_OFFSET 0x800000 |
| 86 | #define IWL8260_DCCM_LEN 0x18000 | 86 | #define IWL8260_DCCM_LEN 0x18000 |
| 87 | #define IWL8260_DCCM2_OFFSET 0x880000 | ||
| 88 | #define IWL8260_DCCM2_LEN 0x8000 | ||
| 87 | #define IWL8260_SMEM_OFFSET 0x400000 | 89 | #define IWL8260_SMEM_OFFSET 0x400000 |
| 88 | #define IWL8260_SMEM_LEN 0x68000 | 90 | #define IWL8260_SMEM_LEN 0x68000 |
| 89 | 91 | ||
| @@ -134,6 +136,8 @@ static const struct iwl_ht_params iwl8000_ht_params = { | |||
| 134 | .non_shared_ant = ANT_A, \ | 136 | .non_shared_ant = ANT_A, \ |
| 135 | .dccm_offset = IWL8260_DCCM_OFFSET, \ | 137 | .dccm_offset = IWL8260_DCCM_OFFSET, \ |
| 136 | .dccm_len = IWL8260_DCCM_LEN, \ | 138 | .dccm_len = IWL8260_DCCM_LEN, \ |
| 139 | .dccm2_offset = IWL8260_DCCM2_OFFSET, \ | ||
| 140 | .dccm2_len = IWL8260_DCCM2_LEN, \ | ||
| 137 | .smem_offset = IWL8260_SMEM_OFFSET, \ | 141 | .smem_offset = IWL8260_SMEM_OFFSET, \ |
| 138 | .smem_len = IWL8260_SMEM_LEN | 142 | .smem_len = IWL8260_SMEM_LEN |
| 139 | 143 | ||
| @@ -156,6 +160,16 @@ const struct iwl_cfg iwl8260_2ac_cfg = { | |||
| 156 | .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, | 160 | .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, |
| 157 | }; | 161 | }; |
| 158 | 162 | ||
| 163 | const struct iwl_cfg iwl4165_2ac_cfg = { | ||
| 164 | .name = "Intel(R) Dual Band Wireless AC 4165", | ||
| 165 | .fw_name_pre = IWL8000_FW_PRE, | ||
| 166 | IWL_DEVICE_8000, | ||
| 167 | .ht_params = &iwl8000_ht_params, | ||
| 168 | .nvm_ver = IWL8000_NVM_VERSION, | ||
| 169 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | ||
| 170 | .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, | ||
| 171 | }; | ||
| 172 | |||
| 159 | const struct iwl_cfg iwl8260_2ac_sdio_cfg = { | 173 | const struct iwl_cfg iwl8260_2ac_sdio_cfg = { |
| 160 | .name = "Intel(R) Dual Band Wireless-AC 8260", | 174 | .name = "Intel(R) Dual Band Wireless-AC 8260", |
| 161 | .fw_name_pre = IWL8000_FW_PRE, | 175 | .fw_name_pre = IWL8000_FW_PRE, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index fa0bc4845e1a..4b190d98a1ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
| @@ -126,7 +126,7 @@ enum iwl_led_mode { | |||
| 126 | 126 | ||
| 127 | /* TX queue watchdog timeouts in mSecs */ | 127 | /* TX queue watchdog timeouts in mSecs */ |
| 128 | #define IWL_WATCHDOG_DISABLED 0 | 128 | #define IWL_WATCHDOG_DISABLED 0 |
| 129 | #define IWL_DEF_WD_TIMEOUT 2000 | 129 | #define IWL_DEF_WD_TIMEOUT 2500 |
| 130 | #define IWL_LONG_WD_TIMEOUT 10000 | 130 | #define IWL_LONG_WD_TIMEOUT 10000 |
| 131 | #define IWL_MAX_WD_TIMEOUT 120000 | 131 | #define IWL_MAX_WD_TIMEOUT 120000 |
| 132 | 132 | ||
| @@ -263,6 +263,8 @@ struct iwl_pwr_tx_backoff { | |||
| 263 | * station can receive in VHT | 263 | * station can receive in VHT |
| 264 | * @dccm_offset: offset from which DCCM begins | 264 | * @dccm_offset: offset from which DCCM begins |
| 265 | * @dccm_len: length of DCCM (including runtime stack CCM) | 265 | * @dccm_len: length of DCCM (including runtime stack CCM) |
| 266 | * @dccm2_offset: offset from which the second DCCM begins | ||
| 267 | * @dccm2_len: length of the second DCCM | ||
| 266 | * @smem_offset: offset from which the SMEM begins | 268 | * @smem_offset: offset from which the SMEM begins |
| 267 | * @smem_len: the length of SMEM | 269 | * @smem_len: the length of SMEM |
| 268 | * | 270 | * |
| @@ -310,6 +312,8 @@ struct iwl_cfg { | |||
| 310 | unsigned int max_vht_ampdu_exponent; | 312 | unsigned int max_vht_ampdu_exponent; |
| 311 | const u32 dccm_offset; | 313 | const u32 dccm_offset; |
| 312 | const u32 dccm_len; | 314 | const u32 dccm_len; |
| 315 | const u32 dccm2_offset; | ||
| 316 | const u32 dccm2_len; | ||
| 313 | const u32 smem_offset; | 317 | const u32 smem_offset; |
| 314 | const u32 smem_len; | 318 | const u32 smem_len; |
| 315 | }; | 319 | }; |
| @@ -378,6 +382,7 @@ extern const struct iwl_cfg iwl7265d_2n_cfg; | |||
| 378 | extern const struct iwl_cfg iwl7265d_n_cfg; | 382 | extern const struct iwl_cfg iwl7265d_n_cfg; |
| 379 | extern const struct iwl_cfg iwl8260_2n_cfg; | 383 | extern const struct iwl_cfg iwl8260_2n_cfg; |
| 380 | extern const struct iwl_cfg iwl8260_2ac_cfg; | 384 | extern const struct iwl_cfg iwl8260_2ac_cfg; |
| 385 | extern const struct iwl_cfg iwl4165_2ac_cfg; | ||
| 381 | extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; | 386 | extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; |
| 382 | extern const struct iwl_cfg iwl4165_2ac_sdio_cfg; | 387 | extern const struct iwl_cfg iwl4165_2ac_sdio_cfg; |
| 383 | #endif /* CONFIG_IWLMVM */ | 388 | #endif /* CONFIG_IWLMVM */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 7f40cf36ec0e..faa17f2e352a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
| @@ -307,6 +307,7 @@ | |||
| 307 | enum { | 307 | enum { |
| 308 | SILICON_A_STEP = 0, | 308 | SILICON_A_STEP = 0, |
| 309 | SILICON_B_STEP, | 309 | SILICON_B_STEP, |
| 310 | SILICON_C_STEP, | ||
| 310 | }; | 311 | }; |
| 311 | 312 | ||
| 312 | 313 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index e766dcdf72ab..996e7f16adf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
| @@ -1367,7 +1367,6 @@ struct iwl_mod_params iwlwifi_mod_params = { | |||
| 1367 | .restart_fw = true, | 1367 | .restart_fw = true, |
| 1368 | .bt_coex_active = true, | 1368 | .bt_coex_active = true, |
| 1369 | .power_level = IWL_POWER_INDEX_1, | 1369 | .power_level = IWL_POWER_INDEX_1, |
| 1370 | .wd_disable = true, | ||
| 1371 | .d0i3_disable = true, | 1370 | .d0i3_disable = true, |
| 1372 | #ifndef CONFIG_IWLWIFI_UAPSD | 1371 | #ifndef CONFIG_IWLWIFI_UAPSD |
| 1373 | .uapsd_disable = true, | 1372 | .uapsd_disable = true, |
| @@ -1478,10 +1477,6 @@ module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, | |||
| 1478 | MODULE_PARM_DESC(antenna_coupling, | 1477 | MODULE_PARM_DESC(antenna_coupling, |
| 1479 | "specify antenna coupling in dB (default: 0 dB)"); | 1478 | "specify antenna coupling in dB (default: 0 dB)"); |
| 1480 | 1479 | ||
| 1481 | module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); | ||
| 1482 | MODULE_PARM_DESC(wd_disable, | ||
| 1483 | "Disable stuck queue watchdog timer 0=system default, 1=disable (default: 1)"); | ||
| 1484 | |||
| 1485 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); | 1480 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); |
| 1486 | MODULE_PARM_DESC(nvm_file, "NVM file name"); | 1481 | MODULE_PARM_DESC(nvm_file, "NVM file name"); |
| 1487 | 1482 | ||
| @@ -1490,7 +1485,7 @@ module_param_named(d0i3_disable, iwlwifi_mod_params.d0i3_disable, | |||
| 1490 | MODULE_PARM_DESC(d0i3_disable, "disable d0i3 functionality (default: Y)"); | 1485 | MODULE_PARM_DESC(d0i3_disable, "disable d0i3 functionality (default: Y)"); |
| 1491 | 1486 | ||
| 1492 | module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, | 1487 | module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, |
| 1493 | bool, S_IRUGO); | 1488 | bool, S_IRUGO | S_IWUSR); |
| 1494 | #ifdef CONFIG_IWLWIFI_UAPSD | 1489 | #ifdef CONFIG_IWLWIFI_UAPSD |
| 1495 | MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: N)"); | 1490 | MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: N)"); |
| 1496 | #else | 1491 | #else |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index ec115bded88a..919a2548a92c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | |||
| @@ -134,6 +134,27 @@ struct iwl_fw_error_dump_txcmd { | |||
| 134 | u8 data[]; | 134 | u8 data[]; |
| 135 | } __packed; | 135 | } __packed; |
| 136 | 136 | ||
| 137 | /** | ||
| 138 | * struct iwl_fw_error_dump_fifo - RX/TX FIFO data | ||
| 139 | * @fifo_num: number of FIFO (starting from 0) | ||
| 140 | * @available_bytes: num of bytes available in FIFO (may be less than FIFO size) | ||
| 141 | * @wr_ptr: position of write pointer | ||
| 142 | * @rd_ptr: position of read pointer | ||
| 143 | * @fence_ptr: position of fence pointer | ||
| 144 | * @fence_mode: the current mode of the fence (before locking) - | ||
| 145 | * 0=follow RD pointer ; 1 = freeze | ||
| 146 | * @data: all of the FIFO's data | ||
| 147 | */ | ||
| 148 | struct iwl_fw_error_dump_fifo { | ||
| 149 | __le32 fifo_num; | ||
| 150 | __le32 available_bytes; | ||
| 151 | __le32 wr_ptr; | ||
| 152 | __le32 rd_ptr; | ||
| 153 | __le32 fence_ptr; | ||
| 154 | __le32 fence_mode; | ||
| 155 | u8 data[]; | ||
| 156 | } __packed; | ||
| 157 | |||
| 137 | enum iwl_fw_error_dump_family { | 158 | enum iwl_fw_error_dump_family { |
| 138 | IWL_FW_ERROR_DUMP_FAMILY_7 = 7, | 159 | IWL_FW_ERROR_DUMP_FAMILY_7 = 7, |
| 139 | IWL_FW_ERROR_DUMP_FAMILY_8 = 8, | 160 | IWL_FW_ERROR_DUMP_FAMILY_8 = 8, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 752c72b77fba..016d91384681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
| @@ -235,25 +235,34 @@ enum iwl_ucode_tlv_flag { | |||
| 235 | 235 | ||
| 236 | /** | 236 | /** |
| 237 | * enum iwl_ucode_tlv_api - ucode api | 237 | * enum iwl_ucode_tlv_api - ucode api |
| 238 | * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field. | ||
| 239 | * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification | ||
| 240 | * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex | 238 | * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex |
| 241 | * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA. | ||
| 242 | * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit. | 239 | * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit. |
| 243 | * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API. | 240 | * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API. |
| 244 | * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif. | 241 | * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif. |
| 245 | * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time | 242 | * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time |
| 246 | * longer than the passive one, which is essential for fragmented scan. | 243 | * longer than the passive one, which is essential for fragmented scan. |
| 244 | * IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR | ||
| 245 | * @IWL_UCODE_TLV_API_BASIC_DWELL: use only basic dwell time in scan command, | ||
| 246 | * regardless of the band or the number of the probes. FW will calculate | ||
| 247 | * the actual dwell time. | ||
| 248 | * @IWL_UCODE_TLV_API_SCD_CFG: This firmware can configure the scheduler | ||
| 249 | * through the dedicated host command. | ||
| 250 | * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too. | ||
| 251 | * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. | ||
| 252 | * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params | ||
| 247 | */ | 253 | */ |
| 248 | enum iwl_ucode_tlv_api { | 254 | enum iwl_ucode_tlv_api { |
| 249 | IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0), | ||
| 250 | IWL_UCODE_TLV_CAPA_EXTENDED_BEACON = BIT(1), | ||
| 251 | IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3), | 255 | IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3), |
| 252 | IWL_UCODE_TLV_API_CSA_FLOW = BIT(4), | ||
| 253 | IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5), | 256 | IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5), |
| 254 | IWL_UCODE_TLV_API_LMAC_SCAN = BIT(6), | 257 | IWL_UCODE_TLV_API_LMAC_SCAN = BIT(6), |
| 255 | IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF = BIT(7), | 258 | IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF = BIT(7), |
| 256 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8), | 259 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8), |
| 260 | IWL_UCODE_TLV_API_HDC_PHASE_0 = BIT(10), | ||
| 261 | IWL_UCODE_TLV_API_BASIC_DWELL = BIT(13), | ||
| 262 | IWL_UCODE_TLV_API_SCD_CFG = BIT(15), | ||
| 263 | IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = BIT(16), | ||
| 264 | IWL_UCODE_TLV_API_ASYNC_DTM = BIT(17), | ||
| 265 | IWL_UCODE_TLV_API_LQ_SS_PARAMS = BIT(18), | ||
| 257 | }; | 266 | }; |
| 258 | 267 | ||
| 259 | /** | 268 | /** |
| @@ -261,6 +270,7 @@ enum iwl_ucode_tlv_api { | |||
| 261 | * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 | 270 | * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 |
| 262 | * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory | 271 | * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory |
| 263 | * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan. | 272 | * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan. |
| 273 | * @IWL_UCODE_TLV_CAPA_BEAMFORMER: supports Beamformer | ||
| 264 | * @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality | 274 | * @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality |
| 265 | * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current | 275 | * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current |
| 266 | * tx power value into TPC Report action frame and Link Measurement Report | 276 | * tx power value into TPC Report action frame and Link Measurement Report |
| @@ -279,6 +289,7 @@ enum iwl_ucode_tlv_capa { | |||
| 279 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), | 289 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), |
| 280 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT = BIT(1), | 290 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT = BIT(1), |
| 281 | IWL_UCODE_TLV_CAPA_UMAC_SCAN = BIT(2), | 291 | IWL_UCODE_TLV_CAPA_UMAC_SCAN = BIT(2), |
| 292 | IWL_UCODE_TLV_CAPA_BEAMFORMER = BIT(3), | ||
| 282 | IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = BIT(6), | 293 | IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = BIT(6), |
| 283 | IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8), | 294 | IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8), |
| 284 | IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9), | 295 | IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9), |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 7a2cbf6f90db..03250a45272e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
| @@ -193,11 +193,15 @@ void iwl_force_nmi(struct iwl_trans *trans) | |||
| 193 | * DEVICE_SET_NMI_8000B_REG - is used. | 193 | * DEVICE_SET_NMI_8000B_REG - is used. |
| 194 | */ | 194 | */ |
| 195 | if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) || | 195 | if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) || |
| 196 | (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP)) | 196 | (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP)) { |
| 197 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, DEVICE_SET_NMI_VAL); | 197 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, |
| 198 | else | 198 | DEVICE_SET_NMI_VAL_DRV); |
| 199 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, | ||
| 200 | DEVICE_SET_NMI_VAL_HW); | ||
| 201 | } else { | ||
| 199 | iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG, | 202 | iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG, |
| 200 | DEVICE_SET_NMI_8000B_VAL); | 203 | DEVICE_SET_NMI_8000B_VAL); |
| 204 | } | ||
| 201 | } | 205 | } |
| 202 | IWL_EXPORT_SYMBOL(iwl_force_nmi); | 206 | IWL_EXPORT_SYMBOL(iwl_force_nmi); |
| 203 | 207 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 2a8cf4b2445c..e8eabd21ccfe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
| @@ -96,7 +96,6 @@ enum iwl_disable_11n { | |||
| 96 | * use IWL_[DIS,EN]ABLE_HT_* constants | 96 | * use IWL_[DIS,EN]ABLE_HT_* constants |
| 97 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 | 97 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 |
| 98 | * @restart_fw: restart firmware, default = 1 | 98 | * @restart_fw: restart firmware, default = 1 |
| 99 | * @wd_disable: disable stuck queue check, default = 1 | ||
| 100 | * @bt_coex_active: enable bt coex, default = true | 99 | * @bt_coex_active: enable bt coex, default = true |
| 101 | * @led_mode: system default, default = 0 | 100 | * @led_mode: system default, default = 0 |
| 102 | * @power_save: enable power save, default = false | 101 | * @power_save: enable power save, default = false |
| @@ -111,7 +110,6 @@ struct iwl_mod_params { | |||
| 111 | unsigned int disable_11n; | 110 | unsigned int disable_11n; |
| 112 | int amsdu_size_8K; | 111 | int amsdu_size_8K; |
| 113 | bool restart_fw; | 112 | bool restart_fw; |
| 114 | int wd_disable; | ||
| 115 | bool bt_coex_active; | 113 | bool bt_coex_active; |
| 116 | int led_mode; | 114 | int led_mode; |
| 117 | bool power_save; | 115 | bool power_save; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 83ab4239082c..6221e4dfc64f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
| @@ -108,7 +108,8 @@ | |||
| 108 | 108 | ||
| 109 | /* Device NMI register */ | 109 | /* Device NMI register */ |
| 110 | #define DEVICE_SET_NMI_REG 0x00a01c30 | 110 | #define DEVICE_SET_NMI_REG 0x00a01c30 |
| 111 | #define DEVICE_SET_NMI_VAL 0x1 | 111 | #define DEVICE_SET_NMI_VAL_HW BIT(0) |
| 112 | #define DEVICE_SET_NMI_VAL_DRV BIT(7) | ||
| 112 | #define DEVICE_SET_NMI_8000B_REG 0x00a01c24 | 113 | #define DEVICE_SET_NMI_8000B_REG 0x00a01c24 |
| 113 | #define DEVICE_SET_NMI_8000B_VAL 0x1000000 | 114 | #define DEVICE_SET_NMI_8000B_VAL 0x1000000 |
| 114 | 115 | ||
| @@ -251,6 +252,7 @@ | |||
| 251 | #define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) | 252 | #define SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) |
| 252 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) | 253 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) |
| 253 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) | 254 | #define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) |
| 255 | #define SCD_GP_CTRL_ENABLE_31_QUEUES BIT(0) | ||
| 254 | 256 | ||
| 255 | /* Context Data */ | 257 | /* Context Data */ |
| 256 | #define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) | 258 | #define SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) |
| @@ -284,32 +286,9 @@ | |||
| 284 | #define SCD_CHAINEXT_EN (SCD_BASE + 0x244) | 286 | #define SCD_CHAINEXT_EN (SCD_BASE + 0x244) |
| 285 | #define SCD_AGGR_SEL (SCD_BASE + 0x248) | 287 | #define SCD_AGGR_SEL (SCD_BASE + 0x248) |
| 286 | #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) | 288 | #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) |
| 289 | #define SCD_GP_CTRL (SCD_BASE + 0x1a8) | ||
| 287 | #define SCD_EN_CTRL (SCD_BASE + 0x254) | 290 | #define SCD_EN_CTRL (SCD_BASE + 0x254) |
| 288 | 291 | ||
| 289 | static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl) | ||
| 290 | { | ||
| 291 | if (chnl < 20) | ||
| 292 | return SCD_BASE + 0x18 + chnl * 4; | ||
| 293 | WARN_ON_ONCE(chnl >= 32); | ||
| 294 | return SCD_BASE + 0x284 + (chnl - 20) * 4; | ||
| 295 | } | ||
| 296 | |||
| 297 | static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl) | ||
| 298 | { | ||
| 299 | if (chnl < 20) | ||
| 300 | return SCD_BASE + 0x68 + chnl * 4; | ||
| 301 | WARN_ON_ONCE(chnl >= 32); | ||
| 302 | return SCD_BASE + 0x2B4 + (chnl - 20) * 4; | ||
| 303 | } | ||
| 304 | |||
| 305 | static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl) | ||
| 306 | { | ||
| 307 | if (chnl < 20) | ||
| 308 | return SCD_BASE + 0x10c + chnl * 4; | ||
| 309 | WARN_ON_ONCE(chnl >= 32); | ||
| 310 | return SCD_BASE + 0x384 + (chnl - 20) * 4; | ||
| 311 | } | ||
| 312 | |||
| 313 | /*********************** END TX SCHEDULER *************************************/ | 292 | /*********************** END TX SCHEDULER *************************************/ |
| 314 | 293 | ||
| 315 | /* Oscillator clock */ | 294 | /* Oscillator clock */ |
| @@ -359,12 +338,30 @@ enum secure_load_status_reg { | |||
| 359 | 338 | ||
| 360 | /* Rx FIFO */ | 339 | /* Rx FIFO */ |
| 361 | #define RXF_SIZE_ADDR (0xa00c88) | 340 | #define RXF_SIZE_ADDR (0xa00c88) |
| 341 | #define RXF_RD_D_SPACE (0xa00c40) | ||
| 342 | #define RXF_RD_WR_PTR (0xa00c50) | ||
| 343 | #define RXF_RD_RD_PTR (0xa00c54) | ||
| 344 | #define RXF_RD_FENCE_PTR (0xa00c4c) | ||
| 345 | #define RXF_SET_FENCE_MODE (0xa00c14) | ||
| 346 | #define RXF_LD_WR2FENCE (0xa00c1c) | ||
| 347 | #define RXF_FIFO_RD_FENCE_INC (0xa00c68) | ||
| 362 | #define RXF_SIZE_BYTE_CND_POS (7) | 348 | #define RXF_SIZE_BYTE_CND_POS (7) |
| 363 | #define RXF_SIZE_BYTE_CNT_MSK (0x3ff << RXF_SIZE_BYTE_CND_POS) | 349 | #define RXF_SIZE_BYTE_CNT_MSK (0x3ff << RXF_SIZE_BYTE_CND_POS) |
| 350 | #define RXF_DIFF_FROM_PREV (0x200) | ||
| 364 | 351 | ||
| 365 | #define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10) | 352 | #define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10) |
| 366 | #define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c) | 353 | #define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c) |
| 367 | 354 | ||
| 355 | /* Tx FIFO */ | ||
| 356 | #define TXF_FIFO_ITEM_CNT (0xa00438) | ||
| 357 | #define TXF_WR_PTR (0xa00414) | ||
| 358 | #define TXF_RD_PTR (0xa00410) | ||
| 359 | #define TXF_FENCE_PTR (0xa00418) | ||
| 360 | #define TXF_LOCK_FENCE (0xa00424) | ||
| 361 | #define TXF_LARC_NUM (0xa0043c) | ||
| 362 | #define TXF_READ_MODIFY_DATA (0xa00448) | ||
| 363 | #define TXF_READ_MODIFY_ADDR (0xa0044c) | ||
| 364 | |||
| 368 | /* FW monitor */ | 365 | /* FW monitor */ |
| 369 | #define MON_BUFF_SAMPLE_CTL (0xa03c00) | 366 | #define MON_BUFF_SAMPLE_CTL (0xa03c00) |
| 370 | #define MON_BUFF_BASE_ADDR (0xa03c3c) | 367 | #define MON_BUFF_BASE_ADDR (0xa03c3c) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scd.h b/drivers/net/wireless/iwlwifi/iwl-scd.h index 6c622b21bba7..f2353ebf2666 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scd.h +++ b/drivers/net/wireless/iwlwifi/iwl-scd.h | |||
| @@ -69,14 +69,6 @@ | |||
| 69 | #include "iwl-prph.h" | 69 | #include "iwl-prph.h" |
| 70 | 70 | ||
| 71 | 71 | ||
| 72 | static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans, | ||
| 73 | u16 txq_id) | ||
| 74 | { | ||
| 75 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), | ||
| 76 | (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
| 77 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans, | 72 | static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans, |
| 81 | u16 txq_id) | 73 | u16 txq_id) |
| 82 | { | 74 | { |
| @@ -115,4 +107,37 @@ static inline void iwl_scd_enable_set_active(struct iwl_trans *trans, | |||
| 115 | { | 107 | { |
| 116 | iwl_write_prph(trans, SCD_EN_CTRL, value); | 108 | iwl_write_prph(trans, SCD_EN_CTRL, value); |
| 117 | } | 109 | } |
| 110 | |||
| 111 | static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl) | ||
| 112 | { | ||
| 113 | if (chnl < 20) | ||
| 114 | return SCD_BASE + 0x18 + chnl * 4; | ||
| 115 | WARN_ON_ONCE(chnl >= 32); | ||
| 116 | return SCD_BASE + 0x284 + (chnl - 20) * 4; | ||
| 117 | } | ||
| 118 | |||
| 119 | static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl) | ||
| 120 | { | ||
| 121 | if (chnl < 20) | ||
| 122 | return SCD_BASE + 0x68 + chnl * 4; | ||
| 123 | WARN_ON_ONCE(chnl >= 32); | ||
| 124 | return SCD_BASE + 0x2B4 + chnl * 4; | ||
| 125 | } | ||
| 126 | |||
| 127 | static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl) | ||
| 128 | { | ||
| 129 | if (chnl < 20) | ||
| 130 | return SCD_BASE + 0x10c + chnl * 4; | ||
| 131 | WARN_ON_ONCE(chnl >= 32); | ||
| 132 | return SCD_BASE + 0x334 + chnl * 4; | ||
| 133 | } | ||
| 134 | |||
| 135 | static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans, | ||
| 136 | u16 txq_id) | ||
| 137 | { | ||
| 138 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), | ||
| 139 | (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
| 140 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
| 141 | } | ||
| 142 | |||
| 118 | #endif | 143 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 84d8477432a2..a96bd8db6ceb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
| @@ -368,6 +368,7 @@ enum iwl_trans_status { | |||
| 368 | * @cmd_queue: the index of the command queue. | 368 | * @cmd_queue: the index of the command queue. |
| 369 | * Must be set before start_fw. | 369 | * Must be set before start_fw. |
| 370 | * @cmd_fifo: the fifo for host commands | 370 | * @cmd_fifo: the fifo for host commands |
| 371 | * @cmd_q_wdg_timeout: the timeout of the watchdog timer for the command queue. | ||
| 371 | * @no_reclaim_cmds: Some devices erroneously don't set the | 372 | * @no_reclaim_cmds: Some devices erroneously don't set the |
| 372 | * SEQ_RX_FRAME bit on some notifications, this is the | 373 | * SEQ_RX_FRAME bit on some notifications, this is the |
| 373 | * list of such notifications to filter. Max length is | 374 | * list of such notifications to filter. Max length is |
| @@ -378,8 +379,6 @@ enum iwl_trans_status { | |||
| 378 | * @bc_table_dword: set to true if the BC table expects the byte count to be | 379 | * @bc_table_dword: set to true if the BC table expects the byte count to be |
| 379 | * in DWORD (as opposed to bytes) | 380 | * in DWORD (as opposed to bytes) |
| 380 | * @scd_set_active: should the transport configure the SCD for HCMD queue | 381 | * @scd_set_active: should the transport configure the SCD for HCMD queue |
| 381 | * @queue_watchdog_timeout: time (in ms) after which queues | ||
| 382 | * are considered stuck and will trigger device restart | ||
| 383 | * @command_names: array of command names, must be 256 entries | 382 | * @command_names: array of command names, must be 256 entries |
| 384 | * (one for each command); for debugging only | 383 | * (one for each command); for debugging only |
| 385 | * @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until | 384 | * @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until |
| @@ -390,13 +389,13 @@ struct iwl_trans_config { | |||
| 390 | 389 | ||
| 391 | u8 cmd_queue; | 390 | u8 cmd_queue; |
| 392 | u8 cmd_fifo; | 391 | u8 cmd_fifo; |
| 392 | unsigned int cmd_q_wdg_timeout; | ||
| 393 | const u8 *no_reclaim_cmds; | 393 | const u8 *no_reclaim_cmds; |
| 394 | unsigned int n_no_reclaim_cmds; | 394 | unsigned int n_no_reclaim_cmds; |
| 395 | 395 | ||
| 396 | bool rx_buf_size_8k; | 396 | bool rx_buf_size_8k; |
| 397 | bool bc_table_dword; | 397 | bool bc_table_dword; |
| 398 | bool scd_set_active; | 398 | bool scd_set_active; |
| 399 | unsigned int queue_watchdog_timeout; | ||
| 400 | const char *const *command_names; | 399 | const char *const *command_names; |
| 401 | 400 | ||
| 402 | u32 sdio_adma_addr; | 401 | u32 sdio_adma_addr; |
| @@ -511,7 +510,8 @@ struct iwl_trans_ops { | |||
| 511 | struct sk_buff_head *skbs); | 510 | struct sk_buff_head *skbs); |
| 512 | 511 | ||
| 513 | void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, | 512 | void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, |
| 514 | const struct iwl_trans_txq_scd_cfg *cfg); | 513 | const struct iwl_trans_txq_scd_cfg *cfg, |
| 514 | unsigned int queue_wdg_timeout); | ||
| 515 | void (*txq_disable)(struct iwl_trans *trans, int queue, | 515 | void (*txq_disable)(struct iwl_trans *trans, int queue, |
| 516 | bool configure_scd); | 516 | bool configure_scd); |
| 517 | 517 | ||
| @@ -829,19 +829,21 @@ static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue, | |||
| 829 | 829 | ||
| 830 | static inline void | 830 | static inline void |
| 831 | iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn, | 831 | iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn, |
| 832 | const struct iwl_trans_txq_scd_cfg *cfg) | 832 | const struct iwl_trans_txq_scd_cfg *cfg, |
| 833 | unsigned int queue_wdg_timeout) | ||
| 833 | { | 834 | { |
| 834 | might_sleep(); | 835 | might_sleep(); |
| 835 | 836 | ||
| 836 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) | 837 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) |
| 837 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); | 838 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
| 838 | 839 | ||
| 839 | trans->ops->txq_enable(trans, queue, ssn, cfg); | 840 | trans->ops->txq_enable(trans, queue, ssn, cfg, queue_wdg_timeout); |
| 840 | } | 841 | } |
| 841 | 842 | ||
| 842 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | 843 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, |
| 843 | int fifo, int sta_id, int tid, | 844 | int fifo, int sta_id, int tid, |
| 844 | int frame_limit, u16 ssn) | 845 | int frame_limit, u16 ssn, |
| 846 | unsigned int queue_wdg_timeout) | ||
| 845 | { | 847 | { |
| 846 | struct iwl_trans_txq_scd_cfg cfg = { | 848 | struct iwl_trans_txq_scd_cfg cfg = { |
| 847 | .fifo = fifo, | 849 | .fifo = fifo, |
| @@ -851,11 +853,12 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | |||
| 851 | .aggregate = sta_id >= 0, | 853 | .aggregate = sta_id >= 0, |
| 852 | }; | 854 | }; |
| 853 | 855 | ||
| 854 | iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg); | 856 | iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg, queue_wdg_timeout); |
| 855 | } | 857 | } |
| 856 | 858 | ||
| 857 | static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | 859 | static inline |
| 858 | int fifo) | 860 | void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, int fifo, |
| 861 | unsigned int queue_wdg_timeout) | ||
| 859 | { | 862 | { |
| 860 | struct iwl_trans_txq_scd_cfg cfg = { | 863 | struct iwl_trans_txq_scd_cfg cfg = { |
| 861 | .fifo = fifo, | 864 | .fifo = fifo, |
| @@ -865,16 +868,16 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | |||
| 865 | .aggregate = false, | 868 | .aggregate = false, |
| 866 | }; | 869 | }; |
| 867 | 870 | ||
| 868 | iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg); | 871 | iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg, queue_wdg_timeout); |
| 869 | } | 872 | } |
| 870 | 873 | ||
| 871 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, | 874 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, |
| 872 | u32 txq_bm) | 875 | u32 txqs) |
| 873 | { | 876 | { |
| 874 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | 877 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 875 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); | 878 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
| 876 | 879 | ||
| 877 | return trans->ops->wait_tx_queue_empty(trans, txq_bm); | 880 | return trans->ops->wait_tx_queue_empty(trans, txqs); |
| 878 | } | 881 | } |
| 879 | 882 | ||
| 880 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | 883 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index d2fd48c31d3d..1ec4d55155f7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
| @@ -342,7 +342,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 342 | { | 342 | { |
| 343 | .range = 12, | 343 | .range = 12, |
| 344 | .lut20 = { | 344 | .lut20 = { |
| 345 | cpu_to_le32(0x00000001), cpu_to_le32(0x00000000), | 345 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 346 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 346 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 347 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 347 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 348 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 348 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -363,7 +363,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 363 | { | 363 | { |
| 364 | .range = 20, | 364 | .range = 20, |
| 365 | .lut20 = { | 365 | .lut20 = { |
| 366 | cpu_to_le32(0x00000002), cpu_to_le32(0x00000000), | 366 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 367 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 367 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 368 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 368 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 369 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 369 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -384,7 +384,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 384 | { | 384 | { |
| 385 | .range = 21, | 385 | .range = 21, |
| 386 | .lut20 = { | 386 | .lut20 = { |
| 387 | cpu_to_le32(0x00000003), cpu_to_le32(0x00000000), | 387 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 388 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 388 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 389 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 389 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 390 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 390 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -405,7 +405,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 405 | { | 405 | { |
| 406 | .range = 23, | 406 | .range = 23, |
| 407 | .lut20 = { | 407 | .lut20 = { |
| 408 | cpu_to_le32(0x00000004), cpu_to_le32(0x00000000), | 408 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 409 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 409 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 410 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 410 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 411 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 411 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -426,7 +426,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 426 | { | 426 | { |
| 427 | .range = 27, | 427 | .range = 27, |
| 428 | .lut20 = { | 428 | .lut20 = { |
| 429 | cpu_to_le32(0x00000005), cpu_to_le32(0x00000000), | 429 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 430 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 430 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 431 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 431 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 432 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 432 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -447,7 +447,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 447 | { | 447 | { |
| 448 | .range = 30, | 448 | .range = 30, |
| 449 | .lut20 = { | 449 | .lut20 = { |
| 450 | cpu_to_le32(0x00000006), cpu_to_le32(0x00000000), | 450 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 451 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 451 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 452 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 452 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 453 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 453 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -468,7 +468,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 468 | { | 468 | { |
| 469 | .range = 32, | 469 | .range = 32, |
| 470 | .lut20 = { | 470 | .lut20 = { |
| 471 | cpu_to_le32(0x00000007), cpu_to_le32(0x00000000), | 471 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 472 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 472 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 473 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 473 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 474 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 474 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -489,7 +489,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 489 | { | 489 | { |
| 490 | .range = 33, | 490 | .range = 33, |
| 491 | .lut20 = { | 491 | .lut20 = { |
| 492 | cpu_to_le32(0x00000008), cpu_to_le32(0x00000000), | 492 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 493 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 493 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 494 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 494 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 495 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 495 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c index 973f2881dd1d..d530ef3da107 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c | |||
| @@ -330,7 +330,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 330 | { | 330 | { |
| 331 | .range = 12, | 331 | .range = 12, |
| 332 | .lut20 = { | 332 | .lut20 = { |
| 333 | cpu_to_le32(0x00000001), cpu_to_le32(0x00000000), | 333 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 334 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 334 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 335 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 335 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 336 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 336 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -351,7 +351,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 351 | { | 351 | { |
| 352 | .range = 20, | 352 | .range = 20, |
| 353 | .lut20 = { | 353 | .lut20 = { |
| 354 | cpu_to_le32(0x00000002), cpu_to_le32(0x00000000), | 354 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 355 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 355 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 356 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 356 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 357 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 357 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -372,7 +372,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 372 | { | 372 | { |
| 373 | .range = 21, | 373 | .range = 21, |
| 374 | .lut20 = { | 374 | .lut20 = { |
| 375 | cpu_to_le32(0x00000003), cpu_to_le32(0x00000000), | 375 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 376 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 376 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 377 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 377 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 378 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 378 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -393,7 +393,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 393 | { | 393 | { |
| 394 | .range = 23, | 394 | .range = 23, |
| 395 | .lut20 = { | 395 | .lut20 = { |
| 396 | cpu_to_le32(0x00000004), cpu_to_le32(0x00000000), | 396 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 397 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 397 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 398 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 398 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 399 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 399 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -414,7 +414,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 414 | { | 414 | { |
| 415 | .range = 27, | 415 | .range = 27, |
| 416 | .lut20 = { | 416 | .lut20 = { |
| 417 | cpu_to_le32(0x00000005), cpu_to_le32(0x00000000), | 417 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 418 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 418 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 419 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 419 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 420 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 420 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -435,7 +435,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 435 | { | 435 | { |
| 436 | .range = 30, | 436 | .range = 30, |
| 437 | .lut20 = { | 437 | .lut20 = { |
| 438 | cpu_to_le32(0x00000006), cpu_to_le32(0x00000000), | 438 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 439 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 439 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 440 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 440 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 441 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 441 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -456,7 +456,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 456 | { | 456 | { |
| 457 | .range = 32, | 457 | .range = 32, |
| 458 | .lut20 = { | 458 | .lut20 = { |
| 459 | cpu_to_le32(0x00000007), cpu_to_le32(0x00000000), | 459 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 460 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 460 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 461 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 461 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 462 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 462 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| @@ -477,7 +477,7 @@ static const struct corunning_block_luts antenna_coupling_ranges[] = { | |||
| 477 | { | 477 | { |
| 478 | .range = 33, | 478 | .range = 33, |
| 479 | .lut20 = { | 479 | .lut20 = { |
| 480 | cpu_to_le32(0x00000008), cpu_to_le32(0x00000000), | 480 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 481 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 481 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 482 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 482 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
| 483 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), | 483 | cpu_to_le32(0x00000000), cpu_to_le32(0x00000000), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index 7cd1de820ca7..beba375489f1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
| @@ -94,21 +94,22 @@ | |||
| 94 | #define IWL_MVM_BT_COEX_MPLUT 1 | 94 | #define IWL_MVM_BT_COEX_MPLUT 1 |
| 95 | #define IWL_MVM_BT_COEX_RRC 1 | 95 | #define IWL_MVM_BT_COEX_RRC 1 |
| 96 | #define IWL_MVM_BT_COEX_TTC 1 | 96 | #define IWL_MVM_BT_COEX_TTC 1 |
| 97 | #define IWL_MVM_BT_COEX_MPLUT_REG0 0x28412201 | 97 | #define IWL_MVM_BT_COEX_MPLUT_REG0 0x22002200 |
| 98 | #define IWL_MVM_BT_COEX_MPLUT_REG1 0x11118451 | 98 | #define IWL_MVM_BT_COEX_MPLUT_REG1 0x11118451 |
| 99 | #define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 | 99 | #define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 |
| 100 | #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 | 100 | #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 |
| 101 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 | 101 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 |
| 102 | #define IWL_MVM_QUOTA_THRESHOLD 8 | 102 | #define IWL_MVM_QUOTA_THRESHOLD 4 |
| 103 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 | 103 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 |
| 104 | #define IWL_MVM_RS_DISABLE_MIMO 0 | 104 | #define IWL_MVM_RS_DISABLE_P2P_MIMO 0 |
| 105 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 | 105 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 |
| 106 | #define IWL_MVM_RS_LEGACY_RETRIES_PER_RATE 1 | ||
| 107 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 | 106 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 |
| 108 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 | 107 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 |
| 109 | #define IWL_MVM_RS_INITIAL_MIMO_NUM_RATES 3 | 108 | #define IWL_MVM_RS_INITIAL_MIMO_NUM_RATES 3 |
| 110 | #define IWL_MVM_RS_INITIAL_SISO_NUM_RATES 3 | 109 | #define IWL_MVM_RS_INITIAL_SISO_NUM_RATES 3 |
| 111 | #define IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES 16 | 110 | #define IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES 2 |
| 111 | #define IWL_MVM_RS_INITIAL_LEGACY_RETRIES 2 | ||
| 112 | #define IWL_MVM_RS_SECONDARY_LEGACY_RETRIES 1 | ||
| 112 | #define IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES 16 | 113 | #define IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES 16 |
| 113 | #define IWL_MVM_RS_SECONDARY_SISO_NUM_RATES 3 | 114 | #define IWL_MVM_RS_SECONDARY_SISO_NUM_RATES 3 |
| 114 | #define IWL_MVM_RS_SECONDARY_SISO_RETRIES 1 | 115 | #define IWL_MVM_RS_SECONDARY_SISO_RETRIES 1 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 8dc3ca9f4904..5fe14591e1c4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
| @@ -517,6 +517,34 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file, | |||
| 517 | return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); | 517 | return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); |
| 518 | } | 518 | } |
| 519 | 519 | ||
| 520 | static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file, | ||
| 521 | char __user *user_buf, | ||
| 522 | size_t count, loff_t *ppos) | ||
| 523 | { | ||
| 524 | struct ieee80211_vif *vif = file->private_data; | ||
| 525 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 526 | char buf[20]; | ||
| 527 | int len; | ||
| 528 | |||
| 529 | len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid); | ||
| 530 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 531 | } | ||
| 532 | |||
| 533 | static ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif, | ||
| 534 | char *buf, size_t count, | ||
| 535 | loff_t *ppos) | ||
| 536 | { | ||
| 537 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 538 | struct iwl_mvm *mvm = mvmvif->mvm; | ||
| 539 | bool ret; | ||
| 540 | |||
| 541 | mutex_lock(&mvm->mutex); | ||
| 542 | ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid); | ||
| 543 | mutex_unlock(&mvm->mutex); | ||
| 544 | |||
| 545 | return ret ? count : -EINVAL; | ||
| 546 | } | ||
| 547 | |||
| 520 | #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ | 548 | #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ |
| 521 | _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) | 549 | _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) |
| 522 | #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ | 550 | #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ |
| @@ -531,6 +559,7 @@ MVM_DEBUGFS_READ_FILE_OPS(mac_params); | |||
| 531 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32); | 559 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32); |
| 532 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256); | 560 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256); |
| 533 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10); | 561 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10); |
| 562 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20); | ||
| 534 | 563 | ||
| 535 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 564 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
| 536 | { | 565 | { |
| @@ -564,6 +593,8 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 564 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR); | 593 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR); |
| 565 | MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, | 594 | MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, |
| 566 | S_IRUSR | S_IWUSR); | 595 | S_IRUSR | S_IWUSR); |
| 596 | MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir, | ||
| 597 | S_IRUSR | S_IWUSR); | ||
| 567 | 598 | ||
| 568 | if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && | 599 | if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && |
| 569 | mvmvif == mvm->bf_allowed_vif) | 600 | mvmvif == mvm->bf_allowed_vif) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index a1b276c4dee0..82c09d86af8c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
| @@ -654,10 +654,10 @@ out: | |||
| 654 | return ret ?: count; | 654 | return ret ?: count; |
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | #define PRINT_STATS_LE32(_str, _val) \ | 657 | #define PRINT_STATS_LE32(_struct, _memb) \ |
| 658 | pos += scnprintf(buf + pos, bufsz - pos, \ | 658 | pos += scnprintf(buf + pos, bufsz - pos, \ |
| 659 | fmt_table, _str, \ | 659 | fmt_table, #_memb, \ |
| 660 | le32_to_cpu(_val)) | 660 | le32_to_cpu(_struct->_memb)) |
| 661 | 661 | ||
| 662 | static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, | 662 | static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, |
| 663 | char __user *user_buf, size_t count, | 663 | char __user *user_buf, size_t count, |
| @@ -692,97 +692,89 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, | |||
| 692 | 692 | ||
| 693 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, | 693 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, |
| 694 | "Statistics_Rx - OFDM"); | 694 | "Statistics_Rx - OFDM"); |
| 695 | PRINT_STATS_LE32("ina_cnt", ofdm->ina_cnt); | 695 | PRINT_STATS_LE32(ofdm, ina_cnt); |
| 696 | PRINT_STATS_LE32("fina_cnt", ofdm->fina_cnt); | 696 | PRINT_STATS_LE32(ofdm, fina_cnt); |
| 697 | PRINT_STATS_LE32("plcp_err", ofdm->plcp_err); | 697 | PRINT_STATS_LE32(ofdm, plcp_err); |
| 698 | PRINT_STATS_LE32("crc32_err", ofdm->crc32_err); | 698 | PRINT_STATS_LE32(ofdm, crc32_err); |
| 699 | PRINT_STATS_LE32("overrun_err", ofdm->overrun_err); | 699 | PRINT_STATS_LE32(ofdm, overrun_err); |
| 700 | PRINT_STATS_LE32("early_overrun_err", ofdm->early_overrun_err); | 700 | PRINT_STATS_LE32(ofdm, early_overrun_err); |
| 701 | PRINT_STATS_LE32("crc32_good", ofdm->crc32_good); | 701 | PRINT_STATS_LE32(ofdm, crc32_good); |
| 702 | PRINT_STATS_LE32("false_alarm_cnt", ofdm->false_alarm_cnt); | 702 | PRINT_STATS_LE32(ofdm, false_alarm_cnt); |
| 703 | PRINT_STATS_LE32("fina_sync_err_cnt", ofdm->fina_sync_err_cnt); | 703 | PRINT_STATS_LE32(ofdm, fina_sync_err_cnt); |
| 704 | PRINT_STATS_LE32("sfd_timeout", ofdm->sfd_timeout); | 704 | PRINT_STATS_LE32(ofdm, sfd_timeout); |
| 705 | PRINT_STATS_LE32("fina_timeout", ofdm->fina_timeout); | 705 | PRINT_STATS_LE32(ofdm, fina_timeout); |
| 706 | PRINT_STATS_LE32("unresponded_rts", ofdm->unresponded_rts); | 706 | PRINT_STATS_LE32(ofdm, unresponded_rts); |
| 707 | PRINT_STATS_LE32("rxe_frame_lmt_overrun", | 707 | PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun); |
| 708 | ofdm->rxe_frame_limit_overrun); | 708 | PRINT_STATS_LE32(ofdm, sent_ack_cnt); |
| 709 | PRINT_STATS_LE32("sent_ack_cnt", ofdm->sent_ack_cnt); | 709 | PRINT_STATS_LE32(ofdm, sent_cts_cnt); |
| 710 | PRINT_STATS_LE32("sent_cts_cnt", ofdm->sent_cts_cnt); | 710 | PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt); |
| 711 | PRINT_STATS_LE32("sent_ba_rsp_cnt", ofdm->sent_ba_rsp_cnt); | 711 | PRINT_STATS_LE32(ofdm, dsp_self_kill); |
| 712 | PRINT_STATS_LE32("dsp_self_kill", ofdm->dsp_self_kill); | 712 | PRINT_STATS_LE32(ofdm, mh_format_err); |
| 713 | PRINT_STATS_LE32("mh_format_err", ofdm->mh_format_err); | 713 | PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum); |
| 714 | PRINT_STATS_LE32("re_acq_main_rssi_sum", ofdm->re_acq_main_rssi_sum); | 714 | PRINT_STATS_LE32(ofdm, reserved); |
| 715 | PRINT_STATS_LE32("reserved", ofdm->reserved); | ||
| 716 | 715 | ||
| 717 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, | 716 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, |
| 718 | "Statistics_Rx - CCK"); | 717 | "Statistics_Rx - CCK"); |
| 719 | PRINT_STATS_LE32("ina_cnt", cck->ina_cnt); | 718 | PRINT_STATS_LE32(cck, ina_cnt); |
| 720 | PRINT_STATS_LE32("fina_cnt", cck->fina_cnt); | 719 | PRINT_STATS_LE32(cck, fina_cnt); |
| 721 | PRINT_STATS_LE32("plcp_err", cck->plcp_err); | 720 | PRINT_STATS_LE32(cck, plcp_err); |
| 722 | PRINT_STATS_LE32("crc32_err", cck->crc32_err); | 721 | PRINT_STATS_LE32(cck, crc32_err); |
| 723 | PRINT_STATS_LE32("overrun_err", cck->overrun_err); | 722 | PRINT_STATS_LE32(cck, overrun_err); |
| 724 | PRINT_STATS_LE32("early_overrun_err", cck->early_overrun_err); | 723 | PRINT_STATS_LE32(cck, early_overrun_err); |
| 725 | PRINT_STATS_LE32("crc32_good", cck->crc32_good); | 724 | PRINT_STATS_LE32(cck, crc32_good); |
| 726 | PRINT_STATS_LE32("false_alarm_cnt", cck->false_alarm_cnt); | 725 | PRINT_STATS_LE32(cck, false_alarm_cnt); |
| 727 | PRINT_STATS_LE32("fina_sync_err_cnt", cck->fina_sync_err_cnt); | 726 | PRINT_STATS_LE32(cck, fina_sync_err_cnt); |
| 728 | PRINT_STATS_LE32("sfd_timeout", cck->sfd_timeout); | 727 | PRINT_STATS_LE32(cck, sfd_timeout); |
| 729 | PRINT_STATS_LE32("fina_timeout", cck->fina_timeout); | 728 | PRINT_STATS_LE32(cck, fina_timeout); |
| 730 | PRINT_STATS_LE32("unresponded_rts", cck->unresponded_rts); | 729 | PRINT_STATS_LE32(cck, unresponded_rts); |
| 731 | PRINT_STATS_LE32("rxe_frame_lmt_overrun", | 730 | PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun); |
| 732 | cck->rxe_frame_limit_overrun); | 731 | PRINT_STATS_LE32(cck, sent_ack_cnt); |
| 733 | PRINT_STATS_LE32("sent_ack_cnt", cck->sent_ack_cnt); | 732 | PRINT_STATS_LE32(cck, sent_cts_cnt); |
| 734 | PRINT_STATS_LE32("sent_cts_cnt", cck->sent_cts_cnt); | 733 | PRINT_STATS_LE32(cck, sent_ba_rsp_cnt); |
| 735 | PRINT_STATS_LE32("sent_ba_rsp_cnt", cck->sent_ba_rsp_cnt); | 734 | PRINT_STATS_LE32(cck, dsp_self_kill); |
| 736 | PRINT_STATS_LE32("dsp_self_kill", cck->dsp_self_kill); | 735 | PRINT_STATS_LE32(cck, mh_format_err); |
| 737 | PRINT_STATS_LE32("mh_format_err", cck->mh_format_err); | 736 | PRINT_STATS_LE32(cck, re_acq_main_rssi_sum); |
| 738 | PRINT_STATS_LE32("re_acq_main_rssi_sum", cck->re_acq_main_rssi_sum); | 737 | PRINT_STATS_LE32(cck, reserved); |
| 739 | PRINT_STATS_LE32("reserved", cck->reserved); | ||
| 740 | 738 | ||
| 741 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, | 739 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, |
| 742 | "Statistics_Rx - GENERAL"); | 740 | "Statistics_Rx - GENERAL"); |
| 743 | PRINT_STATS_LE32("bogus_cts", general->bogus_cts); | 741 | PRINT_STATS_LE32(general, bogus_cts); |
| 744 | PRINT_STATS_LE32("bogus_ack", general->bogus_ack); | 742 | PRINT_STATS_LE32(general, bogus_ack); |
| 745 | PRINT_STATS_LE32("non_bssid_frames", general->non_bssid_frames); | 743 | PRINT_STATS_LE32(general, non_bssid_frames); |
| 746 | PRINT_STATS_LE32("filtered_frames", general->filtered_frames); | 744 | PRINT_STATS_LE32(general, filtered_frames); |
| 747 | PRINT_STATS_LE32("non_channel_beacons", general->non_channel_beacons); | 745 | PRINT_STATS_LE32(general, non_channel_beacons); |
| 748 | PRINT_STATS_LE32("channel_beacons", general->channel_beacons); | 746 | PRINT_STATS_LE32(general, channel_beacons); |
| 749 | PRINT_STATS_LE32("num_missed_bcon", general->num_missed_bcon); | 747 | PRINT_STATS_LE32(general, num_missed_bcon); |
| 750 | PRINT_STATS_LE32("adc_rx_saturation_time", | 748 | PRINT_STATS_LE32(general, adc_rx_saturation_time); |
| 751 | general->adc_rx_saturation_time); | 749 | PRINT_STATS_LE32(general, ina_detection_search_time); |
| 752 | PRINT_STATS_LE32("ina_detection_search_time", | 750 | PRINT_STATS_LE32(general, beacon_silence_rssi_a); |
| 753 | general->ina_detection_search_time); | 751 | PRINT_STATS_LE32(general, beacon_silence_rssi_b); |
| 754 | PRINT_STATS_LE32("beacon_silence_rssi_a", | 752 | PRINT_STATS_LE32(general, beacon_silence_rssi_c); |
| 755 | general->beacon_silence_rssi_a); | 753 | PRINT_STATS_LE32(general, interference_data_flag); |
| 756 | PRINT_STATS_LE32("beacon_silence_rssi_b", | 754 | PRINT_STATS_LE32(general, channel_load); |
| 757 | general->beacon_silence_rssi_b); | 755 | PRINT_STATS_LE32(general, dsp_false_alarms); |
| 758 | PRINT_STATS_LE32("beacon_silence_rssi_c", | 756 | PRINT_STATS_LE32(general, beacon_rssi_a); |
| 759 | general->beacon_silence_rssi_c); | 757 | PRINT_STATS_LE32(general, beacon_rssi_b); |
| 760 | PRINT_STATS_LE32("interference_data_flag", | 758 | PRINT_STATS_LE32(general, beacon_rssi_c); |
| 761 | general->interference_data_flag); | 759 | PRINT_STATS_LE32(general, beacon_energy_a); |
| 762 | PRINT_STATS_LE32("channel_load", general->channel_load); | 760 | PRINT_STATS_LE32(general, beacon_energy_b); |
| 763 | PRINT_STATS_LE32("dsp_false_alarms", general->dsp_false_alarms); | 761 | PRINT_STATS_LE32(general, beacon_energy_c); |
| 764 | PRINT_STATS_LE32("beacon_rssi_a", general->beacon_rssi_a); | 762 | PRINT_STATS_LE32(general, num_bt_kills); |
| 765 | PRINT_STATS_LE32("beacon_rssi_b", general->beacon_rssi_b); | 763 | PRINT_STATS_LE32(general, mac_id); |
| 766 | PRINT_STATS_LE32("beacon_rssi_c", general->beacon_rssi_c); | 764 | PRINT_STATS_LE32(general, directed_data_mpdu); |
| 767 | PRINT_STATS_LE32("beacon_energy_a", general->beacon_energy_a); | ||
| 768 | PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b); | ||
| 769 | PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c); | ||
| 770 | PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills); | ||
| 771 | PRINT_STATS_LE32("mac_id", general->mac_id); | ||
| 772 | PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu); | ||
| 773 | 765 | ||
| 774 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, | 766 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, |
| 775 | "Statistics_Rx - HT"); | 767 | "Statistics_Rx - HT"); |
| 776 | PRINT_STATS_LE32("plcp_err", ht->plcp_err); | 768 | PRINT_STATS_LE32(ht, plcp_err); |
| 777 | PRINT_STATS_LE32("overrun_err", ht->overrun_err); | 769 | PRINT_STATS_LE32(ht, overrun_err); |
| 778 | PRINT_STATS_LE32("early_overrun_err", ht->early_overrun_err); | 770 | PRINT_STATS_LE32(ht, early_overrun_err); |
| 779 | PRINT_STATS_LE32("crc32_good", ht->crc32_good); | 771 | PRINT_STATS_LE32(ht, crc32_good); |
| 780 | PRINT_STATS_LE32("crc32_err", ht->crc32_err); | 772 | PRINT_STATS_LE32(ht, crc32_err); |
| 781 | PRINT_STATS_LE32("mh_format_err", ht->mh_format_err); | 773 | PRINT_STATS_LE32(ht, mh_format_err); |
| 782 | PRINT_STATS_LE32("agg_crc32_good", ht->agg_crc32_good); | 774 | PRINT_STATS_LE32(ht, agg_crc32_good); |
| 783 | PRINT_STATS_LE32("agg_mpdu_cnt", ht->agg_mpdu_cnt); | 775 | PRINT_STATS_LE32(ht, agg_mpdu_cnt); |
| 784 | PRINT_STATS_LE32("agg_cnt", ht->agg_cnt); | 776 | PRINT_STATS_LE32(ht, agg_cnt); |
| 785 | PRINT_STATS_LE32("unsupport_mcs", ht->unsupport_mcs); | 777 | PRINT_STATS_LE32(ht, unsupport_mcs); |
| 786 | 778 | ||
| 787 | mutex_unlock(&mvm->mutex); | 779 | mutex_unlock(&mvm->mutex); |
| 788 | 780 | ||
| @@ -988,9 +980,14 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, | |||
| 988 | char *buf, size_t count, | 980 | char *buf, size_t count, |
| 989 | loff_t *ppos) | 981 | loff_t *ppos) |
| 990 | { | 982 | { |
| 991 | mutex_lock(&mvm->mutex); | 983 | int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE); |
| 984 | |||
| 985 | if (ret) | ||
| 986 | return ret; | ||
| 987 | |||
| 992 | iwl_mvm_fw_dbg_collect(mvm); | 988 | iwl_mvm_fw_dbg_collect(mvm); |
| 993 | mutex_unlock(&mvm->mutex); | 989 | |
| 990 | iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE); | ||
| 994 | 991 | ||
| 995 | return count; | 992 | return count; |
| 996 | } | 993 | } |
| @@ -1390,6 +1387,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file, | |||
| 1390 | PRINT_MVM_REF(IWL_MVM_REF_TM_CMD); | 1387 | PRINT_MVM_REF(IWL_MVM_REF_TM_CMD); |
| 1391 | PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK); | 1388 | PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK); |
| 1392 | PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA); | 1389 | PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA); |
| 1390 | PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT); | ||
| 1393 | 1391 | ||
| 1394 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1392 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
| 1395 | } | 1393 | } |
| @@ -1489,6 +1487,26 @@ out: | |||
| 1489 | return count; | 1487 | return count; |
| 1490 | } | 1488 | } |
| 1491 | 1489 | ||
| 1490 | static ssize_t iwl_dbgfs_enable_scan_iteration_notif_write(struct iwl_mvm *mvm, | ||
| 1491 | char *buf, | ||
| 1492 | size_t count, | ||
| 1493 | loff_t *ppos) | ||
| 1494 | { | ||
| 1495 | int val; | ||
| 1496 | |||
| 1497 | mutex_lock(&mvm->mutex); | ||
| 1498 | |||
| 1499 | if (kstrtoint(buf, 10, &val)) { | ||
| 1500 | mutex_unlock(&mvm->mutex); | ||
| 1501 | return -EINVAL; | ||
| 1502 | } | ||
| 1503 | |||
| 1504 | mvm->scan_iter_notif_enabled = val; | ||
| 1505 | mutex_unlock(&mvm->mutex); | ||
| 1506 | |||
| 1507 | return count; | ||
| 1508 | } | ||
| 1509 | |||
| 1492 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); | 1510 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); |
| 1493 | 1511 | ||
| 1494 | /* Device wide debugfs entries */ | 1512 | /* Device wide debugfs entries */ |
| @@ -1511,6 +1529,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); | |||
| 1511 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); | 1529 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); |
| 1512 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); | 1530 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); |
| 1513 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8); | 1531 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8); |
| 1532 | MVM_DEBUGFS_WRITE_FILE_OPS(enable_scan_iteration_notif, 8); | ||
| 1514 | 1533 | ||
| 1515 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1534 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
| 1516 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); | 1535 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); |
| @@ -1554,6 +1573,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
| 1554 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1573 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
| 1555 | MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1574 | MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
| 1556 | MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); | 1575 | MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); |
| 1576 | MVM_DEBUGFS_ADD_FILE(enable_scan_iteration_notif, mvm->debugfs_dir, | ||
| 1577 | S_IWUSR); | ||
| 1557 | 1578 | ||
| 1558 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1579 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
| 1559 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { | 1580 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 430020047b77..4fc0938b3fb6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
| @@ -92,14 +92,32 @@ enum iwl_ltr_config_flags { | |||
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | /** | 94 | /** |
| 95 | * struct iwl_ltr_config_cmd_v1 - configures the LTR | ||
| 96 | * @flags: See %enum iwl_ltr_config_flags | ||
| 97 | */ | ||
| 98 | struct iwl_ltr_config_cmd_v1 { | ||
| 99 | __le32 flags; | ||
| 100 | __le32 static_long; | ||
| 101 | __le32 static_short; | ||
| 102 | } __packed; /* LTR_CAPABLE_API_S_VER_1 */ | ||
| 103 | |||
| 104 | #define LTR_VALID_STATES_NUM 4 | ||
| 105 | |||
| 106 | /** | ||
| 95 | * struct iwl_ltr_config_cmd - configures the LTR | 107 | * struct iwl_ltr_config_cmd - configures the LTR |
| 96 | * @flags: See %enum iwl_ltr_config_flags | 108 | * @flags: See %enum iwl_ltr_config_flags |
| 109 | * @static_long: | ||
| 110 | * @static_short: | ||
| 111 | * @ltr_cfg_values: | ||
| 112 | * @ltr_short_idle_timeout: | ||
| 97 | */ | 113 | */ |
| 98 | struct iwl_ltr_config_cmd { | 114 | struct iwl_ltr_config_cmd { |
| 99 | __le32 flags; | 115 | __le32 flags; |
| 100 | __le32 static_long; | 116 | __le32 static_long; |
| 101 | __le32 static_short; | 117 | __le32 static_short; |
| 102 | } __packed; | 118 | __le32 ltr_cfg_values[LTR_VALID_STATES_NUM]; |
| 119 | __le32 ltr_short_idle_timeout; | ||
| 120 | } __packed; /* LTR_CAPABLE_API_S_VER_2 */ | ||
| 103 | 121 | ||
| 104 | /* Radio LP RX Energy Threshold measured in dBm */ | 122 | /* Radio LP RX Energy Threshold measured in dBm */ |
| 105 | #define POWER_LPRX_RSSI_THRESHOLD 75 | 123 | #define POWER_LPRX_RSSI_THRESHOLD 75 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index 8bb5b94bf963..0f1ea80a55ef 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
| @@ -308,6 +308,42 @@ enum { | |||
| 308 | #define LQ_FLAG_DYNAMIC_BW_POS 6 | 308 | #define LQ_FLAG_DYNAMIC_BW_POS 6 |
| 309 | #define LQ_FLAG_DYNAMIC_BW_MSK (1 << LQ_FLAG_DYNAMIC_BW_POS) | 309 | #define LQ_FLAG_DYNAMIC_BW_MSK (1 << LQ_FLAG_DYNAMIC_BW_POS) |
| 310 | 310 | ||
| 311 | /* Single Stream Tx Parameters (lq_cmd->ss_params) | ||
| 312 | * Flags to control a smart FW decision about whether BFER/STBC/SISO will be | ||
| 313 | * used for single stream Tx. | ||
| 314 | */ | ||
| 315 | |||
| 316 | /* Bit 0-1: Max STBC streams allowed. Can be 0-3. | ||
| 317 | * (0) - No STBC allowed | ||
| 318 | * (1) - 2x1 STBC allowed (HT/VHT) | ||
| 319 | * (2) - 4x2 STBC allowed (HT/VHT) | ||
| 320 | * (3) - 3x2 STBC allowed (HT only) | ||
| 321 | * All our chips are at most 2 antennas so only (1) is valid for now. | ||
| 322 | */ | ||
| 323 | #define LQ_SS_STBC_ALLOWED_POS 0 | ||
| 324 | #define LQ_SS_STBC_ALLOWED_MSK (3 << LQ_SS_STBC_ALLOWED_MSK) | ||
| 325 | |||
| 326 | /* 2x1 STBC is allowed */ | ||
| 327 | #define LQ_SS_STBC_1SS_ALLOWED (1 << LQ_SS_STBC_ALLOWED_POS) | ||
| 328 | |||
| 329 | /* Bit 2: Beamformer (VHT only) is allowed */ | ||
| 330 | #define LQ_SS_BFER_ALLOWED_POS 2 | ||
| 331 | #define LQ_SS_BFER_ALLOWED (1 << LQ_SS_BFER_ALLOWED_POS) | ||
| 332 | |||
| 333 | /* Bit 3: Force BFER or STBC for testing | ||
| 334 | * If this is set: | ||
| 335 | * If BFER is allowed then force the ucode to choose BFER else | ||
| 336 | * If STBC is allowed then force the ucode to choose STBC over SISO | ||
| 337 | */ | ||
| 338 | #define LQ_SS_FORCE_POS 3 | ||
| 339 | #define LQ_SS_FORCE (1 << LQ_SS_FORCE_POS) | ||
| 340 | |||
| 341 | /* Bit 31: ss_params field is valid. Used for FW backward compatibility | ||
| 342 | * with other drivers which don't support the ss_params API yet | ||
| 343 | */ | ||
| 344 | #define LQ_SS_PARAMS_VALID_POS 31 | ||
| 345 | #define LQ_SS_PARAMS_VALID (1 << LQ_SS_PARAMS_VALID_POS) | ||
| 346 | |||
| 311 | /** | 347 | /** |
| 312 | * struct iwl_lq_cmd - link quality command | 348 | * struct iwl_lq_cmd - link quality command |
| 313 | * @sta_id: station to update | 349 | * @sta_id: station to update |
| @@ -330,7 +366,7 @@ enum { | |||
| 330 | * 2 - 0x3f: maximal number of frames (up to 3f == 63) | 366 | * 2 - 0x3f: maximal number of frames (up to 3f == 63) |
| 331 | * @rs_table: array of rates for each TX try, each is rate_n_flags, | 367 | * @rs_table: array of rates for each TX try, each is rate_n_flags, |
| 332 | * meaning it is a combination of RATE_MCS_* and IWL_RATE_*_PLCP | 368 | * meaning it is a combination of RATE_MCS_* and IWL_RATE_*_PLCP |
| 333 | * @bf_params: beam forming params, currently not used | 369 | * @ss_params: single stream features. declare whether STBC or BFER are allowed. |
| 334 | */ | 370 | */ |
| 335 | struct iwl_lq_cmd { | 371 | struct iwl_lq_cmd { |
| 336 | u8 sta_id; | 372 | u8 sta_id; |
| @@ -348,6 +384,6 @@ struct iwl_lq_cmd { | |||
| 348 | u8 agg_frame_cnt_limit; | 384 | u8 agg_frame_cnt_limit; |
| 349 | __le32 reserved2; | 385 | __le32 reserved2; |
| 350 | __le32 rs_table[LQ_MAX_RETRY_NUM]; | 386 | __le32 rs_table[LQ_MAX_RETRY_NUM]; |
| 351 | __le32 bf_params; | 387 | __le32 ss_params; |
| 352 | }; /* LINK_QUALITY_CMD_API_S_VER_1 */ | 388 | }; /* LINK_QUALITY_CMD_API_S_VER_1 */ |
| 353 | #endif /* __fw_api_rs_h__ */ | 389 | #endif /* __fw_api_rs_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 2d1a81c493f1..cfc0e65b34a5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
| @@ -675,6 +675,7 @@ struct iwl_scan_channel_opt { | |||
| 675 | * @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented | 675 | * @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented |
| 676 | * @IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED: insert WFA vendor-specific TPC report | 676 | * @IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED: insert WFA vendor-specific TPC report |
| 677 | * and DS parameter set IEs into probe requests. | 677 | * and DS parameter set IEs into probe requests. |
| 678 | * @IWL_MVM_LMAC_SCAN_FLAG_MATCH: Send match found notification on matches | ||
| 678 | */ | 679 | */ |
| 679 | enum iwl_mvm_lmac_scan_flags { | 680 | enum iwl_mvm_lmac_scan_flags { |
| 680 | IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL = BIT(0), | 681 | IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL = BIT(0), |
| @@ -684,6 +685,7 @@ enum iwl_mvm_lmac_scan_flags { | |||
| 684 | IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS = BIT(4), | 685 | IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS = BIT(4), |
| 685 | IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED = BIT(5), | 686 | IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED = BIT(5), |
| 686 | IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED = BIT(6), | 687 | IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED = BIT(6), |
| 688 | IWL_MVM_LMAC_SCAN_FLAG_MATCH = BIT(9), | ||
| 687 | }; | 689 | }; |
| 688 | 690 | ||
| 689 | enum iwl_scan_priority { | 691 | enum iwl_scan_priority { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h new file mode 100644 index 000000000000..928168b18346 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h | |||
| @@ -0,0 +1,277 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
| 4 | * redistributing this file, you may do so under either license. | ||
| 5 | * | ||
| 6 | * GPL LICENSE SUMMARY | ||
| 7 | * | ||
| 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | ||
| 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | ||
| 10 | * | ||
| 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 | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, but | ||
| 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 18 | * General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
| 23 | * USA | ||
| 24 | * | ||
| 25 | * The full GNU General Public License is included in this distribution | ||
| 26 | * in the file called COPYING. | ||
| 27 | * | ||
| 28 | * Contact Information: | ||
| 29 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
| 30 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
| 31 | * | ||
| 32 | * BSD LICENSE | ||
| 33 | * | ||
| 34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | ||
| 35 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | ||
| 36 | * All rights reserved. | ||
| 37 | * | ||
| 38 | * Redistribution and use in source and binary forms, with or without | ||
| 39 | * modification, are permitted provided that the following conditions | ||
| 40 | * are met: | ||
| 41 | * | ||
| 42 | * * Redistributions of source code must retain the above copyright | ||
| 43 | * notice, this list of conditions and the following disclaimer. | ||
| 44 | * * Redistributions in binary form must reproduce the above copyright | ||
| 45 | * notice, this list of conditions and the following disclaimer in | ||
| 46 | * the documentation and/or other materials provided with the | ||
| 47 | * distribution. | ||
| 48 | * * Neither the name Intel Corporation nor the names of its | ||
| 49 | * contributors may be used to endorse or promote products derived | ||
| 50 | * from this software without specific prior written permission. | ||
| 51 | * | ||
| 52 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 53 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 54 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 55 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 56 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 57 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 58 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 59 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 60 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 61 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 62 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 63 | * | ||
| 64 | *****************************************************************************/ | ||
| 65 | |||
| 66 | #ifndef __fw_api_stats_h__ | ||
| 67 | #define __fw_api_stats_h__ | ||
| 68 | |||
| 69 | struct mvm_statistics_dbg { | ||
| 70 | __le32 burst_check; | ||
| 71 | __le32 burst_count; | ||
| 72 | __le32 wait_for_silence_timeout_cnt; | ||
| 73 | __le32 reserved[3]; | ||
| 74 | } __packed; /* STATISTICS_DEBUG_API_S_VER_2 */ | ||
| 75 | |||
| 76 | struct mvm_statistics_div { | ||
| 77 | __le32 tx_on_a; | ||
| 78 | __le32 tx_on_b; | ||
| 79 | __le32 exec_time; | ||
| 80 | __le32 probe_time; | ||
| 81 | __le32 rssi_ant; | ||
| 82 | __le32 reserved2; | ||
| 83 | } __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */ | ||
| 84 | |||
| 85 | struct mvm_statistics_rx_non_phy { | ||
| 86 | __le32 bogus_cts; /* CTS received when not expecting CTS */ | ||
| 87 | __le32 bogus_ack; /* ACK received when not expecting ACK */ | ||
| 88 | __le32 non_bssid_frames; /* number of frames with BSSID that | ||
| 89 | * doesn't belong to the STA BSSID */ | ||
| 90 | __le32 filtered_frames; /* count frames that were dumped in the | ||
| 91 | * filtering process */ | ||
| 92 | __le32 non_channel_beacons; /* beacons with our bss id but not on | ||
| 93 | * our serving channel */ | ||
| 94 | __le32 channel_beacons; /* beacons with our bss id and in our | ||
| 95 | * serving channel */ | ||
| 96 | __le32 num_missed_bcon; /* number of missed beacons */ | ||
| 97 | __le32 adc_rx_saturation_time; /* count in 0.8us units the time the | ||
| 98 | * ADC was in saturation */ | ||
| 99 | __le32 ina_detection_search_time;/* total time (in 0.8us) searched | ||
| 100 | * for INA */ | ||
| 101 | __le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */ | ||
| 102 | __le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */ | ||
| 103 | __le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */ | ||
| 104 | __le32 interference_data_flag; /* flag for interference data | ||
| 105 | * availability. 1 when data is | ||
| 106 | * available. */ | ||
| 107 | __le32 channel_load; /* counts RX Enable time in uSec */ | ||
| 108 | __le32 dsp_false_alarms; /* DSP false alarm (both OFDM | ||
| 109 | * and CCK) counter */ | ||
| 110 | __le32 beacon_rssi_a; | ||
| 111 | __le32 beacon_rssi_b; | ||
| 112 | __le32 beacon_rssi_c; | ||
| 113 | __le32 beacon_energy_a; | ||
| 114 | __le32 beacon_energy_b; | ||
| 115 | __le32 beacon_energy_c; | ||
| 116 | __le32 num_bt_kills; | ||
| 117 | __le32 mac_id; | ||
| 118 | __le32 directed_data_mpdu; | ||
| 119 | } __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */ | ||
| 120 | |||
| 121 | struct mvm_statistics_rx_phy { | ||
| 122 | __le32 ina_cnt; | ||
| 123 | __le32 fina_cnt; | ||
| 124 | __le32 plcp_err; | ||
| 125 | __le32 crc32_err; | ||
| 126 | __le32 overrun_err; | ||
| 127 | __le32 early_overrun_err; | ||
| 128 | __le32 crc32_good; | ||
| 129 | __le32 false_alarm_cnt; | ||
| 130 | __le32 fina_sync_err_cnt; | ||
| 131 | __le32 sfd_timeout; | ||
| 132 | __le32 fina_timeout; | ||
| 133 | __le32 unresponded_rts; | ||
| 134 | __le32 rxe_frame_lmt_overrun; | ||
| 135 | __le32 sent_ack_cnt; | ||
| 136 | __le32 sent_cts_cnt; | ||
| 137 | __le32 sent_ba_rsp_cnt; | ||
| 138 | __le32 dsp_self_kill; | ||
| 139 | __le32 mh_format_err; | ||
| 140 | __le32 re_acq_main_rssi_sum; | ||
| 141 | __le32 reserved; | ||
| 142 | } __packed; /* STATISTICS_RX_PHY_API_S_VER_2 */ | ||
| 143 | |||
| 144 | struct mvm_statistics_rx_ht_phy { | ||
| 145 | __le32 plcp_err; | ||
| 146 | __le32 overrun_err; | ||
| 147 | __le32 early_overrun_err; | ||
| 148 | __le32 crc32_good; | ||
| 149 | __le32 crc32_err; | ||
| 150 | __le32 mh_format_err; | ||
| 151 | __le32 agg_crc32_good; | ||
| 152 | __le32 agg_mpdu_cnt; | ||
| 153 | __le32 agg_cnt; | ||
| 154 | __le32 unsupport_mcs; | ||
| 155 | } __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_1 */ | ||
| 156 | |||
| 157 | struct mvm_statistics_tx_non_phy { | ||
| 158 | __le32 preamble_cnt; | ||
| 159 | __le32 rx_detected_cnt; | ||
| 160 | __le32 bt_prio_defer_cnt; | ||
| 161 | __le32 bt_prio_kill_cnt; | ||
| 162 | __le32 few_bytes_cnt; | ||
| 163 | __le32 cts_timeout; | ||
| 164 | __le32 ack_timeout; | ||
| 165 | __le32 expected_ack_cnt; | ||
| 166 | __le32 actual_ack_cnt; | ||
| 167 | __le32 dump_msdu_cnt; | ||
| 168 | __le32 burst_abort_next_frame_mismatch_cnt; | ||
| 169 | __le32 burst_abort_missing_next_frame_cnt; | ||
| 170 | __le32 cts_timeout_collision; | ||
| 171 | __le32 ack_or_ba_timeout_collision; | ||
| 172 | } __packed; /* STATISTICS_TX_NON_PHY_API_S_VER_3 */ | ||
| 173 | |||
| 174 | #define MAX_CHAINS 3 | ||
| 175 | |||
| 176 | struct mvm_statistics_tx_non_phy_agg { | ||
| 177 | __le32 ba_timeout; | ||
| 178 | __le32 ba_reschedule_frames; | ||
| 179 | __le32 scd_query_agg_frame_cnt; | ||
| 180 | __le32 scd_query_no_agg; | ||
| 181 | __le32 scd_query_agg; | ||
| 182 | __le32 scd_query_mismatch; | ||
| 183 | __le32 frame_not_ready; | ||
| 184 | __le32 underrun; | ||
| 185 | __le32 bt_prio_kill; | ||
| 186 | __le32 rx_ba_rsp_cnt; | ||
| 187 | __s8 txpower[MAX_CHAINS]; | ||
| 188 | __s8 reserved; | ||
| 189 | __le32 reserved2; | ||
| 190 | } __packed; /* STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */ | ||
| 191 | |||
| 192 | struct mvm_statistics_tx_channel_width { | ||
| 193 | __le32 ext_cca_narrow_ch20[1]; | ||
| 194 | __le32 ext_cca_narrow_ch40[2]; | ||
| 195 | __le32 ext_cca_narrow_ch80[3]; | ||
| 196 | __le32 ext_cca_narrow_ch160[4]; | ||
| 197 | __le32 last_tx_ch_width_indx; | ||
| 198 | __le32 rx_detected_per_ch_width[4]; | ||
| 199 | __le32 success_per_ch_width[4]; | ||
| 200 | __le32 fail_per_ch_width[4]; | ||
| 201 | }; /* STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */ | ||
| 202 | |||
| 203 | struct mvm_statistics_tx { | ||
| 204 | struct mvm_statistics_tx_non_phy general; | ||
| 205 | struct mvm_statistics_tx_non_phy_agg agg; | ||
| 206 | struct mvm_statistics_tx_channel_width channel_width; | ||
| 207 | } __packed; /* STATISTICS_TX_API_S_VER_4 */ | ||
| 208 | |||
| 209 | |||
| 210 | struct mvm_statistics_bt_activity { | ||
| 211 | __le32 hi_priority_tx_req_cnt; | ||
| 212 | __le32 hi_priority_tx_denied_cnt; | ||
| 213 | __le32 lo_priority_tx_req_cnt; | ||
| 214 | __le32 lo_priority_tx_denied_cnt; | ||
| 215 | __le32 hi_priority_rx_req_cnt; | ||
| 216 | __le32 hi_priority_rx_denied_cnt; | ||
| 217 | __le32 lo_priority_rx_req_cnt; | ||
| 218 | __le32 lo_priority_rx_denied_cnt; | ||
| 219 | } __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ | ||
| 220 | |||
| 221 | struct mvm_statistics_general { | ||
| 222 | __le32 radio_temperature; | ||
| 223 | __le32 radio_voltage; | ||
| 224 | struct mvm_statistics_dbg dbg; | ||
| 225 | __le32 sleep_time; | ||
| 226 | __le32 slots_out; | ||
| 227 | __le32 slots_idle; | ||
| 228 | __le32 ttl_timestamp; | ||
| 229 | struct mvm_statistics_div slow_div; | ||
| 230 | __le32 rx_enable_counter; | ||
| 231 | /* | ||
| 232 | * num_of_sos_states: | ||
| 233 | * count the number of times we have to re-tune | ||
| 234 | * in order to get out of bad PHY status | ||
| 235 | */ | ||
| 236 | __le32 num_of_sos_states; | ||
| 237 | __le32 beacon_filtered; | ||
| 238 | __le32 missed_beacons; | ||
| 239 | __s8 beacon_filter_average_energy; | ||
| 240 | __s8 beacon_filter_reason; | ||
| 241 | __s8 beacon_filter_current_energy; | ||
| 242 | __s8 beacon_filter_reserved; | ||
| 243 | __le32 beacon_filter_delta_time; | ||
| 244 | struct mvm_statistics_bt_activity bt_activity; | ||
| 245 | } __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ | ||
| 246 | |||
| 247 | struct mvm_statistics_rx { | ||
| 248 | struct mvm_statistics_rx_phy ofdm; | ||
| 249 | struct mvm_statistics_rx_phy cck; | ||
| 250 | struct mvm_statistics_rx_non_phy general; | ||
| 251 | struct mvm_statistics_rx_ht_phy ofdm_ht; | ||
| 252 | } __packed; /* STATISTICS_RX_API_S_VER_3 */ | ||
| 253 | |||
| 254 | /* | ||
| 255 | * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) | ||
| 256 | * | ||
| 257 | * By default, uCode issues this notification after receiving a beacon | ||
| 258 | * while associated. To disable this behavior, set DISABLE_NOTIF flag in the | ||
| 259 | * REPLY_STATISTICS_CMD 0x9c, above. | ||
| 260 | * | ||
| 261 | * Statistics counters continue to increment beacon after beacon, but are | ||
| 262 | * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD | ||
| 263 | * 0x9c with CLEAR_STATS bit set (see above). | ||
| 264 | * | ||
| 265 | * uCode also issues this notification during scans. uCode clears statistics | ||
| 266 | * appropriately so that each notification contains statistics for only the | ||
| 267 | * one channel that has just been scanned. | ||
| 268 | */ | ||
| 269 | |||
| 270 | struct iwl_notif_statistics { | ||
| 271 | __le32 flag; | ||
| 272 | struct mvm_statistics_rx rx; | ||
| 273 | struct mvm_statistics_tx tx; | ||
| 274 | struct mvm_statistics_general general; | ||
| 275 | } __packed; /* STATISTICS_NTFY_API_S_VER_8 */ | ||
| 276 | |||
| 277 | #endif /* __fw_api_stats_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 5bca1f8bfebf..81c4ea3c6958 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
| @@ -592,4 +592,43 @@ static inline u32 iwl_mvm_get_scd_ssn(struct iwl_mvm_tx_resp *tx_resp) | |||
| 592 | tx_resp->frame_count) & 0xfff; | 592 | tx_resp->frame_count) & 0xfff; |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | /** | ||
| 596 | * struct iwl_scd_txq_cfg_cmd - New txq hw scheduler config command | ||
| 597 | * @token: | ||
| 598 | * @sta_id: station id | ||
| 599 | * @tid: | ||
| 600 | * @scd_queue: scheduler queue to confiug | ||
| 601 | * @enable: 1 queue enable, 0 queue disable | ||
| 602 | * @aggregate: 1 aggregated queue, 0 otherwise | ||
| 603 | * @tx_fifo: %enum iwl_mvm_tx_fifo | ||
| 604 | * @window: BA window size | ||
| 605 | * @ssn: SSN for the BA agreement | ||
| 606 | */ | ||
| 607 | struct iwl_scd_txq_cfg_cmd { | ||
| 608 | u8 token; | ||
| 609 | u8 sta_id; | ||
| 610 | u8 tid; | ||
| 611 | u8 scd_queue; | ||
| 612 | u8 enable; | ||
| 613 | u8 aggregate; | ||
| 614 | u8 tx_fifo; | ||
| 615 | u8 window; | ||
| 616 | __le16 ssn; | ||
| 617 | __le16 reserved; | ||
| 618 | } __packed; /* SCD_QUEUE_CFG_CMD_API_S_VER_1 */ | ||
| 619 | |||
| 620 | /** | ||
| 621 | * struct iwl_scd_txq_cfg_rsp | ||
| 622 | * @token: taken from the command | ||
| 623 | * @sta_id: station id from the command | ||
| 624 | * @tid: tid from the command | ||
| 625 | * @scd_queue: scd_queue from the command | ||
| 626 | */ | ||
| 627 | struct iwl_scd_txq_cfg_rsp { | ||
| 628 | u8 token; | ||
| 629 | u8 sta_id; | ||
| 630 | u8 tid; | ||
| 631 | u8 scd_queue; | ||
| 632 | } __packed; /* SCD_QUEUE_CFG_RSP_API_S_VER_1 */ | ||
| 633 | |||
| 595 | #endif /* __fw_api_tx_h__ */ | 634 | #endif /* __fw_api_tx_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 88af6dd2ceaa..b56154fe8ec5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
| @@ -74,6 +74,7 @@ | |||
| 74 | #include "fw-api-d3.h" | 74 | #include "fw-api-d3.h" |
| 75 | #include "fw-api-coex.h" | 75 | #include "fw-api-coex.h" |
| 76 | #include "fw-api-scan.h" | 76 | #include "fw-api-scan.h" |
| 77 | #include "fw-api-stats.h" | ||
| 77 | 78 | ||
| 78 | /* Tx queue numbers */ | 79 | /* Tx queue numbers */ |
| 79 | enum { | 80 | enum { |
| @@ -128,6 +129,9 @@ enum { | |||
| 128 | /* global key */ | 129 | /* global key */ |
| 129 | WEP_KEY = 0x20, | 130 | WEP_KEY = 0x20, |
| 130 | 131 | ||
| 132 | /* Memory */ | ||
| 133 | SHARED_MEM_CFG = 0x25, | ||
| 134 | |||
| 131 | /* TDLS */ | 135 | /* TDLS */ |
| 132 | TDLS_CHANNEL_SWITCH_CMD = 0x27, | 136 | TDLS_CHANNEL_SWITCH_CMD = 0x27, |
| 133 | TDLS_CHANNEL_SWITCH_NOTIFICATION = 0xaa, | 137 | TDLS_CHANNEL_SWITCH_NOTIFICATION = 0xaa, |
| @@ -1381,214 +1385,6 @@ struct iwl_mvm_marker { | |||
| 1381 | __le32 metadata[0]; | 1385 | __le32 metadata[0]; |
| 1382 | } __packed; /* MARKER_API_S_VER_1 */ | 1386 | } __packed; /* MARKER_API_S_VER_1 */ |
| 1383 | 1387 | ||
| 1384 | struct mvm_statistics_dbg { | ||
| 1385 | __le32 burst_check; | ||
| 1386 | __le32 burst_count; | ||
| 1387 | __le32 wait_for_silence_timeout_cnt; | ||
| 1388 | __le32 reserved[3]; | ||
| 1389 | } __packed; /* STATISTICS_DEBUG_API_S_VER_2 */ | ||
| 1390 | |||
| 1391 | struct mvm_statistics_div { | ||
| 1392 | __le32 tx_on_a; | ||
| 1393 | __le32 tx_on_b; | ||
| 1394 | __le32 exec_time; | ||
| 1395 | __le32 probe_time; | ||
| 1396 | __le32 rssi_ant; | ||
| 1397 | __le32 reserved2; | ||
| 1398 | } __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */ | ||
| 1399 | |||
| 1400 | struct mvm_statistics_general_common { | ||
| 1401 | __le32 temperature; /* radio temperature */ | ||
| 1402 | __le32 temperature_m; /* radio voltage */ | ||
| 1403 | struct mvm_statistics_dbg dbg; | ||
| 1404 | __le32 sleep_time; | ||
| 1405 | __le32 slots_out; | ||
| 1406 | __le32 slots_idle; | ||
| 1407 | __le32 ttl_timestamp; | ||
| 1408 | struct mvm_statistics_div div; | ||
| 1409 | __le32 rx_enable_counter; | ||
| 1410 | /* | ||
| 1411 | * num_of_sos_states: | ||
| 1412 | * count the number of times we have to re-tune | ||
| 1413 | * in order to get out of bad PHY status | ||
| 1414 | */ | ||
| 1415 | __le32 num_of_sos_states; | ||
| 1416 | } __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ | ||
| 1417 | |||
| 1418 | struct mvm_statistics_rx_non_phy { | ||
| 1419 | __le32 bogus_cts; /* CTS received when not expecting CTS */ | ||
| 1420 | __le32 bogus_ack; /* ACK received when not expecting ACK */ | ||
| 1421 | __le32 non_bssid_frames; /* number of frames with BSSID that | ||
| 1422 | * doesn't belong to the STA BSSID */ | ||
| 1423 | __le32 filtered_frames; /* count frames that were dumped in the | ||
| 1424 | * filtering process */ | ||
| 1425 | __le32 non_channel_beacons; /* beacons with our bss id but not on | ||
| 1426 | * our serving channel */ | ||
| 1427 | __le32 channel_beacons; /* beacons with our bss id and in our | ||
| 1428 | * serving channel */ | ||
| 1429 | __le32 num_missed_bcon; /* number of missed beacons */ | ||
| 1430 | __le32 adc_rx_saturation_time; /* count in 0.8us units the time the | ||
| 1431 | * ADC was in saturation */ | ||
| 1432 | __le32 ina_detection_search_time;/* total time (in 0.8us) searched | ||
| 1433 | * for INA */ | ||
| 1434 | __le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */ | ||
| 1435 | __le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */ | ||
| 1436 | __le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */ | ||
| 1437 | __le32 interference_data_flag; /* flag for interference data | ||
| 1438 | * availability. 1 when data is | ||
| 1439 | * available. */ | ||
| 1440 | __le32 channel_load; /* counts RX Enable time in uSec */ | ||
| 1441 | __le32 dsp_false_alarms; /* DSP false alarm (both OFDM | ||
| 1442 | * and CCK) counter */ | ||
| 1443 | __le32 beacon_rssi_a; | ||
| 1444 | __le32 beacon_rssi_b; | ||
| 1445 | __le32 beacon_rssi_c; | ||
| 1446 | __le32 beacon_energy_a; | ||
| 1447 | __le32 beacon_energy_b; | ||
| 1448 | __le32 beacon_energy_c; | ||
| 1449 | __le32 num_bt_kills; | ||
| 1450 | __le32 mac_id; | ||
| 1451 | __le32 directed_data_mpdu; | ||
| 1452 | } __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */ | ||
| 1453 | |||
| 1454 | struct mvm_statistics_rx_phy { | ||
| 1455 | __le32 ina_cnt; | ||
| 1456 | __le32 fina_cnt; | ||
| 1457 | __le32 plcp_err; | ||
| 1458 | __le32 crc32_err; | ||
| 1459 | __le32 overrun_err; | ||
| 1460 | __le32 early_overrun_err; | ||
| 1461 | __le32 crc32_good; | ||
| 1462 | __le32 false_alarm_cnt; | ||
| 1463 | __le32 fina_sync_err_cnt; | ||
| 1464 | __le32 sfd_timeout; | ||
| 1465 | __le32 fina_timeout; | ||
| 1466 | __le32 unresponded_rts; | ||
| 1467 | __le32 rxe_frame_limit_overrun; | ||
| 1468 | __le32 sent_ack_cnt; | ||
| 1469 | __le32 sent_cts_cnt; | ||
| 1470 | __le32 sent_ba_rsp_cnt; | ||
| 1471 | __le32 dsp_self_kill; | ||
| 1472 | __le32 mh_format_err; | ||
| 1473 | __le32 re_acq_main_rssi_sum; | ||
| 1474 | __le32 reserved; | ||
| 1475 | } __packed; /* STATISTICS_RX_PHY_API_S_VER_2 */ | ||
| 1476 | |||
| 1477 | struct mvm_statistics_rx_ht_phy { | ||
| 1478 | __le32 plcp_err; | ||
| 1479 | __le32 overrun_err; | ||
| 1480 | __le32 early_overrun_err; | ||
| 1481 | __le32 crc32_good; | ||
| 1482 | __le32 crc32_err; | ||
| 1483 | __le32 mh_format_err; | ||
| 1484 | __le32 agg_crc32_good; | ||
| 1485 | __le32 agg_mpdu_cnt; | ||
| 1486 | __le32 agg_cnt; | ||
| 1487 | __le32 unsupport_mcs; | ||
| 1488 | } __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_1 */ | ||
| 1489 | |||
| 1490 | #define MAX_CHAINS 3 | ||
| 1491 | |||
| 1492 | struct mvm_statistics_tx_non_phy_agg { | ||
| 1493 | __le32 ba_timeout; | ||
| 1494 | __le32 ba_reschedule_frames; | ||
| 1495 | __le32 scd_query_agg_frame_cnt; | ||
| 1496 | __le32 scd_query_no_agg; | ||
| 1497 | __le32 scd_query_agg; | ||
| 1498 | __le32 scd_query_mismatch; | ||
| 1499 | __le32 frame_not_ready; | ||
| 1500 | __le32 underrun; | ||
| 1501 | __le32 bt_prio_kill; | ||
| 1502 | __le32 rx_ba_rsp_cnt; | ||
| 1503 | __s8 txpower[MAX_CHAINS]; | ||
| 1504 | __s8 reserved; | ||
| 1505 | __le32 reserved2; | ||
| 1506 | } __packed; /* STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */ | ||
| 1507 | |||
| 1508 | struct mvm_statistics_tx_channel_width { | ||
| 1509 | __le32 ext_cca_narrow_ch20[1]; | ||
| 1510 | __le32 ext_cca_narrow_ch40[2]; | ||
| 1511 | __le32 ext_cca_narrow_ch80[3]; | ||
| 1512 | __le32 ext_cca_narrow_ch160[4]; | ||
| 1513 | __le32 last_tx_ch_width_indx; | ||
| 1514 | __le32 rx_detected_per_ch_width[4]; | ||
| 1515 | __le32 success_per_ch_width[4]; | ||
| 1516 | __le32 fail_per_ch_width[4]; | ||
| 1517 | }; /* STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */ | ||
| 1518 | |||
| 1519 | struct mvm_statistics_tx { | ||
| 1520 | __le32 preamble_cnt; | ||
| 1521 | __le32 rx_detected_cnt; | ||
| 1522 | __le32 bt_prio_defer_cnt; | ||
| 1523 | __le32 bt_prio_kill_cnt; | ||
| 1524 | __le32 few_bytes_cnt; | ||
| 1525 | __le32 cts_timeout; | ||
| 1526 | __le32 ack_timeout; | ||
| 1527 | __le32 expected_ack_cnt; | ||
| 1528 | __le32 actual_ack_cnt; | ||
| 1529 | __le32 dump_msdu_cnt; | ||
| 1530 | __le32 burst_abort_next_frame_mismatch_cnt; | ||
| 1531 | __le32 burst_abort_missing_next_frame_cnt; | ||
| 1532 | __le32 cts_timeout_collision; | ||
| 1533 | __le32 ack_or_ba_timeout_collision; | ||
| 1534 | struct mvm_statistics_tx_non_phy_agg agg; | ||
| 1535 | struct mvm_statistics_tx_channel_width channel_width; | ||
| 1536 | } __packed; /* STATISTICS_TX_API_S_VER_4 */ | ||
| 1537 | |||
| 1538 | |||
| 1539 | struct mvm_statistics_bt_activity { | ||
| 1540 | __le32 hi_priority_tx_req_cnt; | ||
| 1541 | __le32 hi_priority_tx_denied_cnt; | ||
| 1542 | __le32 lo_priority_tx_req_cnt; | ||
| 1543 | __le32 lo_priority_tx_denied_cnt; | ||
| 1544 | __le32 hi_priority_rx_req_cnt; | ||
| 1545 | __le32 hi_priority_rx_denied_cnt; | ||
| 1546 | __le32 lo_priority_rx_req_cnt; | ||
| 1547 | __le32 lo_priority_rx_denied_cnt; | ||
| 1548 | } __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ | ||
| 1549 | |||
| 1550 | struct mvm_statistics_general { | ||
| 1551 | struct mvm_statistics_general_common common; | ||
| 1552 | __le32 beacon_filtered; | ||
| 1553 | __le32 missed_beacons; | ||
| 1554 | __s8 beacon_filter_average_energy; | ||
| 1555 | __s8 beacon_filter_reason; | ||
| 1556 | __s8 beacon_filter_current_energy; | ||
| 1557 | __s8 beacon_filter_reserved; | ||
| 1558 | __le32 beacon_filter_delta_time; | ||
| 1559 | struct mvm_statistics_bt_activity bt_activity; | ||
| 1560 | } __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ | ||
| 1561 | |||
| 1562 | struct mvm_statistics_rx { | ||
| 1563 | struct mvm_statistics_rx_phy ofdm; | ||
| 1564 | struct mvm_statistics_rx_phy cck; | ||
| 1565 | struct mvm_statistics_rx_non_phy general; | ||
| 1566 | struct mvm_statistics_rx_ht_phy ofdm_ht; | ||
| 1567 | } __packed; /* STATISTICS_RX_API_S_VER_3 */ | ||
| 1568 | |||
| 1569 | /* | ||
| 1570 | * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) | ||
| 1571 | * | ||
| 1572 | * By default, uCode issues this notification after receiving a beacon | ||
| 1573 | * while associated. To disable this behavior, set DISABLE_NOTIF flag in the | ||
| 1574 | * REPLY_STATISTICS_CMD 0x9c, above. | ||
| 1575 | * | ||
| 1576 | * Statistics counters continue to increment beacon after beacon, but are | ||
| 1577 | * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD | ||
| 1578 | * 0x9c with CLEAR_STATS bit set (see above). | ||
| 1579 | * | ||
| 1580 | * uCode also issues this notification during scans. uCode clears statistics | ||
| 1581 | * appropriately so that each notification contains statistics for only the | ||
| 1582 | * one channel that has just been scanned. | ||
| 1583 | */ | ||
| 1584 | |||
| 1585 | struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */ | ||
| 1586 | __le32 flag; | ||
| 1587 | struct mvm_statistics_rx rx; | ||
| 1588 | struct mvm_statistics_tx tx; | ||
| 1589 | struct mvm_statistics_general general; | ||
| 1590 | } __packed; | ||
| 1591 | |||
| 1592 | /*********************************** | 1388 | /*********************************** |
| 1593 | * Smart Fifo API | 1389 | * Smart Fifo API |
| 1594 | ***********************************/ | 1390 | ***********************************/ |
| @@ -1680,63 +1476,6 @@ struct iwl_dts_measurement_notif { | |||
| 1680 | __le32 voltage; | 1476 | __le32 voltage; |
| 1681 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S */ | 1477 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S */ |
| 1682 | 1478 | ||
| 1683 | /** | ||
| 1684 | * enum iwl_scd_control - scheduler config command control flags | ||
| 1685 | * @IWL_SCD_CONTROL_RM_TID: remove TID from this queue | ||
| 1686 | * @IWL_SCD_CONTROL_SET_SSN: use the SSN and program it into HW | ||
| 1687 | */ | ||
| 1688 | enum iwl_scd_control { | ||
| 1689 | IWL_SCD_CONTROL_RM_TID = BIT(4), | ||
| 1690 | IWL_SCD_CONTROL_SET_SSN = BIT(5), | ||
| 1691 | }; | ||
| 1692 | |||
| 1693 | /** | ||
| 1694 | * enum iwl_scd_flags - scheduler config command flags | ||
| 1695 | * @IWL_SCD_FLAGS_SHARE_TID: multiple TIDs map to this queue | ||
| 1696 | * @IWL_SCD_FLAGS_SHARE_RA: multiple RAs map to this queue | ||
| 1697 | * @IWL_SCD_FLAGS_DQA_ENABLED: DQA is enabled | ||
| 1698 | */ | ||
| 1699 | enum iwl_scd_flags { | ||
| 1700 | IWL_SCD_FLAGS_SHARE_TID = BIT(0), | ||
| 1701 | IWL_SCD_FLAGS_SHARE_RA = BIT(1), | ||
| 1702 | IWL_SCD_FLAGS_DQA_ENABLED = BIT(2), | ||
| 1703 | }; | ||
| 1704 | |||
| 1705 | #define IWL_SCDQ_INVALID_STA 0xff | ||
| 1706 | |||
| 1707 | /** | ||
| 1708 | * struct iwl_scd_txq_cfg_cmd - New txq hw scheduler config command | ||
| 1709 | * @token: dialog token addba - unused legacy | ||
| 1710 | * @sta_id: station id 4-bit | ||
| 1711 | * @tid: TID 0..7 | ||
| 1712 | * @scd_queue: TFD queue num 0 .. 31 | ||
| 1713 | * @enable: 1 queue enable, 0 queue disable | ||
| 1714 | * @aggregate: 1 aggregated queue, 0 otherwise | ||
| 1715 | * @tx_fifo: tx fifo num 0..7 | ||
| 1716 | * @window: up to 64 | ||
| 1717 | * @ssn: starting seq num 12-bit | ||
| 1718 | * @control: command control flags | ||
| 1719 | * @flags: flags - see &enum iwl_scd_flags | ||
| 1720 | * | ||
| 1721 | * Note that every time the command is sent, all parameters must | ||
| 1722 | * be filled with the exception of | ||
| 1723 | * - the SSN, which is only used with @IWL_SCD_CONTROL_SET_SSN | ||
| 1724 | * - the window, which is only relevant when starting aggregation | ||
| 1725 | */ | ||
| 1726 | struct iwl_scd_txq_cfg_cmd { | ||
| 1727 | u8 token; | ||
| 1728 | u8 sta_id; | ||
| 1729 | u8 tid; | ||
| 1730 | u8 scd_queue; | ||
| 1731 | u8 enable; | ||
| 1732 | u8 aggregate; | ||
| 1733 | u8 tx_fifo; | ||
| 1734 | u8 window; | ||
| 1735 | __le16 ssn; | ||
| 1736 | u8 control; | ||
| 1737 | u8 flags; | ||
| 1738 | } __packed; | ||
| 1739 | |||
| 1740 | /*********************************** | 1479 | /*********************************** |
| 1741 | * TDLS API | 1480 | * TDLS API |
| 1742 | ***********************************/ | 1481 | ***********************************/ |
| @@ -1878,4 +1617,36 @@ struct iwl_tdls_config_res { | |||
| 1878 | struct iwl_tdls_config_sta_info_res sta_info[IWL_MVM_TDLS_STA_COUNT]; | 1617 | struct iwl_tdls_config_sta_info_res sta_info[IWL_MVM_TDLS_STA_COUNT]; |
| 1879 | } __packed; /* TDLS_CONFIG_RSP_API_S_VER_1 */ | 1618 | } __packed; /* TDLS_CONFIG_RSP_API_S_VER_1 */ |
| 1880 | 1619 | ||
| 1620 | #define TX_FIFO_MAX_NUM 8 | ||
| 1621 | #define RX_FIFO_MAX_NUM 2 | ||
| 1622 | |||
| 1623 | /** | ||
| 1624 | * Shared memory configuration information from the FW | ||
| 1625 | * | ||
| 1626 | * @shared_mem_addr: shared memory addr (pre 8000 HW set to 0x0 as MARBH is not | ||
| 1627 | * accessible) | ||
| 1628 | * @shared_mem_size: shared memory size | ||
| 1629 | * @sample_buff_addr: internal sample (mon/adc) buff addr (pre 8000 HW set to | ||
| 1630 | * 0x0 as accessible only via DBGM RDAT) | ||
| 1631 | * @sample_buff_size: internal sample buff size | ||
| 1632 | * @txfifo_addr: start addr of TXF0 (excluding the context table 0.5KB), (pre | ||
| 1633 | * 8000 HW set to 0x0 as not accessible) | ||
| 1634 | * @txfifo_size: size of TXF0 ... TXF7 | ||
| 1635 | * @rxfifo_size: RXF1, RXF2 sizes. If there is no RXF2, it'll have a value of 0 | ||
| 1636 | * @page_buff_addr: used by UMAC and performance debug (page miss analysis), | ||
| 1637 | * when paging is not supported this should be 0 | ||
| 1638 | * @page_buff_size: size of %page_buff_addr | ||
| 1639 | */ | ||
| 1640 | struct iwl_shared_mem_cfg { | ||
| 1641 | __le32 shared_mem_addr; | ||
| 1642 | __le32 shared_mem_size; | ||
| 1643 | __le32 sample_buff_addr; | ||
| 1644 | __le32 sample_buff_size; | ||
| 1645 | __le32 txfifo_addr; | ||
| 1646 | __le32 txfifo_size[TX_FIFO_MAX_NUM]; | ||
| 1647 | __le32 rxfifo_size[RX_FIFO_MAX_NUM]; | ||
| 1648 | __le32 page_buff_addr; | ||
| 1649 | __le32 page_buff_size; | ||
| 1650 | } __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */ | ||
| 1651 | |||
| 1881 | #endif /* __fw_api_h__ */ | 1652 | #endif /* __fw_api_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 534ee3123a63..ca38e9817374 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
| @@ -400,10 +400,59 @@ out: | |||
| 400 | return ret; | 400 | return ret; |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | void iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm) | 403 | static void iwl_mvm_get_shared_mem_conf(struct iwl_mvm *mvm) |
| 404 | { | 404 | { |
| 405 | struct iwl_host_cmd cmd = { | ||
| 406 | .id = SHARED_MEM_CFG, | ||
| 407 | .flags = CMD_WANT_SKB, | ||
| 408 | .data = { NULL, }, | ||
| 409 | .len = { 0, }, | ||
| 410 | }; | ||
| 411 | struct iwl_rx_packet *pkt; | ||
| 412 | struct iwl_shared_mem_cfg *mem_cfg; | ||
| 413 | u32 i; | ||
| 414 | |||
| 405 | lockdep_assert_held(&mvm->mutex); | 415 | lockdep_assert_held(&mvm->mutex); |
| 406 | 416 | ||
| 417 | if (WARN_ON(iwl_mvm_send_cmd(mvm, &cmd))) | ||
| 418 | return; | ||
| 419 | |||
| 420 | pkt = cmd.resp_pkt; | ||
| 421 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
| 422 | IWL_ERR(mvm, "Bad return from SHARED_MEM_CFG (0x%08X)\n", | ||
| 423 | pkt->hdr.flags); | ||
| 424 | goto exit; | ||
| 425 | } | ||
| 426 | |||
| 427 | mem_cfg = (void *)pkt->data; | ||
| 428 | |||
| 429 | mvm->shared_mem_cfg.shared_mem_addr = | ||
| 430 | le32_to_cpu(mem_cfg->shared_mem_addr); | ||
| 431 | mvm->shared_mem_cfg.shared_mem_size = | ||
| 432 | le32_to_cpu(mem_cfg->shared_mem_size); | ||
| 433 | mvm->shared_mem_cfg.sample_buff_addr = | ||
| 434 | le32_to_cpu(mem_cfg->sample_buff_addr); | ||
| 435 | mvm->shared_mem_cfg.sample_buff_size = | ||
| 436 | le32_to_cpu(mem_cfg->sample_buff_size); | ||
| 437 | mvm->shared_mem_cfg.txfifo_addr = le32_to_cpu(mem_cfg->txfifo_addr); | ||
| 438 | for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size); i++) | ||
| 439 | mvm->shared_mem_cfg.txfifo_size[i] = | ||
| 440 | le32_to_cpu(mem_cfg->txfifo_size[i]); | ||
| 441 | for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.rxfifo_size); i++) | ||
| 442 | mvm->shared_mem_cfg.rxfifo_size[i] = | ||
| 443 | le32_to_cpu(mem_cfg->rxfifo_size[i]); | ||
| 444 | mvm->shared_mem_cfg.page_buff_addr = | ||
| 445 | le32_to_cpu(mem_cfg->page_buff_addr); | ||
| 446 | mvm->shared_mem_cfg.page_buff_size = | ||
| 447 | le32_to_cpu(mem_cfg->page_buff_size); | ||
| 448 | IWL_DEBUG_INFO(mvm, "SHARED MEM CFG: got memory offsets/sizes\n"); | ||
| 449 | |||
| 450 | exit: | ||
| 451 | iwl_free_resp(&cmd); | ||
| 452 | } | ||
| 453 | |||
| 454 | void iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm) | ||
| 455 | { | ||
| 407 | /* stop recording */ | 456 | /* stop recording */ |
| 408 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 457 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { |
| 409 | iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100); | 458 | iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100); |
| @@ -412,11 +461,7 @@ void iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm) | |||
| 412 | iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0); | 461 | iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0); |
| 413 | } | 462 | } |
| 414 | 463 | ||
| 415 | iwl_mvm_fw_error_dump(mvm); | 464 | schedule_work(&mvm->fw_error_dump_wk); |
| 416 | |||
| 417 | /* start recording again */ | ||
| 418 | WARN_ON_ONCE(mvm->fw->dbg_dest_tlv && | ||
| 419 | iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); | ||
| 420 | } | 465 | } |
| 421 | 466 | ||
| 422 | int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, enum iwl_fw_dbg_conf conf_id) | 467 | int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, enum iwl_fw_dbg_conf conf_id) |
| @@ -454,6 +499,35 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, enum iwl_fw_dbg_conf conf_id) | |||
| 454 | return ret; | 499 | return ret; |
| 455 | } | 500 | } |
| 456 | 501 | ||
| 502 | static int iwl_mvm_config_ltr_v1(struct iwl_mvm *mvm) | ||
| 503 | { | ||
| 504 | struct iwl_ltr_config_cmd_v1 cmd_v1 = { | ||
| 505 | .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), | ||
| 506 | }; | ||
| 507 | |||
| 508 | if (!mvm->trans->ltr_enabled) | ||
| 509 | return 0; | ||
| 510 | |||
| 511 | return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, | ||
| 512 | sizeof(cmd_v1), &cmd_v1); | ||
| 513 | } | ||
| 514 | |||
| 515 | static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) | ||
| 516 | { | ||
| 517 | struct iwl_ltr_config_cmd cmd = { | ||
| 518 | .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), | ||
| 519 | }; | ||
| 520 | |||
| 521 | if (!mvm->trans->ltr_enabled) | ||
| 522 | return 0; | ||
| 523 | |||
| 524 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_HDC_PHASE_0)) | ||
| 525 | return iwl_mvm_config_ltr_v1(mvm); | ||
| 526 | |||
| 527 | return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, | ||
| 528 | sizeof(cmd), &cmd); | ||
| 529 | } | ||
| 530 | |||
| 457 | int iwl_mvm_up(struct iwl_mvm *mvm) | 531 | int iwl_mvm_up(struct iwl_mvm *mvm) |
| 458 | { | 532 | { |
| 459 | int ret, i; | 533 | int ret, i; |
| @@ -501,6 +575,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 501 | goto error; | 575 | goto error; |
| 502 | } | 576 | } |
| 503 | 577 | ||
| 578 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 10) | ||
| 579 | iwl_mvm_get_shared_mem_conf(mvm); | ||
| 580 | |||
| 504 | ret = iwl_mvm_sf_update(mvm, NULL, false); | 581 | ret = iwl_mvm_sf_update(mvm, NULL, false); |
| 505 | if (ret) | 582 | if (ret) |
| 506 | IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); | 583 | IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); |
| @@ -557,14 +634,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 557 | /* Initialize tx backoffs to the minimal possible */ | 634 | /* Initialize tx backoffs to the minimal possible */ |
| 558 | iwl_mvm_tt_tx_backoff(mvm, 0); | 635 | iwl_mvm_tt_tx_backoff(mvm, 0); |
| 559 | 636 | ||
| 560 | if (mvm->trans->ltr_enabled) { | 637 | WARN_ON(iwl_mvm_config_ltr(mvm)); |
| 561 | struct iwl_ltr_config_cmd cmd = { | ||
| 562 | .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), | ||
| 563 | }; | ||
| 564 | |||
| 565 | WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, | ||
| 566 | sizeof(cmd), &cmd)); | ||
| 567 | } | ||
| 568 | 638 | ||
| 569 | ret = iwl_mvm_power_update_device(mvm); | 639 | ret = iwl_mvm_power_update_device(mvm); |
| 570 | if (ret) | 640 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 7196b4d6b7cc..7bdc6220743f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
| @@ -208,8 +208,10 @@ u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif) | |||
| 208 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) | 208 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) |
| 209 | return BIT(IWL_MVM_OFFCHANNEL_QUEUE); | 209 | return BIT(IWL_MVM_OFFCHANNEL_QUEUE); |
| 210 | 210 | ||
| 211 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 211 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 212 | qmask |= BIT(vif->hw_queue[ac]); | 212 | if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE) |
| 213 | qmask |= BIT(vif->hw_queue[ac]); | ||
| 214 | } | ||
| 213 | 215 | ||
| 214 | if (vif->type == NL80211_IFTYPE_AP) | 216 | if (vif->type == NL80211_IFTYPE_AP) |
| 215 | qmask |= BIT(vif->cab_queue); | 217 | qmask |= BIT(vif->cab_queue); |
| @@ -460,6 +462,9 @@ exit_fail: | |||
| 460 | 462 | ||
| 461 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 463 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
| 462 | { | 464 | { |
| 465 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
| 466 | mvm->cfg->base_params->wd_timeout : | ||
| 467 | IWL_WATCHDOG_DISABLED; | ||
| 463 | u32 ac; | 468 | u32 ac; |
| 464 | int ret; | 469 | int ret; |
| 465 | 470 | ||
| @@ -472,16 +477,17 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 472 | switch (vif->type) { | 477 | switch (vif->type) { |
| 473 | case NL80211_IFTYPE_P2P_DEVICE: | 478 | case NL80211_IFTYPE_P2P_DEVICE: |
| 474 | iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, | 479 | iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, |
| 475 | IWL_MVM_TX_FIFO_VO); | 480 | IWL_MVM_TX_FIFO_VO, wdg_timeout); |
| 476 | break; | 481 | break; |
| 477 | case NL80211_IFTYPE_AP: | 482 | case NL80211_IFTYPE_AP: |
| 478 | iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, | 483 | iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, |
| 479 | IWL_MVM_TX_FIFO_MCAST); | 484 | IWL_MVM_TX_FIFO_MCAST, wdg_timeout); |
| 480 | /* fall through */ | 485 | /* fall through */ |
| 481 | default: | 486 | default: |
| 482 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 487 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
| 483 | iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], | 488 | iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], |
| 484 | iwl_mvm_ac_to_tx_fifo[ac]); | 489 | iwl_mvm_ac_to_tx_fifo[ac], |
| 490 | wdg_timeout); | ||
| 485 | break; | 491 | break; |
| 486 | } | 492 | } |
| 487 | 493 | ||
| @@ -496,14 +502,14 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 496 | 502 | ||
| 497 | switch (vif->type) { | 503 | switch (vif->type) { |
| 498 | case NL80211_IFTYPE_P2P_DEVICE: | 504 | case NL80211_IFTYPE_P2P_DEVICE: |
| 499 | iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE); | 505 | iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, 0); |
| 500 | break; | 506 | break; |
| 501 | case NL80211_IFTYPE_AP: | 507 | case NL80211_IFTYPE_AP: |
| 502 | iwl_mvm_disable_txq(mvm, vif->cab_queue); | 508 | iwl_mvm_disable_txq(mvm, vif->cab_queue, 0); |
| 503 | /* fall through */ | 509 | /* fall through */ |
| 504 | default: | 510 | default: |
| 505 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 511 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
| 506 | iwl_mvm_disable_txq(mvm, vif->hw_queue[ac]); | 512 | iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], 0); |
| 507 | } | 513 | } |
| 508 | } | 514 | } |
| 509 | 515 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 3756c03e752f..1ff7ec08532d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
| @@ -327,6 +327,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 327 | hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC | | 327 | hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC | |
| 328 | IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED; | 328 | IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED; |
| 329 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 329 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
| 330 | hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; | ||
| 331 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
| 330 | 332 | ||
| 331 | /* | 333 | /* |
| 332 | * Enable 11w if advertised by firmware and software crypto | 334 | * Enable 11w if advertised by firmware and software crypto |
| @@ -337,13 +339,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 337 | !iwlwifi_mod_params.sw_crypto) | 339 | !iwlwifi_mod_params.sw_crypto) |
| 338 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 340 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
| 339 | 341 | ||
| 340 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT && | ||
| 341 | !iwlwifi_mod_params.uapsd_disable) { | ||
| 342 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; | ||
| 343 | hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; | ||
| 344 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
| 345 | } | ||
| 346 | |||
| 347 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN || | 342 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN || |
| 348 | mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) { | 343 | mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) { |
| 349 | hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS; | 344 | hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS; |
| @@ -406,10 +401,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 406 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) | 401 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) |
| 407 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 402 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
| 408 | &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; | 403 | &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; |
| 409 | if (mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels) | 404 | if (mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels) { |
| 410 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 405 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
| 411 | &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; | 406 | &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; |
| 412 | 407 | ||
| 408 | if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BEAMFORMER) | ||
| 409 | hw->wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |= | ||
| 410 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; | ||
| 411 | } | ||
| 412 | |||
| 413 | hw->wiphy->hw_version = mvm->trans->hw_id; | 413 | hw->wiphy->hw_version = mvm->trans->hw_id; |
| 414 | 414 | ||
| 415 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) | 415 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) |
| @@ -712,9 +712,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, | |||
| 712 | mvmvif->uploaded = false; | 712 | mvmvif->uploaded = false; |
| 713 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; | 713 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; |
| 714 | 714 | ||
| 715 | /* does this make sense at all? */ | ||
| 716 | mvmvif->color++; | ||
| 717 | |||
| 718 | spin_lock_bh(&mvm->time_event_lock); | 715 | spin_lock_bh(&mvm->time_event_lock); |
| 719 | iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); | 716 | iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); |
| 720 | spin_unlock_bh(&mvm->time_event_lock); | 717 | spin_unlock_bh(&mvm->time_event_lock); |
| @@ -766,6 +763,132 @@ static void iwl_mvm_free_coredump(const void *data) | |||
| 766 | kfree(fw_error_dump); | 763 | kfree(fw_error_dump); |
| 767 | } | 764 | } |
| 768 | 765 | ||
| 766 | static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm, | ||
| 767 | struct iwl_fw_error_dump_data **dump_data) | ||
| 768 | { | ||
| 769 | struct iwl_fw_error_dump_fifo *fifo_hdr; | ||
| 770 | u32 *fifo_data; | ||
| 771 | u32 fifo_len; | ||
| 772 | unsigned long flags; | ||
| 773 | int i, j; | ||
| 774 | |||
| 775 | if (!iwl_trans_grab_nic_access(mvm->trans, false, &flags)) | ||
| 776 | return; | ||
| 777 | |||
| 778 | /* Pull RXF data from all RXFs */ | ||
| 779 | for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.rxfifo_size); i++) { | ||
| 780 | /* | ||
| 781 | * Keep aside the additional offset that might be needed for | ||
| 782 | * next RXF | ||
| 783 | */ | ||
| 784 | u32 offset_diff = RXF_DIFF_FROM_PREV * i; | ||
| 785 | |||
| 786 | fifo_hdr = (void *)(*dump_data)->data; | ||
| 787 | fifo_data = (void *)fifo_hdr->data; | ||
| 788 | fifo_len = mvm->shared_mem_cfg.rxfifo_size[i]; | ||
| 789 | |||
| 790 | /* No need to try to read the data if the length is 0 */ | ||
| 791 | if (fifo_len == 0) | ||
| 792 | continue; | ||
| 793 | |||
| 794 | /* Add a TLV for the RXF */ | ||
| 795 | (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF); | ||
| 796 | (*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr)); | ||
| 797 | |||
| 798 | fifo_hdr->fifo_num = cpu_to_le32(i); | ||
| 799 | fifo_hdr->available_bytes = | ||
| 800 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 801 | RXF_RD_D_SPACE + | ||
| 802 | offset_diff)); | ||
| 803 | fifo_hdr->wr_ptr = | ||
| 804 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 805 | RXF_RD_WR_PTR + | ||
| 806 | offset_diff)); | ||
| 807 | fifo_hdr->rd_ptr = | ||
| 808 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 809 | RXF_RD_RD_PTR + | ||
| 810 | offset_diff)); | ||
| 811 | fifo_hdr->fence_ptr = | ||
| 812 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 813 | RXF_RD_FENCE_PTR + | ||
| 814 | offset_diff)); | ||
| 815 | fifo_hdr->fence_mode = | ||
| 816 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 817 | RXF_SET_FENCE_MODE + | ||
| 818 | offset_diff)); | ||
| 819 | |||
| 820 | /* Lock fence */ | ||
| 821 | iwl_trans_write_prph(mvm->trans, | ||
| 822 | RXF_SET_FENCE_MODE + offset_diff, 0x1); | ||
| 823 | /* Set fence pointer to the same place like WR pointer */ | ||
| 824 | iwl_trans_write_prph(mvm->trans, | ||
| 825 | RXF_LD_WR2FENCE + offset_diff, 0x1); | ||
| 826 | /* Set fence offset */ | ||
| 827 | iwl_trans_write_prph(mvm->trans, | ||
| 828 | RXF_LD_FENCE_OFFSET_ADDR + offset_diff, | ||
| 829 | 0x0); | ||
| 830 | |||
| 831 | /* Read FIFO */ | ||
| 832 | fifo_len /= sizeof(u32); /* Size in DWORDS */ | ||
| 833 | for (j = 0; j < fifo_len; j++) | ||
| 834 | fifo_data[j] = iwl_trans_read_prph(mvm->trans, | ||
| 835 | RXF_FIFO_RD_FENCE_INC + | ||
| 836 | offset_diff); | ||
| 837 | *dump_data = iwl_fw_error_next_data(*dump_data); | ||
| 838 | } | ||
| 839 | |||
| 840 | /* Pull TXF data from all TXFs */ | ||
| 841 | for (i = 0; i < ARRAY_SIZE(mvm->shared_mem_cfg.txfifo_size); i++) { | ||
| 842 | /* Mark the number of TXF we're pulling now */ | ||
| 843 | iwl_trans_write_prph(mvm->trans, TXF_LARC_NUM, i); | ||
| 844 | |||
| 845 | fifo_hdr = (void *)(*dump_data)->data; | ||
| 846 | fifo_data = (void *)fifo_hdr->data; | ||
| 847 | fifo_len = mvm->shared_mem_cfg.txfifo_size[i]; | ||
| 848 | |||
| 849 | /* No need to try to read the data if the length is 0 */ | ||
| 850 | if (fifo_len == 0) | ||
| 851 | continue; | ||
| 852 | |||
| 853 | /* Add a TLV for the FIFO */ | ||
| 854 | (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXF); | ||
| 855 | (*dump_data)->len = cpu_to_le32(fifo_len + sizeof(*fifo_hdr)); | ||
| 856 | |||
| 857 | fifo_hdr->fifo_num = cpu_to_le32(i); | ||
| 858 | fifo_hdr->available_bytes = | ||
| 859 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 860 | TXF_FIFO_ITEM_CNT)); | ||
| 861 | fifo_hdr->wr_ptr = | ||
| 862 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 863 | TXF_WR_PTR)); | ||
| 864 | fifo_hdr->rd_ptr = | ||
| 865 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 866 | TXF_RD_PTR)); | ||
| 867 | fifo_hdr->fence_ptr = | ||
| 868 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 869 | TXF_FENCE_PTR)); | ||
| 870 | fifo_hdr->fence_mode = | ||
| 871 | cpu_to_le32(iwl_trans_read_prph(mvm->trans, | ||
| 872 | TXF_LOCK_FENCE)); | ||
| 873 | |||
| 874 | /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */ | ||
| 875 | iwl_trans_write_prph(mvm->trans, TXF_READ_MODIFY_ADDR, | ||
| 876 | TXF_WR_PTR); | ||
| 877 | |||
| 878 | /* Dummy-read to advance the read pointer to the head */ | ||
| 879 | iwl_trans_read_prph(mvm->trans, TXF_READ_MODIFY_DATA); | ||
| 880 | |||
| 881 | /* Read FIFO */ | ||
| 882 | fifo_len /= sizeof(u32); /* Size in DWORDS */ | ||
| 883 | for (j = 0; j < fifo_len; j++) | ||
| 884 | fifo_data[j] = iwl_trans_read_prph(mvm->trans, | ||
| 885 | TXF_READ_MODIFY_DATA); | ||
| 886 | *dump_data = iwl_fw_error_next_data(*dump_data); | ||
| 887 | } | ||
| 888 | |||
| 889 | iwl_trans_release_nic_access(mvm->trans, &flags); | ||
| 890 | } | ||
| 891 | |||
| 769 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | 892 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) |
| 770 | { | 893 | { |
| 771 | struct iwl_fw_error_dump_file *dump_file; | 894 | struct iwl_fw_error_dump_file *dump_file; |
| @@ -774,18 +897,21 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 774 | struct iwl_fw_error_dump_mem *dump_mem; | 897 | struct iwl_fw_error_dump_mem *dump_mem; |
| 775 | struct iwl_mvm_dump_ptrs *fw_error_dump; | 898 | struct iwl_mvm_dump_ptrs *fw_error_dump; |
| 776 | u32 sram_len, sram_ofs; | 899 | u32 sram_len, sram_ofs; |
| 777 | u32 file_len, rxf_len; | 900 | u32 file_len, fifo_data_len = 0; |
| 778 | unsigned long flags; | ||
| 779 | int reg_val; | ||
| 780 | u32 smem_len = mvm->cfg->smem_len; | 901 | u32 smem_len = mvm->cfg->smem_len; |
| 902 | u32 sram2_len = mvm->cfg->dccm2_len; | ||
| 781 | 903 | ||
| 782 | lockdep_assert_held(&mvm->mutex); | 904 | lockdep_assert_held(&mvm->mutex); |
| 783 | 905 | ||
| 784 | /* W/A for 8000 HW family A-step */ | 906 | /* W/A for 8000 HW family A-step */ |
| 785 | if (mvm->cfg->smem_len && | 907 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 && |
| 786 | mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 && | 908 | CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) { |
| 787 | CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) | 909 | if (smem_len) |
| 788 | smem_len = 0x38000; | 910 | smem_len = 0x38000; |
| 911 | |||
| 912 | if (sram2_len) | ||
| 913 | sram2_len = 0x10000; | ||
| 914 | } | ||
| 789 | 915 | ||
| 790 | fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); | 916 | fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); |
| 791 | if (!fw_error_dump) | 917 | if (!fw_error_dump) |
| @@ -803,23 +929,49 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 803 | sram_len = mvm->cfg->dccm_len; | 929 | sram_len = mvm->cfg->dccm_len; |
| 804 | } | 930 | } |
| 805 | 931 | ||
| 806 | /* reading buffer size */ | 932 | /* reading RXF/TXF sizes */ |
| 807 | reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR); | 933 | if (test_bit(STATUS_FW_ERROR, &mvm->trans->status)) { |
| 808 | rxf_len = (reg_val & RXF_SIZE_BYTE_CNT_MSK) >> RXF_SIZE_BYTE_CND_POS; | 934 | struct iwl_mvm_shared_mem_cfg *mem_cfg = &mvm->shared_mem_cfg; |
| 935 | int i; | ||
| 936 | |||
| 937 | fifo_data_len = 0; | ||
| 938 | |||
| 939 | /* Count RXF size */ | ||
| 940 | for (i = 0; i < ARRAY_SIZE(mem_cfg->rxfifo_size); i++) { | ||
| 941 | if (!mem_cfg->rxfifo_size[i]) | ||
| 942 | continue; | ||
| 943 | |||
| 944 | /* Add header info */ | ||
| 945 | fifo_data_len += mem_cfg->rxfifo_size[i] + | ||
| 946 | sizeof(*dump_data) + | ||
| 947 | sizeof(struct iwl_fw_error_dump_fifo); | ||
| 948 | } | ||
| 809 | 949 | ||
| 810 | /* the register holds the value divided by 128 */ | 950 | for (i = 0; i < ARRAY_SIZE(mem_cfg->txfifo_size); i++) { |
| 811 | rxf_len = rxf_len << 7; | 951 | if (!mem_cfg->txfifo_size[i]) |
| 952 | continue; | ||
| 953 | |||
| 954 | /* Add header info */ | ||
| 955 | fifo_data_len += mem_cfg->txfifo_size[i] + | ||
| 956 | sizeof(*dump_data) + | ||
| 957 | sizeof(struct iwl_fw_error_dump_fifo); | ||
| 958 | } | ||
| 959 | } | ||
| 812 | 960 | ||
| 813 | file_len = sizeof(*dump_file) + | 961 | file_len = sizeof(*dump_file) + |
| 814 | sizeof(*dump_data) * 3 + | 962 | sizeof(*dump_data) * 2 + |
| 815 | sram_len + sizeof(*dump_mem) + | 963 | sram_len + sizeof(*dump_mem) + |
| 816 | rxf_len + | 964 | fifo_data_len + |
| 817 | sizeof(*dump_info); | 965 | sizeof(*dump_info); |
| 818 | 966 | ||
| 819 | /* Make room for the SMEM, if it exists */ | 967 | /* Make room for the SMEM, if it exists */ |
| 820 | if (smem_len) | 968 | if (smem_len) |
| 821 | file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len; | 969 | file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len; |
| 822 | 970 | ||
| 971 | /* Make room for the secondary SRAM, if it exists */ | ||
| 972 | if (sram2_len) | ||
| 973 | file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; | ||
| 974 | |||
| 823 | dump_file = vzalloc(file_len); | 975 | dump_file = vzalloc(file_len); |
| 824 | if (!dump_file) { | 976 | if (!dump_file) { |
| 825 | kfree(fw_error_dump); | 977 | kfree(fw_error_dump); |
| @@ -847,24 +999,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 847 | sizeof(dump_info->bus_human_readable)); | 999 | sizeof(dump_info->bus_human_readable)); |
| 848 | 1000 | ||
| 849 | dump_data = iwl_fw_error_next_data(dump_data); | 1001 | dump_data = iwl_fw_error_next_data(dump_data); |
| 850 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF); | 1002 | /* We only dump the FIFOs if the FW is in error state */ |
| 851 | dump_data->len = cpu_to_le32(rxf_len); | 1003 | if (test_bit(STATUS_FW_ERROR, &mvm->trans->status)) |
| 1004 | iwl_mvm_dump_fifos(mvm, &dump_data); | ||
| 852 | 1005 | ||
| 853 | if (iwl_trans_grab_nic_access(mvm->trans, false, &flags)) { | ||
| 854 | u32 *rxf = (void *)dump_data->data; | ||
| 855 | int i; | ||
| 856 | |||
| 857 | for (i = 0; i < (rxf_len / sizeof(u32)); i++) { | ||
| 858 | iwl_trans_write_prph(mvm->trans, | ||
| 859 | RXF_LD_FENCE_OFFSET_ADDR, | ||
| 860 | i * sizeof(u32)); | ||
| 861 | rxf[i] = iwl_trans_read_prph(mvm->trans, | ||
| 862 | RXF_FIFO_RD_FENCE_ADDR); | ||
| 863 | } | ||
| 864 | iwl_trans_release_nic_access(mvm->trans, &flags); | ||
| 865 | } | ||
| 866 | |||
| 867 | dump_data = iwl_fw_error_next_data(dump_data); | ||
| 868 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); | 1006 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); |
| 869 | dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem)); | 1007 | dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem)); |
| 870 | dump_mem = (void *)dump_data->data; | 1008 | dump_mem = (void *)dump_data->data; |
| @@ -884,6 +1022,17 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 884 | dump_mem->data, smem_len); | 1022 | dump_mem->data, smem_len); |
| 885 | } | 1023 | } |
| 886 | 1024 | ||
| 1025 | if (sram2_len) { | ||
| 1026 | dump_data = iwl_fw_error_next_data(dump_data); | ||
| 1027 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); | ||
| 1028 | dump_data->len = cpu_to_le32(sram2_len + sizeof(*dump_mem)); | ||
| 1029 | dump_mem = (void *)dump_data->data; | ||
| 1030 | dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM); | ||
| 1031 | dump_mem->offset = cpu_to_le32(mvm->cfg->dccm2_offset); | ||
| 1032 | iwl_trans_read_mem_bytes(mvm->trans, mvm->cfg->dccm2_offset, | ||
| 1033 | dump_mem->data, sram2_len); | ||
| 1034 | } | ||
| 1035 | |||
| 887 | fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans); | 1036 | fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans); |
| 888 | fw_error_dump->op_mode_len = file_len; | 1037 | fw_error_dump->op_mode_len = file_len; |
| 889 | if (fw_error_dump->trans_ptr) | 1038 | if (fw_error_dump->trans_ptr) |
| @@ -1206,7 +1355,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
| 1206 | 1355 | ||
| 1207 | ret = iwl_mvm_power_update_mac(mvm); | 1356 | ret = iwl_mvm_power_update_mac(mvm); |
| 1208 | if (ret) | 1357 | if (ret) |
| 1209 | goto out_release; | 1358 | goto out_remove_mac; |
| 1210 | 1359 | ||
| 1211 | /* beacon filtering */ | 1360 | /* beacon filtering */ |
| 1212 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); | 1361 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); |
| @@ -2165,6 +2314,20 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, | |||
| 2165 | mutex_unlock(&mvm->mutex); | 2314 | mutex_unlock(&mvm->mutex); |
| 2166 | } | 2315 | } |
| 2167 | 2316 | ||
| 2317 | static void iwl_mvm_check_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
| 2318 | const u8 *bssid) | ||
| 2319 | { | ||
| 2320 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT)) | ||
| 2321 | return; | ||
| 2322 | |||
| 2323 | if (iwlwifi_mod_params.uapsd_disable) { | ||
| 2324 | vif->driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD; | ||
| 2325 | return; | ||
| 2326 | } | ||
| 2327 | |||
| 2328 | vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; | ||
| 2329 | } | ||
| 2330 | |||
| 2168 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | 2331 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, |
| 2169 | struct ieee80211_vif *vif, | 2332 | struct ieee80211_vif *vif, |
| 2170 | struct ieee80211_sta *sta, | 2333 | struct ieee80211_sta *sta, |
| @@ -2224,6 +2387,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
| 2224 | * Reset EBS status here assuming environment has been changed. | 2387 | * Reset EBS status here assuming environment has been changed. |
| 2225 | */ | 2388 | */ |
| 2226 | mvm->last_ebs_successful = true; | 2389 | mvm->last_ebs_successful = true; |
| 2390 | iwl_mvm_check_uapsd(mvm, vif, sta->addr); | ||
| 2227 | ret = 0; | 2391 | ret = 0; |
| 2228 | } else if (old_state == IEEE80211_STA_AUTH && | 2392 | } else if (old_state == IEEE80211_STA_AUTH && |
| 2229 | new_state == IEEE80211_STA_ASSOC) { | 2393 | new_state == IEEE80211_STA_ASSOC) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index b2100b414055..6c69d0584f6c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
| @@ -119,11 +119,13 @@ extern const struct ieee80211_ops iwl_mvm_hw_ops; | |||
| 119 | * We will register to mac80211 to have testmode working. The NIC must not | 119 | * We will register to mac80211 to have testmode working. The NIC must not |
| 120 | * be up'ed after the INIT fw asserted. This is useful to be able to use | 120 | * be up'ed after the INIT fw asserted. This is useful to be able to use |
| 121 | * proprietary tools over testmode to debug the INIT fw. | 121 | * proprietary tools over testmode to debug the INIT fw. |
| 122 | * @tfd_q_hang_detect: enabled the detection of hung transmit queues | ||
| 122 | * @power_scheme: CAM(Continuous Active Mode)-1, BPS(Balanced Power | 123 | * @power_scheme: CAM(Continuous Active Mode)-1, BPS(Balanced Power |
| 123 | * Save)-2(default), LP(Low Power)-3 | 124 | * Save)-2(default), LP(Low Power)-3 |
| 124 | */ | 125 | */ |
| 125 | struct iwl_mvm_mod_params { | 126 | struct iwl_mvm_mod_params { |
| 126 | bool init_dbg; | 127 | bool init_dbg; |
| 128 | bool tfd_q_hang_detect; | ||
| 127 | int power_scheme; | 129 | int power_scheme; |
| 128 | }; | 130 | }; |
| 129 | extern struct iwl_mvm_mod_params iwlmvm_mod_params; | 131 | extern struct iwl_mvm_mod_params iwlmvm_mod_params; |
| @@ -276,6 +278,7 @@ enum iwl_mvm_ref_type { | |||
| 276 | IWL_MVM_REF_TM_CMD, | 278 | IWL_MVM_REF_TM_CMD, |
| 277 | IWL_MVM_REF_EXIT_WORK, | 279 | IWL_MVM_REF_EXIT_WORK, |
| 278 | IWL_MVM_REF_PROTECT_CSA, | 280 | IWL_MVM_REF_PROTECT_CSA, |
| 281 | IWL_MVM_REF_FW_DBG_COLLECT, | ||
| 279 | 282 | ||
| 280 | /* update debugfs.c when changing this */ | 283 | /* update debugfs.c when changing this */ |
| 281 | 284 | ||
| @@ -531,10 +534,23 @@ enum { | |||
| 531 | enum iwl_mvm_tdls_cs_state { | 534 | enum iwl_mvm_tdls_cs_state { |
| 532 | IWL_MVM_TDLS_SW_IDLE = 0, | 535 | IWL_MVM_TDLS_SW_IDLE = 0, |
| 533 | IWL_MVM_TDLS_SW_REQ_SENT, | 536 | IWL_MVM_TDLS_SW_REQ_SENT, |
| 537 | IWL_MVM_TDLS_SW_RESP_RCVD, | ||
| 534 | IWL_MVM_TDLS_SW_REQ_RCVD, | 538 | IWL_MVM_TDLS_SW_REQ_RCVD, |
| 535 | IWL_MVM_TDLS_SW_ACTIVE, | 539 | IWL_MVM_TDLS_SW_ACTIVE, |
| 536 | }; | 540 | }; |
| 537 | 541 | ||
| 542 | struct iwl_mvm_shared_mem_cfg { | ||
| 543 | u32 shared_mem_addr; | ||
| 544 | u32 shared_mem_size; | ||
| 545 | u32 sample_buff_addr; | ||
| 546 | u32 sample_buff_size; | ||
| 547 | u32 txfifo_addr; | ||
| 548 | u32 txfifo_size[TX_FIFO_MAX_NUM]; | ||
| 549 | u32 rxfifo_size[RX_FIFO_MAX_NUM]; | ||
| 550 | u32 page_buff_addr; | ||
| 551 | u32 page_buff_size; | ||
| 552 | }; | ||
| 553 | |||
| 538 | struct iwl_mvm { | 554 | struct iwl_mvm { |
| 539 | /* for logger access */ | 555 | /* for logger access */ |
| 540 | struct device *dev; | 556 | struct device *dev; |
| @@ -641,6 +657,8 @@ struct iwl_mvm { | |||
| 641 | bool disable_power_off; | 657 | bool disable_power_off; |
| 642 | bool disable_power_off_d3; | 658 | bool disable_power_off_d3; |
| 643 | 659 | ||
| 660 | bool scan_iter_notif_enabled; | ||
| 661 | |||
| 644 | struct debugfs_blob_wrapper nvm_hw_blob; | 662 | struct debugfs_blob_wrapper nvm_hw_blob; |
| 645 | struct debugfs_blob_wrapper nvm_sw_blob; | 663 | struct debugfs_blob_wrapper nvm_sw_blob; |
| 646 | struct debugfs_blob_wrapper nvm_calib_blob; | 664 | struct debugfs_blob_wrapper nvm_calib_blob; |
| @@ -782,8 +800,13 @@ struct iwl_mvm { | |||
| 782 | struct cfg80211_chan_def chandef; | 800 | struct cfg80211_chan_def chandef; |
| 783 | struct sk_buff *skb; /* ch sw template */ | 801 | struct sk_buff *skb; /* ch sw template */ |
| 784 | u32 ch_sw_tm_ie; | 802 | u32 ch_sw_tm_ie; |
| 803 | |||
| 804 | /* timestamp of last ch-sw request sent (GP2 time) */ | ||
| 805 | u32 sent_timestamp; | ||
| 785 | } peer; | 806 | } peer; |
| 786 | } tdls_cs; | 807 | } tdls_cs; |
| 808 | |||
| 809 | struct iwl_mvm_shared_mem_cfg shared_mem_cfg; | ||
| 787 | }; | 810 | }; |
| 788 | 811 | ||
| 789 | /* Extract MVM priv from op_mode and _hw */ | 812 | /* Extract MVM priv from op_mode and _hw */ |
| @@ -855,9 +878,9 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) | |||
| 855 | (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); | 878 | (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); |
| 856 | } | 879 | } |
| 857 | 880 | ||
| 858 | static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) | 881 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) |
| 859 | { | 882 | { |
| 860 | return mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_DQA_SUPPORT; | 883 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SCD_CFG; |
| 861 | } | 884 | } |
| 862 | 885 | ||
| 863 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 886 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
| @@ -999,6 +1022,9 @@ int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 999 | struct iwl_device_cmd *cmd); | 1022 | struct iwl_device_cmd *cmd); |
| 1000 | int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | 1023 | int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, |
| 1001 | struct iwl_device_cmd *cmd); | 1024 | struct iwl_device_cmd *cmd); |
| 1025 | int iwl_mvm_rx_shared_mem_cfg_notif(struct iwl_mvm *mvm, | ||
| 1026 | struct iwl_rx_cmd_buffer *rxb, | ||
| 1027 | struct iwl_device_cmd *cmd); | ||
| 1002 | 1028 | ||
| 1003 | /* MVM PHY */ | 1029 | /* MVM PHY */ |
| 1004 | int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | 1030 | int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, |
| @@ -1060,6 +1086,9 @@ int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm, bool is_sched_scan); | |||
| 1060 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | 1086 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, |
| 1061 | struct iwl_rx_cmd_buffer *rxb, | 1087 | struct iwl_rx_cmd_buffer *rxb, |
| 1062 | struct iwl_device_cmd *cmd); | 1088 | struct iwl_device_cmd *cmd); |
| 1089 | int iwl_mvm_rx_scan_offload_iter_complete_notif(struct iwl_mvm *mvm, | ||
| 1090 | struct iwl_rx_cmd_buffer *rxb, | ||
| 1091 | struct iwl_device_cmd *cmd); | ||
| 1063 | int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | 1092 | int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, |
| 1064 | struct ieee80211_vif *vif, | 1093 | struct ieee80211_vif *vif, |
| 1065 | struct cfg80211_sched_scan_request *req, | 1094 | struct cfg80211_sched_scan_request *req, |
| @@ -1120,9 +1149,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1120 | 1149 | ||
| 1121 | /* rate scaling */ | 1150 | /* rate scaling */ |
| 1122 | int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); | 1151 | int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); |
| 1123 | void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, | 1152 | void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg); |
| 1124 | struct iwl_mvm_frame_stats *stats, | ||
| 1125 | u32 rate, bool agg); | ||
| 1126 | int rs_pretty_print_rate(char *buf, const u32 rate); | 1153 | int rs_pretty_print_rate(char *buf, const u32 rate); |
| 1127 | void rs_update_last_rssi(struct iwl_mvm *mvm, | 1154 | void rs_update_last_rssi(struct iwl_mvm *mvm, |
| 1128 | struct iwl_lq_sta *lq_sta, | 1155 | struct iwl_lq_sta *lq_sta, |
| @@ -1291,11 +1318,13 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) | |||
| 1291 | 1318 | ||
| 1292 | /* hw scheduler queue config */ | 1319 | /* hw scheduler queue config */ |
| 1293 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | 1320 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, |
| 1294 | const struct iwl_trans_txq_scd_cfg *cfg); | 1321 | const struct iwl_trans_txq_scd_cfg *cfg, |
| 1295 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue); | 1322 | unsigned int wdg_timeout); |
| 1323 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags); | ||
| 1296 | 1324 | ||
| 1297 | static inline void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, | 1325 | static inline |
| 1298 | u8 fifo) | 1326 | void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, |
| 1327 | u8 fifo, unsigned int wdg_timeout) | ||
| 1299 | { | 1328 | { |
| 1300 | struct iwl_trans_txq_scd_cfg cfg = { | 1329 | struct iwl_trans_txq_scd_cfg cfg = { |
| 1301 | .fifo = fifo, | 1330 | .fifo = fifo, |
| @@ -1304,12 +1333,13 @@ static inline void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, | |||
| 1304 | .frame_limit = IWL_FRAME_LIMIT, | 1333 | .frame_limit = IWL_FRAME_LIMIT, |
| 1305 | }; | 1334 | }; |
| 1306 | 1335 | ||
| 1307 | iwl_mvm_enable_txq(mvm, queue, 0, &cfg); | 1336 | iwl_mvm_enable_txq(mvm, queue, 0, &cfg, wdg_timeout); |
| 1308 | } | 1337 | } |
| 1309 | 1338 | ||
| 1310 | static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, | 1339 | static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, |
| 1311 | int fifo, int sta_id, int tid, | 1340 | int fifo, int sta_id, int tid, |
| 1312 | int frame_limit, u16 ssn) | 1341 | int frame_limit, u16 ssn, |
| 1342 | unsigned int wdg_timeout) | ||
| 1313 | { | 1343 | { |
| 1314 | struct iwl_trans_txq_scd_cfg cfg = { | 1344 | struct iwl_trans_txq_scd_cfg cfg = { |
| 1315 | .fifo = fifo, | 1345 | .fifo = fifo, |
| @@ -1319,7 +1349,7 @@ static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, | |||
| 1319 | .aggregate = true, | 1349 | .aggregate = true, |
| 1320 | }; | 1350 | }; |
| 1321 | 1351 | ||
| 1322 | iwl_mvm_enable_txq(mvm, queue, ssn, &cfg); | 1352 | iwl_mvm_enable_txq(mvm, queue, ssn, &cfg, wdg_timeout); |
| 1323 | } | 1353 | } |
| 1324 | 1354 | ||
| 1325 | /* Assoc status */ | 1355 | /* Assoc status */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index d55fd8e3654c..5383429d96c1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
| @@ -356,7 +356,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
| 356 | max_section_size = IWL_MAX_NVM_SECTION_SIZE; | 356 | max_section_size = IWL_MAX_NVM_SECTION_SIZE; |
| 357 | else if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) | 357 | else if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) |
| 358 | max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE; | 358 | max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE; |
| 359 | else /* Family 8000 B-step */ | 359 | else /* Family 8000 B-step or C-step */ |
| 360 | max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE; | 360 | max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE; |
| 361 | 361 | ||
| 362 | /* | 362 | /* |
| @@ -565,6 +565,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) | |||
| 565 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | 565 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
| 566 | if (!mvm->nvm_data) | 566 | if (!mvm->nvm_data) |
| 567 | return -ENODATA; | 567 | return -ENODATA; |
| 568 | IWL_DEBUG_EEPROM(mvm->trans->dev, "nvm version = %x\n", | ||
| 569 | mvm->nvm_data->nvm_version); | ||
| 568 | 570 | ||
| 569 | return 0; | 571 | return 0; |
| 570 | } | 572 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 239f033e3b93..2dffc3600ed3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
| @@ -93,6 +93,7 @@ static const struct iwl_op_mode_ops iwl_mvm_ops; | |||
| 93 | 93 | ||
| 94 | struct iwl_mvm_mod_params iwlmvm_mod_params = { | 94 | struct iwl_mvm_mod_params iwlmvm_mod_params = { |
| 95 | .power_scheme = IWL_POWER_SCHEME_BPS, | 95 | .power_scheme = IWL_POWER_SCHEME_BPS, |
| 96 | .tfd_q_hang_detect = true | ||
| 96 | /* rest of fields are 0 by default */ | 97 | /* rest of fields are 0 by default */ |
| 97 | }; | 98 | }; |
| 98 | 99 | ||
| @@ -102,6 +103,10 @@ MODULE_PARM_DESC(init_dbg, | |||
| 102 | module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, S_IRUGO); | 103 | module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, S_IRUGO); |
| 103 | MODULE_PARM_DESC(power_scheme, | 104 | MODULE_PARM_DESC(power_scheme, |
| 104 | "power management scheme: 1-active, 2-balanced, 3-low power, default: 2"); | 105 | "power management scheme: 1-active, 2-balanced, 3-low power, default: 2"); |
| 106 | module_param_named(tfd_q_hang_detect, iwlmvm_mod_params.tfd_q_hang_detect, | ||
| 107 | bool, S_IRUGO); | ||
| 108 | MODULE_PARM_DESC(tfd_q_hang_detect, | ||
| 109 | "TFD queues hang detection (default: true"); | ||
| 105 | 110 | ||
| 106 | /* | 111 | /* |
| 107 | * module init and exit functions | 112 | * module init and exit functions |
| @@ -234,6 +239,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
| 234 | 239 | ||
| 235 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), | 240 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), |
| 236 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true), | 241 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true), |
| 242 | RX_HANDLER(SCAN_ITERATION_COMPLETE, | ||
| 243 | iwl_mvm_rx_scan_offload_iter_complete_notif, false), | ||
| 237 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, | 244 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, |
| 238 | iwl_mvm_rx_scan_offload_complete_notif, true), | 245 | iwl_mvm_rx_scan_offload_complete_notif, true), |
| 239 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results, | 246 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results, |
| @@ -268,6 +275,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
| 268 | CMD(MGMT_MCAST_KEY), | 275 | CMD(MGMT_MCAST_KEY), |
| 269 | CMD(TX_CMD), | 276 | CMD(TX_CMD), |
| 270 | CMD(TXPATH_FLUSH), | 277 | CMD(TXPATH_FLUSH), |
| 278 | CMD(SHARED_MEM_CFG), | ||
| 271 | CMD(MAC_CONTEXT_CMD), | 279 | CMD(MAC_CONTEXT_CMD), |
| 272 | CMD(TIME_EVENT_CMD), | 280 | CMD(TIME_EVENT_CMD), |
| 273 | CMD(TIME_EVENT_NOTIFICATION), | 281 | CMD(TIME_EVENT_NOTIFICATION), |
| @@ -470,11 +478,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 470 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE) | 478 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE) |
| 471 | trans_cfg.bc_table_dword = true; | 479 | trans_cfg.bc_table_dword = true; |
| 472 | 480 | ||
| 473 | if (!iwlwifi_mod_params.wd_disable) | ||
| 474 | trans_cfg.queue_watchdog_timeout = cfg->base_params->wd_timeout; | ||
| 475 | else | ||
| 476 | trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; | ||
| 477 | |||
| 478 | trans_cfg.command_names = iwl_mvm_cmd_strings; | 481 | trans_cfg.command_names = iwl_mvm_cmd_strings; |
| 479 | 482 | ||
| 480 | trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE; | 483 | trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE; |
| @@ -483,6 +486,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 483 | 486 | ||
| 484 | trans_cfg.sdio_adma_addr = fw->sdio_adma_addr; | 487 | trans_cfg.sdio_adma_addr = fw->sdio_adma_addr; |
| 485 | 488 | ||
| 489 | /* Set a short watchdog for the command queue */ | ||
| 490 | trans_cfg.cmd_q_wdg_timeout = | ||
| 491 | iwlmvm_mod_params.tfd_q_hang_detect ? IWL_DEF_WD_TIMEOUT : | ||
| 492 | IWL_WATCHDOG_DISABLED; | ||
| 493 | |||
| 486 | snprintf(mvm->hw->wiphy->fw_version, | 494 | snprintf(mvm->hw->wiphy->fw_version, |
| 487 | sizeof(mvm->hw->wiphy->fw_version), | 495 | sizeof(mvm->hw->wiphy->fw_version), |
| 488 | "%s", fw->fw_version); | 496 | "%s", fw->fw_version); |
| @@ -560,6 +568,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 560 | if (!mvm->scan_cmd) | 568 | if (!mvm->scan_cmd) |
| 561 | goto out_free; | 569 | goto out_free; |
| 562 | 570 | ||
| 571 | /* Set EBS as successful as long as not stated otherwise by the FW. */ | ||
| 572 | mvm->last_ebs_successful = true; | ||
| 573 | |||
| 563 | err = iwl_mvm_mac_setup_register(mvm); | 574 | err = iwl_mvm_mac_setup_register(mvm); |
| 564 | if (err) | 575 | if (err) |
| 565 | goto out_free; | 576 | goto out_free; |
| @@ -818,9 +829,20 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work) | |||
| 818 | struct iwl_mvm *mvm = | 829 | struct iwl_mvm *mvm = |
| 819 | container_of(work, struct iwl_mvm, fw_error_dump_wk); | 830 | container_of(work, struct iwl_mvm, fw_error_dump_wk); |
| 820 | 831 | ||
| 832 | if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT)) | ||
| 833 | return; | ||
| 834 | |||
| 821 | mutex_lock(&mvm->mutex); | 835 | mutex_lock(&mvm->mutex); |
| 822 | iwl_mvm_fw_error_dump(mvm); | 836 | iwl_mvm_fw_error_dump(mvm); |
| 837 | |||
| 838 | /* start recording again if the firmware is not crashed */ | ||
| 839 | WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) && | ||
| 840 | mvm->fw->dbg_dest_tlv && | ||
| 841 | iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); | ||
| 842 | |||
| 823 | mutex_unlock(&mvm->mutex); | 843 | mutex_unlock(&mvm->mutex); |
| 844 | |||
| 845 | iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT); | ||
| 824 | } | 846 | } |
| 825 | 847 | ||
| 826 | void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) | 848 | void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) |
| @@ -856,7 +878,10 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) | |||
| 856 | * If WoWLAN fw asserted, don't restart either, mac80211 | 878 | * If WoWLAN fw asserted, don't restart either, mac80211 |
| 857 | * can't recover this since we're already half suspended. | 879 | * can't recover this since we're already half suspended. |
| 858 | */ | 880 | */ |
| 859 | if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | 881 | if (!mvm->restart_fw && fw_error) { |
| 882 | schedule_work(&mvm->fw_error_dump_wk); | ||
| 883 | } else if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, | ||
| 884 | &mvm->status)) { | ||
| 860 | struct iwl_mvm_reprobe *reprobe; | 885 | struct iwl_mvm_reprobe *reprobe; |
| 861 | 886 | ||
| 862 | IWL_ERR(mvm, | 887 | IWL_ERR(mvm, |
| @@ -880,16 +905,13 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) | |||
| 880 | reprobe->dev = mvm->trans->dev; | 905 | reprobe->dev = mvm->trans->dev; |
| 881 | INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); | 906 | INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); |
| 882 | schedule_work(&reprobe->work); | 907 | schedule_work(&reprobe->work); |
| 883 | } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && | 908 | } else if (mvm->cur_ucode == IWL_UCODE_REGULAR) { |
| 884 | (!fw_error || mvm->restart_fw)) { | ||
| 885 | /* don't let the transport/FW power down */ | 909 | /* don't let the transport/FW power down */ |
| 886 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); | 910 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); |
| 887 | 911 | ||
| 888 | if (fw_error && mvm->restart_fw > 0) | 912 | if (fw_error && mvm->restart_fw > 0) |
| 889 | mvm->restart_fw--; | 913 | mvm->restart_fw--; |
| 890 | ieee80211_restart_hw(mvm->hw); | 914 | ieee80211_restart_hw(mvm->hw); |
| 891 | } else if (fw_error) { | ||
| 892 | schedule_work(&mvm->fw_error_dump_wk); | ||
| 893 | } | 915 | } |
| 894 | } | 916 | } |
| 895 | 917 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index 540c36bae268..5b43616eeb06 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
| @@ -170,7 +170,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | |||
| 170 | active_cnt = 2; | 170 | active_cnt = 2; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant << | 173 | cmd->rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) << |
| 174 | PHY_RX_CHAIN_VALID_POS); | 174 | PHY_RX_CHAIN_VALID_POS); |
| 175 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); | 175 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); |
| 176 | cmd->rxchain_info |= cpu_to_le32(active_cnt << | 176 | cmd->rxchain_info |= cpu_to_le32(active_cnt << |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 7ba6e5dbbbd0..194bd1f939ca 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include "sta.h" | 39 | #include "sta.h" |
| 40 | #include "iwl-op-mode.h" | 40 | #include "iwl-op-mode.h" |
| 41 | #include "mvm.h" | 41 | #include "mvm.h" |
| 42 | #include "debugfs.h" | ||
| 42 | 43 | ||
| 43 | #define RS_NAME "iwl-mvm-rs" | 44 | #define RS_NAME "iwl-mvm-rs" |
| 44 | 45 | ||
| @@ -917,7 +918,6 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, | |||
| 917 | break; | 918 | break; |
| 918 | if (rate_mask & (1 << low)) | 919 | if (rate_mask & (1 << low)) |
| 919 | break; | 920 | break; |
| 920 | IWL_DEBUG_RATE(mvm, "Skipping masked lower rate: %d\n", low); | ||
| 921 | } | 921 | } |
| 922 | 922 | ||
| 923 | high = index; | 923 | high = index; |
| @@ -927,7 +927,6 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, | |||
| 927 | break; | 927 | break; |
| 928 | if (rate_mask & (1 << high)) | 928 | if (rate_mask & (1 << high)) |
| 929 | break; | 929 | break; |
| 930 | IWL_DEBUG_RATE(mvm, "Skipping masked higher rate: %d\n", high); | ||
| 931 | } | 930 | } |
| 932 | 931 | ||
| 933 | return (high << 8) | low; | 932 | return (high << 8) | low; |
| @@ -1804,18 +1803,10 @@ out: | |||
| 1804 | static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | 1803 | static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
| 1805 | struct iwl_lq_sta *lq_sta) | 1804 | struct iwl_lq_sta *lq_sta) |
| 1806 | { | 1805 | { |
| 1807 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
| 1808 | struct ieee80211_vif *vif = mvmsta->vif; | ||
| 1809 | bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION && | ||
| 1810 | !vif->bss_conf.ps); | ||
| 1811 | |||
| 1812 | /* Our chip supports Tx STBC and the peer is an HT/VHT STA which | 1806 | /* Our chip supports Tx STBC and the peer is an HT/VHT STA which |
| 1813 | * supports STBC of at least 1*SS | 1807 | * supports STBC of at least 1*SS |
| 1814 | */ | 1808 | */ |
| 1815 | if (!lq_sta->stbc) | 1809 | if (!lq_sta->stbc_capable) |
| 1816 | return false; | ||
| 1817 | |||
| 1818 | if (!mvm->ps_disabled && !sta_ps_disabled) | ||
| 1819 | return false; | 1810 | return false; |
| 1820 | 1811 | ||
| 1821 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) | 1812 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) |
| @@ -2610,68 +2601,121 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, | |||
| 2610 | } | 2601 | } |
| 2611 | } | 2602 | } |
| 2612 | 2603 | ||
| 2604 | static void rs_ht_init(struct iwl_mvm *mvm, | ||
| 2605 | struct ieee80211_sta *sta, | ||
| 2606 | struct iwl_lq_sta *lq_sta, | ||
| 2607 | struct ieee80211_sta_ht_cap *ht_cap) | ||
| 2608 | { | ||
| 2609 | /* active_siso_rate mask includes 9 MBits (bit 5), | ||
| 2610 | * and CCK (bits 0-3), supp_rates[] does not; | ||
| 2611 | * shift to convert format, force 9 MBits off. | ||
| 2612 | */ | ||
| 2613 | lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; | ||
| 2614 | lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; | ||
| 2615 | lq_sta->active_siso_rate &= ~((u16)0x2); | ||
| 2616 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2617 | |||
| 2618 | lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; | ||
| 2619 | lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; | ||
| 2620 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | ||
| 2621 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2622 | |||
| 2623 | if (mvm->cfg->ht_params->ldpc && | ||
| 2624 | (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) | ||
| 2625 | lq_sta->ldpc = true; | ||
| 2626 | |||
| 2627 | if (mvm->cfg->ht_params->stbc && | ||
| 2628 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | ||
| 2629 | (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) | ||
| 2630 | lq_sta->stbc_capable = true; | ||
| 2631 | |||
| 2632 | lq_sta->is_vht = false; | ||
| 2633 | } | ||
| 2634 | |||
| 2635 | static void rs_vht_init(struct iwl_mvm *mvm, | ||
| 2636 | struct ieee80211_sta *sta, | ||
| 2637 | struct iwl_lq_sta *lq_sta, | ||
| 2638 | struct ieee80211_sta_vht_cap *vht_cap) | ||
| 2639 | { | ||
| 2640 | rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); | ||
| 2641 | |||
| 2642 | if (mvm->cfg->ht_params->ldpc && | ||
| 2643 | (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)) | ||
| 2644 | lq_sta->ldpc = true; | ||
| 2645 | |||
| 2646 | if (mvm->cfg->ht_params->stbc && | ||
| 2647 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | ||
| 2648 | (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)) | ||
| 2649 | lq_sta->stbc_capable = true; | ||
| 2650 | |||
| 2651 | if ((mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BEAMFORMER) && | ||
| 2652 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | ||
| 2653 | (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) | ||
| 2654 | lq_sta->bfer_capable = true; | ||
| 2655 | |||
| 2656 | lq_sta->is_vht = true; | ||
| 2657 | } | ||
| 2658 | |||
| 2613 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 2659 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 2614 | static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm, | 2660 | static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm) |
| 2615 | struct iwl_mvm_frame_stats *stats) | ||
| 2616 | { | 2661 | { |
| 2617 | spin_lock_bh(&mvm->drv_stats_lock); | 2662 | spin_lock_bh(&mvm->drv_stats_lock); |
| 2618 | memset(stats, 0, sizeof(*stats)); | 2663 | memset(&mvm->drv_rx_stats, 0, sizeof(mvm->drv_rx_stats)); |
| 2619 | spin_unlock_bh(&mvm->drv_stats_lock); | 2664 | spin_unlock_bh(&mvm->drv_stats_lock); |
| 2620 | } | 2665 | } |
| 2621 | 2666 | ||
| 2622 | void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, | 2667 | void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg) |
| 2623 | struct iwl_mvm_frame_stats *stats, | ||
| 2624 | u32 rate, bool agg) | ||
| 2625 | { | 2668 | { |
| 2626 | u8 nss = 0, mcs = 0; | 2669 | u8 nss = 0, mcs = 0; |
| 2627 | 2670 | ||
| 2628 | spin_lock(&mvm->drv_stats_lock); | 2671 | spin_lock(&mvm->drv_stats_lock); |
| 2629 | 2672 | ||
| 2630 | if (agg) | 2673 | if (agg) |
| 2631 | stats->agg_frames++; | 2674 | mvm->drv_rx_stats.agg_frames++; |
| 2632 | 2675 | ||
| 2633 | stats->success_frames++; | 2676 | mvm->drv_rx_stats.success_frames++; |
| 2634 | 2677 | ||
| 2635 | switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { | 2678 | switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { |
| 2636 | case RATE_MCS_CHAN_WIDTH_20: | 2679 | case RATE_MCS_CHAN_WIDTH_20: |
| 2637 | stats->bw_20_frames++; | 2680 | mvm->drv_rx_stats.bw_20_frames++; |
| 2638 | break; | 2681 | break; |
| 2639 | case RATE_MCS_CHAN_WIDTH_40: | 2682 | case RATE_MCS_CHAN_WIDTH_40: |
| 2640 | stats->bw_40_frames++; | 2683 | mvm->drv_rx_stats.bw_40_frames++; |
| 2641 | break; | 2684 | break; |
| 2642 | case RATE_MCS_CHAN_WIDTH_80: | 2685 | case RATE_MCS_CHAN_WIDTH_80: |
| 2643 | stats->bw_80_frames++; | 2686 | mvm->drv_rx_stats.bw_80_frames++; |
| 2644 | break; | 2687 | break; |
| 2645 | default: | 2688 | default: |
| 2646 | WARN_ONCE(1, "bad BW. rate 0x%x", rate); | 2689 | WARN_ONCE(1, "bad BW. rate 0x%x", rate); |
| 2647 | } | 2690 | } |
| 2648 | 2691 | ||
| 2649 | if (rate & RATE_MCS_HT_MSK) { | 2692 | if (rate & RATE_MCS_HT_MSK) { |
| 2650 | stats->ht_frames++; | 2693 | mvm->drv_rx_stats.ht_frames++; |
| 2651 | mcs = rate & RATE_HT_MCS_RATE_CODE_MSK; | 2694 | mcs = rate & RATE_HT_MCS_RATE_CODE_MSK; |
| 2652 | nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; | 2695 | nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; |
| 2653 | } else if (rate & RATE_MCS_VHT_MSK) { | 2696 | } else if (rate & RATE_MCS_VHT_MSK) { |
| 2654 | stats->vht_frames++; | 2697 | mvm->drv_rx_stats.vht_frames++; |
| 2655 | mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; | 2698 | mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; |
| 2656 | nss = ((rate & RATE_VHT_MCS_NSS_MSK) >> | 2699 | nss = ((rate & RATE_VHT_MCS_NSS_MSK) >> |
| 2657 | RATE_VHT_MCS_NSS_POS) + 1; | 2700 | RATE_VHT_MCS_NSS_POS) + 1; |
| 2658 | } else { | 2701 | } else { |
| 2659 | stats->legacy_frames++; | 2702 | mvm->drv_rx_stats.legacy_frames++; |
| 2660 | } | 2703 | } |
| 2661 | 2704 | ||
| 2662 | if (nss == 1) | 2705 | if (nss == 1) |
| 2663 | stats->siso_frames++; | 2706 | mvm->drv_rx_stats.siso_frames++; |
| 2664 | else if (nss == 2) | 2707 | else if (nss == 2) |
| 2665 | stats->mimo2_frames++; | 2708 | mvm->drv_rx_stats.mimo2_frames++; |
| 2666 | 2709 | ||
| 2667 | if (rate & RATE_MCS_SGI_MSK) | 2710 | if (rate & RATE_MCS_SGI_MSK) |
| 2668 | stats->sgi_frames++; | 2711 | mvm->drv_rx_stats.sgi_frames++; |
| 2669 | else | 2712 | else |
| 2670 | stats->ngi_frames++; | 2713 | mvm->drv_rx_stats.ngi_frames++; |
| 2671 | 2714 | ||
| 2672 | stats->last_rates[stats->last_frame_idx] = rate; | 2715 | mvm->drv_rx_stats.last_rates[mvm->drv_rx_stats.last_frame_idx] = rate; |
| 2673 | stats->last_frame_idx = (stats->last_frame_idx + 1) % | 2716 | mvm->drv_rx_stats.last_frame_idx = |
| 2674 | ARRAY_SIZE(stats->last_rates); | 2717 | (mvm->drv_rx_stats.last_frame_idx + 1) % |
| 2718 | ARRAY_SIZE(mvm->drv_rx_stats.last_rates); | ||
| 2675 | 2719 | ||
| 2676 | spin_unlock(&mvm->drv_stats_lock); | 2720 | spin_unlock(&mvm->drv_stats_lock); |
| 2677 | } | 2721 | } |
| @@ -2724,46 +2768,12 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2724 | lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); | 2768 | lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); |
| 2725 | 2769 | ||
| 2726 | /* TODO: should probably account for rx_highest for both HT/VHT */ | 2770 | /* TODO: should probably account for rx_highest for both HT/VHT */ |
| 2727 | if (!vht_cap || !vht_cap->vht_supported) { | 2771 | if (!vht_cap || !vht_cap->vht_supported) |
| 2728 | /* active_siso_rate mask includes 9 MBits (bit 5), | 2772 | rs_ht_init(mvm, sta, lq_sta, ht_cap); |
| 2729 | * and CCK (bits 0-3), supp_rates[] does not; | 2773 | else |
| 2730 | * shift to convert format, force 9 MBits off. | 2774 | rs_vht_init(mvm, sta, lq_sta, vht_cap); |
| 2731 | */ | ||
| 2732 | lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; | ||
| 2733 | lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; | ||
| 2734 | lq_sta->active_siso_rate &= ~((u16)0x2); | ||
| 2735 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2736 | |||
| 2737 | /* Same here */ | ||
| 2738 | lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; | ||
| 2739 | lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; | ||
| 2740 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | ||
| 2741 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2742 | |||
| 2743 | lq_sta->is_vht = false; | ||
| 2744 | if (mvm->cfg->ht_params->ldpc && | ||
| 2745 | (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) | ||
| 2746 | lq_sta->ldpc = true; | ||
| 2747 | |||
| 2748 | if (mvm->cfg->ht_params->stbc && | ||
| 2749 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | ||
| 2750 | (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) | ||
| 2751 | lq_sta->stbc = true; | ||
| 2752 | } else { | ||
| 2753 | rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); | ||
| 2754 | lq_sta->is_vht = true; | ||
| 2755 | |||
| 2756 | if (mvm->cfg->ht_params->ldpc && | ||
| 2757 | (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)) | ||
| 2758 | lq_sta->ldpc = true; | ||
| 2759 | |||
| 2760 | if (mvm->cfg->ht_params->stbc && | ||
| 2761 | (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1) && | ||
| 2762 | (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)) | ||
| 2763 | lq_sta->stbc = true; | ||
| 2764 | } | ||
| 2765 | 2775 | ||
| 2766 | if (IWL_MVM_RS_DISABLE_MIMO) | 2776 | if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p) |
| 2767 | lq_sta->active_mimo2_rate = 0; | 2777 | lq_sta->active_mimo2_rate = 0; |
| 2768 | 2778 | ||
| 2769 | lq_sta->max_legacy_rate_idx = | 2779 | lq_sta->max_legacy_rate_idx = |
| @@ -2774,11 +2784,12 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2774 | rs_get_max_rate_from_mask(lq_sta->active_mimo2_rate); | 2784 | rs_get_max_rate_from_mask(lq_sta->active_mimo2_rate); |
| 2775 | 2785 | ||
| 2776 | IWL_DEBUG_RATE(mvm, | 2786 | IWL_DEBUG_RATE(mvm, |
| 2777 | "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n", | 2787 | "LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC=%d BFER=%d\n", |
| 2778 | lq_sta->active_legacy_rate, | 2788 | lq_sta->active_legacy_rate, |
| 2779 | lq_sta->active_siso_rate, | 2789 | lq_sta->active_siso_rate, |
| 2780 | lq_sta->active_mimo2_rate, | 2790 | lq_sta->active_mimo2_rate, |
| 2781 | lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc); | 2791 | lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc_capable, |
| 2792 | lq_sta->bfer_capable); | ||
| 2782 | IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", | 2793 | IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", |
| 2783 | lq_sta->max_legacy_rate_idx, | 2794 | lq_sta->max_legacy_rate_idx, |
| 2784 | lq_sta->max_siso_rate_idx, | 2795 | lq_sta->max_siso_rate_idx, |
| @@ -2793,7 +2804,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2793 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; | 2804 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; |
| 2794 | lq_sta->is_agg = 0; | 2805 | lq_sta->is_agg = 0; |
| 2795 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 2806 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 2796 | iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats); | 2807 | iwl_mvm_reset_frame_stats(mvm); |
| 2797 | #endif | 2808 | #endif |
| 2798 | rs_initialize_lq(mvm, sta, lq_sta, band, init); | 2809 | rs_initialize_lq(mvm, sta, lq_sta, band, init); |
| 2799 | } | 2810 | } |
| @@ -2862,12 +2873,13 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm, | |||
| 2862 | int index = *rs_table_index; | 2873 | int index = *rs_table_index; |
| 2863 | 2874 | ||
| 2864 | for (i = 0; i < num_rates && index < end; i++) { | 2875 | for (i = 0; i < num_rates && index < end; i++) { |
| 2865 | ucode_rate = cpu_to_le32(ucode_rate_from_rs_rate(mvm, rate)); | 2876 | for (j = 0; j < num_retries && index < end; j++, index++) { |
| 2866 | for (j = 0; j < num_retries && index < end; j++, index++) | 2877 | ucode_rate = cpu_to_le32(ucode_rate_from_rs_rate(mvm, |
| 2878 | rate)); | ||
| 2867 | rs_table[index] = ucode_rate; | 2879 | rs_table[index] = ucode_rate; |
| 2868 | 2880 | if (toggle_ant) | |
| 2869 | if (toggle_ant) | 2881 | rs_toggle_antenna(valid_tx_ant, rate); |
| 2870 | rs_toggle_antenna(valid_tx_ant, rate); | 2882 | } |
| 2871 | 2883 | ||
| 2872 | prev_rate_idx = rate->index; | 2884 | prev_rate_idx = rate->index; |
| 2873 | bottom_reached = rs_get_lower_rate_in_column(lq_sta, rate); | 2885 | bottom_reached = rs_get_lower_rate_in_column(lq_sta, rate); |
| @@ -2875,7 +2887,7 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm, | |||
| 2875 | break; | 2887 | break; |
| 2876 | } | 2888 | } |
| 2877 | 2889 | ||
| 2878 | if (!bottom_reached) | 2890 | if (!bottom_reached && !is_legacy(rate)) |
| 2879 | rate->index = prev_rate_idx; | 2891 | rate->index = prev_rate_idx; |
| 2880 | 2892 | ||
| 2881 | *rs_table_index = index; | 2893 | *rs_table_index = index; |
| @@ -2915,7 +2927,11 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
| 2915 | memcpy(&rate, initial_rate, sizeof(rate)); | 2927 | memcpy(&rate, initial_rate, sizeof(rate)); |
| 2916 | 2928 | ||
| 2917 | valid_tx_ant = iwl_mvm_get_valid_tx_ant(mvm); | 2929 | valid_tx_ant = iwl_mvm_get_valid_tx_ant(mvm); |
| 2918 | rate.stbc = rs_stbc_allow(mvm, sta, lq_sta); | 2930 | |
| 2931 | /* TODO: remove old API when min FW API hits 14 */ | ||
| 2932 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS) && | ||
| 2933 | rs_stbc_allow(mvm, sta, lq_sta)) | ||
| 2934 | rate.stbc = true; | ||
| 2919 | 2935 | ||
| 2920 | if (is_siso(&rate)) { | 2936 | if (is_siso(&rate)) { |
| 2921 | num_rates = IWL_MVM_RS_INITIAL_SISO_NUM_RATES; | 2937 | num_rates = IWL_MVM_RS_INITIAL_SISO_NUM_RATES; |
| @@ -2925,7 +2941,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
| 2925 | num_retries = IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE; | 2941 | num_retries = IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE; |
| 2926 | } else { | 2942 | } else { |
| 2927 | num_rates = IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES; | 2943 | num_rates = IWL_MVM_RS_INITIAL_LEGACY_NUM_RATES; |
| 2928 | num_retries = IWL_MVM_RS_LEGACY_RETRIES_PER_RATE; | 2944 | num_retries = IWL_MVM_RS_INITIAL_LEGACY_RETRIES; |
| 2929 | toggle_ant = true; | 2945 | toggle_ant = true; |
| 2930 | } | 2946 | } |
| 2931 | 2947 | ||
| @@ -2941,7 +2957,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
| 2941 | lq_cmd->mimo_delim = index; | 2957 | lq_cmd->mimo_delim = index; |
| 2942 | } else if (is_legacy(&rate)) { | 2958 | } else if (is_legacy(&rate)) { |
| 2943 | num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES; | 2959 | num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES; |
| 2944 | num_retries = IWL_MVM_RS_LEGACY_RETRIES_PER_RATE; | 2960 | num_retries = IWL_MVM_RS_SECONDARY_LEGACY_RETRIES; |
| 2945 | } else { | 2961 | } else { |
| 2946 | WARN_ON_ONCE(1); | 2962 | WARN_ON_ONCE(1); |
| 2947 | } | 2963 | } |
| @@ -2955,7 +2971,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
| 2955 | rs_get_lower_rate_down_column(lq_sta, &rate); | 2971 | rs_get_lower_rate_down_column(lq_sta, &rate); |
| 2956 | 2972 | ||
| 2957 | num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES; | 2973 | num_rates = IWL_MVM_RS_SECONDARY_LEGACY_NUM_RATES; |
| 2958 | num_retries = IWL_MVM_RS_LEGACY_RETRIES_PER_RATE; | 2974 | num_retries = IWL_MVM_RS_SECONDARY_LEGACY_RETRIES; |
| 2959 | 2975 | ||
| 2960 | rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index, | 2976 | rs_fill_rates_for_column(mvm, lq_sta, &rate, lq_cmd->rs_table, &index, |
| 2961 | num_rates, num_retries, valid_tx_ant, | 2977 | num_rates, num_retries, valid_tx_ant, |
| @@ -2963,6 +2979,142 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
| 2963 | 2979 | ||
| 2964 | } | 2980 | } |
| 2965 | 2981 | ||
| 2982 | struct rs_bfer_active_iter_data { | ||
| 2983 | struct ieee80211_sta *exclude_sta; | ||
| 2984 | struct iwl_mvm_sta *bfer_mvmsta; | ||
| 2985 | }; | ||
| 2986 | |||
| 2987 | static void rs_bfer_active_iter(void *_data, | ||
| 2988 | struct ieee80211_sta *sta) | ||
| 2989 | { | ||
| 2990 | struct rs_bfer_active_iter_data *data = _data; | ||
| 2991 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
| 2992 | struct iwl_lq_cmd *lq_cmd = &mvmsta->lq_sta.lq; | ||
| 2993 | u32 ss_params = le32_to_cpu(lq_cmd->ss_params); | ||
| 2994 | |||
| 2995 | if (sta == data->exclude_sta) | ||
| 2996 | return; | ||
| 2997 | |||
| 2998 | /* The current sta has BFER allowed */ | ||
| 2999 | if (ss_params & LQ_SS_BFER_ALLOWED) { | ||
| 3000 | WARN_ON_ONCE(data->bfer_mvmsta != NULL); | ||
| 3001 | |||
| 3002 | data->bfer_mvmsta = mvmsta; | ||
| 3003 | } | ||
| 3004 | } | ||
| 3005 | |||
| 3006 | static int rs_bfer_priority(struct iwl_mvm_sta *sta) | ||
| 3007 | { | ||
| 3008 | int prio = -1; | ||
| 3009 | enum nl80211_iftype viftype = ieee80211_vif_type_p2p(sta->vif); | ||
| 3010 | |||
| 3011 | switch (viftype) { | ||
| 3012 | case NL80211_IFTYPE_AP: | ||
| 3013 | case NL80211_IFTYPE_P2P_GO: | ||
| 3014 | prio = 3; | ||
| 3015 | break; | ||
| 3016 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 3017 | prio = 2; | ||
| 3018 | break; | ||
| 3019 | case NL80211_IFTYPE_STATION: | ||
| 3020 | prio = 1; | ||
| 3021 | break; | ||
| 3022 | default: | ||
| 3023 | WARN_ONCE(true, "viftype %d sta_id %d", viftype, sta->sta_id); | ||
| 3024 | prio = -1; | ||
| 3025 | } | ||
| 3026 | |||
| 3027 | return prio; | ||
| 3028 | } | ||
| 3029 | |||
| 3030 | /* Returns >0 if sta1 has a higher BFER priority compared to sta2 */ | ||
| 3031 | static int rs_bfer_priority_cmp(struct iwl_mvm_sta *sta1, | ||
| 3032 | struct iwl_mvm_sta *sta2) | ||
| 3033 | { | ||
| 3034 | int prio1 = rs_bfer_priority(sta1); | ||
| 3035 | int prio2 = rs_bfer_priority(sta2); | ||
| 3036 | |||
| 3037 | if (prio1 > prio2) | ||
| 3038 | return 1; | ||
| 3039 | if (prio1 < prio2) | ||
| 3040 | return -1; | ||
| 3041 | return 0; | ||
| 3042 | } | ||
| 3043 | |||
| 3044 | static void rs_set_lq_ss_params(struct iwl_mvm *mvm, | ||
| 3045 | struct ieee80211_sta *sta, | ||
| 3046 | struct iwl_lq_sta *lq_sta, | ||
| 3047 | const struct rs_rate *initial_rate) | ||
| 3048 | { | ||
| 3049 | struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; | ||
| 3050 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
| 3051 | struct rs_bfer_active_iter_data data = { | ||
| 3052 | .exclude_sta = sta, | ||
| 3053 | .bfer_mvmsta = NULL, | ||
| 3054 | }; | ||
| 3055 | struct iwl_mvm_sta *bfer_mvmsta = NULL; | ||
| 3056 | u32 ss_params = LQ_SS_PARAMS_VALID; | ||
| 3057 | |||
| 3058 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) | ||
| 3059 | goto out; | ||
| 3060 | |||
| 3061 | /* Check if forcing the decision is configured. | ||
| 3062 | * Note that SISO is forced by not allowing STBC or BFER | ||
| 3063 | */ | ||
| 3064 | if (lq_sta->ss_force == RS_SS_FORCE_STBC) | ||
| 3065 | ss_params |= (LQ_SS_STBC_1SS_ALLOWED | LQ_SS_FORCE); | ||
| 3066 | else if (lq_sta->ss_force == RS_SS_FORCE_BFER) | ||
| 3067 | ss_params |= (LQ_SS_BFER_ALLOWED | LQ_SS_FORCE); | ||
| 3068 | |||
| 3069 | if (lq_sta->ss_force != RS_SS_FORCE_NONE) { | ||
| 3070 | IWL_DEBUG_RATE(mvm, "Forcing single stream Tx decision %d\n", | ||
| 3071 | lq_sta->ss_force); | ||
| 3072 | goto out; | ||
| 3073 | } | ||
| 3074 | |||
| 3075 | if (lq_sta->stbc_capable) | ||
| 3076 | ss_params |= LQ_SS_STBC_1SS_ALLOWED; | ||
| 3077 | |||
| 3078 | if (!lq_sta->bfer_capable) | ||
| 3079 | goto out; | ||
| 3080 | |||
| 3081 | ieee80211_iterate_stations_atomic(mvm->hw, | ||
| 3082 | rs_bfer_active_iter, | ||
| 3083 | &data); | ||
| 3084 | bfer_mvmsta = data.bfer_mvmsta; | ||
| 3085 | |||
| 3086 | /* This code is safe as it doesn't run concurrently for different | ||
| 3087 | * stations. This is guaranteed by the fact that calls to | ||
| 3088 | * ieee80211_tx_status wouldn't run concurrently for a single HW. | ||
| 3089 | */ | ||
| 3090 | if (!bfer_mvmsta) { | ||
| 3091 | IWL_DEBUG_RATE(mvm, "No sta with BFER allowed found. Allow\n"); | ||
| 3092 | |||
| 3093 | ss_params |= LQ_SS_BFER_ALLOWED; | ||
| 3094 | goto out; | ||
| 3095 | } | ||
| 3096 | |||
| 3097 | IWL_DEBUG_RATE(mvm, "Found existing sta %d with BFER activated\n", | ||
| 3098 | bfer_mvmsta->sta_id); | ||
| 3099 | |||
| 3100 | /* Disallow BFER on another STA if active and we're a higher priority */ | ||
| 3101 | if (rs_bfer_priority_cmp(mvmsta, bfer_mvmsta) > 0) { | ||
| 3102 | struct iwl_lq_cmd *bfersta_lq_cmd = &bfer_mvmsta->lq_sta.lq; | ||
| 3103 | u32 bfersta_ss_params = le32_to_cpu(bfersta_lq_cmd->ss_params); | ||
| 3104 | |||
| 3105 | bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED; | ||
| 3106 | bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params); | ||
| 3107 | iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd, false); | ||
| 3108 | |||
| 3109 | ss_params |= LQ_SS_BFER_ALLOWED; | ||
| 3110 | IWL_DEBUG_RATE(mvm, | ||
| 3111 | "Lower priority BFER sta found (%d). Switch BFER\n", | ||
| 3112 | bfer_mvmsta->sta_id); | ||
| 3113 | } | ||
| 3114 | out: | ||
| 3115 | lq_cmd->ss_params = cpu_to_le32(ss_params); | ||
| 3116 | } | ||
| 3117 | |||
| 2966 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | 3118 | static void rs_fill_lq_cmd(struct iwl_mvm *mvm, |
| 2967 | struct ieee80211_sta *sta, | 3119 | struct ieee80211_sta *sta, |
| 2968 | struct iwl_lq_sta *lq_sta, | 3120 | struct iwl_lq_sta *lq_sta, |
| @@ -2989,6 +3141,9 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | |||
| 2989 | 3141 | ||
| 2990 | rs_build_rates_table(mvm, sta, lq_sta, initial_rate); | 3142 | rs_build_rates_table(mvm, sta, lq_sta, initial_rate); |
| 2991 | 3143 | ||
| 3144 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS) | ||
| 3145 | rs_set_lq_ss_params(mvm, sta, lq_sta, initial_rate); | ||
| 3146 | |||
| 2992 | if (num_of_ant(initial_rate->ant) == 1) | 3147 | if (num_of_ant(initial_rate->ant) == 1) |
| 2993 | lq_cmd->single_stream_ant_msk = initial_rate->ant; | 3148 | lq_cmd->single_stream_ant_msk = initial_rate->ant; |
| 2994 | 3149 | ||
| @@ -3362,9 +3517,73 @@ static const struct file_operations rs_sta_dbgfs_drv_tx_stats_ops = { | |||
| 3362 | .llseek = default_llseek, | 3517 | .llseek = default_llseek, |
| 3363 | }; | 3518 | }; |
| 3364 | 3519 | ||
| 3520 | static ssize_t iwl_dbgfs_ss_force_read(struct file *file, | ||
| 3521 | char __user *user_buf, | ||
| 3522 | size_t count, loff_t *ppos) | ||
| 3523 | { | ||
| 3524 | struct iwl_lq_sta *lq_sta = file->private_data; | ||
| 3525 | char buf[12]; | ||
| 3526 | int bufsz = sizeof(buf); | ||
| 3527 | int pos = 0; | ||
| 3528 | static const char * const ss_force_name[] = { | ||
| 3529 | [RS_SS_FORCE_NONE] = "none", | ||
| 3530 | [RS_SS_FORCE_STBC] = "stbc", | ||
| 3531 | [RS_SS_FORCE_BFER] = "bfer", | ||
| 3532 | [RS_SS_FORCE_SISO] = "siso", | ||
| 3533 | }; | ||
| 3534 | |||
| 3535 | pos += scnprintf(buf+pos, bufsz-pos, "%s\n", | ||
| 3536 | ss_force_name[lq_sta->ss_force]); | ||
| 3537 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
| 3538 | } | ||
| 3539 | |||
| 3540 | static ssize_t iwl_dbgfs_ss_force_write(struct iwl_lq_sta *lq_sta, char *buf, | ||
| 3541 | size_t count, loff_t *ppos) | ||
| 3542 | { | ||
| 3543 | struct iwl_mvm *mvm = lq_sta->pers.drv; | ||
| 3544 | int ret = 0; | ||
| 3545 | |||
| 3546 | if (!strncmp("none", buf, 4)) { | ||
| 3547 | lq_sta->ss_force = RS_SS_FORCE_NONE; | ||
| 3548 | } else if (!strncmp("siso", buf, 4)) { | ||
| 3549 | lq_sta->ss_force = RS_SS_FORCE_SISO; | ||
| 3550 | } else if (!strncmp("stbc", buf, 4)) { | ||
| 3551 | if (lq_sta->stbc_capable) { | ||
| 3552 | lq_sta->ss_force = RS_SS_FORCE_STBC; | ||
| 3553 | } else { | ||
| 3554 | IWL_ERR(mvm, | ||
| 3555 | "can't force STBC. peer doesn't support\n"); | ||
| 3556 | ret = -EINVAL; | ||
| 3557 | } | ||
| 3558 | } else if (!strncmp("bfer", buf, 4)) { | ||
| 3559 | if (lq_sta->bfer_capable) { | ||
| 3560 | lq_sta->ss_force = RS_SS_FORCE_BFER; | ||
| 3561 | } else { | ||
| 3562 | IWL_ERR(mvm, | ||
| 3563 | "can't force BFER. peer doesn't support\n"); | ||
| 3564 | ret = -EINVAL; | ||
| 3565 | } | ||
| 3566 | } else { | ||
| 3567 | IWL_ERR(mvm, "valid values none|siso|stbc|bfer\n"); | ||
| 3568 | ret = -EINVAL; | ||
| 3569 | } | ||
| 3570 | return ret ?: count; | ||
| 3571 | } | ||
| 3572 | |||
| 3573 | #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ | ||
| 3574 | _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_lq_sta) | ||
| 3575 | #define MVM_DEBUGFS_ADD_FILE_RS(name, parent, mode) do { \ | ||
| 3576 | if (!debugfs_create_file(#name, mode, parent, lq_sta, \ | ||
| 3577 | &iwl_dbgfs_##name##_ops)) \ | ||
| 3578 | goto err; \ | ||
| 3579 | } while (0) | ||
| 3580 | |||
| 3581 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32); | ||
| 3582 | |||
| 3365 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | 3583 | static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) |
| 3366 | { | 3584 | { |
| 3367 | struct iwl_lq_sta *lq_sta = mvm_sta; | 3585 | struct iwl_lq_sta *lq_sta = mvm_sta; |
| 3586 | |||
| 3368 | debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, | 3587 | debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, |
| 3369 | lq_sta, &rs_sta_dbgfs_scale_table_ops); | 3588 | lq_sta, &rs_sta_dbgfs_scale_table_ops); |
| 3370 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, | 3589 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, |
| @@ -3375,6 +3594,11 @@ static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) | |||
| 3375 | &lq_sta->tx_agg_tid_en); | 3594 | &lq_sta->tx_agg_tid_en); |
| 3376 | debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir, | 3595 | debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir, |
| 3377 | &lq_sta->pers.dbg_fixed_txp_reduction); | 3596 | &lq_sta->pers.dbg_fixed_txp_reduction); |
| 3597 | |||
| 3598 | MVM_DEBUGFS_ADD_FILE_RS(ss_force, dir, S_IRUSR | S_IWUSR); | ||
| 3599 | return; | ||
| 3600 | err: | ||
| 3601 | IWL_ERR((struct iwl_mvm *)mvm, "Can't create debugfs entity\n"); | ||
| 3378 | } | 3602 | } |
| 3379 | 3603 | ||
| 3380 | static void rs_remove_debugfs(void *mvm, void *mvm_sta) | 3604 | static void rs_remove_debugfs(void *mvm, void *mvm_sta) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index f8f5bf21cc38..dc4ef3dfafe1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
| @@ -240,6 +240,13 @@ enum rs_column { | |||
| 240 | RS_COLUMN_INVALID, | 240 | RS_COLUMN_INVALID, |
| 241 | }; | 241 | }; |
| 242 | 242 | ||
| 243 | enum rs_ss_force_opt { | ||
| 244 | RS_SS_FORCE_NONE = 0, | ||
| 245 | RS_SS_FORCE_STBC, | ||
| 246 | RS_SS_FORCE_BFER, | ||
| 247 | RS_SS_FORCE_SISO, | ||
| 248 | }; | ||
| 249 | |||
| 243 | /* Packet stats per rate */ | 250 | /* Packet stats per rate */ |
| 244 | struct rs_rate_stats { | 251 | struct rs_rate_stats { |
| 245 | u64 success; | 252 | u64 success; |
| @@ -293,7 +300,9 @@ struct iwl_lq_sta { | |||
| 293 | u64 last_tx; | 300 | u64 last_tx; |
| 294 | bool is_vht; | 301 | bool is_vht; |
| 295 | bool ldpc; /* LDPC Rx is supported by the STA */ | 302 | bool ldpc; /* LDPC Rx is supported by the STA */ |
| 296 | bool stbc; /* Tx STBC is supported by chip and Rx by STA */ | 303 | bool stbc_capable; /* Tx STBC is supported by chip and Rx by STA */ |
| 304 | bool bfer_capable; /* Remote supports beamformee and we BFer */ | ||
| 305 | |||
| 297 | enum ieee80211_band band; | 306 | enum ieee80211_band band; |
| 298 | 307 | ||
| 299 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 308 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
| @@ -322,6 +331,9 @@ struct iwl_lq_sta { | |||
| 322 | /* tx power reduce for this sta */ | 331 | /* tx power reduce for this sta */ |
| 323 | int tpc_reduce; | 332 | int tpc_reduce; |
| 324 | 333 | ||
| 334 | /* force STBC/BFER/SISO for testing */ | ||
| 335 | enum rs_ss_force_opt ss_force; | ||
| 336 | |||
| 325 | /* persistent fields - initialized only once - keep last! */ | 337 | /* persistent fields - initialized only once - keep last! */ |
| 326 | struct lq_sta_pers { | 338 | struct lq_sta_pers { |
| 327 | #ifdef CONFIG_MAC80211_DEBUGFS | 339 | #ifdef CONFIG_MAC80211_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 94b6e7297a1e..f922131b4eab 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
| @@ -407,7 +407,7 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 409 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 410 | iwl_mvm_update_frame_stats(mvm, &mvm->drv_rx_stats, rate_n_flags, | 410 | iwl_mvm_update_frame_stats(mvm, rate_n_flags, |
| 411 | rx_status->flag & RX_FLAG_AMPDU_DETAILS); | 411 | rx_status->flag & RX_FLAG_AMPDU_DETAILS); |
| 412 | #endif | 412 | #endif |
| 413 | iwl_mvm_pass_packet_to_mac80211(mvm, skb, hdr, len, ampdu_status, | 413 | iwl_mvm_pass_packet_to_mac80211(mvm, skb, hdr, len, ampdu_status, |
| @@ -511,13 +511,17 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | |||
| 511 | { | 511 | { |
| 512 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 512 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
| 513 | struct iwl_notif_statistics *stats = (void *)&pkt->data; | 513 | struct iwl_notif_statistics *stats = (void *)&pkt->data; |
| 514 | struct mvm_statistics_general_common *common = &stats->general.common; | ||
| 515 | struct iwl_mvm_stat_data data = { | 514 | struct iwl_mvm_stat_data data = { |
| 516 | .stats = stats, | 515 | .stats = stats, |
| 517 | .mvm = mvm, | 516 | .mvm = mvm, |
| 518 | }; | 517 | }; |
| 519 | 518 | ||
| 520 | iwl_mvm_tt_temp_changed(mvm, le32_to_cpu(common->temperature)); | 519 | /* Only handle rx statistics temperature changes if async temp |
| 520 | * notifications are not supported | ||
| 521 | */ | ||
| 522 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_ASYNC_DTM)) | ||
| 523 | iwl_mvm_tt_temp_changed(mvm, | ||
| 524 | le32_to_cpu(stats->general.radio_temperature)); | ||
| 521 | 525 | ||
| 522 | iwl_mvm_update_rx_statistics(mvm, stats); | 526 | iwl_mvm_update_rx_statistics(mvm, stats); |
| 523 | 527 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 348b9c4b694a..7e9aa3cb3254 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
| @@ -173,15 +173,21 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_ssid_ie *cmd_ssid, | |||
| 173 | * already included in the probe template, so we need to set only | 173 | * already included in the probe template, so we need to set only |
| 174 | * req->n_ssids - 1 bits in addition to the first bit. | 174 | * req->n_ssids - 1 bits in addition to the first bit. |
| 175 | */ | 175 | */ |
| 176 | static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) | 176 | static u16 iwl_mvm_get_active_dwell(struct iwl_mvm *mvm, |
| 177 | enum ieee80211_band band, int n_ssids) | ||
| 177 | { | 178 | { |
| 179 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL) | ||
| 180 | return 10; | ||
| 178 | if (band == IEEE80211_BAND_2GHZ) | 181 | if (band == IEEE80211_BAND_2GHZ) |
| 179 | return 20 + 3 * (n_ssids + 1); | 182 | return 20 + 3 * (n_ssids + 1); |
| 180 | return 10 + 2 * (n_ssids + 1); | 183 | return 10 + 2 * (n_ssids + 1); |
| 181 | } | 184 | } |
| 182 | 185 | ||
| 183 | static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band) | 186 | static u16 iwl_mvm_get_passive_dwell(struct iwl_mvm *mvm, |
| 187 | enum ieee80211_band band) | ||
| 184 | { | 188 | { |
| 189 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BASIC_DWELL) | ||
| 190 | return 110; | ||
| 185 | return band == IEEE80211_BAND_2GHZ ? 100 + 20 : 100 + 10; | 191 | return band == IEEE80211_BAND_2GHZ ? 100 + 20 : 100 + 10; |
| 186 | } | 192 | } |
| 187 | 193 | ||
| @@ -309,18 +315,18 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | |||
| 309 | goto not_bound; | 315 | goto not_bound; |
| 310 | 316 | ||
| 311 | params->suspend_time = 30; | 317 | params->suspend_time = 30; |
| 312 | params->max_out_time = 170; | 318 | params->max_out_time = 120; |
| 313 | 319 | ||
| 314 | if (iwl_mvm_low_latency(mvm)) { | 320 | if (iwl_mvm_low_latency(mvm)) { |
| 315 | if (mvm->fw->ucode_capa.api[0] & | 321 | if (mvm->fw->ucode_capa.api[0] & |
| 316 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN) { | 322 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN) { |
| 317 | params->suspend_time = 105; | 323 | params->suspend_time = 105; |
| 318 | params->max_out_time = 70; | ||
| 319 | /* | 324 | /* |
| 320 | * If there is more than one active interface make | 325 | * If there is more than one active interface make |
| 321 | * passive scan more fragmented. | 326 | * passive scan more fragmented. |
| 322 | */ | 327 | */ |
| 323 | frag_passive_dwell = (global_cnt < 2) ? 40 : 20; | 328 | frag_passive_dwell = (global_cnt < 2) ? 40 : 20; |
| 329 | params->max_out_time = frag_passive_dwell; | ||
| 324 | } else { | 330 | } else { |
| 325 | params->suspend_time = 120; | 331 | params->suspend_time = 120; |
| 326 | params->max_out_time = 120; | 332 | params->max_out_time = 120; |
| @@ -337,7 +343,8 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | |||
| 337 | */ | 343 | */ |
| 338 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { | 344 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { |
| 339 | u32 passive_dwell = | 345 | u32 passive_dwell = |
| 340 | iwl_mvm_get_passive_dwell(IEEE80211_BAND_2GHZ); | 346 | iwl_mvm_get_passive_dwell(mvm, |
| 347 | IEEE80211_BAND_2GHZ); | ||
| 341 | params->max_out_time = passive_dwell; | 348 | params->max_out_time = passive_dwell; |
| 342 | } else { | 349 | } else { |
| 343 | params->passive_fragmented = true; | 350 | params->passive_fragmented = true; |
| @@ -354,8 +361,8 @@ not_bound: | |||
| 354 | params->dwell[band].passive = frag_passive_dwell; | 361 | params->dwell[band].passive = frag_passive_dwell; |
| 355 | else | 362 | else |
| 356 | params->dwell[band].passive = | 363 | params->dwell[band].passive = |
| 357 | iwl_mvm_get_passive_dwell(band); | 364 | iwl_mvm_get_passive_dwell(mvm, band); |
| 358 | params->dwell[band].active = iwl_mvm_get_active_dwell(band, | 365 | params->dwell[band].active = iwl_mvm_get_active_dwell(mvm, band, |
| 359 | n_ssids); | 366 | n_ssids); |
| 360 | } | 367 | } |
| 361 | } | 368 | } |
| @@ -536,6 +543,19 @@ int iwl_mvm_rx_scan_response(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 536 | return 0; | 543 | return 0; |
| 537 | } | 544 | } |
| 538 | 545 | ||
| 546 | int iwl_mvm_rx_scan_offload_iter_complete_notif(struct iwl_mvm *mvm, | ||
| 547 | struct iwl_rx_cmd_buffer *rxb, | ||
| 548 | struct iwl_device_cmd *cmd) | ||
| 549 | { | ||
| 550 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 551 | struct iwl_scan_complete_notif *notif = (void *)pkt->data; | ||
| 552 | |||
| 553 | IWL_DEBUG_SCAN(mvm, | ||
| 554 | "Scan offload iteration complete: status=0x%x scanned channels=%d\n", | ||
| 555 | notif->status, notif->scanned_channels); | ||
| 556 | return 0; | ||
| 557 | } | ||
| 558 | |||
| 539 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | 559 | int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, |
| 540 | struct iwl_device_cmd *cmd) | 560 | struct iwl_device_cmd *cmd) |
| 541 | { | 561 | { |
| @@ -684,7 +704,8 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | |||
| 684 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 704 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
| 685 | } | 705 | } |
| 686 | 706 | ||
| 687 | mvm->last_ebs_successful = !ebs_status; | 707 | if (ebs_status) |
| 708 | mvm->last_ebs_successful = false; | ||
| 688 | 709 | ||
| 689 | return 0; | 710 | return 0; |
| 690 | } | 711 | } |
| @@ -1104,6 +1125,12 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify) | |||
| 1104 | return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN, | 1125 | return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN, |
| 1105 | notify); | 1126 | notify); |
| 1106 | 1127 | ||
| 1128 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) | ||
| 1129 | return 0; | ||
| 1130 | |||
| 1131 | if (iwl_mvm_is_radio_killed(mvm)) | ||
| 1132 | goto out; | ||
| 1133 | |||
| 1107 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED && | 1134 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED && |
| 1108 | (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) || | 1135 | (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) || |
| 1109 | mvm->scan_status != IWL_MVM_SCAN_OS)) { | 1136 | mvm->scan_status != IWL_MVM_SCAN_OS)) { |
| @@ -1140,6 +1167,7 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify) | |||
| 1140 | if (mvm->scan_status == IWL_MVM_SCAN_OS) | 1167 | if (mvm->scan_status == IWL_MVM_SCAN_OS) |
| 1141 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1168 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); |
| 1142 | 1169 | ||
| 1170 | out: | ||
| 1143 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 1171 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
| 1144 | 1172 | ||
| 1145 | if (notify) { | 1173 | if (notify) { |
| @@ -1296,22 +1324,6 @@ iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm, | |||
| 1296 | cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH); | 1324 | cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH); |
| 1297 | cmd->iter_num = cpu_to_le32(1); | 1325 | cmd->iter_num = cpu_to_le32(1); |
| 1298 | 1326 | ||
| 1299 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT && | ||
| 1300 | mvm->last_ebs_successful) { | ||
| 1301 | cmd->channel_opt[0].flags = | ||
| 1302 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1303 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1304 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1305 | cmd->channel_opt[0].non_ebs_ratio = | ||
| 1306 | cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO); | ||
| 1307 | cmd->channel_opt[1].flags = | ||
| 1308 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1309 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1310 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1311 | cmd->channel_opt[1].non_ebs_ratio = | ||
| 1312 | cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | if (iwl_mvm_rrm_scan_needed(mvm)) | 1327 | if (iwl_mvm_rrm_scan_needed(mvm)) |
| 1316 | cmd->scan_flags |= | 1328 | cmd->scan_flags |= |
| 1317 | cpu_to_le32(IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED); | 1329 | cpu_to_le32(IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED); |
| @@ -1386,6 +1398,22 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm, | |||
| 1386 | cmd->schedule[1].iterations = 0; | 1398 | cmd->schedule[1].iterations = 0; |
| 1387 | cmd->schedule[1].full_scan_mul = 0; | 1399 | cmd->schedule[1].full_scan_mul = 0; |
| 1388 | 1400 | ||
| 1401 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SINGLE_SCAN_EBS && | ||
| 1402 | mvm->last_ebs_successful) { | ||
| 1403 | cmd->channel_opt[0].flags = | ||
| 1404 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1405 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1406 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1407 | cmd->channel_opt[0].non_ebs_ratio = | ||
| 1408 | cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO); | ||
| 1409 | cmd->channel_opt[1].flags = | ||
| 1410 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1411 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1412 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1413 | cmd->channel_opt[1].non_ebs_ratio = | ||
| 1414 | cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO); | ||
| 1415 | } | ||
| 1416 | |||
| 1389 | for (i = 1; i <= req->req.n_ssids; i++) | 1417 | for (i = 1; i <= req->req.n_ssids; i++) |
| 1390 | ssid_bitmap |= BIT(i); | 1418 | ssid_bitmap |= BIT(i); |
| 1391 | 1419 | ||
| @@ -1458,6 +1486,8 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, | |||
| 1458 | 1486 | ||
| 1459 | if (iwl_mvm_scan_pass_all(mvm, req)) | 1487 | if (iwl_mvm_scan_pass_all(mvm, req)) |
| 1460 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL; | 1488 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL; |
| 1489 | else | ||
| 1490 | flags |= IWL_MVM_LMAC_SCAN_FLAG_MATCH; | ||
| 1461 | 1491 | ||
| 1462 | if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0) | 1492 | if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0) |
| 1463 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; | 1493 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; |
| @@ -1468,6 +1498,11 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, | |||
| 1468 | if (req->n_ssids == 0) | 1498 | if (req->n_ssids == 0) |
| 1469 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE; | 1499 | flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE; |
| 1470 | 1500 | ||
| 1501 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 1502 | if (mvm->scan_iter_notif_enabled) | ||
| 1503 | flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE; | ||
| 1504 | #endif | ||
| 1505 | |||
| 1471 | cmd->scan_flags |= cpu_to_le32(flags); | 1506 | cmd->scan_flags |= cpu_to_le32(flags); |
| 1472 | 1507 | ||
| 1473 | cmd->flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band); | 1508 | cmd->flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band); |
| @@ -1484,6 +1519,22 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, | |||
| 1484 | cmd->schedule[1].iterations = 0xff; | 1519 | cmd->schedule[1].iterations = 0xff; |
| 1485 | cmd->schedule[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER; | 1520 | cmd->schedule[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER; |
| 1486 | 1521 | ||
| 1522 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT && | ||
| 1523 | mvm->last_ebs_successful) { | ||
| 1524 | cmd->channel_opt[0].flags = | ||
| 1525 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1526 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1527 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1528 | cmd->channel_opt[0].non_ebs_ratio = | ||
| 1529 | cpu_to_le16(IWL_DENSE_EBS_SCAN_RATIO); | ||
| 1530 | cmd->channel_opt[1].flags = | ||
| 1531 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1532 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1533 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD); | ||
| 1534 | cmd->channel_opt[1].non_ebs_ratio = | ||
| 1535 | cpu_to_le16(IWL_SPARSE_EBS_SCAN_RATIO); | ||
| 1536 | } | ||
| 1537 | |||
| 1487 | iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels, | 1538 | iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels, |
| 1488 | ssid_bitmap, cmd); | 1539 | ssid_bitmap, cmd); |
| 1489 | 1540 | ||
| @@ -1632,10 +1683,10 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) | |||
| 1632 | 1683 | ||
| 1633 | band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; | 1684 | band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ]; |
| 1634 | for (i = 0; i < band->n_channels; i++, j++) | 1685 | for (i = 0; i < band->n_channels; i++, j++) |
| 1635 | scan_config->channel_array[j] = band->channels[i].center_freq; | 1686 | scan_config->channel_array[j] = band->channels[i].hw_value; |
| 1636 | band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; | 1687 | band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ]; |
| 1637 | for (i = 0; i < band->n_channels; i++, j++) | 1688 | for (i = 0; i < band->n_channels; i++, j++) |
| 1638 | scan_config->channel_array[j] = band->channels[i].center_freq; | 1689 | scan_config->channel_array[j] = band->channels[i].hw_value; |
| 1639 | 1690 | ||
| 1640 | cmd.data[0] = scan_config; | 1691 | cmd.data[0] = scan_config; |
| 1641 | cmd.len[0] = cmd_size; | 1692 | cmd.len[0] = cmd_size; |
| @@ -1812,6 +1863,13 @@ int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 1812 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL; | 1863 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL; |
| 1813 | 1864 | ||
| 1814 | cmd->general_flags = cpu_to_le32(flags); | 1865 | cmd->general_flags = cpu_to_le32(flags); |
| 1866 | |||
| 1867 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SINGLE_SCAN_EBS && | ||
| 1868 | mvm->last_ebs_successful) | ||
| 1869 | cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | | ||
| 1870 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | ||
| 1871 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; | ||
| 1872 | |||
| 1815 | cmd->n_channels = req->req.n_channels; | 1873 | cmd->n_channels = req->req.n_channels; |
| 1816 | 1874 | ||
| 1817 | for (i = 0; i < req->req.n_ssids; i++) | 1875 | for (i = 0; i < req->req.n_ssids; i++) |
| @@ -1975,7 +2033,9 @@ int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, | |||
| 1975 | notif->ebs_status == IWL_SCAN_EBS_SUCCESS ? | 2033 | notif->ebs_status == IWL_SCAN_EBS_SUCCESS ? |
| 1976 | "success" : "failed"); | 2034 | "success" : "failed"); |
| 1977 | 2035 | ||
| 1978 | mvm->last_ebs_successful = !notif->ebs_status; | 2036 | if (notif->ebs_status) |
| 2037 | mvm->last_ebs_successful = false; | ||
| 2038 | |||
| 1979 | mvm->scan_uid[uid_idx] = 0; | 2039 | mvm->scan_uid[uid_idx] = 0; |
| 1980 | 2040 | ||
| 1981 | if (!sched) { | 2041 | if (!sched) { |
| @@ -2008,10 +2068,14 @@ static bool iwl_scan_umac_done_check(struct iwl_notif_wait_data *notif_wait, | |||
| 2008 | 2068 | ||
| 2009 | /* | 2069 | /* |
| 2010 | * Clear scan uid of scans that was aborted from above and completed | 2070 | * Clear scan uid of scans that was aborted from above and completed |
| 2011 | * in FW so the RX handler does nothing. | 2071 | * in FW so the RX handler does nothing. Set last_ebs_successful here if |
| 2072 | * needed. | ||
| 2012 | */ | 2073 | */ |
| 2013 | scan_done->mvm->scan_uid[uid_idx] = 0; | 2074 | scan_done->mvm->scan_uid[uid_idx] = 0; |
| 2014 | 2075 | ||
| 2076 | if (notif->ebs_status) | ||
| 2077 | scan_done->mvm->last_ebs_successful = false; | ||
| 2078 | |||
| 2015 | return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type); | 2079 | return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type); |
| 2016 | } | 2080 | } |
| 2017 | 2081 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index ad327984b099..5c23cddaaae3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
| @@ -209,6 +209,9 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, | |||
| 209 | { | 209 | { |
| 210 | unsigned long used_hw_queues; | 210 | unsigned long used_hw_queues; |
| 211 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 211 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
| 212 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
| 213 | mvm->cfg->base_params->wd_timeout : | ||
| 214 | IWL_WATCHDOG_DISABLED; | ||
| 212 | u32 ac; | 215 | u32 ac; |
| 213 | 216 | ||
| 214 | lockdep_assert_held(&mvm->mutex); | 217 | lockdep_assert_held(&mvm->mutex); |
| @@ -232,7 +235,7 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, | |||
| 232 | /* Found a place for all queues - enable them */ | 235 | /* Found a place for all queues - enable them */ |
| 233 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 236 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 234 | iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], | 237 | iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], |
| 235 | iwl_mvm_ac_to_tx_fifo[ac]); | 238 | iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout); |
| 236 | mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); | 239 | mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); |
| 237 | } | 240 | } |
| 238 | 241 | ||
| @@ -250,8 +253,8 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm, | |||
| 250 | 253 | ||
| 251 | /* disable the TDLS STA-specific queues */ | 254 | /* disable the TDLS STA-specific queues */ |
| 252 | sta_msk = mvmsta->tfd_queue_msk; | 255 | sta_msk = mvmsta->tfd_queue_msk; |
| 253 | for_each_set_bit(i, &sta_msk, sizeof(sta_msk)) | 256 | for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) |
| 254 | iwl_mvm_disable_txq(mvm, i); | 257 | iwl_mvm_disable_txq(mvm, i, 0); |
| 255 | } | 258 | } |
| 256 | 259 | ||
| 257 | int iwl_mvm_add_sta(struct iwl_mvm *mvm, | 260 | int iwl_mvm_add_sta(struct iwl_mvm *mvm, |
| @@ -464,8 +467,8 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) | |||
| 464 | if (mvm->tfd_drained[sta_id]) { | 467 | if (mvm->tfd_drained[sta_id]) { |
| 465 | unsigned long i, msk = mvm->tfd_drained[sta_id]; | 468 | unsigned long i, msk = mvm->tfd_drained[sta_id]; |
| 466 | 469 | ||
| 467 | for_each_set_bit(i, &msk, sizeof(msk)) | 470 | for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) |
| 468 | iwl_mvm_disable_txq(mvm, i); | 471 | iwl_mvm_disable_txq(mvm, i, 0); |
| 469 | 472 | ||
| 470 | mvm->tfd_drained[sta_id] = 0; | 473 | mvm->tfd_drained[sta_id] = 0; |
| 471 | IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", | 474 | IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", |
| @@ -626,13 +629,16 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
| 626 | 629 | ||
| 627 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) | 630 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) |
| 628 | { | 631 | { |
| 632 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
| 633 | mvm->cfg->base_params->wd_timeout : | ||
| 634 | IWL_WATCHDOG_DISABLED; | ||
| 629 | int ret; | 635 | int ret; |
| 630 | 636 | ||
| 631 | lockdep_assert_held(&mvm->mutex); | 637 | lockdep_assert_held(&mvm->mutex); |
| 632 | 638 | ||
| 633 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ | 639 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ |
| 634 | iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, | 640 | iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, |
| 635 | IWL_MVM_TX_FIFO_MCAST); | 641 | IWL_MVM_TX_FIFO_MCAST, wdg_timeout); |
| 636 | 642 | ||
| 637 | /* Allocate aux station and assign to it the aux queue */ | 643 | /* Allocate aux station and assign to it the aux queue */ |
| 638 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), | 644 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), |
| @@ -965,6 +971,9 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 965 | { | 971 | { |
| 966 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 972 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
| 967 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | 973 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; |
| 974 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
| 975 | mvm->cfg->base_params->wd_timeout : | ||
| 976 | IWL_WATCHDOG_DISABLED; | ||
| 968 | int queue, fifo, ret; | 977 | int queue, fifo, ret; |
| 969 | u16 ssn; | 978 | u16 ssn; |
| 970 | 979 | ||
| @@ -988,7 +997,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 988 | return -EIO; | 997 | return -EIO; |
| 989 | 998 | ||
| 990 | iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid, | 999 | iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid, |
| 991 | buf_size, ssn); | 1000 | buf_size, ssn, wdg_timeout); |
| 992 | 1001 | ||
| 993 | /* | 1002 | /* |
| 994 | * Even though in theory the peer could have different | 1003 | * Even though in theory the peer could have different |
| @@ -1058,7 +1067,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 1058 | 1067 | ||
| 1059 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); | 1068 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); |
| 1060 | 1069 | ||
| 1061 | iwl_mvm_disable_txq(mvm, txq_id); | 1070 | iwl_mvm_disable_txq(mvm, txq_id, 0); |
| 1062 | return 0; | 1071 | return 0; |
| 1063 | case IWL_AGG_STARTING: | 1072 | case IWL_AGG_STARTING: |
| 1064 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 1073 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
| @@ -1116,7 +1125,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 1116 | 1125 | ||
| 1117 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); | 1126 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); |
| 1118 | 1127 | ||
| 1119 | iwl_mvm_disable_txq(mvm, tid_data->txq_id); | 1128 | iwl_mvm_disable_txq(mvm, tid_data->txq_id, 0); |
| 1120 | } | 1129 | } |
| 1121 | 1130 | ||
| 1122 | mvm->queue_to_mac80211[tid_data->txq_id] = | 1131 | mvm->queue_to_mac80211[tid_data->txq_id] = |
| @@ -1196,6 +1205,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 1196 | break; | 1205 | break; |
| 1197 | case WLAN_CIPHER_SUITE_WEP104: | 1206 | case WLAN_CIPHER_SUITE_WEP104: |
| 1198 | key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_13BYTES); | 1207 | key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_13BYTES); |
| 1208 | /* fall through */ | ||
| 1199 | case WLAN_CIPHER_SUITE_WEP40: | 1209 | case WLAN_CIPHER_SUITE_WEP40: |
| 1200 | key_flags |= cpu_to_le16(STA_KEY_FLG_WEP); | 1210 | key_flags |= cpu_to_le16(STA_KEY_FLG_WEP); |
| 1201 | memcpy(cmd.key + 3, keyconf->key, keyconf->keylen); | 1211 | memcpy(cmd.key + 3, keyconf->key, keyconf->keylen); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tdls.c b/drivers/net/wireless/iwlwifi/mvm/tdls.c index c0e00bae5bd0..a87b506c8c72 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tdls.c +++ b/drivers/net/wireless/iwlwifi/mvm/tdls.c | |||
| @@ -64,6 +64,8 @@ | |||
| 64 | #include <linux/etherdevice.h> | 64 | #include <linux/etherdevice.h> |
| 65 | #include "mvm.h" | 65 | #include "mvm.h" |
| 66 | #include "time-event.h" | 66 | #include "time-event.h" |
| 67 | #include "iwl-io.h" | ||
| 68 | #include "iwl-prph.h" | ||
| 67 | 69 | ||
| 68 | #define TU_TO_US(x) (x * 1024) | 70 | #define TU_TO_US(x) (x * 1024) |
| 69 | #define TU_TO_MS(x) (TU_TO_US(x) / 1000) | 71 | #define TU_TO_MS(x) (TU_TO_US(x) / 1000) |
| @@ -228,6 +230,8 @@ iwl_mvm_tdls_cs_state_str(enum iwl_mvm_tdls_cs_state state) | |||
| 228 | return "IDLE"; | 230 | return "IDLE"; |
| 229 | case IWL_MVM_TDLS_SW_REQ_SENT: | 231 | case IWL_MVM_TDLS_SW_REQ_SENT: |
| 230 | return "REQ SENT"; | 232 | return "REQ SENT"; |
| 233 | case IWL_MVM_TDLS_SW_RESP_RCVD: | ||
| 234 | return "RESP RECEIVED"; | ||
| 231 | case IWL_MVM_TDLS_SW_REQ_RCVD: | 235 | case IWL_MVM_TDLS_SW_REQ_RCVD: |
| 232 | return "REQ RECEIVED"; | 236 | return "REQ RECEIVED"; |
| 233 | case IWL_MVM_TDLS_SW_ACTIVE: | 237 | case IWL_MVM_TDLS_SW_ACTIVE: |
| @@ -248,6 +252,11 @@ static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm, | |||
| 248 | iwl_mvm_tdls_cs_state_str(state)); | 252 | iwl_mvm_tdls_cs_state_str(state)); |
| 249 | mvm->tdls_cs.state = state; | 253 | mvm->tdls_cs.state = state; |
| 250 | 254 | ||
| 255 | /* we only send requests to our switching peer - update sent time */ | ||
| 256 | if (state == IWL_MVM_TDLS_SW_REQ_SENT) | ||
| 257 | mvm->tdls_cs.peer.sent_timestamp = | ||
| 258 | iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); | ||
| 259 | |||
| 251 | if (state == IWL_MVM_TDLS_SW_IDLE) | 260 | if (state == IWL_MVM_TDLS_SW_IDLE) |
| 252 | mvm->tdls_cs.cur_sta_id = IWL_MVM_STATION_COUNT; | 261 | mvm->tdls_cs.cur_sta_id = IWL_MVM_STATION_COUNT; |
| 253 | } | 262 | } |
| @@ -300,7 +309,7 @@ out: | |||
| 300 | static int | 309 | static int |
| 301 | iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, | 310 | iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, |
| 302 | enum iwl_tdls_channel_switch_type type, | 311 | enum iwl_tdls_channel_switch_type type, |
| 303 | const u8 *peer, bool peer_initiator) | 312 | const u8 *peer, bool peer_initiator, u32 timestamp) |
| 304 | { | 313 | { |
| 305 | bool same_peer = false; | 314 | bool same_peer = false; |
| 306 | int ret = 0; | 315 | int ret = 0; |
| @@ -325,17 +334,30 @@ iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, | |||
| 325 | ret = -EINVAL; | 334 | ret = -EINVAL; |
| 326 | break; | 335 | break; |
| 327 | case IWL_MVM_TDLS_SW_REQ_SENT: | 336 | case IWL_MVM_TDLS_SW_REQ_SENT: |
| 337 | /* only allow requests from the same peer */ | ||
| 338 | if (!same_peer) | ||
| 339 | ret = -EBUSY; | ||
| 340 | else if (type == TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH && | ||
| 341 | !peer_initiator) | ||
| 342 | /* | ||
| 343 | * We received a ch-switch request while an outgoing | ||
| 344 | * one is pending. Allow it if the peer is the link | ||
| 345 | * initiator. | ||
| 346 | */ | ||
| 347 | ret = -EBUSY; | ||
| 348 | else if (type == TDLS_SEND_CHAN_SW_REQ) | ||
| 349 | /* wait for idle before sending another request */ | ||
| 350 | ret = -EBUSY; | ||
| 351 | else if (timestamp <= mvm->tdls_cs.peer.sent_timestamp) | ||
| 352 | /* we got a stale response - ignore it */ | ||
| 353 | ret = -EINVAL; | ||
| 354 | break; | ||
| 355 | case IWL_MVM_TDLS_SW_RESP_RCVD: | ||
| 328 | /* | 356 | /* |
| 329 | * We received a ch-switch request while an outgoing one is | 357 | * we are waiting for the FW to give an "active" notification, |
| 330 | * pending. Allow it to proceed if the other peer is the same | 358 | * so ignore requests in the meantime |
| 331 | * one we sent to, and we are not the link initiator. | ||
| 332 | */ | 359 | */ |
| 333 | if (type == TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH) { | 360 | ret = -EBUSY; |
| 334 | if (!same_peer) | ||
| 335 | ret = -EBUSY; | ||
| 336 | else if (!peer_initiator) /* we are the initiator */ | ||
| 337 | ret = -EBUSY; | ||
| 338 | } | ||
| 339 | break; | 361 | break; |
| 340 | case IWL_MVM_TDLS_SW_REQ_RCVD: | 362 | case IWL_MVM_TDLS_SW_REQ_RCVD: |
| 341 | /* as above, allow the link initiator to proceed */ | 363 | /* as above, allow the link initiator to proceed */ |
| @@ -349,9 +371,12 @@ iwl_mvm_tdls_check_action(struct iwl_mvm *mvm, | |||
| 349 | } | 371 | } |
| 350 | break; | 372 | break; |
| 351 | case IWL_MVM_TDLS_SW_ACTIVE: | 373 | case IWL_MVM_TDLS_SW_ACTIVE: |
| 352 | /* we don't allow initiations during active channel switch */ | 374 | /* |
| 353 | if (type == TDLS_SEND_CHAN_SW_REQ) | 375 | * the only valid request when active is a request to return |
| 354 | ret = -EINVAL; | 376 | * to the base channel by the current off-channel peer |
| 377 | */ | ||
| 378 | if (type != TDLS_MOVE_CH || !same_peer) | ||
| 379 | ret = -EBUSY; | ||
| 355 | break; | 380 | break; |
| 356 | } | 381 | } |
| 357 | 382 | ||
| @@ -384,7 +409,8 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, | |||
| 384 | 409 | ||
| 385 | lockdep_assert_held(&mvm->mutex); | 410 | lockdep_assert_held(&mvm->mutex); |
| 386 | 411 | ||
| 387 | ret = iwl_mvm_tdls_check_action(mvm, type, peer, peer_initiator); | 412 | ret = iwl_mvm_tdls_check_action(mvm, type, peer, peer_initiator, |
| 413 | timestamp); | ||
| 388 | if (ret) | 414 | if (ret) |
| 389 | return ret; | 415 | return ret; |
| 390 | 416 | ||
| @@ -473,6 +499,8 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, | |||
| 473 | type == TDLS_SEND_CHAN_SW_REQ ? | 499 | type == TDLS_SEND_CHAN_SW_REQ ? |
| 474 | IWL_MVM_TDLS_SW_REQ_SENT : | 500 | IWL_MVM_TDLS_SW_REQ_SENT : |
| 475 | IWL_MVM_TDLS_SW_REQ_RCVD); | 501 | IWL_MVM_TDLS_SW_REQ_RCVD); |
| 502 | } else { | ||
| 503 | iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_RESP_RCVD); | ||
| 476 | } | 504 | } |
| 477 | 505 | ||
| 478 | out: | 506 | out: |
| @@ -657,12 +685,15 @@ iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw, | |||
| 657 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 685 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 658 | enum iwl_tdls_channel_switch_type type; | 686 | enum iwl_tdls_channel_switch_type type; |
| 659 | unsigned int delay; | 687 | unsigned int delay; |
| 688 | const char *action_str = | ||
| 689 | params->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ? | ||
| 690 | "REQ" : "RESP"; | ||
| 660 | 691 | ||
| 661 | mutex_lock(&mvm->mutex); | 692 | mutex_lock(&mvm->mutex); |
| 662 | 693 | ||
| 663 | IWL_DEBUG_TDLS(mvm, | 694 | IWL_DEBUG_TDLS(mvm, |
| 664 | "Received TDLS ch switch action %d from %pM status %d\n", | 695 | "Received TDLS ch switch action %s from %pM status %d\n", |
| 665 | params->action_code, params->sta->addr, params->status); | 696 | action_str, params->sta->addr, params->status); |
| 666 | 697 | ||
| 667 | /* | 698 | /* |
| 668 | * we got a non-zero status from a peer we were switching to - move to | 699 | * we got a non-zero status from a peer we were switching to - move to |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index d6cdb770881a..07304e1fd64a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
| @@ -90,8 +90,6 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 90 | 90 | ||
| 91 | if (ieee80211_is_probe_resp(fc)) | 91 | if (ieee80211_is_probe_resp(fc)) |
| 92 | tx_flags |= TX_CMD_FLG_TSF; | 92 | tx_flags |= TX_CMD_FLG_TSF; |
| 93 | else if (ieee80211_is_back_req(fc)) | ||
| 94 | tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR; | ||
| 95 | 93 | ||
| 96 | if (ieee80211_has_morefrags(fc)) | 94 | if (ieee80211_has_morefrags(fc)) |
| 97 | tx_flags |= TX_CMD_FLG_MORE_FRAG; | 95 | tx_flags |= TX_CMD_FLG_MORE_FRAG; |
| @@ -100,6 +98,15 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 100 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 98 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
| 101 | tx_cmd->tid_tspec = qc[0] & 0xf; | 99 | tx_cmd->tid_tspec = qc[0] & 0xf; |
| 102 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL; | 100 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL; |
| 101 | } else if (ieee80211_is_back_req(fc)) { | ||
| 102 | struct ieee80211_bar *bar = (void *)skb->data; | ||
| 103 | u16 control = le16_to_cpu(bar->control); | ||
| 104 | |||
| 105 | tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR; | ||
| 106 | tx_cmd->tid_tspec = (control & | ||
| 107 | IEEE80211_BAR_CTRL_TID_INFO_MASK) >> | ||
| 108 | IEEE80211_BAR_CTRL_TID_INFO_SHIFT; | ||
| 109 | WARN_ON_ONCE(tx_cmd->tid_tspec >= IWL_MAX_TID_COUNT); | ||
| 103 | } else { | 110 | } else { |
| 104 | tx_cmd->tid_tspec = IWL_TID_NON_QOS; | 111 | tx_cmd->tid_tspec = IWL_TID_NON_QOS; |
| 105 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) | 112 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) |
| @@ -108,8 +115,12 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 108 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL; | 115 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL; |
| 109 | } | 116 | } |
| 110 | 117 | ||
| 111 | /* tid_tspec will default to 0 = BE when QOS isn't enabled */ | 118 | /* Default to 0 (BE) when tid_spec is set to IWL_TID_NON_QOS */ |
| 112 | ac = tid_to_mac80211_ac[tx_cmd->tid_tspec]; | 119 | if (tx_cmd->tid_tspec < IWL_MAX_TID_COUNT) |
| 120 | ac = tid_to_mac80211_ac[tx_cmd->tid_tspec]; | ||
| 121 | else | ||
| 122 | ac = tid_to_mac80211_ac[0]; | ||
| 123 | |||
| 113 | tx_flags |= iwl_mvm_bt_coex_tx_prio(mvm, hdr, info, ac) << | 124 | tx_flags |= iwl_mvm_bt_coex_tx_prio(mvm, hdr, info, ac) << |
| 114 | TX_CMD_FLG_BT_PRIO_POS; | 125 | TX_CMD_FLG_BT_PRIO_POS; |
| 115 | 126 | ||
| @@ -496,7 +507,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, | |||
| 496 | IWL_DEBUG_TX_QUEUES(mvm, | 507 | IWL_DEBUG_TX_QUEUES(mvm, |
| 497 | "Can continue DELBA flow ssn = next_recl = %d\n", | 508 | "Can continue DELBA flow ssn = next_recl = %d\n", |
| 498 | tid_data->next_reclaimed); | 509 | tid_data->next_reclaimed); |
| 499 | iwl_mvm_disable_txq(mvm, tid_data->txq_id); | 510 | iwl_mvm_disable_txq(mvm, tid_data->txq_id, CMD_ASYNC); |
| 500 | tid_data->state = IWL_AGG_OFF; | 511 | tid_data->state = IWL_AGG_OFF; |
| 501 | /* | 512 | /* |
| 502 | * we can't hold the mutex - but since we are after a sequence | 513 | * we can't hold the mutex - but since we are after a sequence |
| @@ -656,7 +667,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 656 | 667 | ||
| 657 | /* Single frame failure in an AMPDU queue => send BAR */ | 668 | /* Single frame failure in an AMPDU queue => send BAR */ |
| 658 | if (txq_id >= mvm->first_agg_queue && | 669 | if (txq_id >= mvm->first_agg_queue && |
| 659 | !(info->flags & IEEE80211_TX_STAT_ACK)) | 670 | !(info->flags & IEEE80211_TX_STAT_ACK) && |
| 671 | !(info->flags & IEEE80211_TX_STAT_TX_FILTERED)) | ||
| 660 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 672 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
| 661 | 673 | ||
| 662 | /* W/A FW bug: seq_ctl is wrong when the status isn't success */ | 674 | /* W/A FW bug: seq_ctl is wrong when the status isn't success */ |
| @@ -919,6 +931,11 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 919 | sta_id = ba_notif->sta_id; | 931 | sta_id = ba_notif->sta_id; |
| 920 | tid = ba_notif->tid; | 932 | tid = ba_notif->tid; |
| 921 | 933 | ||
| 934 | if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT || | ||
| 935 | tid >= IWL_MAX_TID_COUNT, | ||
| 936 | "sta_id %d tid %d", sta_id, tid)) | ||
| 937 | return 0; | ||
| 938 | |||
| 922 | rcu_read_lock(); | 939 | rcu_read_lock(); |
| 923 | 940 | ||
| 924 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | 941 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index f0a114102c3f..8decf9953229 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
| @@ -432,7 +432,7 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) | |||
| 432 | mvm->status, table.valid); | 432 | mvm->status, table.valid); |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | IWL_ERR(mvm, "0x%08X | %-28s\n", table.error_id, | 435 | IWL_ERR(mvm, "0x%08X | %s\n", table.error_id, |
| 436 | desc_lookup(table.error_id)); | 436 | desc_lookup(table.error_id)); |
| 437 | IWL_ERR(mvm, "0x%08X | umac branchlink1\n", table.blink1); | 437 | IWL_ERR(mvm, "0x%08X | umac branchlink1\n", table.blink1); |
| 438 | IWL_ERR(mvm, "0x%08X | umac branchlink2\n", table.blink2); | 438 | IWL_ERR(mvm, "0x%08X | umac branchlink2\n", table.blink2); |
| @@ -531,49 +531,50 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
| 531 | } | 531 | } |
| 532 | 532 | ||
| 533 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | 533 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, |
| 534 | const struct iwl_trans_txq_scd_cfg *cfg) | 534 | const struct iwl_trans_txq_scd_cfg *cfg, |
| 535 | unsigned int wdg_timeout) | ||
| 535 | { | 536 | { |
| 536 | if (iwl_mvm_is_dqa_supported(mvm)) { | 537 | struct iwl_scd_txq_cfg_cmd cmd = { |
| 537 | struct iwl_scd_txq_cfg_cmd cmd = { | 538 | .scd_queue = queue, |
| 538 | .scd_queue = queue, | 539 | .enable = 1, |
| 539 | .enable = 1, | 540 | .window = cfg->frame_limit, |
| 540 | .window = cfg->frame_limit, | 541 | .sta_id = cfg->sta_id, |
| 541 | .sta_id = cfg->sta_id, | 542 | .ssn = cpu_to_le16(ssn), |
| 542 | .ssn = cpu_to_le16(ssn), | 543 | .tx_fifo = cfg->fifo, |
| 543 | .tx_fifo = cfg->fifo, | 544 | .aggregate = cfg->aggregate, |
| 544 | .aggregate = cfg->aggregate, | 545 | .tid = cfg->tid, |
| 545 | .flags = IWL_SCD_FLAGS_DQA_ENABLED, | 546 | }; |
| 546 | .tid = cfg->tid, | 547 | |
| 547 | .control = IWL_SCD_CONTROL_SET_SSN, | 548 | if (!iwl_mvm_is_scd_cfg_supported(mvm)) { |
| 548 | }; | 549 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, cfg, |
| 549 | int ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, | 550 | wdg_timeout); |
| 550 | sizeof(cmd), &cmd); | 551 | return; |
| 551 | if (ret) | ||
| 552 | IWL_ERR(mvm, | ||
| 553 | "Failed to configure queue %d on FIFO %d\n", | ||
| 554 | queue, cfg->fifo); | ||
| 555 | } | 552 | } |
| 556 | 553 | ||
| 557 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, | 554 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout); |
| 558 | iwl_mvm_is_dqa_supported(mvm) ? NULL : cfg); | 555 | WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), |
| 556 | "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); | ||
| 559 | } | 557 | } |
| 560 | 558 | ||
| 561 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue) | 559 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags) |
| 562 | { | 560 | { |
| 563 | iwl_trans_txq_disable(mvm->trans, queue, | 561 | struct iwl_scd_txq_cfg_cmd cmd = { |
| 564 | !iwl_mvm_is_dqa_supported(mvm)); | 562 | .scd_queue = queue, |
| 565 | 563 | .enable = 0, | |
| 566 | if (iwl_mvm_is_dqa_supported(mvm)) { | 564 | }; |
| 567 | struct iwl_scd_txq_cfg_cmd cmd = { | 565 | int ret; |
| 568 | .scd_queue = queue, | 566 | |
| 569 | .enable = 0, | 567 | if (!iwl_mvm_is_scd_cfg_supported(mvm)) { |
| 570 | }; | 568 | iwl_trans_txq_disable(mvm->trans, queue, true); |
| 571 | int ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, CMD_ASYNC, | 569 | return; |
| 572 | sizeof(cmd), &cmd); | ||
| 573 | if (ret) | ||
| 574 | IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n", | ||
| 575 | queue, ret); | ||
| 576 | } | 570 | } |
| 571 | |||
| 572 | iwl_trans_txq_disable(mvm->trans, queue, false); | ||
| 573 | ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, | ||
| 574 | sizeof(cmd), &cmd); | ||
| 575 | if (ret) | ||
| 576 | IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n", | ||
| 577 | queue, ret); | ||
| 577 | } | 578 | } |
| 578 | 579 | ||
| 579 | /** | 580 | /** |
| @@ -665,7 +666,7 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) | |||
| 665 | if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1) | 666 | if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1) |
| 666 | return false; | 667 | return false; |
| 667 | 668 | ||
| 668 | if (!mvm->cfg->rx_with_siso_diversity) | 669 | if (mvm->cfg->rx_with_siso_diversity) |
| 669 | return false; | 670 | return false; |
| 670 | 671 | ||
| 671 | ieee80211_iterate_active_interfaces_atomic( | 672 | ieee80211_iterate_active_interfaces_atomic( |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 2f0c4b170344..dbd6bcf52205 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
| @@ -415,6 +415,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 415 | {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)}, | 415 | {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)}, |
| 416 | {IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)}, | 416 | {IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)}, |
| 417 | {IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)}, | 417 | {IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)}, |
| 418 | {IWL_PCI_DEVICE(0x24F5, 0x0010, iwl4165_2ac_cfg)}, | ||
| 419 | {IWL_PCI_DEVICE(0x24F6, 0x0030, iwl4165_2ac_cfg)}, | ||
| 418 | #endif /* CONFIG_IWLMVM */ | 420 | #endif /* CONFIG_IWLMVM */ |
| 419 | 421 | ||
| 420 | {0} | 422 | {0} |
| @@ -527,8 +529,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 527 | else if (cfg == &iwl7265_n_cfg) | 529 | else if (cfg == &iwl7265_n_cfg) |
| 528 | cfg_7265d = &iwl7265d_n_cfg; | 530 | cfg_7265d = &iwl7265d_n_cfg; |
| 529 | if (cfg_7265d && | 531 | if (cfg_7265d && |
| 530 | (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D) | 532 | (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D) { |
| 531 | cfg = cfg_7265d; | 533 | cfg = cfg_7265d; |
| 534 | iwl_trans->cfg = cfg_7265d; | ||
| 535 | } | ||
| 532 | #endif | 536 | #endif |
| 533 | 537 | ||
| 534 | pci_set_drvdata(pdev, iwl_trans); | 538 | pci_set_drvdata(pdev, iwl_trans); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index e5652d82d79e..cae0eb8835ce 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
| @@ -216,6 +216,7 @@ struct iwl_pcie_txq_scratch_buf { | |||
| 216 | * @need_update: indicates need to update read/write index | 216 | * @need_update: indicates need to update read/write index |
| 217 | * @active: stores if queue is active | 217 | * @active: stores if queue is active |
| 218 | * @ampdu: true if this queue is an ampdu queue for an specific RA/TID | 218 | * @ampdu: true if this queue is an ampdu queue for an specific RA/TID |
| 219 | * @wd_timeout: queue watchdog timeout (jiffies) - per queue | ||
| 219 | * | 220 | * |
| 220 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame | 221 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame |
| 221 | * descriptors) and required locking structures. | 222 | * descriptors) and required locking structures. |
| @@ -232,6 +233,7 @@ struct iwl_txq { | |||
| 232 | bool need_update; | 233 | bool need_update; |
| 233 | u8 active; | 234 | u8 active; |
| 234 | bool ampdu; | 235 | bool ampdu; |
| 236 | unsigned long wd_timeout; | ||
| 235 | }; | 237 | }; |
| 236 | 238 | ||
| 237 | static inline dma_addr_t | 239 | static inline dma_addr_t |
| @@ -259,7 +261,6 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) | |||
| 259 | * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes) | 261 | * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes) |
| 260 | * @scd_set_active: should the transport configure the SCD for HCMD queue | 262 | * @scd_set_active: should the transport configure the SCD for HCMD queue |
| 261 | * @rx_page_order: page order for receive buffer size | 263 | * @rx_page_order: page order for receive buffer size |
| 262 | * @wd_timeout: queue watchdog timeout (jiffies) | ||
| 263 | * @reg_lock: protect hw register access | 264 | * @reg_lock: protect hw register access |
| 264 | * @cmd_in_flight: true when we have a host command in flight | 265 | * @cmd_in_flight: true when we have a host command in flight |
| 265 | * @fw_mon_phys: physical address of the buffer for the firmware monitor | 266 | * @fw_mon_phys: physical address of the buffer for the firmware monitor |
| @@ -302,6 +303,7 @@ struct iwl_trans_pcie { | |||
| 302 | 303 | ||
| 303 | u8 cmd_queue; | 304 | u8 cmd_queue; |
| 304 | u8 cmd_fifo; | 305 | u8 cmd_fifo; |
| 306 | unsigned int cmd_q_wdg_timeout; | ||
| 305 | u8 n_no_reclaim_cmds; | 307 | u8 n_no_reclaim_cmds; |
| 306 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; | 308 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; |
| 307 | 309 | ||
| @@ -312,9 +314,6 @@ struct iwl_trans_pcie { | |||
| 312 | 314 | ||
| 313 | const char *const *command_names; | 315 | const char *const *command_names; |
| 314 | 316 | ||
| 315 | /* queue watchdog */ | ||
| 316 | unsigned long wd_timeout; | ||
| 317 | |||
| 318 | /*protect hw register */ | 317 | /*protect hw register */ |
| 319 | spinlock_t reg_lock; | 318 | spinlock_t reg_lock; |
| 320 | bool cmd_in_flight; | 319 | bool cmd_in_flight; |
| @@ -373,7 +372,8 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr); | |||
| 373 | int iwl_pcie_tx_stop(struct iwl_trans *trans); | 372 | int iwl_pcie_tx_stop(struct iwl_trans *trans); |
| 374 | void iwl_pcie_tx_free(struct iwl_trans *trans); | 373 | void iwl_pcie_tx_free(struct iwl_trans *trans); |
| 375 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn, | 374 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn, |
| 376 | const struct iwl_trans_txq_scd_cfg *cfg); | 375 | const struct iwl_trans_txq_scd_cfg *cfg, |
| 376 | unsigned int wdg_timeout); | ||
| 377 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue, | 377 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue, |
| 378 | bool configure_scd); | 378 | bool configure_scd); |
| 379 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | 379 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 9ee4ca0ba8d3..69935aa5a1b3 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
| @@ -75,6 +75,7 @@ | |||
| 75 | #include "iwl-trans.h" | 75 | #include "iwl-trans.h" |
| 76 | #include "iwl-csr.h" | 76 | #include "iwl-csr.h" |
| 77 | #include "iwl-prph.h" | 77 | #include "iwl-prph.h" |
| 78 | #include "iwl-scd.h" | ||
| 78 | #include "iwl-agn-hw.h" | 79 | #include "iwl-agn-hw.h" |
| 79 | #include "iwl-fw-error-dump.h" | 80 | #include "iwl-fw-error-dump.h" |
| 80 | #include "internal.h" | 81 | #include "internal.h" |
| @@ -722,6 +723,11 @@ static int iwl_pcie_load_cpu_sections_8000b(struct iwl_trans *trans, | |||
| 722 | 723 | ||
| 723 | *first_ucode_section = last_read_idx; | 724 | *first_ucode_section = last_read_idx; |
| 724 | 725 | ||
| 726 | if (cpu == 1) | ||
| 727 | iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFF); | ||
| 728 | else | ||
| 729 | iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFFFFFF); | ||
| 730 | |||
| 725 | return 0; | 731 | return 0; |
| 726 | } | 732 | } |
| 727 | 733 | ||
| @@ -911,9 +917,6 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans, | |||
| 911 | if (trans->dbg_dest_tlv) | 917 | if (trans->dbg_dest_tlv) |
| 912 | iwl_pcie_apply_destination(trans); | 918 | iwl_pcie_apply_destination(trans); |
| 913 | 919 | ||
| 914 | /* Notify FW loading is done */ | ||
| 915 | iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFFFFFF); | ||
| 916 | |||
| 917 | /* wait for image verification to complete */ | 920 | /* wait for image verification to complete */ |
| 918 | ret = iwl_poll_prph_bit(trans, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0, | 921 | ret = iwl_poll_prph_bit(trans, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0, |
| 919 | LMPM_SECURE_BOOT_STATUS_SUCCESS, | 922 | LMPM_SECURE_BOOT_STATUS_SUCCESS, |
| @@ -982,7 +985,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
| 982 | 985 | ||
| 983 | /* Load the given image to the HW */ | 986 | /* Load the given image to the HW */ |
| 984 | if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) && | 987 | if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) && |
| 985 | (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_B_STEP)) | 988 | (CSR_HW_REV_STEP(trans->hw_rev) != SILICON_A_STEP)) |
| 986 | return iwl_pcie_load_given_ucode_8000b(trans, fw); | 989 | return iwl_pcie_load_given_ucode_8000b(trans, fw); |
| 987 | else | 990 | else |
| 988 | return iwl_pcie_load_given_ucode(trans, fw); | 991 | return iwl_pcie_load_given_ucode(trans, fw); |
| @@ -1266,6 +1269,7 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
| 1266 | 1269 | ||
| 1267 | trans_pcie->cmd_queue = trans_cfg->cmd_queue; | 1270 | trans_pcie->cmd_queue = trans_cfg->cmd_queue; |
| 1268 | trans_pcie->cmd_fifo = trans_cfg->cmd_fifo; | 1271 | trans_pcie->cmd_fifo = trans_cfg->cmd_fifo; |
| 1272 | trans_pcie->cmd_q_wdg_timeout = trans_cfg->cmd_q_wdg_timeout; | ||
| 1269 | if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) | 1273 | if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) |
| 1270 | trans_pcie->n_no_reclaim_cmds = 0; | 1274 | trans_pcie->n_no_reclaim_cmds = 0; |
| 1271 | else | 1275 | else |
| @@ -1280,9 +1284,6 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
| 1280 | else | 1284 | else |
| 1281 | trans_pcie->rx_page_order = get_order(4 * 1024); | 1285 | trans_pcie->rx_page_order = get_order(4 * 1024); |
| 1282 | 1286 | ||
| 1283 | trans_pcie->wd_timeout = | ||
| 1284 | msecs_to_jiffies(trans_cfg->queue_watchdog_timeout); | ||
| 1285 | |||
| 1286 | trans_pcie->command_names = trans_cfg->command_names; | 1287 | trans_pcie->command_names = trans_cfg->command_names; |
| 1287 | trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; | 1288 | trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; |
| 1288 | trans_pcie->scd_set_active = trans_cfg->scd_set_active; | 1289 | trans_pcie->scd_set_active = trans_cfg->scd_set_active; |
| @@ -2348,6 +2349,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
| 2348 | trans_pcie->trans = trans; | 2349 | trans_pcie->trans = trans; |
| 2349 | spin_lock_init(&trans_pcie->irq_lock); | 2350 | spin_lock_init(&trans_pcie->irq_lock); |
| 2350 | spin_lock_init(&trans_pcie->reg_lock); | 2351 | spin_lock_init(&trans_pcie->reg_lock); |
| 2352 | spin_lock_init(&trans_pcie->ref_lock); | ||
| 2351 | init_waitqueue_head(&trans_pcie->ucode_write_waitq); | 2353 | init_waitqueue_head(&trans_pcie->ucode_write_waitq); |
| 2352 | 2354 | ||
| 2353 | err = pci_enable_device(pdev); | 2355 | err = pci_enable_device(pdev); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index c1c4c75026b2..af0bce736358 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
| @@ -147,7 +147,6 @@ static void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, | |||
| 147 | static void iwl_pcie_txq_stuck_timer(unsigned long data) | 147 | static void iwl_pcie_txq_stuck_timer(unsigned long data) |
| 148 | { | 148 | { |
| 149 | struct iwl_txq *txq = (void *)data; | 149 | struct iwl_txq *txq = (void *)data; |
| 150 | struct iwl_queue *q = &txq->q; | ||
| 151 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; | 150 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; |
| 152 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); | 151 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); |
| 153 | u32 scd_sram_addr = trans_pcie->scd_base_addr + | 152 | u32 scd_sram_addr = trans_pcie->scd_base_addr + |
| @@ -164,7 +163,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
| 164 | spin_unlock(&txq->lock); | 163 | spin_unlock(&txq->lock); |
| 165 | 164 | ||
| 166 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, | 165 | IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->q.id, |
| 167 | jiffies_to_msecs(trans_pcie->wd_timeout)); | 166 | jiffies_to_msecs(txq->wd_timeout)); |
| 168 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | 167 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", |
| 169 | txq->q.read_ptr, txq->q.write_ptr); | 168 | txq->q.read_ptr, txq->q.write_ptr); |
| 170 | 169 | ||
| @@ -198,11 +197,6 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
| 198 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); | 197 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); |
| 199 | } | 198 | } |
| 200 | 199 | ||
| 201 | for (i = q->read_ptr; i != q->write_ptr; | ||
| 202 | i = iwl_queue_inc_wrap(i)) | ||
| 203 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | ||
| 204 | le32_to_cpu(txq->scratchbufs[i].scratch)); | ||
| 205 | |||
| 206 | iwl_force_nmi(trans); | 200 | iwl_force_nmi(trans); |
| 207 | } | 201 | } |
| 208 | 202 | ||
| @@ -680,7 +674,8 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) | |||
| 680 | iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); | 674 | iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); |
| 681 | 675 | ||
| 682 | iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, | 676 | iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue, |
| 683 | trans_pcie->cmd_fifo); | 677 | trans_pcie->cmd_fifo, |
| 678 | trans_pcie->cmd_q_wdg_timeout); | ||
| 684 | 679 | ||
| 685 | /* Activate all Tx DMA/FIFO channels */ | 680 | /* Activate all Tx DMA/FIFO channels */ |
| 686 | iwl_scd_activate_fifos(trans); | 681 | iwl_scd_activate_fifos(trans); |
| @@ -722,7 +717,12 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) | |||
| 722 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, | 717 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, |
| 723 | trans_pcie->kw.dma >> 4); | 718 | trans_pcie->kw.dma >> 4); |
| 724 | 719 | ||
| 725 | iwl_pcie_tx_start(trans, trans_pcie->scd_base_addr); | 720 | /* |
| 721 | * Send 0 as the scd_base_addr since the device may have be reset | ||
| 722 | * while we were in WoWLAN in which case SCD_SRAM_BASE_ADDR will | ||
| 723 | * contain garbage. | ||
| 724 | */ | ||
| 725 | iwl_pcie_tx_start(trans, 0); | ||
| 726 | } | 726 | } |
| 727 | 727 | ||
| 728 | /* | 728 | /* |
| @@ -898,6 +898,10 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) | |||
| 898 | } | 898 | } |
| 899 | } | 899 | } |
| 900 | 900 | ||
| 901 | if (trans->cfg->base_params->num_of_queues > 20) | ||
| 902 | iwl_set_bits_prph(trans, SCD_GP_CTRL, | ||
| 903 | SCD_GP_CTRL_ENABLE_31_QUEUES); | ||
| 904 | |||
| 901 | return 0; | 905 | return 0; |
| 902 | error: | 906 | error: |
| 903 | /*Upon error, free only if we allocated something */ | 907 | /*Upon error, free only if we allocated something */ |
| @@ -906,10 +910,9 @@ error: | |||
| 906 | return ret; | 910 | return ret; |
| 907 | } | 911 | } |
| 908 | 912 | ||
| 909 | static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie, | 913 | static inline void iwl_pcie_txq_progress(struct iwl_txq *txq) |
| 910 | struct iwl_txq *txq) | ||
| 911 | { | 914 | { |
| 912 | if (!trans_pcie->wd_timeout) | 915 | if (!txq->wd_timeout) |
| 913 | return; | 916 | return; |
| 914 | 917 | ||
| 915 | /* | 918 | /* |
| @@ -919,7 +922,7 @@ static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie, | |||
| 919 | if (txq->q.read_ptr == txq->q.write_ptr) | 922 | if (txq->q.read_ptr == txq->q.write_ptr) |
| 920 | del_timer(&txq->stuck_timer); | 923 | del_timer(&txq->stuck_timer); |
| 921 | else | 924 | else |
| 922 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | 925 | mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); |
| 923 | } | 926 | } |
| 924 | 927 | ||
| 925 | /* Frees buffers until index _not_ inclusive */ | 928 | /* Frees buffers until index _not_ inclusive */ |
| @@ -981,7 +984,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
| 981 | iwl_pcie_txq_free_tfd(trans, txq); | 984 | iwl_pcie_txq_free_tfd(trans, txq); |
| 982 | } | 985 | } |
| 983 | 986 | ||
| 984 | iwl_pcie_txq_progress(trans_pcie, txq); | 987 | iwl_pcie_txq_progress(txq); |
| 985 | 988 | ||
| 986 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) | 989 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) |
| 987 | iwl_wake_queue(trans, txq); | 990 | iwl_wake_queue(trans, txq); |
| @@ -1109,7 +1112,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
| 1109 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | 1112 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); |
| 1110 | } | 1113 | } |
| 1111 | 1114 | ||
| 1112 | iwl_pcie_txq_progress(trans_pcie, txq); | 1115 | iwl_pcie_txq_progress(txq); |
| 1113 | } | 1116 | } |
| 1114 | 1117 | ||
| 1115 | static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, | 1118 | static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, |
| @@ -1142,14 +1145,18 @@ static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, | |||
| 1142 | #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) | 1145 | #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) |
| 1143 | 1146 | ||
| 1144 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | 1147 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, |
| 1145 | const struct iwl_trans_txq_scd_cfg *cfg) | 1148 | const struct iwl_trans_txq_scd_cfg *cfg, |
| 1149 | unsigned int wdg_timeout) | ||
| 1146 | { | 1150 | { |
| 1147 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1151 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1152 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | ||
| 1148 | int fifo = -1; | 1153 | int fifo = -1; |
| 1149 | 1154 | ||
| 1150 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) | 1155 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) |
| 1151 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); | 1156 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); |
| 1152 | 1157 | ||
| 1158 | txq->wd_timeout = msecs_to_jiffies(wdg_timeout); | ||
| 1159 | |||
| 1153 | if (cfg) { | 1160 | if (cfg) { |
| 1154 | fifo = cfg->fifo; | 1161 | fifo = cfg->fifo; |
| 1155 | 1162 | ||
| @@ -1173,7 +1180,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
| 1173 | 1180 | ||
| 1174 | /* enable aggregations for the queue */ | 1181 | /* enable aggregations for the queue */ |
| 1175 | iwl_scd_txq_enable_agg(trans, txq_id); | 1182 | iwl_scd_txq_enable_agg(trans, txq_id); |
| 1176 | trans_pcie->txq[txq_id].ampdu = true; | 1183 | txq->ampdu = true; |
| 1177 | } else { | 1184 | } else { |
| 1178 | /* | 1185 | /* |
| 1179 | * disable aggregations for the queue, this will also | 1186 | * disable aggregations for the queue, this will also |
| @@ -1182,20 +1189,20 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
| 1182 | */ | 1189 | */ |
| 1183 | iwl_scd_txq_disable_agg(trans, txq_id); | 1190 | iwl_scd_txq_disable_agg(trans, txq_id); |
| 1184 | 1191 | ||
| 1185 | ssn = trans_pcie->txq[txq_id].q.read_ptr; | 1192 | ssn = txq->q.read_ptr; |
| 1186 | } | 1193 | } |
| 1187 | } | 1194 | } |
| 1188 | 1195 | ||
| 1189 | /* Place first TFD at index corresponding to start sequence number. | 1196 | /* Place first TFD at index corresponding to start sequence number. |
| 1190 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | 1197 | * Assumes that ssn_idx is valid (!= 0xFFF) */ |
| 1191 | trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff); | 1198 | txq->q.read_ptr = (ssn & 0xff); |
| 1192 | trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff); | 1199 | txq->q.write_ptr = (ssn & 0xff); |
| 1200 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | ||
| 1201 | (ssn & 0xff) | (txq_id << 8)); | ||
| 1193 | 1202 | ||
| 1194 | if (cfg) { | 1203 | if (cfg) { |
| 1195 | u8 frame_limit = cfg->frame_limit; | 1204 | u8 frame_limit = cfg->frame_limit; |
| 1196 | 1205 | ||
| 1197 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | ||
| 1198 | (ssn & 0xff) | (txq_id << 8)); | ||
| 1199 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); | 1206 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); |
| 1200 | 1207 | ||
| 1201 | /* Set up Tx window size and frame limit for this queue */ | 1208 | /* Set up Tx window size and frame limit for this queue */ |
| @@ -1220,11 +1227,17 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
| 1220 | if (txq_id == trans_pcie->cmd_queue && | 1227 | if (txq_id == trans_pcie->cmd_queue && |
| 1221 | trans_pcie->scd_set_active) | 1228 | trans_pcie->scd_set_active) |
| 1222 | iwl_scd_enable_set_active(trans, BIT(txq_id)); | 1229 | iwl_scd_enable_set_active(trans, BIT(txq_id)); |
| 1230 | |||
| 1231 | IWL_DEBUG_TX_QUEUES(trans, | ||
| 1232 | "Activate queue %d on FIFO %d WrPtr: %d\n", | ||
| 1233 | txq_id, fifo, ssn & 0xff); | ||
| 1234 | } else { | ||
| 1235 | IWL_DEBUG_TX_QUEUES(trans, | ||
| 1236 | "Activate queue %d WrPtr: %d\n", | ||
| 1237 | txq_id, ssn & 0xff); | ||
| 1223 | } | 1238 | } |
| 1224 | 1239 | ||
| 1225 | trans_pcie->txq[txq_id].active = true; | 1240 | txq->active = true; |
| 1226 | IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n", | ||
| 1227 | txq_id, fifo, ssn & 0xff); | ||
| 1228 | } | 1241 | } |
| 1229 | 1242 | ||
| 1230 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, | 1243 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, |
| @@ -1489,8 +1502,8 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1489 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); | 1502 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); |
| 1490 | 1503 | ||
| 1491 | /* start timer if queue currently empty */ | 1504 | /* start timer if queue currently empty */ |
| 1492 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | 1505 | if (q->read_ptr == q->write_ptr && txq->wd_timeout) |
| 1493 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | 1506 | mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); |
| 1494 | 1507 | ||
| 1495 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); | 1508 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); |
| 1496 | ret = iwl_pcie_set_cmd_in_flight(trans, cmd); | 1509 | ret = iwl_pcie_set_cmd_in_flight(trans, cmd); |
| @@ -1840,9 +1853,8 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 1840 | 1853 | ||
| 1841 | /* start timer if queue currently empty */ | 1854 | /* start timer if queue currently empty */ |
| 1842 | if (q->read_ptr == q->write_ptr) { | 1855 | if (q->read_ptr == q->write_ptr) { |
| 1843 | if (txq->need_update && trans_pcie->wd_timeout) | 1856 | if (txq->wd_timeout) |
| 1844 | mod_timer(&txq->stuck_timer, | 1857 | mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); |
| 1845 | jiffies + trans_pcie->wd_timeout); | ||
| 1846 | IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id); | 1858 | IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id); |
| 1847 | iwl_trans_pcie_ref(trans); | 1859 | iwl_trans_pcie_ref(trans); |
| 1848 | } | 1860 | } |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 34f09ef90bb3..a92985a6ea21 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
| @@ -1616,10 +1616,10 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1616 | 1616 | ||
| 1617 | lbs_deb_enter(LBS_DEB_CFG80211); | 1617 | lbs_deb_enter(LBS_DEB_CFG80211); |
| 1618 | 1618 | ||
| 1619 | sinfo->filled |= STATION_INFO_TX_BYTES | | 1619 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES) | |
| 1620 | STATION_INFO_TX_PACKETS | | 1620 | BIT(NL80211_STA_INFO_TX_PACKETS) | |
| 1621 | STATION_INFO_RX_BYTES | | 1621 | BIT(NL80211_STA_INFO_RX_BYTES) | |
| 1622 | STATION_INFO_RX_PACKETS; | 1622 | BIT(NL80211_STA_INFO_RX_PACKETS); |
| 1623 | sinfo->tx_bytes = priv->dev->stats.tx_bytes; | 1623 | sinfo->tx_bytes = priv->dev->stats.tx_bytes; |
| 1624 | sinfo->tx_packets = priv->dev->stats.tx_packets; | 1624 | sinfo->tx_packets = priv->dev->stats.tx_packets; |
| 1625 | sinfo->rx_bytes = priv->dev->stats.rx_bytes; | 1625 | sinfo->rx_bytes = priv->dev->stats.rx_bytes; |
| @@ -1629,14 +1629,14 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1629 | ret = lbs_get_rssi(priv, &signal, &noise); | 1629 | ret = lbs_get_rssi(priv, &signal, &noise); |
| 1630 | if (ret == 0) { | 1630 | if (ret == 0) { |
| 1631 | sinfo->signal = signal; | 1631 | sinfo->signal = signal; |
| 1632 | sinfo->filled |= STATION_INFO_SIGNAL; | 1632 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 1633 | } | 1633 | } |
| 1634 | 1634 | ||
| 1635 | /* Convert priv->cur_rate from hw_value to NL80211 value */ | 1635 | /* Convert priv->cur_rate from hw_value to NL80211 value */ |
| 1636 | for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) { | 1636 | for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) { |
| 1637 | if (priv->cur_rate == lbs_rates[i].hw_value) { | 1637 | if (priv->cur_rate == lbs_rates[i].hw_value) { |
| 1638 | sinfo->txrate.legacy = lbs_rates[i].bitrate; | 1638 | sinfo->txrate.legacy = lbs_rates[i].bitrate; |
| 1639 | sinfo->filled |= STATION_INFO_TX_BITRATE; | 1639 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
| 1640 | break; | 1640 | break; |
| 1641 | } | 1641 | } |
| 1642 | } | 1642 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index ef58a8862d91..494e7335aa64 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
| @@ -625,22 +625,22 @@ static int hwsim_fops_ps_write(void *dat, u64 val) | |||
| 625 | old_ps = data->ps; | 625 | old_ps = data->ps; |
| 626 | data->ps = val; | 626 | data->ps = val; |
| 627 | 627 | ||
| 628 | local_bh_disable(); | ||
| 628 | if (val == PS_MANUAL_POLL) { | 629 | if (val == PS_MANUAL_POLL) { |
| 629 | ieee80211_iterate_active_interfaces(data->hw, | 630 | ieee80211_iterate_active_interfaces_atomic( |
| 630 | IEEE80211_IFACE_ITER_NORMAL, | 631 | data->hw, IEEE80211_IFACE_ITER_NORMAL, |
| 631 | hwsim_send_ps_poll, data); | 632 | hwsim_send_ps_poll, data); |
| 632 | data->ps_poll_pending = true; | 633 | data->ps_poll_pending = true; |
| 633 | } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { | 634 | } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { |
| 634 | ieee80211_iterate_active_interfaces(data->hw, | 635 | ieee80211_iterate_active_interfaces_atomic( |
| 635 | IEEE80211_IFACE_ITER_NORMAL, | 636 | data->hw, IEEE80211_IFACE_ITER_NORMAL, |
| 636 | hwsim_send_nullfunc_ps, | 637 | hwsim_send_nullfunc_ps, data); |
| 637 | data); | ||
| 638 | } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { | 638 | } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { |
| 639 | ieee80211_iterate_active_interfaces(data->hw, | 639 | ieee80211_iterate_active_interfaces_atomic( |
| 640 | IEEE80211_IFACE_ITER_NORMAL, | 640 | data->hw, IEEE80211_IFACE_ITER_NORMAL, |
| 641 | hwsim_send_nullfunc_no_ps, | 641 | hwsim_send_nullfunc_no_ps, data); |
| 642 | data); | ||
| 643 | } | 642 | } |
| 643 | local_bh_enable(); | ||
| 644 | 644 | ||
| 645 | return 0; | 645 | return 0; |
| 646 | } | 646 | } |
| @@ -2149,14 +2149,14 @@ static int append_radio_msg(struct sk_buff *skb, int id, | |||
| 2149 | if (param->regd) { | 2149 | if (param->regd) { |
| 2150 | int i; | 2150 | int i; |
| 2151 | 2151 | ||
| 2152 | for (i = 0; hwsim_world_regdom_custom[i] != param->regd && | 2152 | for (i = 0; i < ARRAY_SIZE(hwsim_world_regdom_custom); i++) { |
| 2153 | i < ARRAY_SIZE(hwsim_world_regdom_custom); i++) | 2153 | if (hwsim_world_regdom_custom[i] != param->regd) |
| 2154 | ; | 2154 | continue; |
| 2155 | 2155 | ||
| 2156 | if (i < ARRAY_SIZE(hwsim_world_regdom_custom)) { | ||
| 2157 | ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i); | 2156 | ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i); |
| 2158 | if (ret < 0) | 2157 | if (ret < 0) |
| 2159 | return ret; | 2158 | return ret; |
| 2159 | break; | ||
| 2160 | } | 2160 | } |
| 2161 | } | 2161 | } |
| 2162 | 2162 | ||
diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c index 2668e83afbb6..3ab87a855122 100644 --- a/drivers/net/wireless/mwifiex/11h.c +++ b/drivers/net/wireless/mwifiex/11h.c | |||
| @@ -21,6 +21,16 @@ | |||
| 21 | #include "fw.h" | 21 | #include "fw.h" |
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | void mwifiex_init_11h_params(struct mwifiex_private *priv) | ||
| 25 | { | ||
| 26 | priv->state_11h.is_11h_enabled = true; | ||
| 27 | priv->state_11h.is_11h_active = false; | ||
| 28 | } | ||
| 29 | |||
| 30 | inline int mwifiex_is_11h_active(struct mwifiex_private *priv) | ||
| 31 | { | ||
| 32 | return priv->state_11h.is_11h_active; | ||
| 33 | } | ||
| 24 | /* This function appends 11h info to a buffer while joining an | 34 | /* This function appends 11h info to a buffer while joining an |
| 25 | * infrastructure BSS | 35 | * infrastructure BSS |
| 26 | */ | 36 | */ |
| @@ -39,7 +49,7 @@ mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer, | |||
| 39 | return; | 49 | return; |
| 40 | 50 | ||
| 41 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); | 51 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); |
| 42 | sband = priv->wdev->wiphy->bands[radio_type]; | 52 | sband = priv->wdev.wiphy->bands[radio_type]; |
| 43 | 53 | ||
| 44 | cap = (struct mwifiex_ie_types_pwr_capability *)*buffer; | 54 | cap = (struct mwifiex_ie_types_pwr_capability *)*buffer; |
| 45 | cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY); | 55 | cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY); |
| @@ -69,10 +79,14 @@ mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer, | |||
| 69 | } | 79 | } |
| 70 | 80 | ||
| 71 | /* Enable or disable the 11h extensions in the firmware */ | 81 | /* Enable or disable the 11h extensions in the firmware */ |
| 72 | static int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag) | 82 | int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag) |
| 73 | { | 83 | { |
| 74 | u32 enable = flag; | 84 | u32 enable = flag; |
| 75 | 85 | ||
| 86 | /* enable master mode radar detection on AP interface */ | ||
| 87 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && enable) | ||
| 88 | enable |= MWIFIEX_MASTER_RADAR_DET_MASK; | ||
| 89 | |||
| 76 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, | 90 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
| 77 | HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true); | 91 | HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true); |
| 78 | } | 92 | } |
| @@ -91,11 +105,191 @@ void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, | |||
| 91 | * bit | 105 | * bit |
| 92 | */ | 106 | */ |
| 93 | mwifiex_11h_activate(priv, true); | 107 | mwifiex_11h_activate(priv, true); |
| 108 | priv->state_11h.is_11h_active = true; | ||
| 94 | bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT; | 109 | bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT; |
| 95 | mwifiex_11h_process_infra_join(priv, buffer, bss_desc); | 110 | mwifiex_11h_process_infra_join(priv, buffer, bss_desc); |
| 96 | } else { | 111 | } else { |
| 97 | /* Deactivate 11h functions in the firmware */ | 112 | /* Deactivate 11h functions in the firmware */ |
| 98 | mwifiex_11h_activate(priv, false); | 113 | mwifiex_11h_activate(priv, false); |
| 114 | priv->state_11h.is_11h_active = false; | ||
| 99 | bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT; | 115 | bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT; |
| 100 | } | 116 | } |
| 101 | } | 117 | } |
| 118 | |||
| 119 | /* This is DFS CAC work queue function. | ||
| 120 | * This delayed work emits CAC finished event for cfg80211 if | ||
| 121 | * CAC was started earlier. | ||
| 122 | */ | ||
| 123 | void mwifiex_dfs_cac_work_queue(struct work_struct *work) | ||
| 124 | { | ||
| 125 | struct cfg80211_chan_def chandef; | ||
| 126 | struct delayed_work *delayed_work = | ||
| 127 | container_of(work, struct delayed_work, work); | ||
| 128 | struct mwifiex_private *priv = | ||
| 129 | container_of(delayed_work, struct mwifiex_private, | ||
| 130 | dfs_cac_work); | ||
| 131 | |||
| 132 | if (WARN_ON(!priv)) | ||
| 133 | return; | ||
| 134 | |||
| 135 | chandef = priv->dfs_chandef; | ||
| 136 | if (priv->wdev.cac_started) { | ||
| 137 | dev_dbg(priv->adapter->dev, | ||
| 138 | "CAC timer finished; No radar detected\n"); | ||
| 139 | cfg80211_cac_event(priv->netdev, &chandef, | ||
| 140 | NL80211_RADAR_CAC_FINISHED, | ||
| 141 | GFP_KERNEL); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | /* This function prepares channel report request command to FW for | ||
| 146 | * starting radar detection. | ||
| 147 | */ | ||
| 148 | int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv, | ||
| 149 | struct host_cmd_ds_command *cmd, | ||
| 150 | void *data_buf) | ||
| 151 | { | ||
| 152 | struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req; | ||
| 153 | struct mwifiex_radar_params *radar_params = (void *)data_buf; | ||
| 154 | |||
| 155 | cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST); | ||
| 156 | cmd->size = cpu_to_le16(S_DS_GEN); | ||
| 157 | le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_chan_rpt_req)); | ||
| 158 | |||
| 159 | cr_req->chan_desc.start_freq = cpu_to_le16(MWIFIEX_A_BAND_START_FREQ); | ||
| 160 | cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value; | ||
| 161 | cr_req->chan_desc.chan_width = radar_params->chandef->width; | ||
| 162 | cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms); | ||
| 163 | |||
| 164 | dev_dbg(priv->adapter->dev, | ||
| 165 | "11h: issuing DFS Radar check for channel=%d\n", | ||
| 166 | radar_params->chandef->chan->hw_value); | ||
| 167 | |||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | /* This function is to abort ongoing CAC upon stopping AP operations | ||
| 172 | * or during unload. | ||
| 173 | */ | ||
| 174 | void mwifiex_abort_cac(struct mwifiex_private *priv) | ||
| 175 | { | ||
| 176 | if (priv->wdev.cac_started) { | ||
| 177 | dev_dbg(priv->adapter->dev, | ||
| 178 | "Aborting delayed work for CAC.\n"); | ||
| 179 | cancel_delayed_work_sync(&priv->dfs_cac_work); | ||
| 180 | cfg80211_cac_event(priv->netdev, &priv->dfs_chandef, | ||
| 181 | NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | /* This function handles channel report event from FW during CAC period. | ||
| 186 | * If radar is detected during CAC, driver indicates the same to cfg80211 | ||
| 187 | * and also cancels ongoing delayed work. | ||
| 188 | */ | ||
| 189 | int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv, | ||
| 190 | struct sk_buff *skb) | ||
| 191 | { | ||
| 192 | struct host_cmd_ds_chan_rpt_event *rpt_event; | ||
| 193 | struct mwifiex_ie_types_chan_rpt_data *rpt; | ||
| 194 | u8 *evt_buf; | ||
| 195 | u16 event_len, tlv_len; | ||
| 196 | |||
| 197 | rpt_event = (void *)(skb->data + sizeof(u32)); | ||
| 198 | event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event)+ | ||
| 199 | sizeof(u32)); | ||
| 200 | |||
| 201 | if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) { | ||
| 202 | dev_err(priv->adapter->dev, "Error in channel report event\n"); | ||
| 203 | return -1; | ||
| 204 | } | ||
| 205 | |||
| 206 | evt_buf = (void *)&rpt_event->tlvbuf; | ||
| 207 | |||
| 208 | while (event_len >= sizeof(struct mwifiex_ie_types_header)) { | ||
| 209 | rpt = (void *)&rpt_event->tlvbuf; | ||
| 210 | tlv_len = le16_to_cpu(rpt->header.len); | ||
| 211 | |||
| 212 | switch (le16_to_cpu(rpt->header.type)) { | ||
| 213 | case TLV_TYPE_CHANRPT_11H_BASIC: | ||
| 214 | if (rpt->map.radar) { | ||
| 215 | dev_notice(priv->adapter->dev, | ||
| 216 | "RADAR Detected on channel %d!\n", | ||
| 217 | priv->dfs_chandef.chan->hw_value); | ||
| 218 | cancel_delayed_work_sync(&priv->dfs_cac_work); | ||
| 219 | cfg80211_cac_event(priv->netdev, | ||
| 220 | &priv->dfs_chandef, | ||
| 221 | NL80211_RADAR_DETECTED, | ||
| 222 | GFP_KERNEL); | ||
| 223 | } | ||
| 224 | break; | ||
| 225 | default: | ||
| 226 | break; | ||
| 227 | } | ||
| 228 | |||
| 229 | evt_buf += (tlv_len + sizeof(rpt->header)); | ||
| 230 | event_len -= (tlv_len + sizeof(rpt->header)); | ||
| 231 | } | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* Handler for radar detected event from FW.*/ | ||
| 237 | int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | ||
| 238 | struct sk_buff *skb) | ||
| 239 | { | ||
| 240 | struct mwifiex_radar_det_event *rdr_event; | ||
| 241 | |||
| 242 | rdr_event = (void *)(skb->data + sizeof(u32)); | ||
| 243 | |||
| 244 | if (le32_to_cpu(rdr_event->passed)) { | ||
| 245 | dev_notice(priv->adapter->dev, | ||
| 246 | "radar detected; indicating kernel\n"); | ||
| 247 | cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef, | ||
| 248 | GFP_KERNEL); | ||
| 249 | dev_dbg(priv->adapter->dev, "regdomain: %d\n", | ||
| 250 | rdr_event->reg_domain); | ||
| 251 | dev_dbg(priv->adapter->dev, "radar detection type: %d\n", | ||
| 252 | rdr_event->det_type); | ||
| 253 | } else { | ||
| 254 | dev_dbg(priv->adapter->dev, "false radar detection event!\n"); | ||
| 255 | } | ||
| 256 | |||
| 257 | return 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | /* This is work queue function for channel switch handling. | ||
| 261 | * This function takes care of updating new channel definitin to | ||
| 262 | * bss config structure, restart AP and indicate channel switch success | ||
| 263 | * to cfg80211. | ||
| 264 | */ | ||
| 265 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work) | ||
| 266 | { | ||
| 267 | struct mwifiex_uap_bss_param *bss_cfg; | ||
| 268 | struct delayed_work *delayed_work = | ||
| 269 | container_of(work, struct delayed_work, work); | ||
| 270 | struct mwifiex_private *priv = | ||
| 271 | container_of(delayed_work, struct mwifiex_private, | ||
| 272 | dfs_chan_sw_work); | ||
| 273 | |||
| 274 | if (WARN_ON(!priv)) | ||
| 275 | return; | ||
| 276 | |||
| 277 | bss_cfg = &priv->bss_cfg; | ||
| 278 | if (!bss_cfg->beacon_period) { | ||
| 279 | dev_err(priv->adapter->dev, | ||
| 280 | "channel switch: AP already stopped\n"); | ||
| 281 | return; | ||
| 282 | } | ||
| 283 | |||
| 284 | mwifiex_uap_set_channel(bss_cfg, priv->dfs_chandef); | ||
| 285 | |||
| 286 | if (mwifiex_config_start_uap(priv, bss_cfg)) { | ||
| 287 | dev_dbg(priv->adapter->dev, | ||
| 288 | "Failed to start AP after channel switch\n"); | ||
| 289 | return; | ||
| 290 | } | ||
| 291 | |||
| 292 | dev_notice(priv->adapter->dev, | ||
| 293 | "indicating channel switch completion to kernel\n"); | ||
| 294 | cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef); | ||
| 295 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 9d4786e7ddff..543148d27b01 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
| @@ -39,7 +39,7 @@ int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, | |||
| 39 | { | 39 | { |
| 40 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info); | 40 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info); |
| 41 | struct ieee80211_supported_band *sband = | 41 | struct ieee80211_supported_band *sband = |
| 42 | priv->wdev->wiphy->bands[radio_type]; | 42 | priv->wdev.wiphy->bands[radio_type]; |
| 43 | 43 | ||
| 44 | if (WARN_ON_ONCE(!sband)) { | 44 | if (WARN_ON_ONCE(!sband)) { |
| 45 | dev_err(priv->adapter->dev, "Invalid radio type!\n"); | 45 | dev_err(priv->adapter->dev, "Invalid radio type!\n"); |
| @@ -314,7 +314,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
| 314 | return ret_len; | 314 | return ret_len; |
| 315 | 315 | ||
| 316 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); | 316 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); |
| 317 | sband = priv->wdev->wiphy->bands[radio_type]; | 317 | sband = priv->wdev.wiphy->bands[radio_type]; |
| 318 | 318 | ||
| 319 | if (bss_desc->bcn_ht_cap) { | 319 | if (bss_desc->bcn_ht_cap) { |
| 320 | ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; | 320 | ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; |
| @@ -558,10 +558,10 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) | |||
| 558 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | 558 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); |
| 559 | sta_ptr = mwifiex_get_sta_entry(priv, peer_mac); | 559 | sta_ptr = mwifiex_get_sta_entry(priv, peer_mac); |
| 560 | if (!sta_ptr) { | 560 | if (!sta_ptr) { |
| 561 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
| 561 | dev_warn(priv->adapter->dev, | 562 | dev_warn(priv->adapter->dev, |
| 562 | "BA setup with unknown TDLS peer %pM!\n", | 563 | "BA setup with unknown TDLS peer %pM!\n", |
| 563 | peer_mac); | 564 | peer_mac); |
| 564 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
| 565 | return -1; | 565 | return -1; |
| 566 | } | 566 | } |
| 567 | if (sta_ptr->is_11ac_enabled) | 567 | if (sta_ptr->is_11ac_enabled) |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index f33dc81c5228..a2e8817b56d8 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
| @@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, | |||
| 45 | skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); | 45 | skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); |
| 46 | 46 | ||
| 47 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | 47 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, |
| 48 | priv->wdev->iftype, 0, false); | 48 | priv->wdev.iftype, 0, false); |
| 49 | 49 | ||
| 50 | while (!skb_queue_empty(&list)) { | 50 | while (!skb_queue_empty(&list)) { |
| 51 | rx_skb = __skb_dequeue(&list); | 51 | rx_skb = __skb_dequeue(&list); |
| @@ -353,9 +353,6 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
| 353 | 353 | ||
| 354 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | 354 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); |
| 355 | if (mwifiex_queuing_ra_based(priv)) { | 355 | if (mwifiex_queuing_ra_based(priv)) { |
| 356 | dev_dbg(priv->adapter->dev, | ||
| 357 | "info: AP/ADHOC:last_seq=%d start_win=%d\n", | ||
| 358 | last_seq, new_node->start_win); | ||
| 359 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) { | 356 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) { |
| 360 | node = mwifiex_get_sta_entry(priv, ta); | 357 | node = mwifiex_get_sta_entry(priv, ta); |
| 361 | if (node) | 358 | if (node) |
| @@ -370,6 +367,9 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
| 370 | } | 367 | } |
| 371 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | 368 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); |
| 372 | 369 | ||
| 370 | dev_dbg(priv->adapter->dev, "info: last_seq=%d start_win=%d\n", | ||
| 371 | last_seq, new_node->start_win); | ||
| 372 | |||
| 373 | if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && | 373 | if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && |
| 374 | last_seq >= new_node->start_win) { | 374 | last_seq >= new_node->start_win) { |
| 375 | new_node->start_win = last_seq + 1; | 375 | new_node->start_win = last_seq + 1; |
| @@ -466,10 +466,10 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, | |||
| 466 | sta_ptr = mwifiex_get_sta_entry(priv, | 466 | sta_ptr = mwifiex_get_sta_entry(priv, |
| 467 | cmd_addba_req->peer_mac_addr); | 467 | cmd_addba_req->peer_mac_addr); |
| 468 | if (!sta_ptr) { | 468 | if (!sta_ptr) { |
| 469 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
| 469 | dev_warn(priv->adapter->dev, | 470 | dev_warn(priv->adapter->dev, |
| 470 | "BA setup with unknown TDLS peer %pM!\n", | 471 | "BA setup with unknown TDLS peer %pM!\n", |
| 471 | cmd_addba_req->peer_mac_addr); | 472 | cmd_addba_req->peer_mac_addr); |
| 472 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
| 473 | return -1; | 473 | return -1; |
| 474 | } | 474 | } |
| 475 | if (sta_ptr->is_11ac_enabled) | 475 | if (sta_ptr->is_11ac_enabled) |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 93ab36fc9f93..41c8e25df954 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
| @@ -590,77 +590,62 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
| 590 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | 590 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
| 591 | struct mwifiex_private *priv; | 591 | struct mwifiex_private *priv; |
| 592 | struct mwifiex_uap_bss_param *bss_cfg; | 592 | struct mwifiex_uap_bss_param *bss_cfg; |
| 593 | int ret, bss_started, i; | 593 | int ret; |
| 594 | |||
| 595 | for (i = 0; i < adapter->priv_num; i++) { | ||
| 596 | priv = adapter->priv[i]; | ||
| 597 | |||
| 598 | switch (priv->bss_role) { | ||
| 599 | case MWIFIEX_BSS_ROLE_UAP: | ||
| 600 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), | ||
| 601 | GFP_KERNEL); | ||
| 602 | if (!bss_cfg) | ||
| 603 | return -ENOMEM; | ||
| 604 | |||
| 605 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
| 606 | |||
| 607 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) | ||
| 608 | bss_cfg->rts_threshold = wiphy->rts_threshold; | ||
| 609 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) | ||
| 610 | bss_cfg->frag_threshold = wiphy->frag_threshold; | ||
| 611 | if (changed & WIPHY_PARAM_RETRY_LONG) | ||
| 612 | bss_cfg->retry_limit = wiphy->retry_long; | ||
| 613 | |||
| 614 | bss_started = priv->bss_started; | ||
| 615 | |||
| 616 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
| 617 | HostCmd_ACT_GEN_SET, 0, | ||
| 618 | NULL, true); | ||
| 619 | if (ret) { | ||
| 620 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
| 621 | kfree(bss_cfg); | ||
| 622 | return ret; | ||
| 623 | } | ||
| 624 | 594 | ||
| 625 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | 595 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
| 626 | HostCmd_ACT_GEN_SET, | ||
| 627 | UAP_BSS_PARAMS_I, bss_cfg, | ||
| 628 | false); | ||
| 629 | 596 | ||
| 630 | kfree(bss_cfg); | 597 | switch (priv->bss_role) { |
| 598 | case MWIFIEX_BSS_ROLE_UAP: | ||
| 599 | if (priv->bss_started) { | ||
| 600 | dev_err(adapter->dev, | ||
| 601 | "cannot change wiphy params when bss started"); | ||
| 602 | return -EINVAL; | ||
| 603 | } | ||
| 631 | 604 | ||
| 632 | if (ret) { | 605 | bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL); |
| 633 | wiphy_err(wiphy, "Failed to set bss config\n"); | 606 | if (!bss_cfg) |
| 634 | return ret; | 607 | return -ENOMEM; |
| 635 | } | ||
| 636 | 608 | ||
| 637 | if (!bss_started) | 609 | mwifiex_set_sys_config_invalid_data(bss_cfg); |
| 638 | break; | ||
| 639 | 610 | ||
| 640 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, | 611 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) |
| 641 | HostCmd_ACT_GEN_SET, 0, | 612 | bss_cfg->rts_threshold = wiphy->rts_threshold; |
| 642 | NULL, false); | 613 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) |
| 643 | if (ret) { | 614 | bss_cfg->frag_threshold = wiphy->frag_threshold; |
| 644 | wiphy_err(wiphy, "Failed to start BSS\n"); | 615 | if (changed & WIPHY_PARAM_RETRY_LONG) |
| 645 | return ret; | 616 | bss_cfg->retry_limit = wiphy->retry_long; |
| 646 | } | 617 | |
| 618 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
| 619 | HostCmd_ACT_GEN_SET, | ||
| 620 | UAP_BSS_PARAMS_I, bss_cfg, | ||
| 621 | false); | ||
| 622 | |||
| 623 | kfree(bss_cfg); | ||
| 624 | if (ret) { | ||
| 625 | wiphy_err(wiphy, "Failed to set wiphy phy params\n"); | ||
| 626 | return ret; | ||
| 627 | } | ||
| 628 | break; | ||
| 647 | 629 | ||
| 648 | break; | ||
| 649 | case MWIFIEX_BSS_ROLE_STA: | 630 | case MWIFIEX_BSS_ROLE_STA: |
| 650 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 631 | if (priv->media_connected) { |
| 651 | ret = mwifiex_set_rts(priv, | 632 | dev_err(adapter->dev, |
| 652 | wiphy->rts_threshold); | 633 | "cannot change wiphy params when connected"); |
| 653 | if (ret) | 634 | return -EINVAL; |
| 654 | return ret; | 635 | } |
| 655 | } | 636 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { |
| 656 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { | 637 | ret = mwifiex_set_rts(priv, |
| 657 | ret = mwifiex_set_frag(priv, | 638 | wiphy->rts_threshold); |
| 658 | wiphy->frag_threshold); | 639 | if (ret) |
| 659 | if (ret) | 640 | return ret; |
| 660 | return ret; | 641 | } |
| 661 | } | 642 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { |
| 662 | break; | 643 | ret = mwifiex_set_frag(priv, |
| 644 | wiphy->frag_threshold); | ||
| 645 | if (ret) | ||
| 646 | return ret; | ||
| 663 | } | 647 | } |
| 648 | break; | ||
| 664 | } | 649 | } |
| 665 | 650 | ||
| 666 | return 0; | 651 | return 0; |
| @@ -671,9 +656,6 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) | |||
| 671 | { | 656 | { |
| 672 | u16 mode = P2P_MODE_DISABLE; | 657 | u16 mode = P2P_MODE_DISABLE; |
| 673 | 658 | ||
| 674 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) | ||
| 675 | mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA); | ||
| 676 | |||
| 677 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, | 659 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, |
| 678 | HostCmd_ACT_GEN_SET, 0, &mode, true)) | 660 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
| 679 | return -1; | 661 | return -1; |
| @@ -730,12 +712,249 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) | |||
| 730 | HostCmd_ACT_GEN_SET, 0, &mode, true)) | 712 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
| 731 | return -1; | 713 | return -1; |
| 732 | 714 | ||
| 733 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) | 715 | return 0; |
| 734 | mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_UAP); | 716 | } |
| 717 | |||
| 718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | ||
| 719 | { | ||
| 720 | priv->mgmt_frame_mask = 0; | ||
| 721 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, | ||
| 722 | HostCmd_ACT_GEN_SET, 0, | ||
| 723 | &priv->mgmt_frame_mask, false)) { | ||
| 724 | dev_warn(priv->adapter->dev, | ||
| 725 | "could not unregister mgmt frame rx\n"); | ||
| 726 | return -1; | ||
| 727 | } | ||
| 728 | |||
| 729 | mwifiex_deauthenticate(priv, NULL); | ||
| 730 | mwifiex_free_priv(priv); | ||
| 731 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
| 732 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
| 733 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
| 734 | |||
| 735 | return 0; | ||
| 736 | } | ||
| 737 | |||
| 738 | static int | ||
| 739 | mwifiex_init_new_priv_params(struct mwifiex_private *priv, | ||
| 740 | struct net_device *dev, | ||
| 741 | enum nl80211_iftype type) | ||
| 742 | { | ||
| 743 | mwifiex_init_priv(priv); | ||
| 744 | |||
| 745 | priv->bss_mode = type; | ||
| 746 | priv->wdev.iftype = type; | ||
| 747 | |||
| 748 | mwifiex_init_priv_params(priv, priv->netdev); | ||
| 749 | priv->bss_started = 0; | ||
| 750 | |||
| 751 | switch (type) { | ||
| 752 | case NL80211_IFTYPE_STATION: | ||
| 753 | case NL80211_IFTYPE_ADHOC: | ||
| 754 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | ||
| 755 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; | ||
| 756 | break; | ||
| 757 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 758 | case NL80211_IFTYPE_P2P_GO: | ||
| 759 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | ||
| 760 | priv->bss_type = MWIFIEX_BSS_TYPE_P2P; | ||
| 761 | break; | ||
| 762 | case NL80211_IFTYPE_AP: | ||
| 763 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; | ||
| 764 | priv->bss_role = MWIFIEX_BSS_ROLE_UAP; | ||
| 765 | break; | ||
| 766 | default: | ||
| 767 | dev_err(priv->adapter->dev, | ||
| 768 | "%s: changing to %d not supported\n", | ||
| 769 | dev->name, type); | ||
| 770 | return -EOPNOTSUPP; | ||
| 771 | } | ||
| 772 | |||
| 773 | return 0; | ||
| 774 | } | ||
| 775 | |||
| 776 | static int | ||
| 777 | mwifiex_change_vif_to_p2p(struct net_device *dev, | ||
| 778 | enum nl80211_iftype curr_iftype, | ||
| 779 | enum nl80211_iftype type, u32 *flags, | ||
| 780 | struct vif_params *params) | ||
| 781 | { | ||
| 782 | struct mwifiex_private *priv; | ||
| 783 | struct mwifiex_adapter *adapter; | ||
| 784 | |||
| 785 | priv = mwifiex_netdev_get_priv(dev); | ||
| 786 | |||
| 787 | if (!priv) | ||
| 788 | return -1; | ||
| 789 | |||
| 790 | adapter = priv->adapter; | ||
| 791 | |||
| 792 | if (adapter->curr_iface_comb.p2p_intf == | ||
| 793 | adapter->iface_limit.p2p_intf) { | ||
| 794 | dev_err(adapter->dev, | ||
| 795 | "cannot create multiple P2P ifaces\n"); | ||
| 796 | return -1; | ||
| 797 | } | ||
| 798 | |||
| 799 | dev_dbg(priv->adapter->dev, "%s: changing role to p2p\n", dev->name); | ||
| 800 | |||
| 801 | if (mwifiex_deinit_priv_params(priv)) | ||
| 802 | return -1; | ||
| 803 | if (mwifiex_init_new_priv_params(priv, dev, type)) | ||
| 804 | return -1; | ||
| 805 | |||
| 806 | switch (type) { | ||
| 807 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 808 | if (mwifiex_cfg80211_init_p2p_client(priv)) | ||
| 809 | return -EFAULT; | ||
| 810 | break; | ||
| 811 | case NL80211_IFTYPE_P2P_GO: | ||
| 812 | if (mwifiex_cfg80211_init_p2p_go(priv)) | ||
| 813 | return -EFAULT; | ||
| 814 | break; | ||
| 815 | default: | ||
| 816 | dev_err(priv->adapter->dev, | ||
| 817 | "%s: changing to %d not supported\n", | ||
| 818 | dev->name, type); | ||
| 819 | return -EOPNOTSUPP; | ||
| 820 | } | ||
| 821 | |||
| 822 | if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
| 823 | HostCmd_ACT_GEN_SET, 0, NULL, true)) | ||
| 824 | return -1; | ||
| 825 | |||
| 826 | if (mwifiex_sta_init_cmd(priv, false, false)) | ||
| 827 | return -1; | ||
| 828 | |||
| 829 | switch (curr_iftype) { | ||
| 830 | case NL80211_IFTYPE_STATION: | ||
| 831 | case NL80211_IFTYPE_ADHOC: | ||
| 832 | adapter->curr_iface_comb.sta_intf--; | ||
| 833 | break; | ||
| 834 | case NL80211_IFTYPE_AP: | ||
| 835 | adapter->curr_iface_comb.uap_intf--; | ||
| 836 | break; | ||
| 837 | default: | ||
| 838 | break; | ||
| 839 | } | ||
| 840 | |||
| 841 | adapter->curr_iface_comb.p2p_intf++; | ||
| 842 | dev->ieee80211_ptr->iftype = type; | ||
| 843 | |||
| 844 | return 0; | ||
| 845 | } | ||
| 846 | |||
| 847 | static int | ||
| 848 | mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, | ||
| 849 | enum nl80211_iftype curr_iftype, | ||
| 850 | enum nl80211_iftype type, u32 *flags, | ||
| 851 | struct vif_params *params) | ||
| 852 | { | ||
| 853 | struct mwifiex_private *priv; | ||
| 854 | struct mwifiex_adapter *adapter; | ||
| 855 | |||
| 856 | priv = mwifiex_netdev_get_priv(dev); | ||
| 857 | |||
| 858 | if (!priv) | ||
| 859 | return -1; | ||
| 860 | |||
| 861 | adapter = priv->adapter; | ||
| 862 | |||
| 863 | if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT && | ||
| 864 | curr_iftype != NL80211_IFTYPE_P2P_GO) && | ||
| 865 | (adapter->curr_iface_comb.sta_intf == | ||
| 866 | adapter->iface_limit.sta_intf)) { | ||
| 867 | dev_err(adapter->dev, | ||
| 868 | "cannot create multiple station/adhoc ifaces\n"); | ||
| 869 | return -1; | ||
| 870 | } | ||
| 871 | |||
| 872 | if (type == NL80211_IFTYPE_STATION) | ||
| 873 | dev_notice(adapter->dev, | ||
| 874 | "%s: changing role to station\n", dev->name); | ||
| 875 | else | ||
| 876 | dev_notice(adapter->dev, | ||
| 877 | "%s: changing role to adhoc\n", dev->name); | ||
| 878 | |||
| 879 | if (mwifiex_deinit_priv_params(priv)) | ||
| 880 | return -1; | ||
| 881 | if (mwifiex_init_new_priv_params(priv, dev, type)) | ||
| 882 | return -1; | ||
| 883 | if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
| 884 | HostCmd_ACT_GEN_SET, 0, NULL, true)) | ||
| 885 | return -1; | ||
| 886 | if (mwifiex_sta_init_cmd(priv, false, false)) | ||
| 887 | return -1; | ||
| 888 | |||
| 889 | switch (curr_iftype) { | ||
| 890 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 891 | case NL80211_IFTYPE_P2P_GO: | ||
| 892 | adapter->curr_iface_comb.p2p_intf--; | ||
| 893 | break; | ||
| 894 | case NL80211_IFTYPE_AP: | ||
| 895 | adapter->curr_iface_comb.uap_intf--; | ||
| 896 | break; | ||
| 897 | default: | ||
| 898 | break; | ||
| 899 | } | ||
| 735 | 900 | ||
| 901 | adapter->curr_iface_comb.sta_intf++; | ||
| 902 | dev->ieee80211_ptr->iftype = type; | ||
| 736 | return 0; | 903 | return 0; |
| 737 | } | 904 | } |
| 738 | 905 | ||
| 906 | static int | ||
| 907 | mwifiex_change_vif_to_ap(struct net_device *dev, | ||
| 908 | enum nl80211_iftype curr_iftype, | ||
| 909 | enum nl80211_iftype type, u32 *flags, | ||
| 910 | struct vif_params *params) | ||
| 911 | { | ||
| 912 | struct mwifiex_private *priv; | ||
| 913 | struct mwifiex_adapter *adapter; | ||
| 914 | |||
| 915 | priv = mwifiex_netdev_get_priv(dev); | ||
| 916 | |||
| 917 | if (!priv) | ||
| 918 | return -1; | ||
| 919 | |||
| 920 | adapter = priv->adapter; | ||
| 921 | |||
| 922 | if (adapter->curr_iface_comb.uap_intf == | ||
| 923 | adapter->iface_limit.uap_intf) { | ||
| 924 | dev_err(adapter->dev, | ||
| 925 | "cannot create multiple AP ifaces\n"); | ||
| 926 | return -1; | ||
| 927 | } | ||
| 928 | |||
| 929 | dev_notice(adapter->dev, "%s: changing role to AP\n", dev->name); | ||
| 930 | |||
| 931 | if (mwifiex_deinit_priv_params(priv)) | ||
| 932 | return -1; | ||
| 933 | if (mwifiex_init_new_priv_params(priv, dev, type)) | ||
| 934 | return -1; | ||
| 935 | if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
| 936 | HostCmd_ACT_GEN_SET, 0, NULL, true)) | ||
| 937 | return -1; | ||
| 938 | if (mwifiex_sta_init_cmd(priv, false, false)) | ||
| 939 | return -1; | ||
| 940 | |||
| 941 | switch (curr_iftype) { | ||
| 942 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 943 | case NL80211_IFTYPE_P2P_GO: | ||
| 944 | adapter->curr_iface_comb.p2p_intf--; | ||
| 945 | break; | ||
| 946 | case NL80211_IFTYPE_STATION: | ||
| 947 | case NL80211_IFTYPE_ADHOC: | ||
| 948 | adapter->curr_iface_comb.sta_intf--; | ||
| 949 | break; | ||
| 950 | default: | ||
| 951 | break; | ||
| 952 | } | ||
| 953 | |||
| 954 | adapter->curr_iface_comb.uap_intf++; | ||
| 955 | dev->ieee80211_ptr->iftype = type; | ||
| 956 | return 0; | ||
| 957 | } | ||
| 739 | /* | 958 | /* |
| 740 | * CFG802.11 operation handler to change interface type. | 959 | * CFG802.11 operation handler to change interface type. |
| 741 | */ | 960 | */ |
| @@ -745,19 +964,32 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
| 745 | enum nl80211_iftype type, u32 *flags, | 964 | enum nl80211_iftype type, u32 *flags, |
| 746 | struct vif_params *params) | 965 | struct vif_params *params) |
| 747 | { | 966 | { |
| 748 | int ret; | ||
| 749 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 967 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 968 | enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype; | ||
| 750 | 969 | ||
| 751 | switch (dev->ieee80211_ptr->iftype) { | 970 | switch (curr_iftype) { |
| 752 | case NL80211_IFTYPE_ADHOC: | 971 | case NL80211_IFTYPE_ADHOC: |
| 753 | switch (type) { | 972 | switch (type) { |
| 754 | case NL80211_IFTYPE_STATION: | 973 | case NL80211_IFTYPE_STATION: |
| 755 | break; | 974 | priv->bss_mode = type; |
| 975 | priv->sec_info.authentication_mode = | ||
| 976 | NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
| 977 | dev->ieee80211_ptr->iftype = type; | ||
| 978 | mwifiex_deauthenticate(priv, NULL); | ||
| 979 | return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
| 980 | HostCmd_ACT_GEN_SET, 0, NULL, | ||
| 981 | true); | ||
| 982 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 983 | case NL80211_IFTYPE_P2P_GO: | ||
| 984 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, | ||
| 985 | type, flags, params); | ||
| 986 | case NL80211_IFTYPE_AP: | ||
| 987 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, | ||
| 988 | flags, params); | ||
| 756 | case NL80211_IFTYPE_UNSPECIFIED: | 989 | case NL80211_IFTYPE_UNSPECIFIED: |
| 757 | wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); | 990 | wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); |
| 758 | case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ | 991 | case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ |
| 759 | return 0; | 992 | return 0; |
| 760 | case NL80211_IFTYPE_AP: | ||
| 761 | default: | 993 | default: |
| 762 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | 994 | wiphy_err(wiphy, "%s: changing to %d not supported\n", |
| 763 | dev->name, type); | 995 | dev->name, type); |
| @@ -767,22 +999,25 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
| 767 | case NL80211_IFTYPE_STATION: | 999 | case NL80211_IFTYPE_STATION: |
| 768 | switch (type) { | 1000 | switch (type) { |
| 769 | case NL80211_IFTYPE_ADHOC: | 1001 | case NL80211_IFTYPE_ADHOC: |
| 770 | break; | 1002 | priv->bss_mode = type; |
| 771 | case NL80211_IFTYPE_P2P_CLIENT: | 1003 | priv->sec_info.authentication_mode = |
| 772 | if (mwifiex_cfg80211_init_p2p_client(priv)) | 1004 | NL80211_AUTHTYPE_OPEN_SYSTEM; |
| 773 | return -EFAULT; | ||
| 774 | dev->ieee80211_ptr->iftype = type; | 1005 | dev->ieee80211_ptr->iftype = type; |
| 775 | return 0; | 1006 | mwifiex_deauthenticate(priv, NULL); |
| 1007 | return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
| 1008 | HostCmd_ACT_GEN_SET, 0, NULL, | ||
| 1009 | true); | ||
| 1010 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 776 | case NL80211_IFTYPE_P2P_GO: | 1011 | case NL80211_IFTYPE_P2P_GO: |
| 777 | if (mwifiex_cfg80211_init_p2p_go(priv)) | 1012 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, |
| 778 | return -EFAULT; | 1013 | type, flags, params); |
| 779 | dev->ieee80211_ptr->iftype = type; | 1014 | case NL80211_IFTYPE_AP: |
| 780 | return 0; | 1015 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, |
| 1016 | flags, params); | ||
| 781 | case NL80211_IFTYPE_UNSPECIFIED: | 1017 | case NL80211_IFTYPE_UNSPECIFIED: |
| 782 | wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); | 1018 | wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); |
| 783 | case NL80211_IFTYPE_STATION: /* This shouldn't happen */ | 1019 | case NL80211_IFTYPE_STATION: /* This shouldn't happen */ |
| 784 | return 0; | 1020 | return 0; |
| 785 | case NL80211_IFTYPE_AP: | ||
| 786 | default: | 1021 | default: |
| 787 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | 1022 | wiphy_err(wiphy, "%s: changing to %d not supported\n", |
| 788 | dev->name, type); | 1023 | dev->name, type); |
| @@ -791,12 +1026,20 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
| 791 | break; | 1026 | break; |
| 792 | case NL80211_IFTYPE_AP: | 1027 | case NL80211_IFTYPE_AP: |
| 793 | switch (type) { | 1028 | switch (type) { |
| 1029 | case NL80211_IFTYPE_ADHOC: | ||
| 1030 | case NL80211_IFTYPE_STATION: | ||
| 1031 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, | ||
| 1032 | type, flags, | ||
| 1033 | params); | ||
| 1034 | break; | ||
| 1035 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 1036 | case NL80211_IFTYPE_P2P_GO: | ||
| 1037 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, | ||
| 1038 | type, flags, params); | ||
| 794 | case NL80211_IFTYPE_UNSPECIFIED: | 1039 | case NL80211_IFTYPE_UNSPECIFIED: |
| 795 | wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); | 1040 | wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); |
| 796 | case NL80211_IFTYPE_AP: /* This shouldn't happen */ | 1041 | case NL80211_IFTYPE_AP: /* This shouldn't happen */ |
| 797 | return 0; | 1042 | return 0; |
| 798 | case NL80211_IFTYPE_ADHOC: | ||
| 799 | case NL80211_IFTYPE_STATION: | ||
| 800 | default: | 1043 | default: |
| 801 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | 1044 | wiphy_err(wiphy, "%s: changing to %d not supported\n", |
| 802 | dev->name, type); | 1045 | dev->name, type); |
| @@ -807,11 +1050,30 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
| 807 | case NL80211_IFTYPE_P2P_GO: | 1050 | case NL80211_IFTYPE_P2P_GO: |
| 808 | switch (type) { | 1051 | switch (type) { |
| 809 | case NL80211_IFTYPE_STATION: | 1052 | case NL80211_IFTYPE_STATION: |
| 810 | if (mwifiex_cfg80211_deinit_p2p(priv)) | 1053 | if (mwifiex_cfg80211_init_p2p_client(priv)) |
| 811 | return -EFAULT; | 1054 | return -EFAULT; |
| 812 | dev->ieee80211_ptr->iftype = type; | 1055 | dev->ieee80211_ptr->iftype = type; |
| 1056 | break; | ||
| 1057 | case NL80211_IFTYPE_ADHOC: | ||
| 1058 | if (mwifiex_cfg80211_deinit_p2p(priv)) | ||
| 1059 | return -EFAULT; | ||
| 1060 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, | ||
| 1061 | type, flags, | ||
| 1062 | params); | ||
| 1063 | break; | ||
| 1064 | case NL80211_IFTYPE_AP: | ||
| 1065 | if (mwifiex_cfg80211_deinit_p2p(priv)) | ||
| 1066 | return -EFAULT; | ||
| 1067 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, | ||
| 1068 | flags, params); | ||
| 1069 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 1070 | wiphy_warn(wiphy, "%s: kept type as P2P\n", dev->name); | ||
| 1071 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 1072 | case NL80211_IFTYPE_P2P_GO: | ||
| 813 | return 0; | 1073 | return 0; |
| 814 | default: | 1074 | default: |
| 1075 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
| 1076 | dev->name, type); | ||
| 815 | return -EOPNOTSUPP; | 1077 | return -EOPNOTSUPP; |
| 816 | } | 1078 | } |
| 817 | break; | 1079 | break; |
| @@ -821,16 +1083,8 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
| 821 | return -EOPNOTSUPP; | 1083 | return -EOPNOTSUPP; |
| 822 | } | 1084 | } |
| 823 | 1085 | ||
| 824 | dev->ieee80211_ptr->iftype = type; | ||
| 825 | priv->bss_mode = type; | ||
| 826 | mwifiex_deauthenticate(priv, NULL); | ||
| 827 | |||
| 828 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
| 829 | |||
| 830 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
| 831 | HostCmd_ACT_GEN_SET, 0, NULL, true); | ||
| 832 | 1086 | ||
| 833 | return ret; | 1087 | return 0; |
| 834 | } | 1088 | } |
| 835 | 1089 | ||
| 836 | static void | 1090 | static void |
| @@ -856,16 +1110,16 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, | |||
| 856 | /* HT or VHT */ | 1110 | /* HT or VHT */ |
| 857 | switch (tx_htinfo & (BIT(3) | BIT(2))) { | 1111 | switch (tx_htinfo & (BIT(3) | BIT(2))) { |
| 858 | case 0: | 1112 | case 0: |
| 859 | /* This will be 20MHz */ | 1113 | rate->bw = RATE_INFO_BW_20; |
| 860 | break; | 1114 | break; |
| 861 | case (BIT(2)): | 1115 | case (BIT(2)): |
| 862 | rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 1116 | rate->bw = RATE_INFO_BW_40; |
| 863 | break; | 1117 | break; |
| 864 | case (BIT(3)): | 1118 | case (BIT(3)): |
| 865 | rate->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 1119 | rate->bw = RATE_INFO_BW_80; |
| 866 | break; | 1120 | break; |
| 867 | case (BIT(3) | BIT(2)): | 1121 | case (BIT(3) | BIT(2)): |
| 868 | rate->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 1122 | rate->bw = RATE_INFO_BW_160; |
| 869 | break; | 1123 | break; |
| 870 | } | 1124 | } |
| 871 | 1125 | ||
| @@ -885,8 +1139,9 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, | |||
| 885 | if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { | 1139 | if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { |
| 886 | rate->mcs = priv->tx_rate; | 1140 | rate->mcs = priv->tx_rate; |
| 887 | rate->flags |= RATE_INFO_FLAGS_MCS; | 1141 | rate->flags |= RATE_INFO_FLAGS_MCS; |
| 1142 | rate->bw = RATE_INFO_BW_20; | ||
| 888 | if (tx_htinfo & BIT(1)) | 1143 | if (tx_htinfo & BIT(1)) |
| 889 | rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 1144 | rate->bw = RATE_INFO_BW_40; |
| 890 | if (tx_htinfo & BIT(2)) | 1145 | if (tx_htinfo & BIT(2)) |
| 891 | rate->flags |= RATE_INFO_FLAGS_SHORT_GI; | 1146 | rate->flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 892 | } | 1147 | } |
| @@ -910,10 +1165,10 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
| 910 | { | 1165 | { |
| 911 | u32 rate; | 1166 | u32 rate; |
| 912 | 1167 | ||
| 913 | sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES | | 1168 | sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES) | |
| 914 | STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS | | 1169 | BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) | |
| 915 | STATION_INFO_TX_BITRATE | | 1170 | BIT(NL80211_STA_INFO_TX_BITRATE) | |
| 916 | STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; | 1171 | BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG); |
| 917 | 1172 | ||
| 918 | /* Get signal information from the firmware */ | 1173 | /* Get signal information from the firmware */ |
| 919 | if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, | 1174 | if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, |
| @@ -944,7 +1199,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
| 944 | sinfo->txrate.legacy = rate * 5; | 1199 | sinfo->txrate.legacy = rate * 5; |
| 945 | 1200 | ||
| 946 | if (priv->bss_mode == NL80211_IFTYPE_STATION) { | 1201 | if (priv->bss_mode == NL80211_IFTYPE_STATION) { |
| 947 | sinfo->filled |= STATION_INFO_BSS_PARAM; | 1202 | sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); |
| 948 | sinfo->bss_param.flags = 0; | 1203 | sinfo->bss_param.flags = 0; |
| 949 | if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap & | 1204 | if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap & |
| 950 | WLAN_CAPABILITY_SHORT_PREAMBLE) | 1205 | WLAN_CAPABILITY_SHORT_PREAMBLE) |
| @@ -1037,10 +1292,11 @@ mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, | |||
| 1037 | survey->channel = ieee80211_get_channel(wiphy, | 1292 | survey->channel = ieee80211_get_channel(wiphy, |
| 1038 | ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band)); | 1293 | ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band)); |
| 1039 | survey->filled = SURVEY_INFO_NOISE_DBM | | 1294 | survey->filled = SURVEY_INFO_NOISE_DBM | |
| 1040 | SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY; | 1295 | SURVEY_INFO_TIME | |
| 1296 | SURVEY_INFO_TIME_BUSY; | ||
| 1041 | survey->noise = pchan_stats[idx].noise; | 1297 | survey->noise = pchan_stats[idx].noise; |
| 1042 | survey->channel_time = pchan_stats[idx].cca_scan_dur; | 1298 | survey->time = pchan_stats[idx].cca_scan_dur; |
| 1043 | survey->channel_time_busy = pchan_stats[idx].cca_busy_dur; | 1299 | survey->time_busy = pchan_stats[idx].cca_busy_dur; |
| 1044 | 1300 | ||
| 1045 | return 0; | 1301 | return 0; |
| 1046 | } | 1302 | } |
| @@ -1395,10 +1651,13 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1395 | { | 1651 | { |
| 1396 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1652 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 1397 | 1653 | ||
| 1654 | mwifiex_abort_cac(priv); | ||
| 1655 | |||
| 1398 | if (mwifiex_del_mgmt_ies(priv)) | 1656 | if (mwifiex_del_mgmt_ies(priv)) |
| 1399 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); | 1657 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); |
| 1400 | 1658 | ||
| 1401 | priv->ap_11n_enabled = 0; | 1659 | priv->ap_11n_enabled = 0; |
| 1660 | memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg)); | ||
| 1402 | 1661 | ||
| 1403 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | 1662 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, |
| 1404 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | 1663 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { |
| @@ -1420,12 +1679,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
| 1420 | { | 1679 | { |
| 1421 | struct mwifiex_uap_bss_param *bss_cfg; | 1680 | struct mwifiex_uap_bss_param *bss_cfg; |
| 1422 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1681 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 1423 | u8 config_bands = 0; | ||
| 1424 | 1682 | ||
| 1425 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) | 1683 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) |
| 1426 | return -1; | 1684 | return -1; |
| 1427 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) | ||
| 1428 | return -1; | ||
| 1429 | 1685 | ||
| 1430 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | 1686 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); |
| 1431 | if (!bss_cfg) | 1687 | if (!bss_cfg) |
| @@ -1442,6 +1698,11 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
| 1442 | memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); | 1698 | memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); |
| 1443 | bss_cfg->ssid.ssid_len = params->ssid_len; | 1699 | bss_cfg->ssid.ssid_len = params->ssid_len; |
| 1444 | } | 1700 | } |
| 1701 | if (params->inactivity_timeout > 0) { | ||
| 1702 | /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ | ||
| 1703 | bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout; | ||
| 1704 | bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; | ||
| 1705 | } | ||
| 1445 | 1706 | ||
| 1446 | switch (params->hidden_ssid) { | 1707 | switch (params->hidden_ssid) { |
| 1447 | case NL80211_HIDDEN_SSID_NOT_IN_USE: | 1708 | case NL80211_HIDDEN_SSID_NOT_IN_USE: |
| @@ -1457,33 +1718,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
| 1457 | return -EINVAL; | 1718 | return -EINVAL; |
| 1458 | } | 1719 | } |
| 1459 | 1720 | ||
| 1460 | bss_cfg->channel = ieee80211_frequency_to_channel( | 1721 | mwifiex_uap_set_channel(bss_cfg, params->chandef); |
| 1461 | params->chandef.chan->center_freq); | ||
| 1462 | |||
| 1463 | /* Set appropriate bands */ | ||
| 1464 | if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { | ||
| 1465 | bss_cfg->band_cfg = BAND_CONFIG_BG; | ||
| 1466 | config_bands = BAND_B | BAND_G; | ||
| 1467 | |||
| 1468 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
| 1469 | config_bands |= BAND_GN; | ||
| 1470 | } else { | ||
| 1471 | bss_cfg->band_cfg = BAND_CONFIG_A; | ||
| 1472 | config_bands = BAND_A; | ||
| 1473 | |||
| 1474 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
| 1475 | config_bands |= BAND_AN; | ||
| 1476 | |||
| 1477 | if (params->chandef.width > NL80211_CHAN_WIDTH_40) | ||
| 1478 | config_bands |= BAND_AAC; | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | if (!((config_bands | priv->adapter->fw_bands) & | ||
| 1482 | ~priv->adapter->fw_bands)) | ||
| 1483 | priv->adapter->config_bands = config_bands; | ||
| 1484 | |||
| 1485 | mwifiex_set_uap_rates(bss_cfg, params); | 1722 | mwifiex_set_uap_rates(bss_cfg, params); |
| 1486 | mwifiex_send_domain_info_cmd_fw(wiphy); | ||
| 1487 | 1723 | ||
| 1488 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { | 1724 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { |
| 1489 | kfree(bss_cfg); | 1725 | kfree(bss_cfg); |
| @@ -1506,45 +1742,29 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
| 1506 | 1742 | ||
| 1507 | mwifiex_set_wmm_params(priv, bss_cfg, params); | 1743 | mwifiex_set_wmm_params(priv, bss_cfg, params); |
| 1508 | 1744 | ||
| 1509 | if (params->inactivity_timeout > 0) { | 1745 | if (mwifiex_is_11h_active(priv) && |
| 1510 | /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ | 1746 | !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef, |
| 1511 | bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout; | 1747 | priv->bss_mode)) { |
| 1512 | bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; | 1748 | dev_dbg(priv->adapter->dev, "Disable 11h extensions in FW\n"); |
| 1749 | if (mwifiex_11h_activate(priv, false)) { | ||
| 1750 | dev_err(priv->adapter->dev, | ||
| 1751 | "Failed to disable 11h extensions!!"); | ||
| 1752 | return -1; | ||
| 1753 | } | ||
| 1754 | priv->state_11h.is_11h_active = true; | ||
| 1513 | } | 1755 | } |
| 1514 | 1756 | ||
| 1515 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | 1757 | if (mwifiex_config_start_uap(priv, bss_cfg)) { |
| 1516 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | 1758 | wiphy_err(wiphy, "Failed to start AP\n"); |
| 1517 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
| 1518 | kfree(bss_cfg); | 1759 | kfree(bss_cfg); |
| 1519 | return -1; | 1760 | return -1; |
| 1520 | } | 1761 | } |
| 1521 | 1762 | ||
| 1522 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | 1763 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) |
| 1523 | HostCmd_ACT_GEN_SET, | ||
| 1524 | UAP_BSS_PARAMS_I, bss_cfg, false)) { | ||
| 1525 | wiphy_err(wiphy, "Failed to set the SSID\n"); | ||
| 1526 | kfree(bss_cfg); | ||
| 1527 | return -1; | 1764 | return -1; |
| 1528 | } | ||
| 1529 | 1765 | ||
| 1766 | memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); | ||
| 1530 | kfree(bss_cfg); | 1767 | kfree(bss_cfg); |
| 1531 | |||
| 1532 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, | ||
| 1533 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { | ||
| 1534 | wiphy_err(wiphy, "Failed to start the BSS\n"); | ||
| 1535 | return -1; | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | if (priv->sec_info.wep_enabled) | ||
| 1539 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; | ||
| 1540 | else | ||
| 1541 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | ||
| 1542 | |||
| 1543 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, | ||
| 1544 | HostCmd_ACT_GEN_SET, 0, | ||
| 1545 | &priv->curr_pkt_filter, true)) | ||
| 1546 | return -1; | ||
| 1547 | |||
| 1548 | return 0; | 1768 | return 0; |
| 1549 | } | 1769 | } |
| 1550 | 1770 | ||
| @@ -1603,15 +1823,15 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
| 1603 | ie_len = ie_buf[1] + sizeof(struct ieee_types_header); | 1823 | ie_len = ie_buf[1] + sizeof(struct ieee_types_header); |
| 1604 | 1824 | ||
| 1605 | band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | 1825 | band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); |
| 1606 | chan = __ieee80211_get_channel(priv->wdev->wiphy, | 1826 | chan = __ieee80211_get_channel(priv->wdev.wiphy, |
| 1607 | ieee80211_channel_to_frequency(bss_info.bss_chan, | 1827 | ieee80211_channel_to_frequency(bss_info.bss_chan, |
| 1608 | band)); | 1828 | band)); |
| 1609 | 1829 | ||
| 1610 | bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, | 1830 | bss = cfg80211_inform_bss(priv->wdev.wiphy, chan, |
| 1611 | CFG80211_BSS_FTYPE_UNKNOWN, | 1831 | CFG80211_BSS_FTYPE_UNKNOWN, |
| 1612 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, | 1832 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, |
| 1613 | 0, ie_buf, ie_len, 0, GFP_KERNEL); | 1833 | 0, ie_buf, ie_len, 0, GFP_KERNEL); |
| 1614 | cfg80211_put_bss(priv->wdev->wiphy, bss); | 1834 | cfg80211_put_bss(priv->wdev.wiphy, bss); |
| 1615 | memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); | 1835 | memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); |
| 1616 | 1836 | ||
| 1617 | return 0; | 1837 | return 0; |
| @@ -1732,12 +1952,12 @@ done: | |||
| 1732 | 1952 | ||
| 1733 | /* Find the BSS we want using available scan results */ | 1953 | /* Find the BSS we want using available scan results */ |
| 1734 | if (mode == NL80211_IFTYPE_ADHOC) | 1954 | if (mode == NL80211_IFTYPE_ADHOC) |
| 1735 | bss = cfg80211_get_bss(priv->wdev->wiphy, channel, | 1955 | bss = cfg80211_get_bss(priv->wdev.wiphy, channel, |
| 1736 | bssid, ssid, ssid_len, | 1956 | bssid, ssid, ssid_len, |
| 1737 | WLAN_CAPABILITY_IBSS, | 1957 | WLAN_CAPABILITY_IBSS, |
| 1738 | WLAN_CAPABILITY_IBSS); | 1958 | WLAN_CAPABILITY_IBSS); |
| 1739 | else | 1959 | else |
| 1740 | bss = cfg80211_get_bss(priv->wdev->wiphy, channel, | 1960 | bss = cfg80211_get_bss(priv->wdev.wiphy, channel, |
| 1741 | bssid, ssid, ssid_len, | 1961 | bssid, ssid, ssid_len, |
| 1742 | WLAN_CAPABILITY_ESS, | 1962 | WLAN_CAPABILITY_ESS, |
| 1743 | WLAN_CAPABILITY_ESS); | 1963 | WLAN_CAPABILITY_ESS); |
| @@ -1784,6 +2004,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
| 1784 | struct cfg80211_connect_params *sme) | 2004 | struct cfg80211_connect_params *sme) |
| 1785 | { | 2005 | { |
| 1786 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 2006 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 2007 | struct mwifiex_adapter *adapter = priv->adapter; | ||
| 1787 | int ret; | 2008 | int ret; |
| 1788 | 2009 | ||
| 1789 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) { | 2010 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) { |
| @@ -1793,11 +2014,18 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
| 1793 | return -EINVAL; | 2014 | return -EINVAL; |
| 1794 | } | 2015 | } |
| 1795 | 2016 | ||
| 1796 | if (priv->wdev && priv->wdev->current_bss) { | 2017 | if (priv->wdev.current_bss) { |
| 1797 | wiphy_warn(wiphy, "%s: already connected\n", dev->name); | 2018 | wiphy_warn(wiphy, "%s: already connected\n", dev->name); |
| 1798 | return -EALREADY; | 2019 | return -EALREADY; |
| 1799 | } | 2020 | } |
| 1800 | 2021 | ||
| 2022 | if (adapter->surprise_removed || adapter->is_cmd_timedout) { | ||
| 2023 | wiphy_err(wiphy, | ||
| 2024 | "%s: Ignore connection. Card removed or FW in bad state\n", | ||
| 2025 | dev->name); | ||
| 2026 | return -EFAULT; | ||
| 2027 | } | ||
| 2028 | |||
| 1801 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", | 2029 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", |
| 1802 | (char *) sme->ssid, sme->bssid); | 2030 | (char *) sme->ssid, sme->bssid); |
| 1803 | 2031 | ||
| @@ -1844,7 +2072,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
| 1844 | static int mwifiex_set_ibss_params(struct mwifiex_private *priv, | 2072 | static int mwifiex_set_ibss_params(struct mwifiex_private *priv, |
| 1845 | struct cfg80211_ibss_params *params) | 2073 | struct cfg80211_ibss_params *params) |
| 1846 | { | 2074 | { |
| 1847 | struct wiphy *wiphy = priv->wdev->wiphy; | 2075 | struct wiphy *wiphy = priv->wdev.wiphy; |
| 1848 | struct mwifiex_adapter *adapter = priv->adapter; | 2076 | struct mwifiex_adapter *adapter = priv->adapter; |
| 1849 | int index = 0, i; | 2077 | int index = 0, i; |
| 1850 | u8 config_bands = 0; | 2078 | u8 config_bands = 0; |
| @@ -2169,6 +2397,7 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
| 2169 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 2397 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
| 2170 | } | 2398 | } |
| 2171 | 2399 | ||
| 2400 | #define MWIFIEX_MAX_WQ_LEN 30 | ||
| 2172 | /* | 2401 | /* |
| 2173 | * create a new virtual interface with the given name | 2402 | * create a new virtual interface with the given name |
| 2174 | */ | 2403 | */ |
| @@ -2182,7 +2411,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2182 | struct mwifiex_private *priv; | 2411 | struct mwifiex_private *priv; |
| 2183 | struct net_device *dev; | 2412 | struct net_device *dev; |
| 2184 | void *mdev_priv; | 2413 | void *mdev_priv; |
| 2185 | struct wireless_dev *wdev; | 2414 | char dfs_cac_str[MWIFIEX_MAX_WQ_LEN], dfs_chsw_str[MWIFIEX_MAX_WQ_LEN]; |
| 2186 | 2415 | ||
| 2187 | if (!adapter) | 2416 | if (!adapter) |
| 2188 | return ERR_PTR(-EFAULT); | 2417 | return ERR_PTR(-EFAULT); |
| @@ -2191,20 +2420,22 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2191 | case NL80211_IFTYPE_UNSPECIFIED: | 2420 | case NL80211_IFTYPE_UNSPECIFIED: |
| 2192 | case NL80211_IFTYPE_STATION: | 2421 | case NL80211_IFTYPE_STATION: |
| 2193 | case NL80211_IFTYPE_ADHOC: | 2422 | case NL80211_IFTYPE_ADHOC: |
| 2194 | priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; | 2423 | if (adapter->curr_iface_comb.sta_intf == |
| 2195 | if (priv->bss_mode) { | 2424 | adapter->iface_limit.sta_intf) { |
| 2196 | wiphy_err(wiphy, | 2425 | wiphy_err(wiphy, |
| 2197 | "cannot create multiple sta/adhoc ifaces\n"); | 2426 | "cannot create multiple sta/adhoc ifaces\n"); |
| 2198 | return ERR_PTR(-EINVAL); | 2427 | return ERR_PTR(-EINVAL); |
| 2199 | } | 2428 | } |
| 2200 | 2429 | ||
| 2201 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 2430 | priv = mwifiex_get_unused_priv(adapter); |
| 2202 | if (!wdev) | 2431 | if (!priv) { |
| 2203 | return ERR_PTR(-ENOMEM); | 2432 | wiphy_err(wiphy, |
| 2433 | "could not get free private struct\n"); | ||
| 2434 | return ERR_PTR(-EFAULT); | ||
| 2435 | } | ||
| 2204 | 2436 | ||
| 2205 | wdev->wiphy = wiphy; | 2437 | priv->wdev.wiphy = wiphy; |
| 2206 | priv->wdev = wdev; | 2438 | priv->wdev.iftype = NL80211_IFTYPE_STATION; |
| 2207 | wdev->iftype = NL80211_IFTYPE_STATION; | ||
| 2208 | 2439 | ||
| 2209 | if (type == NL80211_IFTYPE_UNSPECIFIED) | 2440 | if (type == NL80211_IFTYPE_UNSPECIFIED) |
| 2210 | priv->bss_mode = NL80211_IFTYPE_STATION; | 2441 | priv->bss_mode = NL80211_IFTYPE_STATION; |
| @@ -2219,20 +2450,22 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2219 | 2450 | ||
| 2220 | break; | 2451 | break; |
| 2221 | case NL80211_IFTYPE_AP: | 2452 | case NL80211_IFTYPE_AP: |
| 2222 | priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP]; | 2453 | if (adapter->curr_iface_comb.uap_intf == |
| 2223 | 2454 | adapter->iface_limit.uap_intf) { | |
| 2224 | if (priv->bss_mode) { | 2455 | wiphy_err(wiphy, |
| 2225 | wiphy_err(wiphy, "Can't create multiple AP interfaces"); | 2456 | "cannot create multiple AP ifaces\n"); |
| 2226 | return ERR_PTR(-EINVAL); | 2457 | return ERR_PTR(-EINVAL); |
| 2227 | } | 2458 | } |
| 2228 | 2459 | ||
| 2229 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 2460 | priv = mwifiex_get_unused_priv(adapter); |
| 2230 | if (!wdev) | 2461 | if (!priv) { |
| 2231 | return ERR_PTR(-ENOMEM); | 2462 | wiphy_err(wiphy, |
| 2463 | "could not get free private struct\n"); | ||
| 2464 | return ERR_PTR(-EFAULT); | ||
| 2465 | } | ||
| 2232 | 2466 | ||
| 2233 | priv->wdev = wdev; | 2467 | priv->wdev.wiphy = wiphy; |
| 2234 | wdev->wiphy = wiphy; | 2468 | priv->wdev.iftype = NL80211_IFTYPE_AP; |
| 2235 | wdev->iftype = NL80211_IFTYPE_AP; | ||
| 2236 | 2469 | ||
| 2237 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; | 2470 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; |
| 2238 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | 2471 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; |
| @@ -2244,24 +2477,25 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2244 | 2477 | ||
| 2245 | break; | 2478 | break; |
| 2246 | case NL80211_IFTYPE_P2P_CLIENT: | 2479 | case NL80211_IFTYPE_P2P_CLIENT: |
| 2247 | priv = adapter->priv[MWIFIEX_BSS_TYPE_P2P]; | 2480 | if (adapter->curr_iface_comb.p2p_intf == |
| 2248 | 2481 | adapter->iface_limit.p2p_intf) { | |
| 2249 | if (priv->bss_mode) { | 2482 | wiphy_err(wiphy, |
| 2250 | wiphy_err(wiphy, "Can't create multiple P2P ifaces"); | 2483 | "cannot create multiple P2P ifaces\n"); |
| 2251 | return ERR_PTR(-EINVAL); | 2484 | return ERR_PTR(-EINVAL); |
| 2252 | } | 2485 | } |
| 2253 | 2486 | ||
| 2254 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 2487 | priv = mwifiex_get_unused_priv(adapter); |
| 2255 | if (!wdev) | 2488 | if (!priv) { |
| 2256 | return ERR_PTR(-ENOMEM); | 2489 | wiphy_err(wiphy, |
| 2257 | 2490 | "could not get free private struct\n"); | |
| 2258 | priv->wdev = wdev; | 2491 | return ERR_PTR(-EFAULT); |
| 2259 | wdev->wiphy = wiphy; | 2492 | } |
| 2260 | 2493 | ||
| 2494 | priv->wdev.wiphy = wiphy; | ||
| 2261 | /* At start-up, wpa_supplicant tries to change the interface | 2495 | /* At start-up, wpa_supplicant tries to change the interface |
| 2262 | * to NL80211_IFTYPE_STATION if it is not managed mode. | 2496 | * to NL80211_IFTYPE_STATION if it is not managed mode. |
| 2263 | */ | 2497 | */ |
| 2264 | wdev->iftype = NL80211_IFTYPE_P2P_CLIENT; | 2498 | priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; |
| 2265 | priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT; | 2499 | priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT; |
| 2266 | 2500 | ||
| 2267 | /* Setting bss_type to P2P tells firmware that this interface | 2501 | /* Setting bss_type to P2P tells firmware that this interface |
| @@ -2277,8 +2511,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2277 | priv->bss_num = 0; | 2511 | priv->bss_num = 0; |
| 2278 | 2512 | ||
| 2279 | if (mwifiex_cfg80211_init_p2p_client(priv)) { | 2513 | if (mwifiex_cfg80211_init_p2p_client(priv)) { |
| 2280 | wdev = ERR_PTR(-EFAULT); | 2514 | memset(&priv->wdev, 0, sizeof(priv->wdev)); |
| 2281 | goto done; | 2515 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
| 2516 | return ERR_PTR(-EFAULT); | ||
| 2282 | } | 2517 | } |
| 2283 | 2518 | ||
| 2284 | break; | 2519 | break; |
| @@ -2292,9 +2527,10 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2292 | IEEE80211_NUM_ACS, 1); | 2527 | IEEE80211_NUM_ACS, 1); |
| 2293 | if (!dev) { | 2528 | if (!dev) { |
| 2294 | wiphy_err(wiphy, "no memory available for netdevice\n"); | 2529 | wiphy_err(wiphy, "no memory available for netdevice\n"); |
| 2530 | memset(&priv->wdev, 0, sizeof(priv->wdev)); | ||
| 2531 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
| 2295 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 2532 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
| 2296 | wdev = ERR_PTR(-ENOMEM); | 2533 | return ERR_PTR(-ENOMEM); |
| 2297 | goto done; | ||
| 2298 | } | 2534 | } |
| 2299 | 2535 | ||
| 2300 | mwifiex_init_priv_params(priv, dev); | 2536 | mwifiex_init_priv_params(priv, dev); |
| @@ -2314,7 +2550,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2314 | &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv); | 2550 | &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv); |
| 2315 | 2551 | ||
| 2316 | dev_net_set(dev, wiphy_net(wiphy)); | 2552 | dev_net_set(dev, wiphy_net(wiphy)); |
| 2317 | dev->ieee80211_ptr = priv->wdev; | 2553 | dev->ieee80211_ptr = &priv->wdev; |
| 2318 | dev->ieee80211_ptr->iftype = priv->bss_mode; | 2554 | dev->ieee80211_ptr->iftype = priv->bss_mode; |
| 2319 | memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); | 2555 | memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); |
| 2320 | SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); | 2556 | SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); |
| @@ -2335,10 +2571,47 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2335 | free_netdev(dev); | 2571 | free_netdev(dev); |
| 2336 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 2572 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
| 2337 | priv->netdev = NULL; | 2573 | priv->netdev = NULL; |
| 2338 | wdev = ERR_PTR(-EFAULT); | 2574 | memset(&priv->wdev, 0, sizeof(priv->wdev)); |
| 2339 | goto done; | 2575 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
| 2576 | return ERR_PTR(-EFAULT); | ||
| 2577 | } | ||
| 2578 | |||
| 2579 | strcpy(dfs_cac_str, "MWIFIEX_DFS_CAC"); | ||
| 2580 | strcat(dfs_cac_str, name); | ||
| 2581 | priv->dfs_cac_workqueue = alloc_workqueue(dfs_cac_str, | ||
| 2582 | WQ_HIGHPRI | | ||
| 2583 | WQ_MEM_RECLAIM | | ||
| 2584 | WQ_UNBOUND, 1); | ||
| 2585 | if (!priv->dfs_cac_workqueue) { | ||
| 2586 | wiphy_err(wiphy, "cannot register virtual network device\n"); | ||
| 2587 | free_netdev(dev); | ||
| 2588 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
| 2589 | priv->netdev = NULL; | ||
| 2590 | memset(&priv->wdev, 0, sizeof(priv->wdev)); | ||
| 2591 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
| 2592 | return ERR_PTR(-ENOMEM); | ||
| 2593 | } | ||
| 2594 | |||
| 2595 | INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue); | ||
| 2596 | |||
| 2597 | strcpy(dfs_chsw_str, "MWIFIEX_DFS_CHSW"); | ||
| 2598 | strcat(dfs_chsw_str, name); | ||
| 2599 | priv->dfs_chan_sw_workqueue = alloc_workqueue(dfs_chsw_str, | ||
| 2600 | WQ_HIGHPRI | WQ_UNBOUND | | ||
| 2601 | WQ_MEM_RECLAIM, 1); | ||
| 2602 | if (!priv->dfs_chan_sw_workqueue) { | ||
| 2603 | wiphy_err(wiphy, "cannot register virtual network device\n"); | ||
| 2604 | free_netdev(dev); | ||
| 2605 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | ||
| 2606 | priv->netdev = NULL; | ||
| 2607 | memset(&priv->wdev, 0, sizeof(priv->wdev)); | ||
| 2608 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | ||
| 2609 | return ERR_PTR(-ENOMEM); | ||
| 2340 | } | 2610 | } |
| 2341 | 2611 | ||
| 2612 | INIT_DELAYED_WORK(&priv->dfs_chan_sw_work, | ||
| 2613 | mwifiex_dfs_chan_sw_work_queue); | ||
| 2614 | |||
| 2342 | sema_init(&priv->async_sem, 1); | 2615 | sema_init(&priv->async_sem, 1); |
| 2343 | 2616 | ||
| 2344 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); | 2617 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); |
| @@ -2347,13 +2620,24 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
| 2347 | mwifiex_dev_debugfs_init(priv); | 2620 | mwifiex_dev_debugfs_init(priv); |
| 2348 | #endif | 2621 | #endif |
| 2349 | 2622 | ||
| 2350 | done: | 2623 | switch (type) { |
| 2351 | if (IS_ERR(wdev)) { | 2624 | case NL80211_IFTYPE_UNSPECIFIED: |
| 2352 | kfree(priv->wdev); | 2625 | case NL80211_IFTYPE_STATION: |
| 2353 | priv->wdev = NULL; | 2626 | case NL80211_IFTYPE_ADHOC: |
| 2627 | adapter->curr_iface_comb.sta_intf++; | ||
| 2628 | break; | ||
| 2629 | case NL80211_IFTYPE_AP: | ||
| 2630 | adapter->curr_iface_comb.uap_intf++; | ||
| 2631 | break; | ||
| 2632 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 2633 | adapter->curr_iface_comb.p2p_intf++; | ||
| 2634 | break; | ||
| 2635 | default: | ||
| 2636 | wiphy_err(wiphy, "type not supported\n"); | ||
| 2637 | return ERR_PTR(-EINVAL); | ||
| 2354 | } | 2638 | } |
| 2355 | 2639 | ||
| 2356 | return wdev; | 2640 | return &priv->wdev; |
| 2357 | } | 2641 | } |
| 2358 | EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); | 2642 | EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); |
| 2359 | 2643 | ||
| @@ -2363,12 +2647,13 @@ EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); | |||
| 2363 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | 2647 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) |
| 2364 | { | 2648 | { |
| 2365 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); | 2649 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); |
| 2650 | struct mwifiex_adapter *adapter = priv->adapter; | ||
| 2366 | 2651 | ||
| 2367 | #ifdef CONFIG_DEBUG_FS | 2652 | #ifdef CONFIG_DEBUG_FS |
| 2368 | mwifiex_dev_debugfs_remove(priv); | 2653 | mwifiex_dev_debugfs_remove(priv); |
| 2369 | #endif | 2654 | #endif |
| 2370 | 2655 | ||
| 2371 | mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); | 2656 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); |
| 2372 | 2657 | ||
| 2373 | if (netif_carrier_ok(priv->netdev)) | 2658 | if (netif_carrier_ok(priv->netdev)) |
| 2374 | netif_carrier_off(priv->netdev); | 2659 | netif_carrier_off(priv->netdev); |
| @@ -2376,14 +2661,42 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
| 2376 | if (wdev->netdev->reg_state == NETREG_REGISTERED) | 2661 | if (wdev->netdev->reg_state == NETREG_REGISTERED) |
| 2377 | unregister_netdevice(wdev->netdev); | 2662 | unregister_netdevice(wdev->netdev); |
| 2378 | 2663 | ||
| 2664 | if (priv->dfs_cac_workqueue) { | ||
| 2665 | flush_workqueue(priv->dfs_cac_workqueue); | ||
| 2666 | destroy_workqueue(priv->dfs_cac_workqueue); | ||
| 2667 | priv->dfs_cac_workqueue = NULL; | ||
| 2668 | } | ||
| 2669 | |||
| 2670 | if (priv->dfs_chan_sw_workqueue) { | ||
| 2671 | flush_workqueue(priv->dfs_chan_sw_workqueue); | ||
| 2672 | destroy_workqueue(priv->dfs_chan_sw_workqueue); | ||
| 2673 | priv->dfs_chan_sw_workqueue = NULL; | ||
| 2674 | } | ||
| 2379 | /* Clear the priv in adapter */ | 2675 | /* Clear the priv in adapter */ |
| 2380 | priv->netdev->ieee80211_ptr = NULL; | 2676 | priv->netdev->ieee80211_ptr = NULL; |
| 2381 | priv->netdev = NULL; | 2677 | priv->netdev = NULL; |
| 2382 | kfree(wdev); | 2678 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
| 2383 | priv->wdev = NULL; | ||
| 2384 | 2679 | ||
| 2385 | priv->media_connected = false; | 2680 | priv->media_connected = false; |
| 2386 | 2681 | ||
| 2682 | switch (priv->bss_mode) { | ||
| 2683 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 2684 | case NL80211_IFTYPE_STATION: | ||
| 2685 | case NL80211_IFTYPE_ADHOC: | ||
| 2686 | adapter->curr_iface_comb.sta_intf++; | ||
| 2687 | break; | ||
| 2688 | case NL80211_IFTYPE_AP: | ||
| 2689 | adapter->curr_iface_comb.uap_intf++; | ||
| 2690 | break; | ||
| 2691 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 2692 | case NL80211_IFTYPE_P2P_GO: | ||
| 2693 | adapter->curr_iface_comb.p2p_intf++; | ||
| 2694 | break; | ||
| 2695 | default: | ||
| 2696 | dev_err(adapter->dev, "del_virtual_intf: type not supported\n"); | ||
| 2697 | break; | ||
| 2698 | } | ||
| 2699 | |||
| 2387 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 2700 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
| 2388 | 2701 | ||
| 2389 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || | 2702 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || |
| @@ -2838,6 +3151,102 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 2838 | } | 3151 | } |
| 2839 | 3152 | ||
| 2840 | static int | 3153 | static int |
| 3154 | mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | ||
| 3155 | struct cfg80211_csa_settings *params) | ||
| 3156 | { | ||
| 3157 | struct ieee_types_header *chsw_ie; | ||
| 3158 | struct ieee80211_channel_sw_ie *channel_sw; | ||
| 3159 | int chsw_msec; | ||
| 3160 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
| 3161 | |||
| 3162 | if (priv->adapter->scan_processing) { | ||
| 3163 | dev_err(priv->adapter->dev, | ||
| 3164 | "radar detection: scan in process...\n"); | ||
| 3165 | return -EBUSY; | ||
| 3166 | } | ||
| 3167 | |||
| 3168 | if (priv->wdev.cac_started) | ||
| 3169 | return -EBUSY; | ||
| 3170 | |||
| 3171 | if (cfg80211_chandef_identical(¶ms->chandef, | ||
| 3172 | &priv->dfs_chandef)) | ||
| 3173 | return -EINVAL; | ||
| 3174 | |||
| 3175 | chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH, | ||
| 3176 | params->beacon_csa.tail, | ||
| 3177 | params->beacon_csa.tail_len); | ||
| 3178 | if (!chsw_ie) { | ||
| 3179 | dev_err(priv->adapter->dev, | ||
| 3180 | "Could not parse channel switch announcement IE\n"); | ||
| 3181 | return -EINVAL; | ||
| 3182 | } | ||
| 3183 | |||
| 3184 | channel_sw = (void *)(chsw_ie + 1); | ||
| 3185 | if (channel_sw->mode) { | ||
| 3186 | if (netif_carrier_ok(priv->netdev)) | ||
| 3187 | netif_carrier_off(priv->netdev); | ||
| 3188 | mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); | ||
| 3189 | } | ||
| 3190 | |||
| 3191 | if (mwifiex_del_mgmt_ies(priv)) | ||
| 3192 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); | ||
| 3193 | |||
| 3194 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon_csa)) { | ||
| 3195 | wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__); | ||
| 3196 | return -EFAULT; | ||
| 3197 | } | ||
| 3198 | |||
| 3199 | memcpy(&priv->dfs_chandef, ¶ms->chandef, sizeof(priv->dfs_chandef)); | ||
| 3200 | memcpy(&priv->beacon_after, ¶ms->beacon_after, | ||
| 3201 | sizeof(priv->beacon_after)); | ||
| 3202 | |||
| 3203 | chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100); | ||
| 3204 | queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work, | ||
| 3205 | msecs_to_jiffies(chsw_msec)); | ||
| 3206 | return 0; | ||
| 3207 | } | ||
| 3208 | |||
| 3209 | static int | ||
| 3210 | mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, | ||
| 3211 | struct net_device *dev, | ||
| 3212 | struct cfg80211_chan_def *chandef, | ||
| 3213 | u32 cac_time_ms) | ||
| 3214 | { | ||
| 3215 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
| 3216 | struct mwifiex_radar_params radar_params; | ||
| 3217 | |||
| 3218 | if (priv->adapter->scan_processing) { | ||
| 3219 | dev_err(priv->adapter->dev, | ||
| 3220 | "radar detection: scan already in process...\n"); | ||
| 3221 | return -EBUSY; | ||
| 3222 | } | ||
| 3223 | |||
| 3224 | if (!mwifiex_is_11h_active(priv)) { | ||
| 3225 | dev_dbg(priv->adapter->dev, "Enable 11h extensions in FW\n"); | ||
| 3226 | if (mwifiex_11h_activate(priv, true)) { | ||
| 3227 | dev_err(priv->adapter->dev, | ||
| 3228 | "Failed to activate 11h extensions!!"); | ||
| 3229 | return -1; | ||
| 3230 | } | ||
| 3231 | priv->state_11h.is_11h_active = true; | ||
| 3232 | } | ||
| 3233 | |||
| 3234 | memset(&radar_params, 0, sizeof(struct mwifiex_radar_params)); | ||
| 3235 | radar_params.chandef = chandef; | ||
| 3236 | radar_params.cac_time_ms = cac_time_ms; | ||
| 3237 | |||
| 3238 | memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef)); | ||
| 3239 | |||
| 3240 | if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST, | ||
| 3241 | HostCmd_ACT_GEN_SET, 0, &radar_params, true)) | ||
| 3242 | return -1; | ||
| 3243 | |||
| 3244 | queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work, | ||
| 3245 | msecs_to_jiffies(cac_time_ms)); | ||
| 3246 | return 0; | ||
| 3247 | } | ||
| 3248 | |||
| 3249 | static int | ||
| 2841 | mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, | 3250 | mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, |
| 2842 | const u8 *mac, | 3251 | const u8 *mac, |
| 2843 | struct station_parameters *params) | 3252 | struct station_parameters *params) |
| @@ -2901,6 +3310,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
| 2901 | .tdls_oper = mwifiex_cfg80211_tdls_oper, | 3310 | .tdls_oper = mwifiex_cfg80211_tdls_oper, |
| 2902 | .add_station = mwifiex_cfg80211_add_station, | 3311 | .add_station = mwifiex_cfg80211_add_station, |
| 2903 | .change_station = mwifiex_cfg80211_change_station, | 3312 | .change_station = mwifiex_cfg80211_change_station, |
| 3313 | .start_radar_detection = mwifiex_cfg80211_start_radar_detection, | ||
| 3314 | .channel_switch = mwifiex_cfg80211_channel_switch, | ||
| 2904 | }; | 3315 | }; |
| 2905 | 3316 | ||
| 2906 | #ifdef CONFIG_PM | 3317 | #ifdef CONFIG_PM |
| @@ -2999,12 +3410,13 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
| 2999 | wiphy->cipher_suites = mwifiex_cipher_suites; | 3410 | wiphy->cipher_suites = mwifiex_cipher_suites; |
| 3000 | wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); | 3411 | wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); |
| 3001 | 3412 | ||
| 3002 | memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); | 3413 | ether_addr_copy(wiphy->perm_addr, adapter->perm_addr); |
| 3003 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 3414 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
| 3004 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | 3415 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | |
| 3005 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | | 3416 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
| 3006 | WIPHY_FLAG_AP_UAPSD | | 3417 | WIPHY_FLAG_AP_UAPSD | |
| 3007 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 3418 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
| 3419 | WIPHY_FLAG_HAS_CHANNEL_SWITCH; | ||
| 3008 | 3420 | ||
| 3009 | if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) | 3421 | if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) |
| 3010 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | 3422 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index f494fc7eeb62..e9df8826f124 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c | |||
| @@ -322,9 +322,9 @@ mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq) | |||
| 322 | return cfp; | 322 | return cfp; |
| 323 | 323 | ||
| 324 | if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) | 324 | if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) |
| 325 | sband = priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ]; | 325 | sband = priv->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]; |
| 326 | else | 326 | else |
| 327 | sband = priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ]; | 327 | sband = priv->wdev.wiphy->bands[IEEE80211_BAND_5GHZ]; |
| 328 | 328 | ||
| 329 | if (!sband) { | 329 | if (!sband) { |
| 330 | dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d\n", | 330 | dev_err(priv->adapter->dev, "%s: cannot find cfp by band %d\n", |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 946a2f7a172f..c5a14ff7eb82 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
| @@ -315,22 +315,19 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | |||
| 315 | adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; | 315 | adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; |
| 316 | return -1; | 316 | return -1; |
| 317 | } | 317 | } |
| 318 | if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) | 318 | |
| 319 | == MWIFIEX_BSS_ROLE_STA) { | 319 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) |
| 320 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) | 320 | /* Response is not needed for sleep confirm command */ |
| 321 | /* Response is not needed for sleep | 321 | adapter->ps_state = PS_STATE_SLEEP; |
| 322 | confirm command */ | 322 | else |
| 323 | adapter->ps_state = PS_STATE_SLEEP; | 323 | adapter->ps_state = PS_STATE_SLEEP_CFM; |
| 324 | else | 324 | |
| 325 | adapter->ps_state = PS_STATE_SLEEP_CFM; | 325 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && |
| 326 | 326 | (adapter->is_hs_configured && | |
| 327 | if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && | 327 | !adapter->sleep_period.period)) { |
| 328 | (adapter->is_hs_configured && | 328 | adapter->pm_wakeup_card_req = true; |
| 329 | !adapter->sleep_period.period)) { | 329 | mwifiex_hs_activated_event(mwifiex_get_priv |
| 330 | adapter->pm_wakeup_card_req = true; | 330 | (adapter, MWIFIEX_BSS_ROLE_ANY), true); |
| 331 | mwifiex_hs_activated_event(mwifiex_get_priv | ||
| 332 | (adapter, MWIFIEX_BSS_ROLE_STA), true); | ||
| 333 | } | ||
| 334 | } | 331 | } |
| 335 | 332 | ||
| 336 | return ret; | 333 | return ret; |
| @@ -450,6 +447,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
| 450 | EVENT_GET_BSS_TYPE(eventcause)); | 447 | EVENT_GET_BSS_TYPE(eventcause)); |
| 451 | if (!priv) | 448 | if (!priv) |
| 452 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 449 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
| 450 | |||
| 453 | /* Clear BSS_NO_BITS from event */ | 451 | /* Clear BSS_NO_BITS from event */ |
| 454 | eventcause &= EVENT_ID_MASK; | 452 | eventcause &= EVENT_ID_MASK; |
| 455 | adapter->event_cause = eventcause; | 453 | adapter->event_cause = eventcause; |
| @@ -462,12 +460,6 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
| 462 | } | 460 | } |
| 463 | 461 | ||
| 464 | dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause); | 462 | dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause); |
| 465 | if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) { | ||
| 466 | /* Handle PS_SLEEP/AWAKE events on STA */ | ||
| 467 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
| 468 | if (!priv) | ||
| 469 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
| 470 | } | ||
| 471 | 463 | ||
| 472 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 464 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
| 473 | ret = mwifiex_process_uap_event(priv); | 465 | ret = mwifiex_process_uap_event(priv); |
| @@ -1582,9 +1574,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
| 1582 | le16_to_cpu(hw_spec->hw_if_version), | 1574 | le16_to_cpu(hw_spec->hw_if_version), |
| 1583 | le16_to_cpu(hw_spec->version)); | 1575 | le16_to_cpu(hw_spec->version)); |
| 1584 | 1576 | ||
| 1585 | if (priv->curr_addr[0] == 0xff) | 1577 | ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr); |
| 1586 | memmove(priv->curr_addr, hw_spec->permanent_addr, ETH_ALEN); | ||
| 1587 | |||
| 1588 | adapter->region_code = le16_to_cpu(hw_spec->region_code); | 1578 | adapter->region_code = le16_to_cpu(hw_spec->region_code); |
| 1589 | 1579 | ||
| 1590 | for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) | 1580 | for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 7aa988e1dc7a..88d0eade6bb1 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
| @@ -104,6 +104,12 @@ | |||
| 104 | /* Rate index for OFDM 0 */ | 104 | /* Rate index for OFDM 0 */ |
| 105 | #define MWIFIEX_RATE_INDEX_OFDM0 4 | 105 | #define MWIFIEX_RATE_INDEX_OFDM0 4 |
| 106 | 106 | ||
| 107 | #define MWIFIEX_MAX_STA_NUM 1 | ||
| 108 | #define MWIFIEX_MAX_UAP_NUM 1 | ||
| 109 | #define MWIFIEX_MAX_P2P_NUM 1 | ||
| 110 | |||
| 111 | #define MWIFIEX_A_BAND_START_FREQ 5000 | ||
| 112 | |||
| 107 | enum mwifiex_bss_type { | 113 | enum mwifiex_bss_type { |
| 108 | MWIFIEX_BSS_TYPE_STA = 0, | 114 | MWIFIEX_BSS_TYPE_STA = 0, |
| 109 | MWIFIEX_BSS_TYPE_UAP = 1, | 115 | MWIFIEX_BSS_TYPE_UAP = 1, |
| @@ -232,4 +238,19 @@ struct mwifiex_histogram_data { | |||
| 232 | atomic_t num_samples; | 238 | atomic_t num_samples; |
| 233 | }; | 239 | }; |
| 234 | 240 | ||
| 241 | struct mwifiex_iface_comb { | ||
| 242 | u8 sta_intf; | ||
| 243 | u8 uap_intf; | ||
| 244 | u8 p2p_intf; | ||
| 245 | }; | ||
| 246 | |||
| 247 | struct mwifiex_radar_params { | ||
| 248 | struct cfg80211_chan_def *chandef; | ||
| 249 | u32 cac_time_ms; | ||
| 250 | } __packed; | ||
| 251 | |||
| 252 | struct mwifiex_11h_intf_state { | ||
| 253 | bool is_11h_enabled; | ||
| 254 | bool is_11h_active; | ||
| 255 | } __packed; | ||
| 235 | #endif /* !_MWIFIEX_DECL_H_ */ | 256 | #endif /* !_MWIFIEX_DECL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 15ad776ae08e..df553e86a0ad 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
| @@ -158,6 +158,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 158 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) | 158 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) |
| 159 | #define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86) | 159 | #define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86) |
| 160 | #define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87) | 160 | #define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87) |
| 161 | #define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91) | ||
| 161 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) | 162 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) |
| 162 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) | 163 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) |
| 163 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) | 164 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) |
| @@ -336,6 +337,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 336 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf | 337 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf |
| 337 | #define HostCmd_CMD_11N_DELBA 0x00d0 | 338 | #define HostCmd_CMD_11N_DELBA 0x00d0 |
| 338 | #define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 | 339 | #define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 |
| 340 | #define HostCmd_CMD_CHAN_REPORT_REQUEST 0x00dd | ||
| 339 | #define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df | 341 | #define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df |
| 340 | #define HostCmd_CMD_TXPWR_CFG 0x00d1 | 342 | #define HostCmd_CMD_TXPWR_CFG 0x00d1 |
| 341 | #define HostCmd_CMD_TX_RATE_CFG 0x00d6 | 343 | #define HostCmd_CMD_TX_RATE_CFG 0x00d6 |
| @@ -493,6 +495,8 @@ enum P2P_MODES { | |||
| 493 | #define EVENT_HOSTWAKE_STAIE 0x0000004d | 495 | #define EVENT_HOSTWAKE_STAIE 0x0000004d |
| 494 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 | 496 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 |
| 495 | #define EVENT_TDLS_GENERIC_EVENT 0x00000052 | 497 | #define EVENT_TDLS_GENERIC_EVENT 0x00000052 |
| 498 | #define EVENT_RADAR_DETECTED 0x00000053 | ||
| 499 | #define EVENT_CHANNEL_REPORT_RDY 0x00000054 | ||
| 496 | #define EVENT_EXT_SCAN_REPORT 0x00000058 | 500 | #define EVENT_EXT_SCAN_REPORT 0x00000058 |
| 497 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f | 501 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f |
| 498 | #define EVENT_TX_STATUS_REPORT 0x00000074 | 502 | #define EVENT_TX_STATUS_REPORT 0x00000074 |
| @@ -530,6 +534,8 @@ enum P2P_MODES { | |||
| 530 | 534 | ||
| 531 | #define MWIFIEX_FW_V15 15 | 535 | #define MWIFIEX_FW_V15 15 |
| 532 | 536 | ||
| 537 | #define MWIFIEX_MASTER_RADAR_DET_MASK BIT(1) | ||
| 538 | |||
| 533 | struct mwifiex_ie_types_header { | 539 | struct mwifiex_ie_types_header { |
| 534 | __le16 type; | 540 | __le16 type; |
| 535 | __le16 len; | 541 | __le16 len; |
| @@ -1216,6 +1222,24 @@ struct host_cmd_ds_tdls_oper { | |||
| 1216 | u8 peer_mac[ETH_ALEN]; | 1222 | u8 peer_mac[ETH_ALEN]; |
| 1217 | } __packed; | 1223 | } __packed; |
| 1218 | 1224 | ||
| 1225 | struct mwifiex_chan_desc { | ||
| 1226 | __le16 start_freq; | ||
| 1227 | u8 chan_width; | ||
| 1228 | u8 chan_num; | ||
| 1229 | } __packed; | ||
| 1230 | |||
| 1231 | struct host_cmd_ds_chan_rpt_req { | ||
| 1232 | struct mwifiex_chan_desc chan_desc; | ||
| 1233 | __le32 msec_dwell_time; | ||
| 1234 | } __packed; | ||
| 1235 | |||
| 1236 | struct host_cmd_ds_chan_rpt_event { | ||
| 1237 | __le32 result; | ||
| 1238 | __le64 start_tsf; | ||
| 1239 | __le32 duration; | ||
| 1240 | u8 tlvbuf[0]; | ||
| 1241 | } __packed; | ||
| 1242 | |||
| 1219 | struct mwifiex_fixed_bcn_param { | 1243 | struct mwifiex_fixed_bcn_param { |
| 1220 | __le64 timestamp; | 1244 | __le64 timestamp; |
| 1221 | __le16 beacon_period; | 1245 | __le16 beacon_period; |
| @@ -1792,6 +1816,39 @@ struct mwifiex_ie_types_rssi_threshold { | |||
| 1792 | u8 evt_freq; | 1816 | u8 evt_freq; |
| 1793 | } __packed; | 1817 | } __packed; |
| 1794 | 1818 | ||
| 1819 | #define MWIFIEX_DFS_REC_HDR_LEN 8 | ||
| 1820 | #define MWIFIEX_DFS_REC_HDR_NUM 10 | ||
| 1821 | #define MWIFIEX_BIN_COUNTER_LEN 7 | ||
| 1822 | |||
| 1823 | struct mwifiex_radar_det_event { | ||
| 1824 | __le32 detect_count; | ||
| 1825 | u8 reg_domain; /*1=fcc, 2=etsi, 3=mic*/ | ||
| 1826 | u8 det_type; /*0=none, 1=pw(chirp), 2=pri(radar)*/ | ||
| 1827 | __le16 pw_chirp_type; | ||
| 1828 | u8 pw_chirp_idx; | ||
| 1829 | u8 pw_value; | ||
| 1830 | u8 pri_radar_type; | ||
| 1831 | u8 pri_bincnt; | ||
| 1832 | u8 bin_counter[MWIFIEX_BIN_COUNTER_LEN]; | ||
| 1833 | u8 num_dfs_records; | ||
| 1834 | u8 dfs_record_hdr[MWIFIEX_DFS_REC_HDR_NUM][MWIFIEX_DFS_REC_HDR_LEN]; | ||
| 1835 | __le32 passed; | ||
| 1836 | } __packed; | ||
| 1837 | |||
| 1838 | struct meas_rpt_map { | ||
| 1839 | u8 rssi:3; | ||
| 1840 | u8 unmeasured:1; | ||
| 1841 | u8 radar:1; | ||
| 1842 | u8 unidentified_sig:1; | ||
| 1843 | u8 ofdm_preamble:1; | ||
| 1844 | u8 bss:1; | ||
| 1845 | } __packed; | ||
| 1846 | |||
| 1847 | struct mwifiex_ie_types_chan_rpt_data { | ||
| 1848 | struct mwifiex_ie_types_header header; | ||
| 1849 | struct meas_rpt_map map; | ||
| 1850 | } __packed; | ||
| 1851 | |||
| 1795 | struct host_cmd_ds_802_11_subsc_evt { | 1852 | struct host_cmd_ds_802_11_subsc_evt { |
| 1796 | __le16 action; | 1853 | __le16 action; |
| 1797 | __le16 events; | 1854 | __le16 events; |
| @@ -1904,6 +1961,7 @@ struct host_cmd_ds_command { | |||
| 1904 | struct host_cmd_11ac_vht_cfg vht_cfg; | 1961 | struct host_cmd_11ac_vht_cfg vht_cfg; |
| 1905 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; | 1962 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; |
| 1906 | struct host_cmd_ds_tdls_oper tdls_oper; | 1963 | struct host_cmd_ds_tdls_oper tdls_oper; |
| 1964 | struct host_cmd_ds_chan_rpt_req chan_rpt_req; | ||
| 1907 | } params; | 1965 | } params; |
| 1908 | } __packed; | 1966 | } __packed; |
| 1909 | 1967 | ||
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index b933794758b7..f3b6ed249403 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c | |||
| @@ -317,27 +317,27 @@ done: | |||
| 317 | return ret; | 317 | return ret; |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | /* This function parses different IEs-tail IEs, beacon IEs, probe response IEs, | 320 | /* This function parses head and tail IEs, from cfg80211_beacon_data and sets |
| 321 | * association response IEs from cfg80211_ap_settings function and sets these IE | 321 | * these IE to FW. |
| 322 | * to FW. | ||
| 323 | */ | 322 | */ |
| 324 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | 323 | static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv, |
| 325 | struct cfg80211_beacon_data *info) | 324 | struct cfg80211_beacon_data *info) |
| 326 | { | 325 | { |
| 327 | struct mwifiex_ie *gen_ie; | 326 | struct mwifiex_ie *gen_ie; |
| 328 | struct ieee_types_header *rsn_ie, *wpa_ie = NULL; | 327 | struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL; |
| 329 | u16 rsn_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; | 328 | struct ieee_types_header *chsw_ie = NULL; |
| 329 | u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; | ||
| 330 | const u8 *vendor_ie; | 330 | const u8 *vendor_ie; |
| 331 | 331 | ||
| 332 | if (info->tail && info->tail_len) { | 332 | gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL); |
| 333 | gen_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | 333 | if (!gen_ie) |
| 334 | if (!gen_ie) | 334 | return -ENOMEM; |
| 335 | return -ENOMEM; | 335 | gen_ie->ie_index = cpu_to_le16(gen_idx); |
| 336 | gen_ie->ie_index = cpu_to_le16(rsn_idx); | 336 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | |
| 337 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | | 337 | MGMT_MASK_PROBE_RESP | |
| 338 | MGMT_MASK_PROBE_RESP | | 338 | MGMT_MASK_ASSOC_RESP); |
| 339 | MGMT_MASK_ASSOC_RESP); | ||
| 340 | 339 | ||
| 340 | if (info->tail && info->tail_len) { | ||
| 341 | rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, | 341 | rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, |
| 342 | info->tail, info->tail_len); | 342 | info->tail, info->tail_len); |
| 343 | if (rsn_ie) { | 343 | if (rsn_ie) { |
| @@ -358,19 +358,41 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
| 358 | gen_ie->ie_length = cpu_to_le16(ie_len); | 358 | gen_ie->ie_length = cpu_to_le16(ie_len); |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | if (rsn_ie || wpa_ie) { | 361 | chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH, |
| 362 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &rsn_idx, | 362 | info->tail, info->tail_len); |
| 363 | NULL, NULL, | 363 | if (chsw_ie) { |
| 364 | NULL, NULL)) { | 364 | memcpy(gen_ie->ie_buffer + ie_len, |
| 365 | kfree(gen_ie); | 365 | chsw_ie, chsw_ie->len + 2); |
| 366 | return -1; | 366 | ie_len += chsw_ie->len + 2; |
| 367 | } | 367 | gen_ie->ie_length = cpu_to_le16(ie_len); |
| 368 | priv->rsn_idx = rsn_idx; | ||
| 369 | } | 368 | } |
| 369 | } | ||
| 370 | 370 | ||
| 371 | kfree(gen_ie); | 371 | if (rsn_ie || wpa_ie || chsw_ie) { |
| 372 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, | ||
| 373 | NULL, NULL, NULL)) { | ||
| 374 | kfree(gen_ie); | ||
| 375 | return -1; | ||
| 376 | } | ||
| 377 | priv->gen_idx = gen_idx; | ||
| 372 | } | 378 | } |
| 373 | 379 | ||
| 380 | kfree(gen_ie); | ||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | /* This function parses different IEs-head & tail IEs, beacon IEs, | ||
| 385 | * probe response IEs, association response IEs from cfg80211_ap_settings | ||
| 386 | * function and sets these IE to FW. | ||
| 387 | */ | ||
| 388 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
| 389 | struct cfg80211_beacon_data *info) | ||
| 390 | { | ||
| 391 | int ret; | ||
| 392 | |||
| 393 | ret = mwifiex_uap_set_head_tail_ies(priv, info); | ||
| 394 | return ret; | ||
| 395 | |||
| 374 | return mwifiex_set_mgmt_beacon_data_ies(priv, info); | 396 | return mwifiex_set_mgmt_beacon_data_ies(priv, info); |
| 375 | } | 397 | } |
| 376 | 398 | ||
| @@ -378,25 +400,25 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
| 378 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) | 400 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) |
| 379 | { | 401 | { |
| 380 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | 402 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; |
| 381 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | 403 | struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL; |
| 382 | int ret = 0; | 404 | int ret = 0; |
| 383 | 405 | ||
| 384 | if (priv->rsn_idx != MWIFIEX_AUTO_IDX_MASK) { | 406 | if (priv->gen_idx != MWIFIEX_AUTO_IDX_MASK) { |
| 385 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | 407 | gen_ie = kmalloc(sizeof(*gen_ie), GFP_KERNEL); |
| 386 | if (!rsn_ie) | 408 | if (!gen_ie) |
| 387 | return -ENOMEM; | 409 | return -ENOMEM; |
| 388 | 410 | ||
| 389 | rsn_ie->ie_index = cpu_to_le16(priv->rsn_idx); | 411 | gen_ie->ie_index = cpu_to_le16(priv->gen_idx); |
| 390 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | 412 | gen_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); |
| 391 | rsn_ie->ie_length = 0; | 413 | gen_ie->ie_length = 0; |
| 392 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &priv->rsn_idx, | 414 | if (mwifiex_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx, |
| 393 | NULL, &priv->proberesp_idx, | 415 | NULL, &priv->proberesp_idx, |
| 394 | NULL, &priv->assocresp_idx)) { | 416 | NULL, &priv->assocresp_idx)) { |
| 395 | ret = -1; | 417 | ret = -1; |
| 396 | goto done; | 418 | goto done; |
| 397 | } | 419 | } |
| 398 | 420 | ||
| 399 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | 421 | priv->gen_idx = MWIFIEX_AUTO_IDX_MASK; |
| 400 | } | 422 | } |
| 401 | 423 | ||
| 402 | if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) { | 424 | if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) { |
| @@ -440,7 +462,6 @@ done: | |||
| 440 | kfree(beacon_ie); | 462 | kfree(beacon_ie); |
| 441 | kfree(pr_ie); | 463 | kfree(pr_ie); |
| 442 | kfree(ar_ie); | 464 | kfree(ar_ie); |
| 443 | kfree(rsn_ie); | ||
| 444 | 465 | ||
| 445 | return ret; | 466 | return ret; |
| 446 | } | 467 | } |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index b115e0f94dd7..b77ba743e1c4 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
| @@ -152,6 +152,8 @@ int mwifiex_init_priv(struct mwifiex_private *priv) | |||
| 152 | priv->check_tdls_tx = false; | 152 | priv->check_tdls_tx = false; |
| 153 | memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); | 153 | memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); |
| 154 | 154 | ||
| 155 | mwifiex_init_11h_params(priv); | ||
| 156 | |||
| 155 | return mwifiex_add_bss_prio_tbl(priv); | 157 | return mwifiex_add_bss_prio_tbl(priv); |
| 156 | } | 158 | } |
| 157 | 159 | ||
| @@ -294,9 +296,13 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
| 294 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); | 296 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); |
| 295 | adapter->arp_filter_size = 0; | 297 | adapter->arp_filter_size = 0; |
| 296 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; | 298 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; |
| 297 | adapter->ext_scan = true; | 299 | adapter->ext_scan = false; |
| 298 | adapter->key_api_major_ver = 0; | 300 | adapter->key_api_major_ver = 0; |
| 299 | adapter->key_api_minor_ver = 0; | 301 | adapter->key_api_minor_ver = 0; |
| 302 | memset(adapter->perm_addr, 0xff, ETH_ALEN); | ||
| 303 | adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM; | ||
| 304 | adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM; | ||
| 305 | adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM; | ||
| 300 | 306 | ||
| 301 | setup_timer(&adapter->wakeup_timer, wakeup_timer_fn, | 307 | setup_timer(&adapter->wakeup_timer, wakeup_timer_fn, |
| 302 | (unsigned long)adapter); | 308 | (unsigned long)adapter); |
| @@ -551,7 +557,8 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter) | |||
| 551 | 557 | ||
| 552 | for (i = 0; i < adapter->priv_num; i++) { | 558 | for (i = 0; i < adapter->priv_num; i++) { |
| 553 | if (adapter->priv[i]) { | 559 | if (adapter->priv[i]) { |
| 554 | ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); | 560 | ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta, |
| 561 | true); | ||
| 555 | if (ret == -1) | 562 | if (ret == -1) |
| 556 | return -1; | 563 | return -1; |
| 557 | 564 | ||
| @@ -676,6 +683,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
| 676 | priv = adapter->priv[i]; | 683 | priv = adapter->priv[i]; |
| 677 | 684 | ||
| 678 | mwifiex_clean_auto_tdls(priv); | 685 | mwifiex_clean_auto_tdls(priv); |
| 686 | mwifiex_abort_cac(priv); | ||
| 679 | mwifiex_clean_txrx(priv); | 687 | mwifiex_clean_txrx(priv); |
| 680 | mwifiex_delete_bss_prio_tbl(priv); | 688 | mwifiex_delete_bss_prio_tbl(priv); |
| 681 | } | 689 | } |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d235adb82c94..7e74b4fccddd 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
| @@ -562,7 +562,8 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) | |||
| 562 | static int | 562 | static int |
| 563 | mwifiex_open(struct net_device *dev) | 563 | mwifiex_open(struct net_device *dev) |
| 564 | { | 564 | { |
| 565 | netif_tx_start_all_queues(dev); | 565 | netif_carrier_off(dev); |
| 566 | |||
| 566 | return 0; | 567 | return 0; |
| 567 | } | 568 | } |
| 568 | 569 | ||
| @@ -960,21 +961,21 @@ static const struct net_device_ops mwifiex_netdev_ops = { | |||
| 960 | * In addition, the CFG80211 work queue is also created. | 961 | * In addition, the CFG80211 work queue is also created. |
| 961 | */ | 962 | */ |
| 962 | void mwifiex_init_priv_params(struct mwifiex_private *priv, | 963 | void mwifiex_init_priv_params(struct mwifiex_private *priv, |
| 963 | struct net_device *dev) | 964 | struct net_device *dev) |
| 964 | { | 965 | { |
| 965 | dev->netdev_ops = &mwifiex_netdev_ops; | 966 | dev->netdev_ops = &mwifiex_netdev_ops; |
| 966 | dev->destructor = free_netdev; | 967 | dev->destructor = free_netdev; |
| 967 | /* Initialize private structure */ | 968 | /* Initialize private structure */ |
| 968 | priv->current_key_index = 0; | 969 | priv->current_key_index = 0; |
| 969 | priv->media_connected = false; | 970 | priv->media_connected = false; |
| 970 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); | ||
| 971 | memset(priv->mgmt_ie, 0, | 971 | memset(priv->mgmt_ie, 0, |
| 972 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); | 972 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); |
| 973 | priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; | 973 | priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; |
| 974 | priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; | 974 | priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; |
| 975 | priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; | 975 | priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; |
| 976 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | 976 | priv->gen_idx = MWIFIEX_AUTO_IDX_MASK; |
| 977 | priv->num_tx_timeout = 0; | 977 | priv->num_tx_timeout = 0; |
| 978 | ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr); | ||
| 978 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); | 979 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); |
| 979 | 980 | ||
| 980 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || | 981 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || |
| @@ -1203,8 +1204,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) | |||
| 1203 | continue; | 1204 | continue; |
| 1204 | 1205 | ||
| 1205 | rtnl_lock(); | 1206 | rtnl_lock(); |
| 1206 | if (priv->wdev && priv->netdev) | 1207 | if (priv->netdev && |
| 1207 | mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); | 1208 | priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) |
| 1209 | mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev); | ||
| 1208 | rtnl_unlock(); | 1210 | rtnl_unlock(); |
| 1209 | } | 1211 | } |
| 1210 | 1212 | ||
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 55273eefb785..f0a6af179af0 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
| @@ -547,13 +547,12 @@ struct mwifiex_private { | |||
| 547 | u32 curr_bcn_size; | 547 | u32 curr_bcn_size; |
| 548 | /* spin lock for beacon buffer */ | 548 | /* spin lock for beacon buffer */ |
| 549 | spinlock_t curr_bcn_buf_lock; | 549 | spinlock_t curr_bcn_buf_lock; |
| 550 | struct wireless_dev *wdev; | 550 | struct wireless_dev wdev; |
| 551 | struct mwifiex_chan_freq_power cfp; | 551 | struct mwifiex_chan_freq_power cfp; |
| 552 | char version_str[128]; | 552 | char version_str[128]; |
| 553 | #ifdef CONFIG_DEBUG_FS | 553 | #ifdef CONFIG_DEBUG_FS |
| 554 | struct dentry *dfs_dev_dir; | 554 | struct dentry *dfs_dev_dir; |
| 555 | #endif | 555 | #endif |
| 556 | u8 nick_name[16]; | ||
| 557 | u16 current_key_index; | 556 | u16 current_key_index; |
| 558 | struct semaphore async_sem; | 557 | struct semaphore async_sem; |
| 559 | struct cfg80211_scan_request *scan_request; | 558 | struct cfg80211_scan_request *scan_request; |
| @@ -568,7 +567,7 @@ struct mwifiex_private { | |||
| 568 | u16 beacon_idx; | 567 | u16 beacon_idx; |
| 569 | u16 proberesp_idx; | 568 | u16 proberesp_idx; |
| 570 | u16 assocresp_idx; | 569 | u16 assocresp_idx; |
| 571 | u16 rsn_idx; | 570 | u16 gen_idx; |
| 572 | u8 ap_11n_enabled; | 571 | u8 ap_11n_enabled; |
| 573 | u8 ap_11ac_enabled; | 572 | u8 ap_11ac_enabled; |
| 574 | u32 mgmt_frame_mask; | 573 | u32 mgmt_frame_mask; |
| @@ -578,6 +577,7 @@ struct mwifiex_private { | |||
| 578 | unsigned long csa_expire_time; | 577 | unsigned long csa_expire_time; |
| 579 | u8 del_list_idx; | 578 | u8 del_list_idx; |
| 580 | bool hs2_enabled; | 579 | bool hs2_enabled; |
| 580 | struct mwifiex_uap_bss_param bss_cfg; | ||
| 581 | struct station_parameters *sta_params; | 581 | struct station_parameters *sta_params; |
| 582 | struct sk_buff_head tdls_txq; | 582 | struct sk_buff_head tdls_txq; |
| 583 | u8 check_tdls_tx; | 583 | u8 check_tdls_tx; |
| @@ -588,6 +588,14 @@ struct mwifiex_private { | |||
| 588 | spinlock_t ack_status_lock; | 588 | spinlock_t ack_status_lock; |
| 589 | /** rx histogram data */ | 589 | /** rx histogram data */ |
| 590 | struct mwifiex_histogram_data *hist_data; | 590 | struct mwifiex_histogram_data *hist_data; |
| 591 | struct cfg80211_chan_def dfs_chandef; | ||
| 592 | struct workqueue_struct *dfs_cac_workqueue; | ||
| 593 | struct delayed_work dfs_cac_work; | ||
| 594 | struct timer_list dfs_chan_switch_timer; | ||
| 595 | struct workqueue_struct *dfs_chan_sw_workqueue; | ||
| 596 | struct delayed_work dfs_chan_sw_work; | ||
| 597 | struct cfg80211_beacon_data beacon_after; | ||
| 598 | struct mwifiex_11h_intf_state state_11h; | ||
| 591 | }; | 599 | }; |
| 592 | 600 | ||
| 593 | enum mwifiex_ba_status { | 601 | enum mwifiex_ba_status { |
| @@ -731,6 +739,8 @@ struct mwifiex_if_ops { | |||
| 731 | 739 | ||
| 732 | struct mwifiex_adapter { | 740 | struct mwifiex_adapter { |
| 733 | u8 iface_type; | 741 | u8 iface_type; |
| 742 | struct mwifiex_iface_comb iface_limit; | ||
| 743 | struct mwifiex_iface_comb curr_iface_comb; | ||
| 734 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; | 744 | struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; |
| 735 | u8 priv_num; | 745 | u8 priv_num; |
| 736 | const struct firmware *firmware; | 746 | const struct firmware *firmware; |
| @@ -738,6 +748,7 @@ struct mwifiex_adapter { | |||
| 738 | int winner; | 748 | int winner; |
| 739 | struct device *dev; | 749 | struct device *dev; |
| 740 | struct wiphy *wiphy; | 750 | struct wiphy *wiphy; |
| 751 | u8 perm_addr[ETH_ALEN]; | ||
| 741 | bool surprise_removed; | 752 | bool surprise_removed; |
| 742 | u32 fw_release_number; | 753 | u32 fw_release_number; |
| 743 | u16 init_wait_q_woken; | 754 | u16 init_wait_q_woken; |
| @@ -751,6 +762,8 @@ struct mwifiex_adapter { | |||
| 751 | struct work_struct main_work; | 762 | struct work_struct main_work; |
| 752 | struct workqueue_struct *rx_workqueue; | 763 | struct workqueue_struct *rx_workqueue; |
| 753 | struct work_struct rx_work; | 764 | struct work_struct rx_work; |
| 765 | struct workqueue_struct *dfs_workqueue; | ||
| 766 | struct work_struct dfs_work; | ||
| 754 | bool rx_work_enabled; | 767 | bool rx_work_enabled; |
| 755 | bool rx_processing; | 768 | bool rx_processing; |
| 756 | bool delay_main_work; | 769 | bool delay_main_work; |
| @@ -989,7 +1002,7 @@ void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, | |||
| 989 | const u8 *ra_addr); | 1002 | const u8 *ra_addr); |
| 990 | void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); | 1003 | void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); |
| 991 | void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); | 1004 | void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); |
| 992 | int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); | 1005 | int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta, bool init); |
| 993 | int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, | 1006 | int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, |
| 994 | struct mwifiex_scan_cmd_config *scan_cfg); | 1007 | struct mwifiex_scan_cmd_config *scan_cfg); |
| 995 | void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, | 1008 | void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, |
| @@ -1150,6 +1163,25 @@ mwifiex_get_priv(struct mwifiex_adapter *adapter, | |||
| 1150 | } | 1163 | } |
| 1151 | 1164 | ||
| 1152 | /* | 1165 | /* |
| 1166 | * This function returns the first available unused private structure pointer. | ||
| 1167 | */ | ||
| 1168 | static inline struct mwifiex_private * | ||
| 1169 | mwifiex_get_unused_priv(struct mwifiex_adapter *adapter) | ||
| 1170 | { | ||
| 1171 | int i; | ||
| 1172 | |||
| 1173 | for (i = 0; i < adapter->priv_num; i++) { | ||
| 1174 | if (adapter->priv[i]) { | ||
| 1175 | if (adapter->priv[i]->bss_mode == | ||
| 1176 | NL80211_IFTYPE_UNSPECIFIED) | ||
| 1177 | break; | ||
| 1178 | } | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | /* | ||
| 1153 | * This function returns the driver private structure of a network device. | 1185 | * This function returns the driver private structure of a network device. |
| 1154 | */ | 1186 | */ |
| 1155 | static inline struct mwifiex_private * | 1187 | static inline struct mwifiex_private * |
| @@ -1240,8 +1272,6 @@ int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, | |||
| 1240 | struct ieee80211_channel *chan, | 1272 | struct ieee80211_channel *chan, |
| 1241 | unsigned int duration); | 1273 | unsigned int duration); |
| 1242 | 1274 | ||
| 1243 | int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role); | ||
| 1244 | |||
| 1245 | int mwifiex_get_stats_info(struct mwifiex_private *priv, | 1275 | int mwifiex_get_stats_info(struct mwifiex_private *priv, |
| 1246 | struct mwifiex_ds_get_stats *log); | 1276 | struct mwifiex_ds_get_stats *log); |
| 1247 | 1277 | ||
| @@ -1301,9 +1331,17 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | |||
| 1301 | struct cfg80211_beacon_data *data); | 1331 | struct cfg80211_beacon_data *data); |
| 1302 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | 1332 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); |
| 1303 | u8 *mwifiex_11d_code_2_region(u8 code); | 1333 | u8 *mwifiex_11d_code_2_region(u8 code); |
| 1334 | void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg, | ||
| 1335 | struct cfg80211_chan_def chandef); | ||
| 1336 | int mwifiex_config_start_uap(struct mwifiex_private *priv, | ||
| 1337 | struct mwifiex_uap_bss_param *bss_cfg); | ||
| 1304 | void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, | 1338 | void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, |
| 1305 | struct mwifiex_sta_node *node); | 1339 | struct mwifiex_sta_node *node); |
| 1306 | 1340 | ||
| 1341 | void mwifiex_init_11h_params(struct mwifiex_private *priv); | ||
| 1342 | int mwifiex_is_11h_active(struct mwifiex_private *priv); | ||
| 1343 | int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag); | ||
| 1344 | |||
| 1307 | void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, | 1345 | void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, |
| 1308 | struct mwifiex_bssdescriptor *bss_desc); | 1346 | struct mwifiex_bssdescriptor *bss_desc); |
| 1309 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); | 1347 | int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); |
| @@ -1352,6 +1390,11 @@ void mwifiex_check_auto_tdls(unsigned long context); | |||
| 1352 | void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); | 1390 | void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); |
| 1353 | void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); | 1391 | void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); |
| 1354 | void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); | 1392 | void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); |
| 1393 | int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv, | ||
| 1394 | struct host_cmd_ds_command *cmd, | ||
| 1395 | void *data_buf); | ||
| 1396 | int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv, | ||
| 1397 | struct sk_buff *skb); | ||
| 1355 | 1398 | ||
| 1356 | void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, | 1399 | void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, |
| 1357 | void *event_body); | 1400 | void *event_body); |
| @@ -1359,6 +1402,11 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, | |||
| 1359 | struct sk_buff * | 1402 | struct sk_buff * |
| 1360 | mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, | 1403 | mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, |
| 1361 | struct sk_buff *skb, u8 flag, u64 *cookie); | 1404 | struct sk_buff *skb, u8 flag, u64 *cookie); |
| 1405 | void mwifiex_dfs_cac_work_queue(struct work_struct *work); | ||
| 1406 | void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work); | ||
| 1407 | void mwifiex_abort_cac(struct mwifiex_private *priv); | ||
| 1408 | int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, | ||
| 1409 | struct sk_buff *skb); | ||
| 1362 | 1410 | ||
| 1363 | void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, | 1411 | void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, |
| 1364 | s8 nflr); | 1412 | s8 nflr); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index a460b0e6a151..a5828da59365 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
| @@ -204,6 +204,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, | |||
| 204 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; | 204 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; |
| 205 | card->pcie.tx_buf_size = data->tx_buf_size; | 205 | card->pcie.tx_buf_size = data->tx_buf_size; |
| 206 | card->pcie.supports_fw_dump = data->supports_fw_dump; | 206 | card->pcie.supports_fw_dump = data->supports_fw_dump; |
| 207 | card->pcie.can_ext_scan = data->can_ext_scan; | ||
| 207 | } | 208 | } |
| 208 | 209 | ||
| 209 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, | 210 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, |
| @@ -2563,6 +2564,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
| 2563 | adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; | 2564 | adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; |
| 2564 | adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); | 2565 | adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); |
| 2565 | strcpy(adapter->fw_name, card->pcie.firmware); | 2566 | strcpy(adapter->fw_name, card->pcie.firmware); |
| 2567 | adapter->ext_scan = card->pcie.can_ext_scan; | ||
| 2566 | 2568 | ||
| 2567 | return 0; | 2569 | return 0; |
| 2568 | } | 2570 | } |
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h index 200e8b0cb582..666d40e9dbc3 100644 --- a/drivers/net/wireless/mwifiex/pcie.h +++ b/drivers/net/wireless/mwifiex/pcie.h | |||
| @@ -206,6 +206,7 @@ struct mwifiex_pcie_device { | |||
| 206 | u16 blksz_fw_dl; | 206 | u16 blksz_fw_dl; |
| 207 | u16 tx_buf_size; | 207 | u16 tx_buf_size; |
| 208 | bool supports_fw_dump; | 208 | bool supports_fw_dump; |
| 209 | bool can_ext_scan; | ||
| 209 | }; | 210 | }; |
| 210 | 211 | ||
| 211 | static const struct mwifiex_pcie_device mwifiex_pcie8766 = { | 212 | static const struct mwifiex_pcie_device mwifiex_pcie8766 = { |
| @@ -214,6 +215,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8766 = { | |||
| 214 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, | 215 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, |
| 215 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | 216 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, |
| 216 | .supports_fw_dump = false, | 217 | .supports_fw_dump = false, |
| 218 | .can_ext_scan = true, | ||
| 217 | }; | 219 | }; |
| 218 | 220 | ||
| 219 | static const struct mwifiex_pcie_device mwifiex_pcie8897 = { | 221 | static const struct mwifiex_pcie_device mwifiex_pcie8897 = { |
| @@ -222,6 +224,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8897 = { | |||
| 222 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, | 224 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, |
| 223 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, | 225 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, |
| 224 | .supports_fw_dump = true, | 226 | .supports_fw_dump = true, |
| 227 | .can_ext_scan = true, | ||
| 225 | }; | 228 | }; |
| 226 | 229 | ||
| 227 | struct mwifiex_evt_buf_desc { | 230 | struct mwifiex_evt_buf_desc { |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 984a7a4fa93b..0ffdb7c5afd2 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
| @@ -496,10 +496,10 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, | |||
| 496 | 496 | ||
| 497 | for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { | 497 | for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { |
| 498 | 498 | ||
| 499 | if (!priv->wdev->wiphy->bands[band]) | 499 | if (!priv->wdev.wiphy->bands[band]) |
| 500 | continue; | 500 | continue; |
| 501 | 501 | ||
| 502 | sband = priv->wdev->wiphy->bands[band]; | 502 | sband = priv->wdev.wiphy->bands[band]; |
| 503 | 503 | ||
| 504 | for (i = 0; (i < sband->n_channels) ; i++) { | 504 | for (i = 0; (i < sband->n_channels) ; i++) { |
| 505 | ch = &sband->channels[i]; | 505 | ch = &sband->channels[i]; |
| @@ -1429,6 +1429,12 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | |||
| 1429 | return -EBUSY; | 1429 | return -EBUSY; |
| 1430 | } | 1430 | } |
| 1431 | 1431 | ||
| 1432 | if (adapter->surprise_removed || adapter->is_cmd_timedout) { | ||
| 1433 | dev_err(adapter->dev, | ||
| 1434 | "Ignore scan. Card removed or firmware in bad state\n"); | ||
| 1435 | return -EFAULT; | ||
| 1436 | } | ||
| 1437 | |||
| 1432 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 1438 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
| 1433 | adapter->scan_processing = true; | 1439 | adapter->scan_processing = true; |
| 1434 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 1440 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
| @@ -1727,10 +1733,10 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, | |||
| 1727 | 1733 | ||
| 1728 | freq = cfp ? cfp->freq : 0; | 1734 | freq = cfp ? cfp->freq : 0; |
| 1729 | 1735 | ||
| 1730 | chan = ieee80211_get_channel(priv->wdev->wiphy, freq); | 1736 | chan = ieee80211_get_channel(priv->wdev.wiphy, freq); |
| 1731 | 1737 | ||
| 1732 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | 1738 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { |
| 1733 | bss = cfg80211_inform_bss(priv->wdev->wiphy, | 1739 | bss = cfg80211_inform_bss(priv->wdev.wiphy, |
| 1734 | chan, CFG80211_BSS_FTYPE_UNKNOWN, | 1740 | chan, CFG80211_BSS_FTYPE_UNKNOWN, |
| 1735 | bssid, timestamp, | 1741 | bssid, timestamp, |
| 1736 | cap_info_bitmap, beacon_period, | 1742 | cap_info_bitmap, beacon_period, |
| @@ -1742,7 +1748,7 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, | |||
| 1742 | !memcmp(bssid, priv->curr_bss_params.bss_descriptor | 1748 | !memcmp(bssid, priv->curr_bss_params.bss_descriptor |
| 1743 | .mac_address, ETH_ALEN)) | 1749 | .mac_address, ETH_ALEN)) |
| 1744 | mwifiex_update_curr_bss_params(priv, bss); | 1750 | mwifiex_update_curr_bss_params(priv, bss); |
| 1745 | cfg80211_put_bss(priv->wdev->wiphy, bss); | 1751 | cfg80211_put_bss(priv->wdev.wiphy, bss); |
| 1746 | } | 1752 | } |
| 1747 | } else { | 1753 | } else { |
| 1748 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | 1754 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index a70f103359ea..91e36cda9543 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
| @@ -107,6 +107,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | |||
| 107 | card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; | 107 | card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; |
| 108 | card->supports_fw_dump = data->supports_fw_dump; | 108 | card->supports_fw_dump = data->supports_fw_dump; |
| 109 | card->auto_tdls = data->auto_tdls; | 109 | card->auto_tdls = data->auto_tdls; |
| 110 | card->can_ext_scan = data->can_ext_scan; | ||
| 110 | } | 111 | } |
| 111 | 112 | ||
| 112 | sdio_claim_host(func); | 113 | sdio_claim_host(func); |
| @@ -282,6 +283,9 @@ static int mwifiex_sdio_suspend(struct device *dev) | |||
| 282 | #define SDIO_DEVICE_ID_MARVELL_8897 (0x912d) | 283 | #define SDIO_DEVICE_ID_MARVELL_8897 (0x912d) |
| 283 | /* Device ID for SD8887 */ | 284 | /* Device ID for SD8887 */ |
| 284 | #define SDIO_DEVICE_ID_MARVELL_8887 (0x9135) | 285 | #define SDIO_DEVICE_ID_MARVELL_8887 (0x9135) |
| 286 | /* Device ID for SD8801 */ | ||
| 287 | #define SDIO_DEVICE_ID_MARVELL_8801 (0x9139) | ||
| 288 | |||
| 285 | 289 | ||
| 286 | /* WLAN IDs */ | 290 | /* WLAN IDs */ |
| 287 | static const struct sdio_device_id mwifiex_ids[] = { | 291 | static const struct sdio_device_id mwifiex_ids[] = { |
| @@ -295,6 +299,8 @@ static const struct sdio_device_id mwifiex_ids[] = { | |||
| 295 | .driver_data = (unsigned long) &mwifiex_sdio_sd8897}, | 299 | .driver_data = (unsigned long) &mwifiex_sdio_sd8897}, |
| 296 | {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887), | 300 | {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887), |
| 297 | .driver_data = (unsigned long)&mwifiex_sdio_sd8887}, | 301 | .driver_data = (unsigned long)&mwifiex_sdio_sd8887}, |
| 302 | {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801), | ||
| 303 | .driver_data = (unsigned long)&mwifiex_sdio_sd8801}, | ||
| 298 | {}, | 304 | {}, |
| 299 | }; | 305 | }; |
| 300 | 306 | ||
| @@ -1882,6 +1888,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) | |||
| 1882 | } | 1888 | } |
| 1883 | 1889 | ||
| 1884 | adapter->auto_tdls = card->auto_tdls; | 1890 | adapter->auto_tdls = card->auto_tdls; |
| 1891 | adapter->ext_scan = card->can_ext_scan; | ||
| 1885 | return ret; | 1892 | return ret; |
| 1886 | } | 1893 | } |
| 1887 | 1894 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 895eea054c9e..957cca246618 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" | 34 | #define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" |
| 35 | #define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" | 35 | #define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" |
| 36 | #define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin" | 36 | #define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin" |
| 37 | #define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin" | ||
| 37 | 38 | ||
| 38 | #define BLOCK_MODE 1 | 39 | #define BLOCK_MODE 1 |
| 39 | #define BYTE_MODE 0 | 40 | #define BYTE_MODE 0 |
| @@ -255,6 +256,7 @@ struct sdio_mmc_card { | |||
| 255 | 256 | ||
| 256 | u8 *mp_regs; | 257 | u8 *mp_regs; |
| 257 | u8 auto_tdls; | 258 | u8 auto_tdls; |
| 259 | bool can_ext_scan; | ||
| 258 | 260 | ||
| 259 | struct mwifiex_sdio_mpa_tx mpa_tx; | 261 | struct mwifiex_sdio_mpa_tx mpa_tx; |
| 260 | struct mwifiex_sdio_mpa_rx mpa_rx; | 262 | struct mwifiex_sdio_mpa_rx mpa_rx; |
| @@ -272,6 +274,7 @@ struct mwifiex_sdio_device { | |||
| 272 | u32 mp_tx_agg_buf_size; | 274 | u32 mp_tx_agg_buf_size; |
| 273 | u32 mp_rx_agg_buf_size; | 275 | u32 mp_rx_agg_buf_size; |
| 274 | u8 auto_tdls; | 276 | u8 auto_tdls; |
| 277 | bool can_ext_scan; | ||
| 275 | }; | 278 | }; |
| 276 | 279 | ||
| 277 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { | 280 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { |
| @@ -416,6 +419,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { | |||
| 416 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 419 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
| 417 | .supports_fw_dump = false, | 420 | .supports_fw_dump = false, |
| 418 | .auto_tdls = false, | 421 | .auto_tdls = false, |
| 422 | .can_ext_scan = false, | ||
| 419 | }; | 423 | }; |
| 420 | 424 | ||
| 421 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | 425 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { |
| @@ -430,6 +434,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | |||
| 430 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 434 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
| 431 | .supports_fw_dump = false, | 435 | .supports_fw_dump = false, |
| 432 | .auto_tdls = false, | 436 | .auto_tdls = false, |
| 437 | .can_ext_scan = true, | ||
| 433 | }; | 438 | }; |
| 434 | 439 | ||
| 435 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | 440 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { |
| @@ -444,6 +449,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | |||
| 444 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 449 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
| 445 | .supports_fw_dump = false, | 450 | .supports_fw_dump = false, |
| 446 | .auto_tdls = false, | 451 | .auto_tdls = false, |
| 452 | .can_ext_scan = true, | ||
| 447 | }; | 453 | }; |
| 448 | 454 | ||
| 449 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | 455 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { |
| @@ -458,6 +464,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | |||
| 458 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 464 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
| 459 | .supports_fw_dump = true, | 465 | .supports_fw_dump = true, |
| 460 | .auto_tdls = false, | 466 | .auto_tdls = false, |
| 467 | .can_ext_scan = true, | ||
| 461 | }; | 468 | }; |
| 462 | 469 | ||
| 463 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { | 470 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { |
| @@ -472,6 +479,22 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { | |||
| 472 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 479 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
| 473 | .supports_fw_dump = false, | 480 | .supports_fw_dump = false, |
| 474 | .auto_tdls = true, | 481 | .auto_tdls = true, |
| 482 | .can_ext_scan = true, | ||
| 483 | }; | ||
| 484 | |||
| 485 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = { | ||
| 486 | .firmware = SD8801_DEFAULT_FW_NAME, | ||
| 487 | .reg = &mwifiex_reg_sd87xx, | ||
| 488 | .max_ports = 16, | ||
| 489 | .mp_agg_pkt_limit = 8, | ||
| 490 | .supports_sdio_new_mode = false, | ||
| 491 | .has_control_mask = true, | ||
| 492 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | ||
| 493 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | ||
| 494 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | ||
| 495 | .supports_fw_dump = false, | ||
| 496 | .auto_tdls = false, | ||
| 497 | .can_ext_scan = true, | ||
| 475 | }; | 498 | }; |
| 476 | 499 | ||
| 477 | /* | 500 | /* |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index f7b920d7a95a..f7d204ffd6e9 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
| @@ -1897,6 +1897,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
| 1897 | case HostCmd_CMD_TDLS_OPER: | 1897 | case HostCmd_CMD_TDLS_OPER: |
| 1898 | ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); | 1898 | ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); |
| 1899 | break; | 1899 | break; |
| 1900 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | ||
| 1901 | ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, | ||
| 1902 | data_buf); | ||
| 1903 | break; | ||
| 1900 | default: | 1904 | default: |
| 1901 | dev_err(priv->adapter->dev, | 1905 | dev_err(priv->adapter->dev, |
| 1902 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1906 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
| @@ -1911,6 +1915,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
| 1911 | * | 1915 | * |
| 1912 | * This is called after firmware download to bring the card to | 1916 | * This is called after firmware download to bring the card to |
| 1913 | * working state. | 1917 | * working state. |
| 1918 | * Function is also called during reinitialization of virtual | ||
| 1919 | * interfaces. | ||
| 1914 | * | 1920 | * |
| 1915 | * The following commands are issued sequentially - | 1921 | * The following commands are issued sequentially - |
| 1916 | * - Set PCI-Express host buffer configuration (PCIE only) | 1922 | * - Set PCI-Express host buffer configuration (PCIE only) |
| @@ -1925,7 +1931,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
| 1925 | * - Set 11d control | 1931 | * - Set 11d control |
| 1926 | * - Set MAC control (this must be the last command to initialize firmware) | 1932 | * - Set MAC control (this must be the last command to initialize firmware) |
| 1927 | */ | 1933 | */ |
| 1928 | int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | 1934 | int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) |
| 1929 | { | 1935 | { |
| 1930 | struct mwifiex_adapter *adapter = priv->adapter; | 1936 | struct mwifiex_adapter *adapter = priv->adapter; |
| 1931 | int ret; | 1937 | int ret; |
| @@ -2059,9 +2065,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
| 2059 | "11D: failed to enable 11D\n"); | 2065 | "11D: failed to enable 11D\n"); |
| 2060 | } | 2066 | } |
| 2061 | 2067 | ||
| 2062 | /* set last_init_cmd before sending the command */ | ||
| 2063 | priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; | ||
| 2064 | |||
| 2065 | /* Send cmd to FW to configure 11n specific configuration | 2068 | /* Send cmd to FW to configure 11n specific configuration |
| 2066 | * (Short GI, Channel BW, Green field support etc.) for transmit | 2069 | * (Short GI, Channel BW, Green field support etc.) for transmit |
| 2067 | */ | 2070 | */ |
| @@ -2069,7 +2072,11 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
| 2069 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG, | 2072 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG, |
| 2070 | HostCmd_ACT_GEN_SET, 0, &tx_cfg, true); | 2073 | HostCmd_ACT_GEN_SET, 0, &tx_cfg, true); |
| 2071 | 2074 | ||
| 2072 | ret = -EINPROGRESS; | 2075 | if (init) { |
| 2076 | /* set last_init_cmd before sending the command */ | ||
| 2077 | priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; | ||
| 2078 | ret = -EINPROGRESS; | ||
| 2079 | } | ||
| 2073 | 2080 | ||
| 2074 | return ret; | 2081 | return ret; |
| 2075 | } | 2082 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 65d10a33eab5..5f8da5924666 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
| @@ -1105,6 +1105,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
| 1105 | case HostCmd_CMD_UAP_SYS_CONFIG: | 1105 | case HostCmd_CMD_UAP_SYS_CONFIG: |
| 1106 | break; | 1106 | break; |
| 1107 | case HostCmd_CMD_UAP_BSS_START: | 1107 | case HostCmd_CMD_UAP_BSS_START: |
| 1108 | adapter->tx_lock_flag = false; | ||
| 1109 | adapter->pps_uapsd_mode = false; | ||
| 1110 | adapter->delay_null_pkt = false; | ||
| 1108 | priv->bss_started = 1; | 1111 | priv->bss_started = 1; |
| 1109 | break; | 1112 | break; |
| 1110 | case HostCmd_CMD_UAP_BSS_STOP: | 1113 | case HostCmd_CMD_UAP_BSS_STOP: |
| @@ -1119,6 +1122,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
| 1119 | case HostCmd_CMD_TDLS_OPER: | 1122 | case HostCmd_CMD_TDLS_OPER: |
| 1120 | ret = mwifiex_ret_tdls_oper(priv, resp); | 1123 | ret = mwifiex_ret_tdls_oper(priv, resp); |
| 1121 | break; | 1124 | break; |
| 1125 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | ||
| 1126 | break; | ||
| 1122 | default: | 1127 | default: |
| 1123 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 1128 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
| 1124 | resp->command); | 1129 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 419e35f1dbf3..80ffe7412496 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
| @@ -312,8 +312,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
| 312 | adapter->ps_state = PS_STATE_AWAKE; | 312 | adapter->ps_state = PS_STATE_AWAKE; |
| 313 | adapter->pm_wakeup_card_req = false; | 313 | adapter->pm_wakeup_card_req = false; |
| 314 | adapter->pm_wakeup_fw_try = false; | 314 | adapter->pm_wakeup_fw_try = false; |
| 315 | mod_timer(&adapter->wakeup_timer, | 315 | del_timer_sync(&adapter->wakeup_timer); |
| 316 | jiffies + (HZ*3)); | ||
| 317 | break; | 316 | break; |
| 318 | } | 317 | } |
| 319 | if (!mwifiex_send_null_packet | 318 | if (!mwifiex_send_null_packet |
| @@ -487,7 +486,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
| 487 | 486 | ||
| 488 | case EVENT_REMAIN_ON_CHAN_EXPIRED: | 487 | case EVENT_REMAIN_ON_CHAN_EXPIRED: |
| 489 | dev_dbg(adapter->dev, "event: Remain on channel expired\n"); | 488 | dev_dbg(adapter->dev, "event: Remain on channel expired\n"); |
| 490 | cfg80211_remain_on_channel_expired(priv->wdev, | 489 | cfg80211_remain_on_channel_expired(&priv->wdev, |
| 491 | priv->roc_cfg.cookie, | 490 | priv->roc_cfg.cookie, |
| 492 | &priv->roc_cfg.chan, | 491 | &priv->roc_cfg.chan, |
| 493 | GFP_ATOMIC); | 492 | GFP_ATOMIC); |
| @@ -516,6 +515,16 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
| 516 | mwifiex_parse_tx_status_event(priv, adapter->event_body); | 515 | mwifiex_parse_tx_status_event(priv, adapter->event_body); |
| 517 | break; | 516 | break; |
| 518 | 517 | ||
| 518 | case EVENT_CHANNEL_REPORT_RDY: | ||
| 519 | dev_dbg(adapter->dev, "event: Channel Report\n"); | ||
| 520 | ret = mwifiex_11h_handle_chanrpt_ready(priv, | ||
| 521 | adapter->event_skb); | ||
| 522 | break; | ||
| 523 | case EVENT_RADAR_DETECTED: | ||
| 524 | dev_dbg(adapter->dev, "event: Radar detected\n"); | ||
| 525 | ret = mwifiex_11h_handle_radar_detected(priv, | ||
| 526 | adapter->event_skb); | ||
| 527 | break; | ||
| 519 | default: | 528 | default: |
| 520 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 529 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
| 521 | eventcause); | 530 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index fb9c5fc83e5d..0599e41e253c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
| @@ -219,7 +219,7 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
| 219 | 219 | ||
| 220 | if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { | 220 | if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { |
| 221 | rcu_read_unlock(); | 221 | rcu_read_unlock(); |
| 222 | wiphy_dbg(priv->wdev->wiphy, | 222 | wiphy_dbg(priv->wdev.wiphy, |
| 223 | "11D: skip setting domain info in FW\n"); | 223 | "11D: skip setting domain info in FW\n"); |
| 224 | return 0; | 224 | return 0; |
| 225 | } | 225 | } |
| @@ -1135,36 +1135,6 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, | |||
| 1135 | return roc_cfg.status; | 1135 | return roc_cfg.status; |
| 1136 | } | 1136 | } |
| 1137 | 1137 | ||
| 1138 | int | ||
| 1139 | mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role) | ||
| 1140 | { | ||
| 1141 | if (GET_BSS_ROLE(priv) == bss_role) { | ||
| 1142 | dev_dbg(priv->adapter->dev, | ||
| 1143 | "info: already in the desired role.\n"); | ||
| 1144 | return 0; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | mwifiex_free_priv(priv); | ||
| 1148 | mwifiex_init_priv(priv); | ||
| 1149 | |||
| 1150 | priv->bss_role = bss_role; | ||
| 1151 | switch (bss_role) { | ||
| 1152 | case MWIFIEX_BSS_ROLE_UAP: | ||
| 1153 | priv->bss_mode = NL80211_IFTYPE_AP; | ||
| 1154 | break; | ||
| 1155 | case MWIFIEX_BSS_ROLE_STA: | ||
| 1156 | case MWIFIEX_BSS_ROLE_ANY: | ||
| 1157 | default: | ||
| 1158 | priv->bss_mode = NL80211_IFTYPE_STATION; | ||
| 1159 | break; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, | ||
| 1163 | HostCmd_ACT_GEN_SET, 0, NULL, true); | ||
| 1164 | |||
| 1165 | return mwifiex_sta_init_cmd(priv, false); | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | /* | 1138 | /* |
| 1169 | * Sends IOCTL request to get statistics information. | 1139 | * Sends IOCTL request to get statistics information. |
| 1170 | * | 1140 | * |
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 1debe76017b1..5ce2d9a4f919 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c | |||
| @@ -183,9 +183,13 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
| 183 | } | 183 | } |
| 184 | switch (ret) { | 184 | switch (ret) { |
| 185 | case -EBUSY: | 185 | case -EBUSY: |
| 186 | adapter->data_sent = true; | 186 | dev_kfree_skb_any(skb); |
| 187 | /* Fall through FAILURE handling */ | 187 | dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", |
| 188 | __func__, ret); | ||
| 189 | adapter->dbg.num_tx_host_to_card_failure++; | ||
| 190 | break; | ||
| 188 | case -1: | 191 | case -1: |
| 192 | adapter->data_sent = false; | ||
| 189 | dev_kfree_skb_any(skb); | 193 | dev_kfree_skb_any(skb); |
| 190 | dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", | 194 | dev_err(adapter->dev, "%s: host_to_card failed: ret=%d\n", |
| 191 | __func__, ret); | 195 | __func__, ret); |
| @@ -198,6 +202,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
| 198 | adapter->tx_lock_flag = true; | 202 | adapter->tx_lock_flag = true; |
| 199 | break; | 203 | break; |
| 200 | case -EINPROGRESS: | 204 | case -EINPROGRESS: |
| 205 | adapter->tx_lock_flag = true; | ||
| 201 | break; | 206 | break; |
| 202 | default: | 207 | default: |
| 203 | break; | 208 | break; |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 6ae133333363..ac93557cbdc9 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
| @@ -227,7 +227,7 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, | |||
| 227 | /* consumes ack_skb */ | 227 | /* consumes ack_skb */ |
| 228 | skb_complete_wifi_ack(ack_skb, !tx_status->status); | 228 | skb_complete_wifi_ack(ack_skb, !tx_status->status); |
| 229 | } else { | 229 | } else { |
| 230 | cfg80211_mgmt_tx_status(priv->wdev, tx_info->cookie, | 230 | cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie, |
| 231 | ack_skb->data, ack_skb->len, | 231 | ack_skb->data, ack_skb->len, |
| 232 | !tx_status->status, GFP_ATOMIC); | 232 | !tx_status->status, GFP_ATOMIC); |
| 233 | dev_kfree_skb_any(ack_skb); | 233 | dev_kfree_skb_any(ack_skb); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 0f347fdefa0a..f5c2af01ba0a 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
| @@ -761,6 +761,11 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
| 761 | if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) | 761 | if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) |
| 762 | return -1; | 762 | return -1; |
| 763 | break; | 763 | break; |
| 764 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | ||
| 765 | if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf, | ||
| 766 | data_buf)) | ||
| 767 | return -1; | ||
| 768 | break; | ||
| 764 | default: | 769 | default: |
| 765 | dev_err(priv->adapter->dev, | 770 | dev_err(priv->adapter->dev, |
| 766 | "PREP_CMD: unknown cmd %#x\n", cmd_no); | 771 | "PREP_CMD: unknown cmd %#x\n", cmd_no); |
| @@ -769,3 +774,68 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | |||
| 769 | 774 | ||
| 770 | return 0; | 775 | return 0; |
| 771 | } | 776 | } |
| 777 | |||
| 778 | void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg, | ||
| 779 | struct cfg80211_chan_def chandef) | ||
| 780 | { | ||
| 781 | u8 config_bands = 0; | ||
| 782 | |||
| 783 | bss_cfg->channel = ieee80211_frequency_to_channel( | ||
| 784 | chandef.chan->center_freq); | ||
| 785 | |||
| 786 | /* Set appropriate bands */ | ||
| 787 | if (chandef.chan->band == IEEE80211_BAND_2GHZ) { | ||
| 788 | bss_cfg->band_cfg = BAND_CONFIG_BG; | ||
| 789 | config_bands = BAND_B | BAND_G; | ||
| 790 | |||
| 791 | if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
| 792 | config_bands |= BAND_GN; | ||
| 793 | } else { | ||
| 794 | bss_cfg->band_cfg = BAND_CONFIG_A; | ||
| 795 | config_bands = BAND_A; | ||
| 796 | |||
| 797 | if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | ||
| 798 | config_bands |= BAND_AN; | ||
| 799 | |||
| 800 | if (chandef.width > NL80211_CHAN_WIDTH_40) | ||
| 801 | config_bands |= BAND_AAC; | ||
| 802 | } | ||
| 803 | } | ||
| 804 | |||
| 805 | int mwifiex_config_start_uap(struct mwifiex_private *priv, | ||
| 806 | struct mwifiex_uap_bss_param *bss_cfg) | ||
| 807 | { | ||
| 808 | if (mwifiex_del_mgmt_ies(priv)) | ||
| 809 | dev_err(priv->adapter->dev, "Failed to delete mgmt IEs!\n"); | ||
| 810 | |||
| 811 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
| 812 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { | ||
| 813 | dev_err(priv->adapter->dev, "Failed to stop the BSS\n"); | ||
| 814 | return -1; | ||
| 815 | } | ||
| 816 | |||
| 817 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
| 818 | HostCmd_ACT_GEN_SET, | ||
| 819 | UAP_BSS_PARAMS_I, bss_cfg, false)) { | ||
| 820 | dev_err(priv->adapter->dev, "Failed to set the SSID\n"); | ||
| 821 | return -1; | ||
| 822 | } | ||
| 823 | |||
| 824 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, | ||
| 825 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { | ||
| 826 | dev_err(priv->adapter->dev, "Failed to start the BSS\n"); | ||
| 827 | return -1; | ||
| 828 | } | ||
| 829 | |||
| 830 | if (priv->sec_info.wep_enabled) | ||
| 831 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; | ||
| 832 | else | ||
| 833 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | ||
| 834 | |||
| 835 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, | ||
| 836 | HostCmd_ACT_GEN_SET, 0, | ||
| 837 | &priv->curr_pkt_filter, true)) | ||
| 838 | return -1; | ||
| 839 | |||
| 840 | return 0; | ||
| 841 | } | ||
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index f31086cdf937..f4794cdc36d2 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c | |||
| @@ -68,7 +68,6 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
| 68 | len = ETH_ALEN; | 68 | len = ETH_ALEN; |
| 69 | 69 | ||
| 70 | if (len != -1) { | 70 | if (len != -1) { |
| 71 | sinfo.filled = STATION_INFO_ASSOC_REQ_IES; | ||
| 72 | sinfo.assoc_req_ies = &event->data[len]; | 71 | sinfo.assoc_req_ies = &event->data[len]; |
| 73 | len = (u8 *)sinfo.assoc_req_ies - | 72 | len = (u8 *)sinfo.assoc_req_ies - |
| 74 | (u8 *)&event->frame_control; | 73 | (u8 *)&event->frame_control; |
| @@ -179,6 +178,53 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
| 179 | dev_dbg(adapter->dev, "event: TX_STATUS Report\n"); | 178 | dev_dbg(adapter->dev, "event: TX_STATUS Report\n"); |
| 180 | mwifiex_parse_tx_status_event(priv, adapter->event_body); | 179 | mwifiex_parse_tx_status_event(priv, adapter->event_body); |
| 181 | break; | 180 | break; |
| 181 | case EVENT_PS_SLEEP: | ||
| 182 | dev_dbg(adapter->dev, "info: EVENT: SLEEP\n"); | ||
| 183 | |||
| 184 | adapter->ps_state = PS_STATE_PRE_SLEEP; | ||
| 185 | |||
| 186 | mwifiex_check_ps_cond(adapter); | ||
| 187 | break; | ||
| 188 | |||
| 189 | case EVENT_PS_AWAKE: | ||
| 190 | dev_dbg(adapter->dev, "info: EVENT: AWAKE\n"); | ||
| 191 | if (!adapter->pps_uapsd_mode && | ||
| 192 | priv->media_connected && adapter->sleep_period.period) { | ||
| 193 | adapter->pps_uapsd_mode = true; | ||
| 194 | dev_dbg(adapter->dev, | ||
| 195 | "event: PPS/UAPSD mode activated\n"); | ||
| 196 | } | ||
| 197 | adapter->tx_lock_flag = false; | ||
| 198 | if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { | ||
| 199 | if (mwifiex_check_last_packet_indication(priv)) { | ||
| 200 | if (adapter->data_sent) { | ||
| 201 | adapter->ps_state = PS_STATE_AWAKE; | ||
| 202 | adapter->pm_wakeup_card_req = false; | ||
| 203 | adapter->pm_wakeup_fw_try = false; | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | if (!mwifiex_send_null_packet | ||
| 207 | (priv, | ||
| 208 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | | ||
| 209 | MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) | ||
| 210 | adapter->ps_state = | ||
| 211 | PS_STATE_SLEEP; | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | adapter->ps_state = PS_STATE_AWAKE; | ||
| 216 | adapter->pm_wakeup_card_req = false; | ||
| 217 | adapter->pm_wakeup_fw_try = false; | ||
| 218 | break; | ||
| 219 | |||
| 220 | case EVENT_CHANNEL_REPORT_RDY: | ||
| 221 | dev_dbg(adapter->dev, "event: Channel Report\n"); | ||
| 222 | mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb); | ||
| 223 | break; | ||
| 224 | case EVENT_RADAR_DETECTED: | ||
| 225 | dev_dbg(adapter->dev, "event: Radar detected\n"); | ||
| 226 | mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); | ||
| 227 | break; | ||
| 182 | default: | 228 | default: |
| 183 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 229 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
| 184 | eventcause); | 230 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 6c62995028e6..223873022ffe 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
| @@ -37,6 +37,11 @@ static struct usb_device_id mwifiex_usb_table[] = { | |||
| 37 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, | 37 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, |
| 38 | USB_CLASS_VENDOR_SPEC, | 38 | USB_CLASS_VENDOR_SPEC, |
| 39 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, | 39 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, |
| 40 | /* 8801 */ | ||
| 41 | {USB_DEVICE(USB8XXX_VID, USB8801_PID_1)}, | ||
| 42 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2, | ||
| 43 | USB_CLASS_VENDOR_SPEC, | ||
| 44 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, | ||
| 40 | /* 8897 */ | 45 | /* 8897 */ |
| 41 | {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)}, | 46 | {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)}, |
| 42 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2, | 47 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2, |
| @@ -361,11 +366,13 @@ static int mwifiex_usb_probe(struct usb_interface *intf, | |||
| 361 | switch (id_product) { | 366 | switch (id_product) { |
| 362 | case USB8766_PID_1: | 367 | case USB8766_PID_1: |
| 363 | case USB8797_PID_1: | 368 | case USB8797_PID_1: |
| 369 | case USB8801_PID_1: | ||
| 364 | case USB8897_PID_1: | 370 | case USB8897_PID_1: |
| 365 | card->usb_boot_state = USB8XXX_FW_DNLD; | 371 | card->usb_boot_state = USB8XXX_FW_DNLD; |
| 366 | break; | 372 | break; |
| 367 | case USB8766_PID_2: | 373 | case USB8766_PID_2: |
| 368 | case USB8797_PID_2: | 374 | case USB8797_PID_2: |
| 375 | case USB8801_PID_2: | ||
| 369 | case USB8897_PID_2: | 376 | case USB8897_PID_2: |
| 370 | card->usb_boot_state = USB8XXX_FW_READY; | 377 | card->usb_boot_state = USB8XXX_FW_READY; |
| 371 | break; | 378 | break; |
| @@ -792,11 +799,19 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
| 792 | case USB8897_PID_2: | 799 | case USB8897_PID_2: |
| 793 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; | 800 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; |
| 794 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); | 801 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); |
| 802 | adapter->ext_scan = true; | ||
| 795 | break; | 803 | break; |
| 796 | case USB8766_PID_1: | 804 | case USB8766_PID_1: |
| 797 | case USB8766_PID_2: | 805 | case USB8766_PID_2: |
| 798 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | 806 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; |
| 799 | strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME); | 807 | strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME); |
| 808 | adapter->ext_scan = true; | ||
| 809 | break; | ||
| 810 | case USB8801_PID_1: | ||
| 811 | case USB8801_PID_2: | ||
| 812 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | ||
| 813 | strcpy(adapter->fw_name, USB8801_DEFAULT_FW_NAME); | ||
| 814 | adapter->ext_scan = false; | ||
| 800 | break; | 815 | break; |
| 801 | case USB8797_PID_1: | 816 | case USB8797_PID_1: |
| 802 | case USB8797_PID_2: | 817 | case USB8797_PID_2: |
| @@ -1083,4 +1098,5 @@ MODULE_VERSION(USB_VERSION); | |||
| 1083 | MODULE_LICENSE("GPL v2"); | 1098 | MODULE_LICENSE("GPL v2"); |
| 1084 | MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); | 1099 | MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); |
| 1085 | MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); | 1100 | MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); |
| 1101 | MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME); | ||
| 1086 | MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); | 1102 | MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); |
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index 0ad1bebc3f93..57e1a5736318 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h | |||
| @@ -30,6 +30,9 @@ | |||
| 30 | #define USB8797_PID_2 0x2044 | 30 | #define USB8797_PID_2 0x2044 |
| 31 | #define USB8897_PID_1 0x2045 | 31 | #define USB8897_PID_1 0x2045 |
| 32 | #define USB8897_PID_2 0x2046 | 32 | #define USB8897_PID_2 0x2046 |
| 33 | #define USB8801_PID_1 0x2049 | ||
| 34 | #define USB8801_PID_2 0x204a | ||
| 35 | |||
| 33 | 36 | ||
| 34 | #define USB8XXX_FW_DNLD 1 | 37 | #define USB8XXX_FW_DNLD 1 |
| 35 | #define USB8XXX_FW_READY 2 | 38 | #define USB8XXX_FW_READY 2 |
| @@ -41,6 +44,7 @@ | |||
| 41 | 44 | ||
| 42 | #define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" | 45 | #define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" |
| 43 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" | 46 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" |
| 47 | #define USB8801_DEFAULT_FW_NAME "mrvl/usb8801_uapsta.bin" | ||
| 44 | #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" | 48 | #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" |
| 45 | 49 | ||
| 46 | #define FW_DNLD_TX_BUF_SIZE 620 | 50 | #define FW_DNLD_TX_BUF_SIZE 620 |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 707319799942..308550611f22 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
| @@ -387,7 +387,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |||
| 387 | pkt_len -= ETH_ALEN + sizeof(pkt_len); | 387 | pkt_len -= ETH_ALEN + sizeof(pkt_len); |
| 388 | rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); | 388 | rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); |
| 389 | 389 | ||
| 390 | cfg80211_rx_mgmt(priv->wdev, priv->roc_cfg.chan.center_freq, | 390 | cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq, |
| 391 | CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len, | 391 | CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len, |
| 392 | 0); | 392 | 0); |
| 393 | 393 | ||
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index ffffd2c5a76e..ef717acec8b7 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
| @@ -1228,6 +1228,9 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
| 1228 | case -EINPROGRESS: | 1228 | case -EINPROGRESS: |
| 1229 | if (adapter->iface_type != MWIFIEX_PCIE) | 1229 | if (adapter->iface_type != MWIFIEX_PCIE) |
| 1230 | adapter->data_sent = false; | 1230 | adapter->data_sent = false; |
| 1231 | break; | ||
| 1232 | case 0: | ||
| 1233 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
| 1231 | default: | 1234 | default: |
| 1232 | break; | 1235 | break; |
| 1233 | } | 1236 | } |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b8d1e04aa9b9..f9b1218c761a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
| @@ -3098,14 +3098,14 @@ static void mwl8k_update_survey(struct mwl8k_priv *priv, | |||
| 3098 | 3098 | ||
| 3099 | cca_cnt = ioread32(priv->regs + NOK_CCA_CNT_REG); | 3099 | cca_cnt = ioread32(priv->regs + NOK_CCA_CNT_REG); |
| 3100 | cca_cnt /= 1000; /* uSecs to mSecs */ | 3100 | cca_cnt /= 1000; /* uSecs to mSecs */ |
| 3101 | survey->channel_time_busy = (u64) cca_cnt; | 3101 | survey->time_busy = (u64) cca_cnt; |
| 3102 | 3102 | ||
| 3103 | rx_rdy = ioread32(priv->regs + BBU_RXRDY_CNT_REG); | 3103 | rx_rdy = ioread32(priv->regs + BBU_RXRDY_CNT_REG); |
| 3104 | rx_rdy /= 1000; /* uSecs to mSecs */ | 3104 | rx_rdy /= 1000; /* uSecs to mSecs */ |
| 3105 | survey->channel_time_rx = (u64) rx_rdy; | 3105 | survey->time_rx = (u64) rx_rdy; |
| 3106 | 3106 | ||
| 3107 | priv->channel_time = jiffies - priv->channel_time; | 3107 | priv->channel_time = jiffies - priv->channel_time; |
| 3108 | survey->channel_time = jiffies_to_msecs(priv->channel_time); | 3108 | survey->time = jiffies_to_msecs(priv->channel_time); |
| 3109 | 3109 | ||
| 3110 | survey->channel = channel; | 3110 | survey->channel = channel; |
| 3111 | 3111 | ||
| @@ -3115,9 +3115,9 @@ static void mwl8k_update_survey(struct mwl8k_priv *priv, | |||
| 3115 | survey->noise = nf * -1; | 3115 | survey->noise = nf * -1; |
| 3116 | 3116 | ||
| 3117 | survey->filled = SURVEY_INFO_NOISE_DBM | | 3117 | survey->filled = SURVEY_INFO_NOISE_DBM | |
| 3118 | SURVEY_INFO_CHANNEL_TIME | | 3118 | SURVEY_INFO_TIME | |
| 3119 | SURVEY_INFO_CHANNEL_TIME_BUSY | | 3119 | SURVEY_INFO_TIME_BUSY | |
| 3120 | SURVEY_INFO_CHANNEL_TIME_RX; | 3120 | SURVEY_INFO_TIME_RX; |
| 3121 | } | 3121 | } |
| 3122 | 3122 | ||
| 3123 | /* | 3123 | /* |
diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig index 60698b020851..6d831d4d1b5f 100644 --- a/drivers/net/wireless/orinoco/Kconfig +++ b/drivers/net/wireless/orinoco/Kconfig | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | config HERMES | 1 | config HERMES |
| 2 | tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" | 2 | tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" |
| 3 | depends on (PPC_PMAC || PCI || PCMCIA) | 3 | depends on (PPC_PMAC || PCI || PCMCIA) |
| 4 | depends on CFG80211 && CFG80211_WEXT | 4 | depends on CFG80211 |
| 5 | select CFG80211_WEXT | ||
| 5 | select WIRELESS_EXT | 6 | select WIRELESS_EXT |
| 6 | select WEXT_SPY | 7 | select WEXT_SPY |
| 7 | select WEXT_PRIV | 8 | select WEXT_PRIV |
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 38ec8d19ac29..c410180479e6 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c | |||
| @@ -2342,7 +2342,7 @@ void free_orinocodev(struct orinoco_private *priv) | |||
| 2342 | list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) { | 2342 | list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) { |
| 2343 | list_del(&sd->list); | 2343 | list_del(&sd->list); |
| 2344 | 2344 | ||
| 2345 | if ((sd->len > 0) && sd->buf) | 2345 | if (sd->len > 0) |
| 2346 | kfree(sd->buf); | 2346 | kfree(sd->buf); |
| 2347 | kfree(sd); | 2347 | kfree(sd); |
| 2348 | } | 2348 | } |
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index b6bdad632842..74219d59d7e1 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c | |||
| @@ -94,7 +94,7 @@ static int orinoco_pci_cor_reset(struct orinoco_private *priv) | |||
| 94 | mdelay(HERMES_PCI_COR_OFFT); | 94 | mdelay(HERMES_PCI_COR_OFFT); |
| 95 | 95 | ||
| 96 | /* The card is ready when it's no longer busy */ | 96 | /* The card is ready when it's no longer busy */ |
| 97 | timeout = jiffies + (HERMES_PCI_COR_BUSYT * HZ / 1000); | 97 | timeout = jiffies + msecs_to_jiffies(HERMES_PCI_COR_BUSYT); |
| 98 | reg = hermes_read_regn(hw, CMD); | 98 | reg = hermes_read_regn(hw, CMD); |
| 99 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { | 99 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { |
| 100 | mdelay(1); | 100 | mdelay(1); |
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index b8f6e5c431ae..8b045236b6e0 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c | |||
| @@ -121,7 +121,7 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv) | |||
| 121 | mdelay(1); | 121 | mdelay(1); |
| 122 | 122 | ||
| 123 | /* Just in case, wait more until the card is no longer busy */ | 123 | /* Just in case, wait more until the card is no longer busy */ |
| 124 | timeout = jiffies + (PLX_RESET_TIME * HZ / 1000); | 124 | timeout = jiffies + msecs_to_jiffies(PLX_RESET_TIME); |
| 125 | reg = hermes_read_regn(hw, CMD); | 125 | reg = hermes_read_regn(hw, CMD); |
| 126 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { | 126 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { |
| 127 | mdelay(1); | 127 | mdelay(1); |
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 79d0e33b625e..20ce569b8a43 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c | |||
| @@ -71,7 +71,7 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | |||
| 71 | mdelay(1); | 71 | mdelay(1); |
| 72 | 72 | ||
| 73 | /* Just in case, wait more until the card is no longer busy */ | 73 | /* Just in case, wait more until the card is no longer busy */ |
| 74 | timeout = jiffies + (TMD_RESET_TIME * HZ / 1000); | 74 | timeout = jiffies + msecs_to_jiffies(TMD_RESET_TIME); |
| 75 | reg = hermes_read_regn(hw, CMD); | 75 | reg = hermes_read_regn(hw, CMD); |
| 76 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { | 76 | while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { |
| 77 | mdelay(1); | 77 | mdelay(1); |
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 0fe67d2da208..2fe713eda7ad 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
| @@ -196,9 +196,9 @@ static int p54_generate_band(struct ieee80211_hw *dev, | |||
| 196 | dest->max_power = chan->max_power; | 196 | dest->max_power = chan->max_power; |
| 197 | priv->survey[*chan_num].channel = &tmp->channels[j]; | 197 | priv->survey[*chan_num].channel = &tmp->channels[j]; |
| 198 | priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM | | 198 | priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM | |
| 199 | SURVEY_INFO_CHANNEL_TIME | | 199 | SURVEY_INFO_TIME | |
| 200 | SURVEY_INFO_CHANNEL_TIME_BUSY | | 200 | SURVEY_INFO_TIME_BUSY | |
| 201 | SURVEY_INFO_CHANNEL_TIME_TX; | 201 | SURVEY_INFO_TIME_TX; |
| 202 | dest->hw_value = (*chan_num); | 202 | dest->hw_value = (*chan_num); |
| 203 | j++; | 203 | j++; |
| 204 | (*chan_num)++; | 204 | (*chan_num)++; |
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index bc065e8e348b..5367d510b22d 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c | |||
| @@ -220,6 +220,7 @@ int p54_download_eeprom(struct p54_common *priv, void *buf, | |||
| 220 | struct sk_buff *skb; | 220 | struct sk_buff *skb; |
| 221 | size_t eeprom_hdr_size; | 221 | size_t eeprom_hdr_size; |
| 222 | int ret = 0; | 222 | int ret = 0; |
| 223 | long timeout; | ||
| 223 | 224 | ||
| 224 | if (priv->fw_var >= 0x509) | 225 | if (priv->fw_var >= 0x509) |
| 225 | eeprom_hdr_size = sizeof(*eeprom_hdr); | 226 | eeprom_hdr_size = sizeof(*eeprom_hdr); |
| @@ -249,9 +250,11 @@ int p54_download_eeprom(struct p54_common *priv, void *buf, | |||
| 249 | 250 | ||
| 250 | p54_tx(priv, skb); | 251 | p54_tx(priv, skb); |
| 251 | 252 | ||
| 252 | if (!wait_for_completion_interruptible_timeout( | 253 | timeout = wait_for_completion_interruptible_timeout( |
| 253 | &priv->eeprom_comp, HZ)) { | 254 | &priv->eeprom_comp, HZ); |
| 254 | wiphy_err(priv->hw->wiphy, "device does not respond!\n"); | 255 | if (timeout <= 0) { |
| 256 | wiphy_err(priv->hw->wiphy, | ||
| 257 | "device does not respond or signal received!\n"); | ||
| 255 | ret = -EBUSY; | 258 | ret = -EBUSY; |
| 256 | } | 259 | } |
| 257 | priv->eeprom = NULL; | 260 | priv->eeprom = NULL; |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 97aeff0edb84..b9250d75d253 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
| @@ -305,9 +305,9 @@ static void p54_reset_stats(struct p54_common *priv) | |||
| 305 | struct survey_info *info = &priv->survey[chan->hw_value]; | 305 | struct survey_info *info = &priv->survey[chan->hw_value]; |
| 306 | 306 | ||
| 307 | /* only reset channel statistics, don't touch .filled, etc. */ | 307 | /* only reset channel statistics, don't touch .filled, etc. */ |
| 308 | info->channel_time = 0; | 308 | info->time = 0; |
| 309 | info->channel_time_busy = 0; | 309 | info->time_busy = 0; |
| 310 | info->channel_time_tx = 0; | 310 | info->time_tx = 0; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | priv->update_stats = true; | 313 | priv->update_stats = true; |
| @@ -575,6 +575,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
| 575 | key->hw_key_idx = 0xff; | 575 | key->hw_key_idx = 0xff; |
| 576 | goto out_unlock; | 576 | goto out_unlock; |
| 577 | } | 577 | } |
| 578 | |||
| 579 | key->flags |= IEEE80211_KEY_FLAG_RESERVE_TAILROOM; | ||
| 578 | } else { | 580 | } else { |
| 579 | slot = key->hw_key_idx; | 581 | slot = key->hw_key_idx; |
| 580 | 582 | ||
| @@ -634,7 +636,7 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx, | |||
| 634 | 636 | ||
| 635 | if (in_use) { | 637 | if (in_use) { |
| 636 | /* test if the reported statistics are valid. */ | 638 | /* test if the reported statistics are valid. */ |
| 637 | if (survey->channel_time != 0) { | 639 | if (survey->time != 0) { |
| 638 | survey->filled |= SURVEY_INFO_IN_USE; | 640 | survey->filled |= SURVEY_INFO_IN_USE; |
| 639 | } else { | 641 | } else { |
| 640 | /* | 642 | /* |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index d4aee64fb5ea..27a49068d32d 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
| @@ -431,6 +431,7 @@ static int p54p_open(struct ieee80211_hw *dev) | |||
| 431 | { | 431 | { |
| 432 | struct p54p_priv *priv = dev->priv; | 432 | struct p54p_priv *priv = dev->priv; |
| 433 | int err; | 433 | int err; |
| 434 | long timeout; | ||
| 434 | 435 | ||
| 435 | init_completion(&priv->boot_comp); | 436 | init_completion(&priv->boot_comp); |
| 436 | err = request_irq(priv->pdev->irq, p54p_interrupt, | 437 | err = request_irq(priv->pdev->irq, p54p_interrupt, |
| @@ -468,10 +469,12 @@ static int p54p_open(struct ieee80211_hw *dev) | |||
| 468 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); | 469 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); |
| 469 | P54P_READ(dev_int); | 470 | P54P_READ(dev_int); |
| 470 | 471 | ||
| 471 | if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { | 472 | timeout = wait_for_completion_interruptible_timeout( |
| 473 | &priv->boot_comp, HZ); | ||
| 474 | if (timeout <= 0) { | ||
| 472 | wiphy_err(dev->wiphy, "Cannot boot firmware!\n"); | 475 | wiphy_err(dev->wiphy, "Cannot boot firmware!\n"); |
| 473 | p54p_stop(dev); | 476 | p54p_stop(dev); |
| 474 | return -ETIMEDOUT; | 477 | return timeout ? -ERESTARTSYS : -ETIMEDOUT; |
| 475 | } | 478 | } |
| 476 | 479 | ||
| 477 | P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); | 480 | P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 153c61539ec8..24e5ff9a9272 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
| @@ -587,13 +587,13 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) | |||
| 587 | if (chan) { | 587 | if (chan) { |
| 588 | struct survey_info *survey = &priv->survey[chan->hw_value]; | 588 | struct survey_info *survey = &priv->survey[chan->hw_value]; |
| 589 | survey->noise = clamp(priv->noise, -128, 127); | 589 | survey->noise = clamp(priv->noise, -128, 127); |
| 590 | survey->channel_time = priv->survey_raw.active; | 590 | survey->time = priv->survey_raw.active; |
| 591 | survey->channel_time_tx = priv->survey_raw.tx; | 591 | survey->time_tx = priv->survey_raw.tx; |
| 592 | survey->channel_time_busy = priv->survey_raw.tx + | 592 | survey->time_busy = priv->survey_raw.tx + |
| 593 | priv->survey_raw.cca; | 593 | priv->survey_raw.cca; |
| 594 | do_div(survey->channel_time, 1024); | 594 | do_div(survey->time, 1024); |
| 595 | do_div(survey->channel_time_tx, 1024); | 595 | do_div(survey->time_tx, 1024); |
| 596 | do_div(survey->channel_time_busy, 1024); | 596 | do_div(survey->time_busy, 1024); |
| 597 | } | 597 | } |
| 598 | 598 | ||
| 599 | tmp = p54_find_and_unlink_skb(priv, hdr->req_id); | 599 | tmp = p54_find_and_unlink_skb(priv, hdr->req_id); |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 1a4facd1fbf3..60d44ce9c017 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
| @@ -2478,7 +2478,7 @@ static void rndis_fill_station_info(struct usbnet *usbdev, | |||
| 2478 | ret = rndis_query_oid(usbdev, RNDIS_OID_GEN_LINK_SPEED, &linkspeed, &len); | 2478 | ret = rndis_query_oid(usbdev, RNDIS_OID_GEN_LINK_SPEED, &linkspeed, &len); |
| 2479 | if (ret == 0) { | 2479 | if (ret == 0) { |
| 2480 | sinfo->txrate.legacy = le32_to_cpu(linkspeed) / 1000; | 2480 | sinfo->txrate.legacy = le32_to_cpu(linkspeed) / 1000; |
| 2481 | sinfo->filled |= STATION_INFO_TX_BITRATE; | 2481 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
| 2482 | } | 2482 | } |
| 2483 | 2483 | ||
| 2484 | len = sizeof(rssi); | 2484 | len = sizeof(rssi); |
| @@ -2486,7 +2486,7 @@ static void rndis_fill_station_info(struct usbnet *usbdev, | |||
| 2486 | &rssi, &len); | 2486 | &rssi, &len); |
| 2487 | if (ret == 0) { | 2487 | if (ret == 0) { |
| 2488 | sinfo->signal = level_to_qual(le32_to_cpu(rssi)); | 2488 | sinfo->signal = level_to_qual(le32_to_cpu(rssi)); |
| 2489 | sinfo->filled |= STATION_INFO_SIGNAL; | 2489 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 2490 | } | 2490 | } |
| 2491 | } | 2491 | } |
| 2492 | 2492 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 81ee481487cf..be2d54f257b1 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
| @@ -8020,13 +8020,13 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx, | |||
| 8020 | rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext); | 8020 | rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext); |
| 8021 | 8021 | ||
| 8022 | if (idle || busy) { | 8022 | if (idle || busy) { |
| 8023 | survey->filled = SURVEY_INFO_CHANNEL_TIME | | 8023 | survey->filled = SURVEY_INFO_TIME | |
| 8024 | SURVEY_INFO_CHANNEL_TIME_BUSY | | 8024 | SURVEY_INFO_TIME_BUSY | |
| 8025 | SURVEY_INFO_CHANNEL_TIME_EXT_BUSY; | 8025 | SURVEY_INFO_TIME_EXT_BUSY; |
| 8026 | 8026 | ||
| 8027 | survey->channel_time = (idle + busy) / 1000; | 8027 | survey->time = (idle + busy) / 1000; |
| 8028 | survey->channel_time_busy = busy / 1000; | 8028 | survey->time_busy = busy / 1000; |
| 8029 | survey->channel_time_ext_busy = busy_ext / 1000; | 8029 | survey->time_ext_busy = busy_ext / 1000; |
| 8030 | } | 8030 | } |
| 8031 | 8031 | ||
| 8032 | if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 8032 | if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index eb203163ed05..a31a12775f1a 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
| @@ -1010,6 +1010,16 @@ static int rtl_op_conf_tx(struct ieee80211_hw *hw, | |||
| 1010 | return 0; | 1010 | return 0; |
| 1011 | } | 1011 | } |
| 1012 | 1012 | ||
| 1013 | static void send_beacon_frame(struct ieee80211_hw *hw, | ||
| 1014 | struct ieee80211_vif *vif) | ||
| 1015 | { | ||
| 1016 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 1017 | struct sk_buff *skb = ieee80211_beacon_get(hw, vif); | ||
| 1018 | |||
| 1019 | if (skb) | ||
| 1020 | rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, NULL); | ||
| 1021 | } | ||
| 1022 | |||
| 1013 | static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | 1023 | static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, |
| 1014 | struct ieee80211_vif *vif, | 1024 | struct ieee80211_vif *vif, |
| 1015 | struct ieee80211_bss_conf *bss_conf, | 1025 | struct ieee80211_bss_conf *bss_conf, |
| @@ -1040,6 +1050,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1040 | 1050 | ||
| 1041 | if (rtlpriv->cfg->ops->linked_set_reg) | 1051 | if (rtlpriv->cfg->ops->linked_set_reg) |
| 1042 | rtlpriv->cfg->ops->linked_set_reg(hw); | 1052 | rtlpriv->cfg->ops->linked_set_reg(hw); |
| 1053 | send_beacon_frame(hw, vif); | ||
| 1043 | } | 1054 | } |
| 1044 | } | 1055 | } |
| 1045 | if ((changed & BSS_CHANGED_BEACON_ENABLED && | 1056 | if ((changed & BSS_CHANGED_BEACON_ENABLED && |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 846a2e6e34d8..88331d729b0e 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
| @@ -578,6 +578,13 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
| 578 | else | 578 | else |
| 579 | entry = (u8 *)(&ring->desc[ring->idx]); | 579 | entry = (u8 *)(&ring->desc[ring->idx]); |
| 580 | 580 | ||
| 581 | if (rtlpriv->cfg->ops->get_available_desc && | ||
| 582 | rtlpriv->cfg->ops->get_available_desc(hw, prio) <= 1) { | ||
| 583 | RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_DMESG, | ||
| 584 | "no available desc!\n"); | ||
| 585 | return; | ||
| 586 | } | ||
| 587 | |||
| 581 | if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx)) | 588 | if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx)) |
| 582 | return; | 589 | return; |
| 583 | ring->idx = (ring->idx + 1) % ring->entries; | 590 | ring->idx = (ring->idx + 1) % ring->entries; |
| @@ -641,10 +648,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
| 641 | 648 | ||
| 642 | ieee80211_tx_status_irqsafe(hw, skb); | 649 | ieee80211_tx_status_irqsafe(hw, skb); |
| 643 | 650 | ||
| 644 | if ((ring->entries - skb_queue_len(&ring->queue)) | 651 | if ((ring->entries - skb_queue_len(&ring->queue)) <= 4) { |
| 645 | == 2) { | ||
| 646 | 652 | ||
| 647 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, | 653 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, |
| 648 | "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n", | 654 | "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n", |
| 649 | prio, ring->idx, | 655 | prio, ring->idx, |
| 650 | skb_queue_len(&ring->queue)); | 656 | skb_queue_len(&ring->queue)); |
| @@ -786,7 +792,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
| 786 | rx_remained_cnt = | 792 | rx_remained_cnt = |
| 787 | rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw, | 793 | rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw, |
| 788 | hw_queue); | 794 | hw_queue); |
| 789 | if (rx_remained_cnt < 1) | 795 | if (rx_remained_cnt == 0) |
| 790 | return; | 796 | return; |
| 791 | 797 | ||
| 792 | } else { /* rx descriptor */ | 798 | } else { /* rx descriptor */ |
| @@ -834,18 +840,18 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
| 834 | else | 840 | else |
| 835 | skb_reserve(skb, stats.rx_drvinfo_size + | 841 | skb_reserve(skb, stats.rx_drvinfo_size + |
| 836 | stats.rx_bufshift); | 842 | stats.rx_bufshift); |
| 837 | |||
| 838 | } else { | 843 | } else { |
| 839 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 844 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
| 840 | "skb->end - skb->tail = %d, len is %d\n", | 845 | "skb->end - skb->tail = %d, len is %d\n", |
| 841 | skb->end - skb->tail, len); | 846 | skb->end - skb->tail, len); |
| 842 | break; | 847 | dev_kfree_skb_any(skb); |
| 848 | goto new_trx_end; | ||
| 843 | } | 849 | } |
| 844 | /* handle command packet here */ | 850 | /* handle command packet here */ |
| 845 | if (rtlpriv->cfg->ops->rx_command_packet && | 851 | if (rtlpriv->cfg->ops->rx_command_packet && |
| 846 | rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { | 852 | rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { |
| 847 | dev_kfree_skb_any(skb); | 853 | dev_kfree_skb_any(skb); |
| 848 | goto end; | 854 | goto new_trx_end; |
| 849 | } | 855 | } |
| 850 | 856 | ||
| 851 | /* | 857 | /* |
| @@ -895,6 +901,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
| 895 | } else { | 901 | } else { |
| 896 | dev_kfree_skb_any(skb); | 902 | dev_kfree_skb_any(skb); |
| 897 | } | 903 | } |
| 904 | new_trx_end: | ||
| 898 | if (rtlpriv->use_new_trx_flow) { | 905 | if (rtlpriv->use_new_trx_flow) { |
| 899 | rtlpci->rx_ring[hw_queue].next_rx_rp += 1; | 906 | rtlpci->rx_ring[hw_queue].next_rx_rp += 1; |
| 900 | rtlpci->rx_ring[hw_queue].next_rx_rp %= | 907 | rtlpci->rx_ring[hw_queue].next_rx_rp %= |
| @@ -910,7 +917,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
| 910 | rtlpriv->enter_ps = false; | 917 | rtlpriv->enter_ps = false; |
| 911 | schedule_work(&rtlpriv->works.lps_change_work); | 918 | schedule_work(&rtlpriv->works.lps_change_work); |
| 912 | } | 919 | } |
| 913 | end: | ||
| 914 | if (rtlpriv->use_new_trx_flow) { | 920 | if (rtlpriv->use_new_trx_flow) { |
| 915 | _rtl_pci_init_one_rxdesc(hw, (u8 *)buffer_desc, | 921 | _rtl_pci_init_one_rxdesc(hw, (u8 *)buffer_desc, |
| 916 | rxring_idx, | 922 | rxring_idx, |
| @@ -1672,6 +1678,15 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, | |||
| 1672 | } | 1678 | } |
| 1673 | } | 1679 | } |
| 1674 | 1680 | ||
| 1681 | if (rtlpriv->cfg->ops->get_available_desc && | ||
| 1682 | rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) { | ||
| 1683 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
| 1684 | "get_available_desc fail\n"); | ||
| 1685 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, | ||
| 1686 | flags); | ||
| 1687 | return skb->len; | ||
| 1688 | } | ||
| 1689 | |||
| 1675 | if (ieee80211_is_data_qos(fc)) { | 1690 | if (ieee80211_is_data_qos(fc)) { |
| 1676 | tid = rtl_get_tid(skb); | 1691 | tid = rtl_get_tid(skb); |
| 1677 | if (sta) { | 1692 | if (sta) { |
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 5e832306dba9..d4567d12e07e 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h | |||
| @@ -325,4 +325,11 @@ static inline void pci_write32_async(struct rtl_priv *rtlpriv, | |||
| 325 | writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); | 325 | writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | static inline u16 calc_fifo_space(u16 rp, u16 wp) | ||
| 329 | { | ||
| 330 | if (rp <= wp) | ||
| 331 | return RTL_PCI_MAX_RX_COUNT - 1 + rp - wp; | ||
| 332 | return rp - wp - 1; | ||
| 333 | } | ||
| 334 | |||
| 328 | #endif | 335 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 551321728ae0..fe4b699a12f5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
| @@ -1000,6 +1000,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) | |||
| 1000 | local_save_flags(flags); | 1000 | local_save_flags(flags); |
| 1001 | local_irq_enable(); | 1001 | local_irq_enable(); |
| 1002 | 1002 | ||
| 1003 | rtlhal->fw_ready = false; | ||
| 1003 | rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; | 1004 | rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; |
| 1004 | err = _rtl92cu_init_mac(hw); | 1005 | err = _rtl92cu_init_mac(hw); |
| 1005 | if (err) { | 1006 | if (err) { |
| @@ -1013,6 +1014,8 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) | |||
| 1013 | err = 1; | 1014 | err = 1; |
| 1014 | goto exit; | 1015 | goto exit; |
| 1015 | } | 1016 | } |
| 1017 | |||
| 1018 | rtlhal->fw_ready = true; | ||
| 1016 | rtlhal->last_hmeboxnum = 0; /* h2c */ | 1019 | rtlhal->last_hmeboxnum = 0; /* h2c */ |
| 1017 | _rtl92cu_phy_param_tab_init(hw); | 1020 | _rtl92cu_phy_param_tab_init(hw); |
| 1018 | rtl92cu_phy_mac_config(hw); | 1021 | rtl92cu_phy_mac_config(hw); |
| @@ -1509,6 +1512,7 @@ void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw) | |||
| 1509 | /* TODO: Modify later (Find the right parameters) | 1512 | /* TODO: Modify later (Find the right parameters) |
| 1510 | * NOTE: Fix test chip's bug (about contention windows's randomness) */ | 1513 | * NOTE: Fix test chip's bug (about contention windows's randomness) */ |
| 1511 | if ((mac->opmode == NL80211_IFTYPE_ADHOC) || | 1514 | if ((mac->opmode == NL80211_IFTYPE_ADHOC) || |
| 1515 | (mac->opmode == NL80211_IFTYPE_MESH_POINT) || | ||
| 1512 | (mac->opmode == NL80211_IFTYPE_AP)) { | 1516 | (mac->opmode == NL80211_IFTYPE_AP)) { |
| 1513 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); | 1517 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); |
| 1514 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); | 1518 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index 280c3da42993..01bcc2d218dc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c | |||
| @@ -546,7 +546,7 @@ static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw) | |||
| 546 | txpktbuf_bndy = 246; | 546 | txpktbuf_bndy = 246; |
| 547 | value8 = 0; | 547 | value8 = 0; |
| 548 | value32 = 0x80bf0d29; | 548 | value32 = 0x80bf0d29; |
| 549 | } else if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { | 549 | } else { |
| 550 | maxPage = 127; | 550 | maxPage = 127; |
| 551 | txpktbuf_bndy = 123; | 551 | txpktbuf_bndy = 123; |
| 552 | value8 = 0; | 552 | value8 = 0; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c index 45c128b91f7f..c5d4b8013cde 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c | |||
| @@ -666,7 +666,6 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
| 666 | struct sk_buff *skb = NULL; | 666 | struct sk_buff *skb = NULL; |
| 667 | 667 | ||
| 668 | u32 totalpacketlen; | 668 | u32 totalpacketlen; |
| 669 | bool rtstatus; | ||
| 670 | u8 u1rsvdpageloc[5] = { 0 }; | 669 | u8 u1rsvdpageloc[5] = { 0 }; |
| 671 | bool b_dlok = false; | 670 | bool b_dlok = false; |
| 672 | 671 | ||
| @@ -728,10 +727,7 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
| 728 | memcpy((u8 *)skb_put(skb, totalpacketlen), | 727 | memcpy((u8 *)skb_put(skb, totalpacketlen), |
| 729 | &reserved_page_packet, totalpacketlen); | 728 | &reserved_page_packet, totalpacketlen); |
| 730 | 729 | ||
| 731 | rtstatus = rtl_cmd_send_packet(hw, skb); | 730 | b_dlok = true; |
| 732 | |||
| 733 | if (rtstatus) | ||
| 734 | b_dlok = true; | ||
| 735 | 731 | ||
| 736 | if (b_dlok) { | 732 | if (b_dlok) { |
| 737 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , | 733 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c index 1a87edca2c3f..b461b3128da5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | |||
| @@ -85,29 +85,6 @@ static void _rtl92ee_enable_bcn_sub_func(struct ieee80211_hw *hw) | |||
| 85 | _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); | 85 | _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static void _rtl92ee_return_beacon_queue_skb(struct ieee80211_hw *hw) | ||
| 89 | { | ||
| 90 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 91 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
| 92 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
| 93 | unsigned long flags; | ||
| 94 | |||
| 95 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); | ||
| 96 | while (skb_queue_len(&ring->queue)) { | ||
| 97 | struct rtl_tx_buffer_desc *entry = | ||
| 98 | &ring->buffer_desc[ring->idx]; | ||
| 99 | struct sk_buff *skb = __skb_dequeue(&ring->queue); | ||
| 100 | |||
| 101 | pci_unmap_single(rtlpci->pdev, | ||
| 102 | rtlpriv->cfg->ops->get_desc( | ||
| 103 | (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), | ||
| 104 | skb->len, PCI_DMA_TODEVICE); | ||
| 105 | kfree_skb(skb); | ||
| 106 | ring->idx = (ring->idx + 1) % ring->entries; | ||
| 107 | } | ||
| 108 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void _rtl92ee_disable_bcn_sub_func(struct ieee80211_hw *hw) | 88 | static void _rtl92ee_disable_bcn_sub_func(struct ieee80211_hw *hw) |
| 112 | { | 89 | { |
| 113 | _rtl92ee_set_bcn_ctrl_reg(hw, BIT(1), 0); | 90 | _rtl92ee_set_bcn_ctrl_reg(hw, BIT(1), 0); |
| @@ -403,9 +380,6 @@ static void _rtl92ee_download_rsvd_page(struct ieee80211_hw *hw) | |||
| 403 | rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, | 380 | rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, |
| 404 | bcnvalid_reg | BIT(0)); | 381 | bcnvalid_reg | BIT(0)); |
| 405 | 382 | ||
| 406 | /* Return Beacon TCB */ | ||
| 407 | _rtl92ee_return_beacon_queue_skb(hw); | ||
| 408 | |||
| 409 | /* download rsvd page */ | 383 | /* download rsvd page */ |
| 410 | rtl92ee_set_fw_rsvdpagepkt(hw, false); | 384 | rtl92ee_set_fw_rsvdpagepkt(hw, false); |
| 411 | 385 | ||
| @@ -1163,6 +1137,139 @@ void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw) | |||
| 1163 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); | 1137 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); |
| 1164 | } | 1138 | } |
| 1165 | 1139 | ||
| 1140 | static bool _rtl8192ee_check_pcie_dma_hang(struct rtl_priv *rtlpriv) | ||
| 1141 | { | ||
| 1142 | u8 tmp; | ||
| 1143 | |||
| 1144 | /* write reg 0x350 Bit[26]=1. Enable debug port. */ | ||
| 1145 | tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); | ||
| 1146 | if (!(tmp & BIT(2))) { | ||
| 1147 | rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3, | ||
| 1148 | tmp | BIT(2)); | ||
| 1149 | mdelay(100); /* Suggested by DD Justin_tsai. */ | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /* read reg 0x350 Bit[25] if 1 : RX hang | ||
| 1153 | * read reg 0x350 Bit[24] if 1 : TX hang | ||
| 1154 | */ | ||
| 1155 | tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); | ||
| 1156 | if ((tmp & BIT(0)) || (tmp & BIT(1))) { | ||
| 1157 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
| 1158 | "CheckPcieDMAHang8192EE(): true!!\n"); | ||
| 1159 | return true; | ||
| 1160 | } | ||
| 1161 | return false; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | static void _rtl8192ee_reset_pcie_interface_dma(struct rtl_priv *rtlpriv, | ||
| 1165 | bool mac_power_on) | ||
| 1166 | { | ||
| 1167 | u8 tmp; | ||
| 1168 | bool release_mac_rx_pause; | ||
| 1169 | u8 backup_pcie_dma_pause; | ||
| 1170 | |||
| 1171 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
| 1172 | "ResetPcieInterfaceDMA8192EE()\n"); | ||
| 1173 | |||
| 1174 | /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03" | ||
| 1175 | * released by SD1 Alan. | ||
| 1176 | */ | ||
| 1177 | |||
| 1178 | /* 1. disable register write lock | ||
| 1179 | * write 0x1C bit[1:0] = 2'h0 | ||
| 1180 | * write 0xCC bit[2] = 1'b1 | ||
| 1181 | */ | ||
| 1182 | tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); | ||
| 1183 | tmp &= ~(BIT(1) | BIT(0)); | ||
| 1184 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); | ||
| 1185 | tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); | ||
| 1186 | tmp |= BIT(2); | ||
| 1187 | rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); | ||
| 1188 | |||
| 1189 | /* 2. Check and pause TRX DMA | ||
| 1190 | * write 0x284 bit[18] = 1'b1 | ||
| 1191 | * write 0x301 = 0xFF | ||
| 1192 | */ | ||
| 1193 | tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
| 1194 | if (tmp & BIT(2)) { | ||
| 1195 | /* Already pause before the function for another reason. */ | ||
| 1196 | release_mac_rx_pause = false; | ||
| 1197 | } else { | ||
| 1198 | rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); | ||
| 1199 | release_mac_rx_pause = true; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); | ||
| 1203 | if (backup_pcie_dma_pause != 0xFF) | ||
| 1204 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); | ||
| 1205 | |||
| 1206 | if (mac_power_on) { | ||
| 1207 | /* 3. reset TRX function | ||
| 1208 | * write 0x100 = 0x00 | ||
| 1209 | */ | ||
| 1210 | rtl_write_byte(rtlpriv, REG_CR, 0); | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | /* 4. Reset PCIe DMA | ||
| 1214 | * write 0x003 bit[0] = 0 | ||
| 1215 | */ | ||
| 1216 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
| 1217 | tmp &= ~(BIT(0)); | ||
| 1218 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); | ||
| 1219 | |||
| 1220 | /* 5. Enable PCIe DMA | ||
| 1221 | * write 0x003 bit[0] = 1 | ||
| 1222 | */ | ||
| 1223 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
| 1224 | tmp |= BIT(0); | ||
| 1225 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); | ||
| 1226 | |||
| 1227 | if (mac_power_on) { | ||
| 1228 | /* 6. enable TRX function | ||
| 1229 | * write 0x100 = 0xFF | ||
| 1230 | */ | ||
| 1231 | rtl_write_byte(rtlpriv, REG_CR, 0xFF); | ||
| 1232 | |||
| 1233 | /* We should init LLT & RQPN and | ||
| 1234 | * prepare Tx/Rx descrptor address later | ||
| 1235 | * because MAC function is reset. | ||
| 1236 | */ | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | /* 7. Restore PCIe autoload down bit | ||
| 1240 | * write 0xF8 bit[17] = 1'b1 | ||
| 1241 | */ | ||
| 1242 | tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); | ||
| 1243 | tmp |= BIT(1); | ||
| 1244 | rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); | ||
| 1245 | |||
| 1246 | /* In MAC power on state, BB and RF maybe in ON state, | ||
| 1247 | * if we release TRx DMA here | ||
| 1248 | * it will cause packets to be started to Tx/Rx, | ||
| 1249 | * so we release Tx/Rx DMA later. | ||
| 1250 | */ | ||
| 1251 | if (!mac_power_on) { | ||
| 1252 | /* 8. release TRX DMA | ||
| 1253 | * write 0x284 bit[18] = 1'b0 | ||
| 1254 | * write 0x301 = 0x00 | ||
| 1255 | */ | ||
| 1256 | if (release_mac_rx_pause) { | ||
| 1257 | tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
| 1258 | rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, | ||
| 1259 | (tmp & (~BIT(2)))); | ||
| 1260 | } | ||
| 1261 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, | ||
| 1262 | backup_pcie_dma_pause); | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | /* 9. lock system register | ||
| 1266 | * write 0xCC bit[2] = 1'b0 | ||
| 1267 | */ | ||
| 1268 | tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); | ||
| 1269 | tmp &= ~(BIT(2)); | ||
| 1270 | rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); | ||
| 1271 | } | ||
| 1272 | |||
| 1166 | int rtl92ee_hw_init(struct ieee80211_hw *hw) | 1273 | int rtl92ee_hw_init(struct ieee80211_hw *hw) |
| 1167 | { | 1274 | { |
| 1168 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1275 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| @@ -1188,6 +1295,13 @@ int rtl92ee_hw_init(struct ieee80211_hw *hw) | |||
| 1188 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; | 1295 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; |
| 1189 | } | 1296 | } |
| 1190 | 1297 | ||
| 1298 | if (_rtl8192ee_check_pcie_dma_hang(rtlpriv)) { | ||
| 1299 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "92ee dma hang!\n"); | ||
| 1300 | _rtl8192ee_reset_pcie_interface_dma(rtlpriv, | ||
| 1301 | rtlhal->mac_func_enable); | ||
| 1302 | rtlhal->mac_func_enable = false; | ||
| 1303 | } | ||
| 1304 | |||
| 1191 | rtstatus = _rtl92ee_init_mac(hw); | 1305 | rtstatus = _rtl92ee_init_mac(hw); |
| 1192 | 1306 | ||
| 1193 | rtl_write_byte(rtlpriv, 0x577, 0x03); | 1307 | rtl_write_byte(rtlpriv, 0x577, 0x03); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h index 3f2a9596e7cd..1eaa1fab550d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h | |||
| @@ -77,9 +77,11 @@ | |||
| 77 | #define REG_HIMRE 0x00B8 | 77 | #define REG_HIMRE 0x00B8 |
| 78 | #define REG_HISRE 0x00BC | 78 | #define REG_HISRE 0x00BC |
| 79 | 79 | ||
| 80 | #define REG_PMC_DBG_CTRL2 0x00CC | ||
| 80 | #define REG_EFUSE_ACCESS 0x00CF | 81 | #define REG_EFUSE_ACCESS 0x00CF |
| 81 | #define REG_HPON_FSM 0x00EC | 82 | #define REG_HPON_FSM 0x00EC |
| 82 | #define REG_SYS_CFG1 0x00F0 | 83 | #define REG_SYS_CFG1 0x00F0 |
| 84 | #define REG_MAC_PHY_CTRL_NORMAL 0x00F8 | ||
| 83 | #define REG_SYS_CFG2 0x00FC | 85 | #define REG_SYS_CFG2 0x00FC |
| 84 | 86 | ||
| 85 | #define REG_CR 0x0100 | 87 | #define REG_CR 0x0100 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c index 9b5a7d5be121..c31c6bfb536d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c | |||
| @@ -113,8 +113,6 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) | |||
| 113 | RCR_HTC_LOC_CTRL | | 113 | RCR_HTC_LOC_CTRL | |
| 114 | RCR_AMF | | 114 | RCR_AMF | |
| 115 | RCR_ACF | | 115 | RCR_ACF | |
| 116 | RCR_ADF | | ||
| 117 | RCR_AICV | | ||
| 118 | RCR_ACRC32 | | 116 | RCR_ACRC32 | |
| 119 | RCR_AB | | 117 | RCR_AB | |
| 120 | RCR_AM | | 118 | RCR_AM | |
| @@ -241,6 +239,7 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = { | |||
| 241 | .set_desc = rtl92ee_set_desc, | 239 | .set_desc = rtl92ee_set_desc, |
| 242 | .get_desc = rtl92ee_get_desc, | 240 | .get_desc = rtl92ee_get_desc, |
| 243 | .is_tx_desc_closed = rtl92ee_is_tx_desc_closed, | 241 | .is_tx_desc_closed = rtl92ee_is_tx_desc_closed, |
| 242 | .get_available_desc = rtl92ee_get_available_desc, | ||
| 244 | .tx_polling = rtl92ee_tx_polling, | 243 | .tx_polling = rtl92ee_tx_polling, |
| 245 | .enable_hw_sec = rtl92ee_enable_hw_security_config, | 244 | .enable_hw_sec = rtl92ee_enable_hw_security_config, |
| 246 | .set_key = rtl92ee_set_key, | 245 | .set_key = rtl92ee_set_key, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c index 55d1da5e162b..d39ee67f6113 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c | |||
| @@ -354,6 +354,10 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, | |||
| 354 | struct ieee80211_hdr *hdr; | 354 | struct ieee80211_hdr *hdr; |
| 355 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); | 355 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); |
| 356 | 356 | ||
| 357 | if (GET_RX_STATUS_DESC_RPT_SEL(pdesc) == 0) | ||
| 358 | status->packet_report_type = NORMAL_RX; | ||
| 359 | else | ||
| 360 | status->packet_report_type = C2H_PACKET; | ||
| 357 | status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); | 361 | status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); |
| 358 | status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * | 362 | status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * |
| 359 | RX_DRV_INFO_SIZE_UNIT; | 363 | RX_DRV_INFO_SIZE_UNIT; |
| @@ -495,14 +499,7 @@ u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, u8 queue_index) | |||
| 495 | if (!start_rx) | 499 | if (!start_rx) |
| 496 | return 0; | 500 | return 0; |
| 497 | 501 | ||
| 498 | if ((last_read_point > (RX_DESC_NUM_92E / 2)) && | 502 | remind_cnt = calc_fifo_space(read_point, write_point); |
| 499 | (read_point <= (RX_DESC_NUM_92E / 2))) { | ||
| 500 | remind_cnt = RX_DESC_NUM_92E - write_point; | ||
| 501 | } else { | ||
| 502 | remind_cnt = (read_point >= write_point) ? | ||
| 503 | (read_point - write_point) : | ||
| 504 | (RX_DESC_NUM_92E - write_point + read_point); | ||
| 505 | } | ||
| 506 | 503 | ||
| 507 | if (remind_cnt == 0) | 504 | if (remind_cnt == 0) |
| 508 | return 0; | 505 | return 0; |
| @@ -551,6 +548,26 @@ static u16 get_desc_addr_fr_q_idx(u16 queue_index) | |||
| 551 | return desc_address; | 548 | return desc_address; |
| 552 | } | 549 | } |
| 553 | 550 | ||
| 551 | u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx) | ||
| 552 | { | ||
| 553 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
| 554 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 555 | u16 point_diff = 0; | ||
| 556 | u16 current_tx_read_point = 0, current_tx_write_point = 0; | ||
| 557 | u32 tmp_4byte; | ||
| 558 | |||
| 559 | tmp_4byte = rtl_read_dword(rtlpriv, | ||
| 560 | get_desc_addr_fr_q_idx(q_idx)); | ||
| 561 | current_tx_read_point = (u16)((tmp_4byte >> 16) & 0x0fff); | ||
| 562 | current_tx_write_point = (u16)((tmp_4byte) & 0x0fff); | ||
| 563 | |||
| 564 | point_diff = calc_fifo_space(current_tx_read_point, | ||
| 565 | current_tx_write_point); | ||
| 566 | |||
| 567 | rtlpci->tx_ring[q_idx].avl_desc = point_diff; | ||
| 568 | return point_diff; | ||
| 569 | } | ||
| 570 | |||
| 554 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, | 571 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, |
| 555 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, | 572 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, |
| 556 | struct sk_buff *skb, dma_addr_t addr) | 573 | struct sk_buff *skb, dma_addr_t addr) |
| @@ -1027,8 +1044,7 @@ bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) | |||
| 1027 | static u8 stop_report_cnt; | 1044 | static u8 stop_report_cnt; |
| 1028 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; | 1045 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; |
| 1029 | 1046 | ||
| 1030 | /*checking Read/Write Point each interrupt wastes CPU */ | 1047 | { |
| 1031 | if (stop_report_cnt > 15 || !rtlpriv->link_info.busytraffic) { | ||
| 1032 | u16 point_diff = 0; | 1048 | u16 point_diff = 0; |
| 1033 | u16 cur_tx_rp, cur_tx_wp; | 1049 | u16 cur_tx_rp, cur_tx_wp; |
| 1034 | u32 tmpu32 = 0; | 1050 | u32 tmpu32 = 0; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h index 48504c25fffb..8f78ac9e6040 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h | |||
| @@ -542,6 +542,8 @@ | |||
| 542 | LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) | 542 | LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) |
| 543 | #define GET_RX_DESC_RX_IS_QOS(__pdesc) \ | 543 | #define GET_RX_DESC_RX_IS_QOS(__pdesc) \ |
| 544 | LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) | 544 | LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) |
| 545 | #define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ | ||
| 546 | LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) | ||
| 545 | 547 | ||
| 546 | #define GET_RX_DESC_RXMCS(__pdesc) \ | 548 | #define GET_RX_DESC_RXMCS(__pdesc) \ |
| 547 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) | 549 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) |
| @@ -829,6 +831,7 @@ void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc, | |||
| 829 | u8 queue_index); | 831 | u8 queue_index); |
| 830 | u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, | 832 | u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, |
| 831 | u8 queue_index); | 833 | u8 queue_index); |
| 834 | u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 queue_index); | ||
| 832 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, | 835 | void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, |
| 833 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, | 836 | u8 *tx_bd_desc, u8 *desc, u8 queue_index, |
| 834 | struct sk_buff *skb, dma_addr_t addr); | 837 | struct sk_buff *skb, dma_addr_t addr); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index b53d9dd7a595..51572912c53d 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
| @@ -2182,6 +2182,7 @@ struct rtl_hal_ops { | |||
| 2182 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, | 2182 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, |
| 2183 | struct rtl_wow_pattern *rtl_pattern, | 2183 | struct rtl_wow_pattern *rtl_pattern, |
| 2184 | u8 index); | 2184 | u8 index); |
| 2185 | u16 (*get_available_desc)(struct ieee80211_hw *hw, u8 q_idx); | ||
| 2185 | }; | 2186 | }; |
| 2186 | 2187 | ||
| 2187 | struct rtl_intf_ops { | 2188 | struct rtl_intf_ops { |
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 0b30a7b4d663..d4ba009ac9aa 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
| @@ -500,6 +500,7 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
| 500 | int ret = 0; | 500 | int ret = 0; |
| 501 | 501 | ||
| 502 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | | 502 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | |
| 503 | IEEE80211_VIF_SUPPORTS_UAPSD | | ||
| 503 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; | 504 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; |
| 504 | 505 | ||
| 505 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 506 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
| @@ -1480,9 +1481,7 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
| 1480 | /* unit us */ | 1481 | /* unit us */ |
| 1481 | /* FIXME: find a proper value */ | 1482 | /* FIXME: find a proper value */ |
| 1482 | 1483 | ||
| 1483 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1484 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS; |
| 1484 | IEEE80211_HW_SUPPORTS_PS | | ||
| 1485 | IEEE80211_HW_SUPPORTS_UAPSD; | ||
| 1486 | 1485 | ||
| 1487 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1486 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
| 1488 | BIT(NL80211_IFTYPE_ADHOC); | 1487 | BIT(NL80211_IFTYPE_ADHOC); |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index b924ceadc02c..f28fa3b5029d 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
| @@ -1725,7 +1725,7 @@ int wl12xx_acx_config_hangover(struct wl1271 *wl) | |||
| 1725 | acx->decrease_delta = conf->decrease_delta; | 1725 | acx->decrease_delta = conf->decrease_delta; |
| 1726 | acx->quiet_time = conf->quiet_time; | 1726 | acx->quiet_time = conf->quiet_time; |
| 1727 | acx->increase_time = conf->increase_time; | 1727 | acx->increase_time = conf->increase_time; |
| 1728 | acx->window_size = acx->window_size; | 1728 | acx->window_size = conf->window_size; |
| 1729 | 1729 | ||
| 1730 | ret = wl1271_cmd_configure(wl, ACX_CONFIG_HANGOVER, acx, | 1730 | ret = wl1271_cmd_configure(wl, ACX_CONFIG_HANGOVER, acx, |
| 1731 | sizeof(*acx)); | 1731 | sizeof(*acx)); |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index e90fb781a6a1..1e136993580f 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
| @@ -1785,8 +1785,10 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
| 1785 | mutex_lock(&wl->mutex); | 1785 | mutex_lock(&wl->mutex); |
| 1786 | 1786 | ||
| 1787 | ret = wl1271_ps_elp_wakeup(wl); | 1787 | ret = wl1271_ps_elp_wakeup(wl); |
| 1788 | if (ret < 0) | 1788 | if (ret < 0) { |
| 1789 | mutex_unlock(&wl->mutex); | ||
| 1789 | return ret; | 1790 | return ret; |
| 1791 | } | ||
| 1790 | 1792 | ||
| 1791 | wl->wow_enabled = true; | 1793 | wl->wow_enabled = true; |
| 1792 | wl12xx_for_each_wlvif(wl, wlvif) { | 1794 | wl12xx_for_each_wlvif(wl, wlvif) { |
| @@ -2552,6 +2554,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
| 2552 | } | 2554 | } |
| 2553 | 2555 | ||
| 2554 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | | 2556 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | |
| 2557 | IEEE80211_VIF_SUPPORTS_UAPSD | | ||
| 2555 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; | 2558 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; |
| 2556 | 2559 | ||
| 2557 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 2560 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
| @@ -5661,14 +5664,15 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw, | |||
| 5661 | ieee80211_queue_work(hw, &wlvif->rc_update_work); | 5664 | ieee80211_queue_work(hw, &wlvif->rc_update_work); |
| 5662 | } | 5665 | } |
| 5663 | 5666 | ||
| 5664 | static int wlcore_op_get_rssi(struct ieee80211_hw *hw, | 5667 | static void wlcore_op_sta_statistics(struct ieee80211_hw *hw, |
| 5665 | struct ieee80211_vif *vif, | 5668 | struct ieee80211_vif *vif, |
| 5666 | struct ieee80211_sta *sta, | 5669 | struct ieee80211_sta *sta, |
| 5667 | s8 *rssi_dbm) | 5670 | struct station_info *sinfo) |
| 5668 | { | 5671 | { |
| 5669 | struct wl1271 *wl = hw->priv; | 5672 | struct wl1271 *wl = hw->priv; |
| 5670 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 5673 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
| 5671 | int ret = 0; | 5674 | s8 rssi_dbm; |
| 5675 | int ret; | ||
| 5672 | 5676 | ||
| 5673 | wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi"); | 5677 | wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi"); |
| 5674 | 5678 | ||
| @@ -5681,17 +5685,18 @@ static int wlcore_op_get_rssi(struct ieee80211_hw *hw, | |||
| 5681 | if (ret < 0) | 5685 | if (ret < 0) |
| 5682 | goto out_sleep; | 5686 | goto out_sleep; |
| 5683 | 5687 | ||
| 5684 | ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm); | 5688 | ret = wlcore_acx_average_rssi(wl, wlvif, &rssi_dbm); |
| 5685 | if (ret < 0) | 5689 | if (ret < 0) |
| 5686 | goto out_sleep; | 5690 | goto out_sleep; |
| 5687 | 5691 | ||
| 5692 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); | ||
| 5693 | sinfo->signal = rssi_dbm; | ||
| 5694 | |||
| 5688 | out_sleep: | 5695 | out_sleep: |
| 5689 | wl1271_ps_elp_sleep(wl); | 5696 | wl1271_ps_elp_sleep(wl); |
| 5690 | 5697 | ||
| 5691 | out: | 5698 | out: |
| 5692 | mutex_unlock(&wl->mutex); | 5699 | mutex_unlock(&wl->mutex); |
| 5693 | |||
| 5694 | return ret; | ||
| 5695 | } | 5700 | } |
| 5696 | 5701 | ||
| 5697 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | 5702 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) |
| @@ -5893,7 +5898,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
| 5893 | .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, | 5898 | .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, |
| 5894 | .switch_vif_chanctx = wlcore_op_switch_vif_chanctx, | 5899 | .switch_vif_chanctx = wlcore_op_switch_vif_chanctx, |
| 5895 | .sta_rc_update = wlcore_op_sta_rc_update, | 5900 | .sta_rc_update = wlcore_op_sta_rc_update, |
| 5896 | .get_rssi = wlcore_op_get_rssi, | 5901 | .sta_statistics = wlcore_op_sta_statistics, |
| 5897 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 5902 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
| 5898 | }; | 5903 | }; |
| 5899 | 5904 | ||
| @@ -6064,7 +6069,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
| 6064 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 6069 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
| 6065 | IEEE80211_HW_SUPPORTS_PS | | 6070 | IEEE80211_HW_SUPPORTS_PS | |
| 6066 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 6071 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
| 6067 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
| 6068 | IEEE80211_HW_HAS_RATE_CONTROL | | 6072 | IEEE80211_HW_HAS_RATE_CONTROL | |
| 6069 | IEEE80211_HW_CONNECTION_MONITOR | | 6073 | IEEE80211_HW_CONNECTION_MONITOR | |
| 6070 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 6074 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 2fead3820849..1e180c400f17 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
| @@ -90,25 +90,6 @@ found: | |||
| 90 | } | 90 | } |
| 91 | #endif /* CONFIG_SSB_PCMCIAHOST */ | 91 | #endif /* CONFIG_SSB_PCMCIAHOST */ |
| 92 | 92 | ||
| 93 | #ifdef CONFIG_SSB_SDIOHOST | ||
| 94 | struct ssb_bus *ssb_sdio_func_to_bus(struct sdio_func *func) | ||
| 95 | { | ||
| 96 | struct ssb_bus *bus; | ||
| 97 | |||
| 98 | ssb_buses_lock(); | ||
| 99 | list_for_each_entry(bus, &buses, list) { | ||
| 100 | if (bus->bustype == SSB_BUSTYPE_SDIO && | ||
| 101 | bus->host_sdio == func) | ||
| 102 | goto found; | ||
| 103 | } | ||
| 104 | bus = NULL; | ||
| 105 | found: | ||
| 106 | ssb_buses_unlock(); | ||
| 107 | |||
| 108 | return bus; | ||
| 109 | } | ||
| 110 | #endif /* CONFIG_SSB_SDIOHOST */ | ||
| 111 | |||
| 112 | int ssb_for_each_bus_call(unsigned long data, | 93 | int ssb_for_each_bus_call(unsigned long data, |
| 113 | int (*func)(struct ssb_bus *bus, unsigned long data)) | 94 | int (*func)(struct ssb_bus *bus, unsigned long data)) |
| 114 | { | 95 | { |
diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c index 82a8c06ab347..c5800ae71fcf 100644 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c | |||
| @@ -1091,17 +1091,17 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy, | |||
| 1091 | goto exit; | 1091 | goto exit; |
| 1092 | } | 1092 | } |
| 1093 | 1093 | ||
| 1094 | sinfo->filled |= STATION_INFO_SIGNAL; | 1094 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 1095 | sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv. | 1095 | sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv. |
| 1096 | signal_strength); | 1096 | signal_strength); |
| 1097 | 1097 | ||
| 1098 | sinfo->filled |= STATION_INFO_TX_BITRATE; | 1098 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
| 1099 | sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter); | 1099 | sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter); |
| 1100 | 1100 | ||
| 1101 | sinfo->filled |= STATION_INFO_RX_PACKETS; | 1101 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); |
| 1102 | sinfo->rx_packets = sta_rx_data_pkts(psta); | 1102 | sinfo->rx_packets = sta_rx_data_pkts(psta); |
| 1103 | 1103 | ||
| 1104 | sinfo->filled |= STATION_INFO_TX_PACKETS; | 1104 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); |
| 1105 | sinfo->tx_packets = psta->sta_stats.tx_pkts; | 1105 | sinfo->tx_packets = psta->sta_stats.tx_pkts; |
| 1106 | } | 1106 | } |
| 1107 | 1107 | ||
| @@ -2363,7 +2363,7 @@ void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, | |||
| 2363 | ie_offset = offsetof(struct ieee80211_mgmt, | 2363 | ie_offset = offsetof(struct ieee80211_mgmt, |
| 2364 | u.reassoc_req.variable); | 2364 | u.reassoc_req.variable); |
| 2365 | 2365 | ||
| 2366 | sinfo.filled = STATION_INFO_ASSOC_REQ_IES; | 2366 | sinfo.filled = 0; |
| 2367 | sinfo.assoc_req_ies = pmgmt_frame + ie_offset; | 2367 | sinfo.assoc_req_ies = pmgmt_frame + ie_offset; |
| 2368 | sinfo.assoc_req_ies_len = frame_len - ie_offset; | 2368 | sinfo.assoc_req_ies_len = frame_len - ie_offset; |
| 2369 | cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC); | 2369 | cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC); |
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8942dcb44180..7c87aecf4744 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c | |||
| @@ -325,9 +325,9 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 325 | 325 | ||
| 326 | if (result == 0) { | 326 | if (result == 0) { |
| 327 | sinfo->txrate.legacy = quality.txrate.data; | 327 | sinfo->txrate.legacy = quality.txrate.data; |
| 328 | sinfo->filled |= STATION_INFO_TX_BITRATE; | 328 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
| 329 | sinfo->signal = quality.level.data; | 329 | sinfo->signal = quality.level.data; |
| 330 | sinfo->filled |= STATION_INFO_SIGNAL; | 330 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | return result; | 333 | return result; |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index eb1c6a47b67f..994739da827f 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
| @@ -318,6 +318,7 @@ struct bcma_bus { | |||
| 318 | const struct bcma_host_ops *ops; | 318 | const struct bcma_host_ops *ops; |
| 319 | 319 | ||
| 320 | enum bcma_hosttype hosttype; | 320 | enum bcma_hosttype hosttype; |
| 321 | bool host_is_pcie2; /* Used for BCMA_HOSTTYPE_PCI only */ | ||
| 321 | union { | 322 | union { |
| 322 | /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ | 323 | /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ |
| 323 | struct pci_dev *host_pci; | 324 | struct pci_dev *host_pci; |
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h index 0333e605ea0d..3f809ae372c4 100644 --- a/include/linux/bcma/bcma_driver_pci.h +++ b/include/linux/bcma/bcma_driver_pci.h | |||
| @@ -223,6 +223,7 @@ struct bcma_drv_pci_host { | |||
| 223 | 223 | ||
| 224 | struct bcma_drv_pci { | 224 | struct bcma_drv_pci { |
| 225 | struct bcma_device *core; | 225 | struct bcma_device *core; |
| 226 | u8 early_setup_done:1; | ||
| 226 | u8 setup_done:1; | 227 | u8 setup_done:1; |
| 227 | u8 hostmode:1; | 228 | u8 hostmode:1; |
| 228 | 229 | ||
| @@ -237,6 +238,7 @@ struct bcma_drv_pci { | |||
| 237 | #define pcicore_write16(pc, offset, val) bcma_write16((pc)->core, offset, val) | 238 | #define pcicore_write16(pc, offset, val) bcma_write16((pc)->core, offset, val) |
| 238 | #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) | 239 | #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) |
| 239 | 240 | ||
| 241 | extern void bcma_core_pci_early_init(struct bcma_drv_pci *pc); | ||
| 240 | extern void bcma_core_pci_init(struct bcma_drv_pci *pc); | 242 | extern void bcma_core_pci_init(struct bcma_drv_pci *pc); |
| 241 | extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, | 243 | extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, |
| 242 | struct bcma_device *core, bool enable); | 244 | struct bcma_device *core, bool enable); |
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index e64ae7bf80a1..ebd5c1fcdea4 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h | |||
| @@ -64,6 +64,8 @@ | |||
| 64 | #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ | 64 | #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ |
| 65 | #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ | 65 | #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ |
| 66 | 66 | ||
| 67 | #define BCMA_PCIE2_BAR0_WIN2 0x70 | ||
| 68 | |||
| 67 | /* SiliconBackplane Address Map. | 69 | /* SiliconBackplane Address Map. |
| 68 | * All regions may not exist on all chips. | 70 | * All regions may not exist on all chips. |
| 69 | */ | 71 | */ |
diff --git a/include/linux/bcma/bcma_soc.h b/include/linux/bcma/bcma_soc.h index f24d245f8394..1b5fc0c3b1b5 100644 --- a/include/linux/bcma/bcma_soc.h +++ b/include/linux/bcma/bcma_soc.h | |||
| @@ -5,8 +5,6 @@ | |||
| 5 | 5 | ||
| 6 | struct bcma_soc { | 6 | struct bcma_soc { |
| 7 | struct bcma_bus bus; | 7 | struct bcma_bus bus; |
| 8 | struct bcma_device core_cc; | ||
| 9 | struct bcma_device core_mips; | ||
| 10 | }; | 8 | }; |
| 11 | 9 | ||
| 12 | int __init bcma_host_soc_register(struct bcma_soc *soc); | 10 | int __init bcma_host_soc_register(struct bcma_soc *soc); |
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index f7b9100686c3..c0f707ac192b 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
| @@ -173,6 +173,7 @@ | |||
| 173 | #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) | 173 | #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) |
| 174 | #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) | 174 | #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) |
| 175 | #define SSB_SPROMSIZE_WORDS_R10 230 | 175 | #define SSB_SPROMSIZE_WORDS_R10 230 |
| 176 | #define SSB_SPROMSIZE_WORDS_R11 234 | ||
| 176 | #define SSB_SPROM_BASE1 0x1000 | 177 | #define SSB_SPROM_BASE1 0x1000 |
| 177 | #define SSB_SPROM_BASE31 0x0800 | 178 | #define SSB_SPROM_BASE31 0x0800 |
| 178 | #define SSB_SPROM_REVISION 0x007E | 179 | #define SSB_SPROM_REVISION 0x007E |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4ebb816241fa..7b44ba0a7632 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -520,37 +520,41 @@ ieee80211_chandef_max_power(struct cfg80211_chan_def *chandef) | |||
| 520 | * | 520 | * |
| 521 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in | 521 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in |
| 522 | * @SURVEY_INFO_IN_USE: channel is currently being used | 522 | * @SURVEY_INFO_IN_USE: channel is currently being used |
| 523 | * @SURVEY_INFO_CHANNEL_TIME: channel active time (in ms) was filled in | 523 | * @SURVEY_INFO_TIME: active time (in ms) was filled in |
| 524 | * @SURVEY_INFO_CHANNEL_TIME_BUSY: channel busy time was filled in | 524 | * @SURVEY_INFO_TIME_BUSY: busy time was filled in |
| 525 | * @SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: extension channel busy time was filled in | 525 | * @SURVEY_INFO_TIME_EXT_BUSY: extension channel busy time was filled in |
| 526 | * @SURVEY_INFO_CHANNEL_TIME_RX: channel receive time was filled in | 526 | * @SURVEY_INFO_TIME_RX: receive time was filled in |
| 527 | * @SURVEY_INFO_CHANNEL_TIME_TX: channel transmit time was filled in | 527 | * @SURVEY_INFO_TIME_TX: transmit time was filled in |
| 528 | * @SURVEY_INFO_TIME_SCAN: scan time was filled in | ||
| 528 | * | 529 | * |
| 529 | * Used by the driver to indicate which info in &struct survey_info | 530 | * Used by the driver to indicate which info in &struct survey_info |
| 530 | * it has filled in during the get_survey(). | 531 | * it has filled in during the get_survey(). |
| 531 | */ | 532 | */ |
| 532 | enum survey_info_flags { | 533 | enum survey_info_flags { |
| 533 | SURVEY_INFO_NOISE_DBM = 1<<0, | 534 | SURVEY_INFO_NOISE_DBM = BIT(0), |
| 534 | SURVEY_INFO_IN_USE = 1<<1, | 535 | SURVEY_INFO_IN_USE = BIT(1), |
| 535 | SURVEY_INFO_CHANNEL_TIME = 1<<2, | 536 | SURVEY_INFO_TIME = BIT(2), |
| 536 | SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3, | 537 | SURVEY_INFO_TIME_BUSY = BIT(3), |
| 537 | SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4, | 538 | SURVEY_INFO_TIME_EXT_BUSY = BIT(4), |
| 538 | SURVEY_INFO_CHANNEL_TIME_RX = 1<<5, | 539 | SURVEY_INFO_TIME_RX = BIT(5), |
| 539 | SURVEY_INFO_CHANNEL_TIME_TX = 1<<6, | 540 | SURVEY_INFO_TIME_TX = BIT(6), |
| 541 | SURVEY_INFO_TIME_SCAN = BIT(7), | ||
| 540 | }; | 542 | }; |
| 541 | 543 | ||
| 542 | /** | 544 | /** |
| 543 | * struct survey_info - channel survey response | 545 | * struct survey_info - channel survey response |
| 544 | * | 546 | * |
| 545 | * @channel: the channel this survey record reports, mandatory | 547 | * @channel: the channel this survey record reports, may be %NULL for a single |
| 548 | * record to report global statistics | ||
| 546 | * @filled: bitflag of flags from &enum survey_info_flags | 549 | * @filled: bitflag of flags from &enum survey_info_flags |
| 547 | * @noise: channel noise in dBm. This and all following fields are | 550 | * @noise: channel noise in dBm. This and all following fields are |
| 548 | * optional | 551 | * optional |
| 549 | * @channel_time: amount of time in ms the radio spent on the channel | 552 | * @time: amount of time in ms the radio was turn on (on the channel) |
| 550 | * @channel_time_busy: amount of time the primary channel was sensed busy | 553 | * @time_busy: amount of time the primary channel was sensed busy |
| 551 | * @channel_time_ext_busy: amount of time the extension channel was sensed busy | 554 | * @time_ext_busy: amount of time the extension channel was sensed busy |
| 552 | * @channel_time_rx: amount of time the radio spent receiving data | 555 | * @time_rx: amount of time the radio spent receiving data |
| 553 | * @channel_time_tx: amount of time the radio spent transmitting data | 556 | * @time_tx: amount of time the radio spent transmitting data |
| 557 | * @time_scan: amount of time the radio spent for scanning | ||
| 554 | * | 558 | * |
| 555 | * Used by dump_survey() to report back per-channel survey information. | 559 | * Used by dump_survey() to report back per-channel survey information. |
| 556 | * | 560 | * |
| @@ -559,11 +563,12 @@ enum survey_info_flags { | |||
| 559 | */ | 563 | */ |
| 560 | struct survey_info { | 564 | struct survey_info { |
| 561 | struct ieee80211_channel *channel; | 565 | struct ieee80211_channel *channel; |
| 562 | u64 channel_time; | 566 | u64 time; |
| 563 | u64 channel_time_busy; | 567 | u64 time_busy; |
| 564 | u64 channel_time_ext_busy; | 568 | u64 time_ext_busy; |
| 565 | u64 channel_time_rx; | 569 | u64 time_rx; |
| 566 | u64 channel_time_tx; | 570 | u64 time_tx; |
| 571 | u64 time_scan; | ||
| 567 | u32 filled; | 572 | u32 filled; |
| 568 | s8 noise; | 573 | s8 noise; |
| 569 | }; | 574 | }; |
| @@ -861,75 +866,6 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
| 861 | enum cfg80211_station_type statype); | 866 | enum cfg80211_station_type statype); |
| 862 | 867 | ||
| 863 | /** | 868 | /** |
| 864 | * enum station_info_flags - station information flags | ||
| 865 | * | ||
| 866 | * Used by the driver to indicate which info in &struct station_info | ||
| 867 | * it has filled in during get_station() or dump_station(). | ||
| 868 | * | ||
| 869 | * @STATION_INFO_INACTIVE_TIME: @inactive_time filled | ||
| 870 | * @STATION_INFO_RX_BYTES: @rx_bytes filled | ||
| 871 | * @STATION_INFO_TX_BYTES: @tx_bytes filled | ||
| 872 | * @STATION_INFO_RX_BYTES64: @rx_bytes filled with 64-bit value | ||
| 873 | * @STATION_INFO_TX_BYTES64: @tx_bytes filled with 64-bit value | ||
| 874 | * @STATION_INFO_LLID: @llid filled | ||
| 875 | * @STATION_INFO_PLID: @plid filled | ||
| 876 | * @STATION_INFO_PLINK_STATE: @plink_state filled | ||
| 877 | * @STATION_INFO_SIGNAL: @signal filled | ||
| 878 | * @STATION_INFO_TX_BITRATE: @txrate fields are filled | ||
| 879 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) | ||
| 880 | * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value | ||
| 881 | * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value | ||
| 882 | * @STATION_INFO_TX_RETRIES: @tx_retries filled | ||
| 883 | * @STATION_INFO_TX_FAILED: @tx_failed filled | ||
| 884 | * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled | ||
| 885 | * @STATION_INFO_SIGNAL_AVG: @signal_avg filled | ||
| 886 | * @STATION_INFO_RX_BITRATE: @rxrate fields are filled | ||
| 887 | * @STATION_INFO_BSS_PARAM: @bss_param filled | ||
| 888 | * @STATION_INFO_CONNECTED_TIME: @connected_time filled | ||
| 889 | * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled | ||
| 890 | * @STATION_INFO_STA_FLAGS: @sta_flags filled | ||
| 891 | * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled | ||
| 892 | * @STATION_INFO_T_OFFSET: @t_offset filled | ||
| 893 | * @STATION_INFO_LOCAL_PM: @local_pm filled | ||
| 894 | * @STATION_INFO_PEER_PM: @peer_pm filled | ||
| 895 | * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled | ||
| 896 | * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled | ||
| 897 | * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled | ||
| 898 | * @STATION_INFO_EXPECTED_THROUGHPUT: @expected_throughput filled | ||
| 899 | */ | ||
| 900 | enum station_info_flags { | ||
| 901 | STATION_INFO_INACTIVE_TIME = BIT(0), | ||
| 902 | STATION_INFO_RX_BYTES = BIT(1), | ||
| 903 | STATION_INFO_TX_BYTES = BIT(2), | ||
| 904 | STATION_INFO_LLID = BIT(3), | ||
| 905 | STATION_INFO_PLID = BIT(4), | ||
| 906 | STATION_INFO_PLINK_STATE = BIT(5), | ||
| 907 | STATION_INFO_SIGNAL = BIT(6), | ||
| 908 | STATION_INFO_TX_BITRATE = BIT(7), | ||
| 909 | STATION_INFO_RX_PACKETS = BIT(8), | ||
| 910 | STATION_INFO_TX_PACKETS = BIT(9), | ||
| 911 | STATION_INFO_TX_RETRIES = BIT(10), | ||
| 912 | STATION_INFO_TX_FAILED = BIT(11), | ||
| 913 | STATION_INFO_RX_DROP_MISC = BIT(12), | ||
| 914 | STATION_INFO_SIGNAL_AVG = BIT(13), | ||
| 915 | STATION_INFO_RX_BITRATE = BIT(14), | ||
| 916 | STATION_INFO_BSS_PARAM = BIT(15), | ||
| 917 | STATION_INFO_CONNECTED_TIME = BIT(16), | ||
| 918 | STATION_INFO_ASSOC_REQ_IES = BIT(17), | ||
| 919 | STATION_INFO_STA_FLAGS = BIT(18), | ||
| 920 | STATION_INFO_BEACON_LOSS_COUNT = BIT(19), | ||
| 921 | STATION_INFO_T_OFFSET = BIT(20), | ||
| 922 | STATION_INFO_LOCAL_PM = BIT(21), | ||
| 923 | STATION_INFO_PEER_PM = BIT(22), | ||
| 924 | STATION_INFO_NONPEER_PM = BIT(23), | ||
| 925 | STATION_INFO_RX_BYTES64 = BIT(24), | ||
| 926 | STATION_INFO_TX_BYTES64 = BIT(25), | ||
| 927 | STATION_INFO_CHAIN_SIGNAL = BIT(26), | ||
| 928 | STATION_INFO_CHAIN_SIGNAL_AVG = BIT(27), | ||
| 929 | STATION_INFO_EXPECTED_THROUGHPUT = BIT(28), | ||
| 930 | }; | ||
| 931 | |||
| 932 | /** | ||
| 933 | * enum station_info_rate_flags - bitrate info flags | 869 | * enum station_info_rate_flags - bitrate info flags |
| 934 | * | 870 | * |
| 935 | * Used by the driver to indicate the specific rate transmission | 871 | * Used by the driver to indicate the specific rate transmission |
| @@ -937,22 +873,35 @@ enum station_info_flags { | |||
| 937 | * | 873 | * |
| 938 | * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS | 874 | * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS |
| 939 | * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS | 875 | * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS |
| 940 | * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission | ||
| 941 | * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission | ||
| 942 | * @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission | ||
| 943 | * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission | ||
| 944 | * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval | 876 | * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval |
| 945 | * @RATE_INFO_FLAGS_60G: 60GHz MCS | 877 | * @RATE_INFO_FLAGS_60G: 60GHz MCS |
| 946 | */ | 878 | */ |
| 947 | enum rate_info_flags { | 879 | enum rate_info_flags { |
| 948 | RATE_INFO_FLAGS_MCS = BIT(0), | 880 | RATE_INFO_FLAGS_MCS = BIT(0), |
| 949 | RATE_INFO_FLAGS_VHT_MCS = BIT(1), | 881 | RATE_INFO_FLAGS_VHT_MCS = BIT(1), |
| 950 | RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2), | 882 | RATE_INFO_FLAGS_SHORT_GI = BIT(2), |
| 951 | RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3), | 883 | RATE_INFO_FLAGS_60G = BIT(3), |
| 952 | RATE_INFO_FLAGS_80P80_MHZ_WIDTH = BIT(4), | 884 | }; |
| 953 | RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(5), | 885 | |
| 954 | RATE_INFO_FLAGS_SHORT_GI = BIT(6), | 886 | /** |
| 955 | RATE_INFO_FLAGS_60G = BIT(7), | 887 | * enum rate_info_bw - rate bandwidth information |
| 888 | * | ||
| 889 | * Used by the driver to indicate the rate bandwidth. | ||
| 890 | * | ||
| 891 | * @RATE_INFO_BW_5: 5 MHz bandwidth | ||
| 892 | * @RATE_INFO_BW_10: 10 MHz bandwidth | ||
| 893 | * @RATE_INFO_BW_20: 20 MHz bandwidth | ||
| 894 | * @RATE_INFO_BW_40: 40 MHz bandwidth | ||
| 895 | * @RATE_INFO_BW_80: 80 MHz bandwidth | ||
| 896 | * @RATE_INFO_BW_160: 160 MHz bandwidth | ||
| 897 | */ | ||
| 898 | enum rate_info_bw { | ||
| 899 | RATE_INFO_BW_5, | ||
| 900 | RATE_INFO_BW_10, | ||
| 901 | RATE_INFO_BW_20, | ||
| 902 | RATE_INFO_BW_40, | ||
| 903 | RATE_INFO_BW_80, | ||
| 904 | RATE_INFO_BW_160, | ||
| 956 | }; | 905 | }; |
| 957 | 906 | ||
| 958 | /** | 907 | /** |
| @@ -964,12 +913,14 @@ enum rate_info_flags { | |||
| 964 | * @mcs: mcs index if struct describes a 802.11n bitrate | 913 | * @mcs: mcs index if struct describes a 802.11n bitrate |
| 965 | * @legacy: bitrate in 100kbit/s for 802.11abg | 914 | * @legacy: bitrate in 100kbit/s for 802.11abg |
| 966 | * @nss: number of streams (VHT only) | 915 | * @nss: number of streams (VHT only) |
| 916 | * @bw: bandwidth (from &enum rate_info_bw) | ||
| 967 | */ | 917 | */ |
| 968 | struct rate_info { | 918 | struct rate_info { |
| 969 | u8 flags; | 919 | u8 flags; |
| 970 | u8 mcs; | 920 | u8 mcs; |
| 971 | u16 legacy; | 921 | u16 legacy; |
| 972 | u8 nss; | 922 | u8 nss; |
| 923 | u8 bw; | ||
| 973 | }; | 924 | }; |
| 974 | 925 | ||
| 975 | /** | 926 | /** |
| @@ -1003,6 +954,24 @@ struct sta_bss_parameters { | |||
| 1003 | u16 beacon_interval; | 954 | u16 beacon_interval; |
| 1004 | }; | 955 | }; |
| 1005 | 956 | ||
| 957 | /** | ||
| 958 | * struct cfg80211_tid_stats - per-TID statistics | ||
| 959 | * @filled: bitmap of flags using the bits of &enum nl80211_tid_stats to | ||
| 960 | * indicate the relevant values in this struct are filled | ||
| 961 | * @rx_msdu: number of received MSDUs | ||
| 962 | * @tx_msdu: number of (attempted) transmitted MSDUs | ||
| 963 | * @tx_msdu_retries: number of retries (not counting the first) for | ||
| 964 | * transmitted MSDUs | ||
| 965 | * @tx_msdu_failed: number of failed transmitted MSDUs | ||
| 966 | */ | ||
| 967 | struct cfg80211_tid_stats { | ||
| 968 | u32 filled; | ||
| 969 | u64 rx_msdu; | ||
| 970 | u64 tx_msdu; | ||
| 971 | u64 tx_msdu_retries; | ||
| 972 | u64 tx_msdu_failed; | ||
| 973 | }; | ||
| 974 | |||
| 1006 | #define IEEE80211_MAX_CHAINS 4 | 975 | #define IEEE80211_MAX_CHAINS 4 |
| 1007 | 976 | ||
| 1008 | /** | 977 | /** |
| @@ -1010,11 +979,12 @@ struct sta_bss_parameters { | |||
| 1010 | * | 979 | * |
| 1011 | * Station information filled by driver for get_station() and dump_station. | 980 | * Station information filled by driver for get_station() and dump_station. |
| 1012 | * | 981 | * |
| 1013 | * @filled: bitflag of flags from &enum station_info_flags | 982 | * @filled: bitflag of flags using the bits of &enum nl80211_sta_info to |
| 983 | * indicate the relevant values in this struct for them | ||
| 1014 | * @connected_time: time(in secs) since a station is last connected | 984 | * @connected_time: time(in secs) since a station is last connected |
| 1015 | * @inactive_time: time since last station activity (tx/rx) in milliseconds | 985 | * @inactive_time: time since last station activity (tx/rx) in milliseconds |
| 1016 | * @rx_bytes: bytes received from this station | 986 | * @rx_bytes: bytes (size of MPDUs) received from this station |
| 1017 | * @tx_bytes: bytes transmitted to this station | 987 | * @tx_bytes: bytes (size of MPDUs) transmitted to this station |
| 1018 | * @llid: mesh local link id | 988 | * @llid: mesh local link id |
| 1019 | * @plid: mesh peer link id | 989 | * @plid: mesh peer link id |
| 1020 | * @plink_state: mesh peer link state | 990 | * @plink_state: mesh peer link state |
| @@ -1027,10 +997,10 @@ struct sta_bss_parameters { | |||
| 1027 | * @chain_signal_avg: per-chain signal strength average in dBm | 997 | * @chain_signal_avg: per-chain signal strength average in dBm |
| 1028 | * @txrate: current unicast bitrate from this station | 998 | * @txrate: current unicast bitrate from this station |
| 1029 | * @rxrate: current unicast bitrate to this station | 999 | * @rxrate: current unicast bitrate to this station |
| 1030 | * @rx_packets: packets received from this station | 1000 | * @rx_packets: packets (MSDUs & MMPDUs) received from this station |
| 1031 | * @tx_packets: packets transmitted to this station | 1001 | * @tx_packets: packets (MSDUs & MMPDUs) transmitted to this station |
| 1032 | * @tx_retries: cumulative retry counts | 1002 | * @tx_retries: cumulative retry counts (MPDUs) |
| 1033 | * @tx_failed: number of failed transmissions (retries exceeded, no ACK) | 1003 | * @tx_failed: number of failed transmissions (MPDUs) (retries exceeded, no ACK) |
| 1034 | * @rx_dropped_misc: Dropped for un-specified reason. | 1004 | * @rx_dropped_misc: Dropped for un-specified reason. |
| 1035 | * @bss_param: current BSS parameters | 1005 | * @bss_param: current BSS parameters |
| 1036 | * @generation: generation number for nl80211 dumps. | 1006 | * @generation: generation number for nl80211 dumps. |
| @@ -1050,6 +1020,11 @@ struct sta_bss_parameters { | |||
| 1050 | * @nonpeer_pm: non-peer mesh STA power save mode | 1020 | * @nonpeer_pm: non-peer mesh STA power save mode |
| 1051 | * @expected_throughput: expected throughput in kbps (including 802.11 headers) | 1021 | * @expected_throughput: expected throughput in kbps (including 802.11 headers) |
| 1052 | * towards this station. | 1022 | * towards this station. |
| 1023 | * @rx_beacon: number of beacons received from this peer | ||
| 1024 | * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received | ||
| 1025 | * from this peer | ||
| 1026 | * @pertid: per-TID statistics, see &struct cfg80211_tid_stats, using the last | ||
| 1027 | * (IEEE80211_NUM_TIDS) index for MSDUs not encapsulated in QoS-MPDUs. | ||
| 1053 | */ | 1028 | */ |
| 1054 | struct station_info { | 1029 | struct station_info { |
| 1055 | u32 filled; | 1030 | u32 filled; |
| @@ -1090,10 +1065,9 @@ struct station_info { | |||
| 1090 | 1065 | ||
| 1091 | u32 expected_throughput; | 1066 | u32 expected_throughput; |
| 1092 | 1067 | ||
| 1093 | /* | 1068 | u64 rx_beacon; |
| 1094 | * Note: Add a new enum station_info_flags value for each new field and | 1069 | u8 rx_beacon_signal_avg; |
| 1095 | * use it to check which fields are initialized. | 1070 | struct cfg80211_tid_stats pertid[IEEE80211_NUM_TIDS + 1]; |
| 1096 | */ | ||
| 1097 | }; | 1071 | }; |
| 1098 | 1072 | ||
| 1099 | /** | 1073 | /** |
| @@ -1516,6 +1490,9 @@ struct cfg80211_match_set { | |||
| 1516 | * @mac_addr_mask: MAC address mask used with randomisation, bits that | 1490 | * @mac_addr_mask: MAC address mask used with randomisation, bits that |
| 1517 | * are 0 in the mask should be randomised, bits that are 1 should | 1491 | * are 0 in the mask should be randomised, bits that are 1 should |
| 1518 | * be taken from the @mac_addr | 1492 | * be taken from the @mac_addr |
| 1493 | * @rcu_head: RCU callback used to free the struct | ||
| 1494 | * @owner_nlportid: netlink portid of owner (if this should is a request | ||
| 1495 | * owned by a particular socket) | ||
| 1519 | */ | 1496 | */ |
| 1520 | struct cfg80211_sched_scan_request { | 1497 | struct cfg80211_sched_scan_request { |
| 1521 | struct cfg80211_ssid *ssids; | 1498 | struct cfg80211_ssid *ssids; |
| @@ -1537,6 +1514,8 @@ struct cfg80211_sched_scan_request { | |||
| 1537 | struct wiphy *wiphy; | 1514 | struct wiphy *wiphy; |
| 1538 | struct net_device *dev; | 1515 | struct net_device *dev; |
| 1539 | unsigned long scan_start; | 1516 | unsigned long scan_start; |
| 1517 | struct rcu_head rcu_head; | ||
| 1518 | u32 owner_nlportid; | ||
| 1540 | 1519 | ||
| 1541 | /* keep last */ | 1520 | /* keep last */ |
| 1542 | struct ieee80211_channel *channels[0]; | 1521 | struct ieee80211_channel *channels[0]; |
| @@ -3011,6 +2990,8 @@ struct wiphy_vendor_command { | |||
| 3011 | * @regulatory_flags: wiphy regulatory flags, see | 2990 | * @regulatory_flags: wiphy regulatory flags, see |
| 3012 | * &enum ieee80211_regulatory_flags | 2991 | * &enum ieee80211_regulatory_flags |
| 3013 | * @features: features advertised to nl80211, see &enum nl80211_feature_flags. | 2992 | * @features: features advertised to nl80211, see &enum nl80211_feature_flags. |
| 2993 | * @ext_features: extended features advertised to nl80211, see | ||
| 2994 | * &enum nl80211_ext_feature_index. | ||
| 3014 | * @bss_priv_size: each BSS struct has private data allocated with it, | 2995 | * @bss_priv_size: each BSS struct has private data allocated with it, |
| 3015 | * this variable determines its size | 2996 | * this variable determines its size |
| 3016 | * @max_scan_ssids: maximum number of SSIDs the device can scan for in | 2997 | * @max_scan_ssids: maximum number of SSIDs the device can scan for in |
| @@ -3120,6 +3101,7 @@ struct wiphy { | |||
| 3120 | u16 max_acl_mac_addrs; | 3101 | u16 max_acl_mac_addrs; |
| 3121 | 3102 | ||
| 3122 | u32 flags, regulatory_flags, features; | 3103 | u32 flags, regulatory_flags, features; |
| 3104 | u8 ext_features[DIV_ROUND_UP(NUM_NL80211_EXT_FEATURES, 8)]; | ||
| 3123 | 3105 | ||
| 3124 | u32 ap_sme_capa; | 3106 | u32 ap_sme_capa; |
| 3125 | 3107 | ||
| @@ -3808,6 +3790,34 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, | |||
| 3808 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2); | 3790 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2); |
| 3809 | 3791 | ||
| 3810 | /** | 3792 | /** |
| 3793 | * regulatory_set_wiphy_regd - set regdom info for self managed drivers | ||
| 3794 | * @wiphy: the wireless device we want to process the regulatory domain on | ||
| 3795 | * @rd: the regulatory domain informatoin to use for this wiphy | ||
| 3796 | * | ||
| 3797 | * Set the regulatory domain information for self-managed wiphys, only they | ||
| 3798 | * may use this function. See %REGULATORY_WIPHY_SELF_MANAGED for more | ||
| 3799 | * information. | ||
| 3800 | * | ||
| 3801 | * Return: 0 on success. -EINVAL, -EPERM | ||
| 3802 | */ | ||
| 3803 | int regulatory_set_wiphy_regd(struct wiphy *wiphy, | ||
| 3804 | struct ieee80211_regdomain *rd); | ||
| 3805 | |||
| 3806 | /** | ||
| 3807 | * regulatory_set_wiphy_regd_sync_rtnl - set regdom for self-managed drivers | ||
| 3808 | * @wiphy: the wireless device we want to process the regulatory domain on | ||
| 3809 | * @rd: the regulatory domain information to use for this wiphy | ||
| 3810 | * | ||
| 3811 | * This functions requires the RTNL to be held and applies the new regdomain | ||
| 3812 | * synchronously to this wiphy. For more details see | ||
| 3813 | * regulatory_set_wiphy_regd(). | ||
| 3814 | * | ||
| 3815 | * Return: 0 on success. -EINVAL, -EPERM | ||
| 3816 | */ | ||
| 3817 | int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, | ||
| 3818 | struct ieee80211_regdomain *rd); | ||
| 3819 | |||
| 3820 | /** | ||
| 3811 | * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain | 3821 | * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain |
| 3812 | * @wiphy: the wireless device we want to process the regulatory domain on | 3822 | * @wiphy: the wireless device we want to process the regulatory domain on |
| 3813 | * @regd: the custom regulatory domain to use for this wiphy | 3823 | * @regd: the custom regulatory domain to use for this wiphy |
| @@ -4565,13 +4575,27 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
| 4565 | struct station_info *sinfo, gfp_t gfp); | 4575 | struct station_info *sinfo, gfp_t gfp); |
| 4566 | 4576 | ||
| 4567 | /** | 4577 | /** |
| 4578 | * cfg80211_del_sta_sinfo - notify userspace about deletion of a station | ||
| 4579 | * @dev: the netdev | ||
| 4580 | * @mac_addr: the station's address | ||
| 4581 | * @sinfo: the station information/statistics | ||
| 4582 | * @gfp: allocation flags | ||
| 4583 | */ | ||
| 4584 | void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr, | ||
| 4585 | struct station_info *sinfo, gfp_t gfp); | ||
| 4586 | |||
| 4587 | /** | ||
| 4568 | * cfg80211_del_sta - notify userspace about deletion of a station | 4588 | * cfg80211_del_sta - notify userspace about deletion of a station |
| 4569 | * | 4589 | * |
| 4570 | * @dev: the netdev | 4590 | * @dev: the netdev |
| 4571 | * @mac_addr: the station's address | 4591 | * @mac_addr: the station's address |
| 4572 | * @gfp: allocation flags | 4592 | * @gfp: allocation flags |
| 4573 | */ | 4593 | */ |
| 4574 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); | 4594 | static inline void cfg80211_del_sta(struct net_device *dev, |
| 4595 | const u8 *mac_addr, gfp_t gfp) | ||
| 4596 | { | ||
| 4597 | cfg80211_del_sta_sinfo(dev, mac_addr, NULL, gfp); | ||
| 4598 | } | ||
| 4575 | 4599 | ||
| 4576 | /** | 4600 | /** |
| 4577 | * cfg80211_conn_failed - connection request failed notification | 4601 | * cfg80211_conn_failed - connection request failed notification |
| @@ -5033,6 +5057,42 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
| 5033 | */ | 5057 | */ |
| 5034 | void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy); | 5058 | void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy); |
| 5035 | 5059 | ||
| 5060 | /** | ||
| 5061 | * wiphy_ext_feature_set - set the extended feature flag | ||
| 5062 | * | ||
| 5063 | * @wiphy: the wiphy to modify. | ||
| 5064 | * @ftidx: extended feature bit index. | ||
| 5065 | * | ||
| 5066 | * The extended features are flagged in multiple bytes (see | ||
| 5067 | * &struct wiphy.@ext_features) | ||
| 5068 | */ | ||
| 5069 | static inline void wiphy_ext_feature_set(struct wiphy *wiphy, | ||
| 5070 | enum nl80211_ext_feature_index ftidx) | ||
| 5071 | { | ||
| 5072 | u8 *ft_byte; | ||
| 5073 | |||
| 5074 | ft_byte = &wiphy->ext_features[ftidx / 8]; | ||
| 5075 | *ft_byte |= BIT(ftidx % 8); | ||
| 5076 | } | ||
| 5077 | |||
| 5078 | /** | ||
| 5079 | * wiphy_ext_feature_isset - check the extended feature flag | ||
| 5080 | * | ||
| 5081 | * @wiphy: the wiphy to modify. | ||
| 5082 | * @ftidx: extended feature bit index. | ||
| 5083 | * | ||
| 5084 | * The extended features are flagged in multiple bytes (see | ||
| 5085 | * &struct wiphy.@ext_features) | ||
| 5086 | */ | ||
| 5087 | static inline bool | ||
| 5088 | wiphy_ext_feature_isset(struct wiphy *wiphy, | ||
| 5089 | enum nl80211_ext_feature_index ftidx) | ||
| 5090 | { | ||
| 5091 | u8 ft_byte; | ||
| 5092 | |||
| 5093 | ft_byte = wiphy->ext_features[ftidx / 8]; | ||
| 5094 | return (ft_byte & BIT(ftidx % 8)) != 0; | ||
| 5095 | } | ||
| 5036 | 5096 | ||
| 5037 | /* ethtool helper */ | 5097 | /* ethtool helper */ |
| 5038 | void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); | 5098 | void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 58d719ddaa60..275ee56152ad 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
| @@ -505,8 +505,11 @@ struct ieee80211_bss_conf { | |||
| 505 | * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it | 505 | * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it |
| 506 | * would be fragmented by size (this is optional, only used for | 506 | * would be fragmented by size (this is optional, only used for |
| 507 | * monitor injection). | 507 | * monitor injection). |
| 508 | * @IEEE80211_TX_CTL_PS_RESPONSE: This frame is a response to a poll | 508 | * @IEEE80211_TX_STAT_NOACK_TRANSMITTED: A frame that was marked with |
| 509 | * frame (PS-Poll or uAPSD). | 509 | * IEEE80211_TX_CTL_NO_ACK has been successfully transmitted without |
| 510 | * any errors (like issues specific to the driver/HW). | ||
| 511 | * This flag must not be set for frames that don't request no-ack | ||
| 512 | * behaviour with IEEE80211_TX_CTL_NO_ACK. | ||
| 510 | * | 513 | * |
| 511 | * Note: If you have to add new flags to the enumeration, then don't | 514 | * Note: If you have to add new flags to the enumeration, then don't |
| 512 | * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. | 515 | * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. |
| @@ -542,7 +545,7 @@ enum mac80211_tx_info_flags { | |||
| 542 | IEEE80211_TX_STATUS_EOSP = BIT(28), | 545 | IEEE80211_TX_STATUS_EOSP = BIT(28), |
| 543 | IEEE80211_TX_CTL_USE_MINRATE = BIT(29), | 546 | IEEE80211_TX_CTL_USE_MINRATE = BIT(29), |
| 544 | IEEE80211_TX_CTL_DONTFRAG = BIT(30), | 547 | IEEE80211_TX_CTL_DONTFRAG = BIT(30), |
| 545 | IEEE80211_TX_CTL_PS_RESPONSE = BIT(31), | 548 | IEEE80211_TX_STAT_NOACK_TRANSMITTED = BIT(31), |
| 546 | }; | 549 | }; |
| 547 | 550 | ||
| 548 | #define IEEE80211_TX_CTL_STBC_SHIFT 23 | 551 | #define IEEE80211_TX_CTL_STBC_SHIFT 23 |
| @@ -552,11 +555,14 @@ enum mac80211_tx_info_flags { | |||
| 552 | * | 555 | * |
| 553 | * @IEEE80211_TX_CTRL_PORT_CTRL_PROTO: this frame is a port control | 556 | * @IEEE80211_TX_CTRL_PORT_CTRL_PROTO: this frame is a port control |
| 554 | * protocol frame (e.g. EAP) | 557 | * protocol frame (e.g. EAP) |
| 558 | * @IEEE80211_TX_CTRL_PS_RESPONSE: This frame is a response to a poll | ||
| 559 | * frame (PS-Poll or uAPSD). | ||
| 555 | * | 560 | * |
| 556 | * These flags are used in tx_info->control.flags. | 561 | * These flags are used in tx_info->control.flags. |
| 557 | */ | 562 | */ |
| 558 | enum mac80211_tx_control_flags { | 563 | enum mac80211_tx_control_flags { |
| 559 | IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0), | 564 | IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0), |
| 565 | IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1), | ||
| 560 | }; | 566 | }; |
| 561 | 567 | ||
| 562 | /* | 568 | /* |
| @@ -925,15 +931,13 @@ enum mac80211_rx_flags { | |||
| 925 | * These flags are used with the @vht_flag member of | 931 | * These flags are used with the @vht_flag member of |
| 926 | * &struct ieee80211_rx_status. | 932 | * &struct ieee80211_rx_status. |
| 927 | * @RX_VHT_FLAG_80MHZ: 80 MHz was used | 933 | * @RX_VHT_FLAG_80MHZ: 80 MHz was used |
| 928 | * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used | ||
| 929 | * @RX_VHT_FLAG_160MHZ: 160 MHz was used | 934 | * @RX_VHT_FLAG_160MHZ: 160 MHz was used |
| 930 | * @RX_VHT_FLAG_BF: packet was beamformed | 935 | * @RX_VHT_FLAG_BF: packet was beamformed |
| 931 | */ | 936 | */ |
| 932 | enum mac80211_rx_vht_flags { | 937 | enum mac80211_rx_vht_flags { |
| 933 | RX_VHT_FLAG_80MHZ = BIT(0), | 938 | RX_VHT_FLAG_80MHZ = BIT(0), |
| 934 | RX_VHT_FLAG_80P80MHZ = BIT(1), | 939 | RX_VHT_FLAG_160MHZ = BIT(1), |
| 935 | RX_VHT_FLAG_160MHZ = BIT(2), | 940 | RX_VHT_FLAG_BF = BIT(2), |
| 936 | RX_VHT_FLAG_BF = BIT(3), | ||
| 937 | }; | 941 | }; |
| 938 | 942 | ||
| 939 | /** | 943 | /** |
| @@ -1181,10 +1185,15 @@ struct ieee80211_channel_switch { | |||
| 1181 | * monitoring on this virtual interface -- i.e. it can monitor | 1185 | * monitoring on this virtual interface -- i.e. it can monitor |
| 1182 | * connection quality related parameters, such as the RSSI level and | 1186 | * connection quality related parameters, such as the RSSI level and |
| 1183 | * provide notifications if configured trigger levels are reached. | 1187 | * provide notifications if configured trigger levels are reached. |
| 1188 | * @IEEE80211_VIF_SUPPORTS_UAPSD: The device can do U-APSD for this | ||
| 1189 | * interface. This flag should be set during interface addition, | ||
| 1190 | * but may be set/cleared as late as authentication to an AP. It is | ||
| 1191 | * only valid for managed/station mode interfaces. | ||
| 1184 | */ | 1192 | */ |
| 1185 | enum ieee80211_vif_flags { | 1193 | enum ieee80211_vif_flags { |
| 1186 | IEEE80211_VIF_BEACON_FILTER = BIT(0), | 1194 | IEEE80211_VIF_BEACON_FILTER = BIT(0), |
| 1187 | IEEE80211_VIF_SUPPORTS_CQM_RSSI = BIT(1), | 1195 | IEEE80211_VIF_SUPPORTS_CQM_RSSI = BIT(1), |
| 1196 | IEEE80211_VIF_SUPPORTS_UAPSD = BIT(2), | ||
| 1188 | }; | 1197 | }; |
| 1189 | 1198 | ||
| 1190 | /** | 1199 | /** |
| @@ -1296,6 +1305,9 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev); | |||
| 1296 | * @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the | 1305 | * @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the |
| 1297 | * driver for a CCMP key to indicate that is requires IV generation | 1306 | * driver for a CCMP key to indicate that is requires IV generation |
| 1298 | * only for managment frames (MFP). | 1307 | * only for managment frames (MFP). |
| 1308 | * @IEEE80211_KEY_FLAG_RESERVE_TAILROOM: This flag should be set by the | ||
| 1309 | * driver for a key to indicate that sufficient tailroom must always | ||
| 1310 | * be reserved for ICV or MIC, even when HW encryption is enabled. | ||
| 1299 | */ | 1311 | */ |
| 1300 | enum ieee80211_key_flags { | 1312 | enum ieee80211_key_flags { |
| 1301 | IEEE80211_KEY_FLAG_GENERATE_IV_MGMT = BIT(0), | 1313 | IEEE80211_KEY_FLAG_GENERATE_IV_MGMT = BIT(0), |
| @@ -1305,6 +1317,7 @@ enum ieee80211_key_flags { | |||
| 1305 | IEEE80211_KEY_FLAG_SW_MGMT_TX = BIT(4), | 1317 | IEEE80211_KEY_FLAG_SW_MGMT_TX = BIT(4), |
| 1306 | IEEE80211_KEY_FLAG_PUT_IV_SPACE = BIT(5), | 1318 | IEEE80211_KEY_FLAG_PUT_IV_SPACE = BIT(5), |
| 1307 | IEEE80211_KEY_FLAG_RX_MGMT = BIT(6), | 1319 | IEEE80211_KEY_FLAG_RX_MGMT = BIT(6), |
| 1320 | IEEE80211_KEY_FLAG_RESERVE_TAILROOM = BIT(7), | ||
| 1308 | }; | 1321 | }; |
| 1309 | 1322 | ||
| 1310 | /** | 1323 | /** |
| @@ -1583,11 +1596,6 @@ struct ieee80211_tx_control { | |||
| 1583 | * @IEEE80211_HW_MFP_CAPABLE: | 1596 | * @IEEE80211_HW_MFP_CAPABLE: |
| 1584 | * Hardware supports management frame protection (MFP, IEEE 802.11w). | 1597 | * Hardware supports management frame protection (MFP, IEEE 802.11w). |
| 1585 | * | 1598 | * |
| 1586 | * @IEEE80211_HW_SUPPORTS_UAPSD: | ||
| 1587 | * Hardware supports Unscheduled Automatic Power Save Delivery | ||
| 1588 | * (U-APSD) in managed mode. The mode is configured with | ||
| 1589 | * conf_tx() operation. | ||
| 1590 | * | ||
| 1591 | * @IEEE80211_HW_REPORTS_TX_ACK_STATUS: | 1599 | * @IEEE80211_HW_REPORTS_TX_ACK_STATUS: |
| 1592 | * Hardware can provide ack status reports of Tx frames to | 1600 | * Hardware can provide ack status reports of Tx frames to |
| 1593 | * the stack. | 1601 | * the stack. |
| @@ -1673,8 +1681,7 @@ enum ieee80211_hw_flags { | |||
| 1673 | IEEE80211_HW_MFP_CAPABLE = 1<<13, | 1681 | IEEE80211_HW_MFP_CAPABLE = 1<<13, |
| 1674 | IEEE80211_HW_WANT_MONITOR_VIF = 1<<14, | 1682 | IEEE80211_HW_WANT_MONITOR_VIF = 1<<14, |
| 1675 | IEEE80211_HW_NO_AUTO_VIF = 1<<15, | 1683 | IEEE80211_HW_NO_AUTO_VIF = 1<<15, |
| 1676 | /* free slot */ | 1684 | /* free slots */ |
| 1677 | IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, | ||
| 1678 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, | 1685 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, |
| 1679 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, | 1686 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, |
| 1680 | IEEE80211_HW_QUEUE_CONTROL = 1<<20, | 1687 | IEEE80211_HW_QUEUE_CONTROL = 1<<20, |
| @@ -2026,7 +2033,7 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
| 2026 | * enabled whenever user has enabled powersave. | 2033 | * enabled whenever user has enabled powersave. |
| 2027 | * | 2034 | * |
| 2028 | * Driver informs U-APSD client support by enabling | 2035 | * Driver informs U-APSD client support by enabling |
| 2029 | * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the | 2036 | * %IEEE80211_VIF_SUPPORTS_UAPSD flag. The mode is configured through the |
| 2030 | * uapsd parameter in conf_tx() operation. Hardware needs to send the QoS | 2037 | * uapsd parameter in conf_tx() operation. Hardware needs to send the QoS |
| 2031 | * Nullfunc frames and stay awake until the service period has ended. To | 2038 | * Nullfunc frames and stay awake until the service period has ended. To |
| 2032 | * utilize U-APSD, dynamic powersave is disabled for voip AC and all frames | 2039 | * utilize U-APSD, dynamic powersave is disabled for voip AC and all frames |
| @@ -2699,6 +2706,14 @@ enum ieee80211_reconfig_type { | |||
| 2699 | * is only used if the configured rate control algorithm actually uses | 2706 | * is only used if the configured rate control algorithm actually uses |
| 2700 | * the new rate table API, and is therefore optional. Must be atomic. | 2707 | * the new rate table API, and is therefore optional. Must be atomic. |
| 2701 | * | 2708 | * |
| 2709 | * @sta_statistics: Get statistics for this station. For example with beacon | ||
| 2710 | * filtering, the statistics kept by mac80211 might not be accurate, so | ||
| 2711 | * let the driver pre-fill the statistics. The driver can fill most of | ||
| 2712 | * the values (indicating which by setting the filled bitmap), but not | ||
| 2713 | * all of them make sense - see the source for which ones are possible. | ||
| 2714 | * Statistics that the driver doesn't fill will be filled by mac80211. | ||
| 2715 | * The callback can sleep. | ||
| 2716 | * | ||
| 2702 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), | 2717 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), |
| 2703 | * bursting) for a hardware TX queue. | 2718 | * bursting) for a hardware TX queue. |
| 2704 | * Returns a negative error code on failure. | 2719 | * Returns a negative error code on failure. |
| @@ -2859,9 +2874,6 @@ enum ieee80211_reconfig_type { | |||
| 2859 | * @get_et_strings: Ethtool API to get a set of strings to describe stats | 2874 | * @get_et_strings: Ethtool API to get a set of strings to describe stats |
| 2860 | * and perhaps other supported types of ethtool data-sets. | 2875 | * and perhaps other supported types of ethtool data-sets. |
| 2861 | * | 2876 | * |
| 2862 | * @get_rssi: Get current signal strength in dBm, the function is optional | ||
| 2863 | * and can sleep. | ||
| 2864 | * | ||
| 2865 | * @mgd_prepare_tx: Prepare for transmitting a management frame for association | 2877 | * @mgd_prepare_tx: Prepare for transmitting a management frame for association |
| 2866 | * before associated. In multi-channel scenarios, a virtual interface is | 2878 | * before associated. In multi-channel scenarios, a virtual interface is |
| 2867 | * bound to a channel before it is associated, but as it isn't associated | 2879 | * bound to a channel before it is associated, but as it isn't associated |
| @@ -3062,6 +3074,10 @@ struct ieee80211_ops { | |||
| 3062 | void (*sta_rate_tbl_update)(struct ieee80211_hw *hw, | 3074 | void (*sta_rate_tbl_update)(struct ieee80211_hw *hw, |
| 3063 | struct ieee80211_vif *vif, | 3075 | struct ieee80211_vif *vif, |
| 3064 | struct ieee80211_sta *sta); | 3076 | struct ieee80211_sta *sta); |
| 3077 | void (*sta_statistics)(struct ieee80211_hw *hw, | ||
| 3078 | struct ieee80211_vif *vif, | ||
| 3079 | struct ieee80211_sta *sta, | ||
| 3080 | struct station_info *sinfo); | ||
| 3065 | int (*conf_tx)(struct ieee80211_hw *hw, | 3081 | int (*conf_tx)(struct ieee80211_hw *hw, |
| 3066 | struct ieee80211_vif *vif, u16 ac, | 3082 | struct ieee80211_vif *vif, u16 ac, |
| 3067 | const struct ieee80211_tx_queue_params *params); | 3083 | const struct ieee80211_tx_queue_params *params); |
| @@ -3129,8 +3145,6 @@ struct ieee80211_ops { | |||
| 3129 | void (*get_et_strings)(struct ieee80211_hw *hw, | 3145 | void (*get_et_strings)(struct ieee80211_hw *hw, |
| 3130 | struct ieee80211_vif *vif, | 3146 | struct ieee80211_vif *vif, |
| 3131 | u32 sset, u8 *data); | 3147 | u32 sset, u8 *data); |
| 3132 | int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 3133 | struct ieee80211_sta *sta, s8 *rssi_dbm); | ||
| 3134 | 3148 | ||
| 3135 | void (*mgd_prepare_tx)(struct ieee80211_hw *hw, | 3149 | void (*mgd_prepare_tx)(struct ieee80211_hw *hw, |
| 3136 | struct ieee80211_vif *vif); | 3150 | struct ieee80211_vif *vif); |
diff --git a/include/net/regulatory.h b/include/net/regulatory.h index b776d72d84be..ebc5a2ed8631 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h | |||
| @@ -147,6 +147,24 @@ struct regulatory_request { | |||
| 147 | * NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_P2P_GO, | 147 | * NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_P2P_GO, |
| 148 | * NL80211_IFTYPE_P2P_DEVICE. The flag will be set by default if a device | 148 | * NL80211_IFTYPE_P2P_DEVICE. The flag will be set by default if a device |
| 149 | * includes any modes unsupported for enforcement checking. | 149 | * includes any modes unsupported for enforcement checking. |
| 150 | * @REGULATORY_WIPHY_SELF_MANAGED: for devices that employ wiphy-specific | ||
| 151 | * regdom management. These devices will ignore all regdom changes not | ||
| 152 | * originating from their own wiphy. | ||
| 153 | * A self-managed wiphys only employs regulatory information obtained from | ||
| 154 | * the FW and driver and does not use other cfg80211 sources like | ||
| 155 | * beacon-hints, country-code IEs and hints from other devices on the same | ||
| 156 | * system. Conversely, a self-managed wiphy does not share its regulatory | ||
| 157 | * hints with other devices in the system. If a system contains several | ||
| 158 | * devices, one or more of which are self-managed, there might be | ||
| 159 | * contradictory regulatory settings between them. Usage of flag is | ||
| 160 | * generally discouraged. Only use it if the FW/driver is incompatible | ||
| 161 | * with non-locally originated hints. | ||
| 162 | * This flag is incompatible with the flags: %REGULATORY_CUSTOM_REG, | ||
| 163 | * %REGULATORY_STRICT_REG, %REGULATORY_COUNTRY_IE_FOLLOW_POWER, | ||
| 164 | * %REGULATORY_COUNTRY_IE_IGNORE and %REGULATORY_DISABLE_BEACON_HINTS. | ||
| 165 | * Mixing any of the above flags with this flag will result in a failure | ||
| 166 | * to register the wiphy. This flag implies | ||
| 167 | * %REGULATORY_DISABLE_BEACON_HINTS and %REGULATORY_COUNTRY_IE_IGNORE. | ||
| 150 | */ | 168 | */ |
| 151 | enum ieee80211_regulatory_flags { | 169 | enum ieee80211_regulatory_flags { |
| 152 | REGULATORY_CUSTOM_REG = BIT(0), | 170 | REGULATORY_CUSTOM_REG = BIT(0), |
| @@ -156,6 +174,7 @@ enum ieee80211_regulatory_flags { | |||
| 156 | REGULATORY_COUNTRY_IE_IGNORE = BIT(4), | 174 | REGULATORY_COUNTRY_IE_IGNORE = BIT(4), |
| 157 | REGULATORY_ENABLE_RELAX_NO_IR = BIT(5), | 175 | REGULATORY_ENABLE_RELAX_NO_IR = BIT(5), |
| 158 | REGULATORY_IGNORE_STALE_KICKOFF = BIT(6), | 176 | REGULATORY_IGNORE_STALE_KICKOFF = BIT(6), |
| 177 | REGULATORY_WIPHY_SELF_MANAGED = BIT(7), | ||
| 159 | }; | 178 | }; |
| 160 | 179 | ||
| 161 | struct ieee80211_freq_range { | 180 | struct ieee80211_freq_range { |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b37bd5a1cb82..f52797a90816 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
| @@ -29,6 +29,13 @@ | |||
| 29 | 29 | ||
| 30 | #define NL80211_GENL_NAME "nl80211" | 30 | #define NL80211_GENL_NAME "nl80211" |
| 31 | 31 | ||
| 32 | #define NL80211_MULTICAST_GROUP_CONFIG "config" | ||
| 33 | #define NL80211_MULTICAST_GROUP_SCAN "scan" | ||
| 34 | #define NL80211_MULTICAST_GROUP_REG "regulatory" | ||
| 35 | #define NL80211_MULTICAST_GROUP_MLME "mlme" | ||
| 36 | #define NL80211_MULTICAST_GROUP_VENDOR "vendor" | ||
| 37 | #define NL80211_MULTICAST_GROUP_TESTMODE "testmode" | ||
| 38 | |||
| 32 | /** | 39 | /** |
| 33 | * DOC: Station handling | 40 | * DOC: Station handling |
| 34 | * | 41 | * |
| @@ -252,7 +259,18 @@ | |||
| 252 | * %NL80211_ATTR_IFINDEX. | 259 | * %NL80211_ATTR_IFINDEX. |
| 253 | * | 260 | * |
| 254 | * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set | 261 | * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set |
| 255 | * regulatory domain. | 262 | * regulatory domain. If %NL80211_ATTR_WIPHY is specified and the device |
| 263 | * has a private regulatory domain, it will be returned. Otherwise, the | ||
| 264 | * global regdomain will be returned. | ||
| 265 | * A device will have a private regulatory domain if it uses the | ||
| 266 | * regulatory_hint() API. Even when a private regdomain is used the channel | ||
| 267 | * information will still be mended according to further hints from | ||
| 268 | * the regulatory core to help with compliance. A dump version of this API | ||
| 269 | * is now available which will returns the global regdomain as well as | ||
| 270 | * all private regdomains of present wiphys (for those that have it). | ||
| 271 | * If a wiphy is self-managed (%NL80211_ATTR_WIPHY_SELF_MANAGED_REG), then | ||
| 272 | * its private regdomain is the only valid one for it. The regulatory | ||
| 273 | * core is not used to help with compliance in this case. | ||
| 256 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command | 274 | * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command |
| 257 | * after being queried by the kernel. CRDA replies by sending a regulatory | 275 | * after being queried by the kernel. CRDA replies by sending a regulatory |
| 258 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our | 276 | * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our |
| @@ -774,6 +792,10 @@ | |||
| 774 | * peer given by %NL80211_ATTR_MAC. Both peers must be on the base channel | 792 | * peer given by %NL80211_ATTR_MAC. Both peers must be on the base channel |
| 775 | * when this command completes. | 793 | * when this command completes. |
| 776 | * | 794 | * |
| 795 | * @NL80211_CMD_WIPHY_REG_CHANGE: Similar to %NL80211_CMD_REG_CHANGE, but used | ||
| 796 | * as an event to indicate changes for devices with wiphy-specific regdom | ||
| 797 | * management. | ||
| 798 | * | ||
| 777 | * @NL80211_CMD_MAX: highest used command number | 799 | * @NL80211_CMD_MAX: highest used command number |
| 778 | * @__NL80211_CMD_AFTER_LAST: internal use | 800 | * @__NL80211_CMD_AFTER_LAST: internal use |
| 779 | */ | 801 | */ |
| @@ -958,6 +980,8 @@ enum nl80211_commands { | |||
| 958 | NL80211_CMD_TDLS_CHANNEL_SWITCH, | 980 | NL80211_CMD_TDLS_CHANNEL_SWITCH, |
| 959 | NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, | 981 | NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, |
| 960 | 982 | ||
| 983 | NL80211_CMD_WIPHY_REG_CHANGE, | ||
| 984 | |||
| 961 | /* add new commands above here */ | 985 | /* add new commands above here */ |
| 962 | 986 | ||
| 963 | /* used to define NL80211_CMD_MAX below */ | 987 | /* used to define NL80211_CMD_MAX below */ |
| @@ -1655,6 +1679,9 @@ enum nl80211_commands { | |||
| 1655 | * @NL80211_ATTR_SOCKET_OWNER: Flag attribute, if set during interface | 1679 | * @NL80211_ATTR_SOCKET_OWNER: Flag attribute, if set during interface |
| 1656 | * creation then the new interface will be owned by the netlink socket | 1680 | * creation then the new interface will be owned by the netlink socket |
| 1657 | * that created it and will be destroyed when the socket is closed. | 1681 | * that created it and will be destroyed when the socket is closed. |
| 1682 | * If set during scheduled scan start then the new scan req will be | ||
| 1683 | * owned by the netlink socket that created it and the scheduled scan will | ||
| 1684 | * be stopped when the socket is closed. | ||
| 1658 | * | 1685 | * |
| 1659 | * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is | 1686 | * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is |
| 1660 | * the TDLS link initiator. | 1687 | * the TDLS link initiator. |
| @@ -1688,6 +1715,26 @@ enum nl80211_commands { | |||
| 1688 | * | 1715 | * |
| 1689 | * @NL80211_ATTR_MAC_MASK: MAC address mask | 1716 | * @NL80211_ATTR_MAC_MASK: MAC address mask |
| 1690 | * | 1717 | * |
| 1718 | * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating this device | ||
| 1719 | * is self-managing its regulatory information and any regulatory domain | ||
| 1720 | * obtained from it is coming from the device's wiphy and not the global | ||
| 1721 | * cfg80211 regdomain. | ||
| 1722 | * | ||
| 1723 | * @NL80211_ATTR_EXT_FEATURES: extended feature flags contained in a byte | ||
| 1724 | * array. The feature flags are identified by their bit index (see &enum | ||
| 1725 | * nl80211_ext_feature_index). The bit index is ordered starting at the | ||
| 1726 | * least-significant bit of the first byte in the array, ie. bit index 0 | ||
| 1727 | * is located at bit 0 of byte 0. bit index 25 would be located at bit 1 | ||
| 1728 | * of byte 3 (u8 array). | ||
| 1729 | * | ||
| 1730 | * @NL80211_ATTR_SURVEY_RADIO_STATS: Request overall radio statistics to be | ||
| 1731 | * returned along with other survey data. If set, @NL80211_CMD_GET_SURVEY | ||
| 1732 | * may return a survey entry without a channel indicating global radio | ||
| 1733 | * statistics (only some values are valid and make sense.) | ||
| 1734 | * For devices that don't return such an entry even then, the information | ||
| 1735 | * should be contained in the result as the sum of the respective counters | ||
| 1736 | * over all channels. | ||
| 1737 | * | ||
| 1691 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available | 1738 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
| 1692 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1739 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 1693 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1740 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| @@ -2045,6 +2092,12 @@ enum nl80211_attrs { | |||
| 2045 | 2092 | ||
| 2046 | NL80211_ATTR_MAC_MASK, | 2093 | NL80211_ATTR_MAC_MASK, |
| 2047 | 2094 | ||
| 2095 | NL80211_ATTR_WIPHY_SELF_MANAGED_REG, | ||
| 2096 | |||
| 2097 | NL80211_ATTR_EXT_FEATURES, | ||
| 2098 | |||
| 2099 | NL80211_ATTR_SURVEY_RADIO_STATS, | ||
| 2100 | |||
| 2048 | /* add attributes here, update the policy in nl80211.c */ | 2101 | /* add attributes here, update the policy in nl80211.c */ |
| 2049 | 2102 | ||
| 2050 | __NL80211_ATTR_AFTER_LAST, | 2103 | __NL80211_ATTR_AFTER_LAST, |
| @@ -2085,7 +2138,7 @@ enum nl80211_attrs { | |||
| 2085 | 2138 | ||
| 2086 | #define NL80211_MAX_SUPP_RATES 32 | 2139 | #define NL80211_MAX_SUPP_RATES 32 |
| 2087 | #define NL80211_MAX_SUPP_HT_RATES 77 | 2140 | #define NL80211_MAX_SUPP_HT_RATES 77 |
| 2088 | #define NL80211_MAX_SUPP_REG_RULES 32 | 2141 | #define NL80211_MAX_SUPP_REG_RULES 64 |
| 2089 | #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 | 2142 | #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 |
| 2090 | #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 | 2143 | #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 |
| 2091 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 | 2144 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 |
| @@ -2225,8 +2278,15 @@ struct nl80211_sta_flag_update { | |||
| 2225 | * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8) | 2278 | * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8) |
| 2226 | * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8) | 2279 | * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8) |
| 2227 | * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate | 2280 | * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate |
| 2228 | * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate | 2281 | * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: unused - 80+80 is treated the |
| 2282 | * same as 160 for purposes of the bitrates | ||
| 2229 | * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate | 2283 | * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate |
| 2284 | * @NL80211_RATE_INFO_10_MHZ_WIDTH: 10 MHz width - note that this is | ||
| 2285 | * a legacy rate and will be reported as the actual bitrate, i.e. | ||
| 2286 | * half the base (20 MHz) rate | ||
| 2287 | * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is | ||
| 2288 | * a legacy rate and will be reported as the actual bitrate, i.e. | ||
| 2289 | * a quarter of the base (20 MHz) rate | ||
| 2230 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use | 2290 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use |
| 2231 | */ | 2291 | */ |
| 2232 | enum nl80211_rate_info { | 2292 | enum nl80211_rate_info { |
| @@ -2241,6 +2301,8 @@ enum nl80211_rate_info { | |||
| 2241 | NL80211_RATE_INFO_80_MHZ_WIDTH, | 2301 | NL80211_RATE_INFO_80_MHZ_WIDTH, |
| 2242 | NL80211_RATE_INFO_80P80_MHZ_WIDTH, | 2302 | NL80211_RATE_INFO_80P80_MHZ_WIDTH, |
| 2243 | NL80211_RATE_INFO_160_MHZ_WIDTH, | 2303 | NL80211_RATE_INFO_160_MHZ_WIDTH, |
| 2304 | NL80211_RATE_INFO_10_MHZ_WIDTH, | ||
| 2305 | NL80211_RATE_INFO_5_MHZ_WIDTH, | ||
| 2244 | 2306 | ||
| 2245 | /* keep last */ | 2307 | /* keep last */ |
| 2246 | __NL80211_RATE_INFO_AFTER_LAST, | 2308 | __NL80211_RATE_INFO_AFTER_LAST, |
| @@ -2285,18 +2347,24 @@ enum nl80211_sta_bss_param { | |||
| 2285 | * | 2347 | * |
| 2286 | * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved | 2348 | * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved |
| 2287 | * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) | 2349 | * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) |
| 2288 | * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) | 2350 | * @NL80211_STA_INFO_RX_BYTES: total received bytes (MPDU length) |
| 2289 | * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) | 2351 | * (u32, from this station) |
| 2290 | * @NL80211_STA_INFO_RX_BYTES64: total received bytes (u64, from this station) | 2352 | * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (MPDU length) |
| 2291 | * @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (u64, to this station) | 2353 | * (u32, to this station) |
| 2354 | * @NL80211_STA_INFO_RX_BYTES64: total received bytes (MPDU length) | ||
| 2355 | * (u64, from this station) | ||
| 2356 | * @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (MPDU length) | ||
| 2357 | * (u64, to this station) | ||
| 2292 | * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) | 2358 | * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) |
| 2293 | * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute | 2359 | * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute |
| 2294 | * containing info as possible, see &enum nl80211_rate_info | 2360 | * containing info as possible, see &enum nl80211_rate_info |
| 2295 | * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) | 2361 | * @NL80211_STA_INFO_RX_PACKETS: total received packet (MSDUs and MMPDUs) |
| 2296 | * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this | 2362 | * (u32, from this station) |
| 2297 | * station) | 2363 | * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (MSDUs and MMPDUs) |
| 2298 | * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station) | 2364 | * (u32, to this station) |
| 2299 | * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station) | 2365 | * @NL80211_STA_INFO_TX_RETRIES: total retries (MPDUs) (u32, to this station) |
| 2366 | * @NL80211_STA_INFO_TX_FAILED: total failed packets (MPDUs) | ||
| 2367 | * (u32, to this station) | ||
| 2300 | * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm) | 2368 | * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm) |
| 2301 | * @NL80211_STA_INFO_LLID: the station's mesh LLID | 2369 | * @NL80211_STA_INFO_LLID: the station's mesh LLID |
| 2302 | * @NL80211_STA_INFO_PLID: the station's mesh PLID | 2370 | * @NL80211_STA_INFO_PLID: the station's mesh PLID |
| @@ -2320,6 +2388,16 @@ enum nl80211_sta_bss_param { | |||
| 2320 | * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. | 2388 | * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. |
| 2321 | * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the | 2389 | * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the |
| 2322 | * 802.11 header (u32, kbps) | 2390 | * 802.11 header (u32, kbps) |
| 2391 | * @NL80211_STA_INFO_RX_DROP_MISC: RX packets dropped for unspecified reasons | ||
| 2392 | * (u64) | ||
| 2393 | * @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64) | ||
| 2394 | * @NL80211_STA_INFO_BEACON_SIGNAL_AVG: signal strength average | ||
| 2395 | * for beacons only (u8, dBm) | ||
| 2396 | * @NL80211_STA_INFO_TID_STATS: per-TID statistics (see &enum nl80211_tid_stats) | ||
| 2397 | * This is a nested attribute where each the inner attribute number is the | ||
| 2398 | * TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames; | ||
| 2399 | * each one of those is again nested with &enum nl80211_tid_stats | ||
| 2400 | * attributes carrying the actual values. | ||
| 2323 | * @__NL80211_STA_INFO_AFTER_LAST: internal | 2401 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
| 2324 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 2402 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
| 2325 | */ | 2403 | */ |
| @@ -2352,6 +2430,10 @@ enum nl80211_sta_info { | |||
| 2352 | NL80211_STA_INFO_CHAIN_SIGNAL, | 2430 | NL80211_STA_INFO_CHAIN_SIGNAL, |
| 2353 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG, | 2431 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG, |
| 2354 | NL80211_STA_INFO_EXPECTED_THROUGHPUT, | 2432 | NL80211_STA_INFO_EXPECTED_THROUGHPUT, |
| 2433 | NL80211_STA_INFO_RX_DROP_MISC, | ||
| 2434 | NL80211_STA_INFO_BEACON_RX, | ||
| 2435 | NL80211_STA_INFO_BEACON_SIGNAL_AVG, | ||
| 2436 | NL80211_STA_INFO_TID_STATS, | ||
| 2355 | 2437 | ||
| 2356 | /* keep last */ | 2438 | /* keep last */ |
| 2357 | __NL80211_STA_INFO_AFTER_LAST, | 2439 | __NL80211_STA_INFO_AFTER_LAST, |
| @@ -2359,6 +2441,31 @@ enum nl80211_sta_info { | |||
| 2359 | }; | 2441 | }; |
| 2360 | 2442 | ||
| 2361 | /** | 2443 | /** |
| 2444 | * enum nl80211_tid_stats - per TID statistics attributes | ||
| 2445 | * @__NL80211_TID_STATS_INVALID: attribute number 0 is reserved | ||
| 2446 | * @NL80211_TID_STATS_RX_MSDU: number of MSDUs received (u64) | ||
| 2447 | * @NL80211_TID_STATS_TX_MSDU: number of MSDUs transmitted (or | ||
| 2448 | * attempted to transmit; u64) | ||
| 2449 | * @NL80211_TID_STATS_TX_MSDU_RETRIES: number of retries for | ||
| 2450 | * transmitted MSDUs (not counting the first attempt; u64) | ||
| 2451 | * @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted | ||
| 2452 | * MSDUs (u64) | ||
| 2453 | * @NUM_NL80211_TID_STATS: number of attributes here | ||
| 2454 | * @NL80211_TID_STATS_MAX: highest numbered attribute here | ||
| 2455 | */ | ||
| 2456 | enum nl80211_tid_stats { | ||
| 2457 | __NL80211_TID_STATS_INVALID, | ||
| 2458 | NL80211_TID_STATS_RX_MSDU, | ||
| 2459 | NL80211_TID_STATS_TX_MSDU, | ||
| 2460 | NL80211_TID_STATS_TX_MSDU_RETRIES, | ||
| 2461 | NL80211_TID_STATS_TX_MSDU_FAILED, | ||
| 2462 | |||
| 2463 | /* keep last */ | ||
| 2464 | NUM_NL80211_TID_STATS, | ||
| 2465 | NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1 | ||
| 2466 | }; | ||
| 2467 | |||
| 2468 | /** | ||
| 2362 | * enum nl80211_mpath_flags - nl80211 mesh path flags | 2469 | * enum nl80211_mpath_flags - nl80211 mesh path flags |
| 2363 | * | 2470 | * |
| 2364 | * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active | 2471 | * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active |
| @@ -2772,16 +2879,18 @@ enum nl80211_user_reg_hint_type { | |||
| 2772 | * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel | 2879 | * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel |
| 2773 | * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) | 2880 | * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) |
| 2774 | * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used | 2881 | * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used |
| 2775 | * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio | 2882 | * @NL80211_SURVEY_INFO_TIME: amount of time (in ms) that the radio |
| 2776 | * spent on this channel | 2883 | * was turned on (on channel or globally) |
| 2777 | * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary | 2884 | * @NL80211_SURVEY_INFO_TIME_BUSY: amount of the time the primary |
| 2778 | * channel was sensed busy (either due to activity or energy detect) | 2885 | * channel was sensed busy (either due to activity or energy detect) |
| 2779 | * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension | 2886 | * @NL80211_SURVEY_INFO_TIME_EXT_BUSY: amount of time the extension |
| 2780 | * channel was sensed busy | 2887 | * channel was sensed busy |
| 2781 | * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent | 2888 | * @NL80211_SURVEY_INFO_TIME_RX: amount of time the radio spent |
| 2782 | * receiving data | 2889 | * receiving data (on channel or globally) |
| 2783 | * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent | 2890 | * @NL80211_SURVEY_INFO_TIME_TX: amount of time the radio spent |
| 2784 | * transmitting data | 2891 | * transmitting data (on channel or globally) |
| 2892 | * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan | ||
| 2893 | * (on this channel or globally) | ||
| 2785 | * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number | 2894 | * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number |
| 2786 | * currently defined | 2895 | * currently defined |
| 2787 | * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use | 2896 | * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use |
| @@ -2791,17 +2900,25 @@ enum nl80211_survey_info { | |||
| 2791 | NL80211_SURVEY_INFO_FREQUENCY, | 2900 | NL80211_SURVEY_INFO_FREQUENCY, |
| 2792 | NL80211_SURVEY_INFO_NOISE, | 2901 | NL80211_SURVEY_INFO_NOISE, |
| 2793 | NL80211_SURVEY_INFO_IN_USE, | 2902 | NL80211_SURVEY_INFO_IN_USE, |
| 2794 | NL80211_SURVEY_INFO_CHANNEL_TIME, | 2903 | NL80211_SURVEY_INFO_TIME, |
| 2795 | NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, | 2904 | NL80211_SURVEY_INFO_TIME_BUSY, |
| 2796 | NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, | 2905 | NL80211_SURVEY_INFO_TIME_EXT_BUSY, |
| 2797 | NL80211_SURVEY_INFO_CHANNEL_TIME_RX, | 2906 | NL80211_SURVEY_INFO_TIME_RX, |
| 2798 | NL80211_SURVEY_INFO_CHANNEL_TIME_TX, | 2907 | NL80211_SURVEY_INFO_TIME_TX, |
| 2908 | NL80211_SURVEY_INFO_TIME_SCAN, | ||
| 2799 | 2909 | ||
| 2800 | /* keep last */ | 2910 | /* keep last */ |
| 2801 | __NL80211_SURVEY_INFO_AFTER_LAST, | 2911 | __NL80211_SURVEY_INFO_AFTER_LAST, |
| 2802 | NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 | 2912 | NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 |
| 2803 | }; | 2913 | }; |
| 2804 | 2914 | ||
| 2915 | /* keep old names for compatibility */ | ||
| 2916 | #define NL80211_SURVEY_INFO_CHANNEL_TIME NL80211_SURVEY_INFO_TIME | ||
| 2917 | #define NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY NL80211_SURVEY_INFO_TIME_BUSY | ||
| 2918 | #define NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY NL80211_SURVEY_INFO_TIME_EXT_BUSY | ||
| 2919 | #define NL80211_SURVEY_INFO_CHANNEL_TIME_RX NL80211_SURVEY_INFO_TIME_RX | ||
| 2920 | #define NL80211_SURVEY_INFO_CHANNEL_TIME_TX NL80211_SURVEY_INFO_TIME_TX | ||
| 2921 | |||
| 2805 | /** | 2922 | /** |
| 2806 | * enum nl80211_mntr_flags - monitor configuration flags | 2923 | * enum nl80211_mntr_flags - monitor configuration flags |
| 2807 | * | 2924 | * |
| @@ -3238,6 +3355,9 @@ enum nl80211_bss { | |||
| 3238 | /** | 3355 | /** |
| 3239 | * enum nl80211_bss_status - BSS "status" | 3356 | * enum nl80211_bss_status - BSS "status" |
| 3240 | * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. | 3357 | * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. |
| 3358 | * Note that this is no longer used since cfg80211 no longer | ||
| 3359 | * keeps track of whether or not authentication was done with | ||
| 3360 | * a given BSS. | ||
| 3241 | * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. | 3361 | * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. |
| 3242 | * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. | 3362 | * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. |
| 3243 | * | 3363 | * |
| @@ -3623,7 +3743,9 @@ struct nl80211_pattern_support { | |||
| 3623 | * same attributes used with @NL80211_CMD_START_SCHED_SCAN. It | 3743 | * same attributes used with @NL80211_CMD_START_SCHED_SCAN. It |
| 3624 | * specifies how the scan is performed (e.g. the interval and the | 3744 | * specifies how the scan is performed (e.g. the interval and the |
| 3625 | * channels to scan) as well as the scan results that will | 3745 | * channels to scan) as well as the scan results that will |
| 3626 | * trigger a wake (i.e. the matchsets). | 3746 | * trigger a wake (i.e. the matchsets). This attribute is also |
| 3747 | * sent in a response to @NL80211_CMD_GET_WIPHY, indicating the | ||
| 3748 | * number of match sets supported by the driver (u32). | ||
| 3627 | * @NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS: nested attribute | 3749 | * @NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS: nested attribute |
| 3628 | * containing an array with information about what triggered the | 3750 | * containing an array with information about what triggered the |
| 3629 | * wake up. If no elements are present in the array, it means | 3751 | * wake up. If no elements are present in the array, it means |
| @@ -4194,6 +4316,19 @@ enum nl80211_feature_flags { | |||
| 4194 | }; | 4316 | }; |
| 4195 | 4317 | ||
| 4196 | /** | 4318 | /** |
| 4319 | * enum nl80211_ext_feature_index - bit index of extended features. | ||
| 4320 | * | ||
| 4321 | * @NUM_NL80211_EXT_FEATURES: number of extended features. | ||
| 4322 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. | ||
| 4323 | */ | ||
| 4324 | enum nl80211_ext_feature_index { | ||
| 4325 | |||
| 4326 | /* add new features before the definition below */ | ||
| 4327 | NUM_NL80211_EXT_FEATURES, | ||
| 4328 | MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1 | ||
| 4329 | }; | ||
| 4330 | |||
| 4331 | /** | ||
| 4197 | * enum nl80211_probe_resp_offload_support_attr - optional supported | 4332 | * enum nl80211_probe_resp_offload_support_attr - optional supported |
| 4198 | * protocols for probe-response offloading by the driver/FW. | 4333 | * protocols for probe-response offloading by the driver/FW. |
| 4199 | * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute. | 4334 | * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute. |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e75d5c53e97b..ff090ef1ea2c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -428,11 +428,13 @@ void sta_set_rate_info_tx(struct sta_info *sta, | |||
| 428 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | 428 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); |
| 429 | } | 429 | } |
| 430 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 430 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) |
| 431 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 431 | rinfo->bw = RATE_INFO_BW_40; |
| 432 | if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) | 432 | else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) |
| 433 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 433 | rinfo->bw = RATE_INFO_BW_80; |
| 434 | if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) | 434 | else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) |
| 435 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 435 | rinfo->bw = RATE_INFO_BW_160; |
| 436 | else | ||
| 437 | rinfo->bw = RATE_INFO_BW_20; | ||
| 436 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | 438 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) |
| 437 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 439 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 438 | } | 440 | } |
| @@ -459,16 +461,21 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | |||
| 459 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | 461 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); |
| 460 | } | 462 | } |
| 461 | 463 | ||
| 462 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | ||
| 463 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
| 464 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | 464 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) |
| 465 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 465 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 466 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) | 466 | |
| 467 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 467 | if (sta->last_rx_rate_flag & RX_FLAG_5MHZ) |
| 468 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80P80MHZ) | 468 | rinfo->bw = RATE_INFO_BW_5; |
| 469 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 469 | else if (sta->last_rx_rate_flag & RX_FLAG_10MHZ) |
| 470 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) | 470 | rinfo->bw = RATE_INFO_BW_10; |
| 471 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 471 | else if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) |
| 472 | rinfo->bw = RATE_INFO_BW_40; | ||
| 473 | else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) | ||
| 474 | rinfo->bw = RATE_INFO_BW_80; | ||
| 475 | else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) | ||
| 476 | rinfo->bw = RATE_INFO_BW_160; | ||
| 477 | else | ||
| 478 | rinfo->bw = RATE_INFO_BW_20; | ||
| 472 | } | 479 | } |
| 473 | 480 | ||
| 474 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 481 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, |
| @@ -678,7 +685,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
| 678 | BSS_CHANGED_BEACON_ENABLED | | 685 | BSS_CHANGED_BEACON_ENABLED | |
| 679 | BSS_CHANGED_BEACON | | 686 | BSS_CHANGED_BEACON | |
| 680 | BSS_CHANGED_SSID | | 687 | BSS_CHANGED_SSID | |
| 681 | BSS_CHANGED_P2P_PS; | 688 | BSS_CHANGED_P2P_PS | |
| 689 | BSS_CHANGED_TXPOWER; | ||
| 682 | int err; | 690 | int err; |
| 683 | 691 | ||
| 684 | old = sdata_dereference(sdata->u.ap.beacon, sdata); | 692 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
| @@ -2556,7 +2564,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
| 2556 | 2564 | ||
| 2557 | /* if there's one pending or we're scanning, queue this one */ | 2565 | /* if there's one pending or we're scanning, queue this one */ |
| 2558 | if (!list_empty(&local->roc_list) || | 2566 | if (!list_empty(&local->roc_list) || |
| 2559 | local->scanning || local->radar_detect_enabled) | 2567 | local->scanning || ieee80211_is_radar_required(local)) |
| 2560 | goto out_check_combine; | 2568 | goto out_check_combine; |
| 2561 | 2569 | ||
| 2562 | /* if not HW assist, just queue & schedule work */ | 2570 | /* if not HW assist, just queue & schedule work */ |
| @@ -3664,7 +3672,7 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev, | |||
| 3664 | * queues. | 3672 | * queues. |
| 3665 | */ | 3673 | */ |
| 3666 | synchronize_net(); | 3674 | synchronize_net(); |
| 3667 | ieee80211_flush_queues(local, sdata); | 3675 | ieee80211_flush_queues(local, sdata, false); |
| 3668 | 3676 | ||
| 3669 | /* restore the normal QoS parameters | 3677 | /* restore the normal QoS parameters |
| 3670 | * (unconditionally to avoid races) | 3678 | * (unconditionally to avoid races) |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index da1c12c34487..35b11e11e0c4 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -388,7 +388,7 @@ ieee80211_find_chanctx(struct ieee80211_local *local, | |||
| 388 | return NULL; | 388 | return NULL; |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | static bool ieee80211_is_radar_required(struct ieee80211_local *local) | 391 | bool ieee80211_is_radar_required(struct ieee80211_local *local) |
| 392 | { | 392 | { |
| 393 | struct ieee80211_sub_if_data *sdata; | 393 | struct ieee80211_sub_if_data *sdata; |
| 394 | 394 | ||
| @@ -406,6 +406,34 @@ static bool ieee80211_is_radar_required(struct ieee80211_local *local) | |||
| 406 | return false; | 406 | return false; |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | static bool | ||
| 410 | ieee80211_chanctx_radar_required(struct ieee80211_local *local, | ||
| 411 | struct ieee80211_chanctx *ctx) | ||
| 412 | { | ||
| 413 | struct ieee80211_chanctx_conf *conf = &ctx->conf; | ||
| 414 | struct ieee80211_sub_if_data *sdata; | ||
| 415 | bool required = false; | ||
| 416 | |||
| 417 | lockdep_assert_held(&local->chanctx_mtx); | ||
| 418 | lockdep_assert_held(&local->mtx); | ||
| 419 | |||
| 420 | rcu_read_lock(); | ||
| 421 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
| 422 | if (!ieee80211_sdata_running(sdata)) | ||
| 423 | continue; | ||
| 424 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) | ||
| 425 | continue; | ||
| 426 | if (!sdata->radar_required) | ||
| 427 | continue; | ||
| 428 | |||
| 429 | required = true; | ||
| 430 | break; | ||
| 431 | } | ||
| 432 | rcu_read_unlock(); | ||
| 433 | |||
| 434 | return required; | ||
| 435 | } | ||
| 436 | |||
| 409 | static struct ieee80211_chanctx * | 437 | static struct ieee80211_chanctx * |
| 410 | ieee80211_alloc_chanctx(struct ieee80211_local *local, | 438 | ieee80211_alloc_chanctx(struct ieee80211_local *local, |
| 411 | const struct cfg80211_chan_def *chandef, | 439 | const struct cfg80211_chan_def *chandef, |
| @@ -425,7 +453,7 @@ ieee80211_alloc_chanctx(struct ieee80211_local *local, | |||
| 425 | ctx->conf.rx_chains_static = 1; | 453 | ctx->conf.rx_chains_static = 1; |
| 426 | ctx->conf.rx_chains_dynamic = 1; | 454 | ctx->conf.rx_chains_dynamic = 1; |
| 427 | ctx->mode = mode; | 455 | ctx->mode = mode; |
| 428 | ctx->conf.radar_enabled = ieee80211_is_radar_required(local); | 456 | ctx->conf.radar_enabled = false; |
| 429 | ieee80211_recalc_chanctx_min_def(local, ctx); | 457 | ieee80211_recalc_chanctx_min_def(local, ctx); |
| 430 | 458 | ||
| 431 | return ctx; | 459 | return ctx; |
| @@ -567,16 +595,15 @@ static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, | |||
| 567 | bool radar_enabled; | 595 | bool radar_enabled; |
| 568 | 596 | ||
| 569 | lockdep_assert_held(&local->chanctx_mtx); | 597 | lockdep_assert_held(&local->chanctx_mtx); |
| 570 | /* for setting local->radar_detect_enabled */ | 598 | /* for ieee80211_is_radar_required */ |
| 571 | lockdep_assert_held(&local->mtx); | 599 | lockdep_assert_held(&local->mtx); |
| 572 | 600 | ||
| 573 | radar_enabled = ieee80211_is_radar_required(local); | 601 | radar_enabled = ieee80211_chanctx_radar_required(local, chanctx); |
| 574 | 602 | ||
| 575 | if (radar_enabled == chanctx->conf.radar_enabled) | 603 | if (radar_enabled == chanctx->conf.radar_enabled) |
| 576 | return; | 604 | return; |
| 577 | 605 | ||
| 578 | chanctx->conf.radar_enabled = radar_enabled; | 606 | chanctx->conf.radar_enabled = radar_enabled; |
| 579 | local->radar_detect_enabled = chanctx->conf.radar_enabled; | ||
| 580 | 607 | ||
| 581 | if (!local->use_chanctx) { | 608 | if (!local->use_chanctx) { |
| 582 | local->hw.conf.radar_enabled = chanctx->conf.radar_enabled; | 609 | local->hw.conf.radar_enabled = chanctx->conf.radar_enabled; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 54a189f0393e..eeb0bbd69d98 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
| @@ -303,8 +303,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
| 303 | sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); | 303 | sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); |
| 304 | if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) | 304 | if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) |
| 305 | sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); | 305 | sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); |
| 306 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | ||
| 307 | sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); | ||
| 308 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 306 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
| 309 | sf += scnprintf(buf + sf, mxln - sf, | 307 | sf += scnprintf(buf + sf, mxln - sf, |
| 310 | "REPORTS_TX_ACK_STATUS\n"); | 308 | "REPORTS_TX_ACK_STATUS\n"); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 2ebc9ead9695..fdeda17b8dd2 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
| @@ -639,6 +639,21 @@ static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local, | |||
| 639 | trace_drv_return_void(local); | 639 | trace_drv_return_void(local); |
| 640 | } | 640 | } |
| 641 | 641 | ||
| 642 | static inline void drv_sta_statistics(struct ieee80211_local *local, | ||
| 643 | struct ieee80211_sub_if_data *sdata, | ||
| 644 | struct ieee80211_sta *sta, | ||
| 645 | struct station_info *sinfo) | ||
| 646 | { | ||
| 647 | sdata = get_bss_sdata(sdata); | ||
| 648 | if (!check_sdata_in_driver(sdata)) | ||
| 649 | return; | ||
| 650 | |||
| 651 | trace_drv_sta_statistics(local, sdata, sta); | ||
| 652 | if (local->ops->sta_statistics) | ||
| 653 | local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo); | ||
| 654 | trace_drv_return_void(local); | ||
| 655 | } | ||
| 656 | |||
| 642 | static inline int drv_conf_tx(struct ieee80211_local *local, | 657 | static inline int drv_conf_tx(struct ieee80211_local *local, |
| 643 | struct ieee80211_sub_if_data *sdata, u16 ac, | 658 | struct ieee80211_sub_if_data *sdata, u16 ac, |
| 644 | const struct ieee80211_tx_queue_params *params) | 659 | const struct ieee80211_tx_queue_params *params) |
| @@ -966,21 +981,6 @@ drv_allow_buffered_frames(struct ieee80211_local *local, | |||
| 966 | trace_drv_return_void(local); | 981 | trace_drv_return_void(local); |
| 967 | } | 982 | } |
| 968 | 983 | ||
| 969 | static inline int drv_get_rssi(struct ieee80211_local *local, | ||
| 970 | struct ieee80211_sub_if_data *sdata, | ||
| 971 | struct ieee80211_sta *sta, | ||
| 972 | s8 *rssi_dbm) | ||
| 973 | { | ||
| 974 | int ret; | ||
| 975 | |||
| 976 | might_sleep(); | ||
| 977 | |||
| 978 | ret = local->ops->get_rssi(&local->hw, &sdata->vif, sta, rssi_dbm); | ||
| 979 | trace_drv_get_rssi(local, sta, *rssi_dbm, ret); | ||
| 980 | |||
| 981 | return ret; | ||
| 982 | } | ||
| 983 | |||
| 984 | static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, | 984 | static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, |
| 985 | struct ieee80211_sub_if_data *sdata) | 985 | struct ieee80211_sub_if_data *sdata) |
| 986 | { | 986 | { |
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c index ebfc8091557b..52bcea6ad9e8 100644 --- a/net/mac80211/ethtool.c +++ b/net/mac80211/ethtool.c | |||
| @@ -117,16 +117,16 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
| 117 | data[i++] = sta->sta_state; | 117 | data[i++] = sta->sta_state; |
| 118 | 118 | ||
| 119 | 119 | ||
| 120 | if (sinfo.filled & STATION_INFO_TX_BITRATE) | 120 | if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) |
| 121 | data[i] = 100000 * | 121 | data[i] = 100000 * |
| 122 | cfg80211_calculate_bitrate(&sinfo.txrate); | 122 | cfg80211_calculate_bitrate(&sinfo.txrate); |
| 123 | i++; | 123 | i++; |
| 124 | if (sinfo.filled & STATION_INFO_RX_BITRATE) | 124 | if (sinfo.filled & BIT(NL80211_STA_INFO_RX_BITRATE)) |
| 125 | data[i] = 100000 * | 125 | data[i] = 100000 * |
| 126 | cfg80211_calculate_bitrate(&sinfo.rxrate); | 126 | cfg80211_calculate_bitrate(&sinfo.rxrate); |
| 127 | i++; | 127 | i++; |
| 128 | 128 | ||
| 129 | if (sinfo.filled & STATION_INFO_SIGNAL_AVG) | 129 | if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL_AVG)) |
| 130 | data[i] = (u8)sinfo.signal_avg; | 130 | data[i] = (u8)sinfo.signal_avg; |
| 131 | i++; | 131 | i++; |
| 132 | } else { | 132 | } else { |
| @@ -175,24 +175,24 @@ do_survey: | |||
| 175 | data[i++] = (u8)survey.noise; | 175 | data[i++] = (u8)survey.noise; |
| 176 | else | 176 | else |
| 177 | data[i++] = -1LL; | 177 | data[i++] = -1LL; |
| 178 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME) | 178 | if (survey.filled & SURVEY_INFO_TIME) |
| 179 | data[i++] = survey.channel_time; | 179 | data[i++] = survey.time; |
| 180 | else | 180 | else |
| 181 | data[i++] = -1LL; | 181 | data[i++] = -1LL; |
| 182 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY) | 182 | if (survey.filled & SURVEY_INFO_TIME_BUSY) |
| 183 | data[i++] = survey.channel_time_busy; | 183 | data[i++] = survey.time_busy; |
| 184 | else | 184 | else |
| 185 | data[i++] = -1LL; | 185 | data[i++] = -1LL; |
| 186 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) | 186 | if (survey.filled & SURVEY_INFO_TIME_EXT_BUSY) |
| 187 | data[i++] = survey.channel_time_ext_busy; | 187 | data[i++] = survey.time_ext_busy; |
| 188 | else | 188 | else |
| 189 | data[i++] = -1LL; | 189 | data[i++] = -1LL; |
| 190 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX) | 190 | if (survey.filled & SURVEY_INFO_TIME_RX) |
| 191 | data[i++] = survey.channel_time_rx; | 191 | data[i++] = survey.time_rx; |
| 192 | else | 192 | else |
| 193 | data[i++] = -1LL; | 193 | data[i++] = -1LL; |
| 194 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX) | 194 | if (survey.filled & SURVEY_INFO_TIME_TX) |
| 195 | data[i++] = survey.channel_time_tx; | 195 | data[i++] = survey.time_tx; |
| 196 | else | 196 | else |
| 197 | data[i++] = -1LL; | 197 | data[i++] = -1LL; |
| 198 | 198 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 509bc157ce55..b606b53a49a7 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -1069,9 +1069,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
| 1069 | } | 1069 | } |
| 1070 | 1070 | ||
| 1071 | if (sta && rates_updated) { | 1071 | if (sta && rates_updated) { |
| 1072 | drv_sta_rc_update(local, sdata, &sta->sta, | 1072 | u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED; |
| 1073 | IEEE80211_RC_SUPP_RATES_CHANGED); | 1073 | u8 rx_nss = sta->sta.rx_nss; |
| 1074 | |||
| 1075 | /* Force rx_nss recalculation */ | ||
| 1076 | sta->sta.rx_nss = 0; | ||
| 1074 | rate_control_rate_init(sta); | 1077 | rate_control_rate_init(sta); |
| 1078 | if (sta->sta.rx_nss != rx_nss) | ||
| 1079 | changed |= IEEE80211_RC_NSS_CHANGED; | ||
| 1080 | |||
| 1081 | drv_sta_rc_update(local, sdata, &sta->sta, changed); | ||
| 1075 | } | 1082 | } |
| 1076 | 1083 | ||
| 1077 | rcu_read_unlock(); | 1084 | rcu_read_unlock(); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index cc6e964d9837..156ea79e0157 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -1168,8 +1168,6 @@ struct ieee80211_local { | |||
| 1168 | /* wowlan is enabled -- don't reconfig on resume */ | 1168 | /* wowlan is enabled -- don't reconfig on resume */ |
| 1169 | bool wowlan; | 1169 | bool wowlan; |
| 1170 | 1170 | ||
| 1171 | /* DFS/radar detection is enabled */ | ||
| 1172 | bool radar_detect_enabled; | ||
| 1173 | struct work_struct radar_detected_work; | 1171 | struct work_struct radar_detected_work; |
| 1174 | 1172 | ||
| 1175 | /* number of RX chains the hardware has */ | 1173 | /* number of RX chains the hardware has */ |
| @@ -1704,6 +1702,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
| 1704 | struct ieee80211_supported_band *sband, | 1702 | struct ieee80211_supported_band *sband, |
| 1705 | const struct ieee80211_vht_cap *vht_cap_ie, | 1703 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 1706 | struct sta_info *sta); | 1704 | struct sta_info *sta); |
| 1705 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta); | ||
| 1707 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); | 1706 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); |
| 1708 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); | 1707 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); |
| 1709 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1708 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
| @@ -1881,10 +1880,10 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
| 1881 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, | 1880 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, |
| 1882 | struct sk_buff_head *skbs); | 1881 | struct sk_buff_head *skbs); |
| 1883 | void ieee80211_flush_queues(struct ieee80211_local *local, | 1882 | void ieee80211_flush_queues(struct ieee80211_local *local, |
| 1884 | struct ieee80211_sub_if_data *sdata); | 1883 | struct ieee80211_sub_if_data *sdata, bool drop); |
| 1885 | void __ieee80211_flush_queues(struct ieee80211_local *local, | 1884 | void __ieee80211_flush_queues(struct ieee80211_local *local, |
| 1886 | struct ieee80211_sub_if_data *sdata, | 1885 | struct ieee80211_sub_if_data *sdata, |
| 1887 | unsigned int queues); | 1886 | unsigned int queues, bool drop); |
| 1888 | 1887 | ||
| 1889 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1888 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
| 1890 | u16 transaction, u16 auth_alg, u16 status, | 1889 | u16 transaction, u16 auth_alg, u16 status, |
| @@ -1981,6 +1980,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | |||
| 1981 | struct ieee80211_chanctx *chanctx); | 1980 | struct ieee80211_chanctx *chanctx); |
| 1982 | void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, | 1981 | void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, |
| 1983 | struct ieee80211_chanctx *ctx); | 1982 | struct ieee80211_chanctx *ctx); |
| 1983 | bool ieee80211_is_radar_required(struct ieee80211_local *local); | ||
| 1984 | 1984 | ||
| 1985 | void ieee80211_dfs_cac_timer(unsigned long data); | 1985 | void ieee80211_dfs_cac_timer(unsigned long data); |
| 1986 | void ieee80211_dfs_cac_timer_work(struct work_struct *work); | 1986 | void ieee80211_dfs_cac_timer_work(struct work_struct *work); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 417355390873..677422e11e07 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -93,7 +93,7 @@ static u32 __ieee80211_idle_on(struct ieee80211_local *local) | |||
| 93 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | 93 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) |
| 94 | return 0; | 94 | return 0; |
| 95 | 95 | ||
| 96 | ieee80211_flush_queues(local, NULL); | 96 | ieee80211_flush_queues(local, NULL, false); |
| 97 | 97 | ||
| 98 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 98 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
| 99 | return IEEE80211_CONF_CHANGE_IDLE; | 99 | return IEEE80211_CONF_CHANGE_IDLE; |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 0bb7038121ac..f8d9f0ee59bf 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
| @@ -140,7 +140,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
| 140 | if (!ret) { | 140 | if (!ret) { |
| 141 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 141 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
| 142 | 142 | ||
| 143 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) | 143 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
| 144 | (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) | ||
| 144 | sdata->crypto_tx_tailroom_needed_cnt--; | 145 | sdata->crypto_tx_tailroom_needed_cnt--; |
| 145 | 146 | ||
| 146 | WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && | 147 | WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && |
| @@ -188,7 +189,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
| 188 | sta = key->sta; | 189 | sta = key->sta; |
| 189 | sdata = key->sdata; | 190 | sdata = key->sdata; |
| 190 | 191 | ||
| 191 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) | 192 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
| 193 | (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) | ||
| 192 | increment_tailroom_need_count(sdata); | 194 | increment_tailroom_need_count(sdata); |
| 193 | 195 | ||
| 194 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, | 196 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, |
| @@ -884,7 +886,8 @@ void ieee80211_remove_key(struct ieee80211_key_conf *keyconf) | |||
| 884 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 886 | if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
| 885 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 887 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
| 886 | 888 | ||
| 887 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) | 889 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
| 890 | (key->conf.flags & IEEE80211_KEY_FLAG_RESERVE_TAILROOM))) | ||
| 888 | increment_tailroom_need_count(key->sdata); | 891 | increment_tailroom_need_count(key->sdata); |
| 889 | } | 892 | } |
| 890 | 893 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6ab99da38db9..d9ce33663c73 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -916,10 +916,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 916 | } | 916 | } |
| 917 | } | 917 | } |
| 918 | 918 | ||
| 919 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | ||
| 920 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | ||
| 921 | "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"); | ||
| 922 | |||
| 923 | /* | 919 | /* |
| 924 | * Calculate scan IE length -- we need this to alloc | 920 | * Calculate scan IE length -- we need this to alloc |
| 925 | * memory and to subtract from the driver limit. It | 921 | * memory and to subtract from the driver limit. It |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index b488e1859b18..fa94ca15ba95 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
| @@ -523,6 +523,13 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | |||
| 523 | sdata->u.mesh.mshcfg.auto_open_plinks && | 523 | sdata->u.mesh.mshcfg.auto_open_plinks && |
| 524 | rssi_threshold_check(sdata, sta)) | 524 | rssi_threshold_check(sdata, sta)) |
| 525 | changed = mesh_plink_open(sta); | 525 | changed = mesh_plink_open(sta); |
| 526 | else if (sta->plink_state == NL80211_PLINK_LISTEN && | ||
| 527 | (sdata->u.mesh.user_mpm || | ||
| 528 | sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)) | ||
| 529 | cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, | ||
| 530 | elems->ie_start, | ||
| 531 | elems->total_len, | ||
| 532 | GFP_ATOMIC); | ||
| 526 | 533 | ||
| 527 | ieee80211_mps_frame_release(sta, elems); | 534 | ieee80211_mps_frame_release(sta, elems); |
| 528 | out: | 535 | out: |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2c36c4765f47..1875181ebd94 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -157,14 +157,18 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 157 | { | 157 | { |
| 158 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 158 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 159 | struct cfg80211_chan_def vht_chandef; | 159 | struct cfg80211_chan_def vht_chandef; |
| 160 | struct ieee80211_sta_ht_cap sta_ht_cap; | ||
| 160 | u32 ht_cfreq, ret; | 161 | u32 ht_cfreq, ret; |
| 161 | 162 | ||
| 163 | memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); | ||
| 164 | ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); | ||
| 165 | |||
| 162 | chandef->chan = channel; | 166 | chandef->chan = channel; |
| 163 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; | 167 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; |
| 164 | chandef->center_freq1 = channel->center_freq; | 168 | chandef->center_freq1 = channel->center_freq; |
| 165 | chandef->center_freq2 = 0; | 169 | chandef->center_freq2 = 0; |
| 166 | 170 | ||
| 167 | if (!ht_cap || !ht_oper || !sband->ht_cap.ht_supported) { | 171 | if (!ht_cap || !ht_oper || !sta_ht_cap.ht_supported) { |
| 168 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | 172 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; |
| 169 | goto out; | 173 | goto out; |
| 170 | } | 174 | } |
| @@ -198,7 +202,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
| 198 | } | 202 | } |
| 199 | 203 | ||
| 200 | /* check 40 MHz support, if we have it */ | 204 | /* check 40 MHz support, if we have it */ |
| 201 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | 205 | if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { |
| 202 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 206 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
| 203 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 207 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
| 204 | chandef->width = NL80211_CHAN_WIDTH_40; | 208 | chandef->width = NL80211_CHAN_WIDTH_40; |
| @@ -1054,8 +1058,6 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata) | |||
| 1054 | sdata->csa_block_tx = false; | 1058 | sdata->csa_block_tx = false; |
| 1055 | } | 1059 | } |
| 1056 | 1060 | ||
| 1057 | cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef); | ||
| 1058 | |||
| 1059 | sdata->vif.csa_active = false; | 1061 | sdata->vif.csa_active = false; |
| 1060 | ifmgd->csa_waiting_bcn = false; | 1062 | ifmgd->csa_waiting_bcn = false; |
| 1061 | 1063 | ||
| @@ -1067,6 +1069,8 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata) | |||
| 1067 | &ifmgd->csa_connection_drop_work); | 1069 | &ifmgd->csa_connection_drop_work); |
| 1068 | return; | 1070 | return; |
| 1069 | } | 1071 | } |
| 1072 | |||
| 1073 | cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef); | ||
| 1070 | } | 1074 | } |
| 1071 | 1075 | ||
| 1072 | void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) | 1076 | void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) |
| @@ -1284,8 +1288,11 @@ ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
| 1284 | country_ie_len -= 3; | 1288 | country_ie_len -= 3; |
| 1285 | } | 1289 | } |
| 1286 | 1290 | ||
| 1287 | if (have_chan_pwr) | 1291 | if (have_chan_pwr && pwr_constr_elem) |
| 1288 | *pwr_reduction = *pwr_constr_elem; | 1292 | *pwr_reduction = *pwr_constr_elem; |
| 1293 | else | ||
| 1294 | *pwr_reduction = 0; | ||
| 1295 | |||
| 1289 | return have_chan_pwr; | 1296 | return have_chan_pwr; |
| 1290 | } | 1297 | } |
| 1291 | 1298 | ||
| @@ -1314,10 +1321,11 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
| 1314 | int chan_pwr = 0, pwr_reduction_80211h = 0; | 1321 | int chan_pwr = 0, pwr_reduction_80211h = 0; |
| 1315 | int pwr_level_cisco, pwr_level_80211h; | 1322 | int pwr_level_cisco, pwr_level_80211h; |
| 1316 | int new_ap_level; | 1323 | int new_ap_level; |
| 1324 | __le16 capab = mgmt->u.probe_resp.capab_info; | ||
| 1317 | 1325 | ||
| 1318 | if (country_ie && pwr_constr_ie && | 1326 | if (country_ie && |
| 1319 | mgmt->u.probe_resp.capab_info & | 1327 | (capab & cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT) || |
| 1320 | cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) { | 1328 | capab & cpu_to_le16(WLAN_CAPABILITY_RADIO_MEASURE))) { |
| 1321 | has_80211h_pwr = ieee80211_find_80211h_pwr_constr( | 1329 | has_80211h_pwr = ieee80211_find_80211h_pwr_constr( |
| 1322 | sdata, channel, country_ie, country_ie_len, | 1330 | sdata, channel, country_ie, country_ie_len, |
| 1323 | pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h); | 1331 | pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h); |
| @@ -1596,7 +1604,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
| 1596 | } else { | 1604 | } else { |
| 1597 | ieee80211_send_nullfunc(local, sdata, 1); | 1605 | ieee80211_send_nullfunc(local, sdata, 1); |
| 1598 | /* Flush to get the tx status of nullfunc frame */ | 1606 | /* Flush to get the tx status of nullfunc frame */ |
| 1599 | ieee80211_flush_queues(local, sdata); | 1607 | ieee80211_flush_queues(local, sdata, false); |
| 1600 | } | 1608 | } |
| 1601 | } | 1609 | } |
| 1602 | 1610 | ||
| @@ -2003,18 +2011,23 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
| 2003 | /* disable per-vif ps */ | 2011 | /* disable per-vif ps */ |
| 2004 | ieee80211_recalc_ps_vif(sdata); | 2012 | ieee80211_recalc_ps_vif(sdata); |
| 2005 | 2013 | ||
| 2006 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | 2014 | /* |
| 2015 | * drop any frame before deauth/disassoc, this can be data or | ||
| 2016 | * management frame. Since we are disconnecting, we should not | ||
| 2017 | * insist sending these frames which can take time and delay | ||
| 2018 | * the disconnection and possible the roaming. | ||
| 2019 | */ | ||
| 2007 | if (tx) | 2020 | if (tx) |
| 2008 | ieee80211_flush_queues(local, sdata); | 2021 | ieee80211_flush_queues(local, sdata, true); |
| 2009 | 2022 | ||
| 2010 | /* deauthenticate/disassociate now */ | 2023 | /* deauthenticate/disassociate now */ |
| 2011 | if (tx || frame_buf) | 2024 | if (tx || frame_buf) |
| 2012 | ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, | 2025 | ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, |
| 2013 | reason, tx, frame_buf); | 2026 | reason, tx, frame_buf); |
| 2014 | 2027 | ||
| 2015 | /* flush out frame */ | 2028 | /* flush out frame - make sure the deauth was actually sent */ |
| 2016 | if (tx) | 2029 | if (tx) |
| 2017 | ieee80211_flush_queues(local, sdata); | 2030 | ieee80211_flush_queues(local, sdata, false); |
| 2018 | 2031 | ||
| 2019 | /* clear bssid only after building the needed mgmt frames */ | 2032 | /* clear bssid only after building the needed mgmt frames */ |
| 2020 | memset(ifmgd->bssid, 0, ETH_ALEN); | 2033 | memset(ifmgd->bssid, 0, ETH_ALEN); |
| @@ -2440,6 +2453,12 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
| 2440 | sdata_assert_lock(sdata); | 2453 | sdata_assert_lock(sdata); |
| 2441 | 2454 | ||
| 2442 | if (!assoc) { | 2455 | if (!assoc) { |
| 2456 | /* | ||
| 2457 | * we are not authenticated yet, the only timer that could be | ||
| 2458 | * running is the timeout for the authentication response which | ||
| 2459 | * which is not relevant anymore. | ||
| 2460 | */ | ||
| 2461 | del_timer_sync(&sdata->u.mgd.timer); | ||
| 2443 | sta_info_destroy_addr(sdata, auth_data->bss->bssid); | 2462 | sta_info_destroy_addr(sdata, auth_data->bss->bssid); |
| 2444 | 2463 | ||
| 2445 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 2464 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
| @@ -2747,6 +2766,12 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, | |||
| 2747 | sdata_assert_lock(sdata); | 2766 | sdata_assert_lock(sdata); |
| 2748 | 2767 | ||
| 2749 | if (!assoc) { | 2768 | if (!assoc) { |
| 2769 | /* | ||
| 2770 | * we are not associated yet, the only timer that could be | ||
| 2771 | * running is the timeout for the association response which | ||
| 2772 | * which is not relevant anymore. | ||
| 2773 | */ | ||
| 2774 | del_timer_sync(&sdata->u.mgd.timer); | ||
| 2750 | sta_info_destroy_addr(sdata, assoc_data->bss->bssid); | 2775 | sta_info_destroy_addr(sdata, assoc_data->bss->bssid); |
| 2751 | 2776 | ||
| 2752 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 2777 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
| @@ -4197,9 +4222,13 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
| 4197 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4222 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 4198 | struct ieee80211_bss *bss = (void *)cbss->priv; | 4223 | struct ieee80211_bss *bss = (void *)cbss->priv; |
| 4199 | struct sta_info *new_sta = NULL; | 4224 | struct sta_info *new_sta = NULL; |
| 4200 | bool have_sta = false; | 4225 | struct ieee80211_supported_band *sband; |
| 4226 | struct ieee80211_sta_ht_cap sta_ht_cap; | ||
| 4227 | bool have_sta = false, is_override = false; | ||
| 4201 | int err; | 4228 | int err; |
| 4202 | 4229 | ||
| 4230 | sband = local->hw.wiphy->bands[cbss->channel->band]; | ||
| 4231 | |||
| 4203 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | 4232 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) |
| 4204 | return -EINVAL; | 4233 | return -EINVAL; |
| 4205 | 4234 | ||
| @@ -4214,25 +4243,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
| 4214 | if (!new_sta) | 4243 | if (!new_sta) |
| 4215 | return -ENOMEM; | 4244 | return -ENOMEM; |
| 4216 | } | 4245 | } |
| 4246 | |||
| 4247 | memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap)); | ||
| 4248 | ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap); | ||
| 4249 | |||
| 4250 | is_override = (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) != | ||
| 4251 | (sband->ht_cap.cap & | ||
| 4252 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
| 4253 | |||
| 4254 | if (new_sta || is_override) { | ||
| 4255 | err = ieee80211_prep_channel(sdata, cbss); | ||
| 4256 | if (err) { | ||
| 4257 | if (new_sta) | ||
| 4258 | sta_info_free(local, new_sta); | ||
| 4259 | return -EINVAL; | ||
| 4260 | } | ||
| 4261 | } | ||
| 4262 | |||
| 4217 | if (new_sta) { | 4263 | if (new_sta) { |
| 4218 | u32 rates = 0, basic_rates = 0; | 4264 | u32 rates = 0, basic_rates = 0; |
| 4219 | bool have_higher_than_11mbit; | 4265 | bool have_higher_than_11mbit; |
| 4220 | int min_rate = INT_MAX, min_rate_index = -1; | 4266 | int min_rate = INT_MAX, min_rate_index = -1; |
| 4221 | struct ieee80211_chanctx_conf *chanctx_conf; | 4267 | struct ieee80211_chanctx_conf *chanctx_conf; |
| 4222 | struct ieee80211_supported_band *sband; | ||
| 4223 | const struct cfg80211_bss_ies *ies; | 4268 | const struct cfg80211_bss_ies *ies; |
| 4224 | int shift; | 4269 | int shift = ieee80211_vif_get_shift(&sdata->vif); |
| 4225 | u32 rate_flags; | 4270 | u32 rate_flags; |
| 4226 | 4271 | ||
| 4227 | sband = local->hw.wiphy->bands[cbss->channel->band]; | ||
| 4228 | |||
| 4229 | err = ieee80211_prep_channel(sdata, cbss); | ||
| 4230 | if (err) { | ||
| 4231 | sta_info_free(local, new_sta); | ||
| 4232 | return -EINVAL; | ||
| 4233 | } | ||
| 4234 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
| 4235 | |||
| 4236 | rcu_read_lock(); | 4272 | rcu_read_lock(); |
| 4237 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 4273 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
| 4238 | if (WARN_ON(!chanctx_conf)) { | 4274 | if (WARN_ON(!chanctx_conf)) { |
| @@ -4668,8 +4704,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 4668 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 4704 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
| 4669 | rcu_read_unlock(); | 4705 | rcu_read_unlock(); |
| 4670 | 4706 | ||
| 4707 | if (WARN((sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD) && | ||
| 4708 | (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | ||
| 4709 | "U-APSD not supported with HW_PS_NULLFUNC_STACK\n")) | ||
| 4710 | sdata->vif.driver_flags &= ~IEEE80211_VIF_SUPPORTS_UAPSD; | ||
| 4711 | |||
| 4671 | if (bss->wmm_used && bss->uapsd_supported && | 4712 | if (bss->wmm_used && bss->uapsd_supported && |
| 4672 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 4713 | (sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_UAPSD)) { |
| 4673 | assoc_data->uapsd = true; | 4714 | assoc_data->uapsd = true; |
| 4674 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; | 4715 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; |
| 4675 | } else { | 4716 | } else { |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index ff20b2ebdb30..683f0e3cb124 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
| @@ -121,7 +121,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) | |||
| 121 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | 121 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, |
| 122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, | 122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, |
| 123 | false); | 123 | false); |
| 124 | ieee80211_flush_queues(local, NULL); | 124 | ieee80211_flush_queues(local, NULL, false); |
| 125 | 125 | ||
| 126 | mutex_lock(&local->iflist_mtx); | 126 | mutex_lock(&local->iflist_mtx); |
| 127 | list_for_each_entry(sdata, &local->interfaces, list) { | 127 | list_for_each_entry(sdata, &local->interfaces, list) { |
| @@ -398,7 +398,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
| 398 | ieee80211_roc_notify_destroy(roc, !roc->abort); | 398 | ieee80211_roc_notify_destroy(roc, !roc->abort); |
| 399 | 399 | ||
| 400 | if (started && !on_channel) { | 400 | if (started && !on_channel) { |
| 401 | ieee80211_flush_queues(local, NULL); | 401 | ieee80211_flush_queues(local, NULL, false); |
| 402 | 402 | ||
| 403 | local->tmp_channel = NULL; | 403 | local->tmp_channel = NULL; |
| 404 | ieee80211_hw_config(local, 0); | 404 | ieee80211_hw_config(local, 0); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 4c5192e0d66c..8c8c67819072 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
| @@ -41,7 +41,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 41 | /* flush out all packets */ | 41 | /* flush out all packets */ |
| 42 | synchronize_net(); | 42 | synchronize_net(); |
| 43 | 43 | ||
| 44 | ieee80211_flush_queues(local, NULL); | 44 | ieee80211_flush_queues(local, NULL, true); |
| 45 | 45 | ||
| 46 | local->quiescing = true; | 46 | local->quiescing = true; |
| 47 | /* make quiescing visible to timers everywhere */ | 47 | /* make quiescing visible to timers everywhere */ |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index d51f6b1c549b..7c86a002df95 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
| @@ -263,12 +263,12 @@ static inline unsigned int | |||
| 263 | minstrel_get_retry_count(struct minstrel_rate *mr, | 263 | minstrel_get_retry_count(struct minstrel_rate *mr, |
| 264 | struct ieee80211_tx_info *info) | 264 | struct ieee80211_tx_info *info) |
| 265 | { | 265 | { |
| 266 | unsigned int retry = mr->adjusted_retry_count; | 266 | u8 retry = mr->adjusted_retry_count; |
| 267 | 267 | ||
| 268 | if (info->control.use_rts) | 268 | if (info->control.use_rts) |
| 269 | retry = max(2U, min(mr->stats.retry_count_rtscts, retry)); | 269 | retry = max_t(u8, 2, min(mr->stats.retry_count_rtscts, retry)); |
| 270 | else if (info->control.use_cts_prot) | 270 | else if (info->control.use_cts_prot) |
| 271 | retry = max(2U, min(mr->retry_count_cts, retry)); | 271 | retry = max_t(u8, 2, min(mr->retry_count_cts, retry)); |
| 272 | return retry; | 272 | return retry; |
| 273 | } | 273 | } |
| 274 | 274 | ||
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 97eca86a4af0..410efe620c57 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
| @@ -33,8 +33,8 @@ minstrel_ewma(int old, int new, int weight) | |||
| 33 | 33 | ||
| 34 | struct minstrel_rate_stats { | 34 | struct minstrel_rate_stats { |
| 35 | /* current / last sampling period attempts/success counters */ | 35 | /* current / last sampling period attempts/success counters */ |
| 36 | unsigned int attempts, last_attempts; | 36 | u16 attempts, last_attempts; |
| 37 | unsigned int success, last_success; | 37 | u16 success, last_success; |
| 38 | 38 | ||
| 39 | /* total attempts/success counters */ | 39 | /* total attempts/success counters */ |
| 40 | u64 att_hist, succ_hist; | 40 | u64 att_hist, succ_hist; |
| @@ -46,8 +46,8 @@ struct minstrel_rate_stats { | |||
| 46 | unsigned int cur_prob, probability; | 46 | unsigned int cur_prob, probability; |
| 47 | 47 | ||
| 48 | /* maximum retry counts */ | 48 | /* maximum retry counts */ |
| 49 | unsigned int retry_count; | 49 | u8 retry_count; |
| 50 | unsigned int retry_count_rtscts; | 50 | u8 retry_count_rtscts; |
| 51 | 51 | ||
| 52 | u8 sample_skipped; | 52 | u8 sample_skipped; |
| 53 | bool retry_updated; | 53 | bool retry_updated; |
| @@ -55,14 +55,15 @@ struct minstrel_rate_stats { | |||
| 55 | 55 | ||
| 56 | struct minstrel_rate { | 56 | struct minstrel_rate { |
| 57 | int bitrate; | 57 | int bitrate; |
| 58 | int rix; | 58 | |
| 59 | s8 rix; | ||
| 60 | u8 retry_count_cts; | ||
| 61 | u8 adjusted_retry_count; | ||
| 59 | 62 | ||
| 60 | unsigned int perfect_tx_time; | 63 | unsigned int perfect_tx_time; |
| 61 | unsigned int ack_time; | 64 | unsigned int ack_time; |
| 62 | 65 | ||
| 63 | int sample_limit; | 66 | int sample_limit; |
| 64 | unsigned int retry_count_cts; | ||
| 65 | unsigned int adjusted_retry_count; | ||
| 66 | 67 | ||
| 67 | struct minstrel_rate_stats stats; | 68 | struct minstrel_rate_stats stats; |
| 68 | }; | 69 | }; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 683b10f46505..3d79d498e7f6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -361,9 +361,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 361 | u16 known = local->hw.radiotap_vht_details; | 361 | u16 known = local->hw.radiotap_vht_details; |
| 362 | 362 | ||
| 363 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); | 363 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); |
| 364 | /* known field - how to handle 80+80? */ | ||
| 365 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) | ||
| 366 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | ||
| 367 | put_unaligned_le16(known, pos); | 364 | put_unaligned_le16(known, pos); |
| 368 | pos += 2; | 365 | pos += 2; |
| 369 | /* flags */ | 366 | /* flags */ |
| @@ -378,8 +375,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 378 | /* bandwidth */ | 375 | /* bandwidth */ |
| 379 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) | 376 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
| 380 | *pos++ = 4; | 377 | *pos++ = 4; |
| 381 | else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) | ||
| 382 | *pos++ = 0; /* marked not known above */ | ||
| 383 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) | 378 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
| 384 | *pos++ = 11; | 379 | *pos++ = 11; |
| 385 | else if (status->flag & RX_FLAG_40MHZ) | 380 | else if (status->flag & RX_FLAG_40MHZ) |
| @@ -2314,6 +2309,15 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
| 2314 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) | 2309 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
| 2315 | return RX_DROP_MONITOR; | 2310 | return RX_DROP_MONITOR; |
| 2316 | 2311 | ||
| 2312 | if (rx->sta) { | ||
| 2313 | /* The security index has the same property as needed | ||
| 2314 | * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS | ||
| 2315 | * for non-QoS-data frames. Here we know it's a data | ||
| 2316 | * frame, so count MSDUs. | ||
| 2317 | */ | ||
| 2318 | rx->sta->rx_msdu[rx->security_idx]++; | ||
| 2319 | } | ||
| 2320 | |||
| 2317 | /* | 2321 | /* |
| 2318 | * Send unexpected-4addr-frame event to hostapd. For older versions, | 2322 | * Send unexpected-4addr-frame event to hostapd. For older versions, |
| 2319 | * also drop the frame to cooked monitor interfaces. | 2323 | * also drop the frame to cooked monitor interfaces. |
| @@ -2598,7 +2602,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 2598 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { | 2602 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { |
| 2599 | struct ieee80211_supported_band *sband; | 2603 | struct ieee80211_supported_band *sband; |
| 2600 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; | 2604 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; |
| 2601 | enum ieee80211_sta_rx_bandwidth new_bw; | 2605 | enum ieee80211_sta_rx_bandwidth max_bw, new_bw; |
| 2602 | 2606 | ||
| 2603 | /* If it doesn't support 40 MHz it can't change ... */ | 2607 | /* If it doesn't support 40 MHz it can't change ... */ |
| 2604 | if (!(rx->sta->sta.ht_cap.cap & | 2608 | if (!(rx->sta->sta.ht_cap.cap & |
| @@ -2606,13 +2610,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 2606 | goto handled; | 2610 | goto handled; |
| 2607 | 2611 | ||
| 2608 | if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) | 2612 | if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) |
| 2609 | new_bw = IEEE80211_STA_RX_BW_20; | 2613 | max_bw = IEEE80211_STA_RX_BW_20; |
| 2610 | else | 2614 | else |
| 2611 | new_bw = ieee80211_sta_cur_vht_bw(rx->sta); | 2615 | max_bw = ieee80211_sta_cap_rx_bw(rx->sta); |
| 2616 | |||
| 2617 | /* set cur_max_bandwidth and recalc sta bw */ | ||
| 2618 | rx->sta->cur_max_bandwidth = max_bw; | ||
| 2619 | new_bw = ieee80211_sta_cur_vht_bw(rx->sta); | ||
| 2612 | 2620 | ||
| 2613 | if (rx->sta->sta.bandwidth == new_bw) | 2621 | if (rx->sta->sta.bandwidth == new_bw) |
| 2614 | goto handled; | 2622 | goto handled; |
| 2615 | 2623 | ||
| 2624 | rx->sta->sta.bandwidth = new_bw; | ||
| 2616 | sband = rx->local->hw.wiphy->bands[status->band]; | 2625 | sband = rx->local->hw.wiphy->bands[status->band]; |
| 2617 | 2626 | ||
| 2618 | rate_control_rate_update(local, sband, rx->sta, | 2627 | rate_control_rate_update(local, sband, rx->sta, |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ae842678b629..7807fa42ed3f 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -416,7 +416,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local, | |||
| 416 | ieee80211_offchannel_stop_vifs(local); | 416 | ieee80211_offchannel_stop_vifs(local); |
| 417 | 417 | ||
| 418 | /* ensure nullfunc is transmitted before leaving operating channel */ | 418 | /* ensure nullfunc is transmitted before leaving operating channel */ |
| 419 | ieee80211_flush_queues(local, NULL); | 419 | ieee80211_flush_queues(local, NULL, false); |
| 420 | 420 | ||
| 421 | ieee80211_configure_filter(local); | 421 | ieee80211_configure_filter(local); |
| 422 | 422 | ||
| @@ -432,7 +432,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local, | |||
| 432 | static bool ieee80211_can_scan(struct ieee80211_local *local, | 432 | static bool ieee80211_can_scan(struct ieee80211_local *local, |
| 433 | struct ieee80211_sub_if_data *sdata) | 433 | struct ieee80211_sub_if_data *sdata) |
| 434 | { | 434 | { |
| 435 | if (local->radar_detect_enabled) | 435 | if (ieee80211_is_radar_required(local)) |
| 436 | return false; | 436 | return false; |
| 437 | 437 | ||
| 438 | if (!list_empty(&local->roc_list)) | 438 | if (!list_empty(&local->roc_list)) |
| @@ -505,7 +505,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
| 505 | 505 | ||
| 506 | lockdep_assert_held(&local->mtx); | 506 | lockdep_assert_held(&local->mtx); |
| 507 | 507 | ||
| 508 | if (local->scan_req) | 508 | if (local->scan_req || ieee80211_is_radar_required(local)) |
| 509 | return -EBUSY; | 509 | return -EBUSY; |
| 510 | 510 | ||
| 511 | if (!ieee80211_can_scan(local, sdata)) { | 511 | if (!ieee80211_can_scan(local, sdata)) { |
| @@ -805,7 +805,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local, | |||
| 805 | ieee80211_offchannel_stop_vifs(local); | 805 | ieee80211_offchannel_stop_vifs(local); |
| 806 | 806 | ||
| 807 | if (local->ops->flush) { | 807 | if (local->ops->flush) { |
| 808 | ieee80211_flush_queues(local, NULL); | 808 | ieee80211_flush_queues(local, NULL, false); |
| 809 | *next_delay = 0; | 809 | *next_delay = 0; |
| 810 | } else | 810 | } else |
| 811 | *next_delay = HZ / 10; | 811 | *next_delay = HZ / 10; |
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index efeba56c913b..06e6ac8cc693 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
| @@ -34,19 +34,15 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | |||
| 34 | struct cfg80211_chan_def new_vht_chandef = {}; | 34 | struct cfg80211_chan_def new_vht_chandef = {}; |
| 35 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; | 35 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; |
| 36 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; | 36 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; |
| 37 | const struct ieee80211_ht_operation *ht_oper; | ||
| 38 | int secondary_channel_offset = -1; | 37 | int secondary_channel_offset = -1; |
| 39 | 38 | ||
| 40 | sec_chan_offs = elems->sec_chan_offs; | 39 | sec_chan_offs = elems->sec_chan_offs; |
| 41 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; | 40 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; |
| 42 | ht_oper = elems->ht_operation; | ||
| 43 | 41 | ||
| 44 | if (sta_flags & (IEEE80211_STA_DISABLE_HT | | 42 | if (sta_flags & (IEEE80211_STA_DISABLE_HT | |
| 45 | IEEE80211_STA_DISABLE_40MHZ)) { | 43 | IEEE80211_STA_DISABLE_40MHZ)) { |
| 46 | sec_chan_offs = NULL; | 44 | sec_chan_offs = NULL; |
| 47 | wide_bw_chansw_ie = NULL; | 45 | wide_bw_chansw_ie = NULL; |
| 48 | /* only used for bandwidth here */ | ||
| 49 | ht_oper = NULL; | ||
| 50 | } | 46 | } |
| 51 | 47 | ||
| 52 | if (sta_flags & IEEE80211_STA_DISABLE_VHT) | 48 | if (sta_flags & IEEE80211_STA_DISABLE_VHT) |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a42f5b2b024d..79383ef0c264 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -116,7 +116,6 @@ static void __cleanup_single_sta(struct sta_info *sta) | |||
| 116 | clear_sta_flag(sta, WLAN_STA_PS_DELIVER); | 116 | clear_sta_flag(sta, WLAN_STA_PS_DELIVER); |
| 117 | 117 | ||
| 118 | atomic_dec(&ps->num_sta_ps); | 118 | atomic_dec(&ps->num_sta_ps); |
| 119 | sta_info_recalc_tim(sta); | ||
| 120 | } | 119 | } |
| 121 | 120 | ||
| 122 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 121 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| @@ -625,7 +624,7 @@ static unsigned long ieee80211_tids_for_ac(int ac) | |||
| 625 | } | 624 | } |
| 626 | } | 625 | } |
| 627 | 626 | ||
| 628 | void sta_info_recalc_tim(struct sta_info *sta) | 627 | static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending) |
| 629 | { | 628 | { |
| 630 | struct ieee80211_local *local = sta->local; | 629 | struct ieee80211_local *local = sta->local; |
| 631 | struct ps_data *ps; | 630 | struct ps_data *ps; |
| @@ -667,6 +666,9 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
| 667 | if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1) | 666 | if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1) |
| 668 | ignore_for_tim = 0; | 667 | ignore_for_tim = 0; |
| 669 | 668 | ||
| 669 | if (ignore_pending) | ||
| 670 | ignore_for_tim = BIT(IEEE80211_NUM_ACS) - 1; | ||
| 671 | |||
| 670 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 672 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 671 | unsigned long tids; | 673 | unsigned long tids; |
| 672 | 674 | ||
| @@ -695,7 +697,7 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
| 695 | else | 697 | else |
| 696 | __bss_tim_clear(ps->tim, id); | 698 | __bss_tim_clear(ps->tim, id); |
| 697 | 699 | ||
| 698 | if (local->ops->set_tim) { | 700 | if (local->ops->set_tim && !WARN_ON(sta->dead)) { |
| 699 | local->tim_in_locked_section = true; | 701 | local->tim_in_locked_section = true; |
| 700 | drv_set_tim(local, &sta->sta, indicate_tim); | 702 | drv_set_tim(local, &sta->sta, indicate_tim); |
| 701 | local->tim_in_locked_section = false; | 703 | local->tim_in_locked_section = false; |
| @@ -705,6 +707,11 @@ out_unlock: | |||
| 705 | spin_unlock_bh(&local->tim_lock); | 707 | spin_unlock_bh(&local->tim_lock); |
| 706 | } | 708 | } |
| 707 | 709 | ||
| 710 | void sta_info_recalc_tim(struct sta_info *sta) | ||
| 711 | { | ||
| 712 | __sta_info_recalc_tim(sta, false); | ||
| 713 | } | ||
| 714 | |||
| 708 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) | 715 | static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) |
| 709 | { | 716 | { |
| 710 | struct ieee80211_tx_info *info; | 717 | struct ieee80211_tx_info *info; |
| @@ -874,6 +881,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta) | |||
| 874 | { | 881 | { |
| 875 | struct ieee80211_local *local = sta->local; | 882 | struct ieee80211_local *local = sta->local; |
| 876 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 883 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
| 884 | struct station_info sinfo = {}; | ||
| 877 | int ret; | 885 | int ret; |
| 878 | 886 | ||
| 879 | /* | 887 | /* |
| @@ -887,6 +895,9 @@ static void __sta_info_destroy_part2(struct sta_info *sta) | |||
| 887 | /* now keys can no longer be reached */ | 895 | /* now keys can no longer be reached */ |
| 888 | ieee80211_free_sta_keys(local, sta); | 896 | ieee80211_free_sta_keys(local, sta); |
| 889 | 897 | ||
| 898 | /* disable TIM bit - last chance to tell driver */ | ||
| 899 | __sta_info_recalc_tim(sta, true); | ||
| 900 | |||
| 890 | sta->dead = true; | 901 | sta->dead = true; |
| 891 | 902 | ||
| 892 | local->num_sta--; | 903 | local->num_sta--; |
| @@ -908,7 +919,8 @@ static void __sta_info_destroy_part2(struct sta_info *sta) | |||
| 908 | 919 | ||
| 909 | sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); | 920 | sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); |
| 910 | 921 | ||
| 911 | cfg80211_del_sta(sdata->dev, sta->sta.addr, GFP_KERNEL); | 922 | sta_set_sinfo(sta, &sinfo); |
| 923 | cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | ||
| 912 | 924 | ||
| 913 | rate_control_remove_sta_debugfs(sta); | 925 | rate_control_remove_sta_debugfs(sta); |
| 914 | ieee80211_sta_debugfs_remove(sta); | 926 | ieee80211_sta_debugfs_remove(sta); |
| @@ -1243,10 +1255,11 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
| 1243 | * ends the poll/service period. | 1255 | * ends the poll/service period. |
| 1244 | */ | 1256 | */ |
| 1245 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | | 1257 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | |
| 1246 | IEEE80211_TX_CTL_PS_RESPONSE | | ||
| 1247 | IEEE80211_TX_STATUS_EOSP | | 1258 | IEEE80211_TX_STATUS_EOSP | |
| 1248 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 1259 | IEEE80211_TX_CTL_REQ_TX_STATUS; |
| 1249 | 1260 | ||
| 1261 | info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE; | ||
| 1262 | |||
| 1250 | if (call_driver) | 1263 | if (call_driver) |
| 1251 | drv_allow_buffered_frames(local, sta, BIT(tid), 1, | 1264 | drv_allow_buffered_frames(local, sta, BIT(tid), 1, |
| 1252 | reason, false); | 1265 | reason, false); |
| @@ -1395,8 +1408,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
| 1395 | * STA may still remain is PS mode after this frame | 1408 | * STA may still remain is PS mode after this frame |
| 1396 | * exchange. | 1409 | * exchange. |
| 1397 | */ | 1410 | */ |
| 1398 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | | 1411 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; |
| 1399 | IEEE80211_TX_CTL_PS_RESPONSE; | 1412 | info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE; |
| 1400 | 1413 | ||
| 1401 | /* | 1414 | /* |
| 1402 | * Use MoreData flag to indicate whether there are | 1415 | * Use MoreData flag to indicate whether there are |
| @@ -1743,7 +1756,6 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
| 1743 | struct ieee80211_local *local = sdata->local; | 1756 | struct ieee80211_local *local = sdata->local; |
| 1744 | struct rate_control_ref *ref = NULL; | 1757 | struct rate_control_ref *ref = NULL; |
| 1745 | struct timespec uptime; | 1758 | struct timespec uptime; |
| 1746 | u64 packets = 0; | ||
| 1747 | u32 thr = 0; | 1759 | u32 thr = 0; |
| 1748 | int i, ac; | 1760 | int i, ac; |
| 1749 | 1761 | ||
| @@ -1752,49 +1764,76 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
| 1752 | 1764 | ||
| 1753 | sinfo->generation = sdata->local->sta_generation; | 1765 | sinfo->generation = sdata->local->sta_generation; |
| 1754 | 1766 | ||
| 1755 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 1767 | drv_sta_statistics(local, sdata, &sta->sta, sinfo); |
| 1756 | STATION_INFO_RX_BYTES64 | | 1768 | |
| 1757 | STATION_INFO_TX_BYTES64 | | 1769 | sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) | |
| 1758 | STATION_INFO_RX_PACKETS | | 1770 | BIT(NL80211_STA_INFO_STA_FLAGS) | |
| 1759 | STATION_INFO_TX_PACKETS | | 1771 | BIT(NL80211_STA_INFO_BSS_PARAM) | |
| 1760 | STATION_INFO_TX_RETRIES | | 1772 | BIT(NL80211_STA_INFO_CONNECTED_TIME) | |
| 1761 | STATION_INFO_TX_FAILED | | 1773 | BIT(NL80211_STA_INFO_RX_DROP_MISC) | |
| 1762 | STATION_INFO_TX_BITRATE | | 1774 | BIT(NL80211_STA_INFO_BEACON_LOSS); |
| 1763 | STATION_INFO_RX_BITRATE | | ||
| 1764 | STATION_INFO_RX_DROP_MISC | | ||
| 1765 | STATION_INFO_BSS_PARAM | | ||
| 1766 | STATION_INFO_CONNECTED_TIME | | ||
| 1767 | STATION_INFO_STA_FLAGS | | ||
| 1768 | STATION_INFO_BEACON_LOSS_COUNT; | ||
| 1769 | 1775 | ||
| 1770 | ktime_get_ts(&uptime); | 1776 | ktime_get_ts(&uptime); |
| 1771 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | 1777 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
| 1772 | |||
| 1773 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 1778 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
| 1774 | sinfo->tx_bytes = 0; | 1779 | |
| 1775 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1780 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES64) | |
| 1776 | sinfo->tx_bytes += sta->tx_bytes[ac]; | 1781 | BIT(NL80211_STA_INFO_TX_BYTES)))) { |
| 1777 | packets += sta->tx_packets[ac]; | 1782 | sinfo->tx_bytes = 0; |
| 1783 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
| 1784 | sinfo->tx_bytes += sta->tx_bytes[ac]; | ||
| 1785 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_PACKETS))) { | ||
| 1789 | sinfo->tx_packets = 0; | ||
| 1790 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
| 1791 | sinfo->tx_packets += sta->tx_packets[ac]; | ||
| 1792 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); | ||
| 1793 | } | ||
| 1794 | |||
| 1795 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | | ||
| 1796 | BIT(NL80211_STA_INFO_RX_BYTES)))) { | ||
| 1797 | sinfo->rx_bytes = sta->rx_bytes; | ||
| 1798 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); | ||
| 1799 | } | ||
| 1800 | |||
| 1801 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) { | ||
| 1802 | sinfo->rx_packets = sta->rx_packets; | ||
| 1803 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_RETRIES))) { | ||
| 1807 | sinfo->tx_retries = sta->tx_retry_count; | ||
| 1808 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_RETRIES); | ||
| 1778 | } | 1809 | } |
| 1779 | sinfo->tx_packets = packets; | 1810 | |
| 1780 | sinfo->rx_bytes = sta->rx_bytes; | 1811 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_FAILED))) { |
| 1781 | sinfo->rx_packets = sta->rx_packets; | 1812 | sinfo->tx_failed = sta->tx_retry_failed; |
| 1782 | sinfo->tx_retries = sta->tx_retry_count; | 1813 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); |
| 1783 | sinfo->tx_failed = sta->tx_retry_failed; | 1814 | } |
| 1815 | |||
| 1784 | sinfo->rx_dropped_misc = sta->rx_dropped; | 1816 | sinfo->rx_dropped_misc = sta->rx_dropped; |
| 1785 | sinfo->beacon_loss_count = sta->beacon_loss_count; | 1817 | sinfo->beacon_loss_count = sta->beacon_loss_count; |
| 1786 | 1818 | ||
| 1787 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 1819 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
| 1788 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 1820 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
| 1789 | sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; | 1821 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) { |
| 1790 | if (!local->ops->get_rssi || | ||
| 1791 | drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal)) | ||
| 1792 | sinfo->signal = (s8)sta->last_signal; | 1822 | sinfo->signal = (s8)sta->last_signal; |
| 1793 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | 1823 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
| 1824 | } | ||
| 1825 | |||
| 1826 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { | ||
| 1827 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | ||
| 1828 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); | ||
| 1829 | } | ||
| 1794 | } | 1830 | } |
| 1795 | if (sta->chains) { | 1831 | |
| 1796 | sinfo->filled |= STATION_INFO_CHAIN_SIGNAL | | 1832 | if (sta->chains && |
| 1797 | STATION_INFO_CHAIN_SIGNAL_AVG; | 1833 | !(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | |
| 1834 | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) { | ||
| 1835 | sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | | ||
| 1836 | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); | ||
| 1798 | 1837 | ||
| 1799 | sinfo->chains = sta->chains; | 1838 | sinfo->chains = sta->chains; |
| 1800 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { | 1839 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { |
| @@ -1804,23 +1843,61 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
| 1804 | } | 1843 | } |
| 1805 | } | 1844 | } |
| 1806 | 1845 | ||
| 1807 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); | 1846 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE))) { |
| 1808 | sta_set_rate_info_rx(sta, &sinfo->rxrate); | 1847 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); |
| 1848 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE))) { | ||
| 1852 | sta_set_rate_info_rx(sta, &sinfo->rxrate); | ||
| 1853 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | sinfo->filled |= BIT(NL80211_STA_INFO_TID_STATS); | ||
| 1857 | for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { | ||
| 1858 | struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i]; | ||
| 1859 | |||
| 1860 | if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { | ||
| 1861 | tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU); | ||
| 1862 | tidstats->rx_msdu = sta->rx_msdu[i]; | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) { | ||
| 1866 | tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU); | ||
| 1867 | tidstats->tx_msdu = sta->tx_msdu[i]; | ||
| 1868 | } | ||
| 1869 | |||
| 1870 | if (!(tidstats->filled & | ||
| 1871 | BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) && | ||
| 1872 | local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | ||
| 1873 | tidstats->filled |= | ||
| 1874 | BIT(NL80211_TID_STATS_TX_MSDU_RETRIES); | ||
| 1875 | tidstats->tx_msdu_retries = sta->tx_msdu_retries[i]; | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | if (!(tidstats->filled & | ||
| 1879 | BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) && | ||
| 1880 | local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | ||
| 1881 | tidstats->filled |= | ||
| 1882 | BIT(NL80211_TID_STATS_TX_MSDU_FAILED); | ||
| 1883 | tidstats->tx_msdu_failed = sta->tx_msdu_failed[i]; | ||
| 1884 | } | ||
| 1885 | } | ||
| 1809 | 1886 | ||
| 1810 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1887 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
| 1811 | #ifdef CONFIG_MAC80211_MESH | 1888 | #ifdef CONFIG_MAC80211_MESH |
| 1812 | sinfo->filled |= STATION_INFO_LLID | | 1889 | sinfo->filled |= BIT(NL80211_STA_INFO_LLID) | |
| 1813 | STATION_INFO_PLID | | 1890 | BIT(NL80211_STA_INFO_PLID) | |
| 1814 | STATION_INFO_PLINK_STATE | | 1891 | BIT(NL80211_STA_INFO_PLINK_STATE) | |
| 1815 | STATION_INFO_LOCAL_PM | | 1892 | BIT(NL80211_STA_INFO_LOCAL_PM) | |
| 1816 | STATION_INFO_PEER_PM | | 1893 | BIT(NL80211_STA_INFO_PEER_PM) | |
| 1817 | STATION_INFO_NONPEER_PM; | 1894 | BIT(NL80211_STA_INFO_NONPEER_PM); |
| 1818 | 1895 | ||
| 1819 | sinfo->llid = sta->llid; | 1896 | sinfo->llid = sta->llid; |
| 1820 | sinfo->plid = sta->plid; | 1897 | sinfo->plid = sta->plid; |
| 1821 | sinfo->plink_state = sta->plink_state; | 1898 | sinfo->plink_state = sta->plink_state; |
| 1822 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | 1899 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { |
| 1823 | sinfo->filled |= STATION_INFO_T_OFFSET; | 1900 | sinfo->filled |= BIT(NL80211_STA_INFO_T_OFFSET); |
| 1824 | sinfo->t_offset = sta->t_offset; | 1901 | sinfo->t_offset = sta->t_offset; |
| 1825 | } | 1902 | } |
| 1826 | sinfo->local_pm = sta->local_pm; | 1903 | sinfo->local_pm = sta->local_pm; |
| @@ -1869,7 +1946,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
| 1869 | thr = drv_get_expected_throughput(local, &sta->sta); | 1946 | thr = drv_get_expected_throughput(local, &sta->sta); |
| 1870 | 1947 | ||
| 1871 | if (thr != 0) { | 1948 | if (thr != 0) { |
| 1872 | sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT; | 1949 | sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT); |
| 1873 | sinfo->expected_throughput = thr; | 1950 | sinfo->expected_throughput = thr; |
| 1874 | } | 1951 | } |
| 1875 | } | 1952 | } |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4f052bb2a5ad..925e68fe64c7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
| @@ -346,6 +346,14 @@ struct ieee80211_tx_latency_stat { | |||
| 346 | * @cipher_scheme: optional cipher scheme for this station | 346 | * @cipher_scheme: optional cipher scheme for this station |
| 347 | * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed | 347 | * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed |
| 348 | * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) | 348 | * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) |
| 349 | * @tx_msdu: MSDUs transmitted to this station, using IEEE80211_NUM_TID | ||
| 350 | * entry for non-QoS frames | ||
| 351 | * @tx_msdu_retries: MSDU retries for transmissions to to this station, | ||
| 352 | * using IEEE80211_NUM_TID entry for non-QoS frames | ||
| 353 | * @tx_msdu_failed: MSDU failures for transmissions to to this station, | ||
| 354 | * using IEEE80211_NUM_TID entry for non-QoS frames | ||
| 355 | * @rx_msdu: MSDUs received from this station, using IEEE80211_NUM_TID | ||
| 356 | * entry for non-QoS frames | ||
| 349 | */ | 357 | */ |
| 350 | struct sta_info { | 358 | struct sta_info { |
| 351 | /* General information, mostly static */ | 359 | /* General information, mostly static */ |
| @@ -416,6 +424,10 @@ struct sta_info { | |||
| 416 | u32 last_rx_rate_vht_flag; | 424 | u32 last_rx_rate_vht_flag; |
| 417 | u8 last_rx_rate_vht_nss; | 425 | u8 last_rx_rate_vht_nss; |
| 418 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 426 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
| 427 | u64 tx_msdu[IEEE80211_NUM_TIDS + 1]; | ||
| 428 | u64 tx_msdu_retries[IEEE80211_NUM_TIDS + 1]; | ||
| 429 | u64 tx_msdu_failed[IEEE80211_NUM_TIDS + 1]; | ||
| 430 | u64 rx_msdu[IEEE80211_NUM_TIDS + 1]; | ||
| 419 | 431 | ||
| 420 | /* | 432 | /* |
| 421 | * Aggregation information, locked with lock. | 433 | * Aggregation information, locked with lock. |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index bb146f377ee4..e679b7c9b160 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
| @@ -664,13 +664,15 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, | |||
| 664 | struct ieee80211_supported_band *sband; | 664 | struct ieee80211_supported_band *sband; |
| 665 | int retry_count; | 665 | int retry_count; |
| 666 | int rates_idx; | 666 | int rates_idx; |
| 667 | bool acked; | 667 | bool acked, noack_success; |
| 668 | 668 | ||
| 669 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); | 669 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); |
| 670 | 670 | ||
| 671 | sband = hw->wiphy->bands[info->band]; | 671 | sband = hw->wiphy->bands[info->band]; |
| 672 | 672 | ||
| 673 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); | 673 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); |
| 674 | noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED); | ||
| 675 | |||
| 674 | if (pubsta) { | 676 | if (pubsta) { |
| 675 | struct sta_info *sta; | 677 | struct sta_info *sta; |
| 676 | 678 | ||
| @@ -696,7 +698,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, | |||
| 696 | rate_control_tx_status_noskb(local, sband, sta, info); | 698 | rate_control_tx_status_noskb(local, sband, sta, info); |
| 697 | } | 699 | } |
| 698 | 700 | ||
| 699 | if (acked) { | 701 | if (acked || noack_success) { |
| 700 | local->dot11TransmittedFrameCount++; | 702 | local->dot11TransmittedFrameCount++; |
| 701 | if (!pubsta) | 703 | if (!pubsta) |
| 702 | local->dot11MulticastTransmittedFrameCount++; | 704 | local->dot11MulticastTransmittedFrameCount++; |
| @@ -728,6 +730,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 728 | struct ieee80211_bar *bar; | 730 | struct ieee80211_bar *bar; |
| 729 | int rtap_len; | 731 | int rtap_len; |
| 730 | int shift = 0; | 732 | int shift = 0; |
| 733 | int tid = IEEE80211_NUM_TIDS; | ||
| 731 | 734 | ||
| 732 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); | 735 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); |
| 733 | 736 | ||
| @@ -771,7 +774,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 771 | 774 | ||
| 772 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 775 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
| 773 | (ieee80211_is_data_qos(fc))) { | 776 | (ieee80211_is_data_qos(fc))) { |
| 774 | u16 tid, ssn; | 777 | u16 ssn; |
| 775 | u8 *qc; | 778 | u8 *qc; |
| 776 | 779 | ||
| 777 | qc = ieee80211_get_qos_ctl(hdr); | 780 | qc = ieee80211_get_qos_ctl(hdr); |
| @@ -780,10 +783,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 780 | & IEEE80211_SCTL_SEQ); | 783 | & IEEE80211_SCTL_SEQ); |
| 781 | ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, | 784 | ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, |
| 782 | tid, ssn); | 785 | tid, ssn); |
| 786 | } else if (ieee80211_is_data_qos(fc)) { | ||
| 787 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
| 788 | |||
| 789 | tid = qc[0] & 0xf; | ||
| 783 | } | 790 | } |
| 784 | 791 | ||
| 785 | if (!acked && ieee80211_is_back_req(fc)) { | 792 | if (!acked && ieee80211_is_back_req(fc)) { |
| 786 | u16 tid, control; | 793 | u16 control; |
| 787 | 794 | ||
| 788 | /* | 795 | /* |
| 789 | * BAR failed, store the last SSN and retry sending | 796 | * BAR failed, store the last SSN and retry sending |
| @@ -811,6 +818,12 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 811 | if (!acked) | 818 | if (!acked) |
| 812 | sta->tx_retry_failed++; | 819 | sta->tx_retry_failed++; |
| 813 | sta->tx_retry_count += retry_count; | 820 | sta->tx_retry_count += retry_count; |
| 821 | |||
| 822 | if (ieee80211_is_data_present(fc)) { | ||
| 823 | if (!acked) | ||
| 824 | sta->tx_msdu_failed[tid]++; | ||
| 825 | sta->tx_msdu_retries[tid] += retry_count; | ||
| 826 | } | ||
| 814 | } | 827 | } |
| 815 | 828 | ||
| 816 | rate_control_tx_status(local, sband, sta, skb); | 829 | rate_control_tx_status(local, sband, sta, skb); |
| @@ -856,10 +869,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 856 | * Fragments are passed to low-level drivers as separate skbs, so these | 869 | * Fragments are passed to low-level drivers as separate skbs, so these |
| 857 | * are actually fragments, not frames. Update frame counters only for | 870 | * are actually fragments, not frames. Update frame counters only for |
| 858 | * the first fragment of the frame. */ | 871 | * the first fragment of the frame. */ |
| 859 | if (info->flags & IEEE80211_TX_STAT_ACK) { | 872 | if ((info->flags & IEEE80211_TX_STAT_ACK) || |
| 873 | (info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) { | ||
| 860 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) { | 874 | if (ieee80211_is_first_frag(hdr->seq_ctrl)) { |
| 861 | local->dot11TransmittedFrameCount++; | 875 | local->dot11TransmittedFrameCount++; |
| 862 | if (is_multicast_ether_addr(hdr->addr1)) | 876 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) |
| 863 | local->dot11MulticastTransmittedFrameCount++; | 877 | local->dot11MulticastTransmittedFrameCount++; |
| 864 | if (retry_count > 0) | 878 | if (retry_count > 0) |
| 865 | local->dot11RetryCount++; | 879 | local->dot11RetryCount++; |
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index 55ddd77b865d..917088dfd696 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c | |||
| @@ -68,17 +68,24 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata, | |||
| 68 | ch = ieee80211_get_channel(sdata->local->hw.wiphy, i); | 68 | ch = ieee80211_get_channel(sdata->local->hw.wiphy, i); |
| 69 | if (ch) { | 69 | if (ch) { |
| 70 | /* we will be active on the channel */ | 70 | /* we will be active on the channel */ |
| 71 | u32 flags = IEEE80211_CHAN_DISABLED | | ||
| 72 | IEEE80211_CHAN_NO_IR; | ||
| 73 | cfg80211_chandef_create(&chandef, ch, | 71 | cfg80211_chandef_create(&chandef, ch, |
| 74 | NL80211_CHAN_HT20); | 72 | NL80211_CHAN_NO_HT); |
| 75 | if (cfg80211_chandef_usable(sdata->local->hw.wiphy, | 73 | if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy, |
| 76 | &chandef, flags)) { | 74 | &chandef, |
| 75 | sdata->wdev.iftype)) { | ||
| 77 | ch_cnt++; | 76 | ch_cnt++; |
| 77 | /* | ||
| 78 | * check if the next channel is also part of | ||
| 79 | * this allowed range | ||
| 80 | */ | ||
| 78 | continue; | 81 | continue; |
| 79 | } | 82 | } |
| 80 | } | 83 | } |
| 81 | 84 | ||
| 85 | /* | ||
| 86 | * we've reached the end of a range, with allowed channels | ||
| 87 | * found | ||
| 88 | */ | ||
| 82 | if (ch_cnt) { | 89 | if (ch_cnt) { |
| 83 | u8 *pos = skb_put(skb, 2); | 90 | u8 *pos = skb_put(skb, 2); |
| 84 | *pos++ = ieee80211_frequency_to_channel(subband_start); | 91 | *pos++ = ieee80211_frequency_to_channel(subband_start); |
| @@ -89,6 +96,15 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata, | |||
| 89 | } | 96 | } |
| 90 | } | 97 | } |
| 91 | 98 | ||
| 99 | /* all channels in the requested range are allowed - add them here */ | ||
| 100 | if (ch_cnt) { | ||
| 101 | u8 *pos = skb_put(skb, 2); | ||
| 102 | *pos++ = ieee80211_frequency_to_channel(subband_start); | ||
| 103 | *pos++ = ch_cnt; | ||
| 104 | |||
| 105 | subband_cnt++; | ||
| 106 | } | ||
| 107 | |||
| 92 | return subband_cnt; | 108 | return subband_cnt; |
| 93 | } | 109 | } |
| 94 | 110 | ||
| @@ -912,7 +928,7 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, | |||
| 912 | rcu_read_unlock(); | 928 | rcu_read_unlock(); |
| 913 | } | 929 | } |
| 914 | 930 | ||
| 915 | ieee80211_flush_queues(local, sdata); | 931 | ieee80211_flush_queues(local, sdata, false); |
| 916 | 932 | ||
| 917 | ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code, | 933 | ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code, |
| 918 | dialog_token, status_code, | 934 | dialog_token, status_code, |
| @@ -952,7 +968,7 @@ ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev, | |||
| 952 | */ | 968 | */ |
| 953 | ieee80211_stop_vif_queues(local, sdata, | 969 | ieee80211_stop_vif_queues(local, sdata, |
| 954 | IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN); | 970 | IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN); |
| 955 | ieee80211_flush_queues(local, sdata); | 971 | ieee80211_flush_queues(local, sdata, false); |
| 956 | 972 | ||
| 957 | ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code, | 973 | ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code, |
| 958 | dialog_token, status_code, | 974 | dialog_token, status_code, |
| @@ -1098,7 +1114,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
| 1098 | */ | 1114 | */ |
| 1099 | tasklet_kill(&local->tx_pending_tasklet); | 1115 | tasklet_kill(&local->tx_pending_tasklet); |
| 1100 | /* flush a potentially queued teardown packet */ | 1116 | /* flush a potentially queued teardown packet */ |
| 1101 | ieee80211_flush_queues(local, sdata); | 1117 | ieee80211_flush_queues(local, sdata, false); |
| 1102 | 1118 | ||
| 1103 | ret = sta_info_destroy_addr(sdata, peer); | 1119 | ret = sta_info_destroy_addr(sdata, peer); |
| 1104 | break; | 1120 | break; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 8e461a02c6a8..263a9561eb26 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
| @@ -825,6 +825,13 @@ DECLARE_EVENT_CLASS(sta_event, | |||
| 825 | ) | 825 | ) |
| 826 | ); | 826 | ); |
| 827 | 827 | ||
| 828 | DEFINE_EVENT(sta_event, drv_sta_statistics, | ||
| 829 | TP_PROTO(struct ieee80211_local *local, | ||
| 830 | struct ieee80211_sub_if_data *sdata, | ||
| 831 | struct ieee80211_sta *sta), | ||
| 832 | TP_ARGS(local, sdata, sta) | ||
| 833 | ); | ||
| 834 | |||
| 828 | DEFINE_EVENT(sta_event, drv_sta_add, | 835 | DEFINE_EVENT(sta_event, drv_sta_add, |
| 829 | TP_PROTO(struct ieee80211_local *local, | 836 | TP_PROTO(struct ieee80211_local *local, |
| 830 | struct ieee80211_sub_if_data *sdata, | 837 | struct ieee80211_sub_if_data *sdata, |
| @@ -1329,32 +1336,6 @@ DEFINE_EVENT(release_evt, drv_allow_buffered_frames, | |||
| 1329 | TP_ARGS(local, sta, tids, num_frames, reason, more_data) | 1336 | TP_ARGS(local, sta, tids, num_frames, reason, more_data) |
| 1330 | ); | 1337 | ); |
| 1331 | 1338 | ||
| 1332 | TRACE_EVENT(drv_get_rssi, | ||
| 1333 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta, | ||
| 1334 | s8 rssi, int ret), | ||
| 1335 | |||
| 1336 | TP_ARGS(local, sta, rssi, ret), | ||
| 1337 | |||
| 1338 | TP_STRUCT__entry( | ||
| 1339 | LOCAL_ENTRY | ||
| 1340 | STA_ENTRY | ||
| 1341 | __field(s8, rssi) | ||
| 1342 | __field(int, ret) | ||
| 1343 | ), | ||
| 1344 | |||
| 1345 | TP_fast_assign( | ||
| 1346 | LOCAL_ASSIGN; | ||
| 1347 | STA_ASSIGN; | ||
| 1348 | __entry->rssi = rssi; | ||
| 1349 | __entry->ret = ret; | ||
| 1350 | ), | ||
| 1351 | |||
| 1352 | TP_printk( | ||
| 1353 | LOCAL_PR_FMT STA_PR_FMT " rssi:%d ret:%d", | ||
| 1354 | LOCAL_PR_ARG, STA_PR_ARG, __entry->rssi, __entry->ret | ||
| 1355 | ) | ||
| 1356 | ); | ||
| 1357 | |||
| 1358 | DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx, | 1339 | DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx, |
| 1359 | TP_PROTO(struct ieee80211_local *local, | 1340 | TP_PROTO(struct ieee80211_local *local, |
| 1360 | struct ieee80211_sub_if_data *sdata), | 1341 | struct ieee80211_sub_if_data *sdata), |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 058686a721a1..02ed6f60629a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -815,6 +815,8 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
| 815 | /* for pure STA mode without beacons, we can do it */ | 815 | /* for pure STA mode without beacons, we can do it */ |
| 816 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); | 816 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); |
| 817 | tx->sdata->sequence_number += 0x10; | 817 | tx->sdata->sequence_number += 0x10; |
| 818 | if (tx->sta) | ||
| 819 | tx->sta->tx_msdu[IEEE80211_NUM_TIDS]++; | ||
| 818 | return TX_CONTINUE; | 820 | return TX_CONTINUE; |
| 819 | } | 821 | } |
| 820 | 822 | ||
| @@ -831,6 +833,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
| 831 | qc = ieee80211_get_qos_ctl(hdr); | 833 | qc = ieee80211_get_qos_ctl(hdr); |
| 832 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 834 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
| 833 | seq = &tx->sta->tid_seq[tid]; | 835 | seq = &tx->sta->tid_seq[tid]; |
| 836 | tx->sta->tx_msdu[tid]++; | ||
| 834 | 837 | ||
| 835 | hdr->seq_ctrl = cpu_to_le16(*seq); | 838 | hdr->seq_ctrl = cpu_to_le16(*seq); |
| 836 | 839 | ||
| @@ -3152,7 +3155,7 @@ int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid) | |||
| 3152 | } | 3155 | } |
| 3153 | 3156 | ||
| 3154 | queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]); | 3157 | queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]); |
| 3155 | __ieee80211_flush_queues(local, sdata, queues); | 3158 | __ieee80211_flush_queues(local, sdata, queues, false); |
| 3156 | 3159 | ||
| 3157 | sta->reserved_tid = tid; | 3160 | sta->reserved_tid = tid; |
| 3158 | 3161 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 974ebe70f5b0..fbd37d43dfce 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -578,7 +578,7 @@ ieee80211_get_vif_queues(struct ieee80211_local *local, | |||
| 578 | 578 | ||
| 579 | void __ieee80211_flush_queues(struct ieee80211_local *local, | 579 | void __ieee80211_flush_queues(struct ieee80211_local *local, |
| 580 | struct ieee80211_sub_if_data *sdata, | 580 | struct ieee80211_sub_if_data *sdata, |
| 581 | unsigned int queues) | 581 | unsigned int queues, bool drop) |
| 582 | { | 582 | { |
| 583 | if (!local->ops->flush) | 583 | if (!local->ops->flush) |
| 584 | return; | 584 | return; |
| @@ -594,7 +594,7 @@ void __ieee80211_flush_queues(struct ieee80211_local *local, | |||
| 594 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | 594 | IEEE80211_QUEUE_STOP_REASON_FLUSH, |
| 595 | false); | 595 | false); |
| 596 | 596 | ||
| 597 | drv_flush(local, sdata, queues, false); | 597 | drv_flush(local, sdata, queues, drop); |
| 598 | 598 | ||
| 599 | ieee80211_wake_queues_by_reason(&local->hw, queues, | 599 | ieee80211_wake_queues_by_reason(&local->hw, queues, |
| 600 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | 600 | IEEE80211_QUEUE_STOP_REASON_FLUSH, |
| @@ -602,9 +602,9 @@ void __ieee80211_flush_queues(struct ieee80211_local *local, | |||
| 602 | } | 602 | } |
| 603 | 603 | ||
| 604 | void ieee80211_flush_queues(struct ieee80211_local *local, | 604 | void ieee80211_flush_queues(struct ieee80211_local *local, |
| 605 | struct ieee80211_sub_if_data *sdata) | 605 | struct ieee80211_sub_if_data *sdata, bool drop) |
| 606 | { | 606 | { |
| 607 | __ieee80211_flush_queues(local, sdata, 0); | 607 | __ieee80211_flush_queues(local, sdata, 0, drop); |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | void ieee80211_stop_vif_queues(struct ieee80211_local *local, | 610 | void ieee80211_stop_vif_queues(struct ieee80211_local *local, |
| @@ -1470,10 +1470,12 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
| 1470 | 1470 | ||
| 1471 | /* Check if any channel in this sband supports at least 80 MHz */ | 1471 | /* Check if any channel in this sband supports at least 80 MHz */ |
| 1472 | for (i = 0; i < sband->n_channels; i++) { | 1472 | for (i = 0; i < sband->n_channels; i++) { |
| 1473 | if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) { | 1473 | if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | |
| 1474 | have_80mhz = true; | 1474 | IEEE80211_CHAN_NO_80MHZ)) |
| 1475 | break; | 1475 | continue; |
| 1476 | } | 1476 | |
| 1477 | have_80mhz = true; | ||
| 1478 | break; | ||
| 1477 | } | 1479 | } |
| 1478 | 1480 | ||
| 1479 | if (sband->vht_cap.vht_supported && have_80mhz) { | 1481 | if (sband->vht_cap.vht_supported && have_80mhz) { |
| @@ -1735,6 +1737,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1735 | struct cfg80211_sched_scan_request *sched_scan_req; | 1737 | struct cfg80211_sched_scan_request *sched_scan_req; |
| 1736 | bool sched_scan_stopped = false; | 1738 | bool sched_scan_stopped = false; |
| 1737 | 1739 | ||
| 1740 | /* nothing to do if HW shouldn't run */ | ||
| 1741 | if (!local->open_count) | ||
| 1742 | goto wake_up; | ||
| 1743 | |||
| 1738 | #ifdef CONFIG_PM | 1744 | #ifdef CONFIG_PM |
| 1739 | if (local->suspended) | 1745 | if (local->suspended) |
| 1740 | local->resuming = true; | 1746 | local->resuming = true; |
| @@ -1756,9 +1762,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1756 | reconfig_due_to_wowlan = true; | 1762 | reconfig_due_to_wowlan = true; |
| 1757 | } | 1763 | } |
| 1758 | #endif | 1764 | #endif |
| 1759 | /* everything else happens only if HW was up & running */ | ||
| 1760 | if (!local->open_count) | ||
| 1761 | goto wake_up; | ||
| 1762 | 1765 | ||
| 1763 | /* | 1766 | /* |
| 1764 | * Upon resume hardware can sometimes be goofy due to | 1767 | * Upon resume hardware can sometimes be goofy due to |
| @@ -2042,7 +2045,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 2042 | * If this is for hw restart things are still running. | 2045 | * If this is for hw restart things are still running. |
| 2043 | * We may want to change that later, however. | 2046 | * We may want to change that later, however. |
| 2044 | */ | 2047 | */ |
| 2045 | if (!local->suspended || reconfig_due_to_wowlan) | 2048 | if (local->open_count && (!local->suspended || reconfig_due_to_wowlan)) |
| 2046 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART); | 2049 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART); |
| 2047 | 2050 | ||
| 2048 | if (!local->suspended) | 2051 | if (!local->suspended) |
| @@ -2054,7 +2057,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 2054 | mb(); | 2057 | mb(); |
| 2055 | local->resuming = false; | 2058 | local->resuming = false; |
| 2056 | 2059 | ||
| 2057 | if (!reconfig_due_to_wowlan) | 2060 | if (local->open_count && !reconfig_due_to_wowlan) |
| 2058 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); | 2061 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); |
| 2059 | 2062 | ||
| 2060 | list_for_each_entry(sdata, &local->interfaces, list) { | 2063 | list_for_each_entry(sdata, &local->interfaces, list) { |
| @@ -2538,7 +2541,9 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
| 2538 | ri.mcs = status->rate_idx; | 2541 | ri.mcs = status->rate_idx; |
| 2539 | ri.flags |= RATE_INFO_FLAGS_MCS; | 2542 | ri.flags |= RATE_INFO_FLAGS_MCS; |
| 2540 | if (status->flag & RX_FLAG_40MHZ) | 2543 | if (status->flag & RX_FLAG_40MHZ) |
| 2541 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2544 | ri.bw = RATE_INFO_BW_40; |
| 2545 | else | ||
| 2546 | ri.bw = RATE_INFO_BW_20; | ||
| 2542 | if (status->flag & RX_FLAG_SHORT_GI) | 2547 | if (status->flag & RX_FLAG_SHORT_GI) |
| 2543 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2548 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 2544 | } else if (status->flag & RX_FLAG_VHT) { | 2549 | } else if (status->flag & RX_FLAG_VHT) { |
| @@ -2546,13 +2551,13 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
| 2546 | ri.mcs = status->rate_idx; | 2551 | ri.mcs = status->rate_idx; |
| 2547 | ri.nss = status->vht_nss; | 2552 | ri.nss = status->vht_nss; |
| 2548 | if (status->flag & RX_FLAG_40MHZ) | 2553 | if (status->flag & RX_FLAG_40MHZ) |
| 2549 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2554 | ri.bw = RATE_INFO_BW_40; |
| 2550 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) | 2555 | else if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
| 2551 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 2556 | ri.bw = RATE_INFO_BW_80; |
| 2552 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) | 2557 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
| 2553 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 2558 | ri.bw = RATE_INFO_BW_160; |
| 2554 | if (status->vht_flag & RX_VHT_FLAG_160MHZ) | 2559 | else |
| 2555 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 2560 | ri.bw = RATE_INFO_BW_20; |
| 2556 | if (status->flag & RX_FLAG_SHORT_GI) | 2561 | if (status->flag & RX_FLAG_SHORT_GI) |
| 2557 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2562 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 2558 | } else { | 2563 | } else { |
| @@ -2560,10 +2565,15 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
| 2560 | int shift = 0; | 2565 | int shift = 0; |
| 2561 | int bitrate; | 2566 | int bitrate; |
| 2562 | 2567 | ||
| 2563 | if (status->flag & RX_FLAG_10MHZ) | 2568 | if (status->flag & RX_FLAG_10MHZ) { |
| 2564 | shift = 1; | 2569 | shift = 1; |
| 2565 | if (status->flag & RX_FLAG_5MHZ) | 2570 | ri.bw = RATE_INFO_BW_10; |
| 2571 | } else if (status->flag & RX_FLAG_5MHZ) { | ||
| 2566 | shift = 2; | 2572 | shift = 2; |
| 2573 | ri.bw = RATE_INFO_BW_5; | ||
| 2574 | } else { | ||
| 2575 | ri.bw = RATE_INFO_BW_20; | ||
| 2576 | } | ||
| 2567 | 2577 | ||
| 2568 | sband = local->hw.wiphy->bands[status->band]; | 2578 | sband = local->hw.wiphy->bands[status->band]; |
| 2569 | bitrate = sband->bitrates[status->rate_idx].bitrate; | 2579 | bitrate = sband->bitrates[status->rate_idx].bitrate; |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index bc9e8fc48785..85f9596da07b 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
| @@ -269,51 +269,54 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
| 269 | sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); | 269 | sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) | 272 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta) |
| 273 | { | 273 | { |
| 274 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 274 | struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; |
| 275 | u32 cap = sta->sta.vht_cap.cap; | 275 | u32 cap_width; |
| 276 | enum ieee80211_sta_rx_bandwidth bw; | ||
| 277 | 276 | ||
| 278 | if (!sta->sta.vht_cap.vht_supported) { | 277 | if (!vht_cap->vht_supported) |
| 279 | bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? | 278 | return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? |
| 280 | IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; | 279 | IEEE80211_STA_RX_BW_40 : |
| 281 | goto check_max; | 280 | IEEE80211_STA_RX_BW_20; |
| 282 | } | ||
| 283 | 281 | ||
| 284 | switch (sdata->vif.bss_conf.chandef.width) { | 282 | cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; |
| 285 | default: | 283 | |
| 286 | WARN_ON_ONCE(1); | 284 | if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ || |
| 287 | /* fall through */ | 285 | cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) |
| 286 | return IEEE80211_STA_RX_BW_160; | ||
| 287 | |||
| 288 | return IEEE80211_STA_RX_BW_80; | ||
| 289 | } | ||
| 290 | |||
| 291 | static enum ieee80211_sta_rx_bandwidth | ||
| 292 | ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) | ||
| 293 | { | ||
| 294 | switch (width) { | ||
| 288 | case NL80211_CHAN_WIDTH_20_NOHT: | 295 | case NL80211_CHAN_WIDTH_20_NOHT: |
| 289 | case NL80211_CHAN_WIDTH_20: | 296 | case NL80211_CHAN_WIDTH_20: |
| 290 | bw = IEEE80211_STA_RX_BW_20; | 297 | return IEEE80211_STA_RX_BW_20; |
| 291 | break; | ||
| 292 | case NL80211_CHAN_WIDTH_40: | 298 | case NL80211_CHAN_WIDTH_40: |
| 293 | bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? | 299 | return IEEE80211_STA_RX_BW_40; |
| 294 | IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; | 300 | case NL80211_CHAN_WIDTH_80: |
| 295 | break; | 301 | return IEEE80211_STA_RX_BW_80; |
| 296 | case NL80211_CHAN_WIDTH_160: | 302 | case NL80211_CHAN_WIDTH_160: |
| 297 | if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == | ||
| 298 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) { | ||
| 299 | bw = IEEE80211_STA_RX_BW_160; | ||
| 300 | break; | ||
| 301 | } | ||
| 302 | /* fall through */ | ||
| 303 | case NL80211_CHAN_WIDTH_80P80: | 303 | case NL80211_CHAN_WIDTH_80P80: |
| 304 | if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == | 304 | return IEEE80211_STA_RX_BW_160; |
| 305 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) { | 305 | default: |
| 306 | bw = IEEE80211_STA_RX_BW_160; | 306 | WARN_ON_ONCE(1); |
| 307 | break; | 307 | return IEEE80211_STA_RX_BW_20; |
| 308 | } | ||
| 309 | /* fall through */ | ||
| 310 | case NL80211_CHAN_WIDTH_80: | ||
| 311 | bw = IEEE80211_STA_RX_BW_80; | ||
| 312 | } | 308 | } |
| 309 | } | ||
| 310 | |||
| 311 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) | ||
| 312 | { | ||
| 313 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
| 314 | enum ieee80211_sta_rx_bandwidth bw; | ||
| 315 | |||
| 316 | bw = ieee80211_chan_width_to_rx_bw(sdata->vif.bss_conf.chandef.width); | ||
| 317 | bw = min(bw, ieee80211_sta_cap_rx_bw(sta)); | ||
| 318 | bw = min(bw, sta->cur_max_bandwidth); | ||
| 313 | 319 | ||
| 314 | check_max: | ||
| 315 | if (bw > sta->cur_max_bandwidth) | ||
| 316 | bw = sta->cur_max_bandwidth; | ||
| 317 | return bw; | 320 | return bw; |
| 318 | } | 321 | } |
| 319 | 322 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 53dda7728f86..3af0ecf1cc16 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -320,6 +320,20 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work) | |||
| 320 | rtnl_unlock(); | 320 | rtnl_unlock(); |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | static void cfg80211_sched_scan_stop_wk(struct work_struct *work) | ||
| 324 | { | ||
| 325 | struct cfg80211_registered_device *rdev; | ||
| 326 | |||
| 327 | rdev = container_of(work, struct cfg80211_registered_device, | ||
| 328 | sched_scan_stop_wk); | ||
| 329 | |||
| 330 | rtnl_lock(); | ||
| 331 | |||
| 332 | __cfg80211_stop_sched_scan(rdev, false); | ||
| 333 | |||
| 334 | rtnl_unlock(); | ||
| 335 | } | ||
| 336 | |||
| 323 | /* exported functions */ | 337 | /* exported functions */ |
| 324 | 338 | ||
| 325 | struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, | 339 | struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, |
| @@ -406,6 +420,7 @@ use_default_name: | |||
| 406 | INIT_LIST_HEAD(&rdev->destroy_list); | 420 | INIT_LIST_HEAD(&rdev->destroy_list); |
| 407 | spin_lock_init(&rdev->destroy_list_lock); | 421 | spin_lock_init(&rdev->destroy_list_lock); |
| 408 | INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk); | 422 | INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk); |
| 423 | INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); | ||
| 409 | 424 | ||
| 410 | #ifdef CONFIG_CFG80211_DEFAULT_PS | 425 | #ifdef CONFIG_CFG80211_DEFAULT_PS |
| 411 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; | 426 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| @@ -560,6 +575,14 @@ int wiphy_register(struct wiphy *wiphy) | |||
| 560 | BIT(NL80211_IFTYPE_MONITOR))) | 575 | BIT(NL80211_IFTYPE_MONITOR))) |
| 561 | wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; | 576 | wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; |
| 562 | 577 | ||
| 578 | if (WARN_ON((wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) && | ||
| 579 | (wiphy->regulatory_flags & | ||
| 580 | (REGULATORY_CUSTOM_REG | | ||
| 581 | REGULATORY_STRICT_REG | | ||
| 582 | REGULATORY_COUNTRY_IE_FOLLOW_POWER | | ||
| 583 | REGULATORY_COUNTRY_IE_IGNORE)))) | ||
| 584 | return -EINVAL; | ||
| 585 | |||
| 563 | if (WARN_ON(wiphy->coalesce && | 586 | if (WARN_ON(wiphy->coalesce && |
| 564 | (!wiphy->coalesce->n_rules || | 587 | (!wiphy->coalesce->n_rules || |
| 565 | !wiphy->coalesce->n_patterns) && | 588 | !wiphy->coalesce->n_patterns) && |
| @@ -778,6 +801,7 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
| 778 | flush_work(&rdev->event_work); | 801 | flush_work(&rdev->event_work); |
| 779 | cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); | 802 | cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); |
| 780 | flush_work(&rdev->destroy_work); | 803 | flush_work(&rdev->destroy_work); |
| 804 | flush_work(&rdev->sched_scan_stop_wk); | ||
| 781 | 805 | ||
| 782 | #ifdef CONFIG_PM | 806 | #ifdef CONFIG_PM |
| 783 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) | 807 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) |
| @@ -858,6 +882,7 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 858 | struct wireless_dev *wdev) | 882 | struct wireless_dev *wdev) |
| 859 | { | 883 | { |
| 860 | struct net_device *dev = wdev->netdev; | 884 | struct net_device *dev = wdev->netdev; |
| 885 | struct cfg80211_sched_scan_request *sched_scan_req; | ||
| 861 | 886 | ||
| 862 | ASSERT_RTNL(); | 887 | ASSERT_RTNL(); |
| 863 | ASSERT_WDEV_LOCK(wdev); | 888 | ASSERT_WDEV_LOCK(wdev); |
| @@ -868,7 +893,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 868 | break; | 893 | break; |
| 869 | case NL80211_IFTYPE_P2P_CLIENT: | 894 | case NL80211_IFTYPE_P2P_CLIENT: |
| 870 | case NL80211_IFTYPE_STATION: | 895 | case NL80211_IFTYPE_STATION: |
| 871 | if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev) | 896 | sched_scan_req = rtnl_dereference(rdev->sched_scan_req); |
| 897 | if (sched_scan_req && dev == sched_scan_req->dev) | ||
| 872 | __cfg80211_stop_sched_scan(rdev, false); | 898 | __cfg80211_stop_sched_scan(rdev, false); |
| 873 | 899 | ||
| 874 | #ifdef CONFIG_CFG80211_WEXT | 900 | #ifdef CONFIG_CFG80211_WEXT |
| @@ -943,6 +969,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
| 943 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | 969 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
| 944 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 970 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 945 | struct cfg80211_registered_device *rdev; | 971 | struct cfg80211_registered_device *rdev; |
| 972 | struct cfg80211_sched_scan_request *sched_scan_req; | ||
| 946 | 973 | ||
| 947 | if (!wdev) | 974 | if (!wdev) |
| 948 | return NOTIFY_DONE; | 975 | return NOTIFY_DONE; |
| @@ -1007,8 +1034,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
| 1007 | ___cfg80211_scan_done(rdev, false); | 1034 | ___cfg80211_scan_done(rdev, false); |
| 1008 | } | 1035 | } |
| 1009 | 1036 | ||
| 1010 | if (WARN_ON(rdev->sched_scan_req && | 1037 | sched_scan_req = rtnl_dereference(rdev->sched_scan_req); |
| 1011 | rdev->sched_scan_req->dev == wdev->netdev)) { | 1038 | if (WARN_ON(sched_scan_req && |
| 1039 | sched_scan_req->dev == wdev->netdev)) { | ||
| 1012 | __cfg80211_stop_sched_scan(rdev, false); | 1040 | __cfg80211_stop_sched_scan(rdev, false); |
| 1013 | } | 1041 | } |
| 1014 | 1042 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index faa5b1609aae..801cd49c5a0c 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -36,6 +36,13 @@ struct cfg80211_registered_device { | |||
| 36 | * the country on the country IE changed. */ | 36 | * the country on the country IE changed. */ |
| 37 | char country_ie_alpha2[2]; | 37 | char country_ie_alpha2[2]; |
| 38 | 38 | ||
| 39 | /* | ||
| 40 | * the driver requests the regulatory core to set this regulatory | ||
| 41 | * domain as the wiphy's. Only used for %REGULATORY_WIPHY_SELF_MANAGED | ||
| 42 | * devices using the regulatory_set_wiphy_regd() API | ||
| 43 | */ | ||
| 44 | const struct ieee80211_regdomain *requested_regd; | ||
| 45 | |||
| 39 | /* If a Country IE has been received this tells us the environment | 46 | /* If a Country IE has been received this tells us the environment |
| 40 | * which its telling us its in. This defaults to ENVIRON_ANY */ | 47 | * which its telling us its in. This defaults to ENVIRON_ANY */ |
| 41 | enum environment_cap env; | 48 | enum environment_cap env; |
| @@ -63,7 +70,7 @@ struct cfg80211_registered_device { | |||
| 63 | u32 bss_generation; | 70 | u32 bss_generation; |
| 64 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | 71 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ |
| 65 | struct sk_buff *scan_msg; | 72 | struct sk_buff *scan_msg; |
| 66 | struct cfg80211_sched_scan_request *sched_scan_req; | 73 | struct cfg80211_sched_scan_request __rcu *sched_scan_req; |
| 67 | unsigned long suspend_at; | 74 | unsigned long suspend_at; |
| 68 | struct work_struct scan_done_wk; | 75 | struct work_struct scan_done_wk; |
| 69 | struct work_struct sched_scan_results_wk; | 76 | struct work_struct sched_scan_results_wk; |
| @@ -84,6 +91,8 @@ struct cfg80211_registered_device { | |||
| 84 | struct list_head destroy_list; | 91 | struct list_head destroy_list; |
| 85 | struct work_struct destroy_work; | 92 | struct work_struct destroy_work; |
| 86 | 93 | ||
| 94 | struct work_struct sched_scan_stop_wk; | ||
| 95 | |||
| 87 | /* must be last because of the way we do wiphy_priv(), | 96 | /* must be last because of the way we do wiphy_priv(), |
| 88 | * and it should at least be aligned to NETDEV_ALIGN */ | 97 | * and it should at least be aligned to NETDEV_ALIGN */ |
| 89 | struct wiphy wiphy __aligned(NETDEV_ALIGN); | 98 | struct wiphy wiphy __aligned(NETDEV_ALIGN); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7ca4b5133123..c5661c5ad8f3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -59,13 +59,13 @@ enum nl80211_multicast_groups { | |||
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | static const struct genl_multicast_group nl80211_mcgrps[] = { | 61 | static const struct genl_multicast_group nl80211_mcgrps[] = { |
| 62 | [NL80211_MCGRP_CONFIG] = { .name = "config", }, | 62 | [NL80211_MCGRP_CONFIG] = { .name = NL80211_MULTICAST_GROUP_CONFIG }, |
| 63 | [NL80211_MCGRP_SCAN] = { .name = "scan", }, | 63 | [NL80211_MCGRP_SCAN] = { .name = NL80211_MULTICAST_GROUP_SCAN }, |
| 64 | [NL80211_MCGRP_REGULATORY] = { .name = "regulatory", }, | 64 | [NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG }, |
| 65 | [NL80211_MCGRP_MLME] = { .name = "mlme", }, | 65 | [NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME }, |
| 66 | [NL80211_MCGRP_VENDOR] = { .name = "vendor", }, | 66 | [NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR }, |
| 67 | #ifdef CONFIG_NL80211_TESTMODE | 67 | #ifdef CONFIG_NL80211_TESTMODE |
| 68 | [NL80211_MCGRP_TESTMODE] = { .name = "testmode", } | 68 | [NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE } |
| 69 | #endif | 69 | #endif |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| @@ -396,6 +396,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
| 396 | [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 }, | 396 | [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 }, |
| 397 | [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, | 397 | [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, |
| 398 | [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN }, | 398 | [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN }, |
| 399 | [NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG }, | ||
| 399 | }; | 400 | }; |
| 400 | 401 | ||
| 401 | /* policy for the key attributes */ | 402 | /* policy for the key attributes */ |
| @@ -1087,6 +1088,11 @@ static int nl80211_send_wowlan(struct sk_buff *msg, | |||
| 1087 | return -ENOBUFS; | 1088 | return -ENOBUFS; |
| 1088 | } | 1089 | } |
| 1089 | 1090 | ||
| 1091 | if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) && | ||
| 1092 | nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT, | ||
| 1093 | rdev->wiphy.wowlan->max_nd_match_sets)) | ||
| 1094 | return -ENOBUFS; | ||
| 1095 | |||
| 1090 | if (large && nl80211_send_wowlan_tcp_caps(rdev, msg)) | 1096 | if (large && nl80211_send_wowlan_tcp_caps(rdev, msg)) |
| 1091 | return -ENOBUFS; | 1097 | return -ENOBUFS; |
| 1092 | 1098 | ||
| @@ -1701,6 +1707,15 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, | |||
| 1701 | rdev->wiphy.max_num_csa_counters)) | 1707 | rdev->wiphy.max_num_csa_counters)) |
| 1702 | goto nla_put_failure; | 1708 | goto nla_put_failure; |
| 1703 | 1709 | ||
| 1710 | if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED && | ||
| 1711 | nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG)) | ||
| 1712 | goto nla_put_failure; | ||
| 1713 | |||
| 1714 | if (nla_put(msg, NL80211_ATTR_EXT_FEATURES, | ||
| 1715 | sizeof(rdev->wiphy.ext_features), | ||
| 1716 | rdev->wiphy.ext_features)) | ||
| 1717 | goto nla_put_failure; | ||
| 1718 | |||
| 1704 | /* done */ | 1719 | /* done */ |
| 1705 | state->split_start = 0; | 1720 | state->split_start = 0; |
| 1706 | break; | 1721 | break; |
| @@ -3563,6 +3578,7 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
| 3563 | struct nlattr *rate; | 3578 | struct nlattr *rate; |
| 3564 | u32 bitrate; | 3579 | u32 bitrate; |
| 3565 | u16 bitrate_compat; | 3580 | u16 bitrate_compat; |
| 3581 | enum nl80211_attrs rate_flg; | ||
| 3566 | 3582 | ||
| 3567 | rate = nla_nest_start(msg, attr); | 3583 | rate = nla_nest_start(msg, attr); |
| 3568 | if (!rate) | 3584 | if (!rate) |
| @@ -3579,12 +3595,36 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
| 3579 | nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) | 3595 | nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) |
| 3580 | return false; | 3596 | return false; |
| 3581 | 3597 | ||
| 3598 | switch (info->bw) { | ||
| 3599 | case RATE_INFO_BW_5: | ||
| 3600 | rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH; | ||
| 3601 | break; | ||
| 3602 | case RATE_INFO_BW_10: | ||
| 3603 | rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH; | ||
| 3604 | break; | ||
| 3605 | default: | ||
| 3606 | WARN_ON(1); | ||
| 3607 | /* fall through */ | ||
| 3608 | case RATE_INFO_BW_20: | ||
| 3609 | rate_flg = 0; | ||
| 3610 | break; | ||
| 3611 | case RATE_INFO_BW_40: | ||
| 3612 | rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH; | ||
| 3613 | break; | ||
| 3614 | case RATE_INFO_BW_80: | ||
| 3615 | rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH; | ||
| 3616 | break; | ||
| 3617 | case RATE_INFO_BW_160: | ||
| 3618 | rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH; | ||
| 3619 | break; | ||
| 3620 | } | ||
| 3621 | |||
| 3622 | if (rate_flg && nla_put_flag(msg, rate_flg)) | ||
| 3623 | return false; | ||
| 3624 | |||
| 3582 | if (info->flags & RATE_INFO_FLAGS_MCS) { | 3625 | if (info->flags & RATE_INFO_FLAGS_MCS) { |
| 3583 | if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) | 3626 | if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) |
| 3584 | return false; | 3627 | return false; |
| 3585 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && | ||
| 3586 | nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) | ||
| 3587 | return false; | ||
| 3588 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && | 3628 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && |
| 3589 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) | 3629 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) |
| 3590 | return false; | 3630 | return false; |
| @@ -3593,18 +3633,6 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
| 3593 | return false; | 3633 | return false; |
| 3594 | if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss)) | 3634 | if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss)) |
| 3595 | return false; | 3635 | return false; |
| 3596 | if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && | ||
| 3597 | nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) | ||
| 3598 | return false; | ||
| 3599 | if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH && | ||
| 3600 | nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH)) | ||
| 3601 | return false; | ||
| 3602 | if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH && | ||
| 3603 | nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH)) | ||
| 3604 | return false; | ||
| 3605 | if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH && | ||
| 3606 | nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH)) | ||
| 3607 | return false; | ||
| 3608 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && | 3636 | if (info->flags & RATE_INFO_FLAGS_SHORT_GI && |
| 3609 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) | 3637 | nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) |
| 3610 | return false; | 3638 | return false; |
| @@ -3640,8 +3668,8 @@ static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal, | |||
| 3640 | return true; | 3668 | return true; |
| 3641 | } | 3669 | } |
| 3642 | 3670 | ||
| 3643 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | 3671 | static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, |
| 3644 | int flags, | 3672 | u32 seq, int flags, |
| 3645 | struct cfg80211_registered_device *rdev, | 3673 | struct cfg80211_registered_device *rdev, |
| 3646 | struct net_device *dev, | 3674 | struct net_device *dev, |
| 3647 | const u8 *mac_addr, struct station_info *sinfo) | 3675 | const u8 *mac_addr, struct station_info *sinfo) |
| @@ -3649,7 +3677,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
| 3649 | void *hdr; | 3677 | void *hdr; |
| 3650 | struct nlattr *sinfoattr, *bss_param; | 3678 | struct nlattr *sinfoattr, *bss_param; |
| 3651 | 3679 | ||
| 3652 | hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION); | 3680 | hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); |
| 3653 | if (!hdr) | 3681 | if (!hdr) |
| 3654 | return -1; | 3682 | return -1; |
| 3655 | 3683 | ||
| @@ -3661,115 +3689,77 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
| 3661 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); | 3689 | sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); |
| 3662 | if (!sinfoattr) | 3690 | if (!sinfoattr) |
| 3663 | goto nla_put_failure; | 3691 | goto nla_put_failure; |
| 3664 | if ((sinfo->filled & STATION_INFO_CONNECTED_TIME) && | 3692 | |
| 3665 | nla_put_u32(msg, NL80211_STA_INFO_CONNECTED_TIME, | 3693 | #define PUT_SINFO(attr, memb, type) do { \ |
| 3666 | sinfo->connected_time)) | 3694 | if (sinfo->filled & BIT(NL80211_STA_INFO_ ## attr) && \ |
| 3667 | goto nla_put_failure; | 3695 | nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \ |
| 3668 | if ((sinfo->filled & STATION_INFO_INACTIVE_TIME) && | 3696 | sinfo->memb)) \ |
| 3669 | nla_put_u32(msg, NL80211_STA_INFO_INACTIVE_TIME, | 3697 | goto nla_put_failure; \ |
| 3670 | sinfo->inactive_time)) | 3698 | } while (0) |
| 3671 | goto nla_put_failure; | 3699 | |
| 3672 | if ((sinfo->filled & (STATION_INFO_RX_BYTES | | 3700 | PUT_SINFO(CONNECTED_TIME, connected_time, u32); |
| 3673 | STATION_INFO_RX_BYTES64)) && | 3701 | PUT_SINFO(INACTIVE_TIME, inactive_time, u32); |
| 3702 | |||
| 3703 | if (sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES) | | ||
| 3704 | BIT(NL80211_STA_INFO_RX_BYTES64)) && | ||
| 3674 | nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, | 3705 | nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, |
| 3675 | (u32)sinfo->rx_bytes)) | 3706 | (u32)sinfo->rx_bytes)) |
| 3676 | goto nla_put_failure; | 3707 | goto nla_put_failure; |
| 3677 | if ((sinfo->filled & (STATION_INFO_TX_BYTES | | 3708 | |
| 3678 | STATION_INFO_TX_BYTES64)) && | 3709 | if (sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES) | |
| 3710 | BIT(NL80211_STA_INFO_TX_BYTES64)) && | ||
| 3679 | nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, | 3711 | nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, |
| 3680 | (u32)sinfo->tx_bytes)) | 3712 | (u32)sinfo->tx_bytes)) |
| 3681 | goto nla_put_failure; | 3713 | goto nla_put_failure; |
| 3682 | if ((sinfo->filled & STATION_INFO_RX_BYTES64) && | 3714 | |
| 3683 | nla_put_u64(msg, NL80211_STA_INFO_RX_BYTES64, | 3715 | PUT_SINFO(RX_BYTES64, rx_bytes, u64); |
| 3684 | sinfo->rx_bytes)) | 3716 | PUT_SINFO(TX_BYTES64, tx_bytes, u64); |
| 3685 | goto nla_put_failure; | 3717 | PUT_SINFO(LLID, llid, u16); |
| 3686 | if ((sinfo->filled & STATION_INFO_TX_BYTES64) && | 3718 | PUT_SINFO(PLID, plid, u16); |
| 3687 | nla_put_u64(msg, NL80211_STA_INFO_TX_BYTES64, | 3719 | PUT_SINFO(PLINK_STATE, plink_state, u8); |
| 3688 | sinfo->tx_bytes)) | 3720 | |
| 3689 | goto nla_put_failure; | ||
| 3690 | if ((sinfo->filled & STATION_INFO_LLID) && | ||
| 3691 | nla_put_u16(msg, NL80211_STA_INFO_LLID, sinfo->llid)) | ||
| 3692 | goto nla_put_failure; | ||
| 3693 | if ((sinfo->filled & STATION_INFO_PLID) && | ||
| 3694 | nla_put_u16(msg, NL80211_STA_INFO_PLID, sinfo->plid)) | ||
| 3695 | goto nla_put_failure; | ||
| 3696 | if ((sinfo->filled & STATION_INFO_PLINK_STATE) && | ||
| 3697 | nla_put_u8(msg, NL80211_STA_INFO_PLINK_STATE, | ||
| 3698 | sinfo->plink_state)) | ||
| 3699 | goto nla_put_failure; | ||
| 3700 | switch (rdev->wiphy.signal_type) { | 3721 | switch (rdev->wiphy.signal_type) { |
| 3701 | case CFG80211_SIGNAL_TYPE_MBM: | 3722 | case CFG80211_SIGNAL_TYPE_MBM: |
| 3702 | if ((sinfo->filled & STATION_INFO_SIGNAL) && | 3723 | PUT_SINFO(SIGNAL, signal, u8); |
| 3703 | nla_put_u8(msg, NL80211_STA_INFO_SIGNAL, | 3724 | PUT_SINFO(SIGNAL_AVG, signal_avg, u8); |
| 3704 | sinfo->signal)) | ||
| 3705 | goto nla_put_failure; | ||
| 3706 | if ((sinfo->filled & STATION_INFO_SIGNAL_AVG) && | ||
| 3707 | nla_put_u8(msg, NL80211_STA_INFO_SIGNAL_AVG, | ||
| 3708 | sinfo->signal_avg)) | ||
| 3709 | goto nla_put_failure; | ||
| 3710 | break; | 3725 | break; |
| 3711 | default: | 3726 | default: |
| 3712 | break; | 3727 | break; |
| 3713 | } | 3728 | } |
| 3714 | if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) { | 3729 | if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL)) { |
| 3715 | if (!nl80211_put_signal(msg, sinfo->chains, | 3730 | if (!nl80211_put_signal(msg, sinfo->chains, |
| 3716 | sinfo->chain_signal, | 3731 | sinfo->chain_signal, |
| 3717 | NL80211_STA_INFO_CHAIN_SIGNAL)) | 3732 | NL80211_STA_INFO_CHAIN_SIGNAL)) |
| 3718 | goto nla_put_failure; | 3733 | goto nla_put_failure; |
| 3719 | } | 3734 | } |
| 3720 | if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) { | 3735 | if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) { |
| 3721 | if (!nl80211_put_signal(msg, sinfo->chains, | 3736 | if (!nl80211_put_signal(msg, sinfo->chains, |
| 3722 | sinfo->chain_signal_avg, | 3737 | sinfo->chain_signal_avg, |
| 3723 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) | 3738 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) |
| 3724 | goto nla_put_failure; | 3739 | goto nla_put_failure; |
| 3725 | } | 3740 | } |
| 3726 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { | 3741 | if (sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE)) { |
| 3727 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, | 3742 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, |
| 3728 | NL80211_STA_INFO_TX_BITRATE)) | 3743 | NL80211_STA_INFO_TX_BITRATE)) |
| 3729 | goto nla_put_failure; | 3744 | goto nla_put_failure; |
| 3730 | } | 3745 | } |
| 3731 | if (sinfo->filled & STATION_INFO_RX_BITRATE) { | 3746 | if (sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE)) { |
| 3732 | if (!nl80211_put_sta_rate(msg, &sinfo->rxrate, | 3747 | if (!nl80211_put_sta_rate(msg, &sinfo->rxrate, |
| 3733 | NL80211_STA_INFO_RX_BITRATE)) | 3748 | NL80211_STA_INFO_RX_BITRATE)) |
| 3734 | goto nla_put_failure; | 3749 | goto nla_put_failure; |
| 3735 | } | 3750 | } |
| 3736 | if ((sinfo->filled & STATION_INFO_RX_PACKETS) && | 3751 | |
| 3737 | nla_put_u32(msg, NL80211_STA_INFO_RX_PACKETS, | 3752 | PUT_SINFO(RX_PACKETS, rx_packets, u32); |
| 3738 | sinfo->rx_packets)) | 3753 | PUT_SINFO(TX_PACKETS, tx_packets, u32); |
| 3739 | goto nla_put_failure; | 3754 | PUT_SINFO(TX_RETRIES, tx_retries, u32); |
| 3740 | if ((sinfo->filled & STATION_INFO_TX_PACKETS) && | 3755 | PUT_SINFO(TX_FAILED, tx_failed, u32); |
| 3741 | nla_put_u32(msg, NL80211_STA_INFO_TX_PACKETS, | 3756 | PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32); |
| 3742 | sinfo->tx_packets)) | 3757 | PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32); |
| 3743 | goto nla_put_failure; | 3758 | PUT_SINFO(LOCAL_PM, local_pm, u32); |
| 3744 | if ((sinfo->filled & STATION_INFO_TX_RETRIES) && | 3759 | PUT_SINFO(PEER_PM, peer_pm, u32); |
| 3745 | nla_put_u32(msg, NL80211_STA_INFO_TX_RETRIES, | 3760 | PUT_SINFO(NONPEER_PM, nonpeer_pm, u32); |
| 3746 | sinfo->tx_retries)) | 3761 | |
| 3747 | goto nla_put_failure; | 3762 | if (sinfo->filled & BIT(NL80211_STA_INFO_BSS_PARAM)) { |
| 3748 | if ((sinfo->filled & STATION_INFO_TX_FAILED) && | ||
| 3749 | nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED, | ||
| 3750 | sinfo->tx_failed)) | ||
| 3751 | goto nla_put_failure; | ||
| 3752 | if ((sinfo->filled & STATION_INFO_EXPECTED_THROUGHPUT) && | ||
| 3753 | nla_put_u32(msg, NL80211_STA_INFO_EXPECTED_THROUGHPUT, | ||
| 3754 | sinfo->expected_throughput)) | ||
| 3755 | goto nla_put_failure; | ||
| 3756 | if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) && | ||
| 3757 | nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, | ||
| 3758 | sinfo->beacon_loss_count)) | ||
| 3759 | goto nla_put_failure; | ||
| 3760 | if ((sinfo->filled & STATION_INFO_LOCAL_PM) && | ||
| 3761 | nla_put_u32(msg, NL80211_STA_INFO_LOCAL_PM, | ||
| 3762 | sinfo->local_pm)) | ||
| 3763 | goto nla_put_failure; | ||
| 3764 | if ((sinfo->filled & STATION_INFO_PEER_PM) && | ||
| 3765 | nla_put_u32(msg, NL80211_STA_INFO_PEER_PM, | ||
| 3766 | sinfo->peer_pm)) | ||
| 3767 | goto nla_put_failure; | ||
| 3768 | if ((sinfo->filled & STATION_INFO_NONPEER_PM) && | ||
| 3769 | nla_put_u32(msg, NL80211_STA_INFO_NONPEER_PM, | ||
| 3770 | sinfo->nonpeer_pm)) | ||
| 3771 | goto nla_put_failure; | ||
| 3772 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { | ||
| 3773 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); | 3763 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); |
| 3774 | if (!bss_param) | 3764 | if (!bss_param) |
| 3775 | goto nla_put_failure; | 3765 | goto nla_put_failure; |
| @@ -3788,18 +3778,62 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
| 3788 | 3778 | ||
| 3789 | nla_nest_end(msg, bss_param); | 3779 | nla_nest_end(msg, bss_param); |
| 3790 | } | 3780 | } |
| 3791 | if ((sinfo->filled & STATION_INFO_STA_FLAGS) && | 3781 | if ((sinfo->filled & BIT(NL80211_STA_INFO_STA_FLAGS)) && |
| 3792 | nla_put(msg, NL80211_STA_INFO_STA_FLAGS, | 3782 | nla_put(msg, NL80211_STA_INFO_STA_FLAGS, |
| 3793 | sizeof(struct nl80211_sta_flag_update), | 3783 | sizeof(struct nl80211_sta_flag_update), |
| 3794 | &sinfo->sta_flags)) | 3784 | &sinfo->sta_flags)) |
| 3795 | goto nla_put_failure; | 3785 | goto nla_put_failure; |
| 3796 | if ((sinfo->filled & STATION_INFO_T_OFFSET) && | 3786 | |
| 3797 | nla_put_u64(msg, NL80211_STA_INFO_T_OFFSET, | 3787 | PUT_SINFO(T_OFFSET, t_offset, u64); |
| 3798 | sinfo->t_offset)) | 3788 | PUT_SINFO(RX_DROP_MISC, rx_dropped_misc, u64); |
| 3799 | goto nla_put_failure; | 3789 | PUT_SINFO(BEACON_RX, rx_beacon, u64); |
| 3790 | PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8); | ||
| 3791 | |||
| 3792 | #undef PUT_SINFO | ||
| 3793 | |||
| 3794 | if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) { | ||
| 3795 | struct nlattr *tidsattr; | ||
| 3796 | int tid; | ||
| 3797 | |||
| 3798 | tidsattr = nla_nest_start(msg, NL80211_STA_INFO_TID_STATS); | ||
| 3799 | if (!tidsattr) | ||
| 3800 | goto nla_put_failure; | ||
| 3801 | |||
| 3802 | for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) { | ||
| 3803 | struct cfg80211_tid_stats *tidstats; | ||
| 3804 | struct nlattr *tidattr; | ||
| 3805 | |||
| 3806 | tidstats = &sinfo->pertid[tid]; | ||
| 3807 | |||
| 3808 | if (!tidstats->filled) | ||
| 3809 | continue; | ||
| 3810 | |||
| 3811 | tidattr = nla_nest_start(msg, tid + 1); | ||
| 3812 | if (!tidattr) | ||
| 3813 | goto nla_put_failure; | ||
| 3814 | |||
| 3815 | #define PUT_TIDVAL(attr, memb, type) do { \ | ||
| 3816 | if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \ | ||
| 3817 | nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr, \ | ||
| 3818 | tidstats->memb)) \ | ||
| 3819 | goto nla_put_failure; \ | ||
| 3820 | } while (0) | ||
| 3821 | |||
| 3822 | PUT_TIDVAL(RX_MSDU, rx_msdu, u64); | ||
| 3823 | PUT_TIDVAL(TX_MSDU, tx_msdu, u64); | ||
| 3824 | PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64); | ||
| 3825 | PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64); | ||
| 3826 | |||
| 3827 | #undef PUT_TIDVAL | ||
| 3828 | nla_nest_end(msg, tidattr); | ||
| 3829 | } | ||
| 3830 | |||
| 3831 | nla_nest_end(msg, tidsattr); | ||
| 3832 | } | ||
| 3833 | |||
| 3800 | nla_nest_end(msg, sinfoattr); | 3834 | nla_nest_end(msg, sinfoattr); |
| 3801 | 3835 | ||
| 3802 | if ((sinfo->filled & STATION_INFO_ASSOC_REQ_IES) && | 3836 | if (sinfo->assoc_req_ies_len && |
| 3803 | nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, | 3837 | nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, |
| 3804 | sinfo->assoc_req_ies)) | 3838 | sinfo->assoc_req_ies)) |
| 3805 | goto nla_put_failure; | 3839 | goto nla_put_failure; |
| @@ -3844,7 +3878,7 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
| 3844 | if (err) | 3878 | if (err) |
| 3845 | goto out_err; | 3879 | goto out_err; |
| 3846 | 3880 | ||
| 3847 | if (nl80211_send_station(skb, | 3881 | if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION, |
| 3848 | NETLINK_CB(cb->skb).portid, | 3882 | NETLINK_CB(cb->skb).portid, |
| 3849 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 3883 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 3850 | rdev, wdev->netdev, mac_addr, | 3884 | rdev, wdev->netdev, mac_addr, |
| @@ -3891,7 +3925,8 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
| 3891 | if (!msg) | 3925 | if (!msg) |
| 3892 | return -ENOMEM; | 3926 | return -ENOMEM; |
| 3893 | 3927 | ||
| 3894 | if (nl80211_send_station(msg, info->snd_portid, info->snd_seq, 0, | 3928 | if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, |
| 3929 | info->snd_portid, info->snd_seq, 0, | ||
| 3895 | rdev, dev, mac_addr, &sinfo) < 0) { | 3930 | rdev, dev, mac_addr, &sinfo) < 0) { |
| 3896 | nlmsg_free(msg); | 3931 | nlmsg_free(msg); |
| 3897 | return -ENOBUFS; | 3932 | return -ENOBUFS; |
| @@ -5327,42 +5362,20 @@ static int nl80211_update_mesh_config(struct sk_buff *skb, | |||
| 5327 | return err; | 5362 | return err; |
| 5328 | } | 5363 | } |
| 5329 | 5364 | ||
| 5330 | static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | 5365 | static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom, |
| 5366 | struct sk_buff *msg) | ||
| 5331 | { | 5367 | { |
| 5332 | const struct ieee80211_regdomain *regdom; | ||
| 5333 | struct sk_buff *msg; | ||
| 5334 | void *hdr = NULL; | ||
| 5335 | struct nlattr *nl_reg_rules; | 5368 | struct nlattr *nl_reg_rules; |
| 5336 | unsigned int i; | 5369 | unsigned int i; |
| 5337 | 5370 | ||
| 5338 | if (!cfg80211_regdomain) | ||
| 5339 | return -EINVAL; | ||
| 5340 | |||
| 5341 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 5342 | if (!msg) | ||
| 5343 | return -ENOBUFS; | ||
| 5344 | |||
| 5345 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | ||
| 5346 | NL80211_CMD_GET_REG); | ||
| 5347 | if (!hdr) | ||
| 5348 | goto put_failure; | ||
| 5349 | |||
| 5350 | if (reg_last_request_cell_base() && | ||
| 5351 | nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE, | ||
| 5352 | NL80211_USER_REG_HINT_CELL_BASE)) | ||
| 5353 | goto nla_put_failure; | ||
| 5354 | |||
| 5355 | rcu_read_lock(); | ||
| 5356 | regdom = rcu_dereference(cfg80211_regdomain); | ||
| 5357 | |||
| 5358 | if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) || | 5371 | if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) || |
| 5359 | (regdom->dfs_region && | 5372 | (regdom->dfs_region && |
| 5360 | nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region))) | 5373 | nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region))) |
| 5361 | goto nla_put_failure_rcu; | 5374 | goto nla_put_failure; |
| 5362 | 5375 | ||
| 5363 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); | 5376 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); |
| 5364 | if (!nl_reg_rules) | 5377 | if (!nl_reg_rules) |
| 5365 | goto nla_put_failure_rcu; | 5378 | goto nla_put_failure; |
| 5366 | 5379 | ||
| 5367 | for (i = 0; i < regdom->n_reg_rules; i++) { | 5380 | for (i = 0; i < regdom->n_reg_rules; i++) { |
| 5368 | struct nlattr *nl_reg_rule; | 5381 | struct nlattr *nl_reg_rule; |
| @@ -5377,7 +5390,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
| 5377 | 5390 | ||
| 5378 | nl_reg_rule = nla_nest_start(msg, i); | 5391 | nl_reg_rule = nla_nest_start(msg, i); |
| 5379 | if (!nl_reg_rule) | 5392 | if (!nl_reg_rule) |
| 5380 | goto nla_put_failure_rcu; | 5393 | goto nla_put_failure; |
| 5381 | 5394 | ||
| 5382 | max_bandwidth_khz = freq_range->max_bandwidth_khz; | 5395 | max_bandwidth_khz = freq_range->max_bandwidth_khz; |
| 5383 | if (!max_bandwidth_khz) | 5396 | if (!max_bandwidth_khz) |
| @@ -5398,13 +5411,74 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
| 5398 | power_rule->max_eirp) || | 5411 | power_rule->max_eirp) || |
| 5399 | nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME, | 5412 | nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME, |
| 5400 | reg_rule->dfs_cac_ms)) | 5413 | reg_rule->dfs_cac_ms)) |
| 5401 | goto nla_put_failure_rcu; | 5414 | goto nla_put_failure; |
| 5402 | 5415 | ||
| 5403 | nla_nest_end(msg, nl_reg_rule); | 5416 | nla_nest_end(msg, nl_reg_rule); |
| 5404 | } | 5417 | } |
| 5405 | rcu_read_unlock(); | ||
| 5406 | 5418 | ||
| 5407 | nla_nest_end(msg, nl_reg_rules); | 5419 | nla_nest_end(msg, nl_reg_rules); |
| 5420 | return 0; | ||
| 5421 | |||
| 5422 | nla_put_failure: | ||
| 5423 | return -EMSGSIZE; | ||
| 5424 | } | ||
| 5425 | |||
| 5426 | static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info) | ||
| 5427 | { | ||
| 5428 | const struct ieee80211_regdomain *regdom = NULL; | ||
| 5429 | struct cfg80211_registered_device *rdev; | ||
| 5430 | struct wiphy *wiphy = NULL; | ||
| 5431 | struct sk_buff *msg; | ||
| 5432 | void *hdr; | ||
| 5433 | |||
| 5434 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 5435 | if (!msg) | ||
| 5436 | return -ENOBUFS; | ||
| 5437 | |||
| 5438 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | ||
| 5439 | NL80211_CMD_GET_REG); | ||
| 5440 | if (!hdr) | ||
| 5441 | goto put_failure; | ||
| 5442 | |||
| 5443 | if (info->attrs[NL80211_ATTR_WIPHY]) { | ||
| 5444 | bool self_managed; | ||
| 5445 | |||
| 5446 | rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); | ||
| 5447 | if (IS_ERR(rdev)) { | ||
| 5448 | nlmsg_free(msg); | ||
| 5449 | return PTR_ERR(rdev); | ||
| 5450 | } | ||
| 5451 | |||
| 5452 | wiphy = &rdev->wiphy; | ||
| 5453 | self_managed = wiphy->regulatory_flags & | ||
| 5454 | REGULATORY_WIPHY_SELF_MANAGED; | ||
| 5455 | regdom = get_wiphy_regdom(wiphy); | ||
| 5456 | |||
| 5457 | /* a self-managed-reg device must have a private regdom */ | ||
| 5458 | if (WARN_ON(!regdom && self_managed)) { | ||
| 5459 | nlmsg_free(msg); | ||
| 5460 | return -EINVAL; | ||
| 5461 | } | ||
| 5462 | |||
| 5463 | if (regdom && | ||
| 5464 | nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) | ||
| 5465 | goto nla_put_failure; | ||
| 5466 | } | ||
| 5467 | |||
| 5468 | if (!wiphy && reg_last_request_cell_base() && | ||
| 5469 | nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE, | ||
| 5470 | NL80211_USER_REG_HINT_CELL_BASE)) | ||
| 5471 | goto nla_put_failure; | ||
| 5472 | |||
| 5473 | rcu_read_lock(); | ||
| 5474 | |||
| 5475 | if (!regdom) | ||
| 5476 | regdom = rcu_dereference(cfg80211_regdomain); | ||
| 5477 | |||
| 5478 | if (nl80211_put_regdom(regdom, msg)) | ||
| 5479 | goto nla_put_failure_rcu; | ||
| 5480 | |||
| 5481 | rcu_read_unlock(); | ||
| 5408 | 5482 | ||
| 5409 | genlmsg_end(msg, hdr); | 5483 | genlmsg_end(msg, hdr); |
| 5410 | return genlmsg_reply(msg, info); | 5484 | return genlmsg_reply(msg, info); |
| @@ -5418,6 +5492,83 @@ put_failure: | |||
| 5418 | return -EMSGSIZE; | 5492 | return -EMSGSIZE; |
| 5419 | } | 5493 | } |
| 5420 | 5494 | ||
| 5495 | static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb, | ||
| 5496 | u32 seq, int flags, struct wiphy *wiphy, | ||
| 5497 | const struct ieee80211_regdomain *regdom) | ||
| 5498 | { | ||
| 5499 | void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags, | ||
| 5500 | NL80211_CMD_GET_REG); | ||
| 5501 | |||
| 5502 | if (!hdr) | ||
| 5503 | return -1; | ||
| 5504 | |||
| 5505 | genl_dump_check_consistent(cb, hdr, &nl80211_fam); | ||
| 5506 | |||
| 5507 | if (nl80211_put_regdom(regdom, msg)) | ||
| 5508 | goto nla_put_failure; | ||
| 5509 | |||
| 5510 | if (!wiphy && reg_last_request_cell_base() && | ||
| 5511 | nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE, | ||
| 5512 | NL80211_USER_REG_HINT_CELL_BASE)) | ||
| 5513 | goto nla_put_failure; | ||
| 5514 | |||
| 5515 | if (wiphy && | ||
| 5516 | nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy))) | ||
| 5517 | goto nla_put_failure; | ||
| 5518 | |||
| 5519 | if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED && | ||
| 5520 | nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG)) | ||
| 5521 | goto nla_put_failure; | ||
| 5522 | |||
| 5523 | return genlmsg_end(msg, hdr); | ||
| 5524 | |||
| 5525 | nla_put_failure: | ||
| 5526 | genlmsg_cancel(msg, hdr); | ||
| 5527 | return -EMSGSIZE; | ||
| 5528 | } | ||
| 5529 | |||
| 5530 | static int nl80211_get_reg_dump(struct sk_buff *skb, | ||
| 5531 | struct netlink_callback *cb) | ||
| 5532 | { | ||
| 5533 | const struct ieee80211_regdomain *regdom = NULL; | ||
| 5534 | struct cfg80211_registered_device *rdev; | ||
| 5535 | int err, reg_idx, start = cb->args[2]; | ||
| 5536 | |||
| 5537 | rtnl_lock(); | ||
| 5538 | |||
| 5539 | if (cfg80211_regdomain && start == 0) { | ||
| 5540 | err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq, | ||
| 5541 | NLM_F_MULTI, NULL, | ||
| 5542 | rtnl_dereference(cfg80211_regdomain)); | ||
| 5543 | if (err < 0) | ||
| 5544 | goto out_err; | ||
| 5545 | } | ||
| 5546 | |||
| 5547 | /* the global regdom is idx 0 */ | ||
| 5548 | reg_idx = 1; | ||
| 5549 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
| 5550 | regdom = get_wiphy_regdom(&rdev->wiphy); | ||
| 5551 | if (!regdom) | ||
| 5552 | continue; | ||
| 5553 | |||
| 5554 | if (++reg_idx <= start) | ||
| 5555 | continue; | ||
| 5556 | |||
| 5557 | err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq, | ||
| 5558 | NLM_F_MULTI, &rdev->wiphy, regdom); | ||
| 5559 | if (err < 0) { | ||
| 5560 | reg_idx--; | ||
| 5561 | break; | ||
| 5562 | } | ||
| 5563 | } | ||
| 5564 | |||
| 5565 | cb->args[2] = reg_idx; | ||
| 5566 | err = skb->len; | ||
| 5567 | out_err: | ||
| 5568 | rtnl_unlock(); | ||
| 5569 | return err; | ||
| 5570 | } | ||
| 5571 | |||
| 5421 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 5572 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
| 5422 | { | 5573 | { |
| 5423 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; | 5574 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; |
| @@ -6069,6 +6220,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
| 6069 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6220 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 6070 | struct net_device *dev = info->user_ptr[1]; | 6221 | struct net_device *dev = info->user_ptr[1]; |
| 6071 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 6222 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 6223 | struct cfg80211_sched_scan_request *sched_scan_req; | ||
| 6072 | int err; | 6224 | int err; |
| 6073 | 6225 | ||
| 6074 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | 6226 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || |
| @@ -6078,27 +6230,32 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
| 6078 | if (rdev->sched_scan_req) | 6230 | if (rdev->sched_scan_req) |
| 6079 | return -EINPROGRESS; | 6231 | return -EINPROGRESS; |
| 6080 | 6232 | ||
| 6081 | rdev->sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev, | 6233 | sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev, |
| 6082 | info->attrs); | 6234 | info->attrs); |
| 6083 | err = PTR_ERR_OR_ZERO(rdev->sched_scan_req); | 6235 | |
| 6236 | err = PTR_ERR_OR_ZERO(sched_scan_req); | ||
| 6084 | if (err) | 6237 | if (err) |
| 6085 | goto out_err; | 6238 | goto out_err; |
| 6086 | 6239 | ||
| 6087 | err = rdev_sched_scan_start(rdev, dev, rdev->sched_scan_req); | 6240 | err = rdev_sched_scan_start(rdev, dev, sched_scan_req); |
| 6088 | if (err) | 6241 | if (err) |
| 6089 | goto out_free; | 6242 | goto out_free; |
| 6090 | 6243 | ||
| 6091 | rdev->sched_scan_req->dev = dev; | 6244 | sched_scan_req->dev = dev; |
| 6092 | rdev->sched_scan_req->wiphy = &rdev->wiphy; | 6245 | sched_scan_req->wiphy = &rdev->wiphy; |
| 6246 | |||
| 6247 | if (info->attrs[NL80211_ATTR_SOCKET_OWNER]) | ||
| 6248 | sched_scan_req->owner_nlportid = info->snd_portid; | ||
| 6249 | |||
| 6250 | rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req); | ||
| 6093 | 6251 | ||
| 6094 | nl80211_send_sched_scan(rdev, dev, | 6252 | nl80211_send_sched_scan(rdev, dev, |
| 6095 | NL80211_CMD_START_SCHED_SCAN); | 6253 | NL80211_CMD_START_SCHED_SCAN); |
| 6096 | return 0; | 6254 | return 0; |
| 6097 | 6255 | ||
| 6098 | out_free: | 6256 | out_free: |
| 6099 | kfree(rdev->sched_scan_req); | 6257 | kfree(sched_scan_req); |
| 6100 | out_err: | 6258 | out_err: |
| 6101 | rdev->sched_scan_req = NULL; | ||
| 6102 | return err; | 6259 | return err; |
| 6103 | } | 6260 | } |
| 6104 | 6261 | ||
| @@ -6481,12 +6638,17 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 6481 | } | 6638 | } |
| 6482 | 6639 | ||
| 6483 | static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, | 6640 | static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, |
| 6484 | int flags, struct net_device *dev, | 6641 | int flags, struct net_device *dev, |
| 6485 | struct survey_info *survey) | 6642 | bool allow_radio_stats, |
| 6643 | struct survey_info *survey) | ||
| 6486 | { | 6644 | { |
| 6487 | void *hdr; | 6645 | void *hdr; |
| 6488 | struct nlattr *infoattr; | 6646 | struct nlattr *infoattr; |
| 6489 | 6647 | ||
| 6648 | /* skip radio stats if userspace didn't request them */ | ||
| 6649 | if (!survey->channel && !allow_radio_stats) | ||
| 6650 | return 0; | ||
| 6651 | |||
| 6490 | hdr = nl80211hdr_put(msg, portid, seq, flags, | 6652 | hdr = nl80211hdr_put(msg, portid, seq, flags, |
| 6491 | NL80211_CMD_NEW_SURVEY_RESULTS); | 6653 | NL80211_CMD_NEW_SURVEY_RESULTS); |
| 6492 | if (!hdr) | 6654 | if (!hdr) |
| @@ -6499,7 +6661,8 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, | |||
| 6499 | if (!infoattr) | 6661 | if (!infoattr) |
| 6500 | goto nla_put_failure; | 6662 | goto nla_put_failure; |
| 6501 | 6663 | ||
| 6502 | if (nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY, | 6664 | if (survey->channel && |
| 6665 | nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY, | ||
| 6503 | survey->channel->center_freq)) | 6666 | survey->channel->center_freq)) |
| 6504 | goto nla_put_failure; | 6667 | goto nla_put_failure; |
| 6505 | 6668 | ||
| @@ -6509,25 +6672,29 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, | |||
| 6509 | if ((survey->filled & SURVEY_INFO_IN_USE) && | 6672 | if ((survey->filled & SURVEY_INFO_IN_USE) && |
| 6510 | nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE)) | 6673 | nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE)) |
| 6511 | goto nla_put_failure; | 6674 | goto nla_put_failure; |
| 6512 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME) && | 6675 | if ((survey->filled & SURVEY_INFO_TIME) && |
| 6513 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME, | 6676 | nla_put_u64(msg, NL80211_SURVEY_INFO_TIME, |
| 6514 | survey->channel_time)) | 6677 | survey->time)) |
| 6678 | goto nla_put_failure; | ||
| 6679 | if ((survey->filled & SURVEY_INFO_TIME_BUSY) && | ||
| 6680 | nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_BUSY, | ||
| 6681 | survey->time_busy)) | ||
| 6515 | goto nla_put_failure; | 6682 | goto nla_put_failure; |
| 6516 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) && | 6683 | if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) && |
| 6517 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, | 6684 | nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY, |
| 6518 | survey->channel_time_busy)) | 6685 | survey->time_ext_busy)) |
| 6519 | goto nla_put_failure; | 6686 | goto nla_put_failure; |
| 6520 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) && | 6687 | if ((survey->filled & SURVEY_INFO_TIME_RX) && |
| 6521 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, | 6688 | nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_RX, |
| 6522 | survey->channel_time_ext_busy)) | 6689 | survey->time_rx)) |
| 6523 | goto nla_put_failure; | 6690 | goto nla_put_failure; |
| 6524 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) && | 6691 | if ((survey->filled & SURVEY_INFO_TIME_TX) && |
| 6525 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX, | 6692 | nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_TX, |
| 6526 | survey->channel_time_rx)) | 6693 | survey->time_tx)) |
| 6527 | goto nla_put_failure; | 6694 | goto nla_put_failure; |
| 6528 | if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) && | 6695 | if ((survey->filled & SURVEY_INFO_TIME_SCAN) && |
| 6529 | nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX, | 6696 | nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_SCAN, |
| 6530 | survey->channel_time_tx)) | 6697 | survey->time_scan)) |
| 6531 | goto nla_put_failure; | 6698 | goto nla_put_failure; |
| 6532 | 6699 | ||
| 6533 | nla_nest_end(msg, infoattr); | 6700 | nla_nest_end(msg, infoattr); |
| @@ -6539,19 +6706,22 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq, | |||
| 6539 | return -EMSGSIZE; | 6706 | return -EMSGSIZE; |
| 6540 | } | 6707 | } |
| 6541 | 6708 | ||
| 6542 | static int nl80211_dump_survey(struct sk_buff *skb, | 6709 | static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) |
| 6543 | struct netlink_callback *cb) | ||
| 6544 | { | 6710 | { |
| 6545 | struct survey_info survey; | 6711 | struct survey_info survey; |
| 6546 | struct cfg80211_registered_device *rdev; | 6712 | struct cfg80211_registered_device *rdev; |
| 6547 | struct wireless_dev *wdev; | 6713 | struct wireless_dev *wdev; |
| 6548 | int survey_idx = cb->args[2]; | 6714 | int survey_idx = cb->args[2]; |
| 6549 | int res; | 6715 | int res; |
| 6716 | bool radio_stats; | ||
| 6550 | 6717 | ||
| 6551 | res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); | 6718 | res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev); |
| 6552 | if (res) | 6719 | if (res) |
| 6553 | return res; | 6720 | return res; |
| 6554 | 6721 | ||
| 6722 | /* prepare_wdev_dump parsed the attributes */ | ||
| 6723 | radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; | ||
| 6724 | |||
| 6555 | if (!wdev->netdev) { | 6725 | if (!wdev->netdev) { |
| 6556 | res = -EINVAL; | 6726 | res = -EINVAL; |
| 6557 | goto out_err; | 6727 | goto out_err; |
| @@ -6569,13 +6739,9 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
| 6569 | if (res) | 6739 | if (res) |
| 6570 | goto out_err; | 6740 | goto out_err; |
| 6571 | 6741 | ||
| 6572 | /* Survey without a channel doesn't make sense */ | 6742 | /* don't send disabled channels, but do send non-channel data */ |
| 6573 | if (!survey.channel) { | 6743 | if (survey.channel && |
| 6574 | res = -EINVAL; | 6744 | survey.channel->flags & IEEE80211_CHAN_DISABLED) { |
| 6575 | goto out; | ||
| 6576 | } | ||
| 6577 | |||
| 6578 | if (survey.channel->flags & IEEE80211_CHAN_DISABLED) { | ||
| 6579 | survey_idx++; | 6745 | survey_idx++; |
| 6580 | continue; | 6746 | continue; |
| 6581 | } | 6747 | } |
| @@ -6583,7 +6749,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, | |||
| 6583 | if (nl80211_send_survey(skb, | 6749 | if (nl80211_send_survey(skb, |
| 6584 | NETLINK_CB(cb->skb).portid, | 6750 | NETLINK_CB(cb->skb).portid, |
| 6585 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 6751 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 6586 | wdev->netdev, &survey) < 0) | 6752 | wdev->netdev, radio_stats, &survey) < 0) |
| 6587 | goto out; | 6753 | goto out; |
| 6588 | survey_idx++; | 6754 | survey_idx++; |
| 6589 | } | 6755 | } |
| @@ -8599,6 +8765,48 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg, | |||
| 8599 | return 0; | 8765 | return 0; |
| 8600 | } | 8766 | } |
| 8601 | 8767 | ||
| 8768 | static int nl80211_send_wowlan_nd(struct sk_buff *msg, | ||
| 8769 | struct cfg80211_sched_scan_request *req) | ||
| 8770 | { | ||
| 8771 | struct nlattr *nd, *freqs, *matches, *match; | ||
| 8772 | int i; | ||
| 8773 | |||
| 8774 | if (!req) | ||
| 8775 | return 0; | ||
| 8776 | |||
| 8777 | nd = nla_nest_start(msg, NL80211_WOWLAN_TRIG_NET_DETECT); | ||
| 8778 | if (!nd) | ||
| 8779 | return -ENOBUFS; | ||
| 8780 | |||
| 8781 | if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval)) | ||
| 8782 | return -ENOBUFS; | ||
| 8783 | |||
| 8784 | freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); | ||
| 8785 | if (!freqs) | ||
| 8786 | return -ENOBUFS; | ||
| 8787 | |||
| 8788 | for (i = 0; i < req->n_channels; i++) | ||
| 8789 | nla_put_u32(msg, i, req->channels[i]->center_freq); | ||
| 8790 | |||
| 8791 | nla_nest_end(msg, freqs); | ||
| 8792 | |||
| 8793 | if (req->n_match_sets) { | ||
| 8794 | matches = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH); | ||
| 8795 | for (i = 0; i < req->n_match_sets; i++) { | ||
| 8796 | match = nla_nest_start(msg, i); | ||
| 8797 | nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID, | ||
| 8798 | req->match_sets[i].ssid.ssid_len, | ||
| 8799 | req->match_sets[i].ssid.ssid); | ||
| 8800 | nla_nest_end(msg, match); | ||
| 8801 | } | ||
| 8802 | nla_nest_end(msg, matches); | ||
| 8803 | } | ||
| 8804 | |||
| 8805 | nla_nest_end(msg, nd); | ||
| 8806 | |||
| 8807 | return 0; | ||
| 8808 | } | ||
| 8809 | |||
| 8602 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | 8810 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) |
| 8603 | { | 8811 | { |
| 8604 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 8812 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| @@ -8656,6 +8864,11 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
| 8656 | rdev->wiphy.wowlan_config->tcp)) | 8864 | rdev->wiphy.wowlan_config->tcp)) |
| 8657 | goto nla_put_failure; | 8865 | goto nla_put_failure; |
| 8658 | 8866 | ||
| 8867 | if (nl80211_send_wowlan_nd( | ||
| 8868 | msg, | ||
| 8869 | rdev->wiphy.wowlan_config->nd_config)) | ||
| 8870 | goto nla_put_failure; | ||
| 8871 | |||
| 8659 | nla_nest_end(msg, nl_wowlan); | 8872 | nla_nest_end(msg, nl_wowlan); |
| 8660 | } | 8873 | } |
| 8661 | 8874 | ||
| @@ -10225,7 +10438,8 @@ static const struct genl_ops nl80211_ops[] = { | |||
| 10225 | }, | 10438 | }, |
| 10226 | { | 10439 | { |
| 10227 | .cmd = NL80211_CMD_GET_REG, | 10440 | .cmd = NL80211_CMD_GET_REG, |
| 10228 | .doit = nl80211_get_reg, | 10441 | .doit = nl80211_get_reg_do, |
| 10442 | .dumpit = nl80211_get_reg_dump, | ||
| 10229 | .policy = nl80211_policy, | 10443 | .policy = nl80211_policy, |
| 10230 | .internal_flags = NL80211_FLAG_NEED_RTNL, | 10444 | .internal_flags = NL80211_FLAG_NEED_RTNL, |
| 10231 | /* can be retrieved by unprivileged users */ | 10445 | /* can be retrieved by unprivileged users */ |
| @@ -10939,25 +11153,9 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | |||
| 10939 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 11153 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
| 10940 | } | 11154 | } |
| 10941 | 11155 | ||
| 10942 | /* | 11156 | static bool nl80211_reg_change_event_fill(struct sk_buff *msg, |
| 10943 | * This can happen on global regulatory changes or device specific settings | 11157 | struct regulatory_request *request) |
| 10944 | * based on custom world regulatory domains. | ||
| 10945 | */ | ||
| 10946 | void nl80211_send_reg_change_event(struct regulatory_request *request) | ||
| 10947 | { | 11158 | { |
| 10948 | struct sk_buff *msg; | ||
| 10949 | void *hdr; | ||
| 10950 | |||
| 10951 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 10952 | if (!msg) | ||
| 10953 | return; | ||
| 10954 | |||
| 10955 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE); | ||
| 10956 | if (!hdr) { | ||
| 10957 | nlmsg_free(msg); | ||
| 10958 | return; | ||
| 10959 | } | ||
| 10960 | |||
| 10961 | /* Userspace can always count this one always being set */ | 11159 | /* Userspace can always count this one always being set */ |
| 10962 | if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator)) | 11160 | if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator)) |
| 10963 | goto nla_put_failure; | 11161 | goto nla_put_failure; |
| @@ -10983,8 +11181,46 @@ void nl80211_send_reg_change_event(struct regulatory_request *request) | |||
| 10983 | goto nla_put_failure; | 11181 | goto nla_put_failure; |
| 10984 | } | 11182 | } |
| 10985 | 11183 | ||
| 10986 | if (request->wiphy_idx != WIPHY_IDX_INVALID && | 11184 | if (request->wiphy_idx != WIPHY_IDX_INVALID) { |
| 10987 | nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) | 11185 | struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx); |
| 11186 | |||
| 11187 | if (wiphy && | ||
| 11188 | nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) | ||
| 11189 | goto nla_put_failure; | ||
| 11190 | |||
| 11191 | if (wiphy && | ||
| 11192 | wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED && | ||
| 11193 | nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG)) | ||
| 11194 | goto nla_put_failure; | ||
| 11195 | } | ||
| 11196 | |||
| 11197 | return true; | ||
| 11198 | |||
| 11199 | nla_put_failure: | ||
| 11200 | return false; | ||
| 11201 | } | ||
| 11202 | |||
| 11203 | /* | ||
| 11204 | * This can happen on global regulatory changes or device specific settings | ||
| 11205 | * based on custom regulatory domains. | ||
| 11206 | */ | ||
| 11207 | void nl80211_common_reg_change_event(enum nl80211_commands cmd_id, | ||
| 11208 | struct regulatory_request *request) | ||
| 11209 | { | ||
| 11210 | struct sk_buff *msg; | ||
| 11211 | void *hdr; | ||
| 11212 | |||
| 11213 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 11214 | if (!msg) | ||
| 11215 | return; | ||
| 11216 | |||
| 11217 | hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id); | ||
| 11218 | if (!hdr) { | ||
| 11219 | nlmsg_free(msg); | ||
| 11220 | return; | ||
| 11221 | } | ||
| 11222 | |||
| 11223 | if (nl80211_reg_change_event_fill(msg, request) == false) | ||
| 10988 | goto nla_put_failure; | 11224 | goto nla_put_failure; |
| 10989 | 11225 | ||
| 10990 | genlmsg_end(msg, hdr); | 11226 | genlmsg_end(msg, hdr); |
| @@ -11523,7 +11759,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
| 11523 | if (!msg) | 11759 | if (!msg) |
| 11524 | return; | 11760 | return; |
| 11525 | 11761 | ||
| 11526 | if (nl80211_send_station(msg, 0, 0, 0, | 11762 | if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0, |
| 11527 | rdev, dev, mac_addr, sinfo) < 0) { | 11763 | rdev, dev, mac_addr, sinfo) < 0) { |
| 11528 | nlmsg_free(msg); | 11764 | nlmsg_free(msg); |
| 11529 | return; | 11765 | return; |
| @@ -11534,12 +11770,16 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
| 11534 | } | 11770 | } |
| 11535 | EXPORT_SYMBOL(cfg80211_new_sta); | 11771 | EXPORT_SYMBOL(cfg80211_new_sta); |
| 11536 | 11772 | ||
| 11537 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) | 11773 | void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr, |
| 11774 | struct station_info *sinfo, gfp_t gfp) | ||
| 11538 | { | 11775 | { |
| 11539 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | 11776 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; |
| 11540 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 11777 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
| 11541 | struct sk_buff *msg; | 11778 | struct sk_buff *msg; |
| 11542 | void *hdr; | 11779 | struct station_info empty_sinfo = {}; |
| 11780 | |||
| 11781 | if (!sinfo) | ||
| 11782 | sinfo = &empty_sinfo; | ||
| 11543 | 11783 | ||
| 11544 | trace_cfg80211_del_sta(dev, mac_addr); | 11784 | trace_cfg80211_del_sta(dev, mac_addr); |
| 11545 | 11785 | ||
| @@ -11547,27 +11787,16 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) | |||
| 11547 | if (!msg) | 11787 | if (!msg) |
| 11548 | return; | 11788 | return; |
| 11549 | 11789 | ||
| 11550 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION); | 11790 | if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0, |
| 11551 | if (!hdr) { | 11791 | rdev, dev, mac_addr, sinfo) < 0) { |
| 11552 | nlmsg_free(msg); | 11792 | nlmsg_free(msg); |
| 11553 | return; | 11793 | return; |
| 11554 | } | 11794 | } |
| 11555 | 11795 | ||
| 11556 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | ||
| 11557 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) | ||
| 11558 | goto nla_put_failure; | ||
| 11559 | |||
| 11560 | genlmsg_end(msg, hdr); | ||
| 11561 | |||
| 11562 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 11796 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, |
| 11563 | NL80211_MCGRP_MLME, gfp); | 11797 | NL80211_MCGRP_MLME, gfp); |
| 11564 | return; | ||
| 11565 | |||
| 11566 | nla_put_failure: | ||
| 11567 | genlmsg_cancel(msg, hdr); | ||
| 11568 | nlmsg_free(msg); | ||
| 11569 | } | 11798 | } |
| 11570 | EXPORT_SYMBOL(cfg80211_del_sta); | 11799 | EXPORT_SYMBOL(cfg80211_del_sta_sinfo); |
| 11571 | 11800 | ||
| 11572 | void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, | 11801 | void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, |
| 11573 | enum nl80211_connect_failed_reason reason, | 11802 | enum nl80211_connect_failed_reason reason, |
| @@ -12471,6 +12700,13 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
| 12471 | 12700 | ||
| 12472 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { | 12701 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) { |
| 12473 | bool schedule_destroy_work = false; | 12702 | bool schedule_destroy_work = false; |
| 12703 | bool schedule_scan_stop = false; | ||
| 12704 | struct cfg80211_sched_scan_request *sched_scan_req = | ||
| 12705 | rcu_dereference(rdev->sched_scan_req); | ||
| 12706 | |||
| 12707 | if (sched_scan_req && notify->portid && | ||
| 12708 | sched_scan_req->owner_nlportid == notify->portid) | ||
| 12709 | schedule_scan_stop = true; | ||
| 12474 | 12710 | ||
| 12475 | list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) { | 12711 | list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) { |
| 12476 | cfg80211_mlme_unregister_socket(wdev, notify->portid); | 12712 | cfg80211_mlme_unregister_socket(wdev, notify->portid); |
| @@ -12501,6 +12737,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
| 12501 | spin_unlock(&rdev->destroy_list_lock); | 12737 | spin_unlock(&rdev->destroy_list_lock); |
| 12502 | schedule_work(&rdev->destroy_work); | 12738 | schedule_work(&rdev->destroy_work); |
| 12503 | } | 12739 | } |
| 12740 | } else if (schedule_scan_stop) { | ||
| 12741 | sched_scan_req->owner_nlportid = 0; | ||
| 12742 | |||
| 12743 | if (rdev->ops->sched_scan_stop && | ||
| 12744 | rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | ||
| 12745 | schedule_work(&rdev->sched_scan_stop_wk); | ||
| 12504 | } | 12746 | } |
| 12505 | } | 12747 | } |
| 12506 | 12748 | ||
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 7ad70d6f0cc6..84d4edf1d545 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
| @@ -17,7 +17,21 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | |||
| 17 | struct net_device *netdev, u32 cmd); | 17 | struct net_device *netdev, u32 cmd); |
| 18 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, | 18 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, |
| 19 | struct net_device *netdev); | 19 | struct net_device *netdev); |
| 20 | void nl80211_send_reg_change_event(struct regulatory_request *request); | 20 | void nl80211_common_reg_change_event(enum nl80211_commands cmd_id, |
| 21 | struct regulatory_request *request); | ||
| 22 | |||
| 23 | static inline void | ||
| 24 | nl80211_send_reg_change_event(struct regulatory_request *request) | ||
| 25 | { | ||
| 26 | nl80211_common_reg_change_event(NL80211_CMD_REG_CHANGE, request); | ||
| 27 | } | ||
| 28 | |||
| 29 | static inline void | ||
| 30 | nl80211_send_wiphy_reg_change_event(struct regulatory_request *request) | ||
| 31 | { | ||
| 32 | nl80211_common_reg_change_event(NL80211_CMD_WIPHY_REG_CHANGE, request); | ||
| 33 | } | ||
| 34 | |||
| 21 | void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, | 35 | void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, |
| 22 | struct net_device *netdev, | 36 | struct net_device *netdev, |
| 23 | const u8 *buf, size_t len, gfp_t gfp); | 37 | const u8 *buf, size_t len, gfp_t gfp); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7b8309840d4e..886cc7cb5566 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -109,7 +109,7 @@ static struct regulatory_request core_request_world = { | |||
| 109 | * protected by RTNL (and can be accessed with RCU protection) | 109 | * protected by RTNL (and can be accessed with RCU protection) |
| 110 | */ | 110 | */ |
| 111 | static struct regulatory_request __rcu *last_request = | 111 | static struct regulatory_request __rcu *last_request = |
| 112 | (void __rcu *)&core_request_world; | 112 | (void __force __rcu *)&core_request_world; |
| 113 | 113 | ||
| 114 | /* To trigger userspace events */ | 114 | /* To trigger userspace events */ |
| 115 | static struct platform_device *reg_pdev; | 115 | static struct platform_device *reg_pdev; |
| @@ -142,7 +142,7 @@ static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | |||
| 142 | return rtnl_dereference(cfg80211_regdomain); | 142 | return rtnl_dereference(cfg80211_regdomain); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) | 145 | const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) |
| 146 | { | 146 | { |
| 147 | return rtnl_dereference(wiphy->regd); | 147 | return rtnl_dereference(wiphy->regd); |
| 148 | } | 148 | } |
| @@ -1307,6 +1307,9 @@ static bool ignore_reg_update(struct wiphy *wiphy, | |||
| 1307 | { | 1307 | { |
| 1308 | struct regulatory_request *lr = get_last_request(); | 1308 | struct regulatory_request *lr = get_last_request(); |
| 1309 | 1309 | ||
| 1310 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) | ||
| 1311 | return true; | ||
| 1312 | |||
| 1310 | if (!lr) { | 1313 | if (!lr) { |
| 1311 | REG_DBG_PRINT("Ignoring regulatory request set by %s " | 1314 | REG_DBG_PRINT("Ignoring regulatory request set by %s " |
| 1312 | "since last_request is not set\n", | 1315 | "since last_request is not set\n", |
| @@ -1683,8 +1686,12 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
| 1683 | if (IS_ERR(reg_rule)) { | 1686 | if (IS_ERR(reg_rule)) { |
| 1684 | REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n", | 1687 | REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n", |
| 1685 | chan->center_freq); | 1688 | chan->center_freq); |
| 1686 | chan->orig_flags |= IEEE80211_CHAN_DISABLED; | 1689 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { |
| 1687 | chan->flags = chan->orig_flags; | 1690 | chan->flags |= IEEE80211_CHAN_DISABLED; |
| 1691 | } else { | ||
| 1692 | chan->orig_flags |= IEEE80211_CHAN_DISABLED; | ||
| 1693 | chan->flags = chan->orig_flags; | ||
| 1694 | } | ||
| 1688 | return; | 1695 | return; |
| 1689 | } | 1696 | } |
| 1690 | 1697 | ||
| @@ -1709,7 +1716,13 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
| 1709 | chan->dfs_state = NL80211_DFS_USABLE; | 1716 | chan->dfs_state = NL80211_DFS_USABLE; |
| 1710 | 1717 | ||
| 1711 | chan->beacon_found = false; | 1718 | chan->beacon_found = false; |
| 1712 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; | 1719 | |
| 1720 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) | ||
| 1721 | chan->flags = chan->orig_flags | bw_flags | | ||
| 1722 | map_regdom_flags(reg_rule->flags); | ||
| 1723 | else | ||
| 1724 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; | ||
| 1725 | |||
| 1713 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); | 1726 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); |
| 1714 | chan->max_reg_power = chan->max_power = | 1727 | chan->max_reg_power = chan->max_power = |
| 1715 | (int) MBM_TO_DBM(power_rule->max_eirp); | 1728 | (int) MBM_TO_DBM(power_rule->max_eirp); |
| @@ -2095,6 +2108,26 @@ out_free: | |||
| 2095 | reg_free_request(reg_request); | 2108 | reg_free_request(reg_request); |
| 2096 | } | 2109 | } |
| 2097 | 2110 | ||
| 2111 | static bool reg_only_self_managed_wiphys(void) | ||
| 2112 | { | ||
| 2113 | struct cfg80211_registered_device *rdev; | ||
| 2114 | struct wiphy *wiphy; | ||
| 2115 | bool self_managed_found = false; | ||
| 2116 | |||
| 2117 | ASSERT_RTNL(); | ||
| 2118 | |||
| 2119 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
| 2120 | wiphy = &rdev->wiphy; | ||
| 2121 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) | ||
| 2122 | self_managed_found = true; | ||
| 2123 | else | ||
| 2124 | return false; | ||
| 2125 | } | ||
| 2126 | |||
| 2127 | /* make sure at least one self-managed wiphy exists */ | ||
| 2128 | return self_managed_found; | ||
| 2129 | } | ||
| 2130 | |||
| 2098 | /* | 2131 | /* |
| 2099 | * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* | 2132 | * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* |
| 2100 | * Regulatory hints come on a first come first serve basis and we | 2133 | * Regulatory hints come on a first come first serve basis and we |
| @@ -2126,6 +2159,11 @@ static void reg_process_pending_hints(void) | |||
| 2126 | 2159 | ||
| 2127 | spin_unlock(®_requests_lock); | 2160 | spin_unlock(®_requests_lock); |
| 2128 | 2161 | ||
| 2162 | if (reg_only_self_managed_wiphys()) { | ||
| 2163 | reg_free_request(reg_request); | ||
| 2164 | return; | ||
| 2165 | } | ||
| 2166 | |||
| 2129 | reg_process_hint(reg_request); | 2167 | reg_process_hint(reg_request); |
| 2130 | } | 2168 | } |
| 2131 | 2169 | ||
| @@ -2153,11 +2191,52 @@ static void reg_process_pending_beacon_hints(void) | |||
| 2153 | spin_unlock_bh(®_pending_beacons_lock); | 2191 | spin_unlock_bh(®_pending_beacons_lock); |
| 2154 | } | 2192 | } |
| 2155 | 2193 | ||
| 2194 | static void reg_process_self_managed_hints(void) | ||
| 2195 | { | ||
| 2196 | struct cfg80211_registered_device *rdev; | ||
| 2197 | struct wiphy *wiphy; | ||
| 2198 | const struct ieee80211_regdomain *tmp; | ||
| 2199 | const struct ieee80211_regdomain *regd; | ||
| 2200 | enum ieee80211_band band; | ||
| 2201 | struct regulatory_request request = {}; | ||
| 2202 | |||
| 2203 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
| 2204 | wiphy = &rdev->wiphy; | ||
| 2205 | |||
| 2206 | spin_lock(®_requests_lock); | ||
| 2207 | regd = rdev->requested_regd; | ||
| 2208 | rdev->requested_regd = NULL; | ||
| 2209 | spin_unlock(®_requests_lock); | ||
| 2210 | |||
| 2211 | if (regd == NULL) | ||
| 2212 | continue; | ||
| 2213 | |||
| 2214 | tmp = get_wiphy_regdom(wiphy); | ||
| 2215 | rcu_assign_pointer(wiphy->regd, regd); | ||
| 2216 | rcu_free_regdom(tmp); | ||
| 2217 | |||
| 2218 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) | ||
| 2219 | handle_band_custom(wiphy, wiphy->bands[band], regd); | ||
| 2220 | |||
| 2221 | reg_process_ht_flags(wiphy); | ||
| 2222 | |||
| 2223 | request.wiphy_idx = get_wiphy_idx(wiphy); | ||
| 2224 | request.alpha2[0] = regd->alpha2[0]; | ||
| 2225 | request.alpha2[1] = regd->alpha2[1]; | ||
| 2226 | request.initiator = NL80211_REGDOM_SET_BY_DRIVER; | ||
| 2227 | |||
| 2228 | nl80211_send_wiphy_reg_change_event(&request); | ||
| 2229 | } | ||
| 2230 | |||
| 2231 | reg_check_channels(); | ||
| 2232 | } | ||
| 2233 | |||
| 2156 | static void reg_todo(struct work_struct *work) | 2234 | static void reg_todo(struct work_struct *work) |
| 2157 | { | 2235 | { |
| 2158 | rtnl_lock(); | 2236 | rtnl_lock(); |
| 2159 | reg_process_pending_hints(); | 2237 | reg_process_pending_hints(); |
| 2160 | reg_process_pending_beacon_hints(); | 2238 | reg_process_pending_beacon_hints(); |
| 2239 | reg_process_self_managed_hints(); | ||
| 2161 | rtnl_unlock(); | 2240 | rtnl_unlock(); |
| 2162 | } | 2241 | } |
| 2163 | 2242 | ||
| @@ -2438,6 +2517,8 @@ static void restore_regulatory_settings(bool reset_user) | |||
| 2438 | world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; | 2517 | world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; |
| 2439 | 2518 | ||
| 2440 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 2519 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
| 2520 | if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) | ||
| 2521 | continue; | ||
| 2441 | if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG) | 2522 | if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG) |
| 2442 | restore_custom_reg_settings(&rdev->wiphy); | 2523 | restore_custom_reg_settings(&rdev->wiphy); |
| 2443 | } | 2524 | } |
| @@ -2841,10 +2922,79 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2841 | return 0; | 2922 | return 0; |
| 2842 | } | 2923 | } |
| 2843 | 2924 | ||
| 2925 | static int __regulatory_set_wiphy_regd(struct wiphy *wiphy, | ||
| 2926 | struct ieee80211_regdomain *rd) | ||
| 2927 | { | ||
| 2928 | const struct ieee80211_regdomain *regd; | ||
| 2929 | const struct ieee80211_regdomain *prev_regd; | ||
| 2930 | struct cfg80211_registered_device *rdev; | ||
| 2931 | |||
| 2932 | if (WARN_ON(!wiphy || !rd)) | ||
| 2933 | return -EINVAL; | ||
| 2934 | |||
| 2935 | if (WARN(!(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED), | ||
| 2936 | "wiphy should have REGULATORY_WIPHY_SELF_MANAGED\n")) | ||
| 2937 | return -EPERM; | ||
| 2938 | |||
| 2939 | if (WARN(!is_valid_rd(rd), "Invalid regulatory domain detected\n")) { | ||
| 2940 | print_regdomain_info(rd); | ||
| 2941 | return -EINVAL; | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | regd = reg_copy_regd(rd); | ||
| 2945 | if (IS_ERR(regd)) | ||
| 2946 | return PTR_ERR(regd); | ||
| 2947 | |||
| 2948 | rdev = wiphy_to_rdev(wiphy); | ||
| 2949 | |||
| 2950 | spin_lock(®_requests_lock); | ||
| 2951 | prev_regd = rdev->requested_regd; | ||
| 2952 | rdev->requested_regd = regd; | ||
| 2953 | spin_unlock(®_requests_lock); | ||
| 2954 | |||
| 2955 | kfree(prev_regd); | ||
| 2956 | return 0; | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | int regulatory_set_wiphy_regd(struct wiphy *wiphy, | ||
| 2960 | struct ieee80211_regdomain *rd) | ||
| 2961 | { | ||
| 2962 | int ret = __regulatory_set_wiphy_regd(wiphy, rd); | ||
| 2963 | |||
| 2964 | if (ret) | ||
| 2965 | return ret; | ||
| 2966 | |||
| 2967 | schedule_work(®_work); | ||
| 2968 | return 0; | ||
| 2969 | } | ||
| 2970 | EXPORT_SYMBOL(regulatory_set_wiphy_regd); | ||
| 2971 | |||
| 2972 | int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, | ||
| 2973 | struct ieee80211_regdomain *rd) | ||
| 2974 | { | ||
| 2975 | int ret; | ||
| 2976 | |||
| 2977 | ASSERT_RTNL(); | ||
| 2978 | |||
| 2979 | ret = __regulatory_set_wiphy_regd(wiphy, rd); | ||
| 2980 | if (ret) | ||
| 2981 | return ret; | ||
| 2982 | |||
| 2983 | /* process the request immediately */ | ||
| 2984 | reg_process_self_managed_hints(); | ||
| 2985 | return 0; | ||
| 2986 | } | ||
| 2987 | EXPORT_SYMBOL(regulatory_set_wiphy_regd_sync_rtnl); | ||
| 2988 | |||
| 2844 | void wiphy_regulatory_register(struct wiphy *wiphy) | 2989 | void wiphy_regulatory_register(struct wiphy *wiphy) |
| 2845 | { | 2990 | { |
| 2846 | struct regulatory_request *lr; | 2991 | struct regulatory_request *lr; |
| 2847 | 2992 | ||
| 2993 | /* self-managed devices ignore external hints */ | ||
| 2994 | if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) | ||
| 2995 | wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS | | ||
| 2996 | REGULATORY_COUNTRY_IE_IGNORE; | ||
| 2997 | |||
| 2848 | if (!reg_dev_ignore_cell_hint(wiphy)) | 2998 | if (!reg_dev_ignore_cell_hint(wiphy)) |
| 2849 | reg_num_devs_support_basehint++; | 2999 | reg_num_devs_support_basehint++; |
| 2850 | 3000 | ||
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 5e48031ccb9a..4b45d6e61d24 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
| @@ -38,6 +38,7 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, | |||
| 38 | const struct ieee80211_reg_rule *rule); | 38 | const struct ieee80211_reg_rule *rule); |
| 39 | 39 | ||
| 40 | bool reg_last_request_cell_base(void); | 40 | bool reg_last_request_cell_base(void); |
| 41 | const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy); | ||
| 41 | 42 | ||
| 42 | /** | 43 | /** |
| 43 | * regulatory_hint_found_beacon - hints a beacon was found on a channel | 44 | * regulatory_hint_found_beacon - hints a beacon was found on a channel |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index bda39f149810..c705c3e2b751 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -257,7 +257,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) | |||
| 257 | 257 | ||
| 258 | rtnl_lock(); | 258 | rtnl_lock(); |
| 259 | 259 | ||
| 260 | request = rdev->sched_scan_req; | 260 | request = rtnl_dereference(rdev->sched_scan_req); |
| 261 | 261 | ||
| 262 | /* we don't have sched_scan_req anymore if the scan is stopping */ | 262 | /* we don't have sched_scan_req anymore if the scan is stopping */ |
| 263 | if (request) { | 263 | if (request) { |
| @@ -279,7 +279,8 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy) | |||
| 279 | { | 279 | { |
| 280 | trace_cfg80211_sched_scan_results(wiphy); | 280 | trace_cfg80211_sched_scan_results(wiphy); |
| 281 | /* ignore if we're not scanning */ | 281 | /* ignore if we're not scanning */ |
| 282 | if (wiphy_to_rdev(wiphy)->sched_scan_req) | 282 | |
| 283 | if (rcu_access_pointer(wiphy_to_rdev(wiphy)->sched_scan_req)) | ||
| 283 | queue_work(cfg80211_wq, | 284 | queue_work(cfg80211_wq, |
| 284 | &wiphy_to_rdev(wiphy)->sched_scan_results_wk); | 285 | &wiphy_to_rdev(wiphy)->sched_scan_results_wk); |
| 285 | } | 286 | } |
| @@ -308,6 +309,7 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped); | |||
| 308 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 309 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, |
| 309 | bool driver_initiated) | 310 | bool driver_initiated) |
| 310 | { | 311 | { |
| 312 | struct cfg80211_sched_scan_request *sched_scan_req; | ||
| 311 | struct net_device *dev; | 313 | struct net_device *dev; |
| 312 | 314 | ||
| 313 | ASSERT_RTNL(); | 315 | ASSERT_RTNL(); |
| @@ -315,7 +317,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | |||
| 315 | if (!rdev->sched_scan_req) | 317 | if (!rdev->sched_scan_req) |
| 316 | return -ENOENT; | 318 | return -ENOENT; |
| 317 | 319 | ||
| 318 | dev = rdev->sched_scan_req->dev; | 320 | sched_scan_req = rtnl_dereference(rdev->sched_scan_req); |
| 321 | dev = sched_scan_req->dev; | ||
| 319 | 322 | ||
| 320 | if (!driver_initiated) { | 323 | if (!driver_initiated) { |
| 321 | int err = rdev_sched_scan_stop(rdev, dev); | 324 | int err = rdev_sched_scan_stop(rdev, dev); |
| @@ -325,8 +328,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | |||
| 325 | 328 | ||
| 326 | nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); | 329 | nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); |
| 327 | 330 | ||
| 328 | kfree(rdev->sched_scan_req); | 331 | RCU_INIT_POINTER(rdev->sched_scan_req, NULL); |
| 329 | rdev->sched_scan_req = NULL; | 332 | kfree_rcu(sched_scan_req, rcu_head); |
| 330 | 333 | ||
| 331 | return 0; | 334 | return 0; |
| 332 | } | 335 | } |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ad38910f7036..b17b3692f8c2 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
| @@ -1604,11 +1604,12 @@ TRACE_EVENT(rdev_return_int_survey_info, | |||
| 1604 | WIPHY_ENTRY | 1604 | WIPHY_ENTRY |
| 1605 | CHAN_ENTRY | 1605 | CHAN_ENTRY |
| 1606 | __field(int, ret) | 1606 | __field(int, ret) |
| 1607 | __field(u64, channel_time) | 1607 | __field(u64, time) |
| 1608 | __field(u64, channel_time_busy) | 1608 | __field(u64, time_busy) |
| 1609 | __field(u64, channel_time_ext_busy) | 1609 | __field(u64, time_ext_busy) |
| 1610 | __field(u64, channel_time_rx) | 1610 | __field(u64, time_rx) |
| 1611 | __field(u64, channel_time_tx) | 1611 | __field(u64, time_tx) |
| 1612 | __field(u64, time_scan) | ||
| 1612 | __field(u32, filled) | 1613 | __field(u32, filled) |
| 1613 | __field(s8, noise) | 1614 | __field(s8, noise) |
| 1614 | ), | 1615 | ), |
| @@ -1616,22 +1617,24 @@ TRACE_EVENT(rdev_return_int_survey_info, | |||
| 1616 | WIPHY_ASSIGN; | 1617 | WIPHY_ASSIGN; |
| 1617 | CHAN_ASSIGN(info->channel); | 1618 | CHAN_ASSIGN(info->channel); |
| 1618 | __entry->ret = ret; | 1619 | __entry->ret = ret; |
| 1619 | __entry->channel_time = info->channel_time; | 1620 | __entry->time = info->time; |
| 1620 | __entry->channel_time_busy = info->channel_time_busy; | 1621 | __entry->time_busy = info->time_busy; |
| 1621 | __entry->channel_time_ext_busy = info->channel_time_ext_busy; | 1622 | __entry->time_ext_busy = info->time_ext_busy; |
| 1622 | __entry->channel_time_rx = info->channel_time_rx; | 1623 | __entry->time_rx = info->time_rx; |
| 1623 | __entry->channel_time_tx = info->channel_time_tx; | 1624 | __entry->time_tx = info->time_tx; |
| 1625 | __entry->time_scan = info->time_scan; | ||
| 1624 | __entry->filled = info->filled; | 1626 | __entry->filled = info->filled; |
| 1625 | __entry->noise = info->noise; | 1627 | __entry->noise = info->noise; |
| 1626 | ), | 1628 | ), |
| 1627 | TP_printk(WIPHY_PR_FMT ", returned: %d, " CHAN_PR_FMT | 1629 | TP_printk(WIPHY_PR_FMT ", returned: %d, " CHAN_PR_FMT |
| 1628 | ", channel time: %llu, channel time busy: %llu, " | 1630 | ", channel time: %llu, channel time busy: %llu, " |
| 1629 | "channel time extension busy: %llu, channel time rx: %llu, " | 1631 | "channel time extension busy: %llu, channel time rx: %llu, " |
| 1630 | "channel time tx: %llu, filled: %u, noise: %d", | 1632 | "channel time tx: %llu, scan time: %llu, filled: %u, noise: %d", |
| 1631 | WIPHY_PR_ARG, __entry->ret, CHAN_PR_ARG, | 1633 | WIPHY_PR_ARG, __entry->ret, CHAN_PR_ARG, |
| 1632 | __entry->channel_time, __entry->channel_time_busy, | 1634 | __entry->time, __entry->time_busy, |
| 1633 | __entry->channel_time_ext_busy, __entry->channel_time_rx, | 1635 | __entry->time_ext_busy, __entry->time_rx, |
| 1634 | __entry->channel_time_tx, __entry->filled, __entry->noise) | 1636 | __entry->time_tx, __entry->time_scan, |
| 1637 | __entry->filled, __entry->noise) | ||
| 1635 | ); | 1638 | ); |
| 1636 | 1639 | ||
| 1637 | TRACE_EVENT(rdev_tdls_oper, | 1640 | TRACE_EVENT(rdev_tdls_oper, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d0ac795445b7..3535e8ade48f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
| @@ -1073,10 +1073,24 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) | |||
| 1073 | if (WARN_ON_ONCE(rate->mcs > 9)) | 1073 | if (WARN_ON_ONCE(rate->mcs > 9)) |
| 1074 | return 0; | 1074 | return 0; |
| 1075 | 1075 | ||
| 1076 | idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH | | 1076 | switch (rate->bw) { |
| 1077 | RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 : | 1077 | case RATE_INFO_BW_160: |
| 1078 | rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 : | 1078 | idx = 3; |
| 1079 | rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0; | 1079 | break; |
| 1080 | case RATE_INFO_BW_80: | ||
| 1081 | idx = 2; | ||
| 1082 | break; | ||
| 1083 | case RATE_INFO_BW_40: | ||
| 1084 | idx = 1; | ||
| 1085 | break; | ||
| 1086 | case RATE_INFO_BW_5: | ||
| 1087 | case RATE_INFO_BW_10: | ||
| 1088 | default: | ||
| 1089 | WARN_ON(1); | ||
| 1090 | /* fall through */ | ||
| 1091 | case RATE_INFO_BW_20: | ||
| 1092 | idx = 0; | ||
| 1093 | } | ||
| 1080 | 1094 | ||
| 1081 | bitrate = base[idx][rate->mcs]; | 1095 | bitrate = base[idx][rate->mcs]; |
| 1082 | bitrate *= rate->nss; | 1096 | bitrate *= rate->nss; |
| @@ -1107,8 +1121,7 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) | |||
| 1107 | modulation = rate->mcs & 7; | 1121 | modulation = rate->mcs & 7; |
| 1108 | streams = (rate->mcs >> 3) + 1; | 1122 | streams = (rate->mcs >> 3) + 1; |
| 1109 | 1123 | ||
| 1110 | bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? | 1124 | bitrate = (rate->bw == RATE_INFO_BW_40) ? 13500000 : 6500000; |
| 1111 | 13500000 : 6500000; | ||
| 1112 | 1125 | ||
| 1113 | if (modulation < 4) | 1126 | if (modulation < 4) |
| 1114 | bitrate *= (modulation + 1); | 1127 | bitrate *= (modulation + 1); |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 0f47948c572f..5b24d39d7903 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
| @@ -1300,7 +1300,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev, | |||
| 1300 | if (err) | 1300 | if (err) |
| 1301 | return err; | 1301 | return err; |
| 1302 | 1302 | ||
| 1303 | if (!(sinfo.filled & STATION_INFO_TX_BITRATE)) | 1303 | if (!(sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))) |
| 1304 | return -EOPNOTSUPP; | 1304 | return -EOPNOTSUPP; |
| 1305 | 1305 | ||
| 1306 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); | 1306 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); |
| @@ -1340,7 +1340,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
| 1340 | 1340 | ||
| 1341 | switch (rdev->wiphy.signal_type) { | 1341 | switch (rdev->wiphy.signal_type) { |
| 1342 | case CFG80211_SIGNAL_TYPE_MBM: | 1342 | case CFG80211_SIGNAL_TYPE_MBM: |
| 1343 | if (sinfo.filled & STATION_INFO_SIGNAL) { | 1343 | if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) { |
| 1344 | int sig = sinfo.signal; | 1344 | int sig = sinfo.signal; |
| 1345 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; | 1345 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; |
| 1346 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; | 1346 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; |
| @@ -1354,7 +1354,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
| 1354 | break; | 1354 | break; |
| 1355 | } | 1355 | } |
| 1356 | case CFG80211_SIGNAL_TYPE_UNSPEC: | 1356 | case CFG80211_SIGNAL_TYPE_UNSPEC: |
| 1357 | if (sinfo.filled & STATION_INFO_SIGNAL) { | 1357 | if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) { |
| 1358 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; | 1358 | wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; |
| 1359 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; | 1359 | wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; |
| 1360 | wstats.qual.level = sinfo.signal; | 1360 | wstats.qual.level = sinfo.signal; |
| @@ -1367,9 +1367,9 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
| 1367 | } | 1367 | } |
| 1368 | 1368 | ||
| 1369 | wstats.qual.updated |= IW_QUAL_NOISE_INVALID; | 1369 | wstats.qual.updated |= IW_QUAL_NOISE_INVALID; |
| 1370 | if (sinfo.filled & STATION_INFO_RX_DROP_MISC) | 1370 | if (sinfo.filled & BIT(NL80211_STA_INFO_RX_DROP_MISC)) |
| 1371 | wstats.discard.misc = sinfo.rx_dropped_misc; | 1371 | wstats.discard.misc = sinfo.rx_dropped_misc; |
| 1372 | if (sinfo.filled & STATION_INFO_TX_FAILED) | 1372 | if (sinfo.filled & BIT(NL80211_STA_INFO_TX_FAILED)) |
| 1373 | wstats.discard.retries = sinfo.tx_failed; | 1373 | wstats.discard.retries = sinfo.tx_failed; |
| 1374 | 1374 | ||
| 1375 | return &wstats; | 1375 | return &wstats; |
