diff options
147 files changed, 2860 insertions, 1428 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e443eb76ce5e..14cffbfbd041 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1674,10 +1674,9 @@ F: drivers/net/ethernet/broadcom/tg3.* | |||
1674 | 1674 | ||
1675 | BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER | 1675 | BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER |
1676 | M: Brett Rudley <brudley@broadcom.com> | 1676 | M: Brett Rudley <brudley@broadcom.com> |
1677 | M: Roland Vossen <rvossen@broadcom.com> | ||
1678 | M: Arend van Spriel <arend@broadcom.com> | 1677 | M: Arend van Spriel <arend@broadcom.com> |
1679 | M: Franky (Zhenhui) Lin <frankyl@broadcom.com> | 1678 | M: Franky (Zhenhui) Lin <frankyl@broadcom.com> |
1680 | M: Kan Yan <kanyan@broadcom.com> | 1679 | M: Hante Meuleman <meuleman@broadcom.com> |
1681 | L: linux-wireless@vger.kernel.org | 1680 | L: linux-wireless@vger.kernel.org |
1682 | L: brcm80211-dev-list@broadcom.com | 1681 | L: brcm80211-dev-list@broadcom.com |
1683 | S: Supported | 1682 | S: Supported |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 169fc58427d3..bcb830ec4bb4 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -84,6 +84,8 @@ extern void __exit bcma_host_pci_exit(void); | |||
84 | /* driver_pci.c */ | 84 | /* driver_pci.c */ |
85 | u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); | 85 | u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); |
86 | 86 | ||
87 | extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc); | ||
88 | |||
87 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 89 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE |
88 | bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); | 90 | bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); |
89 | void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | 91 | void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index ffd74e51f02d..d017f2512275 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -4,12 +4,15 @@ | |||
4 | * | 4 | * |
5 | * Copyright 2005, Broadcom Corporation | 5 | * Copyright 2005, Broadcom Corporation |
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | 6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> |
7 | * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
7 | * | 8 | * |
8 | * Licensed under the GNU/GPL. See COPYING for details. | 9 | * Licensed under the GNU/GPL. See COPYING for details. |
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include "bcma_private.h" | 12 | #include "bcma_private.h" |
13 | #include <linux/bcm47xx_wdt.h> | ||
12 | #include <linux/export.h> | 14 | #include <linux/export.h> |
15 | #include <linux/platform_device.h> | ||
13 | #include <linux/bcma/bcma.h> | 16 | #include <linux/bcma/bcma.h> |
14 | 17 | ||
15 | static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | 18 | static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, |
@@ -22,6 +25,90 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | |||
22 | return value; | 25 | return value; |
23 | } | 26 | } |
24 | 27 | ||
28 | static u32 bcma_chipco_alp_clock(struct bcma_drv_cc *cc) | ||
29 | { | ||
30 | if (cc->capabilities & BCMA_CC_CAP_PMU) | ||
31 | return bcma_pmu_alp_clock(cc); | ||
32 | |||
33 | return 20000000; | ||
34 | } | ||
35 | |||
36 | static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) | ||
37 | { | ||
38 | struct bcma_bus *bus = cc->core->bus; | ||
39 | u32 nb; | ||
40 | |||
41 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | ||
42 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) | ||
43 | nb = 32; | ||
44 | else if (cc->core->id.rev < 26) | ||
45 | nb = 16; | ||
46 | else | ||
47 | nb = (cc->core->id.rev >= 37) ? 32 : 24; | ||
48 | } else { | ||
49 | nb = 28; | ||
50 | } | ||
51 | if (nb == 32) | ||
52 | return 0xffffffff; | ||
53 | else | ||
54 | return (1 << nb) - 1; | ||
55 | } | ||
56 | |||
57 | static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, | ||
58 | u32 ticks) | ||
59 | { | ||
60 | struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt); | ||
61 | |||
62 | return bcma_chipco_watchdog_timer_set(cc, ticks); | ||
63 | } | ||
64 | |||
65 | static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt, | ||
66 | u32 ms) | ||
67 | { | ||
68 | struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt); | ||
69 | u32 ticks; | ||
70 | |||
71 | ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms); | ||
72 | return ticks / cc->ticks_per_ms; | ||
73 | } | ||
74 | |||
75 | static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc) | ||
76 | { | ||
77 | struct bcma_bus *bus = cc->core->bus; | ||
78 | |||
79 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | ||
80 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) | ||
81 | /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */ | ||
82 | return bcma_chipco_alp_clock(cc) / 4000; | ||
83 | else | ||
84 | /* based on 32KHz ILP clock */ | ||
85 | return 32; | ||
86 | } else { | ||
87 | return bcma_chipco_alp_clock(cc) / 1000; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) | ||
92 | { | ||
93 | struct bcm47xx_wdt wdt = {}; | ||
94 | struct platform_device *pdev; | ||
95 | |||
96 | wdt.driver_data = cc; | ||
97 | wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt; | ||
98 | wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt; | ||
99 | wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; | ||
100 | |||
101 | pdev = platform_device_register_data(NULL, "bcm47xx-wdt", | ||
102 | cc->core->bus->num, &wdt, | ||
103 | sizeof(wdt)); | ||
104 | if (IS_ERR(pdev)) | ||
105 | return PTR_ERR(pdev); | ||
106 | |||
107 | cc->watchdog = pdev; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
25 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) | 112 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) |
26 | { | 113 | { |
27 | if (cc->early_setup_done) | 114 | if (cc->early_setup_done) |
@@ -69,15 +156,33 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |||
69 | ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | | 156 | ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | |
70 | (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); | 157 | (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); |
71 | } | 158 | } |
159 | cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc); | ||
72 | 160 | ||
73 | cc->setup_done = true; | 161 | cc->setup_done = true; |
74 | } | 162 | } |
75 | 163 | ||
76 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ | 164 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ |
77 | void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) | 165 | u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) |
78 | { | 166 | { |
79 | /* instant NMI */ | 167 | u32 maxt; |
80 | bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); | 168 | enum bcma_clkmode clkmode; |
169 | |||
170 | maxt = bcma_chipco_watchdog_get_max_timer(cc); | ||
171 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | ||
172 | if (ticks == 1) | ||
173 | ticks = 2; | ||
174 | else if (ticks > maxt) | ||
175 | ticks = maxt; | ||
176 | bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); | ||
177 | } else { | ||
178 | clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC; | ||
179 | bcma_core_set_clockmode(cc->core, clkmode); | ||
180 | if (ticks > maxt) | ||
181 | ticks = maxt; | ||
182 | /* instant NMI */ | ||
183 | bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); | ||
184 | } | ||
185 | return ticks; | ||
81 | } | 186 | } |
82 | 187 | ||
83 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) | 188 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) |
@@ -131,8 +236,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) | |||
131 | struct bcma_serial_port *ports = cc->serial_ports; | 236 | struct bcma_serial_port *ports = cc->serial_ports; |
132 | 237 | ||
133 | if (ccrev >= 11 && ccrev != 15) { | 238 | if (ccrev >= 11 && ccrev != 15) { |
134 | /* Fixed ALP clock */ | 239 | baud_base = bcma_chipco_alp_clock(cc); |
135 | baud_base = bcma_pmu_alp_clock(cc); | ||
136 | if (ccrev >= 21) { | 240 | if (ccrev >= 21) { |
137 | /* Turn off UART clock before switching clocksource. */ | 241 | /* Turn off UART clock before switching clocksource. */ |
138 | bcma_cc_write32(cc, BCMA_CC_CORECTL, | 242 | bcma_cc_write32(cc, BCMA_CC_CORECTL, |
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index e56449506695..e6b5c89469dc 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -538,7 +538,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge); | |||
538 | static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) | 538 | static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) |
539 | { | 539 | { |
540 | struct resource *res; | 540 | struct resource *res; |
541 | int pos; | 541 | int pos, err; |
542 | 542 | ||
543 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | 543 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { |
544 | /* This is not a device on the PCI-core bridge. */ | 544 | /* This is not a device on the PCI-core bridge. */ |
@@ -551,8 +551,12 @@ static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) | |||
551 | 551 | ||
552 | for (pos = 0; pos < 6; pos++) { | 552 | for (pos = 0; pos < 6; pos++) { |
553 | res = &dev->resource[pos]; | 553 | res = &dev->resource[pos]; |
554 | if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) | 554 | if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) { |
555 | pci_assign_resource(dev, pos); | 555 | err = pci_assign_resource(dev, pos); |
556 | if (err) | ||
557 | pr_err("PCI: Problem fixing up the addresses on %s\n", | ||
558 | pci_name(dev)); | ||
559 | } | ||
556 | } | 560 | } |
557 | } | 561 | } |
558 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); | 562 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index a9718893000b..debd4f142f93 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -165,6 +165,12 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
165 | } | 165 | } |
166 | #endif | 166 | #endif |
167 | 167 | ||
168 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | ||
169 | err = bcma_chipco_watchdog_register(&bus->drv_cc); | ||
170 | if (err) | ||
171 | bcma_err(bus, "Error registering watchdog driver\n"); | ||
172 | } | ||
173 | |||
168 | return 0; | 174 | return 0; |
169 | } | 175 | } |
170 | 176 | ||
@@ -177,6 +183,8 @@ static void bcma_unregister_cores(struct bcma_bus *bus) | |||
177 | if (core->dev_registered) | 183 | if (core->dev_registered) |
178 | device_unregister(&core->dev); | 184 | device_unregister(&core->dev); |
179 | } | 185 | } |
186 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | ||
187 | platform_device_unregister(bus->drv_cc.watchdog); | ||
180 | } | 188 | } |
181 | 189 | ||
182 | int __devinit bcma_bus_register(struct bcma_bus *bus) | 190 | int __devinit bcma_bus_register(struct bcma_bus *bus) |
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 154a4965be4f..3d339e04efb7 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1761,7 +1761,7 @@ static const struct ieee80211_ops adm8211_ops = { | |||
1761 | .get_tsf = adm8211_get_tsft | 1761 | .get_tsf = adm8211_get_tsft |
1762 | }; | 1762 | }; |
1763 | 1763 | ||
1764 | static int __devinit adm8211_probe(struct pci_dev *pdev, | 1764 | static int adm8211_probe(struct pci_dev *pdev, |
1765 | const struct pci_device_id *id) | 1765 | const struct pci_device_id *id) |
1766 | { | 1766 | { |
1767 | struct ieee80211_hw *dev; | 1767 | struct ieee80211_hw *dev; |
@@ -1935,7 +1935,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, | |||
1935 | } | 1935 | } |
1936 | 1936 | ||
1937 | 1937 | ||
1938 | static void __devexit adm8211_remove(struct pci_dev *pdev) | 1938 | static void adm8211_remove(struct pci_dev *pdev) |
1939 | { | 1939 | { |
1940 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); | 1940 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); |
1941 | struct adm8211_priv *priv; | 1941 | struct adm8211_priv *priv; |
@@ -1985,7 +1985,7 @@ static struct pci_driver adm8211_driver = { | |||
1985 | .name = "adm8211", | 1985 | .name = "adm8211", |
1986 | .id_table = adm8211_pci_id_table, | 1986 | .id_table = adm8211_pci_id_table, |
1987 | .probe = adm8211_probe, | 1987 | .probe = adm8211_probe, |
1988 | .remove = __devexit_p(adm8211_remove), | 1988 | .remove = adm8211_remove, |
1989 | #ifdef CONFIG_PM | 1989 | #ifdef CONFIG_PM |
1990 | .suspend = adm8211_suspend, | 1990 | .suspend = adm8211_suspend, |
1991 | .resume = adm8211_resume, | 1991 | .resume = adm8211_resume, |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 57f7db1ac31b..53295418f576 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -78,7 +78,7 @@ static struct pci_driver airo_driver = { | |||
78 | .name = DRV_NAME, | 78 | .name = DRV_NAME, |
79 | .id_table = card_ids, | 79 | .id_table = card_ids, |
80 | .probe = airo_pci_probe, | 80 | .probe = airo_pci_probe, |
81 | .remove = __devexit_p(airo_pci_remove), | 81 | .remove = airo_pci_remove, |
82 | .suspend = airo_pci_suspend, | 82 | .suspend = airo_pci_suspend, |
83 | .resume = airo_pci_resume, | 83 | .resume = airo_pci_resume, |
84 | }; | 84 | }; |
@@ -5584,7 +5584,7 @@ static void timer_func( struct net_device *dev ) { | |||
5584 | } | 5584 | } |
5585 | 5585 | ||
5586 | #ifdef CONFIG_PCI | 5586 | #ifdef CONFIG_PCI |
5587 | static int __devinit airo_pci_probe(struct pci_dev *pdev, | 5587 | static int airo_pci_probe(struct pci_dev *pdev, |
5588 | const struct pci_device_id *pent) | 5588 | const struct pci_device_id *pent) |
5589 | { | 5589 | { |
5590 | struct net_device *dev; | 5590 | struct net_device *dev; |
@@ -5606,7 +5606,7 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev, | |||
5606 | return 0; | 5606 | return 0; |
5607 | } | 5607 | } |
5608 | 5608 | ||
5609 | static void __devexit airo_pci_remove(struct pci_dev *pdev) | 5609 | static void airo_pci_remove(struct pci_dev *pdev) |
5610 | { | 5610 | { |
5611 | struct net_device *dev = pci_get_drvdata(pdev); | 5611 | struct net_device *dev = pci_get_drvdata(pdev); |
5612 | 5612 | ||
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index c25dcf192fec..1a67a4f829fe 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -1,4 +1,7 @@ | |||
1 | menuconfig ATH_COMMON | 1 | config ATH_COMMON |
2 | tristate | ||
3 | |||
4 | menuconfig ATH_CARDS | ||
2 | tristate "Atheros Wireless Cards" | 5 | tristate "Atheros Wireless Cards" |
3 | depends on CFG80211 && (!UML || BROKEN) | 6 | depends on CFG80211 && (!UML || BROKEN) |
4 | ---help--- | 7 | ---help--- |
@@ -14,7 +17,7 @@ menuconfig ATH_COMMON | |||
14 | 17 | ||
15 | http://wireless.kernel.org/en/users/Drivers/Atheros | 18 | http://wireless.kernel.org/en/users/Drivers/Atheros |
16 | 19 | ||
17 | if ATH_COMMON | 20 | if ATH_CARDS |
18 | 21 | ||
19 | config ATH_DEBUG | 22 | config ATH_DEBUG |
20 | bool "Atheros wireless debugging" | 23 | bool "Atheros wireless debugging" |
diff --git a/drivers/net/wireless/ath/ar5523/Kconfig b/drivers/net/wireless/ath/ar5523/Kconfig index 11d99ee8de51..0d320cc7769b 100644 --- a/drivers/net/wireless/ath/ar5523/Kconfig +++ b/drivers/net/wireless/ath/ar5523/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config AR5523 | 1 | config AR5523 |
2 | tristate "Atheros AR5523 wireless driver support" | 2 | tristate "Atheros AR5523 wireless driver support" |
3 | depends on MAC80211 && USB | 3 | depends on MAC80211 && USB |
4 | select ATH_COMMON | ||
4 | select FW_LOADER | 5 | select FW_LOADER |
5 | ---help--- | 6 | ---help--- |
6 | This module add support for AR5523 based USB dongles such as D-Link | 7 | This module add support for AR5523 based USB dongles such as D-Link |
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index 338c5c42357d..c9f81a388f15 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config ATH5K | 1 | config ATH5K |
2 | tristate "Atheros 5xxx wireless cards support" | 2 | tristate "Atheros 5xxx wireless cards support" |
3 | depends on (PCI || ATHEROS_AR231X) && MAC80211 | 3 | depends on (PCI || ATHEROS_AR231X) && MAC80211 |
4 | select ATH_COMMON | ||
4 | select MAC80211_LEDS | 5 | select MAC80211_LEDS |
5 | select LEDS_CLASS | 6 | select LEDS_CLASS |
6 | select NEW_LEDS | 7 | select NEW_LEDS |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 2fd5bab2e22a..3a5a61e03922 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -2435,7 +2435,7 @@ static const struct ieee80211_iface_combination if_comb = { | |||
2435 | .num_different_channels = 1, | 2435 | .num_different_channels = 1, |
2436 | }; | 2436 | }; |
2437 | 2437 | ||
2438 | int __devinit | 2438 | int |
2439 | ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) | 2439 | ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) |
2440 | { | 2440 | { |
2441 | struct ieee80211_hw *hw = ah->hw; | 2441 | struct ieee80211_hw *hw = ah->hw; |
@@ -2861,7 +2861,7 @@ static void ath5k_reset_work(struct work_struct *work) | |||
2861 | mutex_unlock(&ah->lock); | 2861 | mutex_unlock(&ah->lock); |
2862 | } | 2862 | } |
2863 | 2863 | ||
2864 | static int __devinit | 2864 | static int |
2865 | ath5k_init(struct ieee80211_hw *hw) | 2865 | ath5k_init(struct ieee80211_hw *hw) |
2866 | { | 2866 | { |
2867 | 2867 | ||
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index b9f708a45f4e..f77ef36acf87 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c | |||
@@ -158,7 +158,7 @@ void ath5k_unregister_leds(struct ath5k_hw *ah) | |||
158 | ath5k_unregister_led(&ah->tx_led); | 158 | ath5k_unregister_led(&ah->tx_led); |
159 | } | 159 | } |
160 | 160 | ||
161 | int __devinit ath5k_init_leds(struct ath5k_hw *ah) | 161 | int ath5k_init_leds(struct ath5k_hw *ah) |
162 | { | 162 | { |
163 | int ret = 0; | 163 | int ret = 0; |
164 | struct ieee80211_hw *hw = ah->hw; | 164 | struct ieee80211_hw *hw = ah->hw; |
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index dff48fbc63bf..859db7c34f87 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -155,7 +155,7 @@ static const struct ath_bus_ops ath_pci_bus_ops = { | |||
155 | * PCI Initialization * | 155 | * PCI Initialization * |
156 | \********************/ | 156 | \********************/ |
157 | 157 | ||
158 | static int __devinit | 158 | static int |
159 | ath5k_pci_probe(struct pci_dev *pdev, | 159 | ath5k_pci_probe(struct pci_dev *pdev, |
160 | const struct pci_device_id *id) | 160 | const struct pci_device_id *id) |
161 | { | 161 | { |
@@ -285,7 +285,7 @@ err: | |||
285 | return ret; | 285 | return ret; |
286 | } | 286 | } |
287 | 287 | ||
288 | static void __devexit | 288 | static void |
289 | ath5k_pci_remove(struct pci_dev *pdev) | 289 | ath5k_pci_remove(struct pci_dev *pdev) |
290 | { | 290 | { |
291 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 291 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
@@ -336,7 +336,7 @@ static struct pci_driver ath5k_pci_driver = { | |||
336 | .name = KBUILD_MODNAME, | 336 | .name = KBUILD_MODNAME, |
337 | .id_table = ath5k_pci_id_table, | 337 | .id_table = ath5k_pci_id_table, |
338 | .probe = ath5k_pci_probe, | 338 | .probe = ath5k_pci_probe, |
339 | .remove = __devexit_p(ath5k_pci_remove), | 339 | .remove = ath5k_pci_remove, |
340 | .driver.pm = ATH5K_PM_OPS, | 340 | .driver.pm = ATH5K_PM_OPS, |
341 | }; | 341 | }; |
342 | 342 | ||
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index c7aa6646123e..5fc15bf8be09 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -17,6 +17,7 @@ config ATH9K_BTCOEX_SUPPORT | |||
17 | config ATH9K | 17 | config ATH9K |
18 | tristate "Atheros 802.11n wireless cards support" | 18 | tristate "Atheros 802.11n wireless cards support" |
19 | depends on MAC80211 | 19 | depends on MAC80211 |
20 | select ATH_COMMON | ||
20 | select ATH9K_HW | 21 | select ATH9K_HW |
21 | select MAC80211_LEDS | 22 | select MAC80211_LEDS |
22 | select LEDS_CLASS | 23 | select LEDS_CLASS |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 80bab1b8447a..86e26a19efda 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -259,9 +259,10 @@ struct ath_atx_tid { | |||
259 | }; | 259 | }; |
260 | 260 | ||
261 | struct ath_node { | 261 | struct ath_node { |
262 | struct ath_softc *sc; | ||
262 | struct ieee80211_sta *sta; /* station struct we're part of */ | 263 | struct ieee80211_sta *sta; /* station struct we're part of */ |
263 | struct ieee80211_vif *vif; /* interface with which we're associated */ | 264 | struct ieee80211_vif *vif; /* interface with which we're associated */ |
264 | struct ath_atx_tid tid[WME_NUM_TID]; | 265 | struct ath_atx_tid tid[IEEE80211_NUM_TIDS]; |
265 | struct ath_atx_ac ac[IEEE80211_NUM_ACS]; | 266 | struct ath_atx_ac ac[IEEE80211_NUM_ACS]; |
266 | int ps_key; | 267 | int ps_key; |
267 | 268 | ||
@@ -269,6 +270,10 @@ struct ath_node { | |||
269 | u8 mpdudensity; | 270 | u8 mpdudensity; |
270 | 271 | ||
271 | bool sleeping; | 272 | bool sleeping; |
273 | |||
274 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | ||
275 | struct dentry *node_stat; | ||
276 | #endif | ||
272 | }; | 277 | }; |
273 | 278 | ||
274 | #define AGGR_CLEANUP BIT(1) | 279 | #define AGGR_CLEANUP BIT(1) |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 76b543900314..5f845beeb18b 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | /* Common header for Atheros 802.11n base driver cores */ | 24 | /* Common header for Atheros 802.11n base driver cores */ |
25 | 25 | ||
26 | #define WME_NUM_TID 16 | ||
27 | #define WME_BA_BMP_SIZE 64 | 26 | #define WME_BA_BMP_SIZE 64 |
28 | #define WME_MAX_BA WME_BA_BMP_SIZE | 27 | #define WME_MAX_BA WME_BA_BMP_SIZE |
29 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) | 28 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 939308c25712..13ff9edc2401 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -1509,6 +1509,215 @@ static const struct file_operations fops_btcoex = { | |||
1509 | }; | 1509 | }; |
1510 | #endif | 1510 | #endif |
1511 | 1511 | ||
1512 | static ssize_t read_file_node_stat(struct file *file, char __user *user_buf, | ||
1513 | size_t count, loff_t *ppos) | ||
1514 | { | ||
1515 | struct ath_node *an = file->private_data; | ||
1516 | struct ath_softc *sc = an->sc; | ||
1517 | struct ath_atx_tid *tid; | ||
1518 | struct ath_atx_ac *ac; | ||
1519 | struct ath_txq *txq; | ||
1520 | u32 len = 0, size = 4096; | ||
1521 | char *buf; | ||
1522 | size_t retval; | ||
1523 | int tidno, acno; | ||
1524 | |||
1525 | buf = kzalloc(size, GFP_KERNEL); | ||
1526 | if (buf == NULL) | ||
1527 | return -ENOMEM; | ||
1528 | |||
1529 | if (!an->sta->ht_cap.ht_supported) { | ||
1530 | len = snprintf(buf, size, "%s\n", | ||
1531 | "HT not supported"); | ||
1532 | goto exit; | ||
1533 | } | ||
1534 | |||
1535 | len = snprintf(buf, size, "Max-AMPDU: %d\n", | ||
1536 | an->maxampdu); | ||
1537 | len += snprintf(buf + len, size - len, "MPDU Density: %d\n\n", | ||
1538 | an->mpdudensity); | ||
1539 | |||
1540 | len += snprintf(buf + len, size - len, | ||
1541 | "%2s%7s\n", "AC", "SCHED"); | ||
1542 | |||
1543 | for (acno = 0, ac = &an->ac[acno]; | ||
1544 | acno < IEEE80211_NUM_ACS; acno++, ac++) { | ||
1545 | txq = ac->txq; | ||
1546 | ath_txq_lock(sc, txq); | ||
1547 | len += snprintf(buf + len, size - len, | ||
1548 | "%2d%7d\n", | ||
1549 | acno, ac->sched); | ||
1550 | ath_txq_unlock(sc, txq); | ||
1551 | } | ||
1552 | |||
1553 | len += snprintf(buf + len, size - len, | ||
1554 | "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n", | ||
1555 | "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", | ||
1556 | "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); | ||
1557 | |||
1558 | for (tidno = 0, tid = &an->tid[tidno]; | ||
1559 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { | ||
1560 | txq = tid->ac->txq; | ||
1561 | ath_txq_lock(sc, txq); | ||
1562 | len += snprintf(buf + len, size - len, | ||
1563 | "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", | ||
1564 | tid->tidno, tid->seq_start, tid->seq_next, | ||
1565 | tid->baw_size, tid->baw_head, tid->baw_tail, | ||
1566 | tid->bar_index, tid->sched, tid->paused); | ||
1567 | ath_txq_unlock(sc, txq); | ||
1568 | } | ||
1569 | exit: | ||
1570 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1571 | kfree(buf); | ||
1572 | |||
1573 | return retval; | ||
1574 | } | ||
1575 | |||
1576 | static const struct file_operations fops_node_stat = { | ||
1577 | .read = read_file_node_stat, | ||
1578 | .open = simple_open, | ||
1579 | .owner = THIS_MODULE, | ||
1580 | .llseek = default_llseek, | ||
1581 | }; | ||
1582 | |||
1583 | void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | ||
1584 | struct ieee80211_vif *vif, | ||
1585 | struct ieee80211_sta *sta, | ||
1586 | struct dentry *dir) | ||
1587 | { | ||
1588 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
1589 | an->node_stat = debugfs_create_file("node_stat", S_IRUGO, | ||
1590 | dir, an, &fops_node_stat); | ||
1591 | } | ||
1592 | |||
1593 | void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw, | ||
1594 | struct ieee80211_vif *vif, | ||
1595 | struct ieee80211_sta *sta, | ||
1596 | struct dentry *dir) | ||
1597 | { | ||
1598 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
1599 | debugfs_remove(an->node_stat); | ||
1600 | } | ||
1601 | |||
1602 | /* Ethtool support for get-stats */ | ||
1603 | |||
1604 | #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" | ||
1605 | static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
1606 | "tx_pkts_nic", | ||
1607 | "tx_bytes_nic", | ||
1608 | "rx_pkts_nic", | ||
1609 | "rx_bytes_nic", | ||
1610 | AMKSTR(d_tx_pkts), | ||
1611 | AMKSTR(d_tx_bytes), | ||
1612 | AMKSTR(d_tx_mpdus_queued), | ||
1613 | AMKSTR(d_tx_mpdus_completed), | ||
1614 | AMKSTR(d_tx_mpdu_xretries), | ||
1615 | AMKSTR(d_tx_aggregates), | ||
1616 | AMKSTR(d_tx_ampdus_queued_hw), | ||
1617 | AMKSTR(d_tx_ampdus_queued_sw), | ||
1618 | AMKSTR(d_tx_ampdus_completed), | ||
1619 | AMKSTR(d_tx_ampdu_retries), | ||
1620 | AMKSTR(d_tx_ampdu_xretries), | ||
1621 | AMKSTR(d_tx_fifo_underrun), | ||
1622 | AMKSTR(d_tx_op_exceeded), | ||
1623 | AMKSTR(d_tx_timer_expiry), | ||
1624 | AMKSTR(d_tx_desc_cfg_err), | ||
1625 | AMKSTR(d_tx_data_underrun), | ||
1626 | AMKSTR(d_tx_delim_underrun), | ||
1627 | "d_rx_decrypt_crc_err", | ||
1628 | "d_rx_phy_err", | ||
1629 | "d_rx_mic_err", | ||
1630 | "d_rx_pre_delim_crc_err", | ||
1631 | "d_rx_post_delim_crc_err", | ||
1632 | "d_rx_decrypt_busy_err", | ||
1633 | |||
1634 | "d_rx_phyerr_radar", | ||
1635 | "d_rx_phyerr_ofdm_timing", | ||
1636 | "d_rx_phyerr_cck_timing", | ||
1637 | |||
1638 | }; | ||
1639 | #define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats) | ||
1640 | |||
1641 | void ath9k_get_et_strings(struct ieee80211_hw *hw, | ||
1642 | struct ieee80211_vif *vif, | ||
1643 | u32 sset, u8 *data) | ||
1644 | { | ||
1645 | if (sset == ETH_SS_STATS) | ||
1646 | memcpy(data, *ath9k_gstrings_stats, | ||
1647 | sizeof(ath9k_gstrings_stats)); | ||
1648 | } | ||
1649 | |||
1650 | int ath9k_get_et_sset_count(struct ieee80211_hw *hw, | ||
1651 | struct ieee80211_vif *vif, int sset) | ||
1652 | { | ||
1653 | if (sset == ETH_SS_STATS) | ||
1654 | return ATH9K_SSTATS_LEN; | ||
1655 | return 0; | ||
1656 | } | ||
1657 | |||
1658 | #define AWDATA(elem) \ | ||
1659 | do { \ | ||
1660 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \ | ||
1661 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem; \ | ||
1662 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem; \ | ||
1663 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem; \ | ||
1664 | } while (0) | ||
1665 | |||
1666 | #define AWDATA_RX(elem) \ | ||
1667 | do { \ | ||
1668 | data[i++] = sc->debug.stats.rxstats.elem; \ | ||
1669 | } while (0) | ||
1670 | |||
1671 | void ath9k_get_et_stats(struct ieee80211_hw *hw, | ||
1672 | struct ieee80211_vif *vif, | ||
1673 | struct ethtool_stats *stats, u64 *data) | ||
1674 | { | ||
1675 | struct ath_softc *sc = hw->priv; | ||
1676 | int i = 0; | ||
1677 | |||
1678 | data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all + | ||
1679 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all + | ||
1680 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all + | ||
1681 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all); | ||
1682 | data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all + | ||
1683 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all + | ||
1684 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all + | ||
1685 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all); | ||
1686 | AWDATA_RX(rx_pkts_all); | ||
1687 | AWDATA_RX(rx_bytes_all); | ||
1688 | |||
1689 | AWDATA(tx_pkts_all); | ||
1690 | AWDATA(tx_bytes_all); | ||
1691 | AWDATA(queued); | ||
1692 | AWDATA(completed); | ||
1693 | AWDATA(xretries); | ||
1694 | AWDATA(a_aggr); | ||
1695 | AWDATA(a_queued_hw); | ||
1696 | AWDATA(a_queued_sw); | ||
1697 | AWDATA(a_completed); | ||
1698 | AWDATA(a_retries); | ||
1699 | AWDATA(a_xretries); | ||
1700 | AWDATA(fifo_underrun); | ||
1701 | AWDATA(xtxop); | ||
1702 | AWDATA(timer_exp); | ||
1703 | AWDATA(desc_cfg_err); | ||
1704 | AWDATA(data_underrun); | ||
1705 | AWDATA(delim_underrun); | ||
1706 | |||
1707 | AWDATA_RX(decrypt_crc_err); | ||
1708 | AWDATA_RX(phy_err); | ||
1709 | AWDATA_RX(mic_err); | ||
1710 | AWDATA_RX(pre_delim_crc_err); | ||
1711 | AWDATA_RX(post_delim_crc_err); | ||
1712 | AWDATA_RX(decrypt_busy_err); | ||
1713 | |||
1714 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]); | ||
1715 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]); | ||
1716 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]); | ||
1717 | |||
1718 | WARN_ON(i != ATH9K_SSTATS_LEN); | ||
1719 | } | ||
1720 | |||
1512 | int ath9k_init_debug(struct ath_hw *ah) | 1721 | int ath9k_init_debug(struct ath_hw *ah) |
1513 | { | 1722 | { |
1514 | struct ath_common *common = ath9k_hw_common(ah); | 1723 | struct ath_common *common = ath9k_hw_common(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index f9bee18de5a0..72d4893311b1 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -307,7 +307,22 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | |||
307 | struct ath_tx_status *ts, struct ath_txq *txq, | 307 | struct ath_tx_status *ts, struct ath_txq *txq, |
308 | unsigned int flags); | 308 | unsigned int flags); |
309 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); | 309 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); |
310 | 310 | int ath9k_get_et_sset_count(struct ieee80211_hw *hw, | |
311 | struct ieee80211_vif *vif, int sset); | ||
312 | void ath9k_get_et_stats(struct ieee80211_hw *hw, | ||
313 | struct ieee80211_vif *vif, | ||
314 | struct ethtool_stats *stats, u64 *data); | ||
315 | void ath9k_get_et_strings(struct ieee80211_hw *hw, | ||
316 | struct ieee80211_vif *vif, | ||
317 | u32 sset, u8 *data); | ||
318 | void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | ||
319 | struct ieee80211_vif *vif, | ||
320 | struct ieee80211_sta *sta, | ||
321 | struct dentry *dir); | ||
322 | void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw, | ||
323 | struct ieee80211_vif *vif, | ||
324 | struct ieee80211_sta *sta, | ||
325 | struct dentry *dir); | ||
311 | #else | 326 | #else |
312 | 327 | ||
313 | #define RX_STAT_INC(c) /* NOP */ | 328 | #define RX_STAT_INC(c) /* NOP */ |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 0653dbc99e31..be30a9af1528 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -331,6 +331,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
331 | u8 density; | 331 | u8 density; |
332 | an = (struct ath_node *)sta->drv_priv; | 332 | an = (struct ath_node *)sta->drv_priv; |
333 | 333 | ||
334 | an->sc = sc; | ||
334 | an->sta = sta; | 335 | an->sta = sta; |
335 | an->vif = vif; | 336 | an->vif = vif; |
336 | 337 | ||
@@ -1882,133 +1883,6 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | |||
1882 | return 0; | 1883 | return 0; |
1883 | } | 1884 | } |
1884 | 1885 | ||
1885 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
1886 | |||
1887 | /* Ethtool support for get-stats */ | ||
1888 | |||
1889 | #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" | ||
1890 | static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
1891 | "tx_pkts_nic", | ||
1892 | "tx_bytes_nic", | ||
1893 | "rx_pkts_nic", | ||
1894 | "rx_bytes_nic", | ||
1895 | AMKSTR(d_tx_pkts), | ||
1896 | AMKSTR(d_tx_bytes), | ||
1897 | AMKSTR(d_tx_mpdus_queued), | ||
1898 | AMKSTR(d_tx_mpdus_completed), | ||
1899 | AMKSTR(d_tx_mpdu_xretries), | ||
1900 | AMKSTR(d_tx_aggregates), | ||
1901 | AMKSTR(d_tx_ampdus_queued_hw), | ||
1902 | AMKSTR(d_tx_ampdus_queued_sw), | ||
1903 | AMKSTR(d_tx_ampdus_completed), | ||
1904 | AMKSTR(d_tx_ampdu_retries), | ||
1905 | AMKSTR(d_tx_ampdu_xretries), | ||
1906 | AMKSTR(d_tx_fifo_underrun), | ||
1907 | AMKSTR(d_tx_op_exceeded), | ||
1908 | AMKSTR(d_tx_timer_expiry), | ||
1909 | AMKSTR(d_tx_desc_cfg_err), | ||
1910 | AMKSTR(d_tx_data_underrun), | ||
1911 | AMKSTR(d_tx_delim_underrun), | ||
1912 | |||
1913 | "d_rx_decrypt_crc_err", | ||
1914 | "d_rx_phy_err", | ||
1915 | "d_rx_mic_err", | ||
1916 | "d_rx_pre_delim_crc_err", | ||
1917 | "d_rx_post_delim_crc_err", | ||
1918 | "d_rx_decrypt_busy_err", | ||
1919 | |||
1920 | "d_rx_phyerr_radar", | ||
1921 | "d_rx_phyerr_ofdm_timing", | ||
1922 | "d_rx_phyerr_cck_timing", | ||
1923 | |||
1924 | }; | ||
1925 | #define ATH9K_SSTATS_LEN ARRAY_SIZE(ath9k_gstrings_stats) | ||
1926 | |||
1927 | static void ath9k_get_et_strings(struct ieee80211_hw *hw, | ||
1928 | struct ieee80211_vif *vif, | ||
1929 | u32 sset, u8 *data) | ||
1930 | { | ||
1931 | if (sset == ETH_SS_STATS) | ||
1932 | memcpy(data, *ath9k_gstrings_stats, | ||
1933 | sizeof(ath9k_gstrings_stats)); | ||
1934 | } | ||
1935 | |||
1936 | static int ath9k_get_et_sset_count(struct ieee80211_hw *hw, | ||
1937 | struct ieee80211_vif *vif, int sset) | ||
1938 | { | ||
1939 | if (sset == ETH_SS_STATS) | ||
1940 | return ATH9K_SSTATS_LEN; | ||
1941 | return 0; | ||
1942 | } | ||
1943 | |||
1944 | #define AWDATA(elem) \ | ||
1945 | do { \ | ||
1946 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].elem; \ | ||
1947 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].elem; \ | ||
1948 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].elem; \ | ||
1949 | data[i++] = sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].elem; \ | ||
1950 | } while (0) | ||
1951 | |||
1952 | #define AWDATA_RX(elem) \ | ||
1953 | do { \ | ||
1954 | data[i++] = sc->debug.stats.rxstats.elem; \ | ||
1955 | } while (0) | ||
1956 | |||
1957 | static void ath9k_get_et_stats(struct ieee80211_hw *hw, | ||
1958 | struct ieee80211_vif *vif, | ||
1959 | struct ethtool_stats *stats, u64 *data) | ||
1960 | { | ||
1961 | struct ath_softc *sc = hw->priv; | ||
1962 | int i = 0; | ||
1963 | |||
1964 | data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all + | ||
1965 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all + | ||
1966 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all + | ||
1967 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all); | ||
1968 | data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all + | ||
1969 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all + | ||
1970 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all + | ||
1971 | sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all); | ||
1972 | AWDATA_RX(rx_pkts_all); | ||
1973 | AWDATA_RX(rx_bytes_all); | ||
1974 | |||
1975 | AWDATA(tx_pkts_all); | ||
1976 | AWDATA(tx_bytes_all); | ||
1977 | AWDATA(queued); | ||
1978 | AWDATA(completed); | ||
1979 | AWDATA(xretries); | ||
1980 | AWDATA(a_aggr); | ||
1981 | AWDATA(a_queued_hw); | ||
1982 | AWDATA(a_queued_sw); | ||
1983 | AWDATA(a_completed); | ||
1984 | AWDATA(a_retries); | ||
1985 | AWDATA(a_xretries); | ||
1986 | AWDATA(fifo_underrun); | ||
1987 | AWDATA(xtxop); | ||
1988 | AWDATA(timer_exp); | ||
1989 | AWDATA(desc_cfg_err); | ||
1990 | AWDATA(data_underrun); | ||
1991 | AWDATA(delim_underrun); | ||
1992 | |||
1993 | AWDATA_RX(decrypt_crc_err); | ||
1994 | AWDATA_RX(phy_err); | ||
1995 | AWDATA_RX(mic_err); | ||
1996 | AWDATA_RX(pre_delim_crc_err); | ||
1997 | AWDATA_RX(post_delim_crc_err); | ||
1998 | AWDATA_RX(decrypt_busy_err); | ||
1999 | |||
2000 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_RADAR]); | ||
2001 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]); | ||
2002 | AWDATA_RX(phy_err_stats[ATH9K_PHYERR_CCK_TIMING]); | ||
2003 | |||
2004 | WARN_ON(i != ATH9K_SSTATS_LEN); | ||
2005 | } | ||
2006 | |||
2007 | /* End of ethtool get-stats functions */ | ||
2008 | |||
2009 | #endif | ||
2010 | |||
2011 | |||
2012 | #ifdef CONFIG_PM_SLEEP | 1886 | #ifdef CONFIG_PM_SLEEP |
2013 | 1887 | ||
2014 | static void ath9k_wow_map_triggers(struct ath_softc *sc, | 1888 | static void ath9k_wow_map_triggers(struct ath_softc *sc, |
@@ -2402,7 +2276,12 @@ struct ieee80211_ops ath9k_ops = { | |||
2402 | 2276 | ||
2403 | #ifdef CONFIG_ATH9K_DEBUGFS | 2277 | #ifdef CONFIG_ATH9K_DEBUGFS |
2404 | .get_et_sset_count = ath9k_get_et_sset_count, | 2278 | .get_et_sset_count = ath9k_get_et_sset_count, |
2405 | .get_et_stats = ath9k_get_et_stats, | 2279 | .get_et_stats = ath9k_get_et_stats, |
2406 | .get_et_strings = ath9k_get_et_strings, | 2280 | .get_et_strings = ath9k_get_et_strings, |
2281 | #endif | ||
2282 | |||
2283 | #if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) | ||
2284 | .sta_add_debugfs = ath9k_sta_add_debugfs, | ||
2285 | .sta_remove_debugfs = ath9k_sta_remove_debugfs, | ||
2407 | #endif | 2286 | #endif |
2408 | }; | 2287 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 706378ea3ba2..5c02702f21e7 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -257,8 +257,9 @@ static void ath_mci_set_concur_txprio(struct ath_softc *sc) | |||
257 | { | 257 | { |
258 | struct ath_btcoex *btcoex = &sc->btcoex; | 258 | struct ath_btcoex *btcoex = &sc->btcoex; |
259 | struct ath_mci_profile *mci = &btcoex->mci; | 259 | struct ath_mci_profile *mci = &btcoex->mci; |
260 | u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */ | 260 | u8 stomp_txprio[ATH_BTCOEX_STOMP_MAX]; |
261 | 261 | ||
262 | memset(stomp_txprio, 0, sizeof(stomp_txprio)); | ||
262 | if (mci->num_mgmt) { | 263 | if (mci->num_mgmt) { |
263 | stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO; | 264 | stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO; |
264 | if (!mci->num_pan && !mci->num_other_acl) | 265 | if (!mci->num_pan && !mci->num_other_acl) |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 9553203ee624..8e9b826f878b 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -287,7 +287,7 @@ static void ath_pci_remove(struct pci_dev *pdev) | |||
287 | pci_release_region(pdev, 0); | 287 | pci_release_region(pdev, 0); |
288 | } | 288 | } |
289 | 289 | ||
290 | #ifdef CONFIG_PM | 290 | #ifdef CONFIG_PM_SLEEP |
291 | 291 | ||
292 | static int ath_pci_suspend(struct device *device) | 292 | static int ath_pci_suspend(struct device *device) |
293 | { | 293 | { |
@@ -333,22 +333,15 @@ static int ath_pci_resume(struct device *device) | |||
333 | return 0; | 333 | return 0; |
334 | } | 334 | } |
335 | 335 | ||
336 | static const struct dev_pm_ops ath9k_pm_ops = { | 336 | static SIMPLE_DEV_PM_OPS(ath9k_pm_ops, ath_pci_suspend, ath_pci_resume); |
337 | .suspend = ath_pci_suspend, | ||
338 | .resume = ath_pci_resume, | ||
339 | .freeze = ath_pci_suspend, | ||
340 | .thaw = ath_pci_resume, | ||
341 | .poweroff = ath_pci_suspend, | ||
342 | .restore = ath_pci_resume, | ||
343 | }; | ||
344 | 337 | ||
345 | #define ATH9K_PM_OPS (&ath9k_pm_ops) | 338 | #define ATH9K_PM_OPS (&ath9k_pm_ops) |
346 | 339 | ||
347 | #else /* !CONFIG_PM */ | 340 | #else /* !CONFIG_PM_SLEEP */ |
348 | 341 | ||
349 | #define ATH9K_PM_OPS NULL | 342 | #define ATH9K_PM_OPS NULL |
350 | 343 | ||
351 | #endif /* !CONFIG_PM */ | 344 | #endif /* !CONFIG_PM_SLEEP */ |
352 | 345 | ||
353 | 346 | ||
354 | MODULE_DEVICE_TABLE(pci, ath_pci_id_table); | 347 | MODULE_DEVICE_TABLE(pci, ath_pci_id_table); |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 34130943f9de..90e48a0fafe5 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -312,7 +312,6 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) | |||
312 | } | 312 | } |
313 | 313 | ||
314 | bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); | 314 | bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); |
315 | bf->bf_next = NULL; | ||
316 | list_del(&bf->list); | 315 | list_del(&bf->list); |
317 | 316 | ||
318 | spin_unlock_bh(&sc->tx.txbuflock); | 317 | spin_unlock_bh(&sc->tx.txbuflock); |
@@ -1263,7 +1262,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | |||
1263 | int tidno; | 1262 | int tidno; |
1264 | 1263 | ||
1265 | for (tidno = 0, tid = &an->tid[tidno]; | 1264 | for (tidno = 0, tid = &an->tid[tidno]; |
1266 | tidno < WME_NUM_TID; tidno++, tid++) { | 1265 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { |
1267 | 1266 | ||
1268 | if (!tid->sched) | 1267 | if (!tid->sched) |
1269 | continue; | 1268 | continue; |
@@ -1297,7 +1296,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | |||
1297 | int tidno; | 1296 | int tidno; |
1298 | 1297 | ||
1299 | for (tidno = 0, tid = &an->tid[tidno]; | 1298 | for (tidno = 0, tid = &an->tid[tidno]; |
1300 | tidno < WME_NUM_TID; tidno++, tid++) { | 1299 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { |
1301 | 1300 | ||
1302 | ac = tid->ac; | 1301 | ac = tid->ac; |
1303 | txq = ac->txq; | 1302 | txq = ac->txq; |
@@ -2448,7 +2447,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2448 | int tidno, acno; | 2447 | int tidno, acno; |
2449 | 2448 | ||
2450 | for (tidno = 0, tid = &an->tid[tidno]; | 2449 | for (tidno = 0, tid = &an->tid[tidno]; |
2451 | tidno < WME_NUM_TID; | 2450 | tidno < IEEE80211_NUM_TIDS; |
2452 | tidno++, tid++) { | 2451 | tidno++, tid++) { |
2453 | tid->an = an; | 2452 | tid->an = an; |
2454 | tid->tidno = tidno; | 2453 | tid->tidno = tidno; |
@@ -2481,7 +2480,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
2481 | int tidno; | 2480 | int tidno; |
2482 | 2481 | ||
2483 | for (tidno = 0, tid = &an->tid[tidno]; | 2482 | for (tidno = 0, tid = &an->tid[tidno]; |
2484 | tidno < WME_NUM_TID; tidno++, tid++) { | 2483 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { |
2485 | 2484 | ||
2486 | ac = tid->ac; | 2485 | ac = tid->ac; |
2487 | txq = ac->txq; | 2486 | txq = ac->txq; |
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig index 267d5dcf82dc..13a204598766 100644 --- a/drivers/net/wireless/ath/carl9170/Kconfig +++ b/drivers/net/wireless/ath/carl9170/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config CARL9170 | 1 | config CARL9170 |
2 | tristate "Linux Community AR9170 802.11n USB support" | 2 | tristate "Linux Community AR9170 802.11n USB support" |
3 | depends on USB && MAC80211 && EXPERIMENTAL | 3 | depends on USB && MAC80211 && EXPERIMENTAL |
4 | select ATH_COMMON | ||
4 | select FW_LOADER | 5 | select FW_LOADER |
5 | select CRC32 | 6 | select CRC32 |
6 | help | 7 | help |
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 6d22382875bc..876a773fd0b4 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c | |||
@@ -814,6 +814,8 @@ static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len) | |||
814 | 814 | ||
815 | if (phy) | 815 | if (phy) |
816 | carl9170_rx_phy_status(ar, phy, &status); | 816 | carl9170_rx_phy_status(ar, phy, &status); |
817 | else | ||
818 | status.flag |= RX_FLAG_NO_SIGNAL_VAL; | ||
817 | 819 | ||
818 | if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status)) | 820 | if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status)) |
819 | goto drop; | 821 | goto drop; |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 84377cf580e0..ef4ec0da6e49 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -1485,6 +1485,13 @@ void carl9170_op_tx(struct ieee80211_hw *hw, | |||
1485 | } | 1485 | } |
1486 | 1486 | ||
1487 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1487 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1488 | /* to static code analyzers and reviewers: | ||
1489 | * mac80211 guarantees that a valid "sta" | ||
1490 | * reference is present, if a frame is to | ||
1491 | * be part of an ampdu. Hence any extra | ||
1492 | * sta == NULL checks are redundant in this | ||
1493 | * special case. | ||
1494 | */ | ||
1488 | run = carl9170_tx_ampdu_queue(ar, sta, skb); | 1495 | run = carl9170_tx_ampdu_queue(ar, sta, skb); |
1489 | if (run) | 1496 | if (run) |
1490 | carl9170_tx_ampdu(ar); | 1497 | carl9170_tx_ampdu(ar); |
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index 51e33b53386e..c1b159ebcffe 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c | |||
@@ -45,11 +45,11 @@ static struct pci_driver atmel_driver = { | |||
45 | .name = "atmel", | 45 | .name = "atmel", |
46 | .id_table = card_ids, | 46 | .id_table = card_ids, |
47 | .probe = atmel_pci_probe, | 47 | .probe = atmel_pci_probe, |
48 | .remove = __devexit_p(atmel_pci_remove), | 48 | .remove = atmel_pci_remove, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | 51 | ||
52 | static int __devinit atmel_pci_probe(struct pci_dev *pdev, | 52 | static int atmel_pci_probe(struct pci_dev *pdev, |
53 | const struct pci_device_id *pent) | 53 | const struct pci_device_id *pent) |
54 | { | 54 | { |
55 | struct net_device *dev; | 55 | struct net_device *dev; |
@@ -69,7 +69,7 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev, | |||
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | 71 | ||
72 | static void __devexit atmel_pci_remove(struct pci_dev *pdev) | 72 | static void atmel_pci_remove(struct pci_dev *pdev) |
73 | { | 73 | { |
74 | stop_atmel_card(pci_get_drvdata(pdev)); | 74 | stop_atmel_card(pci_get_drvdata(pdev)); |
75 | } | 75 | } |
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 714cad649c45..f2ea2ceec8a9 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c | |||
@@ -60,7 +60,7 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev) | |||
60 | # define b43_pcmcia_resume NULL | 60 | # define b43_pcmcia_resume NULL |
61 | #endif /* CONFIG_PM */ | 61 | #endif /* CONFIG_PM */ |
62 | 62 | ||
63 | static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) | 63 | static int b43_pcmcia_probe(struct pcmcia_device *dev) |
64 | { | 64 | { |
65 | struct ssb_bus *ssb; | 65 | struct ssb_bus *ssb; |
66 | int err = -ENOMEM; | 66 | int err = -ENOMEM; |
@@ -110,7 +110,7 @@ out_error: | |||
110 | return err; | 110 | return err; |
111 | } | 111 | } |
112 | 112 | ||
113 | static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev) | 113 | static void b43_pcmcia_remove(struct pcmcia_device *dev) |
114 | { | 114 | { |
115 | struct ssb_bus *ssb = dev->priv; | 115 | struct ssb_bus *ssb = dev->priv; |
116 | 116 | ||
@@ -125,7 +125,7 @@ static struct pcmcia_driver b43_pcmcia_driver = { | |||
125 | .name = "b43-pcmcia", | 125 | .name = "b43-pcmcia", |
126 | .id_table = b43_pcmcia_tbl, | 126 | .id_table = b43_pcmcia_tbl, |
127 | .probe = b43_pcmcia_probe, | 127 | .probe = b43_pcmcia_probe, |
128 | .remove = __devexit_p(b43_pcmcia_remove), | 128 | .remove = b43_pcmcia_remove, |
129 | .suspend = b43_pcmcia_suspend, | 129 | .suspend = b43_pcmcia_suspend, |
130 | .resume = b43_pcmcia_resume, | 130 | .resume = b43_pcmcia_resume, |
131 | }; | 131 | }; |
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c index a54fb2d29089..59a521800694 100644 --- a/drivers/net/wireless/b43/sdio.c +++ b/drivers/net/wireless/b43/sdio.c | |||
@@ -93,7 +93,7 @@ void b43_sdio_free_irq(struct b43_wldev *dev) | |||
93 | sdio->irq_handler = NULL; | 93 | sdio->irq_handler = NULL; |
94 | } | 94 | } |
95 | 95 | ||
96 | static int __devinit b43_sdio_probe(struct sdio_func *func, | 96 | static int b43_sdio_probe(struct sdio_func *func, |
97 | const struct sdio_device_id *id) | 97 | const struct sdio_device_id *id) |
98 | { | 98 | { |
99 | struct b43_sdio *sdio; | 99 | struct b43_sdio *sdio; |
@@ -171,7 +171,7 @@ out: | |||
171 | return error; | 171 | return error; |
172 | } | 172 | } |
173 | 173 | ||
174 | static void __devexit b43_sdio_remove(struct sdio_func *func) | 174 | static void b43_sdio_remove(struct sdio_func *func) |
175 | { | 175 | { |
176 | struct b43_sdio *sdio = sdio_get_drvdata(func); | 176 | struct b43_sdio *sdio = sdio_get_drvdata(func); |
177 | 177 | ||
@@ -193,7 +193,7 @@ static struct sdio_driver b43_sdio_driver = { | |||
193 | .name = "b43-sdio", | 193 | .name = "b43-sdio", |
194 | .id_table = b43_sdio_ids, | 194 | .id_table = b43_sdio_ids, |
195 | .probe = b43_sdio_probe, | 195 | .probe = b43_sdio_probe, |
196 | .remove = __devexit_p(b43_sdio_remove), | 196 | .remove = b43_sdio_remove, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | int b43_sdio_init(void) | 199 | int b43_sdio_init(void) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index fa8fc4433417..7a00c4614baf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c | |||
@@ -314,7 +314,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work) | |||
314 | while ((event = brcmf_fweh_dequeue_event(fweh))) { | 314 | while ((event = brcmf_fweh_dequeue_event(fweh))) { |
315 | ifp = drvr->iflist[event->ifidx]; | 315 | ifp = drvr->iflist[event->ifidx]; |
316 | 316 | ||
317 | brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM:\n", | 317 | brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n", |
318 | brcmf_fweh_event_name(event->code), event->code, | 318 | brcmf_fweh_event_name(event->code), event->code, |
319 | event->emsg.ifidx, event->emsg.bsscfgidx, | 319 | event->emsg.ifidx, event->emsg.bsscfgidx, |
320 | event->emsg.addr); | 320 | event->emsg.addr); |
@@ -337,7 +337,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work) | |||
337 | emsg.version, emsg.flags, emsg.status, emsg.reason); | 337 | emsg.version, emsg.flags, emsg.status, emsg.reason); |
338 | brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data, | 338 | brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data, |
339 | min_t(u32, emsg.datalen, 64), | 339 | min_t(u32, emsg.datalen, 64), |
340 | "appended:"); | 340 | "event payload, len=%d\n", emsg.datalen); |
341 | 341 | ||
342 | /* special handling of interface event */ | 342 | /* special handling of interface event */ |
343 | if (event->code == BRCMF_E_IF) { | 343 | if (event->code == BRCMF_E_IF) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index b39246a630df..240a2eafead5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h | |||
@@ -158,7 +158,7 @@ typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, | |||
158 | */ | 158 | */ |
159 | struct brcmf_fweh_info { | 159 | struct brcmf_fweh_info { |
160 | struct work_struct event_work; | 160 | struct work_struct event_work; |
161 | struct spinlock evt_q_lock; | 161 | spinlock_t evt_q_lock; |
162 | struct list_head event_q; | 162 | struct list_head event_q; |
163 | int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp, | 163 | int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp, |
164 | const struct brcmf_event_msg *evtmsg, | 164 | const struct brcmf_event_msg *evtmsg, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 2044fdb55558..96bc349d7f6c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -447,7 +447,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
447 | struct vif_params *params) | 447 | struct vif_params *params) |
448 | { | 448 | { |
449 | struct brcmf_if *ifp = netdev_priv(ndev); | 449 | struct brcmf_if *ifp = netdev_priv(ndev); |
450 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 450 | struct brcmf_cfg80211_vif *vif = ifp->vif; |
451 | s32 infra = 0; | 451 | s32 infra = 0; |
452 | s32 ap = 0; | 452 | s32 ap = 0; |
453 | s32 err = 0; | 453 | s32 err = 0; |
@@ -461,15 +461,15 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
461 | type); | 461 | type); |
462 | return -EOPNOTSUPP; | 462 | return -EOPNOTSUPP; |
463 | case NL80211_IFTYPE_ADHOC: | 463 | case NL80211_IFTYPE_ADHOC: |
464 | cfg->conf->mode = WL_MODE_IBSS; | 464 | vif->mode = WL_MODE_IBSS; |
465 | infra = 0; | 465 | infra = 0; |
466 | break; | 466 | break; |
467 | case NL80211_IFTYPE_STATION: | 467 | case NL80211_IFTYPE_STATION: |
468 | cfg->conf->mode = WL_MODE_BSS; | 468 | vif->mode = WL_MODE_BSS; |
469 | infra = 1; | 469 | infra = 1; |
470 | break; | 470 | break; |
471 | case NL80211_IFTYPE_AP: | 471 | case NL80211_IFTYPE_AP: |
472 | cfg->conf->mode = WL_MODE_AP; | 472 | vif->mode = WL_MODE_AP; |
473 | ap = 1; | 473 | ap = 1; |
474 | break; | 474 | break; |
475 | default: | 475 | default: |
@@ -478,18 +478,16 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
478 | } | 478 | } |
479 | 479 | ||
480 | if (ap) { | 480 | if (ap) { |
481 | set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); | 481 | set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state); |
482 | WL_INFO("IF Type = AP\n"); | 482 | WL_INFO("IF Type = AP\n"); |
483 | } else { | 483 | } else { |
484 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), | 484 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra); |
485 | BRCMF_C_SET_INFRA, infra); | ||
486 | if (err) { | 485 | if (err) { |
487 | WL_ERR("WLC_SET_INFRA error (%d)\n", err); | 486 | WL_ERR("WLC_SET_INFRA error (%d)\n", err); |
488 | err = -EAGAIN; | 487 | err = -EAGAIN; |
489 | goto done; | 488 | goto done; |
490 | } | 489 | } |
491 | WL_INFO("IF Type = %s\n", | 490 | WL_INFO("IF Type = %s\n", (vif->mode == WL_MODE_IBSS) ? |
492 | (cfg->conf->mode == WL_MODE_IBSS) ? | ||
493 | "Adhoc" : "Infra"); | 491 | "Adhoc" : "Infra"); |
494 | } | 492 | } |
495 | ndev->ieee80211_ptr->iftype = type; | 493 | ndev->ieee80211_ptr->iftype = type; |
@@ -963,22 +961,21 @@ static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, | |||
963 | } | 961 | } |
964 | } | 962 | } |
965 | 963 | ||
966 | static void brcmf_link_down(struct brcmf_cfg80211_info *cfg) | 964 | static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) |
967 | { | 965 | { |
968 | struct net_device *ndev = NULL; | ||
969 | s32 err = 0; | 966 | s32 err = 0; |
970 | 967 | ||
971 | WL_TRACE("Enter\n"); | 968 | WL_TRACE("Enter\n"); |
972 | 969 | ||
973 | if (cfg->link_up) { | 970 | if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) { |
974 | ndev = cfg_to_ndev(cfg); | ||
975 | WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); | 971 | WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); |
976 | err = brcmf_fil_cmd_data_set(netdev_priv(ndev), | 972 | err = brcmf_fil_cmd_data_set(vif->ifp, |
977 | BRCMF_C_DISASSOC, NULL, 0); | 973 | BRCMF_C_DISASSOC, NULL, 0); |
978 | if (err) | 974 | if (err) |
979 | WL_ERR("WLC_DISASSOC failed (%d)\n", err); | 975 | WL_ERR("WLC_DISASSOC failed (%d)\n", err); |
980 | cfg->link_up = false; | 976 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state); |
981 | } | 977 | } |
978 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); | ||
982 | WL_TRACE("Exit\n"); | 979 | WL_TRACE("Exit\n"); |
983 | } | 980 | } |
984 | 981 | ||
@@ -1130,7 +1127,6 @@ done: | |||
1130 | static s32 | 1127 | static s32 |
1131 | brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) | 1128 | brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) |
1132 | { | 1129 | { |
1133 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
1134 | struct brcmf_if *ifp = netdev_priv(ndev); | 1130 | struct brcmf_if *ifp = netdev_priv(ndev); |
1135 | s32 err = 0; | 1131 | s32 err = 0; |
1136 | 1132 | ||
@@ -1138,7 +1134,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) | |||
1138 | if (!check_vif_up(ifp->vif)) | 1134 | if (!check_vif_up(ifp->vif)) |
1139 | return -EIO; | 1135 | return -EIO; |
1140 | 1136 | ||
1141 | brcmf_link_down(cfg); | 1137 | brcmf_link_down(ifp->vif); |
1142 | 1138 | ||
1143 | WL_TRACE("Exit\n"); | 1139 | WL_TRACE("Exit\n"); |
1144 | 1140 | ||
@@ -1496,7 +1492,6 @@ static s32 | |||
1496 | brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, | 1492 | brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, |
1497 | u16 reason_code) | 1493 | u16 reason_code) |
1498 | { | 1494 | { |
1499 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
1500 | struct brcmf_if *ifp = netdev_priv(ndev); | 1495 | struct brcmf_if *ifp = netdev_priv(ndev); |
1501 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | 1496 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
1502 | struct brcmf_scb_val_le scbval; | 1497 | struct brcmf_scb_val_le scbval; |
@@ -1515,8 +1510,6 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, | |||
1515 | if (err) | 1510 | if (err) |
1516 | WL_ERR("error (%d)\n", err); | 1511 | WL_ERR("error (%d)\n", err); |
1517 | 1512 | ||
1518 | cfg->link_up = false; | ||
1519 | |||
1520 | WL_TRACE("Exit\n"); | 1513 | WL_TRACE("Exit\n"); |
1521 | return err; | 1514 | return err; |
1522 | } | 1515 | } |
@@ -1716,7 +1709,6 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1716 | u8 key_idx, bool pairwise, const u8 *mac_addr, | 1709 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
1717 | struct key_params *params) | 1710 | struct key_params *params) |
1718 | { | 1711 | { |
1719 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
1720 | struct brcmf_if *ifp = netdev_priv(ndev); | 1712 | struct brcmf_if *ifp = netdev_priv(ndev); |
1721 | struct brcmf_wsec_key key; | 1713 | struct brcmf_wsec_key key; |
1722 | s32 val; | 1714 | s32 val; |
@@ -1758,7 +1750,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1758 | WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); | 1750 | WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); |
1759 | break; | 1751 | break; |
1760 | case WLAN_CIPHER_SUITE_TKIP: | 1752 | case WLAN_CIPHER_SUITE_TKIP: |
1761 | if (cfg->conf->mode != WL_MODE_AP) { | 1753 | if (ifp->vif->mode != WL_MODE_AP) { |
1762 | WL_CONN("Swapping key\n"); | 1754 | WL_CONN("Swapping key\n"); |
1763 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 1755 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); |
1764 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); | 1756 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); |
@@ -1908,7 +1900,6 @@ static s32 | |||
1908 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | 1900 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, |
1909 | u8 *mac, struct station_info *sinfo) | 1901 | u8 *mac, struct station_info *sinfo) |
1910 | { | 1902 | { |
1911 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
1912 | struct brcmf_if *ifp = netdev_priv(ndev); | 1903 | struct brcmf_if *ifp = netdev_priv(ndev); |
1913 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | 1904 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
1914 | struct brcmf_scb_val_le scb_val; | 1905 | struct brcmf_scb_val_le scb_val; |
@@ -1922,7 +1913,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
1922 | if (!check_vif_up(ifp->vif)) | 1913 | if (!check_vif_up(ifp->vif)) |
1923 | return -EIO; | 1914 | return -EIO; |
1924 | 1915 | ||
1925 | if (cfg->conf->mode == WL_MODE_AP) { | 1916 | if (ifp->vif->mode == WL_MODE_AP) { |
1926 | memcpy(&sta_info_le, mac, ETH_ALEN); | 1917 | memcpy(&sta_info_le, mac, ETH_ALEN); |
1927 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", | 1918 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", |
1928 | &sta_info_le, | 1919 | &sta_info_le, |
@@ -1939,7 +1930,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
1939 | } | 1930 | } |
1940 | WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", | 1931 | WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", |
1941 | sinfo->inactive_time, sinfo->connected_time); | 1932 | sinfo->inactive_time, sinfo->connected_time); |
1942 | } else if (cfg->conf->mode == WL_MODE_BSS) { | 1933 | } else if (ifp->vif->mode == WL_MODE_BSS) { |
1943 | if (memcmp(mac, bssid, ETH_ALEN)) { | 1934 | if (memcmp(mac, bssid, ETH_ALEN)) { |
1944 | WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", | 1935 | WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", |
1945 | mac, bssid); | 1936 | mac, bssid); |
@@ -2249,9 +2240,9 @@ CleanUp: | |||
2249 | return err; | 2240 | return err; |
2250 | } | 2241 | } |
2251 | 2242 | ||
2252 | static bool brcmf_is_ibssmode(struct brcmf_cfg80211_info *cfg) | 2243 | static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif) |
2253 | { | 2244 | { |
2254 | return cfg->conf->mode == WL_MODE_IBSS; | 2245 | return vif->mode == WL_MODE_IBSS; |
2255 | } | 2246 | } |
2256 | 2247 | ||
2257 | /* | 2248 | /* |
@@ -2336,7 +2327,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) | |||
2336 | s32 err = 0; | 2327 | s32 err = 0; |
2337 | 2328 | ||
2338 | WL_TRACE("Enter\n"); | 2329 | WL_TRACE("Enter\n"); |
2339 | if (brcmf_is_ibssmode(cfg)) | 2330 | if (brcmf_is_ibssmode(ifp->vif)) |
2340 | return err; | 2331 | return err; |
2341 | 2332 | ||
2342 | ssid = &profile->ssid; | 2333 | ssid = &profile->ssid; |
@@ -2596,17 +2587,13 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, | |||
2596 | * While going to suspend if associated with AP disassociate | 2587 | * While going to suspend if associated with AP disassociate |
2597 | * from AP to save power while system is in suspended state | 2588 | * from AP to save power while system is in suspended state |
2598 | */ | 2589 | */ |
2599 | if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state) || | 2590 | brcmf_link_down(vif); |
2600 | test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) { | 2591 | |
2601 | WL_INFO("Disassociating from AP before suspend\n"); | 2592 | /* Make sure WPA_Supplicant receives all the event |
2602 | brcmf_link_down(cfg); | 2593 | * generated due to DISASSOC call to the fw to keep |
2603 | 2594 | * the state fw and WPA_Supplicant state consistent | |
2604 | /* Make sure WPA_Supplicant receives all the event | 2595 | */ |
2605 | * generated due to DISASSOC call to the fw to keep | 2596 | brcmf_delay(500); |
2606 | * the state fw and WPA_Supplicant state consistent | ||
2607 | */ | ||
2608 | brcmf_delay(500); | ||
2609 | } | ||
2610 | } | 2597 | } |
2611 | 2598 | ||
2612 | /* end any scanning */ | 2599 | /* end any scanning */ |
@@ -3306,11 +3293,12 @@ brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len, | |||
3306 | if (vndr_ies->count >= MAX_VNDR_IE_NUMBER) | 3293 | if (vndr_ies->count >= MAX_VNDR_IE_NUMBER) |
3307 | break; | 3294 | break; |
3308 | next: | 3295 | next: |
3309 | remaining_len -= ie->len; | 3296 | remaining_len -= (ie->len + TLV_HDR_LEN); |
3310 | if (remaining_len <= 2) | 3297 | if (remaining_len <= TLV_HDR_LEN) |
3311 | ie = NULL; | 3298 | ie = NULL; |
3312 | else | 3299 | else |
3313 | ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len); | 3300 | ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len + |
3301 | TLV_HDR_LEN); | ||
3314 | } | 3302 | } |
3315 | return err; | 3303 | return err; |
3316 | } | 3304 | } |
@@ -3409,11 +3397,11 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, | |||
3409 | } | 3397 | } |
3410 | } | 3398 | } |
3411 | 3399 | ||
3412 | if (mgmt_ie_buf != NULL) { | 3400 | if (mgmt_ie_buf && *mgmt_ie_len) { |
3413 | if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) && | 3401 | if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) && |
3414 | (memcmp(mgmt_ie_buf, curr_ie_buf, | 3402 | (memcmp(mgmt_ie_buf, curr_ie_buf, |
3415 | parsed_ie_buf_len) == 0)) { | 3403 | parsed_ie_buf_len) == 0)) { |
3416 | WL_TRACE("Previous mgmt IE is equals to current IE"); | 3404 | WL_TRACE("Previous mgmt IE equals to current IE\n"); |
3417 | goto exit; | 3405 | goto exit; |
3418 | } | 3406 | } |
3419 | 3407 | ||
@@ -3451,6 +3439,16 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, | |||
3451 | for (i = 0; i < new_vndr_ies.count; i++) { | 3439 | for (i = 0; i < new_vndr_ies.count; i++) { |
3452 | vndrie_info = &new_vndr_ies.ie_info[i]; | 3440 | vndrie_info = &new_vndr_ies.ie_info[i]; |
3453 | 3441 | ||
3442 | /* verify remained buf size before copy data */ | ||
3443 | if (remained_buf_len < (vndrie_info->vndrie.len + | ||
3444 | VNDR_IE_VSIE_OFFSET)) { | ||
3445 | WL_ERR("no space in mgmt_ie_buf: len left %d", | ||
3446 | remained_buf_len); | ||
3447 | break; | ||
3448 | } | ||
3449 | remained_buf_len -= (vndrie_info->ie_len + | ||
3450 | VNDR_IE_VSIE_OFFSET); | ||
3451 | |||
3454 | WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n", | 3452 | WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n", |
3455 | vndrie_info->vndrie.id, | 3453 | vndrie_info->vndrie.id, |
3456 | vndrie_info->vndrie.len, | 3454 | vndrie_info->vndrie.len, |
@@ -3462,13 +3460,6 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, | |||
3462 | vndrie_info->ie_ptr, | 3460 | vndrie_info->ie_ptr, |
3463 | vndrie_info->ie_len, | 3461 | vndrie_info->ie_len, |
3464 | "add"); | 3462 | "add"); |
3465 | /* verify remained buf size before copy data */ | ||
3466 | remained_buf_len -= vndrie_info->ie_len; | ||
3467 | if (remained_buf_len < 0) { | ||
3468 | WL_ERR("no space in mgmt_ie_buf: len left %d", | ||
3469 | remained_buf_len); | ||
3470 | break; | ||
3471 | } | ||
3472 | 3463 | ||
3473 | /* save the parsed IE in wl struct */ | 3464 | /* save the parsed IE in wl struct */ |
3474 | memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr, | 3465 | memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr, |
@@ -3643,22 +3634,20 @@ exit: | |||
3643 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | 3634 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) |
3644 | { | 3635 | { |
3645 | struct brcmf_if *ifp = netdev_priv(ndev); | 3636 | struct brcmf_if *ifp = netdev_priv(ndev); |
3646 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
3647 | s32 err = -EPERM; | 3637 | s32 err = -EPERM; |
3648 | 3638 | ||
3649 | WL_TRACE("Enter\n"); | 3639 | WL_TRACE("Enter\n"); |
3650 | 3640 | ||
3651 | if (cfg->conf->mode == WL_MODE_AP) { | 3641 | if (ifp->vif->mode == WL_MODE_AP) { |
3652 | /* Due to most likely deauths outstanding we sleep */ | 3642 | /* Due to most likely deauths outstanding we sleep */ |
3653 | /* first to make sure they get processed by fw. */ | 3643 | /* first to make sure they get processed by fw. */ |
3654 | msleep(400); | 3644 | msleep(400); |
3655 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), | 3645 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); |
3656 | BRCMF_C_SET_AP, 0); | ||
3657 | if (err < 0) { | 3646 | if (err < 0) { |
3658 | WL_ERR("setting AP mode failed %d\n", err); | 3647 | WL_ERR("setting AP mode failed %d\n", err); |
3659 | goto exit; | 3648 | goto exit; |
3660 | } | 3649 | } |
3661 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_UP, 0); | 3650 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); |
3662 | if (err < 0) { | 3651 | if (err < 0) { |
3663 | WL_ERR("BRCMF_C_UP error %d\n", err); | 3652 | WL_ERR("BRCMF_C_UP error %d\n", err); |
3664 | goto exit; | 3653 | goto exit; |
@@ -3849,23 +3838,20 @@ static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif) | |||
3849 | } | 3838 | } |
3850 | } | 3839 | } |
3851 | 3840 | ||
3852 | static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, | 3841 | static bool brcmf_is_linkup(const struct brcmf_event_msg *e) |
3853 | const struct brcmf_event_msg *e) | ||
3854 | { | 3842 | { |
3855 | u32 event = e->event_code; | 3843 | u32 event = e->event_code; |
3856 | u32 status = e->status; | 3844 | u32 status = e->status; |
3857 | 3845 | ||
3858 | if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { | 3846 | if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { |
3859 | WL_CONN("Processing set ssid\n"); | 3847 | WL_CONN("Processing set ssid\n"); |
3860 | cfg->link_up = true; | ||
3861 | return true; | 3848 | return true; |
3862 | } | 3849 | } |
3863 | 3850 | ||
3864 | return false; | 3851 | return false; |
3865 | } | 3852 | } |
3866 | 3853 | ||
3867 | static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg, | 3854 | static bool brcmf_is_linkdown(const struct brcmf_event_msg *e) |
3868 | const struct brcmf_event_msg *e) | ||
3869 | { | 3855 | { |
3870 | u32 event = e->event_code; | 3856 | u32 event = e->event_code; |
3871 | u16 flags = e->flags; | 3857 | u16 flags = e->flags; |
@@ -4115,11 +4101,11 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4115 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | 4101 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
4116 | s32 err = 0; | 4102 | s32 err = 0; |
4117 | 4103 | ||
4118 | if (cfg->conf->mode == WL_MODE_AP) { | 4104 | if (ifp->vif->mode == WL_MODE_AP) { |
4119 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); | 4105 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); |
4120 | } else if (brcmf_is_linkup(cfg, e)) { | 4106 | } else if (brcmf_is_linkup(e)) { |
4121 | WL_CONN("Linkup\n"); | 4107 | WL_CONN("Linkup\n"); |
4122 | if (brcmf_is_ibssmode(cfg)) { | 4108 | if (brcmf_is_ibssmode(ifp->vif)) { |
4123 | memcpy(profile->bssid, e->addr, ETH_ALEN); | 4109 | memcpy(profile->bssid, e->addr, ETH_ALEN); |
4124 | wl_inform_ibss(cfg, ndev, e->addr); | 4110 | wl_inform_ibss(cfg, ndev, e->addr); |
4125 | cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); | 4111 | cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); |
@@ -4129,26 +4115,19 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4129 | &ifp->vif->sme_state); | 4115 | &ifp->vif->sme_state); |
4130 | } else | 4116 | } else |
4131 | brcmf_bss_connect_done(cfg, ndev, e, true); | 4117 | brcmf_bss_connect_done(cfg, ndev, e, true); |
4132 | } else if (brcmf_is_linkdown(cfg, e)) { | 4118 | } else if (brcmf_is_linkdown(e)) { |
4133 | WL_CONN("Linkdown\n"); | 4119 | WL_CONN("Linkdown\n"); |
4134 | if (brcmf_is_ibssmode(cfg)) { | 4120 | if (!brcmf_is_ibssmode(ifp->vif)) { |
4135 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, | ||
4136 | &ifp->vif->sme_state); | ||
4137 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, | ||
4138 | &ifp->vif->sme_state)) | ||
4139 | brcmf_link_down(cfg); | ||
4140 | } else { | ||
4141 | brcmf_bss_connect_done(cfg, ndev, e, false); | 4121 | brcmf_bss_connect_done(cfg, ndev, e, false); |
4142 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, | 4122 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, |
4143 | &ifp->vif->sme_state)) { | 4123 | &ifp->vif->sme_state)) |
4144 | cfg80211_disconnected(ndev, 0, NULL, 0, | 4124 | cfg80211_disconnected(ndev, 0, NULL, 0, |
4145 | GFP_KERNEL); | 4125 | GFP_KERNEL); |
4146 | brcmf_link_down(cfg); | ||
4147 | } | ||
4148 | } | 4126 | } |
4127 | brcmf_link_down(ifp->vif); | ||
4149 | brcmf_init_prof(ndev_to_prof(ndev)); | 4128 | brcmf_init_prof(ndev_to_prof(ndev)); |
4150 | } else if (brcmf_is_nonetwork(cfg, e)) { | 4129 | } else if (brcmf_is_nonetwork(cfg, e)) { |
4151 | if (brcmf_is_ibssmode(cfg)) | 4130 | if (brcmf_is_ibssmode(ifp->vif)) |
4152 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, | 4131 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, |
4153 | &ifp->vif->sme_state); | 4132 | &ifp->vif->sme_state); |
4154 | else | 4133 | else |
@@ -4197,7 +4176,6 @@ brcmf_notify_mic_status(struct brcmf_if *ifp, | |||
4197 | 4176 | ||
4198 | static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) | 4177 | static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) |
4199 | { | 4178 | { |
4200 | conf->mode = (u32)-1; | ||
4201 | conf->frag_threshold = (u32)-1; | 4179 | conf->frag_threshold = (u32)-1; |
4202 | conf->rts_threshold = (u32)-1; | 4180 | conf->rts_threshold = (u32)-1; |
4203 | conf->retry_short = (u32)-1; | 4181 | conf->retry_short = (u32)-1; |
@@ -4282,7 +4260,6 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) | |||
4282 | mutex_init(&cfg->usr_sync); | 4260 | mutex_init(&cfg->usr_sync); |
4283 | brcmf_init_escan(cfg); | 4261 | brcmf_init_escan(cfg); |
4284 | brcmf_init_conf(cfg->conf); | 4262 | brcmf_init_conf(cfg->conf); |
4285 | brcmf_link_down(cfg); | ||
4286 | 4263 | ||
4287 | return err; | 4264 | return err; |
4288 | } | 4265 | } |
@@ -4290,7 +4267,6 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) | |||
4290 | static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) | 4267 | static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) |
4291 | { | 4268 | { |
4292 | cfg->dongle_up = false; /* dongle down */ | 4269 | cfg->dongle_up = false; /* dongle down */ |
4293 | brcmf_link_down(cfg); | ||
4294 | brcmf_abort_scanning(cfg); | 4270 | brcmf_abort_scanning(cfg); |
4295 | brcmf_deinit_priv_mem(cfg); | 4271 | brcmf_deinit_priv_mem(cfg); |
4296 | } | 4272 | } |
@@ -4537,11 +4513,8 @@ static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp) | |||
4537 | * While going down, if associated with AP disassociate | 4513 | * While going down, if associated with AP disassociate |
4538 | * from AP to save power | 4514 | * from AP to save power |
4539 | */ | 4515 | */ |
4540 | if ((test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state) || | 4516 | if (check_vif_up(ifp->vif)) { |
4541 | test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) && | 4517 | brcmf_link_down(ifp->vif); |
4542 | check_vif_up(ifp->vif)) { | ||
4543 | WL_INFO("Disassociating from AP"); | ||
4544 | brcmf_link_down(cfg); | ||
4545 | 4518 | ||
4546 | /* Make sure WPA_Supplicant receives all the event | 4519 | /* Make sure WPA_Supplicant receives all the event |
4547 | generated due to DISASSOC call to the fw to keep | 4520 | generated due to DISASSOC call to the fw to keep |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index e2ef8519ea84..d60de187e7d9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
@@ -128,7 +128,6 @@ enum wl_mode { | |||
128 | 128 | ||
129 | /* dongle configuration */ | 129 | /* dongle configuration */ |
130 | struct brcmf_cfg80211_conf { | 130 | struct brcmf_cfg80211_conf { |
131 | u32 mode; /* adhoc , infrastructure or ap */ | ||
132 | u32 frag_threshold; | 131 | u32 frag_threshold; |
133 | u32 rts_threshold; | 132 | u32 rts_threshold; |
134 | u32 retry_short; | 133 | u32 retry_short; |
@@ -359,7 +358,6 @@ struct brcmf_pno_scanresults_le { | |||
359 | * @active_scan: current scan mode. | 358 | * @active_scan: current scan mode. |
360 | * @sched_escan: e-scan for scheduled scan support running. | 359 | * @sched_escan: e-scan for scheduled scan support running. |
361 | * @ibss_starter: indicates this sta is ibss starter. | 360 | * @ibss_starter: indicates this sta is ibss starter. |
362 | * @link_up: link/connection up flag. | ||
363 | * @pwr_save: indicate whether dongle to support power save mode. | 361 | * @pwr_save: indicate whether dongle to support power save mode. |
364 | * @dongle_up: indicate whether dongle up or not. | 362 | * @dongle_up: indicate whether dongle up or not. |
365 | * @roam_on: on/off switch for dongle self-roaming. | 363 | * @roam_on: on/off switch for dongle self-roaming. |
@@ -391,7 +389,6 @@ struct brcmf_cfg80211_info { | |||
391 | bool active_scan; | 389 | bool active_scan; |
392 | bool sched_escan; | 390 | bool sched_escan; |
393 | bool ibss_starter; | 391 | bool ibss_starter; |
394 | bool link_up; | ||
395 | bool pwr_save; | 392 | bool pwr_save; |
396 | bool dongle_up; | 393 | bool dongle_up; |
397 | bool roam_on; | 394 | bool roam_on; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c index 6ba4136c7cf6..9761deb46204 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c | |||
@@ -1,8 +1,120 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * Copyright (c) 2012 Canonical Ltd. | ||
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 ANY | ||
12 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
14 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
15 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | #include <linux/debugfs.h> | ||
18 | #include <linux/if_ether.h> | ||
19 | #include <linux/if.h> | ||
1 | #include <linux/net.h> | 20 | #include <linux/net.h> |
21 | #include <linux/netdevice.h> | ||
22 | #include <linux/ieee80211.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <net/mac80211.h> | ||
25 | |||
26 | #include <defs.h> | ||
27 | #include <brcmu_wifi.h> | ||
28 | #include <brcmu_utils.h> | ||
2 | #include "types.h" | 29 | #include "types.h" |
30 | #include "main.h" | ||
3 | #include "debug.h" | 31 | #include "debug.h" |
4 | #include "brcms_trace_events.h" | 32 | #include "brcms_trace_events.h" |
5 | 33 | ||
34 | static struct dentry *root_folder; | ||
35 | |||
36 | void brcms_debugfs_init(void) | ||
37 | { | ||
38 | root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
39 | if (IS_ERR(root_folder)) | ||
40 | root_folder = NULL; | ||
41 | } | ||
42 | |||
43 | void brcms_debugfs_exit(void) | ||
44 | { | ||
45 | if (!root_folder) | ||
46 | return; | ||
47 | |||
48 | debugfs_remove_recursive(root_folder); | ||
49 | root_folder = NULL; | ||
50 | } | ||
51 | |||
52 | int brcms_debugfs_attach(struct brcms_pub *drvr) | ||
53 | { | ||
54 | if (!root_folder) | ||
55 | return -ENODEV; | ||
56 | |||
57 | drvr->dbgfs_dir = debugfs_create_dir( | ||
58 | dev_name(&drvr->wlc->hw->d11core->dev), root_folder); | ||
59 | return PTR_RET(drvr->dbgfs_dir); | ||
60 | } | ||
61 | |||
62 | void brcms_debugfs_detach(struct brcms_pub *drvr) | ||
63 | { | ||
64 | if (!IS_ERR_OR_NULL(drvr->dbgfs_dir)) | ||
65 | debugfs_remove_recursive(drvr->dbgfs_dir); | ||
66 | } | ||
67 | |||
68 | struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr) | ||
69 | { | ||
70 | return drvr->dbgfs_dir; | ||
71 | } | ||
72 | |||
73 | static | ||
74 | ssize_t brcms_debugfs_hardware_read(struct file *f, char __user *data, | ||
75 | size_t count, loff_t *ppos) | ||
76 | { | ||
77 | char buf[128]; | ||
78 | int res; | ||
79 | struct brcms_pub *drvr = f->private_data; | ||
80 | |||
81 | /* only allow read from start */ | ||
82 | if (*ppos > 0) | ||
83 | return 0; | ||
84 | |||
85 | res = scnprintf(buf, sizeof(buf), | ||
86 | "board vendor: %x\n" | ||
87 | "board type: %x\n" | ||
88 | "board revision: %x\n" | ||
89 | "board flags: %x\n" | ||
90 | "board flags2: %x\n" | ||
91 | "firmware revision: %x\n", | ||
92 | drvr->wlc->hw->d11core->bus->boardinfo.vendor, | ||
93 | drvr->wlc->hw->d11core->bus->boardinfo.type, | ||
94 | drvr->wlc->hw->boardrev, | ||
95 | drvr->wlc->hw->boardflags, | ||
96 | drvr->wlc->hw->boardflags2, | ||
97 | drvr->wlc->ucode_rev | ||
98 | ); | ||
99 | |||
100 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
101 | } | ||
102 | |||
103 | static const struct file_operations brcms_debugfs_hardware_ops = { | ||
104 | .owner = THIS_MODULE, | ||
105 | .open = simple_open, | ||
106 | .read = brcms_debugfs_hardware_read | ||
107 | }; | ||
108 | |||
109 | void brcms_debugfs_create_files(struct brcms_pub *drvr) | ||
110 | { | ||
111 | struct dentry *dentry = drvr->dbgfs_dir; | ||
112 | |||
113 | if (!IS_ERR_OR_NULL(dentry)) | ||
114 | debugfs_create_file("hardware", S_IRUGO, dentry, | ||
115 | drvr, &brcms_debugfs_hardware_ops); | ||
116 | } | ||
117 | |||
6 | #define __brcms_fn(fn) \ | 118 | #define __brcms_fn(fn) \ |
7 | void __brcms_ ##fn(struct device *dev, const char *fmt, ...) \ | 119 | void __brcms_ ##fn(struct device *dev, const char *fmt, ...) \ |
8 | { \ | 120 | { \ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/brcm80211/brcmsmac/debug.h index f77066bda9d2..796836b0f469 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/debug.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.h | |||
@@ -1,3 +1,18 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
1 | #ifndef _BRCMS_DEBUG_H_ | 16 | #ifndef _BRCMS_DEBUG_H_ |
2 | #define _BRCMS_DEBUG_H_ | 17 | #define _BRCMS_DEBUG_H_ |
3 | 18 | ||
@@ -49,4 +64,12 @@ void __brcms_dbg(struct device *dev, u32 level, const char *func, | |||
49 | #define brcms_dbg_dma(core, f, a...) brcms_dbg(core, BRCM_DL_DMA, f, ##a) | 64 | #define brcms_dbg_dma(core, f, a...) brcms_dbg(core, BRCM_DL_DMA, f, ##a) |
50 | #define brcms_dbg_ht(core, f, a...) brcms_dbg(core, BRCM_DL_HT, f, ##a) | 65 | #define brcms_dbg_ht(core, f, a...) brcms_dbg(core, BRCM_DL_HT, f, ##a) |
51 | 66 | ||
67 | struct brcms_pub; | ||
68 | void brcms_debugfs_init(void); | ||
69 | void brcms_debugfs_exit(void); | ||
70 | int brcms_debugfs_attach(struct brcms_pub *drvr); | ||
71 | void brcms_debugfs_detach(struct brcms_pub *drvr); | ||
72 | struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr); | ||
73 | void brcms_debugfs_create_files(struct brcms_pub *drvr); | ||
74 | |||
52 | #endif /* _BRCMS_DEBUG_H_ */ | 75 | #endif /* _BRCMS_DEBUG_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index 511e45775c33..1860c572b3c4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c | |||
@@ -349,10 +349,8 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) | |||
349 | { | 349 | { |
350 | uint dmactrlflags; | 350 | uint dmactrlflags; |
351 | 351 | ||
352 | if (di == NULL) { | 352 | if (di == NULL) |
353 | brcms_dbg_dma(di->core, "NULL dma handle\n"); | ||
354 | return 0; | 353 | return 0; |
355 | } | ||
356 | 354 | ||
357 | dmactrlflags = di->dma.dmactrlflags; | 355 | dmactrlflags = di->dma.dmactrlflags; |
358 | dmactrlflags &= ~mask; | 356 | dmactrlflags &= ~mask; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 1710ccba8bac..02d27eacc0e2 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -285,8 +285,8 @@ static void brcms_ops_tx(struct ieee80211_hw *hw, | |||
285 | kfree_skb(skb); | 285 | kfree_skb(skb); |
286 | goto done; | 286 | goto done; |
287 | } | 287 | } |
288 | brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); | 288 | if (brcms_c_sendpkt_mac80211(wl->wlc, skb, hw)) |
289 | tx_info->rate_driver_data[0] = control->sta; | 289 | tx_info->rate_driver_data[0] = control->sta; |
290 | done: | 290 | done: |
291 | spin_unlock_bh(&wl->lock); | 291 | spin_unlock_bh(&wl->lock); |
292 | } | 292 | } |
@@ -846,8 +846,10 @@ static void brcms_free(struct brcms_info *wl) | |||
846 | /* kill dpc */ | 846 | /* kill dpc */ |
847 | tasklet_kill(&wl->tasklet); | 847 | tasklet_kill(&wl->tasklet); |
848 | 848 | ||
849 | if (wl->pub) | 849 | if (wl->pub) { |
850 | brcms_debugfs_detach(wl->pub); | ||
850 | brcms_c_module_unregister(wl->pub, "linux", wl); | 851 | brcms_c_module_unregister(wl->pub, "linux", wl); |
852 | } | ||
851 | 853 | ||
852 | /* free common resources */ | 854 | /* free common resources */ |
853 | if (wl->wlc) { | 855 | if (wl->wlc) { |
@@ -896,27 +898,22 @@ static void brcms_remove(struct bcma_device *pdev) | |||
896 | static irqreturn_t brcms_isr(int irq, void *dev_id) | 898 | static irqreturn_t brcms_isr(int irq, void *dev_id) |
897 | { | 899 | { |
898 | struct brcms_info *wl; | 900 | struct brcms_info *wl; |
899 | bool ours, wantdpc; | 901 | irqreturn_t ret = IRQ_NONE; |
900 | 902 | ||
901 | wl = (struct brcms_info *) dev_id; | 903 | wl = (struct brcms_info *) dev_id; |
902 | 904 | ||
903 | spin_lock(&wl->isr_lock); | 905 | spin_lock(&wl->isr_lock); |
904 | 906 | ||
905 | /* call common first level interrupt handler */ | 907 | /* call common first level interrupt handler */ |
906 | ours = brcms_c_isr(wl->wlc, &wantdpc); | 908 | if (brcms_c_isr(wl->wlc)) { |
907 | if (ours) { | 909 | /* schedule second level handler */ |
908 | /* if more to do... */ | 910 | tasklet_schedule(&wl->tasklet); |
909 | if (wantdpc) { | 911 | ret = IRQ_HANDLED; |
910 | |||
911 | /* ...and call the second level interrupt handler */ | ||
912 | /* schedule dpc */ | ||
913 | tasklet_schedule(&wl->tasklet); | ||
914 | } | ||
915 | } | 912 | } |
916 | 913 | ||
917 | spin_unlock(&wl->isr_lock); | 914 | spin_unlock(&wl->isr_lock); |
918 | 915 | ||
919 | return IRQ_RETVAL(ours); | 916 | return ret; |
920 | } | 917 | } |
921 | 918 | ||
922 | /* | 919 | /* |
@@ -1082,6 +1079,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1082 | regulatory_hint(wl->wiphy, wl->pub->srom_ccode)) | 1079 | regulatory_hint(wl->wiphy, wl->pub->srom_ccode)) |
1083 | wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__); | 1080 | wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__); |
1084 | 1081 | ||
1082 | brcms_debugfs_attach(wl->pub); | ||
1083 | brcms_debugfs_create_files(wl->pub); | ||
1085 | n_adapters_found++; | 1084 | n_adapters_found++; |
1086 | return wl; | 1085 | return wl; |
1087 | 1086 | ||
@@ -1100,7 +1099,7 @@ fail: | |||
1100 | * | 1099 | * |
1101 | * Perimeter lock is initialized in the course of this function. | 1100 | * Perimeter lock is initialized in the course of this function. |
1102 | */ | 1101 | */ |
1103 | static int __devinit brcms_bcma_probe(struct bcma_device *pdev) | 1102 | static int brcms_bcma_probe(struct bcma_device *pdev) |
1104 | { | 1103 | { |
1105 | struct brcms_info *wl; | 1104 | struct brcms_info *wl; |
1106 | struct ieee80211_hw *hw; | 1105 | struct ieee80211_hw *hw; |
@@ -1166,7 +1165,7 @@ static struct bcma_driver brcms_bcma_driver = { | |||
1166 | .probe = brcms_bcma_probe, | 1165 | .probe = brcms_bcma_probe, |
1167 | .suspend = brcms_suspend, | 1166 | .suspend = brcms_suspend, |
1168 | .resume = brcms_resume, | 1167 | .resume = brcms_resume, |
1169 | .remove = __devexit_p(brcms_remove), | 1168 | .remove = brcms_remove, |
1170 | .id_table = brcms_coreid_table, | 1169 | .id_table = brcms_coreid_table, |
1171 | }; | 1170 | }; |
1172 | 1171 | ||
@@ -1190,6 +1189,7 @@ static DECLARE_WORK(brcms_driver_work, brcms_driver_init); | |||
1190 | 1189 | ||
1191 | static int __init brcms_module_init(void) | 1190 | static int __init brcms_module_init(void) |
1192 | { | 1191 | { |
1192 | brcms_debugfs_init(); | ||
1193 | if (!schedule_work(&brcms_driver_work)) | 1193 | if (!schedule_work(&brcms_driver_work)) |
1194 | return -EBUSY; | 1194 | return -EBUSY; |
1195 | 1195 | ||
@@ -1207,6 +1207,7 @@ static void __exit brcms_module_exit(void) | |||
1207 | { | 1207 | { |
1208 | cancel_work_sync(&brcms_driver_work); | 1208 | cancel_work_sync(&brcms_driver_work); |
1209 | bcma_driver_unregister(&brcms_bcma_driver); | 1209 | bcma_driver_unregister(&brcms_bcma_driver); |
1210 | brcms_debugfs_exit(); | ||
1210 | } | 1211 | } |
1211 | 1212 | ||
1212 | module_init(brcms_module_init); | 1213 | module_init(brcms_module_init); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 2a44593f1e37..8fce68751e47 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -1044,11 +1044,17 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
1044 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); | 1044 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); |
1045 | while (!(*fatal) | 1045 | while (!(*fatal) |
1046 | && (s1 & TXS_V)) { | 1046 | && (s1 & TXS_V)) { |
1047 | /* !give others some time to run! */ | ||
1048 | if (n >= max_tx_num) { | ||
1049 | morepending = true; | ||
1050 | break; | ||
1051 | } | ||
1047 | 1052 | ||
1048 | if (s1 == 0xffffffff) { | 1053 | if (s1 == 0xffffffff) { |
1049 | brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, | 1054 | brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, |
1050 | __func__); | 1055 | __func__); |
1051 | return morepending; | 1056 | *fatal = true; |
1057 | return false; | ||
1052 | } | 1058 | } |
1053 | s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2)); | 1059 | s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2)); |
1054 | 1060 | ||
@@ -1060,17 +1066,12 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
1060 | 1066 | ||
1061 | *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); | 1067 | *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); |
1062 | 1068 | ||
1063 | /* !give others some time to run! */ | ||
1064 | if (++n >= max_tx_num) | ||
1065 | break; | ||
1066 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); | 1069 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); |
1070 | n++; | ||
1067 | } | 1071 | } |
1068 | 1072 | ||
1069 | if (*fatal) | 1073 | if (*fatal) |
1070 | return 0; | 1074 | return false; |
1071 | |||
1072 | if (n >= max_tx_num) | ||
1073 | morepending = true; | ||
1074 | 1075 | ||
1075 | return morepending; | 1076 | return morepending; |
1076 | } | 1077 | } |
@@ -2546,10 +2547,6 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr) | |||
2546 | if (macintstatus == 0) | 2547 | if (macintstatus == 0) |
2547 | return 0; | 2548 | return 0; |
2548 | 2549 | ||
2549 | /* interrupts are already turned off for CFE build | ||
2550 | * Caution: For CFE Turning off the interrupts again has some undesired | ||
2551 | * consequences | ||
2552 | */ | ||
2553 | /* turn off the interrupts */ | 2550 | /* turn off the interrupts */ |
2554 | bcma_write32(core, D11REGOFFS(macintmask), 0); | 2551 | bcma_write32(core, D11REGOFFS(macintmask), 0); |
2555 | (void)bcma_read32(core, D11REGOFFS(macintmask)); | 2552 | (void)bcma_read32(core, D11REGOFFS(macintmask)); |
@@ -2592,33 +2589,31 @@ bool brcms_c_intrsupd(struct brcms_c_info *wlc) | |||
2592 | 2589 | ||
2593 | /* | 2590 | /* |
2594 | * First-level interrupt processing. | 2591 | * First-level interrupt processing. |
2595 | * Return true if this was our interrupt, false otherwise. | 2592 | * Return true if this was our interrupt |
2596 | * *wantdpc will be set to true if further brcms_c_dpc() processing is required, | 2593 | * and if further brcms_c_dpc() processing is required, |
2597 | * false otherwise. | 2594 | * false otherwise. |
2598 | */ | 2595 | */ |
2599 | bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc) | 2596 | bool brcms_c_isr(struct brcms_c_info *wlc) |
2600 | { | 2597 | { |
2601 | struct brcms_hardware *wlc_hw = wlc->hw; | 2598 | struct brcms_hardware *wlc_hw = wlc->hw; |
2602 | u32 macintstatus; | 2599 | u32 macintstatus; |
2603 | 2600 | ||
2604 | *wantdpc = false; | ||
2605 | |||
2606 | if (!wlc_hw->up || !wlc->macintmask) | 2601 | if (!wlc_hw->up || !wlc->macintmask) |
2607 | return false; | 2602 | return false; |
2608 | 2603 | ||
2609 | /* read and clear macintstatus and intstatus registers */ | 2604 | /* read and clear macintstatus and intstatus registers */ |
2610 | macintstatus = wlc_intstatus(wlc, true); | 2605 | macintstatus = wlc_intstatus(wlc, true); |
2611 | 2606 | ||
2612 | if (macintstatus == 0xffffffff) | 2607 | if (macintstatus == 0xffffffff) { |
2613 | brcms_err(wlc_hw->d11core, | 2608 | brcms_err(wlc_hw->d11core, |
2614 | "DEVICEREMOVED detected in the ISR code path\n"); | 2609 | "DEVICEREMOVED detected in the ISR code path\n"); |
2610 | return false; | ||
2611 | } | ||
2615 | 2612 | ||
2616 | /* it is not for us */ | 2613 | /* it is not for us */ |
2617 | if (macintstatus == 0) | 2614 | if (macintstatus == 0) |
2618 | return false; | 2615 | return false; |
2619 | 2616 | ||
2620 | *wantdpc = true; | ||
2621 | |||
2622 | /* save interrupt status bits */ | 2617 | /* save interrupt status bits */ |
2623 | wlc->macintstatus = macintstatus; | 2618 | wlc->macintstatus = macintstatus; |
2624 | 2619 | ||
@@ -6928,17 +6923,20 @@ static int brcms_c_tx(struct brcms_c_info *wlc, struct sk_buff *skb) | |||
6928 | return ret; | 6923 | return ret; |
6929 | } | 6924 | } |
6930 | 6925 | ||
6931 | void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, | 6926 | bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, |
6932 | struct ieee80211_hw *hw) | 6927 | struct ieee80211_hw *hw) |
6933 | { | 6928 | { |
6934 | uint fifo; | 6929 | uint fifo; |
6935 | struct scb *scb = &wlc->pri_scb; | 6930 | struct scb *scb = &wlc->pri_scb; |
6936 | 6931 | ||
6937 | fifo = brcms_ac_to_fifo(skb_get_queue_mapping(sdu)); | 6932 | fifo = brcms_ac_to_fifo(skb_get_queue_mapping(sdu)); |
6938 | if (brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0)) | 6933 | brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0); |
6939 | return; | 6934 | if (!brcms_c_tx(wlc, sdu)) |
6940 | if (brcms_c_tx(wlc, sdu)) | 6935 | return true; |
6941 | dev_kfree_skb_any(sdu); | 6936 | |
6937 | /* packet discarded */ | ||
6938 | dev_kfree_skb_any(sdu); | ||
6939 | return false; | ||
6942 | } | 6940 | } |
6943 | 6941 | ||
6944 | int | 6942 | int |
@@ -7634,16 +7632,19 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) | |||
7634 | 7632 | ||
7635 | uint n = 0; | 7633 | uint n = 0; |
7636 | uint bound_limit = bound ? RXBND : -1; | 7634 | uint bound_limit = bound ? RXBND : -1; |
7635 | bool morepending; | ||
7637 | 7636 | ||
7638 | skb_queue_head_init(&recv_frames); | 7637 | skb_queue_head_init(&recv_frames); |
7639 | 7638 | ||
7640 | /* gather received frames */ | 7639 | /* gather received frames */ |
7641 | while (dma_rx(wlc_hw->di[fifo], &recv_frames)) { | 7640 | do { |
7642 | |||
7643 | /* !give others some time to run! */ | 7641 | /* !give others some time to run! */ |
7644 | if (++n >= bound_limit) | 7642 | if (n >= bound_limit) |
7645 | break; | 7643 | break; |
7646 | } | 7644 | |
7645 | morepending = dma_rx(wlc_hw->di[fifo], &recv_frames); | ||
7646 | n++; | ||
7647 | } while (morepending); | ||
7647 | 7648 | ||
7648 | /* post more rbufs */ | 7649 | /* post more rbufs */ |
7649 | dma_rxfill(wlc_hw->di[fifo]); | 7650 | dma_rxfill(wlc_hw->di[fifo]); |
@@ -7673,7 +7674,7 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) | |||
7673 | brcms_c_recv(wlc_hw->wlc, p); | 7674 | brcms_c_recv(wlc_hw->wlc, p); |
7674 | } | 7675 | } |
7675 | 7676 | ||
7676 | return n >= bound_limit; | 7677 | return morepending; |
7677 | } | 7678 | } |
7678 | 7679 | ||
7679 | /* second-level interrupt processing | 7680 | /* second-level interrupt processing |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index abfd78822fb8..606b534347bc 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | |||
@@ -1137,8 +1137,9 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, | |||
1137 | gain0_15 = ((biq1 & 0xf) << 12) | | 1137 | gain0_15 = ((biq1 & 0xf) << 12) | |
1138 | ((tia & 0xf) << 8) | | 1138 | ((tia & 0xf) << 8) | |
1139 | ((lna2 & 0x3) << 6) | | 1139 | ((lna2 & 0x3) << 6) | |
1140 | ((lna2 & | 1140 | ((lna2 & 0x3) << 4) | |
1141 | 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); | 1141 | ((lna1 & 0x3) << 2) | |
1142 | ((lna1 & 0x3) << 0); | ||
1142 | 1143 | ||
1143 | mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); | 1144 | mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); |
1144 | mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); | 1145 | mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); |
@@ -1156,6 +1157,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, | |||
1156 | } | 1157 | } |
1157 | 1158 | ||
1158 | mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); | 1159 | mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); |
1160 | mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); | ||
1161 | mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); | ||
1159 | 1162 | ||
1160 | } | 1163 | } |
1161 | 1164 | ||
@@ -1328,6 +1331,43 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) | |||
1328 | return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; | 1331 | return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; |
1329 | } | 1332 | } |
1330 | 1333 | ||
1334 | static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain, | ||
1335 | u16 tia_gain, u16 lna2_gain) | ||
1336 | { | ||
1337 | u32 i_thresh_l, q_thresh_l; | ||
1338 | u32 i_thresh_h, q_thresh_h; | ||
1339 | struct lcnphy_iq_est iq_est_h, iq_est_l; | ||
1340 | |||
1341 | wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain, | ||
1342 | lna2_gain, 0); | ||
1343 | |||
1344 | wlc_lcnphy_rx_gain_override_enable(pi, true); | ||
1345 | wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); | ||
1346 | usleep_range(500, 500); | ||
1347 | write_radio_reg(pi, RADIO_2064_REG112, 0); | ||
1348 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) | ||
1349 | return false; | ||
1350 | |||
1351 | wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); | ||
1352 | usleep_range(500, 500); | ||
1353 | write_radio_reg(pi, RADIO_2064_REG112, 0); | ||
1354 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) | ||
1355 | return false; | ||
1356 | |||
1357 | i_thresh_l = (iq_est_l.i_pwr << 1); | ||
1358 | i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr; | ||
1359 | |||
1360 | q_thresh_l = (iq_est_l.q_pwr << 1); | ||
1361 | q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr; | ||
1362 | if ((iq_est_h.i_pwr > i_thresh_l) && | ||
1363 | (iq_est_h.i_pwr < i_thresh_h) && | ||
1364 | (iq_est_h.q_pwr > q_thresh_l) && | ||
1365 | (iq_est_h.q_pwr < q_thresh_h)) | ||
1366 | return true; | ||
1367 | |||
1368 | return false; | ||
1369 | } | ||
1370 | |||
1331 | static bool | 1371 | static bool |
1332 | wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | 1372 | wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, |
1333 | const struct lcnphy_rx_iqcomp *iqcomp, | 1373 | const struct lcnphy_rx_iqcomp *iqcomp, |
@@ -1342,8 +1382,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | |||
1342 | RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, | 1382 | RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, |
1343 | rfoverride3_old, rfoverride3val_old, rfoverride4_old, | 1383 | rfoverride3_old, rfoverride3val_old, rfoverride4_old, |
1344 | rfoverride4val_old, afectrlovr_old, afectrlovrval_old; | 1384 | rfoverride4val_old, afectrlovr_old, afectrlovrval_old; |
1345 | int tia_gain; | 1385 | int tia_gain, lna2_gain, biq1_gain; |
1346 | u32 received_power, rx_pwr_threshold; | 1386 | bool set_gain; |
1347 | u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; | 1387 | u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; |
1348 | u16 values_to_save[11]; | 1388 | u16 values_to_save[11]; |
1349 | s16 *ptr; | 1389 | s16 *ptr; |
@@ -1368,126 +1408,134 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | |||
1368 | goto cal_done; | 1408 | goto cal_done; |
1369 | } | 1409 | } |
1370 | 1410 | ||
1371 | if (module == 1) { | 1411 | WARN_ON(module != 1); |
1412 | tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); | ||
1413 | wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); | ||
1372 | 1414 | ||
1373 | tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); | 1415 | for (i = 0; i < 11; i++) |
1374 | wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); | 1416 | values_to_save[i] = |
1417 | read_radio_reg(pi, rxiq_cal_rf_reg[i]); | ||
1418 | Core1TxControl_old = read_phy_reg(pi, 0x631); | ||
1419 | |||
1420 | or_phy_reg(pi, 0x631, 0x0015); | ||
1421 | |||
1422 | RFOverride0_old = read_phy_reg(pi, 0x44c); | ||
1423 | RFOverrideVal0_old = read_phy_reg(pi, 0x44d); | ||
1424 | rfoverride2_old = read_phy_reg(pi, 0x4b0); | ||
1425 | rfoverride2val_old = read_phy_reg(pi, 0x4b1); | ||
1426 | rfoverride3_old = read_phy_reg(pi, 0x4f9); | ||
1427 | rfoverride3val_old = read_phy_reg(pi, 0x4fa); | ||
1428 | rfoverride4_old = read_phy_reg(pi, 0x938); | ||
1429 | rfoverride4val_old = read_phy_reg(pi, 0x939); | ||
1430 | afectrlovr_old = read_phy_reg(pi, 0x43b); | ||
1431 | afectrlovrval_old = read_phy_reg(pi, 0x43c); | ||
1432 | old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | ||
1433 | old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); | ||
1375 | 1434 | ||
1376 | for (i = 0; i < 11; i++) | 1435 | tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); |
1377 | values_to_save[i] = | 1436 | if (tx_gain_override_old) { |
1378 | read_radio_reg(pi, rxiq_cal_rf_reg[i]); | 1437 | wlc_lcnphy_get_tx_gain(pi, &old_gains); |
1379 | Core1TxControl_old = read_phy_reg(pi, 0x631); | 1438 | tx_gain_index_old = pi_lcn->lcnphy_current_index; |
1380 | 1439 | } | |
1381 | or_phy_reg(pi, 0x631, 0x0015); | ||
1382 | |||
1383 | RFOverride0_old = read_phy_reg(pi, 0x44c); | ||
1384 | RFOverrideVal0_old = read_phy_reg(pi, 0x44d); | ||
1385 | rfoverride2_old = read_phy_reg(pi, 0x4b0); | ||
1386 | rfoverride2val_old = read_phy_reg(pi, 0x4b1); | ||
1387 | rfoverride3_old = read_phy_reg(pi, 0x4f9); | ||
1388 | rfoverride3val_old = read_phy_reg(pi, 0x4fa); | ||
1389 | rfoverride4_old = read_phy_reg(pi, 0x938); | ||
1390 | rfoverride4val_old = read_phy_reg(pi, 0x939); | ||
1391 | afectrlovr_old = read_phy_reg(pi, 0x43b); | ||
1392 | afectrlovrval_old = read_phy_reg(pi, 0x43c); | ||
1393 | old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | ||
1394 | old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); | ||
1395 | |||
1396 | tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); | ||
1397 | if (tx_gain_override_old) { | ||
1398 | wlc_lcnphy_get_tx_gain(pi, &old_gains); | ||
1399 | tx_gain_index_old = pi_lcn->lcnphy_current_index; | ||
1400 | } | ||
1401 | 1440 | ||
1402 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); | 1441 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); |
1403 | 1442 | ||
1404 | mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); | 1443 | mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); |
1405 | mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); | 1444 | mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); |
1406 | 1445 | ||
1407 | mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); | 1446 | mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); |
1408 | mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); | 1447 | mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); |
1409 | 1448 | ||
1410 | write_radio_reg(pi, RADIO_2064_REG116, 0x06); | 1449 | write_radio_reg(pi, RADIO_2064_REG116, 0x06); |
1411 | write_radio_reg(pi, RADIO_2064_REG12C, 0x07); | 1450 | write_radio_reg(pi, RADIO_2064_REG12C, 0x07); |
1412 | write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); | 1451 | write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); |
1413 | write_radio_reg(pi, RADIO_2064_REG098, 0x03); | 1452 | write_radio_reg(pi, RADIO_2064_REG098, 0x03); |
1414 | write_radio_reg(pi, RADIO_2064_REG00B, 0x7); | 1453 | write_radio_reg(pi, RADIO_2064_REG00B, 0x7); |
1415 | mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); | 1454 | mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); |
1416 | write_radio_reg(pi, RADIO_2064_REG01D, 0x01); | 1455 | write_radio_reg(pi, RADIO_2064_REG01D, 0x01); |
1417 | write_radio_reg(pi, RADIO_2064_REG114, 0x01); | 1456 | write_radio_reg(pi, RADIO_2064_REG114, 0x01); |
1418 | write_radio_reg(pi, RADIO_2064_REG02E, 0x10); | 1457 | write_radio_reg(pi, RADIO_2064_REG02E, 0x10); |
1419 | write_radio_reg(pi, RADIO_2064_REG12A, 0x08); | 1458 | write_radio_reg(pi, RADIO_2064_REG12A, 0x08); |
1420 | 1459 | ||
1421 | mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); | 1460 | mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); |
1422 | mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); | 1461 | mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); |
1423 | mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); | 1462 | mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); |
1424 | mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); | 1463 | mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); |
1425 | mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); | 1464 | mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); |
1426 | mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); | 1465 | mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); |
1427 | mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); | 1466 | mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); |
1428 | mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); | 1467 | mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); |
1429 | mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); | 1468 | mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); |
1430 | mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); | 1469 | mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); |
1431 | |||
1432 | mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); | ||
1433 | mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); | ||
1434 | |||
1435 | wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0); | ||
1436 | write_phy_reg(pi, 0x6da, 0xffff); | ||
1437 | or_phy_reg(pi, 0x6db, 0x3); | ||
1438 | wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); | ||
1439 | wlc_lcnphy_rx_gain_override_enable(pi, true); | ||
1440 | |||
1441 | tia_gain = 8; | ||
1442 | rx_pwr_threshold = 950; | ||
1443 | while (tia_gain > 0) { | ||
1444 | tia_gain -= 1; | ||
1445 | wlc_lcnphy_set_rx_gain_by_distribution(pi, | ||
1446 | 0, 0, 2, 2, | ||
1447 | (u16) | ||
1448 | tia_gain, 1, 0); | ||
1449 | udelay(500); | ||
1450 | 1470 | ||
1451 | received_power = | 1471 | mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); |
1452 | wlc_lcnphy_measure_digital_power(pi, 2000); | 1472 | mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); |
1453 | if (received_power < rx_pwr_threshold) | 1473 | |
1454 | break; | 1474 | write_phy_reg(pi, 0x6da, 0xffff); |
1475 | or_phy_reg(pi, 0x6db, 0x3); | ||
1476 | |||
1477 | wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); | ||
1478 | set_gain = false; | ||
1479 | |||
1480 | lna2_gain = 3; | ||
1481 | while ((lna2_gain >= 0) && !set_gain) { | ||
1482 | tia_gain = 4; | ||
1483 | |||
1484 | while ((tia_gain >= 0) && !set_gain) { | ||
1485 | biq1_gain = 6; | ||
1486 | |||
1487 | while ((biq1_gain >= 0) && !set_gain) { | ||
1488 | set_gain = wlc_lcnphy_rx_iq_cal_gain(pi, | ||
1489 | (u16) | ||
1490 | biq1_gain, | ||
1491 | (u16) | ||
1492 | tia_gain, | ||
1493 | (u16) | ||
1494 | lna2_gain); | ||
1495 | biq1_gain -= 1; | ||
1496 | } | ||
1497 | tia_gain -= 1; | ||
1455 | } | 1498 | } |
1456 | result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff); | 1499 | lna2_gain -= 1; |
1500 | } | ||
1457 | 1501 | ||
1458 | wlc_lcnphy_stop_tx_tone(pi); | 1502 | if (set_gain) |
1503 | result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024); | ||
1504 | else | ||
1505 | result = false; | ||
1459 | 1506 | ||
1460 | write_phy_reg(pi, 0x631, Core1TxControl_old); | 1507 | wlc_lcnphy_stop_tx_tone(pi); |
1461 | 1508 | ||
1462 | write_phy_reg(pi, 0x44c, RFOverrideVal0_old); | 1509 | write_phy_reg(pi, 0x631, Core1TxControl_old); |
1463 | write_phy_reg(pi, 0x44d, RFOverrideVal0_old); | 1510 | |
1464 | write_phy_reg(pi, 0x4b0, rfoverride2_old); | 1511 | write_phy_reg(pi, 0x44c, RFOverrideVal0_old); |
1465 | write_phy_reg(pi, 0x4b1, rfoverride2val_old); | 1512 | write_phy_reg(pi, 0x44d, RFOverrideVal0_old); |
1466 | write_phy_reg(pi, 0x4f9, rfoverride3_old); | 1513 | write_phy_reg(pi, 0x4b0, rfoverride2_old); |
1467 | write_phy_reg(pi, 0x4fa, rfoverride3val_old); | 1514 | write_phy_reg(pi, 0x4b1, rfoverride2val_old); |
1468 | write_phy_reg(pi, 0x938, rfoverride4_old); | 1515 | write_phy_reg(pi, 0x4f9, rfoverride3_old); |
1469 | write_phy_reg(pi, 0x939, rfoverride4val_old); | 1516 | write_phy_reg(pi, 0x4fa, rfoverride3val_old); |
1470 | write_phy_reg(pi, 0x43b, afectrlovr_old); | 1517 | write_phy_reg(pi, 0x938, rfoverride4_old); |
1471 | write_phy_reg(pi, 0x43c, afectrlovrval_old); | 1518 | write_phy_reg(pi, 0x939, rfoverride4val_old); |
1472 | write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); | 1519 | write_phy_reg(pi, 0x43b, afectrlovr_old); |
1473 | write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); | 1520 | write_phy_reg(pi, 0x43c, afectrlovrval_old); |
1521 | write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); | ||
1522 | write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); | ||
1474 | 1523 | ||
1475 | wlc_lcnphy_clear_trsw_override(pi); | 1524 | wlc_lcnphy_clear_trsw_override(pi); |
1476 | 1525 | ||
1477 | mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); | 1526 | mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); |
1478 | 1527 | ||
1479 | for (i = 0; i < 11; i++) | 1528 | for (i = 0; i < 11; i++) |
1480 | write_radio_reg(pi, rxiq_cal_rf_reg[i], | 1529 | write_radio_reg(pi, rxiq_cal_rf_reg[i], |
1481 | values_to_save[i]); | 1530 | values_to_save[i]); |
1482 | 1531 | ||
1483 | if (tx_gain_override_old) | 1532 | if (tx_gain_override_old) |
1484 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); | 1533 | wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); |
1485 | else | 1534 | else |
1486 | wlc_lcnphy_disable_tx_gain_override(pi); | 1535 | wlc_lcnphy_disable_tx_gain_override(pi); |
1487 | 1536 | ||
1488 | wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); | 1537 | wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); |
1489 | wlc_lcnphy_rx_gain_override_enable(pi, false); | 1538 | wlc_lcnphy_rx_gain_override_enable(pi, false); |
1490 | } | ||
1491 | 1539 | ||
1492 | cal_done: | 1540 | cal_done: |
1493 | kfree(ptr); | 1541 | kfree(ptr); |
@@ -1781,6 +1829,17 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) | |||
1781 | write_radio_reg(pi, RADIO_2064_REG038, 3); | 1829 | write_radio_reg(pi, RADIO_2064_REG038, 3); |
1782 | write_radio_reg(pi, RADIO_2064_REG091, 7); | 1830 | write_radio_reg(pi, RADIO_2064_REG091, 7); |
1783 | } | 1831 | } |
1832 | |||
1833 | if (!(pi->sh->boardflags & BFL_FEM)) { | ||
1834 | u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc, | ||
1835 | 0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0}; | ||
1836 | |||
1837 | write_radio_reg(pi, RADIO_2064_REG02A, 0xf); | ||
1838 | write_radio_reg(pi, RADIO_2064_REG091, 0x3); | ||
1839 | write_radio_reg(pi, RADIO_2064_REG038, 0x3); | ||
1840 | |||
1841 | write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]); | ||
1842 | } | ||
1784 | } | 1843 | } |
1785 | 1844 | ||
1786 | static int | 1845 | static int |
@@ -1860,41 +1919,6 @@ wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) | |||
1860 | return (filt_index != -1) ? 0 : -1; | 1919 | return (filt_index != -1) ? 0 : -1; |
1861 | } | 1920 | } |
1862 | 1921 | ||
1863 | void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) | ||
1864 | { | ||
1865 | u8 channel = CHSPEC_CHANNEL(chanspec); | ||
1866 | |||
1867 | wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec); | ||
1868 | |||
1869 | wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); | ||
1870 | |||
1871 | or_phy_reg(pi, 0x44a, 0x44); | ||
1872 | write_phy_reg(pi, 0x44a, 0x80); | ||
1873 | |||
1874 | wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); | ||
1875 | udelay(1000); | ||
1876 | |||
1877 | wlc_lcnphy_toggle_afe_pwdn(pi); | ||
1878 | |||
1879 | write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); | ||
1880 | write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); | ||
1881 | |||
1882 | if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { | ||
1883 | mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); | ||
1884 | |||
1885 | wlc_lcnphy_load_tx_iir_filter(pi, false, 3); | ||
1886 | } else { | ||
1887 | mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); | ||
1888 | |||
1889 | wlc_lcnphy_load_tx_iir_filter(pi, false, 2); | ||
1890 | } | ||
1891 | |||
1892 | wlc_lcnphy_load_tx_iir_filter(pi, true, 0); | ||
1893 | |||
1894 | mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); | ||
1895 | |||
1896 | } | ||
1897 | |||
1898 | static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) | 1922 | static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) |
1899 | { | 1923 | { |
1900 | u16 pa_gain; | 1924 | u16 pa_gain; |
@@ -1936,6 +1960,21 @@ static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi, | |||
1936 | wlc_lcnphy_enable_tx_gain_override(pi); | 1960 | wlc_lcnphy_enable_tx_gain_override(pi); |
1937 | } | 1961 | } |
1938 | 1962 | ||
1963 | static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) | ||
1964 | { | ||
1965 | u16 m0m1; | ||
1966 | struct phytbl_info tab; | ||
1967 | |||
1968 | tab.tbl_ptr = &m0m1; | ||
1969 | tab.tbl_len = 1; | ||
1970 | tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; | ||
1971 | tab.tbl_offset = 87; | ||
1972 | tab.tbl_width = 16; | ||
1973 | wlc_lcnphy_read_table(pi, &tab); | ||
1974 | |||
1975 | return (u8) ((m0m1 & 0xff00) >> 8); | ||
1976 | } | ||
1977 | |||
1939 | static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0) | 1978 | static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0) |
1940 | { | 1979 | { |
1941 | u16 m0m1 = (u16) m0 << 8; | 1980 | u16 m0m1 = (u16) m0 << 8; |
@@ -1995,6 +2034,16 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) | |||
1995 | } else { | 2034 | } else { |
1996 | mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); | 2035 | mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); |
1997 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); | 2036 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); |
2037 | mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0); | ||
2038 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2); | ||
2039 | mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0); | ||
2040 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4); | ||
2041 | mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); | ||
2042 | mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77); | ||
2043 | mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1); | ||
2044 | mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7); | ||
2045 | mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1); | ||
2046 | mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4); | ||
1998 | } | 2047 | } |
1999 | } else { | 2048 | } else { |
2000 | mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); | 2049 | mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); |
@@ -2081,12 +2130,14 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) | |||
2081 | (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); | 2130 | (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); |
2082 | 2131 | ||
2083 | mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); | 2132 | mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); |
2133 | mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0)); | ||
2084 | } | 2134 | } |
2085 | 2135 | ||
2086 | static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | 2136 | static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) |
2087 | { | 2137 | { |
2088 | struct phytbl_info tab; | 2138 | struct phytbl_info tab; |
2089 | u32 rfseq, ind; | 2139 | u32 rfseq, ind; |
2140 | u8 tssi_sel; | ||
2090 | 2141 | ||
2091 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; | 2142 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; |
2092 | tab.tbl_width = 32; | 2143 | tab.tbl_width = 32; |
@@ -2108,7 +2159,13 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | |||
2108 | 2159 | ||
2109 | mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); | 2160 | mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); |
2110 | 2161 | ||
2111 | wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); | 2162 | if (pi->sh->boardflags & BFL_FEM) { |
2163 | tssi_sel = 0x1; | ||
2164 | wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); | ||
2165 | } else { | ||
2166 | tssi_sel = 0xe; | ||
2167 | wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA); | ||
2168 | } | ||
2112 | mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); | 2169 | mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); |
2113 | 2170 | ||
2114 | mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); | 2171 | mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); |
@@ -2144,9 +2201,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | |||
2144 | mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); | 2201 | mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); |
2145 | 2202 | ||
2146 | if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { | 2203 | if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { |
2147 | mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe); | 2204 | mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel); |
2148 | mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); | 2205 | mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); |
2149 | } else { | 2206 | } else { |
2207 | mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1); | ||
2150 | mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); | 2208 | mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); |
2151 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); | 2209 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); |
2152 | } | 2210 | } |
@@ -2193,6 +2251,10 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | |||
2193 | 2251 | ||
2194 | mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); | 2252 | mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); |
2195 | 2253 | ||
2254 | mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0); | ||
2255 | mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); | ||
2256 | mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); | ||
2257 | |||
2196 | wlc_lcnphy_pwrctrl_rssiparams(pi); | 2258 | wlc_lcnphy_pwrctrl_rssiparams(pi); |
2197 | } | 2259 | } |
2198 | 2260 | ||
@@ -2811,6 +2873,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | |||
2811 | read_radio_reg(pi, RADIO_2064_REG007) & 1; | 2873 | read_radio_reg(pi, RADIO_2064_REG007) & 1; |
2812 | u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; | 2874 | u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; |
2813 | u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; | 2875 | u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; |
2876 | u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi); | ||
2877 | |||
2814 | idleTssi = read_phy_reg(pi, 0x4ab); | 2878 | idleTssi = read_phy_reg(pi, 0x4ab); |
2815 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & | 2879 | suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & |
2816 | MCTL_EN_MAC)); | 2880 | MCTL_EN_MAC)); |
@@ -2828,6 +2892,12 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | |||
2828 | mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); | 2892 | mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); |
2829 | mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); | 2893 | mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); |
2830 | wlc_lcnphy_tssi_setup(pi); | 2894 | wlc_lcnphy_tssi_setup(pi); |
2895 | |||
2896 | mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0)); | ||
2897 | mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6)); | ||
2898 | |||
2899 | wlc_lcnphy_set_bbmult(pi, 0x0); | ||
2900 | |||
2831 | wlc_phy_do_dummy_tx(pi, true, OFF); | 2901 | wlc_phy_do_dummy_tx(pi, true, OFF); |
2832 | idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) | 2902 | idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) |
2833 | >> 0); | 2903 | >> 0); |
@@ -2849,6 +2919,7 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | |||
2849 | 2919 | ||
2850 | mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); | 2920 | mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); |
2851 | 2921 | ||
2922 | wlc_lcnphy_set_bbmult(pi, SAVE_bbmult); | ||
2852 | wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); | 2923 | wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); |
2853 | wlc_lcnphy_set_tx_gain(pi, &old_gains); | 2924 | wlc_lcnphy_set_tx_gain(pi, &old_gains); |
2854 | wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); | 2925 | wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); |
@@ -3062,6 +3133,11 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) | |||
3062 | wlc_lcnphy_write_table(pi, &tab); | 3133 | wlc_lcnphy_write_table(pi, &tab); |
3063 | tab.tbl_offset++; | 3134 | tab.tbl_offset++; |
3064 | } | 3135 | } |
3136 | mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0); | ||
3137 | mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0); | ||
3138 | mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8); | ||
3139 | mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4); | ||
3140 | mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2); | ||
3065 | 3141 | ||
3066 | mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); | 3142 | mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); |
3067 | 3143 | ||
@@ -3075,21 +3151,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) | |||
3075 | wlapi_enable_mac(pi->sh->physhim); | 3151 | wlapi_enable_mac(pi->sh->physhim); |
3076 | } | 3152 | } |
3077 | 3153 | ||
3078 | static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) | ||
3079 | { | ||
3080 | u16 m0m1; | ||
3081 | struct phytbl_info tab; | ||
3082 | |||
3083 | tab.tbl_ptr = &m0m1; | ||
3084 | tab.tbl_len = 1; | ||
3085 | tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; | ||
3086 | tab.tbl_offset = 87; | ||
3087 | tab.tbl_width = 16; | ||
3088 | wlc_lcnphy_read_table(pi, &tab); | ||
3089 | |||
3090 | return (u8) ((m0m1 & 0xff00) >> 8); | ||
3091 | } | ||
3092 | |||
3093 | static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain) | 3154 | static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain) |
3094 | { | 3155 | { |
3095 | mod_phy_reg(pi, 0x4fb, | 3156 | mod_phy_reg(pi, 0x4fb, |
@@ -3878,7 +3939,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) | |||
3878 | target_gains.pad_gain = 21; | 3939 | target_gains.pad_gain = 21; |
3879 | target_gains.dac_gain = 0; | 3940 | target_gains.dac_gain = 0; |
3880 | wlc_lcnphy_set_tx_gain(pi, &target_gains); | 3941 | wlc_lcnphy_set_tx_gain(pi, &target_gains); |
3881 | wlc_lcnphy_set_tx_pwr_by_index(pi, 16); | ||
3882 | 3942 | ||
3883 | if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { | 3943 | if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { |
3884 | 3944 | ||
@@ -3889,6 +3949,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) | |||
3889 | lcnphy_recal ? LCNPHY_CAL_RECAL : | 3949 | lcnphy_recal ? LCNPHY_CAL_RECAL : |
3890 | LCNPHY_CAL_FULL), false); | 3950 | LCNPHY_CAL_FULL), false); |
3891 | } else { | 3951 | } else { |
3952 | wlc_lcnphy_set_tx_pwr_by_index(pi, 16); | ||
3892 | wlc_lcnphy_tx_iqlo_soft_cal_full(pi); | 3953 | wlc_lcnphy_tx_iqlo_soft_cal_full(pi); |
3893 | } | 3954 | } |
3894 | 3955 | ||
@@ -4313,17 +4374,22 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, | |||
4313 | if (CHSPEC_IS5G(pi->radio_chanspec)) | 4374 | if (CHSPEC_IS5G(pi->radio_chanspec)) |
4314 | pa_gain = 0x70; | 4375 | pa_gain = 0x70; |
4315 | else | 4376 | else |
4316 | pa_gain = 0x70; | 4377 | pa_gain = 0x60; |
4317 | 4378 | ||
4318 | if (pi->sh->boardflags & BFL_FEM) | 4379 | if (pi->sh->boardflags & BFL_FEM) |
4319 | pa_gain = 0x10; | 4380 | pa_gain = 0x10; |
4381 | |||
4320 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; | 4382 | tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; |
4321 | tab.tbl_width = 32; | 4383 | tab.tbl_width = 32; |
4322 | tab.tbl_len = 1; | 4384 | tab.tbl_len = 1; |
4323 | tab.tbl_ptr = &val; | 4385 | tab.tbl_ptr = &val; |
4324 | 4386 | ||
4325 | for (j = 0; j < 128; j++) { | 4387 | for (j = 0; j < 128; j++) { |
4326 | gm_gain = gain_table[j].gm; | 4388 | if (pi->sh->boardflags & BFL_FEM) |
4389 | gm_gain = gain_table[j].gm; | ||
4390 | else | ||
4391 | gm_gain = 15; | ||
4392 | |||
4327 | val = (((u32) pa_gain << 24) | | 4393 | val = (((u32) pa_gain << 24) | |
4328 | (gain_table[j].pad << 16) | | 4394 | (gain_table[j].pad << 16) | |
4329 | (gain_table[j].pga << 8) | gm_gain); | 4395 | (gain_table[j].pga << 8) | gm_gain); |
@@ -4534,7 +4600,10 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) | |||
4534 | 4600 | ||
4535 | write_phy_reg(pi, 0x4ea, 0x4688); | 4601 | write_phy_reg(pi, 0x4ea, 0x4688); |
4536 | 4602 | ||
4537 | mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); | 4603 | if (pi->sh->boardflags & BFL_FEM) |
4604 | mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); | ||
4605 | else | ||
4606 | mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0); | ||
4538 | 4607 | ||
4539 | mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); | 4608 | mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); |
4540 | 4609 | ||
@@ -4545,6 +4614,13 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) | |||
4545 | wlc_lcnphy_rcal(pi); | 4614 | wlc_lcnphy_rcal(pi); |
4546 | 4615 | ||
4547 | wlc_lcnphy_rc_cal(pi); | 4616 | wlc_lcnphy_rc_cal(pi); |
4617 | |||
4618 | if (!(pi->sh->boardflags & BFL_FEM)) { | ||
4619 | write_radio_reg(pi, RADIO_2064_REG032, 0x6f); | ||
4620 | write_radio_reg(pi, RADIO_2064_REG033, 0x19); | ||
4621 | write_radio_reg(pi, RADIO_2064_REG039, 0xe); | ||
4622 | } | ||
4623 | |||
4548 | } | 4624 | } |
4549 | 4625 | ||
4550 | static void wlc_lcnphy_radio_init(struct brcms_phy *pi) | 4626 | static void wlc_lcnphy_radio_init(struct brcms_phy *pi) |
@@ -4574,22 +4650,20 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) | |||
4574 | wlc_lcnphy_write_table(pi, &tab); | 4650 | wlc_lcnphy_write_table(pi, &tab); |
4575 | } | 4651 | } |
4576 | 4652 | ||
4577 | tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; | 4653 | if (!(pi->sh->boardflags & BFL_FEM)) { |
4578 | tab.tbl_width = 16; | 4654 | tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; |
4579 | tab.tbl_ptr = &val; | 4655 | tab.tbl_width = 16; |
4580 | tab.tbl_len = 1; | 4656 | tab.tbl_ptr = &val; |
4581 | 4657 | tab.tbl_len = 1; | |
4582 | val = 114; | ||
4583 | tab.tbl_offset = 0; | ||
4584 | wlc_lcnphy_write_table(pi, &tab); | ||
4585 | 4658 | ||
4586 | val = 130; | 4659 | val = 150; |
4587 | tab.tbl_offset = 1; | 4660 | tab.tbl_offset = 0; |
4588 | wlc_lcnphy_write_table(pi, &tab); | 4661 | wlc_lcnphy_write_table(pi, &tab); |
4589 | 4662 | ||
4590 | val = 6; | 4663 | val = 220; |
4591 | tab.tbl_offset = 8; | 4664 | tab.tbl_offset = 1; |
4592 | wlc_lcnphy_write_table(pi, &tab); | 4665 | wlc_lcnphy_write_table(pi, &tab); |
4666 | } | ||
4593 | 4667 | ||
4594 | if (CHSPEC_IS2G(pi->radio_chanspec)) { | 4668 | if (CHSPEC_IS2G(pi->radio_chanspec)) { |
4595 | if (pi->sh->boardflags & BFL_FEM) | 4669 | if (pi->sh->boardflags & BFL_FEM) |
@@ -4946,6 +5020,44 @@ void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi) | |||
4946 | } | 5020 | } |
4947 | } | 5021 | } |
4948 | 5022 | ||
5023 | void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) | ||
5024 | { | ||
5025 | u8 channel = CHSPEC_CHANNEL(chanspec); | ||
5026 | |||
5027 | wlc_phy_chanspec_radio_set((struct brcms_phy_pub *)pi, chanspec); | ||
5028 | |||
5029 | wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); | ||
5030 | |||
5031 | or_phy_reg(pi, 0x44a, 0x44); | ||
5032 | write_phy_reg(pi, 0x44a, 0x80); | ||
5033 | |||
5034 | wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); | ||
5035 | udelay(1000); | ||
5036 | |||
5037 | wlc_lcnphy_toggle_afe_pwdn(pi); | ||
5038 | |||
5039 | write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); | ||
5040 | write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); | ||
5041 | |||
5042 | if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { | ||
5043 | mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); | ||
5044 | |||
5045 | wlc_lcnphy_load_tx_iir_filter(pi, false, 3); | ||
5046 | } else { | ||
5047 | mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); | ||
5048 | |||
5049 | wlc_lcnphy_load_tx_iir_filter(pi, false, 2); | ||
5050 | } | ||
5051 | |||
5052 | if (pi->sh->boardflags & BFL_FEM) | ||
5053 | wlc_lcnphy_load_tx_iir_filter(pi, true, 0); | ||
5054 | else | ||
5055 | wlc_lcnphy_load_tx_iir_filter(pi, true, 3); | ||
5056 | |||
5057 | mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); | ||
5058 | wlc_lcnphy_tssi_setup(pi); | ||
5059 | } | ||
5060 | |||
4949 | void wlc_phy_detach_lcnphy(struct brcms_phy *pi) | 5061 | void wlc_phy_detach_lcnphy(struct brcms_phy *pi) |
4950 | { | 5062 | { |
4951 | kfree(pi->u.pi_lcnphy); | 5063 | kfree(pi->u.pi_lcnphy); |
@@ -4982,8 +5094,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) | |||
4982 | if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) | 5094 | if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) |
4983 | return false; | 5095 | return false; |
4984 | 5096 | ||
4985 | if ((pi->sh->boardflags & BFL_FEM) && | 5097 | if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { |
4986 | (LCNREV_IS(pi->pubpi.phy_rev, 1))) { | ||
4987 | if (pi_lcn->lcnphy_tempsense_option == 3) { | 5098 | if (pi_lcn->lcnphy_tempsense_option == 3) { |
4988 | pi->hwpwrctrl = true; | 5099 | pi->hwpwrctrl = true; |
4989 | pi->hwpwrctrl_capable = true; | 5100 | pi->hwpwrctrl_capable = true; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c index 622c01ca72c5..b7e95acc2084 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c | |||
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = { | |||
1992 | }; | 1992 | }; |
1993 | 1993 | ||
1994 | static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { | 1994 | static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { |
1995 | 0x000a, | ||
1996 | 0x0009, | 1995 | 0x0009, |
1997 | 0x0006, | ||
1998 | 0x0005, | ||
1999 | 0x000a, | 1996 | 0x000a, |
2000 | 0x0009, | ||
2001 | 0x0006, | ||
2002 | 0x0005, | 1997 | 0x0005, |
2003 | 0x000a, | ||
2004 | 0x0009, | ||
2005 | 0x0006, | 1998 | 0x0006, |
2006 | 0x0005, | ||
2007 | 0x000a, | ||
2008 | 0x0009, | 1999 | 0x0009, |
2009 | 0x0006, | ||
2010 | 0x0005, | ||
2011 | 0x000a, | 2000 | 0x000a, |
2012 | 0x0009, | ||
2013 | 0x0006, | ||
2014 | 0x0005, | 2001 | 0x0005, |
2015 | 0x000a, | ||
2016 | 0x0009, | ||
2017 | 0x0006, | 2002 | 0x0006, |
2018 | 0x0005, | ||
2019 | 0x000a, | ||
2020 | 0x0009, | 2003 | 0x0009, |
2021 | 0x0006, | ||
2022 | 0x0005, | ||
2023 | 0x000a, | 2004 | 0x000a, |
2024 | 0x0009, | ||
2025 | 0x0006, | ||
2026 | 0x0005, | 2005 | 0x0005, |
2027 | 0x000a, | ||
2028 | 0x0009, | ||
2029 | 0x0006, | 2006 | 0x0006, |
2030 | 0x0005, | ||
2031 | 0x000a, | ||
2032 | 0x0009, | 2007 | 0x0009, |
2033 | 0x0006, | ||
2034 | 0x0005, | ||
2035 | 0x000a, | 2008 | 0x000a, |
2036 | 0x0009, | ||
2037 | 0x0006, | ||
2038 | 0x0005, | 2009 | 0x0005, |
2039 | 0x000a, | ||
2040 | 0x0009, | ||
2041 | 0x0006, | 2010 | 0x0006, |
2042 | 0x0005, | 2011 | 0x0009, |
2043 | 0x000a, | 2012 | 0x000a, |
2013 | 0x0005, | ||
2014 | 0x0006, | ||
2044 | 0x0009, | 2015 | 0x0009, |
2016 | 0x000a, | ||
2017 | 0x0005, | ||
2045 | 0x0006, | 2018 | 0x0006, |
2019 | 0x0009, | ||
2020 | 0x000a, | ||
2046 | 0x0005, | 2021 | 0x0005, |
2022 | 0x0006, | ||
2023 | 0x0009, | ||
2047 | 0x000a, | 2024 | 0x000a, |
2025 | 0x0005, | ||
2026 | 0x0006, | ||
2048 | 0x0009, | 2027 | 0x0009, |
2028 | 0x000a, | ||
2029 | 0x0005, | ||
2049 | 0x0006, | 2030 | 0x0006, |
2031 | 0x0009, | ||
2032 | 0x000a, | ||
2050 | 0x0005, | 2033 | 0x0005, |
2034 | 0x0006, | ||
2035 | 0x0009, | ||
2051 | 0x000a, | 2036 | 0x000a, |
2037 | 0x0005, | ||
2038 | 0x0006, | ||
2052 | 0x0009, | 2039 | 0x0009, |
2040 | 0x000a, | ||
2041 | 0x0005, | ||
2053 | 0x0006, | 2042 | 0x0006, |
2043 | 0x0009, | ||
2044 | 0x000a, | ||
2054 | 0x0005, | 2045 | 0x0005, |
2046 | 0x0006, | ||
2047 | 0x0009, | ||
2055 | 0x000a, | 2048 | 0x000a, |
2049 | 0x0005, | ||
2050 | 0x0006, | ||
2056 | 0x0009, | 2051 | 0x0009, |
2052 | 0x000a, | ||
2053 | 0x0005, | ||
2057 | 0x0006, | 2054 | 0x0006, |
2055 | 0x0009, | ||
2056 | 0x000a, | ||
2058 | 0x0005, | 2057 | 0x0005, |
2058 | 0x0006, | ||
2059 | }; | 2059 | }; |
2060 | 2060 | ||
2061 | static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { | 2061 | static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 0148dec104f0..4fb2834f4e64 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
@@ -176,6 +176,7 @@ struct brcms_pub { | |||
176 | bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */ | 176 | bool phy_11ncapable; /* the PHY/HW is capable of 802.11N */ |
177 | 177 | ||
178 | struct wl_cnt *_cnt; /* low-level counters in driver */ | 178 | struct wl_cnt *_cnt; /* low-level counters in driver */ |
179 | struct dentry *dbgfs_dir; | ||
179 | }; | 180 | }; |
180 | 181 | ||
181 | enum wlc_par_id { | 182 | enum wlc_par_id { |
@@ -282,9 +283,9 @@ extern void brcms_c_intrson(struct brcms_c_info *wlc); | |||
282 | extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc); | 283 | extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc); |
283 | extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); | 284 | extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); |
284 | extern bool brcms_c_intrsupd(struct brcms_c_info *wlc); | 285 | extern bool brcms_c_intrsupd(struct brcms_c_info *wlc); |
285 | extern bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc); | 286 | extern bool brcms_c_isr(struct brcms_c_info *wlc); |
286 | extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); | 287 | extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); |
287 | extern void brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, | 288 | extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, |
288 | struct sk_buff *sdu, | 289 | struct sk_buff *sdu, |
289 | struct ieee80211_hw *hw); | 290 | struct ieee80211_hw *hw); |
290 | extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); | 291 | extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 46938bc9886d..d92b21a8e597 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -6410,7 +6410,7 @@ out: | |||
6410 | goto out; | 6410 | goto out; |
6411 | } | 6411 | } |
6412 | 6412 | ||
6413 | static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) | 6413 | static void ipw2100_pci_remove_one(struct pci_dev *pci_dev) |
6414 | { | 6414 | { |
6415 | struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); | 6415 | struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); |
6416 | struct net_device *dev = priv->net_dev; | 6416 | struct net_device *dev = priv->net_dev; |
@@ -6606,7 +6606,7 @@ static struct pci_driver ipw2100_pci_driver = { | |||
6606 | .name = DRV_NAME, | 6606 | .name = DRV_NAME, |
6607 | .id_table = ipw2100_pci_id_table, | 6607 | .id_table = ipw2100_pci_id_table, |
6608 | .probe = ipw2100_pci_init_one, | 6608 | .probe = ipw2100_pci_init_one, |
6609 | .remove = __devexit_p(ipw2100_pci_remove_one), | 6609 | .remove = ipw2100_pci_remove_one, |
6610 | #ifdef CONFIG_PM | 6610 | #ifdef CONFIG_PM |
6611 | .suspend = ipw2100_suspend, | 6611 | .suspend = ipw2100_suspend, |
6612 | .resume = ipw2100_resume, | 6612 | .resume = ipw2100_resume, |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 482f505f3f35..844f201b7b70 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -6812,7 +6812,6 @@ static int ipw_wx_get_auth(struct net_device *dev, | |||
6812 | struct libipw_device *ieee = priv->ieee; | 6812 | struct libipw_device *ieee = priv->ieee; |
6813 | struct lib80211_crypt_data *crypt; | 6813 | struct lib80211_crypt_data *crypt; |
6814 | struct iw_param *param = &wrqu->param; | 6814 | struct iw_param *param = &wrqu->param; |
6815 | int ret = 0; | ||
6816 | 6815 | ||
6817 | switch (param->flags & IW_AUTH_INDEX) { | 6816 | switch (param->flags & IW_AUTH_INDEX) { |
6818 | case IW_AUTH_WPA_VERSION: | 6817 | case IW_AUTH_WPA_VERSION: |
@@ -6822,8 +6821,7 @@ static int ipw_wx_get_auth(struct net_device *dev, | |||
6822 | /* | 6821 | /* |
6823 | * wpa_supplicant will control these internally | 6822 | * wpa_supplicant will control these internally |
6824 | */ | 6823 | */ |
6825 | ret = -EOPNOTSUPP; | 6824 | return -EOPNOTSUPP; |
6826 | break; | ||
6827 | 6825 | ||
6828 | case IW_AUTH_TKIP_COUNTERMEASURES: | 6826 | case IW_AUTH_TKIP_COUNTERMEASURES: |
6829 | crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; | 6827 | crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; |
@@ -10774,7 +10772,7 @@ static void ipw_bg_link_down(struct work_struct *work) | |||
10774 | mutex_unlock(&priv->mutex); | 10772 | mutex_unlock(&priv->mutex); |
10775 | } | 10773 | } |
10776 | 10774 | ||
10777 | static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv) | 10775 | static int ipw_setup_deferred_work(struct ipw_priv *priv) |
10778 | { | 10776 | { |
10779 | int ret = 0; | 10777 | int ret = 0; |
10780 | 10778 | ||
@@ -11728,7 +11726,7 @@ static const struct net_device_ops ipw_netdev_ops = { | |||
11728 | .ndo_validate_addr = eth_validate_addr, | 11726 | .ndo_validate_addr = eth_validate_addr, |
11729 | }; | 11727 | }; |
11730 | 11728 | ||
11731 | static int __devinit ipw_pci_probe(struct pci_dev *pdev, | 11729 | static int ipw_pci_probe(struct pci_dev *pdev, |
11732 | const struct pci_device_id *ent) | 11730 | const struct pci_device_id *ent) |
11733 | { | 11731 | { |
11734 | int err = 0; | 11732 | int err = 0; |
@@ -11901,7 +11899,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
11901 | return err; | 11899 | return err; |
11902 | } | 11900 | } |
11903 | 11901 | ||
11904 | static void __devexit ipw_pci_remove(struct pci_dev *pdev) | 11902 | static void ipw_pci_remove(struct pci_dev *pdev) |
11905 | { | 11903 | { |
11906 | struct ipw_priv *priv = pci_get_drvdata(pdev); | 11904 | struct ipw_priv *priv = pci_get_drvdata(pdev); |
11907 | struct list_head *p, *q; | 11905 | struct list_head *p, *q; |
@@ -12063,7 +12061,7 @@ static struct pci_driver ipw_driver = { | |||
12063 | .name = DRV_NAME, | 12061 | .name = DRV_NAME, |
12064 | .id_table = card_ids, | 12062 | .id_table = card_ids, |
12065 | .probe = ipw_pci_probe, | 12063 | .probe = ipw_pci_probe, |
12066 | .remove = __devexit_p(ipw_pci_remove), | 12064 | .remove = ipw_pci_remove, |
12067 | #ifdef CONFIG_PM | 12065 | #ifdef CONFIG_PM |
12068 | .suspend = ipw_pci_suspend, | 12066 | .suspend = ipw_pci_suspend, |
12069 | .resume = ipw_pci_resume, | 12067 | .resume = ipw_pci_resume, |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index e252acb9c862..d604b4036a76 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -3794,7 +3794,7 @@ out: | |||
3794 | return err; | 3794 | return err; |
3795 | } | 3795 | } |
3796 | 3796 | ||
3797 | static void __devexit | 3797 | static void |
3798 | il3945_pci_remove(struct pci_dev *pdev) | 3798 | il3945_pci_remove(struct pci_dev *pdev) |
3799 | { | 3799 | { |
3800 | struct il_priv *il = pci_get_drvdata(pdev); | 3800 | struct il_priv *il = pci_get_drvdata(pdev); |
@@ -3884,7 +3884,7 @@ static struct pci_driver il3945_driver = { | |||
3884 | .name = DRV_NAME, | 3884 | .name = DRV_NAME, |
3885 | .id_table = il3945_hw_card_ids, | 3885 | .id_table = il3945_hw_card_ids, |
3886 | .probe = il3945_pci_probe, | 3886 | .probe = il3945_pci_probe, |
3887 | .remove = __devexit_p(il3945_pci_remove), | 3887 | .remove = il3945_pci_remove, |
3888 | .driver.pm = IL_LEGACY_PM_OPS, | 3888 | .driver.pm = IL_LEGACY_PM_OPS, |
3889 | }; | 3889 | }; |
3890 | 3890 | ||
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 07ffa575e3ef..c3fbf6717564 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -6664,7 +6664,7 @@ out: | |||
6664 | return err; | 6664 | return err; |
6665 | } | 6665 | } |
6666 | 6666 | ||
6667 | static void __devexit | 6667 | static void |
6668 | il4965_pci_remove(struct pci_dev *pdev) | 6668 | il4965_pci_remove(struct pci_dev *pdev) |
6669 | { | 6669 | { |
6670 | struct il_priv *il = pci_get_drvdata(pdev); | 6670 | struct il_priv *il = pci_get_drvdata(pdev); |
@@ -6772,7 +6772,7 @@ static struct pci_driver il4965_driver = { | |||
6772 | .name = DRV_NAME, | 6772 | .name = DRV_NAME, |
6773 | .id_table = il4965_hw_card_ids, | 6773 | .id_table = il4965_hw_card_ids, |
6774 | .probe = il4965_pci_probe, | 6774 | .probe = il4965_pci_probe, |
6775 | .remove = __devexit_p(il4965_pci_remove), | 6775 | .remove = il4965_pci_remove, |
6776 | .driver.pm = IL_LEGACY_PM_OPS, | 6776 | .driver.pm = IL_LEGACY_PM_OPS, |
6777 | }; | 6777 | }; |
6778 | 6778 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index 10896393e5a0..2830ea290502 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
@@ -1012,12 +1012,12 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv, | |||
1012 | * As a consequence, it's not as complicated as it sounds, just add | 1012 | * As a consequence, it's not as complicated as it sounds, just add |
1013 | * any lower rates to the ACK rate bitmap. | 1013 | * any lower rates to the ACK rate bitmap. |
1014 | */ | 1014 | */ |
1015 | if (IWL_RATE_11M_INDEX < lowest_present_ofdm) | 1015 | if (IWL_RATE_11M_INDEX < lowest_present_cck) |
1016 | ofdm |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE; | 1016 | cck |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE; |
1017 | if (IWL_RATE_5M_INDEX < lowest_present_ofdm) | 1017 | if (IWL_RATE_5M_INDEX < lowest_present_cck) |
1018 | ofdm |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE; | 1018 | cck |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE; |
1019 | if (IWL_RATE_2M_INDEX < lowest_present_ofdm) | 1019 | if (IWL_RATE_2M_INDEX < lowest_present_cck) |
1020 | ofdm |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE; | 1020 | cck |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE; |
1021 | /* 1M already there or needed so always add */ | 1021 | /* 1M already there or needed so always add */ |
1022 | cck |= IWL_RATE_1M_MASK >> IWL_FIRST_CCK_RATE; | 1022 | cck |= IWL_RATE_1M_MASK >> IWL_FIRST_CCK_RATE; |
1023 | 1023 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 956fe6c370bc..2b7e8a0b1cd4 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -293,7 +293,7 @@ out_free_trans: | |||
293 | return -EFAULT; | 293 | return -EFAULT; |
294 | } | 294 | } |
295 | 295 | ||
296 | static void __devexit iwl_pci_remove(struct pci_dev *pdev) | 296 | static void iwl_pci_remove(struct pci_dev *pdev) |
297 | { | 297 | { |
298 | struct iwl_trans *trans = pci_get_drvdata(pdev); | 298 | struct iwl_trans *trans = pci_get_drvdata(pdev); |
299 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 299 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
@@ -352,7 +352,7 @@ static struct pci_driver iwl_pci_driver = { | |||
352 | .name = DRV_NAME, | 352 | .name = DRV_NAME, |
353 | .id_table = iwl_hw_card_ids, | 353 | .id_table = iwl_hw_card_ids, |
354 | .probe = iwl_pci_probe, | 354 | .probe = iwl_pci_probe, |
355 | .remove = __devexit_p(iwl_pci_remove), | 355 | .remove = iwl_pci_remove, |
356 | .driver.pm = IWL_PM_OPS, | 356 | .driver.pm = IWL_PM_OPS, |
357 | }; | 357 | }; |
358 | 358 | ||
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index ec36868f6fc5..ec6d5d6b452e 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -298,6 +298,7 @@ static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss) | |||
298 | const u8 *rates_eid, *ext_rates_eid; | 298 | const u8 *rates_eid, *ext_rates_eid; |
299 | int n = 0; | 299 | int n = 0; |
300 | 300 | ||
301 | rcu_read_lock(); | ||
301 | rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); | 302 | rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); |
302 | ext_rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES); | 303 | ext_rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES); |
303 | 304 | ||
@@ -325,6 +326,7 @@ static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss) | |||
325 | *tlv++ = 0x96; | 326 | *tlv++ = 0x96; |
326 | n = 4; | 327 | n = 4; |
327 | } | 328 | } |
329 | rcu_read_unlock(); | ||
328 | 330 | ||
329 | rate_tlv->header.len = cpu_to_le16(n); | 331 | rate_tlv->header.len = cpu_to_le16(n); |
330 | return sizeof(rate_tlv->header) + n; | 332 | return sizeof(rate_tlv->header) + n; |
@@ -1140,11 +1142,13 @@ static int lbs_associate(struct lbs_private *priv, | |||
1140 | cmd->capability = cpu_to_le16(bss->capability); | 1142 | cmd->capability = cpu_to_le16(bss->capability); |
1141 | 1143 | ||
1142 | /* add SSID TLV */ | 1144 | /* add SSID TLV */ |
1145 | rcu_read_lock(); | ||
1143 | ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); | 1146 | ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); |
1144 | if (ssid_eid) | 1147 | if (ssid_eid) |
1145 | pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]); | 1148 | pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]); |
1146 | else | 1149 | else |
1147 | lbs_deb_assoc("no SSID\n"); | 1150 | lbs_deb_assoc("no SSID\n"); |
1151 | rcu_read_unlock(); | ||
1148 | 1152 | ||
1149 | /* add DS param TLV */ | 1153 | /* add DS param TLV */ |
1150 | if (bss->channel) | 1154 | if (bss->channel) |
@@ -1782,7 +1786,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, | |||
1782 | struct cfg80211_ibss_params *params, | 1786 | struct cfg80211_ibss_params *params, |
1783 | struct cfg80211_bss *bss) | 1787 | struct cfg80211_bss *bss) |
1784 | { | 1788 | { |
1785 | const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); | 1789 | const u8 *rates_eid; |
1786 | struct cmd_ds_802_11_ad_hoc_join cmd; | 1790 | struct cmd_ds_802_11_ad_hoc_join cmd; |
1787 | u8 preamble = RADIO_PREAMBLE_SHORT; | 1791 | u8 preamble = RADIO_PREAMBLE_SHORT; |
1788 | int ret = 0; | 1792 | int ret = 0; |
@@ -1841,6 +1845,8 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, | |||
1841 | 1845 | ||
1842 | /* set rates to the intersection of our rates and the rates in the | 1846 | /* set rates to the intersection of our rates and the rates in the |
1843 | bss */ | 1847 | bss */ |
1848 | rcu_read_lock(); | ||
1849 | rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); | ||
1844 | if (!rates_eid) { | 1850 | if (!rates_eid) { |
1845 | lbs_add_rates(cmd.bss.rates); | 1851 | lbs_add_rates(cmd.bss.rates); |
1846 | } else { | 1852 | } else { |
@@ -1860,6 +1866,7 @@ static int lbs_ibss_join_existing(struct lbs_private *priv, | |||
1860 | } | 1866 | } |
1861 | } | 1867 | } |
1862 | } | 1868 | } |
1869 | rcu_read_unlock(); | ||
1863 | 1870 | ||
1864 | /* Only v8 and below support setting this */ | 1871 | /* Only v8 and below support setting this */ |
1865 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) { | 1872 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) { |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 9604a1c4a74d..4bb6574f4073 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -1124,7 +1124,7 @@ static void if_spi_resume_worker(struct work_struct *work) | |||
1124 | } | 1124 | } |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | static int __devinit if_spi_probe(struct spi_device *spi) | 1127 | static int if_spi_probe(struct spi_device *spi) |
1128 | { | 1128 | { |
1129 | struct if_spi_card *card; | 1129 | struct if_spi_card *card; |
1130 | struct lbs_private *priv = NULL; | 1130 | struct lbs_private *priv = NULL; |
@@ -1226,7 +1226,7 @@ out: | |||
1226 | return err; | 1226 | return err; |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | static int __devexit libertas_spi_remove(struct spi_device *spi) | 1229 | static int libertas_spi_remove(struct spi_device *spi) |
1230 | { | 1230 | { |
1231 | struct if_spi_card *card = spi_get_drvdata(spi); | 1231 | struct if_spi_card *card = spi_get_drvdata(spi); |
1232 | struct lbs_private *priv = card->priv; | 1232 | struct lbs_private *priv = card->priv; |
@@ -1285,7 +1285,7 @@ static const struct dev_pm_ops if_spi_pm_ops = { | |||
1285 | 1285 | ||
1286 | static struct spi_driver libertas_spi_driver = { | 1286 | static struct spi_driver libertas_spi_driver = { |
1287 | .probe = if_spi_probe, | 1287 | .probe = if_spi_probe, |
1288 | .remove = __devexit_p(libertas_spi_remove), | 1288 | .remove = libertas_spi_remove, |
1289 | .driver = { | 1289 | .driver = { |
1290 | .name = "libertas_spi", | 1290 | .name = "libertas_spi", |
1291 | .owner = THIS_MODULE, | 1291 | .owner = THIS_MODULE, |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 2aa8a1aa1184..8a61dbd320e6 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1347,9 +1347,14 @@ static void hw_scan_work(struct work_struct *work) | |||
1347 | hwsim->hw_scan_vif, | 1347 | hwsim->hw_scan_vif, |
1348 | req->ssids[i].ssid, | 1348 | req->ssids[i].ssid, |
1349 | req->ssids[i].ssid_len, | 1349 | req->ssids[i].ssid_len, |
1350 | req->ie, req->ie_len); | 1350 | req->ie_len); |
1351 | if (!probe) | 1351 | if (!probe) |
1352 | continue; | 1352 | continue; |
1353 | |||
1354 | if (req->ie_len) | ||
1355 | memcpy(skb_put(probe, req->ie_len), req->ie, | ||
1356 | req->ie_len); | ||
1357 | |||
1353 | local_bh_disable(); | 1358 | local_bh_disable(); |
1354 | mac80211_hwsim_tx_frame(hwsim->hw, probe, | 1359 | mac80211_hwsim_tx_frame(hwsim->hw, probe, |
1355 | hwsim->tmp_chan); | 1360 | hwsim->tmp_chan); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 3b1c27712ad9..a875499f8945 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1948,6 +1948,21 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
1948 | else | 1948 | else |
1949 | ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; | 1949 | ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; |
1950 | 1950 | ||
1951 | if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap)) | ||
1952 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1953 | else | ||
1954 | ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD; | ||
1955 | |||
1956 | if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap)) | ||
1957 | ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT; | ||
1958 | else | ||
1959 | ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT; | ||
1960 | |||
1961 | if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap)) | ||
1962 | ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; | ||
1963 | else | ||
1964 | ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING; | ||
1965 | |||
1951 | ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; | 1966 | ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; |
1952 | ht_info->cap |= IEEE80211_HT_CAP_SM_PS; | 1967 | ht_info->cap |= IEEE80211_HT_CAP_SM_PS; |
1953 | 1968 | ||
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index dda588b35570..4dc8e2e9a889 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -194,6 +194,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
194 | #define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) | 194 | #define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) |
195 | #define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) | 195 | #define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) |
196 | #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) | 196 | #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) |
197 | #define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) | ||
198 | #define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) | ||
197 | 199 | ||
198 | /* httxcfg bitmap | 200 | /* httxcfg bitmap |
199 | * 0 reserved | 201 | * 0 reserved |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 237c8d2ba9f2..cb682561c438 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -160,10 +160,21 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
160 | { | 160 | { |
161 | int ret; | 161 | int ret; |
162 | u8 *beacon_ie; | 162 | u8 *beacon_ie; |
163 | size_t beacon_ie_len; | ||
163 | struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; | 164 | struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; |
165 | const struct cfg80211_bss_ies *ies; | ||
166 | |||
167 | rcu_read_lock(); | ||
168 | ies = rcu_dereference(bss->ies); | ||
169 | if (WARN_ON(!ies)) { | ||
170 | /* should never happen */ | ||
171 | rcu_read_unlock(); | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC); | ||
175 | beacon_ie_len = ies->len; | ||
176 | rcu_read_unlock(); | ||
164 | 177 | ||
165 | beacon_ie = kmemdup(bss->information_elements, bss->len_beacon_ies, | ||
166 | GFP_KERNEL); | ||
167 | if (!beacon_ie) { | 178 | if (!beacon_ie) { |
168 | dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); | 179 | dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n"); |
169 | return -ENOMEM; | 180 | return -ENOMEM; |
@@ -172,7 +183,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
172 | memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); | 183 | memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); |
173 | bss_desc->rssi = bss->signal; | 184 | bss_desc->rssi = bss->signal; |
174 | bss_desc->beacon_buf = beacon_ie; | 185 | bss_desc->beacon_buf = beacon_ie; |
175 | bss_desc->beacon_buf_size = bss->len_beacon_ies; | 186 | bss_desc->beacon_buf_size = beacon_ie_len; |
176 | bss_desc->beacon_period = bss->beacon_interval; | 187 | bss_desc->beacon_period = bss->beacon_interval; |
177 | bss_desc->cap_info_bitmap = bss->capability; | 188 | bss_desc->cap_info_bitmap = bss->capability; |
178 | bss_desc->bss_band = bss_priv->band; | 189 | bss_desc->bss_band = bss_priv->band; |
@@ -198,18 +209,23 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
198 | static int mwifiex_process_country_ie(struct mwifiex_private *priv, | 209 | static int mwifiex_process_country_ie(struct mwifiex_private *priv, |
199 | struct cfg80211_bss *bss) | 210 | struct cfg80211_bss *bss) |
200 | { | 211 | { |
201 | u8 *country_ie, country_ie_len; | 212 | const u8 *country_ie; |
213 | u8 country_ie_len; | ||
202 | struct mwifiex_802_11d_domain_reg *domain_info = | 214 | struct mwifiex_802_11d_domain_reg *domain_info = |
203 | &priv->adapter->domain_reg; | 215 | &priv->adapter->domain_reg; |
204 | 216 | ||
205 | country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); | 217 | rcu_read_lock(); |
206 | 218 | country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); | |
207 | if (!country_ie) | 219 | if (!country_ie) { |
220 | rcu_read_unlock(); | ||
208 | return 0; | 221 | return 0; |
222 | } | ||
209 | 223 | ||
210 | country_ie_len = country_ie[1]; | 224 | country_ie_len = country_ie[1]; |
211 | if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) | 225 | if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) { |
226 | rcu_read_unlock(); | ||
212 | return 0; | 227 | return 0; |
228 | } | ||
213 | 229 | ||
214 | domain_info->country_code[0] = country_ie[2]; | 230 | domain_info->country_code[0] = country_ie[2]; |
215 | domain_info->country_code[1] = country_ie[3]; | 231 | domain_info->country_code[1] = country_ie[3]; |
@@ -223,6 +239,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
223 | memcpy((u8 *)domain_info->triplet, | 239 | memcpy((u8 *)domain_info->triplet, |
224 | &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); | 240 | &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); |
225 | 241 | ||
242 | rcu_read_unlock(); | ||
243 | |||
226 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, | 244 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, |
227 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 245 | HostCmd_ACT_GEN_SET, 0, NULL)) { |
228 | wiphy_err(priv->adapter->wiphy, | 246 | wiphy_err(priv->adapter->wiphy, |
@@ -461,7 +479,7 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) | |||
461 | } | 479 | } |
462 | 480 | ||
463 | if (adapter->hs_activated) { | 481 | if (adapter->hs_activated) { |
464 | dev_dbg(adapter->dev, "cmd: HS Already actived\n"); | 482 | dev_dbg(adapter->dev, "cmd: HS Already activated\n"); |
465 | return true; | 483 | return true; |
466 | } | 484 | } |
467 | 485 | ||
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index bbe1f3518e4b..63ac9f2d11ae 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -351,7 +351,7 @@ static int mwifiex_usb_probe(struct usb_interface *intf, | |||
351 | card->udev = udev; | 351 | card->udev = udev; |
352 | card->intf = intf; | 352 | card->intf = intf; |
353 | 353 | ||
354 | pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocl=%#x\n", | 354 | pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n", |
355 | udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass, | 355 | udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass, |
356 | udev->descriptor.bDeviceSubClass, | 356 | udev->descriptor.bDeviceSubClass, |
357 | udev->descriptor.bDeviceProtocol); | 357 | udev->descriptor.bDeviceProtocol); |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0cdae6632735..f221b95b90b3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -5258,7 +5258,7 @@ enum { | |||
5258 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" | 5258 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" |
5259 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) | 5259 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) |
5260 | 5260 | ||
5261 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { | 5261 | static struct mwl8k_device_info mwl8k_info_tbl[] = { |
5262 | [MWL8363] = { | 5262 | [MWL8363] = { |
5263 | .part_name = "88w8363", | 5263 | .part_name = "88w8363", |
5264 | .helper_image = "mwl8k/helper_8363.fw", | 5264 | .helper_image = "mwl8k/helper_8363.fw", |
@@ -5756,7 +5756,7 @@ err_free_cookie: | |||
5756 | 5756 | ||
5757 | return rc; | 5757 | return rc; |
5758 | } | 5758 | } |
5759 | static int __devinit mwl8k_probe(struct pci_dev *pdev, | 5759 | static int mwl8k_probe(struct pci_dev *pdev, |
5760 | const struct pci_device_id *id) | 5760 | const struct pci_device_id *id) |
5761 | { | 5761 | { |
5762 | static int printed_version; | 5762 | static int printed_version; |
@@ -5873,12 +5873,7 @@ err_disable_device: | |||
5873 | return rc; | 5873 | return rc; |
5874 | } | 5874 | } |
5875 | 5875 | ||
5876 | static void __devexit mwl8k_shutdown(struct pci_dev *pdev) | 5876 | static void mwl8k_remove(struct pci_dev *pdev) |
5877 | { | ||
5878 | printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__); | ||
5879 | } | ||
5880 | |||
5881 | static void __devexit mwl8k_remove(struct pci_dev *pdev) | ||
5882 | { | 5877 | { |
5883 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 5878 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
5884 | struct mwl8k_priv *priv; | 5879 | struct mwl8k_priv *priv; |
@@ -5930,8 +5925,7 @@ static struct pci_driver mwl8k_driver = { | |||
5930 | .name = MWL8K_NAME, | 5925 | .name = MWL8K_NAME, |
5931 | .id_table = mwl8k_pci_id_table, | 5926 | .id_table = mwl8k_pci_id_table, |
5932 | .probe = mwl8k_probe, | 5927 | .probe = mwl8k_probe, |
5933 | .remove = __devexit_p(mwl8k_remove), | 5928 | .remove = mwl8k_remove, |
5934 | .shutdown = __devexit_p(mwl8k_shutdown), | ||
5935 | }; | 5929 | }; |
5936 | 5930 | ||
5937 | module_pci_driver(mwl8k_driver); | 5931 | module_pci_driver(mwl8k_driver); |
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index 326396b313a6..d73fdf6185a2 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c | |||
@@ -255,7 +255,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev, | |||
255 | return err; | 255 | return err; |
256 | } | 256 | } |
257 | 257 | ||
258 | static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev) | 258 | static void orinoco_nortel_remove_one(struct pci_dev *pdev) |
259 | { | 259 | { |
260 | struct orinoco_private *priv = pci_get_drvdata(pdev); | 260 | struct orinoco_private *priv = pci_get_drvdata(pdev); |
261 | struct orinoco_pci_card *card = priv->card; | 261 | struct orinoco_pci_card *card = priv->card; |
@@ -288,7 +288,7 @@ static struct pci_driver orinoco_nortel_driver = { | |||
288 | .name = DRIVER_NAME, | 288 | .name = DRIVER_NAME, |
289 | .id_table = orinoco_nortel_id_table, | 289 | .id_table = orinoco_nortel_id_table, |
290 | .probe = orinoco_nortel_init_one, | 290 | .probe = orinoco_nortel_init_one, |
291 | .remove = __devexit_p(orinoco_nortel_remove_one), | 291 | .remove = orinoco_nortel_remove_one, |
292 | .suspend = orinoco_pci_suspend, | 292 | .suspend = orinoco_pci_suspend, |
293 | .resume = orinoco_pci_resume, | 293 | .resume = orinoco_pci_resume, |
294 | }; | 294 | }; |
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index 6058c66b844e..677bf14eca84 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c | |||
@@ -199,7 +199,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
199 | return err; | 199 | return err; |
200 | } | 200 | } |
201 | 201 | ||
202 | static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) | 202 | static void orinoco_pci_remove_one(struct pci_dev *pdev) |
203 | { | 203 | { |
204 | struct orinoco_private *priv = pci_get_drvdata(pdev); | 204 | struct orinoco_private *priv = pci_get_drvdata(pdev); |
205 | 205 | ||
@@ -228,7 +228,7 @@ static struct pci_driver orinoco_pci_driver = { | |||
228 | .name = DRIVER_NAME, | 228 | .name = DRIVER_NAME, |
229 | .id_table = orinoco_pci_id_table, | 229 | .id_table = orinoco_pci_id_table, |
230 | .probe = orinoco_pci_init_one, | 230 | .probe = orinoco_pci_init_one, |
231 | .remove = __devexit_p(orinoco_pci_remove_one), | 231 | .remove = orinoco_pci_remove_one, |
232 | .suspend = orinoco_pci_suspend, | 232 | .suspend = orinoco_pci_suspend, |
233 | .resume = orinoco_pci_resume, | 233 | .resume = orinoco_pci_resume, |
234 | }; | 234 | }; |
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index 2bac8248a991..2559dbd6184b 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c | |||
@@ -294,7 +294,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
294 | return err; | 294 | return err; |
295 | } | 295 | } |
296 | 296 | ||
297 | static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) | 297 | static void orinoco_plx_remove_one(struct pci_dev *pdev) |
298 | { | 298 | { |
299 | struct orinoco_private *priv = pci_get_drvdata(pdev); | 299 | struct orinoco_private *priv = pci_get_drvdata(pdev); |
300 | struct orinoco_pci_card *card = priv->card; | 300 | struct orinoco_pci_card *card = priv->card; |
@@ -334,7 +334,7 @@ static struct pci_driver orinoco_plx_driver = { | |||
334 | .name = DRIVER_NAME, | 334 | .name = DRIVER_NAME, |
335 | .id_table = orinoco_plx_id_table, | 335 | .id_table = orinoco_plx_id_table, |
336 | .probe = orinoco_plx_init_one, | 336 | .probe = orinoco_plx_init_one, |
337 | .remove = __devexit_p(orinoco_plx_remove_one), | 337 | .remove = orinoco_plx_remove_one, |
338 | .suspend = orinoco_pci_suspend, | 338 | .suspend = orinoco_pci_suspend, |
339 | .resume = orinoco_pci_resume, | 339 | .resume = orinoco_pci_resume, |
340 | }; | 340 | }; |
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 93159d68ec93..42afeeea2c40 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c | |||
@@ -188,7 +188,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
188 | return err; | 188 | return err; |
189 | } | 189 | } |
190 | 190 | ||
191 | static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) | 191 | static void orinoco_tmd_remove_one(struct pci_dev *pdev) |
192 | { | 192 | { |
193 | struct orinoco_private *priv = pci_get_drvdata(pdev); | 193 | struct orinoco_private *priv = pci_get_drvdata(pdev); |
194 | struct orinoco_pci_card *card = priv->card; | 194 | struct orinoco_pci_card *card = priv->card; |
@@ -214,7 +214,7 @@ static struct pci_driver orinoco_tmd_driver = { | |||
214 | .name = DRIVER_NAME, | 214 | .name = DRIVER_NAME, |
215 | .id_table = orinoco_tmd_id_table, | 215 | .id_table = orinoco_tmd_id_table, |
216 | .probe = orinoco_tmd_init_one, | 216 | .probe = orinoco_tmd_init_one, |
217 | .remove = __devexit_p(orinoco_tmd_remove_one), | 217 | .remove = orinoco_tmd_remove_one, |
218 | .suspend = orinoco_pci_suspend, | 218 | .suspend = orinoco_pci_suspend, |
219 | .resume = orinoco_pci_resume, | 219 | .resume = orinoco_pci_resume, |
220 | }; | 220 | }; |
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 1ef1bfe6a9d7..d43e3740e45d 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
@@ -541,8 +541,9 @@ static int p54_parse_rssical(struct ieee80211_hw *dev, | |||
541 | entries = (len - offset) / | 541 | entries = (len - offset) / |
542 | sizeof(struct pda_rssi_cal_ext_entry); | 542 | sizeof(struct pda_rssi_cal_ext_entry); |
543 | 543 | ||
544 | if ((len - offset) % sizeof(struct pda_rssi_cal_ext_entry) || | 544 | if (len < offset || |
545 | entries <= 0) { | 545 | (len - offset) % sizeof(struct pda_rssi_cal_ext_entry) || |
546 | entries == 0) { | ||
546 | wiphy_err(dev->wiphy, "invalid rssi database.\n"); | 547 | wiphy_err(dev->wiphy, "invalid rssi database.\n"); |
547 | goto err_data; | 548 | goto err_data; |
548 | } | 549 | } |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index b4390797d78c..933e5d941937 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -540,7 +540,7 @@ out: | |||
540 | pci_dev_put(pdev); | 540 | pci_dev_put(pdev); |
541 | } | 541 | } |
542 | 542 | ||
543 | static int __devinit p54p_probe(struct pci_dev *pdev, | 543 | static int p54p_probe(struct pci_dev *pdev, |
544 | const struct pci_device_id *id) | 544 | const struct pci_device_id *id) |
545 | { | 545 | { |
546 | struct p54p_priv *priv; | 546 | struct p54p_priv *priv; |
@@ -639,7 +639,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
639 | return err; | 639 | return err; |
640 | } | 640 | } |
641 | 641 | ||
642 | static void __devexit p54p_remove(struct pci_dev *pdev) | 642 | static void p54p_remove(struct pci_dev *pdev) |
643 | { | 643 | { |
644 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); | 644 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); |
645 | struct p54p_priv *priv; | 645 | struct p54p_priv *priv; |
@@ -659,7 +659,7 @@ static void __devexit p54p_remove(struct pci_dev *pdev) | |||
659 | p54_free_common(dev); | 659 | p54_free_common(dev); |
660 | } | 660 | } |
661 | 661 | ||
662 | #ifdef CONFIG_PM | 662 | #ifdef CONFIG_PM_SLEEP |
663 | static int p54p_suspend(struct device *device) | 663 | static int p54p_suspend(struct device *device) |
664 | { | 664 | { |
665 | struct pci_dev *pdev = to_pci_dev(device); | 665 | struct pci_dev *pdev = to_pci_dev(device); |
@@ -681,25 +681,18 @@ static int p54p_resume(struct device *device) | |||
681 | return pci_set_power_state(pdev, PCI_D0); | 681 | return pci_set_power_state(pdev, PCI_D0); |
682 | } | 682 | } |
683 | 683 | ||
684 | static const struct dev_pm_ops p54pci_pm_ops = { | 684 | static SIMPLE_DEV_PM_OPS(p54pci_pm_ops, p54p_suspend, p54p_resume); |
685 | .suspend = p54p_suspend, | ||
686 | .resume = p54p_resume, | ||
687 | .freeze = p54p_suspend, | ||
688 | .thaw = p54p_resume, | ||
689 | .poweroff = p54p_suspend, | ||
690 | .restore = p54p_resume, | ||
691 | }; | ||
692 | 685 | ||
693 | #define P54P_PM_OPS (&p54pci_pm_ops) | 686 | #define P54P_PM_OPS (&p54pci_pm_ops) |
694 | #else | 687 | #else |
695 | #define P54P_PM_OPS (NULL) | 688 | #define P54P_PM_OPS (NULL) |
696 | #endif /* CONFIG_PM */ | 689 | #endif /* CONFIG_PM_SLEEP */ |
697 | 690 | ||
698 | static struct pci_driver p54p_driver = { | 691 | static struct pci_driver p54p_driver = { |
699 | .name = "p54pci", | 692 | .name = "p54pci", |
700 | .id_table = p54p_table, | 693 | .id_table = p54p_table, |
701 | .probe = p54p_probe, | 694 | .probe = p54p_probe, |
702 | .remove = __devexit_p(p54p_remove), | 695 | .remove = p54p_remove, |
703 | .driver.pm = P54P_PM_OPS, | 696 | .driver.pm = P54P_PM_OPS, |
704 | }; | 697 | }; |
705 | 698 | ||
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index f7929906d437..4fd49a007b51 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
@@ -595,7 +595,7 @@ static void p54spi_op_stop(struct ieee80211_hw *dev) | |||
595 | cancel_work_sync(&priv->work); | 595 | cancel_work_sync(&priv->work); |
596 | } | 596 | } |
597 | 597 | ||
598 | static int __devinit p54spi_probe(struct spi_device *spi) | 598 | static int p54spi_probe(struct spi_device *spi) |
599 | { | 599 | { |
600 | struct p54s_priv *priv = NULL; | 600 | struct p54s_priv *priv = NULL; |
601 | struct ieee80211_hw *hw; | 601 | struct ieee80211_hw *hw; |
@@ -683,7 +683,7 @@ err_free: | |||
683 | return ret; | 683 | return ret; |
684 | } | 684 | } |
685 | 685 | ||
686 | static int __devexit p54spi_remove(struct spi_device *spi) | 686 | static int p54spi_remove(struct spi_device *spi) |
687 | { | 687 | { |
688 | struct p54s_priv *priv = dev_get_drvdata(&spi->dev); | 688 | struct p54s_priv *priv = dev_get_drvdata(&spi->dev); |
689 | 689 | ||
@@ -710,7 +710,7 @@ static struct spi_driver p54spi_driver = { | |||
710 | }, | 710 | }, |
711 | 711 | ||
712 | .probe = p54spi_probe, | 712 | .probe = p54spi_probe, |
713 | .remove = __devexit_p(p54spi_remove), | 713 | .remove = p54spi_remove, |
714 | }; | 714 | }; |
715 | 715 | ||
716 | static int __init p54spi_init(void) | 716 | static int __init p54spi_init(void) |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index effb044a8a9d..e71c702e2eb1 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -986,7 +986,7 @@ static int p54u_load_firmware(struct ieee80211_hw *dev, | |||
986 | return err; | 986 | return err; |
987 | } | 987 | } |
988 | 988 | ||
989 | static int __devinit p54u_probe(struct usb_interface *intf, | 989 | static int p54u_probe(struct usb_interface *intf, |
990 | const struct usb_device_id *id) | 990 | const struct usb_device_id *id) |
991 | { | 991 | { |
992 | struct usb_device *udev = interface_to_usbdev(intf); | 992 | struct usb_device *udev = interface_to_usbdev(intf); |
@@ -1057,7 +1057,7 @@ static int __devinit p54u_probe(struct usb_interface *intf, | |||
1057 | return err; | 1057 | return err; |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | static void __devexit p54u_disconnect(struct usb_interface *intf) | 1060 | static void p54u_disconnect(struct usb_interface *intf) |
1061 | { | 1061 | { |
1062 | struct ieee80211_hw *dev = usb_get_intfdata(intf); | 1062 | struct ieee80211_hw *dev = usb_get_intfdata(intf); |
1063 | struct p54u_priv *priv; | 1063 | struct p54u_priv *priv; |
@@ -1131,7 +1131,7 @@ static struct usb_driver p54u_driver = { | |||
1131 | .name = "p54usb", | 1131 | .name = "p54usb", |
1132 | .id_table = p54u_table, | 1132 | .id_table = p54u_table, |
1133 | .probe = p54u_probe, | 1133 | .probe = p54u_probe, |
1134 | .disconnect = __devexit_p(p54u_disconnect), | 1134 | .disconnect = p54u_disconnect, |
1135 | .pre_reset = p54u_pre_reset, | 1135 | .pre_reset = p54u_pre_reset, |
1136 | .post_reset = p54u_post_reset, | 1136 | .post_reset = p54u_post_reset, |
1137 | #ifdef CONFIG_PM | 1137 | #ifdef CONFIG_PM |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e3a2d9070cf6..a2d2bc2c7b3d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1831,7 +1831,7 @@ static struct pci_driver rt2400pci_driver = { | |||
1831 | .name = KBUILD_MODNAME, | 1831 | .name = KBUILD_MODNAME, |
1832 | .id_table = rt2400pci_device_table, | 1832 | .id_table = rt2400pci_device_table, |
1833 | .probe = rt2400pci_probe, | 1833 | .probe = rt2400pci_probe, |
1834 | .remove = __devexit_p(rt2x00pci_remove), | 1834 | .remove = rt2x00pci_remove, |
1835 | .suspend = rt2x00pci_suspend, | 1835 | .suspend = rt2x00pci_suspend, |
1836 | .resume = rt2x00pci_resume, | 1836 | .resume = rt2x00pci_resume, |
1837 | }; | 1837 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 479d756e275b..9bea10f53f0a 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -2122,7 +2122,7 @@ static struct pci_driver rt2500pci_driver = { | |||
2122 | .name = KBUILD_MODNAME, | 2122 | .name = KBUILD_MODNAME, |
2123 | .id_table = rt2500pci_device_table, | 2123 | .id_table = rt2500pci_device_table, |
2124 | .probe = rt2500pci_probe, | 2124 | .probe = rt2500pci_probe, |
2125 | .remove = __devexit_p(rt2x00pci_remove), | 2125 | .remove = rt2x00pci_remove, |
2126 | .suspend = rt2x00pci_suspend, | 2126 | .suspend = rt2x00pci_suspend, |
2127 | .resume = rt2x00pci_resume, | 2127 | .resume = rt2x00pci_resume, |
2128 | }; | 2128 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 6d67c3ede651..4db1088a847f 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1993,8 +1993,10 @@ struct mac_iveiv_entry { | |||
1993 | */ | 1993 | */ |
1994 | #define RFCSR3_K FIELD8(0x0f) | 1994 | #define RFCSR3_K FIELD8(0x0f) |
1995 | /* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */ | 1995 | /* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */ |
1996 | #define RFCSR3_PA1_BIAS_CCK FIELD8(0x70); | 1996 | #define RFCSR3_PA1_BIAS_CCK FIELD8(0x70) |
1997 | #define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80); | 1997 | #define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80) |
1998 | /* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */ | ||
1999 | #define RFCSR3_VCOCAL_EN FIELD8(0x80) | ||
1998 | 2000 | ||
1999 | /* | 2001 | /* |
2000 | * FRCSR 5: | 2002 | * FRCSR 5: |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index c0441a715c96..d4d0c3664eb2 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -2173,7 +2173,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
2173 | rt2800_rfcsr_write(rt2x00dev, 59, | 2173 | rt2800_rfcsr_write(rt2x00dev, 59, |
2174 | r59_nonbt_rev[idx]); | 2174 | r59_nonbt_rev[idx]); |
2175 | } else if (rt2x00_rt(rt2x00dev, RT5390) || | 2175 | } else if (rt2x00_rt(rt2x00dev, RT5390) || |
2176 | rt2x00_rt(rt2x00dev, RT5392)) { | 2176 | rt2x00_rt(rt2x00dev, RT5392)) { |
2177 | static const char r59_non_bt[] = {0x8f, 0x8f, | 2177 | static const char r59_non_bt[] = {0x8f, 0x8f, |
2178 | 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, | 2178 | 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, |
2179 | 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; | 2179 | 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; |
@@ -2243,7 +2243,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2243 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | 2243 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); |
2244 | 2244 | ||
2245 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | 2245 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); |
2246 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | 2246 | rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); |
2247 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | 2247 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); |
2248 | } | 2248 | } |
2249 | 2249 | ||
@@ -2264,7 +2264,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
2264 | 2264 | ||
2265 | if (rf->channel <= 14) { | 2265 | if (rf->channel <= 14) { |
2266 | if (!rt2x00_rt(rt2x00dev, RT5390) && | 2266 | if (!rt2x00_rt(rt2x00dev, RT5390) && |
2267 | !rt2x00_rt(rt2x00dev, RT5392)) { | 2267 | !rt2x00_rt(rt2x00dev, RT5392)) { |
2268 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, | 2268 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, |
2269 | &rt2x00dev->cap_flags)) { | 2269 | &rt2x00dev->cap_flags)) { |
2270 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | 2270 | rt2800_bbp_write(rt2x00dev, 82, 0x62); |
@@ -2804,7 +2804,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) | |||
2804 | case RF5390: | 2804 | case RF5390: |
2805 | case RF5392: | 2805 | case RF5392: |
2806 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | 2806 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); |
2807 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | 2807 | rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); |
2808 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | 2808 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); |
2809 | break; | 2809 | break; |
2810 | default: | 2810 | default: |
@@ -3592,8 +3592,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3592 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) | 3592 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) |
3593 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 3593 | rt2800_bbp_write(rt2x00dev, 84, 0x19); |
3594 | else if (rt2x00_rt(rt2x00dev, RT3290) || | 3594 | else if (rt2x00_rt(rt2x00dev, RT3290) || |
3595 | rt2x00_rt(rt2x00dev, RT5390) || | 3595 | rt2x00_rt(rt2x00dev, RT5390) || |
3596 | rt2x00_rt(rt2x00dev, RT5392)) | 3596 | rt2x00_rt(rt2x00dev, RT5392)) |
3597 | rt2800_bbp_write(rt2x00dev, 84, 0x9a); | 3597 | rt2800_bbp_write(rt2x00dev, 84, 0x9a); |
3598 | else | 3598 | else |
3599 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 3599 | rt2800_bbp_write(rt2x00dev, 84, 0x99); |
@@ -3652,7 +3652,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3652 | else if (rt2x00_rt(rt2x00dev, RT3352)) | 3652 | else if (rt2x00_rt(rt2x00dev, RT3352)) |
3653 | rt2800_bbp_write(rt2x00dev, 105, 0x34); | 3653 | rt2800_bbp_write(rt2x00dev, 105, 0x34); |
3654 | else if (rt2x00_rt(rt2x00dev, RT5390) || | 3654 | else if (rt2x00_rt(rt2x00dev, RT5390) || |
3655 | rt2x00_rt(rt2x00dev, RT5392)) | 3655 | rt2x00_rt(rt2x00dev, RT5392)) |
3656 | rt2800_bbp_write(rt2x00dev, 105, 0x3c); | 3656 | rt2800_bbp_write(rt2x00dev, 105, 0x3c); |
3657 | else | 3657 | else |
3658 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 3658 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
@@ -3746,7 +3746,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
3746 | } | 3746 | } |
3747 | 3747 | ||
3748 | if (rt2x00_rt(rt2x00dev, RT5390) || | 3748 | if (rt2x00_rt(rt2x00dev, RT5390) || |
3749 | rt2x00_rt(rt2x00dev, RT5392)) { | 3749 | rt2x00_rt(rt2x00dev, RT5392)) { |
3750 | int ant, div_mode; | 3750 | int ant, div_mode; |
3751 | 3751 | ||
3752 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); | 3752 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); |
@@ -4220,66 +4220,66 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4220 | rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); | 4220 | rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); |
4221 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); | 4221 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); |
4222 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); | 4222 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); |
4223 | } else if (rt2x00_rt(rt2x00dev, RT5392)) { | 4223 | } else if (rt2x00_rt(rt2x00dev, RT5392)) { |
4224 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); | 4224 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); |
4225 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | 4225 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); |
4226 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); | 4226 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); |
4227 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | 4227 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); |
4228 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); | 4228 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); |
4229 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | 4229 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); |
4230 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | 4230 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); |
4231 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | 4231 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); |
4232 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); | 4232 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); |
4233 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | 4233 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); |
4234 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | 4234 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); |
4235 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | 4235 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); |
4236 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); | 4236 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); |
4237 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); | 4237 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); |
4238 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4d); | 4238 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4d); |
4239 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); | 4239 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); |
4240 | rt2800_rfcsr_write(rt2x00dev, 21, 0x8d); | 4240 | rt2800_rfcsr_write(rt2x00dev, 21, 0x8d); |
4241 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | 4241 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); |
4242 | rt2800_rfcsr_write(rt2x00dev, 23, 0x0b); | 4242 | rt2800_rfcsr_write(rt2x00dev, 23, 0x0b); |
4243 | rt2800_rfcsr_write(rt2x00dev, 24, 0x44); | 4243 | rt2800_rfcsr_write(rt2x00dev, 24, 0x44); |
4244 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | 4244 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); |
4245 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | 4245 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); |
4246 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | 4246 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); |
4247 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | 4247 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); |
4248 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | 4248 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); |
4249 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | 4249 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); |
4250 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | 4250 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); |
4251 | rt2800_rfcsr_write(rt2x00dev, 32, 0x20); | 4251 | rt2800_rfcsr_write(rt2x00dev, 32, 0x20); |
4252 | rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); | 4252 | rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); |
4253 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); | 4253 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); |
4254 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | 4254 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); |
4255 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | 4255 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); |
4256 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); | 4256 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); |
4257 | rt2800_rfcsr_write(rt2x00dev, 38, 0x89); | 4257 | rt2800_rfcsr_write(rt2x00dev, 38, 0x89); |
4258 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | 4258 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); |
4259 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0f); | 4259 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0f); |
4260 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | 4260 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); |
4261 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); | 4261 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); |
4262 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); | 4262 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); |
4263 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | 4263 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); |
4264 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | 4264 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); |
4265 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | 4265 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); |
4266 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0c); | 4266 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0c); |
4267 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | 4267 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); |
4268 | rt2800_rfcsr_write(rt2x00dev, 49, 0x94); | 4268 | rt2800_rfcsr_write(rt2x00dev, 49, 0x94); |
4269 | rt2800_rfcsr_write(rt2x00dev, 50, 0x94); | 4269 | rt2800_rfcsr_write(rt2x00dev, 50, 0x94); |
4270 | rt2800_rfcsr_write(rt2x00dev, 51, 0x3a); | 4270 | rt2800_rfcsr_write(rt2x00dev, 51, 0x3a); |
4271 | rt2800_rfcsr_write(rt2x00dev, 52, 0x48); | 4271 | rt2800_rfcsr_write(rt2x00dev, 52, 0x48); |
4272 | rt2800_rfcsr_write(rt2x00dev, 53, 0x44); | 4272 | rt2800_rfcsr_write(rt2x00dev, 53, 0x44); |
4273 | rt2800_rfcsr_write(rt2x00dev, 54, 0x38); | 4273 | rt2800_rfcsr_write(rt2x00dev, 54, 0x38); |
4274 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | 4274 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); |
4275 | rt2800_rfcsr_write(rt2x00dev, 56, 0xa1); | 4275 | rt2800_rfcsr_write(rt2x00dev, 56, 0xa1); |
4276 | rt2800_rfcsr_write(rt2x00dev, 57, 0x00); | 4276 | rt2800_rfcsr_write(rt2x00dev, 57, 0x00); |
4277 | rt2800_rfcsr_write(rt2x00dev, 58, 0x39); | 4277 | rt2800_rfcsr_write(rt2x00dev, 58, 0x39); |
4278 | rt2800_rfcsr_write(rt2x00dev, 59, 0x07); | 4278 | rt2800_rfcsr_write(rt2x00dev, 59, 0x07); |
4279 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | 4279 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); |
4280 | rt2800_rfcsr_write(rt2x00dev, 61, 0x91); | 4280 | rt2800_rfcsr_write(rt2x00dev, 61, 0x91); |
4281 | rt2800_rfcsr_write(rt2x00dev, 62, 0x39); | 4281 | rt2800_rfcsr_write(rt2x00dev, 62, 0x39); |
4282 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); | 4282 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); |
4283 | } | 4283 | } |
4284 | 4284 | ||
4285 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { | 4285 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { |
@@ -4356,7 +4356,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4356 | rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26); | 4356 | rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26); |
4357 | 4357 | ||
4358 | if (!rt2x00_rt(rt2x00dev, RT5390) && | 4358 | if (!rt2x00_rt(rt2x00dev, RT5390) && |
4359 | !rt2x00_rt(rt2x00dev, RT5392)) { | 4359 | !rt2x00_rt(rt2x00dev, RT5392)) { |
4360 | /* | 4360 | /* |
4361 | * Set back to initial state | 4361 | * Set back to initial state |
4362 | */ | 4362 | */ |
@@ -4385,7 +4385,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4385 | rt2800_register_write(rt2x00dev, OPT_14_CSR, reg); | 4385 | rt2800_register_write(rt2x00dev, OPT_14_CSR, reg); |
4386 | 4386 | ||
4387 | if (!rt2x00_rt(rt2x00dev, RT5390) && | 4387 | if (!rt2x00_rt(rt2x00dev, RT5390) && |
4388 | !rt2x00_rt(rt2x00dev, RT5392)) { | 4388 | !rt2x00_rt(rt2x00dev, RT5392)) { |
4389 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 4389 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); |
4390 | rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); | 4390 | rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); |
4391 | if (rt2x00_rt(rt2x00dev, RT3070) || | 4391 | if (rt2x00_rt(rt2x00dev, RT3070) || |
@@ -4457,7 +4457,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
4457 | } | 4457 | } |
4458 | 4458 | ||
4459 | if (rt2x00_rt(rt2x00dev, RT5390) || | 4459 | if (rt2x00_rt(rt2x00dev, RT5390) || |
4460 | rt2x00_rt(rt2x00dev, RT5392)) { | 4460 | rt2x00_rt(rt2x00dev, RT5392)) { |
4461 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); | 4461 | rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); |
4462 | rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); | 4462 | rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); |
4463 | rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); | 4463 | rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 27829e1e2e38..9224d874bf24 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1176,7 +1176,7 @@ static struct platform_driver rt2800soc_driver = { | |||
1176 | .mod_name = KBUILD_MODNAME, | 1176 | .mod_name = KBUILD_MODNAME, |
1177 | }, | 1177 | }, |
1178 | .probe = rt2800soc_probe, | 1178 | .probe = rt2800soc_probe, |
1179 | .remove = __devexit_p(rt2x00soc_remove), | 1179 | .remove = rt2x00soc_remove, |
1180 | .suspend = rt2x00soc_suspend, | 1180 | .suspend = rt2x00soc_suspend, |
1181 | .resume = rt2x00soc_resume, | 1181 | .resume = rt2x00soc_resume, |
1182 | }; | 1182 | }; |
@@ -1193,7 +1193,7 @@ static struct pci_driver rt2800pci_driver = { | |||
1193 | .name = KBUILD_MODNAME, | 1193 | .name = KBUILD_MODNAME, |
1194 | .id_table = rt2800pci_device_table, | 1194 | .id_table = rt2800pci_device_table, |
1195 | .probe = rt2800pci_probe, | 1195 | .probe = rt2800pci_probe, |
1196 | .remove = __devexit_p(rt2x00pci_remove), | 1196 | .remove = rt2x00pci_remove, |
1197 | .suspend = rt2x00pci_suspend, | 1197 | .suspend = rt2x00pci_suspend, |
1198 | .resume = rt2x00pci_resume, | 1198 | .resume = rt2x00pci_resume, |
1199 | }; | 1199 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 67d167993d45..3248b4224c4e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1124,6 +1124,9 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) | |||
1124 | struct ieee80211_iface_limit *if_limit; | 1124 | struct ieee80211_iface_limit *if_limit; |
1125 | struct ieee80211_iface_combination *if_combination; | 1125 | struct ieee80211_iface_combination *if_combination; |
1126 | 1126 | ||
1127 | if (rt2x00dev->ops->max_ap_intf < 2) | ||
1128 | return; | ||
1129 | |||
1127 | /* | 1130 | /* |
1128 | * Build up AP interface limits structure. | 1131 | * Build up AP interface limits structure. |
1129 | */ | 1132 | */ |
@@ -1183,6 +1186,13 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1183 | rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); | 1186 | rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); |
1184 | 1187 | ||
1185 | /* | 1188 | /* |
1189 | * rt2x00 devices can only use the last n bits of the MAC address | ||
1190 | * for virtual interfaces. | ||
1191 | */ | ||
1192 | rt2x00dev->hw->wiphy->addr_mask[ETH_ALEN - 1] = | ||
1193 | (rt2x00dev->ops->max_ap_intf - 1); | ||
1194 | |||
1195 | /* | ||
1186 | * Determine which operating modes are supported, all modes | 1196 | * Determine which operating modes are supported, all modes |
1187 | * which require beaconing, depend on the availability of | 1197 | * which require beaconing, depend on the availability of |
1188 | * beacon entries. | 1198 | * beacon entries. |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index d6582a2fa353..f95792cfcf89 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -3094,7 +3094,7 @@ static struct pci_driver rt61pci_driver = { | |||
3094 | .name = KBUILD_MODNAME, | 3094 | .name = KBUILD_MODNAME, |
3095 | .id_table = rt61pci_device_table, | 3095 | .id_table = rt61pci_device_table, |
3096 | .probe = rt61pci_probe, | 3096 | .probe = rt61pci_probe, |
3097 | .remove = __devexit_p(rt2x00pci_remove), | 3097 | .remove = rt2x00pci_remove, |
3098 | .suspend = rt2x00pci_suspend, | 3098 | .suspend = rt2x00pci_suspend, |
3099 | .resume = rt2x00pci_resume, | 3099 | .resume = rt2x00pci_resume, |
3100 | }; | 3100 | }; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index b4218a5f2066..1b3c2843221d 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
@@ -901,7 +901,7 @@ static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom) | |||
901 | udelay(10); | 901 | udelay(10); |
902 | } | 902 | } |
903 | 903 | ||
904 | static int __devinit rtl8180_probe(struct pci_dev *pdev, | 904 | static int rtl8180_probe(struct pci_dev *pdev, |
905 | const struct pci_device_id *id) | 905 | const struct pci_device_id *id) |
906 | { | 906 | { |
907 | struct ieee80211_hw *dev; | 907 | struct ieee80211_hw *dev; |
@@ -1131,7 +1131,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
1131 | return err; | 1131 | return err; |
1132 | } | 1132 | } |
1133 | 1133 | ||
1134 | static void __devexit rtl8180_remove(struct pci_dev *pdev) | 1134 | static void rtl8180_remove(struct pci_dev *pdev) |
1135 | { | 1135 | { |
1136 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); | 1136 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); |
1137 | struct rtl8180_priv *priv; | 1137 | struct rtl8180_priv *priv; |
@@ -1170,7 +1170,7 @@ static struct pci_driver rtl8180_driver = { | |||
1170 | .name = KBUILD_MODNAME, | 1170 | .name = KBUILD_MODNAME, |
1171 | .id_table = rtl8180_table, | 1171 | .id_table = rtl8180_table, |
1172 | .probe = rtl8180_probe, | 1172 | .probe = rtl8180_probe, |
1173 | .remove = __devexit_p(rtl8180_remove), | 1173 | .remove = rtl8180_remove, |
1174 | #ifdef CONFIG_PM | 1174 | #ifdef CONFIG_PM |
1175 | .suspend = rtl8180_suspend, | 1175 | .suspend = rtl8180_suspend, |
1176 | .resume = rtl8180_resume, | 1176 | .resume = rtl8180_resume, |
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 52e6bebcf089..4574bd213705 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c | |||
@@ -1411,7 +1411,7 @@ static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom) | |||
1411 | udelay(10); | 1411 | udelay(10); |
1412 | } | 1412 | } |
1413 | 1413 | ||
1414 | static int __devinit rtl8187_probe(struct usb_interface *intf, | 1414 | static int rtl8187_probe(struct usb_interface *intf, |
1415 | const struct usb_device_id *id) | 1415 | const struct usb_device_id *id) |
1416 | { | 1416 | { |
1417 | struct usb_device *udev = interface_to_usbdev(intf); | 1417 | struct usb_device *udev = interface_to_usbdev(intf); |
@@ -1639,7 +1639,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1639 | return err; | 1639 | return err; |
1640 | } | 1640 | } |
1641 | 1641 | ||
1642 | static void __devexit rtl8187_disconnect(struct usb_interface *intf) | 1642 | static void rtl8187_disconnect(struct usb_interface *intf) |
1643 | { | 1643 | { |
1644 | struct ieee80211_hw *dev = usb_get_intfdata(intf); | 1644 | struct ieee80211_hw *dev = usb_get_intfdata(intf); |
1645 | struct rtl8187_priv *priv; | 1645 | struct rtl8187_priv *priv; |
@@ -1664,7 +1664,7 @@ static struct usb_driver rtl8187_driver = { | |||
1664 | .name = KBUILD_MODNAME, | 1664 | .name = KBUILD_MODNAME, |
1665 | .id_table = rtl8187_table, | 1665 | .id_table = rtl8187_table, |
1666 | .probe = rtl8187_probe, | 1666 | .probe = rtl8187_probe, |
1667 | .disconnect = __devexit_p(rtl8187_disconnect), | 1667 | .disconnect = rtl8187_disconnect, |
1668 | .disable_hub_initiated_lpm = 1, | 1668 | .disable_hub_initiated_lpm = 1, |
1669 | }; | 1669 | }; |
1670 | 1670 | ||
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index f38e30a947bc..3deacafdcd5e 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -1756,7 +1756,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1756 | return true; | 1756 | return true; |
1757 | } | 1757 | } |
1758 | 1758 | ||
1759 | int __devinit rtl_pci_probe(struct pci_dev *pdev, | 1759 | int rtl_pci_probe(struct pci_dev *pdev, |
1760 | const struct pci_device_id *id) | 1760 | const struct pci_device_id *id) |
1761 | { | 1761 | { |
1762 | struct ieee80211_hw *hw = NULL; | 1762 | struct ieee80211_hw *hw = NULL; |
@@ -1982,6 +1982,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev) | |||
1982 | } | 1982 | } |
1983 | EXPORT_SYMBOL(rtl_pci_disconnect); | 1983 | EXPORT_SYMBOL(rtl_pci_disconnect); |
1984 | 1984 | ||
1985 | #ifdef CONFIG_PM_SLEEP | ||
1985 | /*************************************** | 1986 | /*************************************** |
1986 | kernel pci power state define: | 1987 | kernel pci power state define: |
1987 | PCI_D0 ((pci_power_t __force) 0) | 1988 | PCI_D0 ((pci_power_t __force) 0) |
@@ -2021,6 +2022,7 @@ int rtl_pci_resume(struct device *dev) | |||
2021 | return 0; | 2022 | return 0; |
2022 | } | 2023 | } |
2023 | EXPORT_SYMBOL(rtl_pci_resume); | 2024 | EXPORT_SYMBOL(rtl_pci_resume); |
2025 | #endif /* CONFIG_PM_SLEEP */ | ||
2024 | 2026 | ||
2025 | struct rtl_intf_ops rtl_pci_ops = { | 2027 | struct rtl_intf_ops rtl_pci_ops = { |
2026 | .read_efuse_byte = read_efuse_byte, | 2028 | .read_efuse_byte = read_efuse_byte, |
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index f71b12aa8cb4..65b08f50022e 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h | |||
@@ -236,11 +236,13 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw); | |||
236 | 236 | ||
237 | extern struct rtl_intf_ops rtl_pci_ops; | 237 | extern struct rtl_intf_ops rtl_pci_ops; |
238 | 238 | ||
239 | int __devinit rtl_pci_probe(struct pci_dev *pdev, | 239 | int rtl_pci_probe(struct pci_dev *pdev, |
240 | const struct pci_device_id *id); | 240 | const struct pci_device_id *id); |
241 | void rtl_pci_disconnect(struct pci_dev *pdev); | 241 | void rtl_pci_disconnect(struct pci_dev *pdev); |
242 | #ifdef CONFIG_PM_SLEEP | ||
242 | int rtl_pci_suspend(struct device *dev); | 243 | int rtl_pci_suspend(struct device *dev); |
243 | int rtl_pci_resume(struct device *dev); | 244 | int rtl_pci_resume(struct device *dev); |
245 | #endif /* CONFIG_PM_SLEEP */ | ||
244 | static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) | 246 | static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) |
245 | { | 247 | { |
246 | return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); | 248 | return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 60451eea4d82..49f663bd93ff 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
@@ -372,14 +372,7 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); | |||
372 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); | 372 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
373 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | 373 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); |
374 | 374 | ||
375 | static const struct dev_pm_ops rtlwifi_pm_ops = { | 375 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); |
376 | .suspend = rtl_pci_suspend, | ||
377 | .resume = rtl_pci_resume, | ||
378 | .freeze = rtl_pci_suspend, | ||
379 | .thaw = rtl_pci_resume, | ||
380 | .poweroff = rtl_pci_suspend, | ||
381 | .restore = rtl_pci_resume, | ||
382 | }; | ||
383 | 376 | ||
384 | static struct pci_driver rtl92ce_driver = { | 377 | static struct pci_driver rtl92ce_driver = { |
385 | .name = KBUILD_MODNAME, | 378 | .name = KBUILD_MODNAME, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 480862c07f92..03c6d18b2e07 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
@@ -352,7 +352,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = { | |||
352 | .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, | 352 | .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, |
353 | }; | 353 | }; |
354 | 354 | ||
355 | static struct pci_device_id rtl92de_pci_ids[] __devinitdata = { | 355 | static struct pci_device_id rtl92de_pci_ids[] = { |
356 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)}, | 356 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)}, |
357 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)}, | 357 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)}, |
358 | {}, | 358 | {}, |
@@ -378,14 +378,7 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); | |||
378 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); | 378 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
379 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | 379 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); |
380 | 380 | ||
381 | static const struct dev_pm_ops rtlwifi_pm_ops = { | 381 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); |
382 | .suspend = rtl_pci_suspend, | ||
383 | .resume = rtl_pci_resume, | ||
384 | .freeze = rtl_pci_suspend, | ||
385 | .thaw = rtl_pci_resume, | ||
386 | .poweroff = rtl_pci_suspend, | ||
387 | .restore = rtl_pci_resume, | ||
388 | }; | ||
389 | 382 | ||
390 | static struct pci_driver rtl92de_driver = { | 383 | static struct pci_driver rtl92de_driver = { |
391 | .name = KBUILD_MODNAME, | 384 | .name = KBUILD_MODNAME, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 20afec62ce05..2d255e02d795 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h | |||
@@ -522,8 +522,7 @@ enum fwcmd_iotype { | |||
522 | FW_CMD_IQK_ENABLE = 30, | 522 | FW_CMD_IQK_ENABLE = 30, |
523 | }; | 523 | }; |
524 | 524 | ||
525 | /* | 525 | /* Driver info contain PHY status |
526 | * Driver info contain PHY status | ||
527 | * and other variabel size info | 526 | * and other variabel size info |
528 | * PHY Status content as below | 527 | * PHY Status content as below |
529 | */ | 528 | */ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c index bf79a52c8a52..e551fe5f9ccd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c | |||
@@ -465,8 +465,8 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) | |||
465 | digtable->cur_igvalue = | 465 | digtable->cur_igvalue = |
466 | digtable->rx_gain_range_min; | 466 | digtable->rx_gain_range_min; |
467 | else | 467 | else |
468 | digtable->cur_igvalue = digtable->rssi_val + 10 - | 468 | digtable->cur_igvalue = digtable->rssi_val + 10 |
469 | digtable->back_val; | 469 | - digtable->back_val; |
470 | 470 | ||
471 | if (falsealm_cnt->cnt_all > 10000) | 471 | if (falsealm_cnt->cnt_all > 10000) |
472 | digtable->cur_igvalue = | 472 | digtable->cur_igvalue = |
@@ -518,7 +518,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) | |||
518 | static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) | 518 | static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) |
519 | { | 519 | { |
520 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 520 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
521 | struct dig_t *digtable = &rtlpriv->dm_digtable; | 521 | struct dig_t *dig = &rtlpriv->dm_digtable; |
522 | 522 | ||
523 | if (rtlpriv->mac80211.act_scanning) | 523 | if (rtlpriv->mac80211.act_scanning) |
524 | return; | 524 | return; |
@@ -526,17 +526,17 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) | |||
526 | /* Decide the current status and if modify initial gain or not */ | 526 | /* Decide the current status and if modify initial gain or not */ |
527 | if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || | 527 | if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || |
528 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) | 528 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) |
529 | digtable->cur_sta_cstate = DIG_STA_CONNECT; | 529 | dig->cur_sta_cstate = DIG_STA_CONNECT; |
530 | else | 530 | else |
531 | digtable->cur_sta_cstate = DIG_STA_DISCONNECT; | 531 | dig->cur_sta_cstate = DIG_STA_DISCONNECT; |
532 | 532 | ||
533 | digtable->rssi_val = rtlpriv->dm.undec_sm_pwdb; | 533 | dig->rssi_val = rtlpriv->dm.undec_sm_pwdb; |
534 | 534 | ||
535 | /* Change dig mode to rssi */ | 535 | /* Change dig mode to rssi */ |
536 | if (digtable->cur_sta_cstate != DIG_STA_DISCONNECT) { | 536 | if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) { |
537 | if (digtable->dig_twoport_algorithm == | 537 | if (dig->dig_twoport_algorithm == |
538 | DIG_TWO_PORT_ALGO_FALSE_ALARM) { | 538 | DIG_TWO_PORT_ALGO_FALSE_ALARM) { |
539 | digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; | 539 | dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; |
540 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); | 540 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); |
541 | } | 541 | } |
542 | } | 542 | } |
@@ -544,7 +544,7 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) | |||
544 | _rtl92s_dm_false_alarm_counter_statistics(hw); | 544 | _rtl92s_dm_false_alarm_counter_statistics(hw); |
545 | _rtl92s_dm_initial_gain_sta_beforeconnect(hw); | 545 | _rtl92s_dm_initial_gain_sta_beforeconnect(hw); |
546 | 546 | ||
547 | digtable->pre_sta_cstate = digtable->cur_sta_cstate; | 547 | dig->pre_sta_cstate = dig->cur_sta_cstate; |
548 | } | 548 | } |
549 | 549 | ||
550 | static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) | 550 | static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 1d72779434ba..28526a7361f5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c | |||
@@ -1089,8 +1089,9 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) | |||
1089 | return err; | 1089 | return err; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr) | 1092 | void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr) |
1093 | { | 1093 | { |
1094 | /* This is a stub. */ | ||
1094 | } | 1095 | } |
1095 | 1096 | ||
1096 | void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | 1097 | void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h index 1886c2644a26..a8e068c76e47 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h | |||
@@ -54,7 +54,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw); | |||
54 | int rtl92se_set_network_type(struct ieee80211_hw *hw, | 54 | int rtl92se_set_network_type(struct ieee80211_hw *hw, |
55 | enum nl80211_iftype type); | 55 | enum nl80211_iftype type); |
56 | void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); | 56 | void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); |
57 | void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr); | 57 | void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr); |
58 | void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); | 58 | void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); |
59 | void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); | 59 | void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); |
60 | void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); | 60 | void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index ad4b4803482d..cecc377e9e61 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -50,8 +50,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) | |||
50 | /*close ASPM for AMD defaultly */ | 50 | /*close ASPM for AMD defaultly */ |
51 | rtlpci->const_amdpci_aspm = 0; | 51 | rtlpci->const_amdpci_aspm = 0; |
52 | 52 | ||
53 | /* | 53 | /* ASPM PS mode. |
54 | * ASPM PS mode. | ||
55 | * 0 - Disable ASPM, | 54 | * 0 - Disable ASPM, |
56 | * 1 - Enable ASPM without Clock Req, | 55 | * 1 - Enable ASPM without Clock Req, |
57 | * 2 - Enable ASPM with Clock Req, | 56 | * 2 - Enable ASPM with Clock Req, |
@@ -67,8 +66,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) | |||
67 | /*Setting for PCI-E bridge */ | 66 | /*Setting for PCI-E bridge */ |
68 | rtlpci->const_hostpci_aspm_setting = 0x02; | 67 | rtlpci->const_hostpci_aspm_setting = 0x02; |
69 | 68 | ||
70 | /* | 69 | /* In Hw/Sw Radio Off situation. |
71 | * In Hw/Sw Radio Off situation. | ||
72 | * 0 - Default, | 70 | * 0 - Default, |
73 | * 1 - From ASPM setting without low Mac Pwr, | 71 | * 1 - From ASPM setting without low Mac Pwr, |
74 | * 2 - From ASPM setting with low Mac Pwr, | 72 | * 2 - From ASPM setting with low Mac Pwr, |
@@ -77,8 +75,7 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) | |||
77 | */ | 75 | */ |
78 | rtlpci->const_hwsw_rfoff_d3 = 2; | 76 | rtlpci->const_hwsw_rfoff_d3 = 2; |
79 | 77 | ||
80 | /* | 78 | /* This setting works for those device with |
81 | * This setting works for those device with | ||
82 | * backdoor ASPM setting such as EPHY setting. | 79 | * backdoor ASPM setting such as EPHY setting. |
83 | * 0 - Not support ASPM, | 80 | * 0 - Not support ASPM, |
84 | * 1 - Support ASPM, | 81 | * 1 - Support ASPM, |
@@ -403,7 +400,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = { | |||
403 | .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, | 400 | .maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15, |
404 | }; | 401 | }; |
405 | 402 | ||
406 | static struct pci_device_id rtl92se_pci_ids[] __devinitdata = { | 403 | static struct pci_device_id rtl92se_pci_ids[] = { |
407 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)}, | 404 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)}, |
408 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)}, | 405 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)}, |
409 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)}, | 406 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)}, |
@@ -432,14 +429,7 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); | |||
432 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); | 429 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
433 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | 430 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); |
434 | 431 | ||
435 | static const struct dev_pm_ops rtlwifi_pm_ops = { | 432 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); |
436 | .suspend = rtl_pci_suspend, | ||
437 | .resume = rtl_pci_resume, | ||
438 | .freeze = rtl_pci_suspend, | ||
439 | .thaw = rtl_pci_resume, | ||
440 | .poweroff = rtl_pci_suspend, | ||
441 | .restore = rtl_pci_resume, | ||
442 | }; | ||
443 | 433 | ||
444 | static struct pci_driver rtl92se_driver = { | 434 | static struct pci_driver rtl92se_driver = { |
445 | .name = KBUILD_MODNAME, | 435 | .name = KBUILD_MODNAME, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c index 0afdc240f2fd..18b0bc51766b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c | |||
@@ -367,14 +367,7 @@ MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); | |||
367 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); | 367 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
368 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | 368 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); |
369 | 369 | ||
370 | static const struct dev_pm_ops rtlwifi_pm_ops = { | 370 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); |
371 | .suspend = rtl_pci_suspend, | ||
372 | .resume = rtl_pci_resume, | ||
373 | .freeze = rtl_pci_suspend, | ||
374 | .thaw = rtl_pci_resume, | ||
375 | .poweroff = rtl_pci_suspend, | ||
376 | .restore = rtl_pci_resume, | ||
377 | }; | ||
378 | 371 | ||
379 | static struct pci_driver rtl8723ae_driver = { | 372 | static struct pci_driver rtl8723ae_driver = { |
380 | .name = KBUILD_MODNAME, | 373 | .name = KBUILD_MODNAME, |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index e3ea4b346889..29f0969e4ba0 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -940,7 +940,7 @@ static struct rtl_intf_ops rtl_usb_ops = { | |||
940 | .waitq_insert = rtl_usb_tx_chk_waitq_insert, | 940 | .waitq_insert = rtl_usb_tx_chk_waitq_insert, |
941 | }; | 941 | }; |
942 | 942 | ||
943 | int __devinit rtl_usb_probe(struct usb_interface *intf, | 943 | int rtl_usb_probe(struct usb_interface *intf, |
944 | const struct usb_device_id *id) | 944 | const struct usb_device_id *id) |
945 | { | 945 | { |
946 | int err; | 946 | int err; |
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h index 43846b329153..5235136f6dd2 100644 --- a/drivers/net/wireless/rtlwifi/usb.h +++ b/drivers/net/wireless/rtlwifi/usb.h | |||
@@ -156,7 +156,7 @@ struct rtl_usb_priv { | |||
156 | 156 | ||
157 | 157 | ||
158 | 158 | ||
159 | int __devinit rtl_usb_probe(struct usb_interface *intf, | 159 | int rtl_usb_probe(struct usb_interface *intf, |
160 | const struct usb_device_id *id); | 160 | const struct usb_device_id *id); |
161 | void rtl_usb_disconnect(struct usb_interface *intf); | 161 | void rtl_usb_disconnect(struct usb_interface *intf); |
162 | int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message); | 162 | int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message); |
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 441cbccbd381..f47e8b0482ad 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -896,11 +896,13 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | |||
896 | goto out; | 896 | goto out; |
897 | 897 | ||
898 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, | 898 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
899 | req->ie, req->ie_len); | 899 | req->ie_len); |
900 | if (!skb) { | 900 | if (!skb) { |
901 | ret = -ENOMEM; | 901 | ret = -ENOMEM; |
902 | goto out; | 902 | goto out; |
903 | } | 903 | } |
904 | if (req->ie_len) | ||
905 | memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len); | ||
904 | 906 | ||
905 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data, | 907 | ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data, |
906 | skb->len); | 908 | skb->len); |
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index e2750a12c6f1..e57ee48edff6 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c | |||
@@ -305,7 +305,7 @@ out_free_hw: | |||
305 | return ret; | 305 | return ret; |
306 | } | 306 | } |
307 | 307 | ||
308 | static void __devexit wl1251_sdio_remove(struct sdio_func *func) | 308 | static void wl1251_sdio_remove(struct sdio_func *func) |
309 | { | 309 | { |
310 | struct wl1251 *wl = sdio_get_drvdata(func); | 310 | struct wl1251 *wl = sdio_get_drvdata(func); |
311 | struct wl1251_sdio *wl_sdio = wl->if_priv; | 311 | struct wl1251_sdio *wl_sdio = wl->if_priv; |
@@ -347,7 +347,7 @@ static struct sdio_driver wl1251_sdio_driver = { | |||
347 | .name = "wl1251_sdio", | 347 | .name = "wl1251_sdio", |
348 | .id_table = wl1251_devices, | 348 | .id_table = wl1251_devices, |
349 | .probe = wl1251_sdio_probe, | 349 | .probe = wl1251_sdio_probe, |
350 | .remove = __devexit_p(wl1251_sdio_remove), | 350 | .remove = wl1251_sdio_remove, |
351 | .drv.pm = &wl1251_sdio_pm_ops, | 351 | .drv.pm = &wl1251_sdio_pm_ops, |
352 | }; | 352 | }; |
353 | 353 | ||
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index 567660cd2fcd..3b266d3231a3 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c | |||
@@ -237,7 +237,7 @@ static const struct wl1251_if_operations wl1251_spi_ops = { | |||
237 | .power = wl1251_spi_set_power, | 237 | .power = wl1251_spi_set_power, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static int __devinit wl1251_spi_probe(struct spi_device *spi) | 240 | static int wl1251_spi_probe(struct spi_device *spi) |
241 | { | 241 | { |
242 | struct wl12xx_platform_data *pdata; | 242 | struct wl12xx_platform_data *pdata; |
243 | struct ieee80211_hw *hw; | 243 | struct ieee80211_hw *hw; |
@@ -309,7 +309,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) | |||
309 | return ret; | 309 | return ret; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int __devexit wl1251_spi_remove(struct spi_device *spi) | 312 | static int wl1251_spi_remove(struct spi_device *spi) |
313 | { | 313 | { |
314 | struct wl1251 *wl = dev_get_drvdata(&spi->dev); | 314 | struct wl1251 *wl = dev_get_drvdata(&spi->dev); |
315 | 315 | ||
@@ -326,7 +326,7 @@ static struct spi_driver wl1251_spi_driver = { | |||
326 | }, | 326 | }, |
327 | 327 | ||
328 | .probe = wl1251_spi_probe, | 328 | .probe = wl1251_spi_probe, |
329 | .remove = __devexit_p(wl1251_spi_remove), | 329 | .remove = wl1251_spi_remove, |
330 | }; | 330 | }; |
331 | 331 | ||
332 | static int __init wl1251_spi_init(void) | 332 | static int __init wl1251_spi_init(void) |
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index dadf1dbb002a..e5f5f8f39144 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -1696,7 +1696,7 @@ static int wl12xx_setup(struct wl1271 *wl) | |||
1696 | return 0; | 1696 | return 0; |
1697 | } | 1697 | } |
1698 | 1698 | ||
1699 | static int __devinit wl12xx_probe(struct platform_device *pdev) | 1699 | static int wl12xx_probe(struct platform_device *pdev) |
1700 | { | 1700 | { |
1701 | struct wl1271 *wl; | 1701 | struct wl1271 *wl; |
1702 | struct ieee80211_hw *hw; | 1702 | struct ieee80211_hw *hw; |
@@ -1725,7 +1725,7 @@ out: | |||
1725 | return ret; | 1725 | return ret; |
1726 | } | 1726 | } |
1727 | 1727 | ||
1728 | static const struct platform_device_id wl12xx_id_table[] __devinitconst = { | 1728 | static const struct platform_device_id wl12xx_id_table[] = { |
1729 | { "wl12xx", 0 }, | 1729 | { "wl12xx", 0 }, |
1730 | { } /* Terminating Entry */ | 1730 | { } /* Terminating Entry */ |
1731 | }; | 1731 | }; |
@@ -1733,7 +1733,7 @@ MODULE_DEVICE_TABLE(platform, wl12xx_id_table); | |||
1733 | 1733 | ||
1734 | static struct platform_driver wl12xx_driver = { | 1734 | static struct platform_driver wl12xx_driver = { |
1735 | .probe = wl12xx_probe, | 1735 | .probe = wl12xx_probe, |
1736 | .remove = __devexit_p(wlcore_remove), | 1736 | .remove = wlcore_remove, |
1737 | .id_table = wl12xx_id_table, | 1737 | .id_table = wl12xx_id_table, |
1738 | .driver = { | 1738 | .driver = { |
1739 | .name = "wl12xx_driver", | 1739 | .name = "wl12xx_driver", |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index a39682a7c25f..8d8c1f8c63b7 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -1499,7 +1499,7 @@ static int wl18xx_setup(struct wl1271 *wl) | |||
1499 | return 0; | 1499 | return 0; |
1500 | } | 1500 | } |
1501 | 1501 | ||
1502 | static int __devinit wl18xx_probe(struct platform_device *pdev) | 1502 | static int wl18xx_probe(struct platform_device *pdev) |
1503 | { | 1503 | { |
1504 | struct wl1271 *wl; | 1504 | struct wl1271 *wl; |
1505 | struct ieee80211_hw *hw; | 1505 | struct ieee80211_hw *hw; |
@@ -1528,7 +1528,7 @@ out: | |||
1528 | return ret; | 1528 | return ret; |
1529 | } | 1529 | } |
1530 | 1530 | ||
1531 | static const struct platform_device_id wl18xx_id_table[] __devinitconst = { | 1531 | static const struct platform_device_id wl18xx_id_table[] = { |
1532 | { "wl18xx", 0 }, | 1532 | { "wl18xx", 0 }, |
1533 | { } /* Terminating Entry */ | 1533 | { } /* Terminating Entry */ |
1534 | }; | 1534 | }; |
@@ -1536,7 +1536,7 @@ MODULE_DEVICE_TABLE(platform, wl18xx_id_table); | |||
1536 | 1536 | ||
1537 | static struct platform_driver wl18xx_driver = { | 1537 | static struct platform_driver wl18xx_driver = { |
1538 | .probe = wl18xx_probe, | 1538 | .probe = wl18xx_probe, |
1539 | .remove = __devexit_p(wlcore_remove), | 1539 | .remove = wlcore_remove, |
1540 | .id_table = wl18xx_id_table, | 1540 | .id_table = wl18xx_id_table, |
1541 | .driver = { | 1541 | .driver = { |
1542 | .name = "wl18xx_driver", | 1542 | .name = "wl18xx_driver", |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index eaef3f41b252..27f83f72a93b 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -1038,11 +1038,13 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1038 | u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | 1038 | u16 template_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; |
1039 | 1039 | ||
1040 | skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, | 1040 | skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, |
1041 | ie, ie_len); | 1041 | ie_len); |
1042 | if (!skb) { | 1042 | if (!skb) { |
1043 | ret = -ENOMEM; | 1043 | ret = -ENOMEM; |
1044 | goto out; | 1044 | goto out; |
1045 | } | 1045 | } |
1046 | if (ie_len) | ||
1047 | memcpy(skb_put(skb, ie_len), ie, ie_len); | ||
1046 | 1048 | ||
1047 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); | 1049 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); |
1048 | 1050 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 4f1a05b92d2d..ea9d8e011bc9 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -5660,7 +5660,7 @@ out: | |||
5660 | complete_all(&wl->nvs_loading_complete); | 5660 | complete_all(&wl->nvs_loading_complete); |
5661 | } | 5661 | } |
5662 | 5662 | ||
5663 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | 5663 | int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) |
5664 | { | 5664 | { |
5665 | int ret; | 5665 | int ret; |
5666 | 5666 | ||
@@ -5683,7 +5683,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5683 | } | 5683 | } |
5684 | EXPORT_SYMBOL_GPL(wlcore_probe); | 5684 | EXPORT_SYMBOL_GPL(wlcore_probe); |
5685 | 5685 | ||
5686 | int __devexit wlcore_remove(struct platform_device *pdev) | 5686 | int wlcore_remove(struct platform_device *pdev) |
5687 | { | 5687 | { |
5688 | struct wl1271 *wl = platform_get_drvdata(pdev); | 5688 | struct wl1271 *wl = platform_get_drvdata(pdev); |
5689 | 5689 | ||
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 73ace4b2604e..646f703ae739 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c | |||
@@ -54,7 +54,7 @@ struct wl12xx_sdio_glue { | |||
54 | struct platform_device *core; | 54 | struct platform_device *core; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static const struct sdio_device_id wl1271_devices[] __devinitconst = { | 57 | static const struct sdio_device_id wl1271_devices[] = { |
58 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, | 58 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, |
59 | {} | 59 | {} |
60 | }; | 60 | }; |
@@ -214,7 +214,7 @@ static struct wl1271_if_operations sdio_ops = { | |||
214 | .set_block_size = wl1271_sdio_set_block_size, | 214 | .set_block_size = wl1271_sdio_set_block_size, |
215 | }; | 215 | }; |
216 | 216 | ||
217 | static int __devinit wl1271_probe(struct sdio_func *func, | 217 | static int wl1271_probe(struct sdio_func *func, |
218 | const struct sdio_device_id *id) | 218 | const struct sdio_device_id *id) |
219 | { | 219 | { |
220 | struct wl12xx_platform_data *wlan_data; | 220 | struct wl12xx_platform_data *wlan_data; |
@@ -319,7 +319,7 @@ out: | |||
319 | return ret; | 319 | return ret; |
320 | } | 320 | } |
321 | 321 | ||
322 | static void __devexit wl1271_remove(struct sdio_func *func) | 322 | static void wl1271_remove(struct sdio_func *func) |
323 | { | 323 | { |
324 | struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); | 324 | struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); |
325 | 325 | ||
@@ -384,7 +384,7 @@ static struct sdio_driver wl1271_sdio_driver = { | |||
384 | .name = "wl1271_sdio", | 384 | .name = "wl1271_sdio", |
385 | .id_table = wl1271_devices, | 385 | .id_table = wl1271_devices, |
386 | .probe = wl1271_probe, | 386 | .probe = wl1271_probe, |
387 | .remove = __devexit_p(wl1271_remove), | 387 | .remove = wl1271_remove, |
388 | #ifdef CONFIG_PM | 388 | #ifdef CONFIG_PM |
389 | .drv = { | 389 | .drv = { |
390 | .pm = &wl1271_sdio_pm_ops, | 390 | .pm = &wl1271_sdio_pm_ops, |
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index a519bc3adec1..f06f4770ce02 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
@@ -324,7 +324,7 @@ static struct wl1271_if_operations spi_ops = { | |||
324 | .set_block_size = NULL, | 324 | .set_block_size = NULL, |
325 | }; | 325 | }; |
326 | 326 | ||
327 | static int __devinit wl1271_probe(struct spi_device *spi) | 327 | static int wl1271_probe(struct spi_device *spi) |
328 | { | 328 | { |
329 | struct wl12xx_spi_glue *glue; | 329 | struct wl12xx_spi_glue *glue; |
330 | struct wl12xx_platform_data *pdata; | 330 | struct wl12xx_platform_data *pdata; |
@@ -403,7 +403,7 @@ out: | |||
403 | return ret; | 403 | return ret; |
404 | } | 404 | } |
405 | 405 | ||
406 | static int __devexit wl1271_remove(struct spi_device *spi) | 406 | static int wl1271_remove(struct spi_device *spi) |
407 | { | 407 | { |
408 | struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); | 408 | struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); |
409 | 409 | ||
@@ -422,7 +422,7 @@ static struct spi_driver wl1271_spi_driver = { | |||
422 | }, | 422 | }, |
423 | 423 | ||
424 | .probe = wl1271_probe, | 424 | .probe = wl1271_probe, |
425 | .remove = __devexit_p(wl1271_remove), | 425 | .remove = wl1271_remove, |
426 | }; | 426 | }; |
427 | 427 | ||
428 | static int __init wl1271_init(void) | 428 | static int __init wl1271_init(void) |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 68584aa0f2b0..c3884937c007 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -414,8 +414,8 @@ struct wl1271 { | |||
414 | struct completion nvs_loading_complete; | 414 | struct completion nvs_loading_complete; |
415 | }; | 415 | }; |
416 | 416 | ||
417 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | 417 | int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); |
418 | int __devexit wlcore_remove(struct platform_device *pdev); | 418 | int wlcore_remove(struct platform_device *pdev); |
419 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size); | 419 | struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size); |
420 | int wlcore_free_hw(struct wl1271 *wl); | 420 | int wlcore_free_hw(struct wl1271 *wl); |
421 | int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | 421 | int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index e9d2ca11283b..95c33a05f434 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright 2005, Broadcom Corporation | 5 | * Copyright 2005, Broadcom Corporation |
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | 6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> |
7 | * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
7 | * | 8 | * |
8 | * Licensed under the GNU/GPL. See COPYING for details. | 9 | * Licensed under the GNU/GPL. See COPYING for details. |
9 | */ | 10 | */ |
@@ -12,6 +13,7 @@ | |||
12 | #include <linux/ssb/ssb_regs.h> | 13 | #include <linux/ssb/ssb_regs.h> |
13 | #include <linux/export.h> | 14 | #include <linux/export.h> |
14 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
16 | #include <linux/bcm47xx_wdt.h> | ||
15 | 17 | ||
16 | #include "ssb_private.h" | 18 | #include "ssb_private.h" |
17 | 19 | ||
@@ -280,6 +282,69 @@ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) | |||
280 | cc->fast_pwrup_delay = tmp; | 282 | cc->fast_pwrup_delay = tmp; |
281 | } | 283 | } |
282 | 284 | ||
285 | static u32 ssb_chipco_alp_clock(struct ssb_chipcommon *cc) | ||
286 | { | ||
287 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) | ||
288 | return ssb_pmu_get_alp_clock(cc); | ||
289 | |||
290 | return 20000000; | ||
291 | } | ||
292 | |||
293 | static u32 ssb_chipco_watchdog_get_max_timer(struct ssb_chipcommon *cc) | ||
294 | { | ||
295 | u32 nb; | ||
296 | |||
297 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { | ||
298 | if (cc->dev->id.revision < 26) | ||
299 | nb = 16; | ||
300 | else | ||
301 | nb = (cc->dev->id.revision >= 37) ? 32 : 24; | ||
302 | } else { | ||
303 | nb = 28; | ||
304 | } | ||
305 | if (nb == 32) | ||
306 | return 0xffffffff; | ||
307 | else | ||
308 | return (1 << nb) - 1; | ||
309 | } | ||
310 | |||
311 | u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks) | ||
312 | { | ||
313 | struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt); | ||
314 | |||
315 | if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB) | ||
316 | return 0; | ||
317 | |||
318 | return ssb_chipco_watchdog_timer_set(cc, ticks); | ||
319 | } | ||
320 | |||
321 | u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms) | ||
322 | { | ||
323 | struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt); | ||
324 | u32 ticks; | ||
325 | |||
326 | if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB) | ||
327 | return 0; | ||
328 | |||
329 | ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms); | ||
330 | return ticks / cc->ticks_per_ms; | ||
331 | } | ||
332 | |||
333 | static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc) | ||
334 | { | ||
335 | struct ssb_bus *bus = cc->dev->bus; | ||
336 | |||
337 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { | ||
338 | /* based on 32KHz ILP clock */ | ||
339 | return 32; | ||
340 | } else { | ||
341 | if (cc->dev->id.revision < 18) | ||
342 | return ssb_clockspeed(bus) / 1000; | ||
343 | else | ||
344 | return ssb_chipco_alp_clock(cc) / 1000; | ||
345 | } | ||
346 | } | ||
347 | |||
283 | void ssb_chipcommon_init(struct ssb_chipcommon *cc) | 348 | void ssb_chipcommon_init(struct ssb_chipcommon *cc) |
284 | { | 349 | { |
285 | if (!cc->dev) | 350 | if (!cc->dev) |
@@ -297,6 +362,11 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) | |||
297 | chipco_powercontrol_init(cc); | 362 | chipco_powercontrol_init(cc); |
298 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); | 363 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); |
299 | calc_fast_powerup_delay(cc); | 364 | calc_fast_powerup_delay(cc); |
365 | |||
366 | if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) { | ||
367 | cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc); | ||
368 | cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; | ||
369 | } | ||
300 | } | 370 | } |
301 | 371 | ||
302 | void ssb_chipco_suspend(struct ssb_chipcommon *cc) | 372 | void ssb_chipco_suspend(struct ssb_chipcommon *cc) |
@@ -395,10 +465,27 @@ void ssb_chipco_timing_init(struct ssb_chipcommon *cc, | |||
395 | } | 465 | } |
396 | 466 | ||
397 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ | 467 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ |
398 | void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks) | 468 | u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks) |
399 | { | 469 | { |
400 | /* instant NMI */ | 470 | u32 maxt; |
401 | chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); | 471 | enum ssb_clkmode clkmode; |
472 | |||
473 | maxt = ssb_chipco_watchdog_get_max_timer(cc); | ||
474 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { | ||
475 | if (ticks == 1) | ||
476 | ticks = 2; | ||
477 | else if (ticks > maxt) | ||
478 | ticks = maxt; | ||
479 | chipco_write32(cc, SSB_CHIPCO_PMU_WATCHDOG, ticks); | ||
480 | } else { | ||
481 | clkmode = ticks ? SSB_CLKMODE_FAST : SSB_CLKMODE_DYNAMIC; | ||
482 | ssb_chipco_set_clockmode(cc, clkmode); | ||
483 | if (ticks > maxt) | ||
484 | ticks = maxt; | ||
485 | /* instant NMI */ | ||
486 | chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); | ||
487 | } | ||
488 | return ticks; | ||
402 | } | 489 | } |
403 | 490 | ||
404 | void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value) | 491 | void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value) |
@@ -473,12 +560,7 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc, | |||
473 | chipco_read32(cc, SSB_CHIPCO_CORECTL) | 560 | chipco_read32(cc, SSB_CHIPCO_CORECTL) |
474 | | SSB_CHIPCO_CORECTL_UARTCLK0); | 561 | | SSB_CHIPCO_CORECTL_UARTCLK0); |
475 | } else if ((ccrev >= 11) && (ccrev != 15)) { | 562 | } else if ((ccrev >= 11) && (ccrev != 15)) { |
476 | /* Fixed ALP clock */ | 563 | baud_base = ssb_chipco_alp_clock(cc); |
477 | baud_base = 20000000; | ||
478 | if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { | ||
479 | /* FIXME: baud_base is different for devices with a PMU */ | ||
480 | SSB_WARN_ON(1); | ||
481 | } | ||
482 | div = 1; | 564 | div = 1; |
483 | if (ccrev >= 21) { | 565 | if (ccrev >= 21) { |
484 | /* Turn off UART clock before switching clocksource. */ | 566 | /* Turn off UART clock before switching clocksource. */ |
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index d7d58044b4bc..a43415a7fbed 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -618,6 +618,33 @@ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on) | |||
618 | EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); | 618 | EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); |
619 | EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); | 619 | EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); |
620 | 620 | ||
621 | static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc) | ||
622 | { | ||
623 | u32 crystalfreq; | ||
624 | const struct pmu0_plltab_entry *e = NULL; | ||
625 | |||
626 | crystalfreq = chipco_read32(cc, SSB_CHIPCO_PMU_CTL) & | ||
627 | SSB_CHIPCO_PMU_CTL_XTALFREQ >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT; | ||
628 | e = pmu0_plltab_find_entry(crystalfreq); | ||
629 | BUG_ON(!e); | ||
630 | return e->freq * 1000; | ||
631 | } | ||
632 | |||
633 | u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc) | ||
634 | { | ||
635 | struct ssb_bus *bus = cc->dev->bus; | ||
636 | |||
637 | switch (bus->chip_id) { | ||
638 | case 0x5354: | ||
639 | ssb_pmu_get_alp_clock_clk0(cc); | ||
640 | default: | ||
641 | ssb_printk(KERN_ERR PFX | ||
642 | "ERROR: PMU alp clock unknown for device %04X\n", | ||
643 | bus->chip_id); | ||
644 | return 0; | ||
645 | } | ||
646 | } | ||
647 | |||
621 | u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) | 648 | u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) |
622 | { | 649 | { |
623 | struct ssb_bus *bus = cc->dev->bus; | 650 | struct ssb_bus *bus = cc->dev->bus; |
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c index dc47f30e9cf7..553227a3062d 100644 --- a/drivers/ssb/driver_extif.c +++ b/drivers/ssb/driver_extif.c | |||
@@ -112,10 +112,30 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif, | |||
112 | *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); | 112 | *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); |
113 | } | 113 | } |
114 | 114 | ||
115 | void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, | 115 | u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks) |
116 | u32 ticks) | ||
117 | { | 116 | { |
117 | struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt); | ||
118 | |||
119 | return ssb_extif_watchdog_timer_set(extif, ticks); | ||
120 | } | ||
121 | |||
122 | u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms) | ||
123 | { | ||
124 | struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt); | ||
125 | u32 ticks = (SSB_EXTIF_WATCHDOG_CLK / 1000) * ms; | ||
126 | |||
127 | ticks = ssb_extif_watchdog_timer_set(extif, ticks); | ||
128 | |||
129 | return (ticks * 1000) / SSB_EXTIF_WATCHDOG_CLK; | ||
130 | } | ||
131 | |||
132 | u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks) | ||
133 | { | ||
134 | if (ticks > SSB_EXTIF_WATCHDOG_MAX_TIMER) | ||
135 | ticks = SSB_EXTIF_WATCHDOG_MAX_TIMER; | ||
118 | extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks); | 136 | extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks); |
137 | |||
138 | return ticks; | ||
119 | } | 139 | } |
120 | 140 | ||
121 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) | 141 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index b918ba922306..5bd05b136d22 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct ssb_mipscore *mcore) | |||
178 | { | 178 | { |
179 | struct ssb_bus *bus = mcore->dev->bus; | 179 | struct ssb_bus *bus = mcore->dev->bus; |
180 | 180 | ||
181 | if (bus->extif.dev) | 181 | if (ssb_extif_available(&bus->extif)) |
182 | mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); | 182 | mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); |
183 | else if (bus->chipco.dev) | 183 | else if (ssb_chipco_available(&bus->chipco)) |
184 | mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); | 184 | mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); |
185 | else | 185 | else |
186 | mcore->nr_serial_ports = 0; | 186 | mcore->nr_serial_ports = 0; |
@@ -191,7 +191,7 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) | |||
191 | struct ssb_bus *bus = mcore->dev->bus; | 191 | struct ssb_bus *bus = mcore->dev->bus; |
192 | 192 | ||
193 | /* When there is no chipcommon on the bus there is 4MB flash */ | 193 | /* When there is no chipcommon on the bus there is 4MB flash */ |
194 | if (!bus->chipco.dev) { | 194 | if (!ssb_chipco_available(&bus->chipco)) { |
195 | mcore->pflash.present = true; | 195 | mcore->pflash.present = true; |
196 | mcore->pflash.buswidth = 2; | 196 | mcore->pflash.buswidth = 2; |
197 | mcore->pflash.window = SSB_FLASH1; | 197 | mcore->pflash.window = SSB_FLASH1; |
@@ -227,9 +227,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore) | |||
227 | if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) | 227 | if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) |
228 | return ssb_pmu_get_cpu_clock(&bus->chipco); | 228 | return ssb_pmu_get_cpu_clock(&bus->chipco); |
229 | 229 | ||
230 | if (bus->extif.dev) { | 230 | if (ssb_extif_available(&bus->extif)) { |
231 | ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); | 231 | ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); |
232 | } else if (bus->chipco.dev) { | 232 | } else if (ssb_chipco_available(&bus->chipco)) { |
233 | ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); | 233 | ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); |
234 | } else | 234 | } else |
235 | return 0; | 235 | return 0; |
@@ -265,9 +265,9 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
265 | hz = 100000000; | 265 | hz = 100000000; |
266 | ns = 1000000000 / hz; | 266 | ns = 1000000000 / hz; |
267 | 267 | ||
268 | if (bus->extif.dev) | 268 | if (ssb_extif_available(&bus->extif)) |
269 | ssb_extif_timing_init(&bus->extif, ns); | 269 | ssb_extif_timing_init(&bus->extif, ns); |
270 | else if (bus->chipco.dev) | 270 | else if (ssb_chipco_available(&bus->chipco)) |
271 | ssb_chipco_timing_init(&bus->chipco, ns); | 271 | ssb_chipco_timing_init(&bus->chipco, ns); |
272 | 272 | ||
273 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ | 273 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ |
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c index 9ef124f9ee2d..bb18d76f9f2c 100644 --- a/drivers/ssb/embedded.c +++ b/drivers/ssb/embedded.c | |||
@@ -4,11 +4,13 @@ | |||
4 | * | 4 | * |
5 | * Copyright 2005-2008, Broadcom Corporation | 5 | * Copyright 2005-2008, Broadcom Corporation |
6 | * Copyright 2006-2008, Michael Buesch <m@bues.ch> | 6 | * Copyright 2006-2008, Michael Buesch <m@bues.ch> |
7 | * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
7 | * | 8 | * |
8 | * Licensed under the GNU/GPL. See COPYING for details. | 9 | * Licensed under the GNU/GPL. See COPYING for details. |
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include <linux/platform_device.h> | ||
12 | #include <linux/ssb/ssb.h> | 14 | #include <linux/ssb/ssb.h> |
13 | #include <linux/ssb/ssb_embedded.h> | 15 | #include <linux/ssb/ssb_embedded.h> |
14 | #include <linux/ssb/ssb_driver_pci.h> | 16 | #include <linux/ssb/ssb_driver_pci.h> |
@@ -32,6 +34,39 @@ int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks) | |||
32 | } | 34 | } |
33 | EXPORT_SYMBOL(ssb_watchdog_timer_set); | 35 | EXPORT_SYMBOL(ssb_watchdog_timer_set); |
34 | 36 | ||
37 | int ssb_watchdog_register(struct ssb_bus *bus) | ||
38 | { | ||
39 | struct bcm47xx_wdt wdt = {}; | ||
40 | struct platform_device *pdev; | ||
41 | |||
42 | if (ssb_chipco_available(&bus->chipco)) { | ||
43 | wdt.driver_data = &bus->chipco; | ||
44 | wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt; | ||
45 | wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms; | ||
46 | wdt.max_timer_ms = bus->chipco.max_timer_ms; | ||
47 | } else if (ssb_extif_available(&bus->extif)) { | ||
48 | wdt.driver_data = &bus->extif; | ||
49 | wdt.timer_set = ssb_extif_watchdog_timer_set_wdt; | ||
50 | wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms; | ||
51 | wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS; | ||
52 | } else { | ||
53 | return -ENODEV; | ||
54 | } | ||
55 | |||
56 | pdev = platform_device_register_data(NULL, "bcm47xx-wdt", | ||
57 | bus->busnumber, &wdt, | ||
58 | sizeof(wdt)); | ||
59 | if (IS_ERR(pdev)) { | ||
60 | ssb_dprintk(KERN_INFO PFX | ||
61 | "can not register watchdog device, err: %li\n", | ||
62 | PTR_ERR(pdev)); | ||
63 | return PTR_ERR(pdev); | ||
64 | } | ||
65 | |||
66 | bus->watchdog = pdev; | ||
67 | return 0; | ||
68 | } | ||
69 | |||
35 | u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) | 70 | u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) |
36 | { | 71 | { |
37 | unsigned long flags; | 72 | unsigned long flags; |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index df0f145c22fc..58c7da29a37c 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/platform_device.h> | ||
16 | #include <linux/ssb/ssb.h> | 17 | #include <linux/ssb/ssb.h> |
17 | #include <linux/ssb/ssb_regs.h> | 18 | #include <linux/ssb/ssb_regs.h> |
18 | #include <linux/ssb/ssb_driver_gige.h> | 19 | #include <linux/ssb/ssb_driver_gige.h> |
@@ -433,6 +434,11 @@ static void ssb_devices_unregister(struct ssb_bus *bus) | |||
433 | if (sdev->dev) | 434 | if (sdev->dev) |
434 | device_unregister(sdev->dev); | 435 | device_unregister(sdev->dev); |
435 | } | 436 | } |
437 | |||
438 | #ifdef CONFIG_SSB_EMBEDDED | ||
439 | if (bus->bustype == SSB_BUSTYPE_SSB) | ||
440 | platform_device_unregister(bus->watchdog); | ||
441 | #endif | ||
436 | } | 442 | } |
437 | 443 | ||
438 | void ssb_bus_unregister(struct ssb_bus *bus) | 444 | void ssb_bus_unregister(struct ssb_bus *bus) |
@@ -561,6 +567,8 @@ static int __devinit ssb_attach_queued_buses(void) | |||
561 | if (err) | 567 | if (err) |
562 | goto error; | 568 | goto error; |
563 | ssb_pcicore_init(&bus->pcicore); | 569 | ssb_pcicore_init(&bus->pcicore); |
570 | if (bus->bustype == SSB_BUSTYPE_SSB) | ||
571 | ssb_watchdog_register(bus); | ||
564 | ssb_bus_may_powerdown(bus); | 572 | ssb_bus_may_powerdown(bus); |
565 | 573 | ||
566 | err = ssb_devices_register(bus); | 574 | err = ssb_devices_register(bus); |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index a305550b4b65..8942db1d855a 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/ssb/ssb.h> | 4 | #include <linux/ssb/ssb.h> |
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/bcm47xx_wdt.h> | ||
6 | 7 | ||
7 | 8 | ||
8 | #define PFX "ssb: " | 9 | #define PFX "ssb: " |
@@ -210,5 +211,35 @@ static inline void b43_pci_ssb_bridge_exit(void) | |||
210 | /* driver_chipcommon_pmu.c */ | 211 | /* driver_chipcommon_pmu.c */ |
211 | extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc); | 212 | extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc); |
212 | extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc); | 213 | extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc); |
214 | extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc); | ||
215 | |||
216 | extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, | ||
217 | u32 ticks); | ||
218 | extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); | ||
219 | |||
220 | #ifdef CONFIG_SSB_DRIVER_EXTIF | ||
221 | extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks); | ||
222 | extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); | ||
223 | #else | ||
224 | static inline u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, | ||
225 | u32 ticks) | ||
226 | { | ||
227 | return 0; | ||
228 | } | ||
229 | static inline u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, | ||
230 | u32 ms) | ||
231 | { | ||
232 | return 0; | ||
233 | } | ||
234 | #endif | ||
235 | |||
236 | #ifdef CONFIG_SSB_EMBEDDED | ||
237 | extern int ssb_watchdog_register(struct ssb_bus *bus); | ||
238 | #else /* CONFIG_SSB_EMBEDDED */ | ||
239 | static inline int ssb_watchdog_register(struct ssb_bus *bus) | ||
240 | { | ||
241 | return 0; | ||
242 | } | ||
243 | #endif /* CONFIG_SSB_EMBEDDED */ | ||
213 | 244 | ||
214 | #endif /* LINUX_SSB_PRIVATE_H_ */ | 245 | #endif /* LINUX_SSB_PRIVATE_H_ */ |
diff --git a/include/linux/bcm47xx_wdt.h b/include/linux/bcm47xx_wdt.h new file mode 100644 index 000000000000..e5dfc256485b --- /dev/null +++ b/include/linux/bcm47xx_wdt.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef LINUX_BCM47XX_WDT_H_ | ||
2 | #define LINUX_BCM47XX_WDT_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | |||
7 | struct bcm47xx_wdt { | ||
8 | u32 (*timer_set)(struct bcm47xx_wdt *, u32); | ||
9 | u32 (*timer_set_ms)(struct bcm47xx_wdt *, u32); | ||
10 | u32 max_timer_ms; | ||
11 | |||
12 | void *driver_data; | ||
13 | }; | ||
14 | |||
15 | static inline void *bcm47xx_wdt_get_drvdata(struct bcm47xx_wdt *wdt) | ||
16 | { | ||
17 | return wdt->driver_data; | ||
18 | } | ||
19 | #endif /* LINUX_BCM47XX_WDT_H_ */ | ||
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 145f3c56227f..e51359180b6f 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef LINUX_BCMA_DRIVER_CC_H_ | 1 | #ifndef LINUX_BCMA_DRIVER_CC_H_ |
2 | #define LINUX_BCMA_DRIVER_CC_H_ | 2 | #define LINUX_BCMA_DRIVER_CC_H_ |
3 | 3 | ||
4 | #include <linux/platform_device.h> | ||
5 | |||
4 | /** ChipCommon core registers. **/ | 6 | /** ChipCommon core registers. **/ |
5 | #define BCMA_CC_ID 0x0000 | 7 | #define BCMA_CC_ID 0x0000 |
6 | #define BCMA_CC_ID_ID 0x0000FFFF | 8 | #define BCMA_CC_ID_ID 0x0000FFFF |
@@ -570,6 +572,8 @@ struct bcma_drv_cc { | |||
570 | int nr_serial_ports; | 572 | int nr_serial_ports; |
571 | struct bcma_serial_port serial_ports[4]; | 573 | struct bcma_serial_port serial_ports[4]; |
572 | #endif /* CONFIG_BCMA_DRIVER_MIPS */ | 574 | #endif /* CONFIG_BCMA_DRIVER_MIPS */ |
575 | u32 ticks_per_ms; | ||
576 | struct platform_device *watchdog; | ||
573 | }; | 577 | }; |
574 | 578 | ||
575 | /* Register access */ | 579 | /* Register access */ |
@@ -593,8 +597,7 @@ extern void bcma_chipco_resume(struct bcma_drv_cc *cc); | |||
593 | 597 | ||
594 | void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); | 598 | void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); |
595 | 599 | ||
596 | extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, | 600 | extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); |
597 | u32 ticks); | ||
598 | 601 | ||
599 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); | 602 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); |
600 | 603 | ||
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index f9c5a787d350..8f690e53dd89 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1213,6 +1213,21 @@ struct ieee80211_vht_cap { | |||
1213 | } __packed; | 1213 | } __packed; |
1214 | 1214 | ||
1215 | /** | 1215 | /** |
1216 | * enum ieee80211_vht_chanwidth - VHT channel width | ||
1217 | * @IEEE80211_VHT_CHANWIDTH_USE_HT: use the HT operation IE to | ||
1218 | * determine the channel width (20 or 40 MHz) | ||
1219 | * @IEEE80211_VHT_CHANWIDTH_80MHZ: 80 MHz bandwidth | ||
1220 | * @IEEE80211_VHT_CHANWIDTH_160MHZ: 160 MHz bandwidth | ||
1221 | * @IEEE80211_VHT_CHANWIDTH_80P80MHZ: 80+80 MHz bandwidth | ||
1222 | */ | ||
1223 | enum ieee80211_vht_chanwidth { | ||
1224 | IEEE80211_VHT_CHANWIDTH_USE_HT = 0, | ||
1225 | IEEE80211_VHT_CHANWIDTH_80MHZ = 1, | ||
1226 | IEEE80211_VHT_CHANWIDTH_160MHZ = 2, | ||
1227 | IEEE80211_VHT_CHANWIDTH_80P80MHZ = 3, | ||
1228 | }; | ||
1229 | |||
1230 | /** | ||
1216 | * struct ieee80211_vht_operation - VHT operation IE | 1231 | * struct ieee80211_vht_operation - VHT operation IE |
1217 | * | 1232 | * |
1218 | * This structure is the "VHT operation element" as | 1233 | * This structure is the "VHT operation element" as |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index bb674c02f306..1f64e3f1f22b 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
9 | #include <linux/mod_devicetable.h> | 9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/dma-mapping.h> | 10 | #include <linux/dma-mapping.h> |
11 | #include <linux/platform_device.h> | ||
11 | 12 | ||
12 | #include <linux/ssb/ssb_regs.h> | 13 | #include <linux/ssb/ssb_regs.h> |
13 | 14 | ||
@@ -432,6 +433,7 @@ struct ssb_bus { | |||
432 | #ifdef CONFIG_SSB_EMBEDDED | 433 | #ifdef CONFIG_SSB_EMBEDDED |
433 | /* Lock for GPIO register access. */ | 434 | /* Lock for GPIO register access. */ |
434 | spinlock_t gpio_lock; | 435 | spinlock_t gpio_lock; |
436 | struct platform_device *watchdog; | ||
435 | #endif /* EMBEDDED */ | 437 | #endif /* EMBEDDED */ |
436 | 438 | ||
437 | /* Internal-only stuff follows. Do not touch. */ | 439 | /* Internal-only stuff follows. Do not touch. */ |
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index c2b02a5c86ae..38339fd68a5f 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h | |||
@@ -591,6 +591,8 @@ struct ssb_chipcommon { | |||
591 | /* Fast Powerup Delay constant */ | 591 | /* Fast Powerup Delay constant */ |
592 | u16 fast_pwrup_delay; | 592 | u16 fast_pwrup_delay; |
593 | struct ssb_chipcommon_pmu pmu; | 593 | struct ssb_chipcommon_pmu pmu; |
594 | u32 ticks_per_ms; | ||
595 | u32 max_timer_ms; | ||
594 | }; | 596 | }; |
595 | 597 | ||
596 | static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) | 598 | static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) |
@@ -630,8 +632,7 @@ enum ssb_clkmode { | |||
630 | extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, | 632 | extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, |
631 | enum ssb_clkmode mode); | 633 | enum ssb_clkmode mode); |
632 | 634 | ||
633 | extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, | 635 | extern u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks); |
634 | u32 ticks); | ||
635 | 636 | ||
636 | void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value); | 637 | void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value); |
637 | 638 | ||
diff --git a/include/linux/ssb/ssb_driver_extif.h b/include/linux/ssb/ssb_driver_extif.h index 91161f0aa22b..99511d0e931d 100644 --- a/include/linux/ssb/ssb_driver_extif.h +++ b/include/linux/ssb/ssb_driver_extif.h | |||
@@ -152,6 +152,9 @@ | |||
152 | /* watchdog */ | 152 | /* watchdog */ |
153 | #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */ | 153 | #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */ |
154 | 154 | ||
155 | #define SSB_EXTIF_WATCHDOG_MAX_TIMER ((1 << 28) - 1) | ||
156 | #define SSB_EXTIF_WATCHDOG_MAX_TIMER_MS (SSB_EXTIF_WATCHDOG_MAX_TIMER \ | ||
157 | / (SSB_EXTIF_WATCHDOG_CLK / 1000)) | ||
155 | 158 | ||
156 | 159 | ||
157 | #ifdef CONFIG_SSB_DRIVER_EXTIF | 160 | #ifdef CONFIG_SSB_DRIVER_EXTIF |
@@ -171,8 +174,7 @@ extern void ssb_extif_get_clockcontrol(struct ssb_extif *extif, | |||
171 | extern void ssb_extif_timing_init(struct ssb_extif *extif, | 174 | extern void ssb_extif_timing_init(struct ssb_extif *extif, |
172 | unsigned long ns); | 175 | unsigned long ns); |
173 | 176 | ||
174 | extern void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, | 177 | extern u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks); |
175 | u32 ticks); | ||
176 | 178 | ||
177 | /* Extif GPIO pin access */ | 179 | /* Extif GPIO pin access */ |
178 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask); | 180 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask); |
@@ -205,10 +207,52 @@ void ssb_extif_get_clockcontrol(struct ssb_extif *extif, | |||
205 | } | 207 | } |
206 | 208 | ||
207 | static inline | 209 | static inline |
208 | void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, | 210 | void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns) |
209 | u32 ticks) | ||
210 | { | 211 | { |
211 | } | 212 | } |
212 | 213 | ||
214 | static inline | ||
215 | u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks) | ||
216 | { | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) | ||
221 | { | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, | ||
226 | u32 value) | ||
227 | { | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, | ||
232 | u32 value) | ||
233 | { | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, | ||
238 | u32 value) | ||
239 | { | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, | ||
244 | u32 value) | ||
245 | { | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | #ifdef CONFIG_SSB_SERIAL | ||
250 | static inline int ssb_extif_serial_init(struct ssb_extif *extif, | ||
251 | struct ssb_serial_port *ports) | ||
252 | { | ||
253 | return 0; | ||
254 | } | ||
255 | #endif /* CONFIG_SSB_SERIAL */ | ||
256 | |||
213 | #endif /* CONFIG_SSB_DRIVER_EXTIF */ | 257 | #endif /* CONFIG_SSB_DRIVER_EXTIF */ |
214 | #endif /* LINUX_SSB_EXTIFCORE_H_ */ | 258 | #endif /* LINUX_SSB_EXTIFCORE_H_ */ |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ef5b85dac3f7..014a2eaa5389 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -376,7 +376,7 @@ extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); | |||
376 | extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, | 376 | extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, |
377 | u16 flags); | 377 | u16 flags); |
378 | 378 | ||
379 | extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); | 379 | extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); |
380 | extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status); | 380 | extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status); |
381 | extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); | 381 | extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); |
382 | extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); | 382 | extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); |
@@ -577,6 +577,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); | |||
577 | int hci_conn_del(struct hci_conn *conn); | 577 | int hci_conn_del(struct hci_conn *conn); |
578 | void hci_conn_hash_flush(struct hci_dev *hdev); | 578 | void hci_conn_hash_flush(struct hci_dev *hdev); |
579 | void hci_conn_check_pending(struct hci_dev *hdev); | 579 | void hci_conn_check_pending(struct hci_dev *hdev); |
580 | void hci_conn_accept(struct hci_conn *conn, int mask); | ||
580 | 581 | ||
581 | struct hci_chan *hci_chan_create(struct hci_conn *conn); | 582 | struct hci_chan *hci_chan_create(struct hci_conn *conn); |
582 | void hci_chan_del(struct hci_chan *chan); | 583 | void hci_chan_del(struct hci_chan *chan); |
@@ -766,7 +767,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); | |||
766 | #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) | 767 | #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) |
767 | #define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC) | 768 | #define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC) |
768 | #define lmp_ext_inq_capable(dev) ((dev)->features[6] & LMP_EXT_INQ) | 769 | #define lmp_ext_inq_capable(dev) ((dev)->features[6] & LMP_EXT_INQ) |
769 | #define lmp_le_br_capable(dev) ((dev)->features[6] & LMP_SIMUL_LE_BR) | 770 | #define lmp_le_br_capable(dev) !!((dev)->features[6] & LMP_SIMUL_LE_BR) |
770 | #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) | 771 | #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) |
771 | #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) | 772 | #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) |
772 | #define lmp_lsto_capable(dev) ((dev)->features[7] & LMP_LSTO) | 773 | #define lmp_lsto_capable(dev) ((dev)->features[7] & LMP_LSTO) |
@@ -775,12 +776,30 @@ void hci_conn_del_sysfs(struct hci_conn *conn); | |||
775 | 776 | ||
776 | /* ----- Extended LMP capabilities ----- */ | 777 | /* ----- Extended LMP capabilities ----- */ |
777 | #define lmp_host_ssp_capable(dev) ((dev)->host_features[0] & LMP_HOST_SSP) | 778 | #define lmp_host_ssp_capable(dev) ((dev)->host_features[0] & LMP_HOST_SSP) |
778 | #define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE) | 779 | #define lmp_host_le_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE) |
779 | #define lmp_host_le_br_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE_BREDR) | 780 | #define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR) |
781 | |||
782 | /* returns true if at least one AMP active */ | ||
783 | static inline bool hci_amp_capable(void) | ||
784 | { | ||
785 | struct hci_dev *hdev; | ||
786 | bool ret = false; | ||
787 | |||
788 | read_lock(&hci_dev_list_lock); | ||
789 | list_for_each_entry(hdev, &hci_dev_list, list) | ||
790 | if (hdev->amp_type == HCI_AMP && | ||
791 | test_bit(HCI_UP, &hdev->flags)) | ||
792 | ret = true; | ||
793 | read_unlock(&hci_dev_list_lock); | ||
794 | |||
795 | return ret; | ||
796 | } | ||
780 | 797 | ||
781 | /* ----- HCI protocols ----- */ | 798 | /* ----- HCI protocols ----- */ |
799 | #define HCI_PROTO_DEFER 0x01 | ||
800 | |||
782 | static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, | 801 | static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, |
783 | __u8 type) | 802 | __u8 type, __u8 *flags) |
784 | { | 803 | { |
785 | switch (type) { | 804 | switch (type) { |
786 | case ACL_LINK: | 805 | case ACL_LINK: |
@@ -788,7 +807,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
788 | 807 | ||
789 | case SCO_LINK: | 808 | case SCO_LINK: |
790 | case ESCO_LINK: | 809 | case ESCO_LINK: |
791 | return sco_connect_ind(hdev, bdaddr); | 810 | return sco_connect_ind(hdev, bdaddr, flags); |
792 | 811 | ||
793 | default: | 812 | default: |
794 | BT_ERR("unknown link type %d", type); | 813 | BT_ERR("unknown link type %d", type); |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f57fab04e7c5..7588ef44ebaf 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -611,7 +611,7 @@ enum { | |||
611 | CONF_MTU_DONE, | 611 | CONF_MTU_DONE, |
612 | CONF_MODE_DONE, | 612 | CONF_MODE_DONE, |
613 | CONF_CONNECT_PEND, | 613 | CONF_CONNECT_PEND, |
614 | CONF_NO_FCS_RECV, | 614 | CONF_RECV_NO_FCS, |
615 | CONF_STATE2_DEVICE, | 615 | CONF_STATE2_DEVICE, |
616 | CONF_EWS_RECV, | 616 | CONF_EWS_RECV, |
617 | CONF_LOC_CONF_PEND, | 617 | CONF_LOC_CONF_PEND, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e78db2cf3d1b..8e6a6b73b9c9 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -58,6 +58,8 @@ | |||
58 | * structures here describe these capabilities in detail. | 58 | * structures here describe these capabilities in detail. |
59 | */ | 59 | */ |
60 | 60 | ||
61 | struct wiphy; | ||
62 | |||
61 | /* | 63 | /* |
62 | * wireless hardware capability structures | 64 | * wireless hardware capability structures |
63 | */ | 65 | */ |
@@ -388,6 +390,22 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1, | |||
388 | const struct cfg80211_chan_def *chandef2); | 390 | const struct cfg80211_chan_def *chandef2); |
389 | 391 | ||
390 | /** | 392 | /** |
393 | * cfg80211_chandef_valid - check if a channel definition is valid | ||
394 | * @chandef: the channel definition to check | ||
395 | */ | ||
396 | bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef); | ||
397 | |||
398 | /** | ||
399 | * cfg80211_chandef_usable - check if secondary channels can be used | ||
400 | * @wiphy: the wiphy to validate against | ||
401 | * @chandef: the channel definition to check | ||
402 | * @prohibited_flags: the regulatory chanenl flags that must not be set | ||
403 | */ | ||
404 | bool cfg80211_chandef_usable(struct wiphy *wiphy, | ||
405 | const struct cfg80211_chan_def *chandef, | ||
406 | u32 prohibited_flags); | ||
407 | |||
408 | /** | ||
391 | * enum survey_info_flags - survey information flags | 409 | * enum survey_info_flags - survey information flags |
392 | * | 410 | * |
393 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in | 411 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in |
@@ -520,6 +538,8 @@ struct cfg80211_beacon_data { | |||
520 | * @privacy: the BSS uses privacy | 538 | * @privacy: the BSS uses privacy |
521 | * @auth_type: Authentication type (algorithm) | 539 | * @auth_type: Authentication type (algorithm) |
522 | * @inactivity_timeout: time in seconds to determine station's inactivity. | 540 | * @inactivity_timeout: time in seconds to determine station's inactivity. |
541 | * @p2p_ctwindow: P2P CT Window | ||
542 | * @p2p_opp_ps: P2P opportunistic PS | ||
523 | */ | 543 | */ |
524 | struct cfg80211_ap_settings { | 544 | struct cfg80211_ap_settings { |
525 | struct cfg80211_chan_def chandef; | 545 | struct cfg80211_chan_def chandef; |
@@ -534,6 +554,8 @@ struct cfg80211_ap_settings { | |||
534 | bool privacy; | 554 | bool privacy; |
535 | enum nl80211_auth_type auth_type; | 555 | enum nl80211_auth_type auth_type; |
536 | int inactivity_timeout; | 556 | int inactivity_timeout; |
557 | u8 p2p_ctwindow; | ||
558 | bool p2p_opp_ps; | ||
537 | }; | 559 | }; |
538 | 560 | ||
539 | /** | 561 | /** |
@@ -895,6 +917,8 @@ struct mpath_info { | |||
895 | * @ap_isolate: do not forward packets between connected stations | 917 | * @ap_isolate: do not forward packets between connected stations |
896 | * @ht_opmode: HT Operation mode | 918 | * @ht_opmode: HT Operation mode |
897 | * (u16 = opmode, -1 = do not change) | 919 | * (u16 = opmode, -1 = do not change) |
920 | * @p2p_ctwindow: P2P CT Window (-1 = no change) | ||
921 | * @p2p_opp_ps: P2P opportunistic PS (-1 = no change) | ||
898 | */ | 922 | */ |
899 | struct bss_parameters { | 923 | struct bss_parameters { |
900 | int use_cts_prot; | 924 | int use_cts_prot; |
@@ -904,6 +928,7 @@ struct bss_parameters { | |||
904 | u8 basic_rates_len; | 928 | u8 basic_rates_len; |
905 | int ap_isolate; | 929 | int ap_isolate; |
906 | int ht_opmode; | 930 | int ht_opmode; |
931 | s8 p2p_ctwindow, p2p_opp_ps; | ||
907 | }; | 932 | }; |
908 | 933 | ||
909 | /** | 934 | /** |
@@ -1045,9 +1070,6 @@ struct ieee80211_txq_params { | |||
1045 | u8 aifs; | 1070 | u8 aifs; |
1046 | }; | 1071 | }; |
1047 | 1072 | ||
1048 | /* from net/wireless.h */ | ||
1049 | struct wiphy; | ||
1050 | |||
1051 | /** | 1073 | /** |
1052 | * DOC: Scanning and BSS list handling | 1074 | * DOC: Scanning and BSS list handling |
1053 | * | 1075 | * |
@@ -1184,6 +1206,18 @@ enum cfg80211_signal_type { | |||
1184 | }; | 1206 | }; |
1185 | 1207 | ||
1186 | /** | 1208 | /** |
1209 | * struct cfg80211_bss_ie_data - BSS entry IE data | ||
1210 | * @rcu_head: internal use, for freeing | ||
1211 | * @len: length of the IEs | ||
1212 | * @data: IE data | ||
1213 | */ | ||
1214 | struct cfg80211_bss_ies { | ||
1215 | struct rcu_head rcu_head; | ||
1216 | int len; | ||
1217 | u8 data[]; | ||
1218 | }; | ||
1219 | |||
1220 | /** | ||
1187 | * struct cfg80211_bss - BSS description | 1221 | * struct cfg80211_bss - BSS description |
1188 | * | 1222 | * |
1189 | * This structure describes a BSS (which may also be a mesh network) | 1223 | * This structure describes a BSS (which may also be a mesh network) |
@@ -1194,36 +1228,34 @@ enum cfg80211_signal_type { | |||
1194 | * @tsf: timestamp of last received update | 1228 | * @tsf: timestamp of last received update |
1195 | * @beacon_interval: the beacon interval as from the frame | 1229 | * @beacon_interval: the beacon interval as from the frame |
1196 | * @capability: the capability field in host byte order | 1230 | * @capability: the capability field in host byte order |
1197 | * @information_elements: the information elements (Note that there | 1231 | * @ies: the information elements (Note that there |
1198 | * is no guarantee that these are well-formed!); this is a pointer to | 1232 | * is no guarantee that these are well-formed!); this is a pointer to |
1199 | * either the beacon_ies or proberesp_ies depending on whether Probe | 1233 | * either the beacon_ies or proberesp_ies depending on whether Probe |
1200 | * Response frame has been received | 1234 | * Response frame has been received |
1201 | * @len_information_elements: total length of the information elements | ||
1202 | * @beacon_ies: the information elements from the last Beacon frame | 1235 | * @beacon_ies: the information elements from the last Beacon frame |
1203 | * @len_beacon_ies: total length of the beacon_ies | ||
1204 | * @proberesp_ies: the information elements from the last Probe Response frame | 1236 | * @proberesp_ies: the information elements from the last Probe Response frame |
1205 | * @len_proberesp_ies: total length of the proberesp_ies | ||
1206 | * @signal: signal strength value (type depends on the wiphy's signal_type) | 1237 | * @signal: signal strength value (type depends on the wiphy's signal_type) |
1207 | * @free_priv: function pointer to free private data | 1238 | * @free_priv: function pointer to free private data |
1208 | * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes | 1239 | * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes |
1209 | */ | 1240 | */ |
1210 | struct cfg80211_bss { | 1241 | struct cfg80211_bss { |
1242 | u64 tsf; | ||
1243 | |||
1211 | struct ieee80211_channel *channel; | 1244 | struct ieee80211_channel *channel; |
1212 | 1245 | ||
1213 | u8 bssid[ETH_ALEN]; | 1246 | const struct cfg80211_bss_ies __rcu *ies; |
1214 | u64 tsf; | 1247 | const struct cfg80211_bss_ies __rcu *beacon_ies; |
1248 | const struct cfg80211_bss_ies __rcu *proberesp_ies; | ||
1249 | |||
1250 | void (*free_priv)(struct cfg80211_bss *bss); | ||
1251 | |||
1252 | s32 signal; | ||
1253 | |||
1215 | u16 beacon_interval; | 1254 | u16 beacon_interval; |
1216 | u16 capability; | 1255 | u16 capability; |
1217 | u8 *information_elements; | ||
1218 | size_t len_information_elements; | ||
1219 | u8 *beacon_ies; | ||
1220 | size_t len_beacon_ies; | ||
1221 | u8 *proberesp_ies; | ||
1222 | size_t len_proberesp_ies; | ||
1223 | 1256 | ||
1224 | s32 signal; | 1257 | u8 bssid[ETH_ALEN]; |
1225 | 1258 | ||
1226 | void (*free_priv)(struct cfg80211_bss *bss); | ||
1227 | u8 priv[0] __attribute__((__aligned__(sizeof(void *)))); | 1259 | u8 priv[0] __attribute__((__aligned__(sizeof(void *)))); |
1228 | }; | 1260 | }; |
1229 | 1261 | ||
@@ -1231,6 +1263,9 @@ struct cfg80211_bss { | |||
1231 | * ieee80211_bss_get_ie - find IE with given ID | 1263 | * ieee80211_bss_get_ie - find IE with given ID |
1232 | * @bss: the bss to search | 1264 | * @bss: the bss to search |
1233 | * @ie: the IE ID | 1265 | * @ie: the IE ID |
1266 | * | ||
1267 | * Note that the return value is an RCU-protected pointer, so | ||
1268 | * rcu_read_lock() must be held when calling this function. | ||
1234 | * Returns %NULL if not found. | 1269 | * Returns %NULL if not found. |
1235 | */ | 1270 | */ |
1236 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); | 1271 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); |
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 7f0df133d119..c3999632e616 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h | |||
@@ -186,6 +186,10 @@ struct ieee80211_radiotap_header { | |||
186 | * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless | 186 | * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless |
187 | * | 187 | * |
188 | * Contains the AMPDU information for the subframe. | 188 | * Contains the AMPDU information for the subframe. |
189 | * | ||
190 | * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 | ||
191 | * | ||
192 | * Contains VHT information about this frame. | ||
189 | */ | 193 | */ |
190 | enum ieee80211_radiotap_type { | 194 | enum ieee80211_radiotap_type { |
191 | IEEE80211_RADIOTAP_TSFT = 0, | 195 | IEEE80211_RADIOTAP_TSFT = 0, |
@@ -209,6 +213,7 @@ enum ieee80211_radiotap_type { | |||
209 | 213 | ||
210 | IEEE80211_RADIOTAP_MCS = 19, | 214 | IEEE80211_RADIOTAP_MCS = 19, |
211 | IEEE80211_RADIOTAP_AMPDU_STATUS = 20, | 215 | IEEE80211_RADIOTAP_AMPDU_STATUS = 20, |
216 | IEEE80211_RADIOTAP_VHT = 21, | ||
212 | 217 | ||
213 | /* valid in every it_present bitmap, even vendor namespaces */ | 218 | /* valid in every it_present bitmap, even vendor namespaces */ |
214 | IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, | 219 | IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, |
@@ -282,6 +287,25 @@ enum ieee80211_radiotap_type { | |||
282 | #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 | 287 | #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 |
283 | #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 | 288 | #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 |
284 | 289 | ||
290 | /* For IEEE80211_RADIOTAP_VHT */ | ||
291 | #define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001 | ||
292 | #define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002 | ||
293 | #define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 | ||
294 | #define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008 | ||
295 | #define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010 | ||
296 | #define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020 | ||
297 | #define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 | ||
298 | #define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080 | ||
299 | #define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100 | ||
300 | |||
301 | #define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 | ||
302 | #define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02 | ||
303 | #define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 | ||
304 | #define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08 | ||
305 | #define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10 | ||
306 | #define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20 | ||
307 | |||
308 | |||
285 | /* helpers */ | 309 | /* helpers */ |
286 | static inline int ieee80211_get_radiotap_len(unsigned char *data) | 310 | static inline int ieee80211_get_radiotap_len(unsigned char *data) |
287 | { | 311 | { |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index db7680acd0da..1c02fb3b3817 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -164,7 +164,7 @@ enum ieee80211_chanctx_change { | |||
164 | * active on the channel to receive MIMO transmissions | 164 | * active on the channel to receive MIMO transmissions |
165 | * @rx_chains_dynamic: The number of RX chains that must be enabled | 165 | * @rx_chains_dynamic: The number of RX chains that must be enabled |
166 | * after RTS/CTS handshake to receive SMPS MIMO transmissions; | 166 | * after RTS/CTS handshake to receive SMPS MIMO transmissions; |
167 | * this will always be >= @rx_chains_always. | 167 | * this will always be >= @rx_chains_static. |
168 | * @drv_priv: data area for driver use, will always be aligned to | 168 | * @drv_priv: data area for driver use, will always be aligned to |
169 | * sizeof(void *), size is determined in hw information. | 169 | * sizeof(void *), size is determined in hw information. |
170 | */ | 170 | */ |
@@ -1473,6 +1473,10 @@ enum ieee80211_hw_flags { | |||
1473 | * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only | 1473 | * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only |
1474 | * adding _BW is supported today. | 1474 | * adding _BW is supported today. |
1475 | * | 1475 | * |
1476 | * @radiotap_vht_details: lists which VHT MCS information the HW reports, | ||
1477 | * the default is _GI | _BANDWIDTH. | ||
1478 | * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values. | ||
1479 | * | ||
1476 | * @netdev_features: netdev features to be set in each netdev created | 1480 | * @netdev_features: netdev features to be set in each netdev created |
1477 | * from this HW. Note only HW checksum features are currently | 1481 | * from this HW. Note only HW checksum features are currently |
1478 | * compatible with mac80211. Other feature bits will be rejected. | 1482 | * compatible with mac80211. Other feature bits will be rejected. |
@@ -1499,6 +1503,7 @@ struct ieee80211_hw { | |||
1499 | u8 max_tx_aggregation_subframes; | 1503 | u8 max_tx_aggregation_subframes; |
1500 | u8 offchannel_tx_hw_queue; | 1504 | u8 offchannel_tx_hw_queue; |
1501 | u8 radiotap_mcs_details; | 1505 | u8 radiotap_mcs_details; |
1506 | u16 radiotap_vht_details; | ||
1502 | netdev_features_t netdev_features; | 1507 | netdev_features_t netdev_features; |
1503 | }; | 1508 | }; |
1504 | 1509 | ||
@@ -3139,8 +3144,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
3139 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 3144 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
3140 | * @ssid: SSID buffer | 3145 | * @ssid: SSID buffer |
3141 | * @ssid_len: length of SSID | 3146 | * @ssid_len: length of SSID |
3142 | * @ie: buffer containing all IEs except SSID for the template | 3147 | * @tailroom: tailroom to reserve at end of SKB for IEs |
3143 | * @ie_len: length of the IE buffer | ||
3144 | * | 3148 | * |
3145 | * Creates a Probe Request template which can, for example, be uploaded to | 3149 | * Creates a Probe Request template which can, for example, be uploaded to |
3146 | * hardware. | 3150 | * hardware. |
@@ -3148,7 +3152,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
3148 | struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | 3152 | struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, |
3149 | struct ieee80211_vif *vif, | 3153 | struct ieee80211_vif *vif, |
3150 | const u8 *ssid, size_t ssid_len, | 3154 | const u8 *ssid, size_t ssid_len, |
3151 | const u8 *ie, size_t ie_len); | 3155 | size_t tailroom); |
3152 | 3156 | ||
3153 | /** | 3157 | /** |
3154 | * ieee80211_rts_get - RTS frame generation function | 3158 | * ieee80211_rts_get - RTS frame generation function |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 33a417481ad8..e3e19f8b16f2 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -1303,6 +1303,13 @@ enum nl80211_commands { | |||
1303 | * | 1303 | * |
1304 | * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) | 1304 | * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) |
1305 | * | 1305 | * |
1306 | * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with | ||
1307 | * the START_AP and SET_BSS commands | ||
1308 | * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the | ||
1309 | * START_AP and SET_BSS commands. This can have the values 0 or 1; | ||
1310 | * if not given in START_AP 0 is assumed, if not given in SET_BSS | ||
1311 | * no change is made. | ||
1312 | * | ||
1306 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1313 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1307 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1314 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1308 | */ | 1315 | */ |
@@ -1570,6 +1577,9 @@ enum nl80211_attrs { | |||
1570 | NL80211_ATTR_CENTER_FREQ1, | 1577 | NL80211_ATTR_CENTER_FREQ1, |
1571 | NL80211_ATTR_CENTER_FREQ2, | 1578 | NL80211_ATTR_CENTER_FREQ2, |
1572 | 1579 | ||
1580 | NL80211_ATTR_P2P_CTWINDOW, | ||
1581 | NL80211_ATTR_P2P_OPPPS, | ||
1582 | |||
1573 | /* add attributes here, update the policy in nl80211.c */ | 1583 | /* add attributes here, update the policy in nl80211.c */ |
1574 | 1584 | ||
1575 | __NL80211_ATTR_AFTER_LAST, | 1585 | __NL80211_ATTR_AFTER_LAST, |
@@ -3126,6 +3136,10 @@ enum nl80211_ap_sme_features { | |||
3126 | * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform | 3136 | * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform |
3127 | * OBSS scans and generate 20/40 BSS coex reports. This flag is used only | 3137 | * OBSS scans and generate 20/40 BSS coex reports. This flag is used only |
3128 | * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied. | 3138 | * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied. |
3139 | * @NL80211_FEATURE_P2P_GO_CTWIN: P2P GO implementation supports CT Window | ||
3140 | * setting | ||
3141 | * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic | ||
3142 | * powersave | ||
3129 | */ | 3143 | */ |
3130 | enum nl80211_feature_flags { | 3144 | enum nl80211_feature_flags { |
3131 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, | 3145 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, |
@@ -3139,6 +3153,8 @@ enum nl80211_feature_flags { | |||
3139 | NL80211_FEATURE_AP_SCAN = 1 << 8, | 3153 | NL80211_FEATURE_AP_SCAN = 1 << 8, |
3140 | NL80211_FEATURE_VIF_TXPOWER = 1 << 9, | 3154 | NL80211_FEATURE_VIF_TXPOWER = 1 << 9, |
3141 | NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, | 3155 | NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, |
3156 | NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11, | ||
3157 | NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12, | ||
3142 | }; | 3158 | }; |
3143 | 3159 | ||
3144 | /** | 3160 | /** |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 7140f83328a2..596660d37c5e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -861,6 +861,9 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
861 | /* Clear flags */ | 861 | /* Clear flags */ |
862 | hdev->flags = 0; | 862 | hdev->flags = 0; |
863 | 863 | ||
864 | /* Controller radio is available but is currently powered down */ | ||
865 | hdev->amp_status = 0; | ||
866 | |||
864 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 867 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
865 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); | 868 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
866 | 869 | ||
@@ -1854,6 +1857,8 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1854 | for (i = 0; i < NUM_REASSEMBLY; i++) | 1857 | for (i = 0; i < NUM_REASSEMBLY; i++) |
1855 | kfree_skb(hdev->reassembly[i]); | 1858 | kfree_skb(hdev->reassembly[i]); |
1856 | 1859 | ||
1860 | cancel_work_sync(&hdev->power_on); | ||
1861 | |||
1857 | if (!test_bit(HCI_INIT, &hdev->flags) && | 1862 | if (!test_bit(HCI_INIT, &hdev->flags) && |
1858 | !test_bit(HCI_SETUP, &hdev->dev_flags)) { | 1863 | !test_bit(HCI_SETUP, &hdev->dev_flags)) { |
1859 | hci_dev_lock(hdev); | 1864 | hci_dev_lock(hdev); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 9f5c5f244502..705078a0cc39 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -794,10 +794,10 @@ static void hci_set_le_support(struct hci_dev *hdev) | |||
794 | 794 | ||
795 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 795 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
796 | cp.le = 1; | 796 | cp.le = 1; |
797 | cp.simul = !!lmp_le_br_capable(hdev); | 797 | cp.simul = lmp_le_br_capable(hdev); |
798 | } | 798 | } |
799 | 799 | ||
800 | if (cp.le != !!lmp_host_le_capable(hdev)) | 800 | if (cp.le != lmp_host_le_capable(hdev)) |
801 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), | 801 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), |
802 | &cp); | 802 | &cp); |
803 | } | 803 | } |
@@ -2047,15 +2047,53 @@ unlock: | |||
2047 | hci_conn_check_pending(hdev); | 2047 | hci_conn_check_pending(hdev); |
2048 | } | 2048 | } |
2049 | 2049 | ||
2050 | void hci_conn_accept(struct hci_conn *conn, int mask) | ||
2051 | { | ||
2052 | struct hci_dev *hdev = conn->hdev; | ||
2053 | |||
2054 | BT_DBG("conn %p", conn); | ||
2055 | |||
2056 | conn->state = BT_CONFIG; | ||
2057 | |||
2058 | if (!lmp_esco_capable(hdev)) { | ||
2059 | struct hci_cp_accept_conn_req cp; | ||
2060 | |||
2061 | bacpy(&cp.bdaddr, &conn->dst); | ||
2062 | |||
2063 | if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) | ||
2064 | cp.role = 0x00; /* Become master */ | ||
2065 | else | ||
2066 | cp.role = 0x01; /* Remain slave */ | ||
2067 | |||
2068 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); | ||
2069 | } else /* lmp_esco_capable(hdev)) */ { | ||
2070 | struct hci_cp_accept_sync_conn_req cp; | ||
2071 | |||
2072 | bacpy(&cp.bdaddr, &conn->dst); | ||
2073 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | ||
2074 | |||
2075 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); | ||
2076 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); | ||
2077 | cp.max_latency = __constant_cpu_to_le16(0xffff); | ||
2078 | cp.content_format = cpu_to_le16(hdev->voice_setting); | ||
2079 | cp.retrans_effort = 0xff; | ||
2080 | |||
2081 | hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, | ||
2082 | sizeof(cp), &cp); | ||
2083 | } | ||
2084 | } | ||
2085 | |||
2050 | static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2086 | static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2051 | { | 2087 | { |
2052 | struct hci_ev_conn_request *ev = (void *) skb->data; | 2088 | struct hci_ev_conn_request *ev = (void *) skb->data; |
2053 | int mask = hdev->link_mode; | 2089 | int mask = hdev->link_mode; |
2090 | __u8 flags = 0; | ||
2054 | 2091 | ||
2055 | BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, | 2092 | BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, |
2056 | ev->link_type); | 2093 | ev->link_type); |
2057 | 2094 | ||
2058 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); | 2095 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, |
2096 | &flags); | ||
2059 | 2097 | ||
2060 | if ((mask & HCI_LM_ACCEPT) && | 2098 | if ((mask & HCI_LM_ACCEPT) && |
2061 | !hci_blacklist_lookup(hdev, &ev->bdaddr)) { | 2099 | !hci_blacklist_lookup(hdev, &ev->bdaddr)) { |
@@ -2081,12 +2119,13 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2081 | } | 2119 | } |
2082 | 2120 | ||
2083 | memcpy(conn->dev_class, ev->dev_class, 3); | 2121 | memcpy(conn->dev_class, ev->dev_class, 3); |
2084 | conn->state = BT_CONNECT; | ||
2085 | 2122 | ||
2086 | hci_dev_unlock(hdev); | 2123 | hci_dev_unlock(hdev); |
2087 | 2124 | ||
2088 | if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { | 2125 | if (ev->link_type == ACL_LINK || |
2126 | (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { | ||
2089 | struct hci_cp_accept_conn_req cp; | 2127 | struct hci_cp_accept_conn_req cp; |
2128 | conn->state = BT_CONNECT; | ||
2090 | 2129 | ||
2091 | bacpy(&cp.bdaddr, &ev->bdaddr); | 2130 | bacpy(&cp.bdaddr, &ev->bdaddr); |
2092 | 2131 | ||
@@ -2097,8 +2136,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2097 | 2136 | ||
2098 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), | 2137 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), |
2099 | &cp); | 2138 | &cp); |
2100 | } else { | 2139 | } else if (!(flags & HCI_PROTO_DEFER)) { |
2101 | struct hci_cp_accept_sync_conn_req cp; | 2140 | struct hci_cp_accept_sync_conn_req cp; |
2141 | conn->state = BT_CONNECT; | ||
2102 | 2142 | ||
2103 | bacpy(&cp.bdaddr, &ev->bdaddr); | 2143 | bacpy(&cp.bdaddr, &ev->bdaddr); |
2104 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 2144 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
@@ -2111,6 +2151,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2111 | 2151 | ||
2112 | hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, | 2152 | hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, |
2113 | sizeof(cp), &cp); | 2153 | sizeof(cp), &cp); |
2154 | } else { | ||
2155 | conn->state = BT_CONNECT2; | ||
2156 | hci_proto_connect_cfm(conn, 0); | ||
2157 | hci_conn_put(conn); | ||
2114 | } | 2158 | } |
2115 | } else { | 2159 | } else { |
2116 | /* Connection rejected */ | 2160 | /* Connection rejected */ |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b52f66d22437..2c78208d793e 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -53,8 +53,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
53 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, | 53 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, |
54 | void *data); | 54 | void *data); |
55 | static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); | 55 | static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); |
56 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, | 56 | static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); |
57 | struct l2cap_chan *chan, int err); | ||
58 | 57 | ||
59 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | 58 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, |
60 | struct sk_buff_head *skbs, u8 event); | 59 | struct sk_buff_head *skbs, u8 event); |
@@ -632,7 +631,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
632 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && | 631 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
633 | conn->hcon->type == ACL_LINK) { | 632 | conn->hcon->type == ACL_LINK) { |
634 | __set_chan_timer(chan, sk->sk_sndtimeo); | 633 | __set_chan_timer(chan, sk->sk_sndtimeo); |
635 | l2cap_send_disconn_req(conn, chan, reason); | 634 | l2cap_send_disconn_req(chan, reason); |
636 | } else | 635 | } else |
637 | l2cap_chan_del(chan, reason); | 636 | l2cap_chan_del(chan, reason); |
638 | break; | 637 | break; |
@@ -1014,6 +1013,7 @@ static bool __amp_capable(struct l2cap_chan *chan) | |||
1014 | struct l2cap_conn *conn = chan->conn; | 1013 | struct l2cap_conn *conn = chan->conn; |
1015 | 1014 | ||
1016 | if (enable_hs && | 1015 | if (enable_hs && |
1016 | hci_amp_capable() && | ||
1017 | chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && | 1017 | chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && |
1018 | conn->fixed_chan_mask & L2CAP_FC_A2MP) | 1018 | conn->fixed_chan_mask & L2CAP_FC_A2MP) |
1019 | return true; | 1019 | return true; |
@@ -1180,10 +1180,10 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) | |||
1180 | } | 1180 | } |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, | 1183 | static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) |
1184 | struct l2cap_chan *chan, int err) | ||
1185 | { | 1184 | { |
1186 | struct sock *sk = chan->sk; | 1185 | struct sock *sk = chan->sk; |
1186 | struct l2cap_conn *conn = chan->conn; | ||
1187 | struct l2cap_disconn_req req; | 1187 | struct l2cap_disconn_req req; |
1188 | 1188 | ||
1189 | if (!conn) | 1189 | if (!conn) |
@@ -1960,7 +1960,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) | |||
1960 | if (chan->max_tx != 0 && | 1960 | if (chan->max_tx != 0 && |
1961 | bt_cb(skb)->control.retries > chan->max_tx) { | 1961 | bt_cb(skb)->control.retries > chan->max_tx) { |
1962 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); | 1962 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); |
1963 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 1963 | l2cap_send_disconn_req(chan, ECONNRESET); |
1964 | l2cap_seq_list_clear(&chan->retrans_list); | 1964 | l2cap_seq_list_clear(&chan->retrans_list); |
1965 | break; | 1965 | break; |
1966 | } | 1966 | } |
@@ -2666,7 +2666,7 @@ static void l2cap_tx_state_wait_f(struct l2cap_chan *chan, | |||
2666 | __set_monitor_timer(chan); | 2666 | __set_monitor_timer(chan); |
2667 | chan->retry_count++; | 2667 | chan->retry_count++; |
2668 | } else { | 2668 | } else { |
2669 | l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); | 2669 | l2cap_send_disconn_req(chan, ECONNABORTED); |
2670 | } | 2670 | } |
2671 | break; | 2671 | break; |
2672 | default: | 2672 | default: |
@@ -3106,18 +3106,17 @@ done: | |||
3106 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) | 3106 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) |
3107 | l2cap_add_opt_efs(&ptr, chan); | 3107 | l2cap_add_opt_efs(&ptr, chan); |
3108 | 3108 | ||
3109 | if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) | ||
3110 | break; | ||
3111 | |||
3112 | if (chan->fcs == L2CAP_FCS_NONE || | ||
3113 | test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | ||
3114 | chan->fcs = L2CAP_FCS_NONE; | ||
3115 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); | ||
3116 | } | ||
3117 | |||
3118 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | 3109 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) |
3119 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, | 3110 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, |
3120 | chan->tx_win); | 3111 | chan->tx_win); |
3112 | |||
3113 | if (chan->conn->feat_mask & L2CAP_FEAT_FCS) | ||
3114 | if (chan->fcs == L2CAP_FCS_NONE || | ||
3115 | test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { | ||
3116 | chan->fcs = L2CAP_FCS_NONE; | ||
3117 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, | ||
3118 | chan->fcs); | ||
3119 | } | ||
3121 | break; | 3120 | break; |
3122 | 3121 | ||
3123 | case L2CAP_MODE_STREAMING: | 3122 | case L2CAP_MODE_STREAMING: |
@@ -3139,14 +3138,13 @@ done: | |||
3139 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) | 3138 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) |
3140 | l2cap_add_opt_efs(&ptr, chan); | 3139 | l2cap_add_opt_efs(&ptr, chan); |
3141 | 3140 | ||
3142 | if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS)) | 3141 | if (chan->conn->feat_mask & L2CAP_FEAT_FCS) |
3143 | break; | 3142 | if (chan->fcs == L2CAP_FCS_NONE || |
3144 | 3143 | test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { | |
3145 | if (chan->fcs == L2CAP_FCS_NONE || | 3144 | chan->fcs = L2CAP_FCS_NONE; |
3146 | test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | 3145 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, |
3147 | chan->fcs = L2CAP_FCS_NONE; | 3146 | chan->fcs); |
3148 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); | 3147 | } |
3149 | } | ||
3150 | break; | 3148 | break; |
3151 | } | 3149 | } |
3152 | 3150 | ||
@@ -3198,7 +3196,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) | |||
3198 | 3196 | ||
3199 | case L2CAP_CONF_FCS: | 3197 | case L2CAP_CONF_FCS: |
3200 | if (val == L2CAP_FCS_NONE) | 3198 | if (val == L2CAP_FCS_NONE) |
3201 | set_bit(CONF_NO_FCS_RECV, &chan->conf_state); | 3199 | set_bit(CONF_RECV_NO_FCS, &chan->conf_state); |
3202 | break; | 3200 | break; |
3203 | 3201 | ||
3204 | case L2CAP_CONF_EFS: | 3202 | case L2CAP_CONF_EFS: |
@@ -3433,6 +3431,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, | |||
3433 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), | 3431 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), |
3434 | (unsigned long) &efs); | 3432 | (unsigned long) &efs); |
3435 | break; | 3433 | break; |
3434 | |||
3435 | case L2CAP_CONF_FCS: | ||
3436 | if (*result == L2CAP_CONF_PENDING) | ||
3437 | if (val == L2CAP_FCS_NONE) | ||
3438 | set_bit(CONF_RECV_NO_FCS, | ||
3439 | &chan->conf_state); | ||
3440 | break; | ||
3436 | } | 3441 | } |
3437 | } | 3442 | } |
3438 | 3443 | ||
@@ -3802,7 +3807,7 @@ static inline void set_default_fcs(struct l2cap_chan *chan) | |||
3802 | */ | 3807 | */ |
3803 | if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) | 3808 | if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING) |
3804 | chan->fcs = L2CAP_FCS_NONE; | 3809 | chan->fcs = L2CAP_FCS_NONE; |
3805 | else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) | 3810 | else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) |
3806 | chan->fcs = L2CAP_FCS_CRC16; | 3811 | chan->fcs = L2CAP_FCS_CRC16; |
3807 | } | 3812 | } |
3808 | 3813 | ||
@@ -3877,7 +3882,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, | |||
3877 | /* Complete config. */ | 3882 | /* Complete config. */ |
3878 | len = l2cap_parse_conf_req(chan, rsp); | 3883 | len = l2cap_parse_conf_req(chan, rsp); |
3879 | if (len < 0) { | 3884 | if (len < 0) { |
3880 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 3885 | l2cap_send_disconn_req(chan, ECONNRESET); |
3881 | goto unlock; | 3886 | goto unlock; |
3882 | } | 3887 | } |
3883 | 3888 | ||
@@ -3899,7 +3904,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, | |||
3899 | err = l2cap_ertm_init(chan); | 3904 | err = l2cap_ertm_init(chan); |
3900 | 3905 | ||
3901 | if (err < 0) | 3906 | if (err < 0) |
3902 | l2cap_send_disconn_req(chan->conn, chan, -err); | 3907 | l2cap_send_disconn_req(chan, -err); |
3903 | else | 3908 | else |
3904 | l2cap_chan_ready(chan); | 3909 | l2cap_chan_ready(chan); |
3905 | 3910 | ||
@@ -3967,7 +3972,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, | |||
3967 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, | 3972 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, |
3968 | buf, &result); | 3973 | buf, &result); |
3969 | if (len < 0) { | 3974 | if (len < 0) { |
3970 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 3975 | l2cap_send_disconn_req(chan, ECONNRESET); |
3971 | goto done; | 3976 | goto done; |
3972 | } | 3977 | } |
3973 | 3978 | ||
@@ -3988,7 +3993,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, | |||
3988 | char req[64]; | 3993 | char req[64]; |
3989 | 3994 | ||
3990 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { | 3995 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { |
3991 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 3996 | l2cap_send_disconn_req(chan, ECONNRESET); |
3992 | goto done; | 3997 | goto done; |
3993 | } | 3998 | } |
3994 | 3999 | ||
@@ -3997,7 +4002,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, | |||
3997 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, | 4002 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, |
3998 | req, &result); | 4003 | req, &result); |
3999 | if (len < 0) { | 4004 | if (len < 0) { |
4000 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 4005 | l2cap_send_disconn_req(chan, ECONNRESET); |
4001 | goto done; | 4006 | goto done; |
4002 | } | 4007 | } |
4003 | 4008 | ||
@@ -4013,7 +4018,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, | |||
4013 | l2cap_chan_set_err(chan, ECONNRESET); | 4018 | l2cap_chan_set_err(chan, ECONNRESET); |
4014 | 4019 | ||
4015 | __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); | 4020 | __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); |
4016 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 4021 | l2cap_send_disconn_req(chan, ECONNRESET); |
4017 | goto done; | 4022 | goto done; |
4018 | } | 4023 | } |
4019 | 4024 | ||
@@ -4030,7 +4035,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, | |||
4030 | err = l2cap_ertm_init(chan); | 4035 | err = l2cap_ertm_init(chan); |
4031 | 4036 | ||
4032 | if (err < 0) | 4037 | if (err < 0) |
4033 | l2cap_send_disconn_req(chan->conn, chan, -err); | 4038 | l2cap_send_disconn_req(chan, -err); |
4034 | else | 4039 | else |
4035 | l2cap_chan_ready(chan); | 4040 | l2cap_chan_ready(chan); |
4036 | } | 4041 | } |
@@ -4392,7 +4397,7 @@ static void l2cap_logical_fail(struct l2cap_chan *chan) | |||
4392 | /* Logical link setup failed */ | 4397 | /* Logical link setup failed */ |
4393 | if (chan->state != BT_CONNECTED) { | 4398 | if (chan->state != BT_CONNECTED) { |
4394 | /* Create channel failure, disconnect */ | 4399 | /* Create channel failure, disconnect */ |
4395 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 4400 | l2cap_send_disconn_req(chan, ECONNRESET); |
4396 | return; | 4401 | return; |
4397 | } | 4402 | } |
4398 | 4403 | ||
@@ -4435,7 +4440,7 @@ static void l2cap_logical_finish_create(struct l2cap_chan *chan, | |||
4435 | 4440 | ||
4436 | err = l2cap_ertm_init(chan); | 4441 | err = l2cap_ertm_init(chan); |
4437 | if (err < 0) | 4442 | if (err < 0) |
4438 | l2cap_send_disconn_req(chan->conn, chan, -err); | 4443 | l2cap_send_disconn_req(chan, -err); |
4439 | else | 4444 | else |
4440 | l2cap_chan_ready(chan); | 4445 | l2cap_chan_ready(chan); |
4441 | } | 4446 | } |
@@ -5400,7 +5405,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan, | |||
5400 | 5405 | ||
5401 | if (control->reqseq == chan->next_tx_seq) { | 5406 | if (control->reqseq == chan->next_tx_seq) { |
5402 | BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); | 5407 | BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); |
5403 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5408 | l2cap_send_disconn_req(chan, ECONNRESET); |
5404 | return; | 5409 | return; |
5405 | } | 5410 | } |
5406 | 5411 | ||
@@ -5414,7 +5419,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan, | |||
5414 | 5419 | ||
5415 | if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { | 5420 | if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { |
5416 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); | 5421 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); |
5417 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5422 | l2cap_send_disconn_req(chan, ECONNRESET); |
5418 | return; | 5423 | return; |
5419 | } | 5424 | } |
5420 | 5425 | ||
@@ -5458,7 +5463,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan, | |||
5458 | 5463 | ||
5459 | if (control->reqseq == chan->next_tx_seq) { | 5464 | if (control->reqseq == chan->next_tx_seq) { |
5460 | BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); | 5465 | BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); |
5461 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5466 | l2cap_send_disconn_req(chan, ECONNRESET); |
5462 | return; | 5467 | return; |
5463 | } | 5468 | } |
5464 | 5469 | ||
@@ -5467,7 +5472,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan, | |||
5467 | if (chan->max_tx && skb && | 5472 | if (chan->max_tx && skb && |
5468 | bt_cb(skb)->control.retries >= chan->max_tx) { | 5473 | bt_cb(skb)->control.retries >= chan->max_tx) { |
5469 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); | 5474 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); |
5470 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5475 | l2cap_send_disconn_req(chan, ECONNRESET); |
5471 | return; | 5476 | return; |
5472 | } | 5477 | } |
5473 | 5478 | ||
@@ -5651,8 +5656,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan, | |||
5651 | break; | 5656 | break; |
5652 | case L2CAP_TXSEQ_INVALID: | 5657 | case L2CAP_TXSEQ_INVALID: |
5653 | default: | 5658 | default: |
5654 | l2cap_send_disconn_req(chan->conn, chan, | 5659 | l2cap_send_disconn_req(chan, ECONNRESET); |
5655 | ECONNRESET); | ||
5656 | break; | 5660 | break; |
5657 | } | 5661 | } |
5658 | break; | 5662 | break; |
@@ -5785,8 +5789,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan, | |||
5785 | break; | 5789 | break; |
5786 | case L2CAP_TXSEQ_INVALID: | 5790 | case L2CAP_TXSEQ_INVALID: |
5787 | default: | 5791 | default: |
5788 | l2cap_send_disconn_req(chan->conn, chan, | 5792 | l2cap_send_disconn_req(chan, ECONNRESET); |
5789 | ECONNRESET); | ||
5790 | break; | 5793 | break; |
5791 | } | 5794 | } |
5792 | break; | 5795 | break; |
@@ -5981,7 +5984,7 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | |||
5981 | BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", | 5984 | BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d", |
5982 | control->reqseq, chan->next_tx_seq, | 5985 | control->reqseq, chan->next_tx_seq, |
5983 | chan->expected_ack_seq); | 5986 | chan->expected_ack_seq); |
5984 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 5987 | l2cap_send_disconn_req(chan, ECONNRESET); |
5985 | } | 5988 | } |
5986 | 5989 | ||
5987 | return err; | 5990 | return err; |
@@ -6050,7 +6053,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | |||
6050 | len -= L2CAP_FCS_SIZE; | 6053 | len -= L2CAP_FCS_SIZE; |
6051 | 6054 | ||
6052 | if (len > chan->mps) { | 6055 | if (len > chan->mps) { |
6053 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 6056 | l2cap_send_disconn_req(chan, ECONNRESET); |
6054 | goto drop; | 6057 | goto drop; |
6055 | } | 6058 | } |
6056 | 6059 | ||
@@ -6075,8 +6078,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | |||
6075 | } | 6078 | } |
6076 | 6079 | ||
6077 | if (err) | 6080 | if (err) |
6078 | l2cap_send_disconn_req(chan->conn, chan, | 6081 | l2cap_send_disconn_req(chan, ECONNRESET); |
6079 | ECONNRESET); | ||
6080 | } else { | 6082 | } else { |
6081 | const u8 rx_func_to_event[4] = { | 6083 | const u8 rx_func_to_event[4] = { |
6082 | L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, | 6084 | L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ, |
@@ -6093,7 +6095,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | |||
6093 | 6095 | ||
6094 | if (len != 0) { | 6096 | if (len != 0) { |
6095 | BT_ERR("Trailing bytes: %d in sframe", len); | 6097 | BT_ERR("Trailing bytes: %d in sframe", len); |
6096 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 6098 | l2cap_send_disconn_req(chan, ECONNRESET); |
6097 | goto drop; | 6099 | goto drop; |
6098 | } | 6100 | } |
6099 | 6101 | ||
@@ -6104,7 +6106,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | |||
6104 | 6106 | ||
6105 | event = rx_func_to_event[control->super]; | 6107 | event = rx_func_to_event[control->super]; |
6106 | if (l2cap_rx(chan, control, skb, event)) | 6108 | if (l2cap_rx(chan, control, skb, event)) |
6107 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | 6109 | l2cap_send_disconn_req(chan, ECONNRESET); |
6108 | } | 6110 | } |
6109 | 6111 | ||
6110 | return 0; | 6112 | return 0; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 142764aec2af..f559b966279c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1226,7 +1226,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1226 | } | 1226 | } |
1227 | 1227 | ||
1228 | val = !!cp->val; | 1228 | val = !!cp->val; |
1229 | enabled = !!lmp_host_le_capable(hdev); | 1229 | enabled = lmp_host_le_capable(hdev); |
1230 | 1230 | ||
1231 | if (!hdev_is_powered(hdev) || val == enabled) { | 1231 | if (!hdev_is_powered(hdev) || val == enabled) { |
1232 | bool changed = false; | 1232 | bool changed = false; |
@@ -1262,7 +1262,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1262 | 1262 | ||
1263 | if (val) { | 1263 | if (val) { |
1264 | hci_cp.le = val; | 1264 | hci_cp.le = val; |
1265 | hci_cp.simul = !!lmp_le_br_capable(hdev); | 1265 | hci_cp.simul = lmp_le_br_capable(hdev); |
1266 | } | 1266 | } |
1267 | 1267 | ||
1268 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), | 1268 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), |
@@ -2926,13 +2926,13 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2926 | struct hci_cp_write_le_host_supported cp; | 2926 | struct hci_cp_write_le_host_supported cp; |
2927 | 2927 | ||
2928 | cp.le = 1; | 2928 | cp.le = 1; |
2929 | cp.simul = !!lmp_le_br_capable(hdev); | 2929 | cp.simul = lmp_le_br_capable(hdev); |
2930 | 2930 | ||
2931 | /* Check first if we already have the right | 2931 | /* Check first if we already have the right |
2932 | * host state (host features set) | 2932 | * host state (host features set) |
2933 | */ | 2933 | */ |
2934 | if (cp.le != !!lmp_host_le_capable(hdev) || | 2934 | if (cp.le != lmp_host_le_capable(hdev) || |
2935 | cp.simul != !!lmp_host_le_br_capable(hdev)) | 2935 | cp.simul != lmp_host_le_br_capable(hdev)) |
2936 | hci_send_cmd(hdev, | 2936 | hci_send_cmd(hdev, |
2937 | HCI_OP_WRITE_LE_HOST_SUPPORTED, | 2937 | HCI_OP_WRITE_LE_HOST_SUPPORTED, |
2938 | sizeof(cp), &cp); | 2938 | sizeof(cp), &cp); |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 4ddef57d03a7..ce3f6658f4b2 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -467,7 +467,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
467 | long timeo; | 467 | long timeo; |
468 | int err = 0; | 468 | int err = 0; |
469 | 469 | ||
470 | lock_sock(sk); | 470 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); |
471 | 471 | ||
472 | if (sk->sk_type != SOCK_STREAM) { | 472 | if (sk->sk_type != SOCK_STREAM) { |
473 | err = -EINVAL; | 473 | err = -EINVAL; |
@@ -504,7 +504,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
504 | 504 | ||
505 | release_sock(sk); | 505 | release_sock(sk); |
506 | timeo = schedule_timeout(timeo); | 506 | timeo = schedule_timeout(timeo); |
507 | lock_sock(sk); | 507 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); |
508 | } | 508 | } |
509 | __set_current_state(TASK_RUNNING); | 509 | __set_current_state(TASK_RUNNING); |
510 | remove_wait_queue(sk_sleep(sk), &wait); | 510 | remove_wait_queue(sk_sleep(sk), &wait); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 450cdcd88e5c..531a93d613d4 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -131,15 +131,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err) | |||
131 | sco_sock_clear_timer(sk); | 131 | sco_sock_clear_timer(sk); |
132 | sco_chan_del(sk, err); | 132 | sco_chan_del(sk, err); |
133 | bh_unlock_sock(sk); | 133 | bh_unlock_sock(sk); |
134 | |||
135 | sco_conn_lock(conn); | ||
136 | conn->sk = NULL; | ||
137 | sco_pi(sk)->conn = NULL; | ||
138 | sco_conn_unlock(conn); | ||
139 | |||
140 | if (conn->hcon) | ||
141 | hci_conn_put(conn->hcon); | ||
142 | |||
143 | sco_sock_kill(sk); | 134 | sco_sock_kill(sk); |
144 | } | 135 | } |
145 | 136 | ||
@@ -397,6 +388,7 @@ static void sco_sock_init(struct sock *sk, struct sock *parent) | |||
397 | 388 | ||
398 | if (parent) { | 389 | if (parent) { |
399 | sk->sk_type = parent->sk_type; | 390 | sk->sk_type = parent->sk_type; |
391 | bt_sk(sk)->flags = bt_sk(parent)->flags; | ||
400 | security_sk_clone(parent, sk); | 392 | security_sk_clone(parent, sk); |
401 | } | 393 | } |
402 | } | 394 | } |
@@ -662,16 +654,57 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
662 | return err; | 654 | return err; |
663 | } | 655 | } |
664 | 656 | ||
657 | static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
658 | struct msghdr *msg, size_t len, int flags) | ||
659 | { | ||
660 | struct sock *sk = sock->sk; | ||
661 | struct sco_pinfo *pi = sco_pi(sk); | ||
662 | |||
663 | lock_sock(sk); | ||
664 | |||
665 | if (sk->sk_state == BT_CONNECT2 && | ||
666 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { | ||
667 | hci_conn_accept(pi->conn->hcon, 0); | ||
668 | sk->sk_state = BT_CONFIG; | ||
669 | |||
670 | release_sock(sk); | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | release_sock(sk); | ||
675 | |||
676 | return bt_sock_recvmsg(iocb, sock, msg, len, flags); | ||
677 | } | ||
678 | |||
665 | static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) | 679 | static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) |
666 | { | 680 | { |
667 | struct sock *sk = sock->sk; | 681 | struct sock *sk = sock->sk; |
668 | int err = 0; | 682 | int err = 0; |
683 | u32 opt; | ||
669 | 684 | ||
670 | BT_DBG("sk %p", sk); | 685 | BT_DBG("sk %p", sk); |
671 | 686 | ||
672 | lock_sock(sk); | 687 | lock_sock(sk); |
673 | 688 | ||
674 | switch (optname) { | 689 | switch (optname) { |
690 | |||
691 | case BT_DEFER_SETUP: | ||
692 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { | ||
693 | err = -EINVAL; | ||
694 | break; | ||
695 | } | ||
696 | |||
697 | if (get_user(opt, (u32 __user *) optval)) { | ||
698 | err = -EFAULT; | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | if (opt) | ||
703 | set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); | ||
704 | else | ||
705 | clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); | ||
706 | break; | ||
707 | |||
675 | default: | 708 | default: |
676 | err = -ENOPROTOOPT; | 709 | err = -ENOPROTOOPT; |
677 | break; | 710 | break; |
@@ -753,6 +786,19 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char | |||
753 | lock_sock(sk); | 786 | lock_sock(sk); |
754 | 787 | ||
755 | switch (optname) { | 788 | switch (optname) { |
789 | |||
790 | case BT_DEFER_SETUP: | ||
791 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { | ||
792 | err = -EINVAL; | ||
793 | break; | ||
794 | } | ||
795 | |||
796 | if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags), | ||
797 | (u32 __user *) optval)) | ||
798 | err = -EFAULT; | ||
799 | |||
800 | break; | ||
801 | |||
756 | default: | 802 | default: |
757 | err = -ENOPROTOOPT; | 803 | err = -ENOPROTOOPT; |
758 | break; | 804 | break; |
@@ -830,6 +876,16 @@ static void sco_chan_del(struct sock *sk, int err) | |||
830 | 876 | ||
831 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); | 877 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); |
832 | 878 | ||
879 | if (conn) { | ||
880 | sco_conn_lock(conn); | ||
881 | conn->sk = NULL; | ||
882 | sco_pi(sk)->conn = NULL; | ||
883 | sco_conn_unlock(conn); | ||
884 | |||
885 | if (conn->hcon) | ||
886 | hci_conn_put(conn->hcon); | ||
887 | } | ||
888 | |||
833 | sk->sk_state = BT_CLOSED; | 889 | sk->sk_state = BT_CLOSED; |
834 | sk->sk_err = err; | 890 | sk->sk_err = err; |
835 | sk->sk_state_change(sk); | 891 | sk->sk_state_change(sk); |
@@ -874,7 +930,10 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
874 | hci_conn_hold(conn->hcon); | 930 | hci_conn_hold(conn->hcon); |
875 | __sco_chan_add(conn, sk, parent); | 931 | __sco_chan_add(conn, sk, parent); |
876 | 932 | ||
877 | sk->sk_state = BT_CONNECTED; | 933 | if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) |
934 | sk->sk_state = BT_CONNECT2; | ||
935 | else | ||
936 | sk->sk_state = BT_CONNECTED; | ||
878 | 937 | ||
879 | /* Wake up parent */ | 938 | /* Wake up parent */ |
880 | parent->sk_data_ready(parent, 1); | 939 | parent->sk_data_ready(parent, 1); |
@@ -887,7 +946,7 @@ done: | |||
887 | } | 946 | } |
888 | 947 | ||
889 | /* ----- SCO interface with lower layer (HCI) ----- */ | 948 | /* ----- SCO interface with lower layer (HCI) ----- */ |
890 | int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | 949 | int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) |
891 | { | 950 | { |
892 | struct sock *sk; | 951 | struct sock *sk; |
893 | struct hlist_node *node; | 952 | struct hlist_node *node; |
@@ -904,6 +963,9 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
904 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || | 963 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || |
905 | !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { | 964 | !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { |
906 | lm |= HCI_LM_ACCEPT; | 965 | lm |= HCI_LM_ACCEPT; |
966 | |||
967 | if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) | ||
968 | *flags |= HCI_PROTO_DEFER; | ||
907 | break; | 969 | break; |
908 | } | 970 | } |
909 | } | 971 | } |
@@ -992,7 +1054,7 @@ static const struct proto_ops sco_sock_ops = { | |||
992 | .accept = sco_sock_accept, | 1054 | .accept = sco_sock_accept, |
993 | .getname = sco_sock_getname, | 1055 | .getname = sco_sock_getname, |
994 | .sendmsg = sco_sock_sendmsg, | 1056 | .sendmsg = sco_sock_sendmsg, |
995 | .recvmsg = bt_sock_recvmsg, | 1057 | .recvmsg = sco_sock_recvmsg, |
996 | .poll = bt_sock_poll, | 1058 | .poll = bt_sock_poll, |
997 | .ioctl = bt_sock_ioctl, | 1059 | .ioctl = bt_sock_ioctl, |
998 | .mmap = sock_no_mmap, | 1060 | .mmap = sock_no_mmap, |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 4965aa6424ec..5c61677487cf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -398,6 +398,38 @@ void sta_set_rate_info_tx(struct sta_info *sta, | |||
398 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 398 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
399 | } | 399 | } |
400 | 400 | ||
401 | void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | ||
402 | { | ||
403 | rinfo->flags = 0; | ||
404 | |||
405 | if (sta->last_rx_rate_flag & RX_FLAG_HT) { | ||
406 | rinfo->flags |= RATE_INFO_FLAGS_MCS; | ||
407 | rinfo->mcs = sta->last_rx_rate_idx; | ||
408 | } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) { | ||
409 | rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
410 | rinfo->nss = sta->last_rx_rate_vht_nss; | ||
411 | rinfo->mcs = sta->last_rx_rate_idx; | ||
412 | } else { | ||
413 | struct ieee80211_supported_band *sband; | ||
414 | |||
415 | sband = sta->local->hw.wiphy->bands[ | ||
416 | ieee80211_get_sdata_band(sta->sdata)]; | ||
417 | rinfo->legacy = | ||
418 | sband->bitrates[sta->last_rx_rate_idx].bitrate; | ||
419 | } | ||
420 | |||
421 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | ||
422 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
423 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | ||
424 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
425 | if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) | ||
426 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
427 | if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) | ||
428 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | ||
429 | if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) | ||
430 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
431 | } | ||
432 | |||
401 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 433 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
402 | { | 434 | { |
403 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 435 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -444,34 +476,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
444 | } | 476 | } |
445 | 477 | ||
446 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); | 478 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); |
447 | 479 | sta_set_rate_info_rx(sta, &sinfo->rxrate); | |
448 | sinfo->rxrate.flags = 0; | ||
449 | if (sta->last_rx_rate_flag & RX_FLAG_HT) { | ||
450 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; | ||
451 | sinfo->rxrate.mcs = sta->last_rx_rate_idx; | ||
452 | } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) { | ||
453 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
454 | sinfo->rxrate.nss = sta->last_rx_rate_vht_nss; | ||
455 | sinfo->rxrate.mcs = sta->last_rx_rate_idx; | ||
456 | } else { | ||
457 | struct ieee80211_supported_band *sband; | ||
458 | |||
459 | sband = sta->local->hw.wiphy->bands[ | ||
460 | ieee80211_get_sdata_band(sta->sdata)]; | ||
461 | sinfo->rxrate.legacy = | ||
462 | sband->bitrates[sta->last_rx_rate_idx].bitrate; | ||
463 | } | ||
464 | |||
465 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | ||
466 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
467 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | ||
468 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
469 | if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) | ||
470 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
471 | if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) | ||
472 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | ||
473 | if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) | ||
474 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
475 | 480 | ||
476 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 481 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
477 | #ifdef CONFIG_MAC80211_MESH | 482 | #ifdef CONFIG_MAC80211_MESH |
@@ -893,7 +898,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
893 | u32 changed = BSS_CHANGED_BEACON_INT | | 898 | u32 changed = BSS_CHANGED_BEACON_INT | |
894 | BSS_CHANGED_BEACON_ENABLED | | 899 | BSS_CHANGED_BEACON_ENABLED | |
895 | BSS_CHANGED_BEACON | | 900 | BSS_CHANGED_BEACON | |
896 | BSS_CHANGED_SSID; | 901 | BSS_CHANGED_SSID | |
902 | BSS_CHANGED_P2P_PS; | ||
897 | int err; | 903 | int err; |
898 | 904 | ||
899 | old = rtnl_dereference(sdata->u.ap.beacon); | 905 | old = rtnl_dereference(sdata->u.ap.beacon); |
@@ -932,6 +938,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
932 | sdata->vif.bss_conf.hidden_ssid = | 938 | sdata->vif.bss_conf.hidden_ssid = |
933 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); | 939 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); |
934 | 940 | ||
941 | sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow; | ||
942 | sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps; | ||
943 | |||
935 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); | 944 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); |
936 | if (err < 0) | 945 | if (err < 0) |
937 | return err; | 946 | return err; |
@@ -1807,6 +1816,16 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1807 | changed |= BSS_CHANGED_HT; | 1816 | changed |= BSS_CHANGED_HT; |
1808 | } | 1817 | } |
1809 | 1818 | ||
1819 | if (params->p2p_ctwindow >= 0) { | ||
1820 | sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow; | ||
1821 | changed |= BSS_CHANGED_P2P_PS; | ||
1822 | } | ||
1823 | |||
1824 | if (params->p2p_opp_ps >= 0) { | ||
1825 | sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps; | ||
1826 | changed |= BSS_CHANGED_P2P_PS; | ||
1827 | } | ||
1828 | |||
1810 | ieee80211_bss_info_change_notify(sdata, changed); | 1829 | ieee80211_bss_info_change_notify(sdata, changed); |
1811 | 1830 | ||
1812 | return 0; | 1831 | return 0; |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 89281d24b094..49a1c70bbd70 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -53,6 +53,7 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
53 | STA_FILE(aid, sta.aid, D); | 53 | STA_FILE(aid, sta.aid, D); |
54 | STA_FILE(dev, sdata->name, S); | 54 | STA_FILE(dev, sdata->name, S); |
55 | STA_FILE(last_signal, last_signal, D); | 55 | STA_FILE(last_signal, last_signal, D); |
56 | STA_FILE(last_ack_signal, last_ack_signal, D); | ||
56 | 57 | ||
57 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 58 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
58 | size_t count, loff_t *ppos) | 59 | size_t count, loff_t *ppos) |
@@ -321,6 +322,38 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
321 | } | 322 | } |
322 | STA_OPS(ht_capa); | 323 | STA_OPS(ht_capa); |
323 | 324 | ||
325 | static ssize_t sta_current_tx_rate_read(struct file *file, char __user *userbuf, | ||
326 | size_t count, loff_t *ppos) | ||
327 | { | ||
328 | struct sta_info *sta = file->private_data; | ||
329 | struct rate_info rinfo; | ||
330 | u16 rate; | ||
331 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo); | ||
332 | rate = cfg80211_calculate_bitrate(&rinfo); | ||
333 | |||
334 | return mac80211_format_buffer(userbuf, count, ppos, | ||
335 | "%d.%d MBit/s\n", | ||
336 | rate/10, rate%10); | ||
337 | } | ||
338 | STA_OPS(current_tx_rate); | ||
339 | |||
340 | static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf, | ||
341 | size_t count, loff_t *ppos) | ||
342 | { | ||
343 | struct sta_info *sta = file->private_data; | ||
344 | struct rate_info rinfo; | ||
345 | u16 rate; | ||
346 | |||
347 | sta_set_rate_info_rx(sta, &rinfo); | ||
348 | |||
349 | rate = cfg80211_calculate_bitrate(&rinfo); | ||
350 | |||
351 | return mac80211_format_buffer(userbuf, count, ppos, | ||
352 | "%d.%d MBit/s\n", | ||
353 | rate/10, rate%10); | ||
354 | } | ||
355 | STA_OPS(last_rx_rate); | ||
356 | |||
324 | #define DEBUGFS_ADD(name) \ | 357 | #define DEBUGFS_ADD(name) \ |
325 | debugfs_create_file(#name, 0400, \ | 358 | debugfs_create_file(#name, 0400, \ |
326 | sta->debugfs.dir, sta, &sta_ ##name## _ops); | 359 | sta->debugfs.dir, sta, &sta_ ##name## _ops); |
@@ -369,6 +402,9 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
369 | DEBUGFS_ADD(dev); | 402 | DEBUGFS_ADD(dev); |
370 | DEBUGFS_ADD(last_signal); | 403 | DEBUGFS_ADD(last_signal); |
371 | DEBUGFS_ADD(ht_capa); | 404 | DEBUGFS_ADD(ht_capa); |
405 | DEBUGFS_ADD(last_ack_signal); | ||
406 | DEBUGFS_ADD(current_tx_rate); | ||
407 | DEBUGFS_ADD(last_rx_rate); | ||
372 | 408 | ||
373 | DEBUGFS_ADD_COUNTER(rx_packets, rx_packets); | 409 | DEBUGFS_ADD_COUNTER(rx_packets, rx_packets); |
374 | DEBUGFS_ADD_COUNTER(tx_packets, tx_packets); | 410 | DEBUGFS_ADD_COUNTER(tx_packets, tx_packets); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5c0d5a6946c1..42d0d0267730 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -371,6 +371,8 @@ enum ieee80211_sta_flags { | |||
371 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | 371 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), |
372 | IEEE80211_STA_DISABLE_40MHZ = BIT(10), | 372 | IEEE80211_STA_DISABLE_40MHZ = BIT(10), |
373 | IEEE80211_STA_DISABLE_VHT = BIT(11), | 373 | IEEE80211_STA_DISABLE_VHT = BIT(11), |
374 | IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), | ||
375 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), | ||
374 | }; | 376 | }; |
375 | 377 | ||
376 | struct ieee80211_mgd_auth_data { | 378 | struct ieee80211_mgd_auth_data { |
@@ -1032,6 +1034,7 @@ struct ieee80211_local { | |||
1032 | enum ieee80211_band hw_scan_band; | 1034 | enum ieee80211_band hw_scan_band; |
1033 | int scan_channel_idx; | 1035 | int scan_channel_idx; |
1034 | int scan_ies_len; | 1036 | int scan_ies_len; |
1037 | int hw_scan_ies_bufsize; | ||
1035 | 1038 | ||
1036 | struct work_struct sched_scan_stopped_work; | 1039 | struct work_struct sched_scan_stopped_work; |
1037 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; | 1040 | struct ieee80211_sub_if_data __rcu *sched_scan_sdata; |
@@ -1573,7 +1576,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1573 | const u8 *bssid, u16 stype, u16 reason, | 1576 | const u8 *bssid, u16 stype, u16 reason, |
1574 | bool send_frame, u8 *frame_buf); | 1577 | bool send_frame, u8 *frame_buf); |
1575 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1578 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1576 | const u8 *ie, size_t ie_len, | 1579 | size_t buffer_len, const u8 *ie, size_t ie_len, |
1577 | enum ieee80211_band band, u32 rate_mask, | 1580 | enum ieee80211_band band, u32 rate_mask, |
1578 | u8 channel); | 1581 | u8 channel); |
1579 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1582 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 5331662489f7..40c36d5d7377 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -223,6 +223,47 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) | ||
227 | { | ||
228 | struct ieee80211_sub_if_data *sdata; | ||
229 | u64 new, mask, tmp; | ||
230 | u8 *m; | ||
231 | int ret = 0; | ||
232 | |||
233 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask)) | ||
234 | return 0; | ||
235 | |||
236 | m = addr; | ||
237 | new = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | ||
238 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | ||
239 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | ||
240 | |||
241 | m = local->hw.wiphy->addr_mask; | ||
242 | mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | ||
243 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | ||
244 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | ||
245 | |||
246 | |||
247 | mutex_lock(&local->iflist_mtx); | ||
248 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
249 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) | ||
250 | continue; | ||
251 | |||
252 | m = sdata->vif.addr; | ||
253 | tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | | ||
254 | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | | ||
255 | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); | ||
256 | |||
257 | if ((new & ~mask) != (tmp & ~mask)) { | ||
258 | ret = -EINVAL; | ||
259 | break; | ||
260 | } | ||
261 | } | ||
262 | mutex_unlock(&local->iflist_mtx); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | |||
226 | static int ieee80211_change_mac(struct net_device *dev, void *addr) | 267 | static int ieee80211_change_mac(struct net_device *dev, void *addr) |
227 | { | 268 | { |
228 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 269 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -232,6 +273,10 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) | |||
232 | if (ieee80211_sdata_running(sdata)) | 273 | if (ieee80211_sdata_running(sdata)) |
233 | return -EBUSY; | 274 | return -EBUSY; |
234 | 275 | ||
276 | ret = ieee80211_verify_mac(sdata->local, sa->sa_data); | ||
277 | if (ret) | ||
278 | return ret; | ||
279 | |||
235 | ret = eth_mac_addr(dev, sa); | 280 | ret = eth_mac_addr(dev, sa); |
236 | 281 | ||
237 | if (ret == 0) | 282 | if (ret == 0) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f5e4c1f24bf2..1b087fff93e7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -474,7 +474,8 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
474 | .tx = 0xffff, | 474 | .tx = 0xffff, |
475 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | 475 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | |
476 | BIT(IEEE80211_STYPE_AUTH >> 4) | | 476 | BIT(IEEE80211_STYPE_AUTH >> 4) | |
477 | BIT(IEEE80211_STYPE_DEAUTH >> 4), | 477 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
478 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
478 | }, | 479 | }, |
479 | [NL80211_IFTYPE_STATION] = { | 480 | [NL80211_IFTYPE_STATION] = { |
480 | .tx = 0xffff, | 481 | .tx = 0xffff, |
@@ -638,6 +639,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
638 | local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | | 639 | local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | |
639 | IEEE80211_RADIOTAP_MCS_HAVE_GI | | 640 | IEEE80211_RADIOTAP_MCS_HAVE_GI | |
640 | IEEE80211_RADIOTAP_MCS_HAVE_BW; | 641 | IEEE80211_RADIOTAP_MCS_HAVE_BW; |
642 | local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | | ||
643 | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | ||
641 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; | 644 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
642 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | 645 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; |
643 | 646 | ||
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index ca52dfdd5375..4b274e9c91a5 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -391,7 +391,8 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
391 | sta->ch_width = chandef.width; | 391 | sta->ch_width = chandef.width; |
392 | } | 392 | } |
393 | 393 | ||
394 | rate_control_rate_init(sta); | 394 | if (insert) |
395 | rate_control_rate_init(sta); | ||
395 | spin_unlock_bh(&sta->lock); | 396 | spin_unlock_bh(&sta->lock); |
396 | 397 | ||
397 | if (insert && sta_info_insert(sta)) | 398 | if (insert && sta_info_insert(sta)) |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 0f40086cce18..aa8d1e437385 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -195,11 +195,15 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | |||
195 | ifmsh->sync_offset_clockdrift_max); | 195 | ifmsh->sync_offset_clockdrift_max); |
196 | set_bit(MESH_WORK_DRIFT_ADJUST, | 196 | set_bit(MESH_WORK_DRIFT_ADJUST, |
197 | &ifmsh->wrkq_flags); | 197 | &ifmsh->wrkq_flags); |
198 | |||
199 | ifmsh->adjusting_tbtt = true; | ||
198 | } else { | 200 | } else { |
199 | msync_dbg(sdata, | 201 | msync_dbg(sdata, |
200 | "TBTT : max clockdrift=%lld; too small to adjust\n", | 202 | "TBTT : max clockdrift=%lld; too small to adjust\n", |
201 | (long long)ifmsh->sync_offset_clockdrift_max); | 203 | (long long)ifmsh->sync_offset_clockdrift_max); |
202 | ifmsh->sync_offset_clockdrift_max = 0; | 204 | ifmsh->sync_offset_clockdrift_max = 0; |
205 | |||
206 | ifmsh->adjusting_tbtt = false; | ||
203 | } | 207 | } |
204 | spin_unlock_bh(&ifmsh->sync_offset_lock); | 208 | spin_unlock_bh(&ifmsh->sync_offset_lock); |
205 | } | 209 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d2a4f78b4b0f..09556303c7e1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -354,6 +354,16 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
354 | /* determine capability flags */ | 354 | /* determine capability flags */ |
355 | cap = vht_cap.cap; | 355 | cap = vht_cap.cap; |
356 | 356 | ||
357 | if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) { | ||
358 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; | ||
359 | cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
360 | } | ||
361 | |||
362 | if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) { | ||
363 | cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160; | ||
364 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
365 | } | ||
366 | |||
357 | /* reserve and fill IE */ | 367 | /* reserve and fill IE */ |
358 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); | 368 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); |
359 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | 369 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); |
@@ -543,6 +553,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
543 | offset = noffset; | 553 | offset = noffset; |
544 | } | 554 | } |
545 | 555 | ||
556 | if (WARN_ON_ONCE((ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | ||
557 | !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))) | ||
558 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
559 | |||
546 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) | 560 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
547 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 561 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
548 | sband, chan, sdata->smps_mode); | 562 | sband, chan, sdata->smps_mode); |
@@ -775,6 +789,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
775 | "not handling channel switch with channel contexts\n"); | 789 | "not handling channel switch with channel contexts\n"); |
776 | ieee80211_queue_work(&sdata->local->hw, | 790 | ieee80211_queue_work(&sdata->local->hw, |
777 | &ifmgd->csa_connection_drop_work); | 791 | &ifmgd->csa_connection_drop_work); |
792 | return; | ||
778 | } | 793 | } |
779 | 794 | ||
780 | mutex_lock(&sdata->local->chanctx_mtx); | 795 | mutex_lock(&sdata->local->chanctx_mtx); |
@@ -1368,19 +1383,26 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1368 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | 1383 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; |
1369 | 1384 | ||
1370 | if (sdata->vif.p2p) { | 1385 | if (sdata->vif.p2p) { |
1371 | u8 noa[2]; | 1386 | const struct cfg80211_bss_ies *ies; |
1372 | int ret; | ||
1373 | 1387 | ||
1374 | ret = cfg80211_get_p2p_attr(cbss->information_elements, | 1388 | rcu_read_lock(); |
1375 | cbss->len_information_elements, | 1389 | ies = rcu_dereference(cbss->ies); |
1376 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, | 1390 | if (ies) { |
1377 | noa, sizeof(noa)); | 1391 | u8 noa[2]; |
1378 | if (ret >= 2) { | 1392 | int ret; |
1379 | bss_conf->p2p_oppps = noa[1] & 0x80; | 1393 | |
1380 | bss_conf->p2p_ctwindow = noa[1] & 0x7f; | 1394 | ret = cfg80211_get_p2p_attr( |
1381 | bss_info_changed |= BSS_CHANGED_P2P_PS; | 1395 | ies->data, ies->len, |
1382 | sdata->u.mgd.p2p_noa_index = noa[0]; | 1396 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, |
1397 | noa, sizeof(noa)); | ||
1398 | if (ret >= 2) { | ||
1399 | bss_conf->p2p_oppps = noa[1] & 0x80; | ||
1400 | bss_conf->p2p_ctwindow = noa[1] & 0x7f; | ||
1401 | bss_info_changed |= BSS_CHANGED_P2P_PS; | ||
1402 | sdata->u.mgd.p2p_noa_index = noa[0]; | ||
1403 | } | ||
1383 | } | 1404 | } |
1405 | rcu_read_unlock(); | ||
1384 | } | 1406 | } |
1385 | 1407 | ||
1386 | /* just to be sure */ | 1408 | /* just to be sure */ |
@@ -1645,6 +1667,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1645 | } else { | 1667 | } else { |
1646 | int ssid_len; | 1668 | int ssid_len; |
1647 | 1669 | ||
1670 | rcu_read_lock(); | ||
1648 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1671 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1649 | if (WARN_ON_ONCE(ssid == NULL)) | 1672 | if (WARN_ON_ONCE(ssid == NULL)) |
1650 | ssid_len = 0; | 1673 | ssid_len = 0; |
@@ -1654,6 +1677,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1654 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, | 1677 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, |
1655 | 0, (u32) -1, true, false, | 1678 | 0, (u32) -1, true, false, |
1656 | ifmgd->associated->channel, false); | 1679 | ifmgd->associated->channel, false); |
1680 | rcu_read_unlock(); | ||
1657 | } | 1681 | } |
1658 | 1682 | ||
1659 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); | 1683 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
@@ -1749,6 +1773,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1749 | else | 1773 | else |
1750 | return NULL; | 1774 | return NULL; |
1751 | 1775 | ||
1776 | rcu_read_lock(); | ||
1752 | ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); | 1777 | ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); |
1753 | if (WARN_ON_ONCE(ssid == NULL)) | 1778 | if (WARN_ON_ONCE(ssid == NULL)) |
1754 | ssid_len = 0; | 1779 | ssid_len = 0; |
@@ -1759,6 +1784,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1759 | (u32) -1, cbss->channel, | 1784 | (u32) -1, cbss->channel, |
1760 | ssid + 2, ssid_len, | 1785 | ssid + 2, ssid_len, |
1761 | NULL, 0, true); | 1786 | NULL, 0, true); |
1787 | rcu_read_unlock(); | ||
1762 | 1788 | ||
1763 | return skb; | 1789 | return skb; |
1764 | } | 1790 | } |
@@ -2844,9 +2870,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2844 | auth_data->bss->bssid, auth_data->tries, | 2870 | auth_data->bss->bssid, auth_data->tries, |
2845 | IEEE80211_AUTH_MAX_TRIES); | 2871 | IEEE80211_AUTH_MAX_TRIES); |
2846 | 2872 | ||
2873 | rcu_read_lock(); | ||
2847 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); | 2874 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); |
2848 | if (!ssidie) | 2875 | if (!ssidie) { |
2876 | rcu_read_unlock(); | ||
2849 | return -EINVAL; | 2877 | return -EINVAL; |
2878 | } | ||
2850 | /* | 2879 | /* |
2851 | * Direct probe is sent to broadcast address as some APs | 2880 | * Direct probe is sent to broadcast address as some APs |
2852 | * will not answer to direct packet in unassociated state. | 2881 | * will not answer to direct packet in unassociated state. |
@@ -2854,6 +2883,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2854 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], | 2883 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], |
2855 | NULL, 0, (u32) -1, true, false, | 2884 | NULL, 0, (u32) -1, true, false, |
2856 | auth_data->bss->channel, false); | 2885 | auth_data->bss->channel, false); |
2886 | rcu_read_unlock(); | ||
2857 | } | 2887 | } |
2858 | 2888 | ||
2859 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 2889 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
@@ -3183,106 +3213,313 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
3183 | return 0; | 3213 | return 0; |
3184 | } | 3214 | } |
3185 | 3215 | ||
3216 | static u32 chandef_downgrade(struct cfg80211_chan_def *c) | ||
3217 | { | ||
3218 | u32 ret; | ||
3219 | int tmp; | ||
3220 | |||
3221 | switch (c->width) { | ||
3222 | case NL80211_CHAN_WIDTH_20: | ||
3223 | c->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
3224 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
3225 | break; | ||
3226 | case NL80211_CHAN_WIDTH_40: | ||
3227 | c->width = NL80211_CHAN_WIDTH_20; | ||
3228 | c->center_freq1 = c->chan->center_freq; | ||
3229 | ret = IEEE80211_STA_DISABLE_40MHZ | | ||
3230 | IEEE80211_STA_DISABLE_VHT; | ||
3231 | break; | ||
3232 | case NL80211_CHAN_WIDTH_80: | ||
3233 | tmp = (30 + c->chan->center_freq - c->center_freq1)/20; | ||
3234 | /* n_P40 */ | ||
3235 | tmp /= 2; | ||
3236 | /* freq_P40 */ | ||
3237 | c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; | ||
3238 | c->width = NL80211_CHAN_WIDTH_40; | ||
3239 | ret = IEEE80211_STA_DISABLE_VHT; | ||
3240 | break; | ||
3241 | case NL80211_CHAN_WIDTH_80P80: | ||
3242 | c->center_freq2 = 0; | ||
3243 | c->width = NL80211_CHAN_WIDTH_80; | ||
3244 | ret = IEEE80211_STA_DISABLE_80P80MHZ | | ||
3245 | IEEE80211_STA_DISABLE_160MHZ; | ||
3246 | break; | ||
3247 | case NL80211_CHAN_WIDTH_160: | ||
3248 | /* n_P20 */ | ||
3249 | tmp = (70 + c->chan->center_freq - c->center_freq1)/20; | ||
3250 | /* n_P80 */ | ||
3251 | tmp /= 4; | ||
3252 | c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; | ||
3253 | c->width = NL80211_CHAN_WIDTH_80; | ||
3254 | ret = IEEE80211_STA_DISABLE_80P80MHZ | | ||
3255 | IEEE80211_STA_DISABLE_160MHZ; | ||
3256 | break; | ||
3257 | default: | ||
3258 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
3259 | WARN_ON_ONCE(1); | ||
3260 | c->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
3261 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
3262 | break; | ||
3263 | } | ||
3264 | |||
3265 | WARN_ON_ONCE(!cfg80211_chandef_valid(c)); | ||
3266 | |||
3267 | return ret; | ||
3268 | } | ||
3269 | |||
3270 | static u32 | ||
3271 | ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | ||
3272 | struct ieee80211_supported_band *sband, | ||
3273 | struct ieee80211_channel *channel, | ||
3274 | const struct ieee80211_ht_operation *ht_oper, | ||
3275 | const struct ieee80211_vht_operation *vht_oper, | ||
3276 | struct cfg80211_chan_def *chandef) | ||
3277 | { | ||
3278 | struct cfg80211_chan_def vht_chandef; | ||
3279 | u32 ht_cfreq, ret; | ||
3280 | |||
3281 | chandef->chan = channel; | ||
3282 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
3283 | chandef->center_freq1 = channel->center_freq; | ||
3284 | chandef->center_freq2 = 0; | ||
3285 | |||
3286 | if (!ht_oper || !sband->ht_cap.ht_supported) { | ||
3287 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
3288 | goto out; | ||
3289 | } | ||
3290 | |||
3291 | chandef->width = NL80211_CHAN_WIDTH_20; | ||
3292 | |||
3293 | ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, | ||
3294 | channel->band); | ||
3295 | /* check that channel matches the right operating channel */ | ||
3296 | if (channel->center_freq != ht_cfreq) { | ||
3297 | /* | ||
3298 | * It's possible that some APs are confused here; | ||
3299 | * Netgear WNDR3700 sometimes reports 4 higher than | ||
3300 | * the actual channel in association responses, but | ||
3301 | * since we look at probe response/beacon data here | ||
3302 | * it should be OK. | ||
3303 | */ | ||
3304 | sdata_info(sdata, | ||
3305 | "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", | ||
3306 | channel->center_freq, ht_cfreq, | ||
3307 | ht_oper->primary_chan, channel->band); | ||
3308 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
3309 | goto out; | ||
3310 | } | ||
3311 | |||
3312 | /* check 40 MHz support, if we have it */ | ||
3313 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | ||
3314 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
3315 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
3316 | chandef->width = NL80211_CHAN_WIDTH_40; | ||
3317 | chandef->center_freq1 += 10; | ||
3318 | break; | ||
3319 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
3320 | chandef->width = NL80211_CHAN_WIDTH_40; | ||
3321 | chandef->center_freq1 -= 10; | ||
3322 | break; | ||
3323 | } | ||
3324 | } else { | ||
3325 | /* 40 MHz (and 80 MHz) must be supported for VHT */ | ||
3326 | ret = IEEE80211_STA_DISABLE_VHT; | ||
3327 | goto out; | ||
3328 | } | ||
3329 | |||
3330 | if (!vht_oper || !sband->vht_cap.vht_supported) { | ||
3331 | ret = IEEE80211_STA_DISABLE_VHT; | ||
3332 | goto out; | ||
3333 | } | ||
3334 | |||
3335 | vht_chandef.chan = channel; | ||
3336 | vht_chandef.center_freq1 = | ||
3337 | ieee80211_channel_to_frequency(vht_oper->center_freq_seg1_idx, | ||
3338 | channel->band); | ||
3339 | vht_chandef.center_freq2 = 0; | ||
3340 | |||
3341 | if (vht_oper->center_freq_seg2_idx) | ||
3342 | vht_chandef.center_freq2 = | ||
3343 | ieee80211_channel_to_frequency( | ||
3344 | vht_oper->center_freq_seg2_idx, | ||
3345 | channel->band); | ||
3346 | |||
3347 | switch (vht_oper->chan_width) { | ||
3348 | case IEEE80211_VHT_CHANWIDTH_USE_HT: | ||
3349 | vht_chandef.width = chandef->width; | ||
3350 | break; | ||
3351 | case IEEE80211_VHT_CHANWIDTH_80MHZ: | ||
3352 | vht_chandef.width = NL80211_CHAN_WIDTH_80; | ||
3353 | break; | ||
3354 | case IEEE80211_VHT_CHANWIDTH_160MHZ: | ||
3355 | vht_chandef.width = NL80211_CHAN_WIDTH_160; | ||
3356 | break; | ||
3357 | case IEEE80211_VHT_CHANWIDTH_80P80MHZ: | ||
3358 | vht_chandef.width = NL80211_CHAN_WIDTH_80P80; | ||
3359 | break; | ||
3360 | default: | ||
3361 | sdata_info(sdata, | ||
3362 | "AP VHT operation IE has invalid channel width (%d), disable VHT\n", | ||
3363 | vht_oper->chan_width); | ||
3364 | ret = IEEE80211_STA_DISABLE_VHT; | ||
3365 | goto out; | ||
3366 | } | ||
3367 | |||
3368 | if (!cfg80211_chandef_valid(&vht_chandef)) { | ||
3369 | sdata_info(sdata, | ||
3370 | "AP VHT information is invalid, disable VHT\n"); | ||
3371 | ret = IEEE80211_STA_DISABLE_VHT; | ||
3372 | goto out; | ||
3373 | } | ||
3374 | |||
3375 | if (cfg80211_chandef_identical(chandef, &vht_chandef)) { | ||
3376 | ret = 0; | ||
3377 | goto out; | ||
3378 | } | ||
3379 | |||
3380 | if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { | ||
3381 | sdata_info(sdata, | ||
3382 | "AP VHT information doesn't match HT, disable VHT\n"); | ||
3383 | ret = IEEE80211_STA_DISABLE_VHT; | ||
3384 | goto out; | ||
3385 | } | ||
3386 | |||
3387 | *chandef = vht_chandef; | ||
3388 | |||
3389 | ret = 0; | ||
3390 | |||
3391 | while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, | ||
3392 | IEEE80211_CHAN_DISABLED)) { | ||
3393 | if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { | ||
3394 | ret = IEEE80211_STA_DISABLE_HT | | ||
3395 | IEEE80211_STA_DISABLE_VHT; | ||
3396 | goto out; | ||
3397 | } | ||
3398 | |||
3399 | ret = chandef_downgrade(chandef); | ||
3400 | } | ||
3401 | |||
3402 | if (chandef->width != vht_chandef.width) | ||
3403 | sdata_info(sdata, | ||
3404 | "local regulatory prevented using AP HT/VHT configuration, downgraded\n"); | ||
3405 | |||
3406 | out: | ||
3407 | WARN_ON_ONCE(!cfg80211_chandef_valid(chandef)); | ||
3408 | return ret; | ||
3409 | } | ||
3410 | |||
3411 | static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata, | ||
3412 | struct cfg80211_bss *cbss) | ||
3413 | { | ||
3414 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3415 | const u8 *ht_cap_ie, *vht_cap_ie; | ||
3416 | const struct ieee80211_ht_cap *ht_cap; | ||
3417 | const struct ieee80211_vht_cap *vht_cap; | ||
3418 | u8 chains = 1; | ||
3419 | |||
3420 | if (ifmgd->flags & IEEE80211_STA_DISABLE_HT) | ||
3421 | return chains; | ||
3422 | |||
3423 | ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY); | ||
3424 | if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) { | ||
3425 | ht_cap = (void *)(ht_cap_ie + 2); | ||
3426 | chains = ieee80211_mcs_to_chains(&ht_cap->mcs); | ||
3427 | /* | ||
3428 | * TODO: use "Tx Maximum Number Spatial Streams Supported" and | ||
3429 | * "Tx Unequal Modulation Supported" fields. | ||
3430 | */ | ||
3431 | } | ||
3432 | |||
3433 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) | ||
3434 | return chains; | ||
3435 | |||
3436 | vht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY); | ||
3437 | if (vht_cap_ie && vht_cap_ie[1] >= sizeof(*vht_cap)) { | ||
3438 | u8 nss; | ||
3439 | u16 tx_mcs_map; | ||
3440 | |||
3441 | vht_cap = (void *)(vht_cap_ie + 2); | ||
3442 | tx_mcs_map = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map); | ||
3443 | for (nss = 8; nss > 0; nss--) { | ||
3444 | if (((tx_mcs_map >> (2 * (nss - 1))) & 3) != | ||
3445 | IEEE80211_VHT_MCS_NOT_SUPPORTED) | ||
3446 | break; | ||
3447 | } | ||
3448 | /* TODO: use "Tx Highest Supported Long GI Data Rate" field? */ | ||
3449 | chains = max(chains, nss); | ||
3450 | } | ||
3451 | |||
3452 | return chains; | ||
3453 | } | ||
3454 | |||
3186 | static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | 3455 | static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, |
3187 | struct cfg80211_bss *cbss) | 3456 | struct cfg80211_bss *cbss) |
3188 | { | 3457 | { |
3189 | struct ieee80211_local *local = sdata->local; | 3458 | struct ieee80211_local *local = sdata->local; |
3190 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3459 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3191 | int ht_cfreq; | ||
3192 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
3193 | const u8 *ht_oper_ie; | ||
3194 | const struct ieee80211_ht_operation *ht_oper = NULL; | 3460 | const struct ieee80211_ht_operation *ht_oper = NULL; |
3461 | const struct ieee80211_vht_operation *vht_oper = NULL; | ||
3195 | struct ieee80211_supported_band *sband; | 3462 | struct ieee80211_supported_band *sband; |
3196 | struct cfg80211_chan_def chandef; | 3463 | struct cfg80211_chan_def chandef; |
3464 | int ret; | ||
3197 | 3465 | ||
3198 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3466 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3199 | 3467 | ||
3200 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; | 3468 | ifmgd->flags &= ~(IEEE80211_STA_DISABLE_40MHZ | |
3469 | IEEE80211_STA_DISABLE_80P80MHZ | | ||
3470 | IEEE80211_STA_DISABLE_160MHZ); | ||
3201 | 3471 | ||
3202 | if (sband->ht_cap.ht_supported) { | 3472 | rcu_read_lock(); |
3203 | ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION, | 3473 | |
3204 | cbss->information_elements, | 3474 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && |
3205 | cbss->len_information_elements); | 3475 | sband->ht_cap.ht_supported) { |
3476 | const u8 *ht_oper_ie; | ||
3477 | |||
3478 | ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION); | ||
3206 | if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) | 3479 | if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) |
3207 | ht_oper = (void *)(ht_oper_ie + 2); | 3480 | ht_oper = (void *)(ht_oper_ie + 2); |
3208 | } | 3481 | } |
3209 | 3482 | ||
3210 | if (ht_oper) { | 3483 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && |
3211 | ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, | 3484 | sband->vht_cap.vht_supported) { |
3212 | cbss->channel->band); | 3485 | const u8 *vht_oper_ie; |
3213 | /* check that channel matches the right operating channel */ | 3486 | |
3214 | if (cbss->channel->center_freq != ht_cfreq) { | 3487 | vht_oper_ie = ieee80211_bss_get_ie(cbss, |
3215 | /* | 3488 | WLAN_EID_VHT_OPERATION); |
3216 | * It's possible that some APs are confused here; | 3489 | if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper)) |
3217 | * Netgear WNDR3700 sometimes reports 4 higher than | 3490 | vht_oper = (void *)(vht_oper_ie + 2); |
3218 | * the actual channel in association responses, but | 3491 | if (vht_oper && !ht_oper) { |
3219 | * since we look at probe response/beacon data here | 3492 | vht_oper = NULL; |
3220 | * it should be OK. | ||
3221 | */ | ||
3222 | sdata_info(sdata, | 3493 | sdata_info(sdata, |
3223 | "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", | 3494 | "AP advertised VHT without HT, disabling both\n"); |
3224 | cbss->channel->center_freq, | 3495 | sdata->flags |= IEEE80211_STA_DISABLE_HT; |
3225 | ht_cfreq, ht_oper->primary_chan, | 3496 | sdata->flags |= IEEE80211_STA_DISABLE_VHT; |
3226 | cbss->channel->band); | ||
3227 | ht_oper = NULL; | ||
3228 | } | 3497 | } |
3229 | } | 3498 | } |
3230 | 3499 | ||
3231 | if (ht_oper) { | 3500 | ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, |
3232 | /* | 3501 | cbss->channel, |
3233 | * cfg80211 already verified that the channel itself can | 3502 | ht_oper, vht_oper, |
3234 | * be used, but it didn't check that we can do the right | 3503 | &chandef); |
3235 | * HT type, so do that here as well. If HT40 isn't allowed | ||
3236 | * on this channel, disable 40 MHz operation. | ||
3237 | */ | ||
3238 | const u8 *ht_cap_ie; | ||
3239 | const struct ieee80211_ht_cap *ht_cap; | ||
3240 | u8 chains = 1; | ||
3241 | |||
3242 | channel_type = NL80211_CHAN_HT20; | ||
3243 | |||
3244 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | ||
3245 | switch (ht_oper->ht_param & | ||
3246 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
3247 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
3248 | if (cbss->channel->flags & | ||
3249 | IEEE80211_CHAN_NO_HT40PLUS) | ||
3250 | ifmgd->flags |= | ||
3251 | IEEE80211_STA_DISABLE_40MHZ; | ||
3252 | else | ||
3253 | channel_type = NL80211_CHAN_HT40PLUS; | ||
3254 | break; | ||
3255 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
3256 | if (cbss->channel->flags & | ||
3257 | IEEE80211_CHAN_NO_HT40MINUS) | ||
3258 | ifmgd->flags |= | ||
3259 | IEEE80211_STA_DISABLE_40MHZ; | ||
3260 | else | ||
3261 | channel_type = NL80211_CHAN_HT40MINUS; | ||
3262 | break; | ||
3263 | } | ||
3264 | } | ||
3265 | 3504 | ||
3266 | ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, | 3505 | sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), |
3267 | cbss->information_elements, | 3506 | local->rx_chains); |
3268 | cbss->len_information_elements); | 3507 | |
3269 | if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) { | 3508 | rcu_read_unlock(); |
3270 | ht_cap = (void *)(ht_cap_ie + 2); | ||
3271 | chains = ieee80211_mcs_to_chains(&ht_cap->mcs); | ||
3272 | } | ||
3273 | sdata->needed_rx_chains = min(chains, local->rx_chains); | ||
3274 | } else { | ||
3275 | sdata->needed_rx_chains = 1; | ||
3276 | sdata->u.mgd.flags |= IEEE80211_STA_DISABLE_HT; | ||
3277 | } | ||
3278 | 3509 | ||
3279 | /* will change later if needed */ | 3510 | /* will change later if needed */ |
3280 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 3511 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
3281 | 3512 | ||
3282 | ieee80211_vif_release_channel(sdata); | 3513 | /* |
3283 | cfg80211_chandef_create(&chandef, cbss->channel, channel_type); | 3514 | * If this fails (possibly due to channel context sharing |
3284 | return ieee80211_vif_use_channel(sdata, &chandef, | 3515 | * on incompatible channels, e.g. 80+80 and 160 sharing the |
3285 | IEEE80211_CHANCTX_SHARED); | 3516 | * same control channel) try to use a smaller bandwidth. |
3517 | */ | ||
3518 | ret = ieee80211_vif_use_channel(sdata, &chandef, | ||
3519 | IEEE80211_CHANCTX_SHARED); | ||
3520 | while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) | ||
3521 | ifmgd->flags |= chandef_downgrade(&chandef); | ||
3522 | return ret; | ||
3286 | } | 3523 | } |
3287 | 3524 | ||
3288 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | 3525 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, |
@@ -3510,14 +3747,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3510 | const u8 *ssidie, *ht_ie; | 3747 | const u8 *ssidie, *ht_ie; |
3511 | int i, err; | 3748 | int i, err; |
3512 | 3749 | ||
3513 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | ||
3514 | if (!ssidie) | ||
3515 | return -EINVAL; | ||
3516 | |||
3517 | assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); | 3750 | assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); |
3518 | if (!assoc_data) | 3751 | if (!assoc_data) |
3519 | return -ENOMEM; | 3752 | return -ENOMEM; |
3520 | 3753 | ||
3754 | rcu_read_lock(); | ||
3755 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | ||
3756 | if (!ssidie) { | ||
3757 | rcu_read_unlock(); | ||
3758 | kfree(assoc_data); | ||
3759 | return -EINVAL; | ||
3760 | } | ||
3761 | memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]); | ||
3762 | assoc_data->ssid_len = ssidie[1]; | ||
3763 | rcu_read_unlock(); | ||
3764 | |||
3521 | mutex_lock(&ifmgd->mtx); | 3765 | mutex_lock(&ifmgd->mtx); |
3522 | 3766 | ||
3523 | if (ifmgd->associated) | 3767 | if (ifmgd->associated) |
@@ -3612,12 +3856,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3612 | assoc_data->supp_rates = bss->supp_rates; | 3856 | assoc_data->supp_rates = bss->supp_rates; |
3613 | assoc_data->supp_rates_len = bss->supp_rates_len; | 3857 | assoc_data->supp_rates_len = bss->supp_rates_len; |
3614 | 3858 | ||
3859 | rcu_read_lock(); | ||
3615 | ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); | 3860 | ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); |
3616 | if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) | 3861 | if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) |
3617 | assoc_data->ap_ht_param = | 3862 | assoc_data->ap_ht_param = |
3618 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; | 3863 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; |
3619 | else | 3864 | else |
3620 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | 3865 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3866 | rcu_read_unlock(); | ||
3621 | 3867 | ||
3622 | if (bss->wmm_used && bss->uapsd_supported && | 3868 | if (bss->wmm_used && bss->uapsd_supported && |
3623 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3869 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
@@ -3628,9 +3874,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3628 | ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; | 3874 | ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; |
3629 | } | 3875 | } |
3630 | 3876 | ||
3631 | memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]); | ||
3632 | assoc_data->ssid_len = ssidie[1]; | ||
3633 | |||
3634 | if (req->prev_bssid) | 3877 | if (req->prev_bssid) |
3635 | memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN); | 3878 | memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN); |
3636 | 3879 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 5abddfe3e101..a5379aea7d09 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -462,8 +462,6 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) | |||
462 | list_move_tail(&roc->list, &tmp_list); | 462 | list_move_tail(&roc->list, &tmp_list); |
463 | roc->abort = true; | 463 | roc->abort = true; |
464 | } | 464 | } |
465 | |||
466 | ieee80211_start_next_roc(local); | ||
467 | mutex_unlock(&local->mtx); | 465 | mutex_unlock(&local->mtx); |
468 | 466 | ||
469 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { | 467 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index fb1d4aa65e8c..9f9c453bc45d 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -389,9 +389,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
389 | struct ieee80211_tx_rate *ar = info->status.rates; | 389 | struct ieee80211_tx_rate *ar = info->status.rates; |
390 | struct minstrel_rate_stats *rate, *rate2; | 390 | struct minstrel_rate_stats *rate, *rate2; |
391 | struct minstrel_priv *mp = priv; | 391 | struct minstrel_priv *mp = priv; |
392 | bool last = false; | 392 | bool last; |
393 | int group; | 393 | int group; |
394 | int i = 0; | 394 | int i; |
395 | 395 | ||
396 | if (!msp->is_ht) | 396 | if (!msp->is_ht) |
397 | return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb); | 397 | return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb); |
@@ -419,13 +419,11 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
419 | if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) | 419 | if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) |
420 | mi->sample_packets += info->status.ampdu_len; | 420 | mi->sample_packets += info->status.ampdu_len; |
421 | 421 | ||
422 | last = !minstrel_ht_txstat_valid(&ar[0]); | ||
422 | for (i = 0; !last; i++) { | 423 | for (i = 0; !last; i++) { |
423 | last = (i == IEEE80211_TX_MAX_RATES - 1) || | 424 | last = (i == IEEE80211_TX_MAX_RATES - 1) || |
424 | !minstrel_ht_txstat_valid(&ar[i + 1]); | 425 | !minstrel_ht_txstat_valid(&ar[i + 1]); |
425 | 426 | ||
426 | if (!minstrel_ht_txstat_valid(&ar[i])) | ||
427 | break; | ||
428 | |||
429 | group = minstrel_ht_get_group_idx(&ar[i]); | 427 | group = minstrel_ht_get_group_idx(&ar[i]); |
430 | rate = &mi->groups[group].rates[ar[i].idx % 8]; | 428 | rate = &mi->groups[group].rates[ar[i].idx % 8]; |
431 | 429 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 825f33cf7bbc..db343fa8033c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -49,7 +49,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
49 | /* driver bug */ | 49 | /* driver bug */ |
50 | WARN_ON(1); | 50 | WARN_ON(1); |
51 | dev_kfree_skb(skb); | 51 | dev_kfree_skb(skb); |
52 | skb = NULL; | 52 | return NULL; |
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
@@ -111,6 +111,11 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
111 | len += 8; | 111 | len += 8; |
112 | } | 112 | } |
113 | 113 | ||
114 | if (status->flag & RX_FLAG_VHT) { | ||
115 | len = ALIGN(len, 2); | ||
116 | len += 12; | ||
117 | } | ||
118 | |||
114 | if (status->vendor_radiotap_len) { | 119 | if (status->vendor_radiotap_len) { |
115 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) | 120 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) |
116 | status->vendor_radiotap_align = 1; | 121 | status->vendor_radiotap_align = 1; |
@@ -297,6 +302,41 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
297 | *pos++ = 0; | 302 | *pos++ = 0; |
298 | } | 303 | } |
299 | 304 | ||
305 | if (status->flag & RX_FLAG_VHT) { | ||
306 | u16 known = local->hw.radiotap_vht_details; | ||
307 | |||
308 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); | ||
309 | /* known field - how to handle 80+80? */ | ||
310 | if (status->flag & RX_FLAG_80P80MHZ) | ||
311 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | ||
312 | put_unaligned_le16(known, pos); | ||
313 | pos += 2; | ||
314 | /* flags */ | ||
315 | if (status->flag & RX_FLAG_SHORT_GI) | ||
316 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; | ||
317 | pos++; | ||
318 | /* bandwidth */ | ||
319 | if (status->flag & RX_FLAG_80MHZ) | ||
320 | *pos++ = 4; | ||
321 | else if (status->flag & RX_FLAG_80P80MHZ) | ||
322 | *pos++ = 0; /* marked not known above */ | ||
323 | else if (status->flag & RX_FLAG_160MHZ) | ||
324 | *pos++ = 11; | ||
325 | else if (status->flag & RX_FLAG_40MHZ) | ||
326 | *pos++ = 1; | ||
327 | else /* 20 MHz */ | ||
328 | *pos++ = 0; | ||
329 | /* MCS/NSS */ | ||
330 | *pos = (status->rate_idx << 4) | status->vht_nss; | ||
331 | pos += 4; | ||
332 | /* coding field */ | ||
333 | pos++; | ||
334 | /* group ID */ | ||
335 | pos++; | ||
336 | /* partial_aid */ | ||
337 | pos += 2; | ||
338 | } | ||
339 | |||
300 | if (status->vendor_radiotap_len) { | 340 | if (status->vendor_radiotap_len) { |
301 | /* ensure 2 byte alignment for the vendor field as required */ | 341 | /* ensure 2 byte alignment for the vendor field as required */ |
302 | if ((pos - (u8 *)rthdr) & 1) | 342 | if ((pos - (u8 *)rthdr) & 1) |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f3340279aba3..f7176ac5a535 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -247,6 +247,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
247 | local->hw_scan_req->n_channels = n_chans; | 247 | local->hw_scan_req->n_channels = n_chans; |
248 | 248 | ||
249 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, | 249 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, |
250 | local->hw_scan_ies_bufsize, | ||
250 | req->ie, req->ie_len, band, | 251 | req->ie, req->ie_len, band, |
251 | req->rates[band], 0); | 252 | req->rates[band], 0); |
252 | local->hw_scan_req->ie_len = ielen; | 253 | local->hw_scan_req->ie_len = ielen; |
@@ -445,11 +446,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
445 | if (local->ops->hw_scan) { | 446 | if (local->ops->hw_scan) { |
446 | u8 *ies; | 447 | u8 *ies; |
447 | 448 | ||
449 | local->hw_scan_ies_bufsize = 2 + IEEE80211_MAX_SSID_LEN + | ||
450 | local->scan_ies_len + | ||
451 | req->ie_len; | ||
448 | local->hw_scan_req = kmalloc( | 452 | local->hw_scan_req = kmalloc( |
449 | sizeof(*local->hw_scan_req) + | 453 | sizeof(*local->hw_scan_req) + |
450 | req->n_channels * sizeof(req->channels[0]) + | 454 | req->n_channels * sizeof(req->channels[0]) + |
451 | 2 + IEEE80211_MAX_SSID_LEN + local->scan_ies_len + | 455 | local->hw_scan_ies_bufsize, GFP_KERNEL); |
452 | req->ie_len, GFP_KERNEL); | ||
453 | if (!local->hw_scan_req) | 456 | if (!local->hw_scan_req) |
454 | return -ENOMEM; | 457 | return -ENOMEM; |
455 | 458 | ||
@@ -928,7 +931,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
928 | { | 931 | { |
929 | struct ieee80211_local *local = sdata->local; | 932 | struct ieee80211_local *local = sdata->local; |
930 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; | 933 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; |
931 | int ret, i; | 934 | int ret, i, iebufsz; |
935 | |||
936 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + | ||
937 | local->scan_ies_len + req->ie_len; | ||
932 | 938 | ||
933 | mutex_lock(&local->mtx); | 939 | mutex_lock(&local->mtx); |
934 | 940 | ||
@@ -946,10 +952,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
946 | if (!local->hw.wiphy->bands[i]) | 952 | if (!local->hw.wiphy->bands[i]) |
947 | continue; | 953 | continue; |
948 | 954 | ||
949 | sched_scan_ies.ie[i] = kzalloc(2 + IEEE80211_MAX_SSID_LEN + | 955 | sched_scan_ies.ie[i] = kzalloc(iebufsz, GFP_KERNEL); |
950 | local->scan_ies_len + | ||
951 | req->ie_len, | ||
952 | GFP_KERNEL); | ||
953 | if (!sched_scan_ies.ie[i]) { | 956 | if (!sched_scan_ies.ie[i]) { |
954 | ret = -ENOMEM; | 957 | ret = -ENOMEM; |
955 | goto out_free; | 958 | goto out_free; |
@@ -957,8 +960,8 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
957 | 960 | ||
958 | sched_scan_ies.len[i] = | 961 | sched_scan_ies.len[i] = |
959 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], | 962 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], |
960 | req->ie, req->ie_len, i, | 963 | iebufsz, req->ie, req->ie_len, |
961 | (u32) -1, 0); | 964 | i, (u32) -1, 0); |
962 | } | 965 | } |
963 | 966 | ||
964 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 967 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6835cea4e402..1489bca9ea97 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -250,6 +250,7 @@ struct sta_ampdu_mlme { | |||
250 | * @rx_dropped: number of dropped MPDUs from this STA | 250 | * @rx_dropped: number of dropped MPDUs from this STA |
251 | * @last_signal: signal of last received frame from this STA | 251 | * @last_signal: signal of last received frame from this STA |
252 | * @avg_signal: moving average of signal of received frames from this STA | 252 | * @avg_signal: moving average of signal of received frames from this STA |
253 | * @last_ack_signal: signal of last received Ack frame from this STA | ||
253 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | 254 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) |
254 | * @tx_filtered_count: number of frames the hardware filtered for this STA | 255 | * @tx_filtered_count: number of frames the hardware filtered for this STA |
255 | * @tx_retry_failed: number of frames that failed retry | 256 | * @tx_retry_failed: number of frames that failed retry |
@@ -329,6 +330,7 @@ struct sta_info { | |||
329 | unsigned long rx_dropped; | 330 | unsigned long rx_dropped; |
330 | int last_signal; | 331 | int last_signal; |
331 | struct ewma avg_signal; | 332 | struct ewma avg_signal; |
333 | int last_ack_signal; | ||
332 | /* Plus 1 for non-QoS frames */ | 334 | /* Plus 1 for non-QoS frames */ |
333 | __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; | 335 | __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; |
334 | 336 | ||
@@ -552,6 +554,8 @@ int sta_info_flush(struct ieee80211_local *local, | |||
552 | void sta_set_rate_info_tx(struct sta_info *sta, | 554 | void sta_set_rate_info_tx(struct sta_info *sta, |
553 | const struct ieee80211_tx_rate *rate, | 555 | const struct ieee80211_tx_rate *rate, |
554 | struct rate_info *rinfo); | 556 | struct rate_info *rinfo); |
557 | void sta_set_rate_info_rx(struct sta_info *sta, | ||
558 | struct rate_info *rinfo); | ||
555 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 559 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
556 | unsigned long exp_time); | 560 | unsigned long exp_time); |
557 | 561 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index ab63237107c8..ab50285fcbab 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -539,6 +539,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
539 | sta->lost_packets = 0; | 539 | sta->lost_packets = 0; |
540 | } | 540 | } |
541 | } | 541 | } |
542 | |||
543 | if (acked) | ||
544 | sta->last_ack_signal = info->status.ack_signal; | ||
542 | } | 545 | } |
543 | 546 | ||
544 | rcu_read_unlock(); | 547 | rcu_read_unlock(); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d287a4f2c01b..e9eadc40c09c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2623,7 +2623,7 @@ EXPORT_SYMBOL(ieee80211_nullfunc_get); | |||
2623 | struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | 2623 | struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, |
2624 | struct ieee80211_vif *vif, | 2624 | struct ieee80211_vif *vif, |
2625 | const u8 *ssid, size_t ssid_len, | 2625 | const u8 *ssid, size_t ssid_len, |
2626 | const u8 *ie, size_t ie_len) | 2626 | size_t tailroom) |
2627 | { | 2627 | { |
2628 | struct ieee80211_sub_if_data *sdata; | 2628 | struct ieee80211_sub_if_data *sdata; |
2629 | struct ieee80211_local *local; | 2629 | struct ieee80211_local *local; |
@@ -2637,7 +2637,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | |||
2637 | ie_ssid_len = 2 + ssid_len; | 2637 | ie_ssid_len = 2 + ssid_len; |
2638 | 2638 | ||
2639 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + | 2639 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + |
2640 | ie_ssid_len + ie_len); | 2640 | ie_ssid_len + tailroom); |
2641 | if (!skb) | 2641 | if (!skb) |
2642 | return NULL; | 2642 | return NULL; |
2643 | 2643 | ||
@@ -2658,11 +2658,6 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | |||
2658 | memcpy(pos, ssid, ssid_len); | 2658 | memcpy(pos, ssid, ssid_len); |
2659 | pos += ssid_len; | 2659 | pos += ssid_len; |
2660 | 2660 | ||
2661 | if (ie) { | ||
2662 | pos = skb_put(skb, ie_len); | ||
2663 | memcpy(pos, ie, ie_len); | ||
2664 | } | ||
2665 | |||
2666 | return skb; | 2661 | return skb; |
2667 | } | 2662 | } |
2668 | EXPORT_SYMBOL(ieee80211_probereq_get); | 2663 | EXPORT_SYMBOL(ieee80211_probereq_get); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 08132ff98155..f11e8c540db4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1107,12 +1107,12 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1107 | } | 1107 | } |
1108 | 1108 | ||
1109 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1109 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1110 | const u8 *ie, size_t ie_len, | 1110 | size_t buffer_len, const u8 *ie, size_t ie_len, |
1111 | enum ieee80211_band band, u32 rate_mask, | 1111 | enum ieee80211_band band, u32 rate_mask, |
1112 | u8 channel) | 1112 | u8 channel) |
1113 | { | 1113 | { |
1114 | struct ieee80211_supported_band *sband; | 1114 | struct ieee80211_supported_band *sband; |
1115 | u8 *pos; | 1115 | u8 *pos = buffer, *end = buffer + buffer_len; |
1116 | size_t offset = 0, noffset; | 1116 | size_t offset = 0, noffset; |
1117 | int supp_rates_len, i; | 1117 | int supp_rates_len, i; |
1118 | u8 rates[32]; | 1118 | u8 rates[32]; |
@@ -1123,8 +1123,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1123 | if (WARN_ON_ONCE(!sband)) | 1123 | if (WARN_ON_ONCE(!sband)) |
1124 | return 0; | 1124 | return 0; |
1125 | 1125 | ||
1126 | pos = buffer; | ||
1127 | |||
1128 | num_rates = 0; | 1126 | num_rates = 0; |
1129 | for (i = 0; i < sband->n_bitrates; i++) { | 1127 | for (i = 0; i < sband->n_bitrates; i++) { |
1130 | if ((BIT(i) & rate_mask) == 0) | 1128 | if ((BIT(i) & rate_mask) == 0) |
@@ -1134,6 +1132,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1134 | 1132 | ||
1135 | supp_rates_len = min_t(int, num_rates, 8); | 1133 | supp_rates_len = min_t(int, num_rates, 8); |
1136 | 1134 | ||
1135 | if (end - pos < 2 + supp_rates_len) | ||
1136 | goto out_err; | ||
1137 | *pos++ = WLAN_EID_SUPP_RATES; | 1137 | *pos++ = WLAN_EID_SUPP_RATES; |
1138 | *pos++ = supp_rates_len; | 1138 | *pos++ = supp_rates_len; |
1139 | memcpy(pos, rates, supp_rates_len); | 1139 | memcpy(pos, rates, supp_rates_len); |
@@ -1150,6 +1150,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1150 | before_extrates, | 1150 | before_extrates, |
1151 | ARRAY_SIZE(before_extrates), | 1151 | ARRAY_SIZE(before_extrates), |
1152 | offset); | 1152 | offset); |
1153 | if (end - pos < noffset - offset) | ||
1154 | goto out_err; | ||
1153 | memcpy(pos, ie + offset, noffset - offset); | 1155 | memcpy(pos, ie + offset, noffset - offset); |
1154 | pos += noffset - offset; | 1156 | pos += noffset - offset; |
1155 | offset = noffset; | 1157 | offset = noffset; |
@@ -1157,6 +1159,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1157 | 1159 | ||
1158 | ext_rates_len = num_rates - supp_rates_len; | 1160 | ext_rates_len = num_rates - supp_rates_len; |
1159 | if (ext_rates_len > 0) { | 1161 | if (ext_rates_len > 0) { |
1162 | if (end - pos < 2 + ext_rates_len) | ||
1163 | goto out_err; | ||
1160 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 1164 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
1161 | *pos++ = ext_rates_len; | 1165 | *pos++ = ext_rates_len; |
1162 | memcpy(pos, rates + supp_rates_len, ext_rates_len); | 1166 | memcpy(pos, rates + supp_rates_len, ext_rates_len); |
@@ -1164,6 +1168,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1164 | } | 1168 | } |
1165 | 1169 | ||
1166 | if (channel && sband->band == IEEE80211_BAND_2GHZ) { | 1170 | if (channel && sband->band == IEEE80211_BAND_2GHZ) { |
1171 | if (end - pos < 3) | ||
1172 | goto out_err; | ||
1167 | *pos++ = WLAN_EID_DS_PARAMS; | 1173 | *pos++ = WLAN_EID_DS_PARAMS; |
1168 | *pos++ = 1; | 1174 | *pos++ = 1; |
1169 | *pos++ = channel; | 1175 | *pos++ = channel; |
@@ -1182,14 +1188,19 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1182 | noffset = ieee80211_ie_split(ie, ie_len, | 1188 | noffset = ieee80211_ie_split(ie, ie_len, |
1183 | before_ht, ARRAY_SIZE(before_ht), | 1189 | before_ht, ARRAY_SIZE(before_ht), |
1184 | offset); | 1190 | offset); |
1191 | if (end - pos < noffset - offset) | ||
1192 | goto out_err; | ||
1185 | memcpy(pos, ie + offset, noffset - offset); | 1193 | memcpy(pos, ie + offset, noffset - offset); |
1186 | pos += noffset - offset; | 1194 | pos += noffset - offset; |
1187 | offset = noffset; | 1195 | offset = noffset; |
1188 | } | 1196 | } |
1189 | 1197 | ||
1190 | if (sband->ht_cap.ht_supported) | 1198 | if (sband->ht_cap.ht_supported) { |
1199 | if (end - pos < 2 + sizeof(struct ieee80211_ht_cap)) | ||
1200 | goto out_err; | ||
1191 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, | 1201 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, |
1192 | sband->ht_cap.cap); | 1202 | sband->ht_cap.cap); |
1203 | } | ||
1193 | 1204 | ||
1194 | /* | 1205 | /* |
1195 | * If adding more here, adjust code in main.c | 1206 | * If adding more here, adjust code in main.c |
@@ -1199,15 +1210,23 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1199 | /* add any remaining custom IEs */ | 1210 | /* add any remaining custom IEs */ |
1200 | if (ie && ie_len) { | 1211 | if (ie && ie_len) { |
1201 | noffset = ie_len; | 1212 | noffset = ie_len; |
1213 | if (end - pos < noffset - offset) | ||
1214 | goto out_err; | ||
1202 | memcpy(pos, ie + offset, noffset - offset); | 1215 | memcpy(pos, ie + offset, noffset - offset); |
1203 | pos += noffset - offset; | 1216 | pos += noffset - offset; |
1204 | } | 1217 | } |
1205 | 1218 | ||
1206 | if (sband->vht_cap.vht_supported) | 1219 | if (sband->vht_cap.vht_supported) { |
1220 | if (end - pos < 2 + sizeof(struct ieee80211_vht_cap)) | ||
1221 | goto out_err; | ||
1207 | pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, | 1222 | pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, |
1208 | sband->vht_cap.cap); | 1223 | sband->vht_cap.cap); |
1224 | } | ||
1209 | 1225 | ||
1210 | return pos - buffer; | 1226 | return pos - buffer; |
1227 | out_err: | ||
1228 | WARN_ONCE(1, "not enough space for preq IEs\n"); | ||
1229 | return pos - buffer; | ||
1211 | } | 1230 | } |
1212 | 1231 | ||
1213 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1232 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
@@ -1220,14 +1239,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1220 | struct ieee80211_local *local = sdata->local; | 1239 | struct ieee80211_local *local = sdata->local; |
1221 | struct sk_buff *skb; | 1240 | struct sk_buff *skb; |
1222 | struct ieee80211_mgmt *mgmt; | 1241 | struct ieee80211_mgmt *mgmt; |
1223 | size_t buf_len; | ||
1224 | u8 *buf; | ||
1225 | u8 chan_no; | 1242 | u8 chan_no; |
1226 | 1243 | int ies_len; | |
1227 | /* FIXME: come up with a proper value */ | ||
1228 | buf = kmalloc(200 + ie_len, GFP_KERNEL); | ||
1229 | if (!buf) | ||
1230 | return NULL; | ||
1231 | 1244 | ||
1232 | /* | 1245 | /* |
1233 | * Do not send DS Channel parameter for directed probe requests | 1246 | * Do not send DS Channel parameter for directed probe requests |
@@ -1239,14 +1252,16 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1239 | else | 1252 | else |
1240 | chan_no = ieee80211_frequency_to_channel(chan->center_freq); | 1253 | chan_no = ieee80211_frequency_to_channel(chan->center_freq); |
1241 | 1254 | ||
1242 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, chan->band, | ||
1243 | ratemask, chan_no); | ||
1244 | |||
1245 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1255 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1246 | ssid, ssid_len, | 1256 | ssid, ssid_len, 100 + ie_len); |
1247 | buf, buf_len); | ||
1248 | if (!skb) | 1257 | if (!skb) |
1249 | goto out; | 1258 | return NULL; |
1259 | |||
1260 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), | ||
1261 | skb_tailroom(skb), | ||
1262 | ie, ie_len, chan->band, | ||
1263 | ratemask, chan_no); | ||
1264 | skb_put(skb, ies_len); | ||
1250 | 1265 | ||
1251 | if (dst) { | 1266 | if (dst) { |
1252 | mgmt = (struct ieee80211_mgmt *) skb->data; | 1267 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -1256,9 +1271,6 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1256 | 1271 | ||
1257 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1272 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1258 | 1273 | ||
1259 | out: | ||
1260 | kfree(buf); | ||
1261 | |||
1262 | return skb; | 1274 | return skb; |
1263 | } | 1275 | } |
1264 | 1276 | ||
@@ -1527,7 +1539,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1527 | changed |= BSS_CHANGED_IBSS; | 1539 | changed |= BSS_CHANGED_IBSS; |
1528 | /* fall through */ | 1540 | /* fall through */ |
1529 | case NL80211_IFTYPE_AP: | 1541 | case NL80211_IFTYPE_AP: |
1530 | changed |= BSS_CHANGED_SSID; | 1542 | changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS; |
1531 | 1543 | ||
1532 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 1544 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
1533 | changed |= BSS_CHANGED_AP_PROBE_RESP; | 1545 | changed |= BSS_CHANGED_AP_PROBE_RESP; |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 2df87056c6df..ec43914c92a9 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -985,15 +985,18 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
985 | /* Remove skbs from the pending queue */ | 985 | /* Remove skbs from the pending queue */ |
986 | if (llcp_sock->send_ack_n != nr) { | 986 | if (llcp_sock->send_ack_n != nr) { |
987 | struct sk_buff *s, *tmp; | 987 | struct sk_buff *s, *tmp; |
988 | u8 n; | ||
988 | 989 | ||
989 | llcp_sock->send_ack_n = nr; | 990 | llcp_sock->send_ack_n = nr; |
990 | 991 | ||
991 | /* Remove and free all skbs until ns == nr */ | 992 | /* Remove and free all skbs until ns == nr */ |
992 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) { | 993 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) { |
994 | n = nfc_llcp_ns(s); | ||
995 | |||
993 | skb_unlink(s, &llcp_sock->tx_pending_queue); | 996 | skb_unlink(s, &llcp_sock->tx_pending_queue); |
994 | kfree_skb(s); | 997 | kfree_skb(s); |
995 | 998 | ||
996 | if (nfc_llcp_ns(s) == nr) | 999 | if (n == nr) |
997 | break; | 1000 | break; |
998 | } | 1001 | } |
999 | 1002 | ||
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index 865adb61685a..78fc0937948d 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c | |||
@@ -213,7 +213,7 @@ static int rfkill_gpio_remove(struct platform_device *pdev) | |||
213 | 213 | ||
214 | static struct platform_driver rfkill_gpio_driver = { | 214 | static struct platform_driver rfkill_gpio_driver = { |
215 | .probe = rfkill_gpio_probe, | 215 | .probe = rfkill_gpio_probe, |
216 | .remove = __devexit_p(rfkill_gpio_remove), | 216 | .remove = rfkill_gpio_remove, |
217 | .driver = { | 217 | .driver = { |
218 | .name = "rfkill_gpio", | 218 | .name = "rfkill_gpio", |
219 | .owner = THIS_MODULE, | 219 | .owner = THIS_MODULE, |
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c index 11da3018a853..4b5ab21ecb24 100644 --- a/net/rfkill/rfkill-regulator.c +++ b/net/rfkill/rfkill-regulator.c | |||
@@ -55,7 +55,7 @@ struct rfkill_ops rfkill_regulator_ops = { | |||
55 | .set_block = rfkill_regulator_set_block, | 55 | .set_block = rfkill_regulator_set_block, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static int __devinit rfkill_regulator_probe(struct platform_device *pdev) | 58 | static int rfkill_regulator_probe(struct platform_device *pdev) |
59 | { | 59 | { |
60 | struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data; | 60 | struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data; |
61 | struct rfkill_regulator_data *rfkill_data; | 61 | struct rfkill_regulator_data *rfkill_data; |
@@ -122,7 +122,7 @@ out: | |||
122 | return ret; | 122 | return ret; |
123 | } | 123 | } |
124 | 124 | ||
125 | static int __devexit rfkill_regulator_remove(struct platform_device *pdev) | 125 | static int rfkill_regulator_remove(struct platform_device *pdev) |
126 | { | 126 | { |
127 | struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev); | 127 | struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev); |
128 | struct rfkill *rf_kill = rfkill_data->rf_kill; | 128 | struct rfkill *rf_kill = rfkill_data->rf_kill; |
@@ -137,7 +137,7 @@ static int __devexit rfkill_regulator_remove(struct platform_device *pdev) | |||
137 | 137 | ||
138 | static struct platform_driver rfkill_regulator_driver = { | 138 | static struct platform_driver rfkill_regulator_driver = { |
139 | .probe = rfkill_regulator_probe, | 139 | .probe = rfkill_regulator_probe, |
140 | .remove = __devexit_p(rfkill_regulator_remove), | 140 | .remove = rfkill_regulator_remove, |
141 | .driver = { | 141 | .driver = { |
142 | .name = "rfkill-regulator", | 142 | .name = "rfkill-regulator", |
143 | .owner = THIS_MODULE, | 143 | .owner = THIS_MODULE, |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index bf2dfd54ff3b..b5f69831e318 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -44,7 +44,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, | |||
44 | } | 44 | } |
45 | EXPORT_SYMBOL(cfg80211_chandef_create); | 45 | EXPORT_SYMBOL(cfg80211_chandef_create); |
46 | 46 | ||
47 | bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef) | 47 | bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) |
48 | { | 48 | { |
49 | u32 control_freq; | 49 | u32 control_freq; |
50 | 50 | ||
@@ -105,6 +105,7 @@ bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef) | |||
105 | 105 | ||
106 | return true; | 106 | return true; |
107 | } | 107 | } |
108 | EXPORT_SYMBOL(cfg80211_chandef_valid); | ||
108 | 109 | ||
109 | static void chandef_primary_freqs(const struct cfg80211_chan_def *c, | 110 | static void chandef_primary_freqs(const struct cfg80211_chan_def *c, |
110 | int *pri40, int *pri80) | 111 | int *pri40, int *pri80) |
@@ -187,9 +188,9 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, | |||
187 | } | 188 | } |
188 | EXPORT_SYMBOL(cfg80211_chandef_compatible); | 189 | EXPORT_SYMBOL(cfg80211_chandef_compatible); |
189 | 190 | ||
190 | bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 191 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, |
191 | u32 center_freq, u32 bandwidth, | 192 | u32 center_freq, u32 bandwidth, |
192 | u32 prohibited_flags) | 193 | u32 prohibited_flags) |
193 | { | 194 | { |
194 | struct ieee80211_channel *c; | 195 | struct ieee80211_channel *c; |
195 | u32 freq; | 196 | u32 freq; |
@@ -205,55 +206,88 @@ bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | |||
205 | return true; | 206 | return true; |
206 | } | 207 | } |
207 | 208 | ||
208 | static bool cfg80211_check_beacon_chans(struct wiphy *wiphy, | 209 | bool cfg80211_chandef_usable(struct wiphy *wiphy, |
209 | u32 center_freq, u32 bw) | 210 | const struct cfg80211_chan_def *chandef, |
211 | u32 prohibited_flags) | ||
210 | { | 212 | { |
211 | return cfg80211_secondary_chans_ok(wiphy, center_freq, bw, | 213 | struct ieee80211_sta_ht_cap *ht_cap; |
212 | IEEE80211_CHAN_DISABLED | | 214 | struct ieee80211_sta_vht_cap *vht_cap; |
213 | IEEE80211_CHAN_PASSIVE_SCAN | | 215 | u32 width, control_freq; |
214 | IEEE80211_CHAN_NO_IBSS | | ||
215 | IEEE80211_CHAN_RADAR); | ||
216 | } | ||
217 | 216 | ||
218 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | 217 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) |
219 | struct cfg80211_chan_def *chandef) | 218 | return false; |
220 | { | ||
221 | u32 width; | ||
222 | bool res; | ||
223 | 219 | ||
224 | trace_cfg80211_reg_can_beacon(wiphy, chandef); | 220 | ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap; |
221 | vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap; | ||
225 | 222 | ||
226 | if (WARN_ON(!cfg80211_chan_def_valid(chandef))) { | 223 | control_freq = chandef->chan->center_freq; |
227 | trace_cfg80211_return_bool(false); | ||
228 | return false; | ||
229 | } | ||
230 | 224 | ||
231 | switch (chandef->width) { | 225 | switch (chandef->width) { |
232 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
233 | case NL80211_CHAN_WIDTH_20: | 226 | case NL80211_CHAN_WIDTH_20: |
227 | if (!ht_cap->ht_supported) | ||
228 | return false; | ||
229 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
234 | width = 20; | 230 | width = 20; |
235 | break; | 231 | break; |
236 | case NL80211_CHAN_WIDTH_40: | 232 | case NL80211_CHAN_WIDTH_40: |
237 | width = 40; | 233 | width = 40; |
234 | if (!ht_cap->ht_supported) | ||
235 | return false; | ||
236 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | ||
237 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) | ||
238 | return false; | ||
239 | if (chandef->center_freq1 < control_freq && | ||
240 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
241 | return false; | ||
242 | if (chandef->center_freq1 > control_freq && | ||
243 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
244 | return false; | ||
238 | break; | 245 | break; |
239 | case NL80211_CHAN_WIDTH_80: | ||
240 | case NL80211_CHAN_WIDTH_80P80: | 246 | case NL80211_CHAN_WIDTH_80P80: |
247 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) | ||
248 | return false; | ||
249 | case NL80211_CHAN_WIDTH_80: | ||
250 | if (!vht_cap->vht_supported) | ||
251 | return false; | ||
241 | width = 80; | 252 | width = 80; |
242 | break; | 253 | break; |
243 | case NL80211_CHAN_WIDTH_160: | 254 | case NL80211_CHAN_WIDTH_160: |
255 | if (!vht_cap->vht_supported) | ||
256 | return false; | ||
257 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) | ||
258 | return false; | ||
244 | width = 160; | 259 | width = 160; |
245 | break; | 260 | break; |
246 | default: | 261 | default: |
247 | WARN_ON_ONCE(1); | 262 | WARN_ON_ONCE(1); |
248 | trace_cfg80211_return_bool(false); | ||
249 | return false; | 263 | return false; |
250 | } | 264 | } |
251 | 265 | ||
252 | res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width); | 266 | /* TODO: missing regulatory check on 80/160 bandwidth */ |
267 | |||
268 | if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1, | ||
269 | width, prohibited_flags)) | ||
270 | return false; | ||
271 | |||
272 | if (!chandef->center_freq2) | ||
273 | return true; | ||
274 | return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2, | ||
275 | width, prohibited_flags); | ||
276 | } | ||
277 | EXPORT_SYMBOL(cfg80211_chandef_usable); | ||
278 | |||
279 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | ||
280 | struct cfg80211_chan_def *chandef) | ||
281 | { | ||
282 | bool res; | ||
283 | |||
284 | trace_cfg80211_reg_can_beacon(wiphy, chandef); | ||
253 | 285 | ||
254 | if (res && chandef->center_freq2) | 286 | res = cfg80211_chandef_usable(wiphy, chandef, |
255 | res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2, | 287 | IEEE80211_CHAN_DISABLED | |
256 | width); | 288 | IEEE80211_CHAN_PASSIVE_SCAN | |
289 | IEEE80211_CHAN_NO_IBSS | | ||
290 | IEEE80211_CHAN_RADAR); | ||
257 | 291 | ||
258 | trace_cfg80211_return_bool(res); | 292 | trace_cfg80211_return_bool(res); |
259 | return res; | 293 | return res; |
diff --git a/net/wireless/core.h b/net/wireless/core.h index a0c8decf6a47..3563097169cb 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -138,8 +138,6 @@ struct cfg80211_internal_bss { | |||
138 | unsigned long ts; | 138 | unsigned long ts; |
139 | struct kref ref; | 139 | struct kref ref; |
140 | atomic_t hold; | 140 | atomic_t hold; |
141 | bool beacon_ies_allocated; | ||
142 | bool proberesp_ies_allocated; | ||
143 | 141 | ||
144 | /* must be last because of priv member */ | 142 | /* must be last because of priv member */ |
145 | struct cfg80211_bss pub; | 143 | struct cfg80211_bss pub; |
@@ -483,12 +481,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
483 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 481 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
484 | enum nl80211_iftype iftype, int num); | 482 | enum nl80211_iftype iftype, int num); |
485 | 483 | ||
486 | bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef); | ||
487 | |||
488 | bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | ||
489 | u32 center_freq, u32 bandwidth, | ||
490 | u32 prohibited_flags); | ||
491 | |||
492 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 484 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
493 | 485 | ||
494 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 486 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 3ee5a7282283..f9d6ce5cfabb 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -146,7 +146,8 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
146 | if (!setup->chandef.chan) | 146 | if (!setup->chandef.chan) |
147 | return -EINVAL; | 147 | return -EINVAL; |
148 | 148 | ||
149 | setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;; | 149 | setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
150 | setup->chandef.center_freq1 = setup->chandef.chan->center_freq; | ||
150 | } | 151 | } |
151 | 152 | ||
152 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) | 153 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d038fa45ecd1..f45706adaf34 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -363,6 +363,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
363 | [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, | 363 | [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, |
364 | [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, | 364 | [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, |
365 | [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, | 365 | [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, |
366 | [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, | ||
367 | [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, | ||
366 | }; | 368 | }; |
367 | 369 | ||
368 | /* policy for the key attributes */ | 370 | /* policy for the key attributes */ |
@@ -1369,9 +1371,7 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, | |||
1369 | struct genl_info *info, | 1371 | struct genl_info *info, |
1370 | struct cfg80211_chan_def *chandef) | 1372 | struct cfg80211_chan_def *chandef) |
1371 | { | 1373 | { |
1372 | struct ieee80211_sta_ht_cap *ht_cap; | 1374 | u32 control_freq; |
1373 | struct ieee80211_sta_vht_cap *vht_cap; | ||
1374 | u32 control_freq, width; | ||
1375 | 1375 | ||
1376 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 1376 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
1377 | return -EINVAL; | 1377 | return -EINVAL; |
@@ -1417,67 +1417,13 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, | |||
1417 | info->attrs[NL80211_ATTR_CENTER_FREQ2]); | 1417 | info->attrs[NL80211_ATTR_CENTER_FREQ2]); |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap; | 1420 | if (!cfg80211_chandef_valid(chandef)) |
1421 | vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap; | ||
1422 | |||
1423 | if (!cfg80211_chan_def_valid(chandef)) | ||
1424 | return -EINVAL; | 1421 | return -EINVAL; |
1425 | 1422 | ||
1426 | switch (chandef->width) { | 1423 | if (!cfg80211_chandef_usable(&rdev->wiphy, chandef, |
1427 | case NL80211_CHAN_WIDTH_20: | 1424 | IEEE80211_CHAN_DISABLED)) |
1428 | if (!ht_cap->ht_supported) | ||
1429 | return -EINVAL; | ||
1430 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
1431 | width = 20; | ||
1432 | break; | ||
1433 | case NL80211_CHAN_WIDTH_40: | ||
1434 | width = 40; | ||
1435 | /* quick early regulatory check */ | ||
1436 | if (chandef->center_freq1 < control_freq && | ||
1437 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
1438 | return -EINVAL; | ||
1439 | if (chandef->center_freq1 > control_freq && | ||
1440 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
1441 | return -EINVAL; | ||
1442 | if (!ht_cap->ht_supported) | ||
1443 | return -EINVAL; | ||
1444 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | ||
1445 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) | ||
1446 | return -EINVAL; | ||
1447 | break; | ||
1448 | case NL80211_CHAN_WIDTH_80: | ||
1449 | width = 80; | ||
1450 | if (!vht_cap->vht_supported) | ||
1451 | return -EINVAL; | ||
1452 | break; | ||
1453 | case NL80211_CHAN_WIDTH_80P80: | ||
1454 | width = 80; | ||
1455 | if (!vht_cap->vht_supported) | ||
1456 | return -EINVAL; | ||
1457 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) | ||
1458 | return -EINVAL; | ||
1459 | break; | ||
1460 | case NL80211_CHAN_WIDTH_160: | ||
1461 | width = 160; | ||
1462 | if (!vht_cap->vht_supported) | ||
1463 | return -EINVAL; | ||
1464 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) | ||
1465 | return -EINVAL; | ||
1466 | break; | ||
1467 | default: | ||
1468 | return -EINVAL; | ||
1469 | } | ||
1470 | |||
1471 | if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1, | ||
1472 | width, IEEE80211_CHAN_DISABLED)) | ||
1473 | return -EINVAL; | ||
1474 | if (chandef->center_freq2 && | ||
1475 | !cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2, | ||
1476 | width, IEEE80211_CHAN_DISABLED)) | ||
1477 | return -EINVAL; | 1425 | return -EINVAL; |
1478 | 1426 | ||
1479 | /* TODO: missing regulatory check on bandwidth */ | ||
1480 | |||
1481 | return 0; | 1427 | return 0; |
1482 | } | 1428 | } |
1483 | 1429 | ||
@@ -1841,7 +1787,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev) | |||
1841 | static int nl80211_send_chandef(struct sk_buff *msg, | 1787 | static int nl80211_send_chandef(struct sk_buff *msg, |
1842 | struct cfg80211_chan_def *chandef) | 1788 | struct cfg80211_chan_def *chandef) |
1843 | { | 1789 | { |
1844 | WARN_ON(!cfg80211_chan_def_valid(chandef)); | 1790 | WARN_ON(!cfg80211_chandef_valid(chandef)); |
1845 | 1791 | ||
1846 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, | 1792 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, |
1847 | chandef->chan->center_freq)) | 1793 | chandef->chan->center_freq)) |
@@ -2732,6 +2678,32 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2732 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); | 2678 | info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); |
2733 | } | 2679 | } |
2734 | 2680 | ||
2681 | if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) { | ||
2682 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
2683 | return -EINVAL; | ||
2684 | params.p2p_ctwindow = | ||
2685 | nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); | ||
2686 | if (params.p2p_ctwindow > 127) | ||
2687 | return -EINVAL; | ||
2688 | if (params.p2p_ctwindow != 0 && | ||
2689 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) | ||
2690 | return -EINVAL; | ||
2691 | } | ||
2692 | |||
2693 | if (info->attrs[NL80211_ATTR_P2P_OPPPS]) { | ||
2694 | u8 tmp; | ||
2695 | |||
2696 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
2697 | return -EINVAL; | ||
2698 | tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); | ||
2699 | if (tmp > 1) | ||
2700 | return -EINVAL; | ||
2701 | params.p2p_opp_ps = tmp; | ||
2702 | if (params.p2p_opp_ps != 0 && | ||
2703 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) | ||
2704 | return -EINVAL; | ||
2705 | } | ||
2706 | |||
2735 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 2707 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
2736 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); | 2708 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); |
2737 | if (err) | 2709 | if (err) |
@@ -3698,6 +3670,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
3698 | params.use_short_slot_time = -1; | 3670 | params.use_short_slot_time = -1; |
3699 | params.ap_isolate = -1; | 3671 | params.ap_isolate = -1; |
3700 | params.ht_opmode = -1; | 3672 | params.ht_opmode = -1; |
3673 | params.p2p_ctwindow = -1; | ||
3674 | params.p2p_opp_ps = -1; | ||
3701 | 3675 | ||
3702 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) | 3676 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) |
3703 | params.use_cts_prot = | 3677 | params.use_cts_prot = |
@@ -3720,6 +3694,32 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
3720 | params.ht_opmode = | 3694 | params.ht_opmode = |
3721 | nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]); | 3695 | nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]); |
3722 | 3696 | ||
3697 | if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) { | ||
3698 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
3699 | return -EINVAL; | ||
3700 | params.p2p_ctwindow = | ||
3701 | nla_get_s8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); | ||
3702 | if (params.p2p_ctwindow < 0) | ||
3703 | return -EINVAL; | ||
3704 | if (params.p2p_ctwindow != 0 && | ||
3705 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) | ||
3706 | return -EINVAL; | ||
3707 | } | ||
3708 | |||
3709 | if (info->attrs[NL80211_ATTR_P2P_OPPPS]) { | ||
3710 | u8 tmp; | ||
3711 | |||
3712 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
3713 | return -EINVAL; | ||
3714 | tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); | ||
3715 | if (tmp > 1) | ||
3716 | return -EINVAL; | ||
3717 | params.p2p_opp_ps = tmp; | ||
3718 | if (params.p2p_opp_ps && | ||
3719 | !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) | ||
3720 | return -EINVAL; | ||
3721 | } | ||
3722 | |||
3723 | if (!rdev->ops->change_bss) | 3723 | if (!rdev->ops->change_bss) |
3724 | return -EOPNOTSUPP; | 3724 | return -EOPNOTSUPP; |
3725 | 3725 | ||
@@ -4808,6 +4808,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
4808 | struct cfg80211_internal_bss *intbss) | 4808 | struct cfg80211_internal_bss *intbss) |
4809 | { | 4809 | { |
4810 | struct cfg80211_bss *res = &intbss->pub; | 4810 | struct cfg80211_bss *res = &intbss->pub; |
4811 | const struct cfg80211_bss_ies *ies; | ||
4811 | void *hdr; | 4812 | void *hdr; |
4812 | struct nlattr *bss; | 4813 | struct nlattr *bss; |
4813 | 4814 | ||
@@ -4828,16 +4829,24 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
4828 | if (!bss) | 4829 | if (!bss) |
4829 | goto nla_put_failure; | 4830 | goto nla_put_failure; |
4830 | if ((!is_zero_ether_addr(res->bssid) && | 4831 | if ((!is_zero_ether_addr(res->bssid) && |
4831 | nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid)) || | 4832 | nla_put(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid))) |
4832 | (res->information_elements && res->len_information_elements && | 4833 | goto nla_put_failure; |
4833 | nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, | 4834 | |
4834 | res->len_information_elements, | 4835 | rcu_read_lock(); |
4835 | res->information_elements)) || | 4836 | ies = rcu_dereference(res->ies); |
4836 | (res->beacon_ies && res->len_beacon_ies && | 4837 | if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, |
4837 | res->beacon_ies != res->information_elements && | 4838 | ies->len, ies->data)) { |
4838 | nla_put(msg, NL80211_BSS_BEACON_IES, | 4839 | rcu_read_unlock(); |
4839 | res->len_beacon_ies, res->beacon_ies))) | 4840 | goto nla_put_failure; |
4841 | } | ||
4842 | ies = rcu_dereference(res->beacon_ies); | ||
4843 | if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, | ||
4844 | ies->len, ies->data)) { | ||
4845 | rcu_read_unlock(); | ||
4840 | goto nla_put_failure; | 4846 | goto nla_put_failure; |
4847 | } | ||
4848 | rcu_read_unlock(); | ||
4849 | |||
4841 | if (res->tsf && | 4850 | if (res->tsf && |
4842 | nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) | 4851 | nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) |
4843 | goto nla_put_failure; | 4852 | goto nla_put_failure; |
@@ -5502,6 +5511,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
5502 | return -EINVAL; | 5511 | return -EINVAL; |
5503 | if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | 5512 | if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && |
5504 | !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) | 5513 | !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) |
5514 | return -EINVAL; | ||
5505 | 5515 | ||
5506 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 5516 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
5507 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; | 5517 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; |
@@ -6529,14 +6539,13 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | |||
6529 | }; | 6539 | }; |
6530 | 6540 | ||
6531 | static int nl80211_set_cqm_txe(struct genl_info *info, | 6541 | static int nl80211_set_cqm_txe(struct genl_info *info, |
6532 | u32 rate, u32 pkts, u32 intvl) | 6542 | u32 rate, u32 pkts, u32 intvl) |
6533 | { | 6543 | { |
6534 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6544 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6535 | struct wireless_dev *wdev; | 6545 | struct wireless_dev *wdev; |
6536 | struct net_device *dev = info->user_ptr[1]; | 6546 | struct net_device *dev = info->user_ptr[1]; |
6537 | 6547 | ||
6538 | if ((rate < 0 || rate > 100) || | 6548 | if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL) |
6539 | (intvl < 0 || intvl > NL80211_CQM_TXE_MAX_INTVL)) | ||
6540 | return -EINVAL; | 6549 | return -EINVAL; |
6541 | 6550 | ||
6542 | wdev = dev->ieee80211_ptr; | 6551 | wdev = dev->ieee80211_ptr; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index b75756b05af7..6e5308998e30 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1796,7 +1796,7 @@ EXPORT_SYMBOL(regulatory_hint); | |||
1796 | */ | 1796 | */ |
1797 | void regulatory_hint_11d(struct wiphy *wiphy, | 1797 | void regulatory_hint_11d(struct wiphy *wiphy, |
1798 | enum ieee80211_band band, | 1798 | enum ieee80211_band band, |
1799 | u8 *country_ie, | 1799 | const u8 *country_ie, |
1800 | u8 country_ie_len) | 1800 | u8 country_ie_len) |
1801 | { | 1801 | { |
1802 | char alpha2[2]; | 1802 | char alpha2[2]; |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index f023c8a31c60..4c0a32ffd530 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -81,7 +81,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, | |||
81 | */ | 81 | */ |
82 | void regulatory_hint_11d(struct wiphy *wiphy, | 82 | void regulatory_hint_11d(struct wiphy *wiphy, |
83 | enum ieee80211_band band, | 83 | enum ieee80211_band band, |
84 | u8 *country_ie, | 84 | const u8 *country_ie, |
85 | u8 country_ie_len); | 85 | u8 country_ie_len); |
86 | 86 | ||
87 | /** | 87 | /** |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 9596015975d2..01592d7d4789 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -23,18 +23,23 @@ | |||
23 | 23 | ||
24 | static void bss_release(struct kref *ref) | 24 | static void bss_release(struct kref *ref) |
25 | { | 25 | { |
26 | struct cfg80211_bss_ies *ies; | ||
26 | struct cfg80211_internal_bss *bss; | 27 | struct cfg80211_internal_bss *bss; |
27 | 28 | ||
28 | bss = container_of(ref, struct cfg80211_internal_bss, ref); | 29 | bss = container_of(ref, struct cfg80211_internal_bss, ref); |
30 | |||
31 | if (WARN_ON(atomic_read(&bss->hold))) | ||
32 | return; | ||
33 | |||
29 | if (bss->pub.free_priv) | 34 | if (bss->pub.free_priv) |
30 | bss->pub.free_priv(&bss->pub); | 35 | bss->pub.free_priv(&bss->pub); |
31 | 36 | ||
32 | if (bss->beacon_ies_allocated) | 37 | ies = (void *)rcu_access_pointer(bss->pub.beacon_ies); |
33 | kfree(bss->pub.beacon_ies); | 38 | if (ies) |
34 | if (bss->proberesp_ies_allocated) | 39 | kfree_rcu(ies, rcu_head); |
35 | kfree(bss->pub.proberesp_ies); | 40 | ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies); |
36 | 41 | if (ies) | |
37 | BUG_ON(atomic_read(&bss->hold)); | 42 | kfree_rcu(ies, rcu_head); |
38 | 43 | ||
39 | kfree(bss); | 44 | kfree(bss); |
40 | } | 45 | } |
@@ -236,9 +241,8 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, | |||
236 | struct cfg80211_internal_bss *bss; | 241 | struct cfg80211_internal_bss *bss; |
237 | unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); | 242 | unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); |
238 | 243 | ||
239 | list_for_each_entry(bss, &dev->bss_list, list) { | 244 | list_for_each_entry(bss, &dev->bss_list, list) |
240 | bss->ts -= age_jiffies; | 245 | bss->ts -= age_jiffies; |
241 | } | ||
242 | } | 246 | } |
243 | 247 | ||
244 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev) | 248 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev) |
@@ -287,7 +291,7 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, | |||
287 | } | 291 | } |
288 | EXPORT_SYMBOL(cfg80211_find_vendor_ie); | 292 | EXPORT_SYMBOL(cfg80211_find_vendor_ie); |
289 | 293 | ||
290 | static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) | 294 | static int cmp_ies(u8 num, const u8 *ies1, int len1, const u8 *ies2, int len2) |
291 | { | 295 | { |
292 | const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); | 296 | const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); |
293 | const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); | 297 | const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); |
@@ -307,10 +311,10 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) | |||
307 | return memcmp(ie1 + 2, ie2 + 2, ie1[1]); | 311 | return memcmp(ie1 + 2, ie2 + 2, ie1[1]); |
308 | } | 312 | } |
309 | 313 | ||
310 | static bool is_bss(struct cfg80211_bss *a, | 314 | static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, |
311 | const u8 *bssid, | ||
312 | const u8 *ssid, size_t ssid_len) | 315 | const u8 *ssid, size_t ssid_len) |
313 | { | 316 | { |
317 | const struct cfg80211_bss_ies *ies; | ||
314 | const u8 *ssidie; | 318 | const u8 *ssidie; |
315 | 319 | ||
316 | if (bssid && !ether_addr_equal(a->bssid, bssid)) | 320 | if (bssid && !ether_addr_equal(a->bssid, bssid)) |
@@ -319,9 +323,10 @@ static bool is_bss(struct cfg80211_bss *a, | |||
319 | if (!ssid) | 323 | if (!ssid) |
320 | return true; | 324 | return true; |
321 | 325 | ||
322 | ssidie = cfg80211_find_ie(WLAN_EID_SSID, | 326 | ies = rcu_access_pointer(a->ies); |
323 | a->information_elements, | 327 | if (!ies) |
324 | a->len_information_elements); | 328 | return false; |
329 | ssidie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); | ||
325 | if (!ssidie) | 330 | if (!ssidie) |
326 | return false; | 331 | return false; |
327 | if (ssidie[1] != ssid_len) | 332 | if (ssidie[1] != ssid_len) |
@@ -331,20 +336,21 @@ static bool is_bss(struct cfg80211_bss *a, | |||
331 | 336 | ||
332 | static bool is_mesh_bss(struct cfg80211_bss *a) | 337 | static bool is_mesh_bss(struct cfg80211_bss *a) |
333 | { | 338 | { |
339 | const struct cfg80211_bss_ies *ies; | ||
334 | const u8 *ie; | 340 | const u8 *ie; |
335 | 341 | ||
336 | if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) | 342 | if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) |
337 | return false; | 343 | return false; |
338 | 344 | ||
339 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, | 345 | ies = rcu_access_pointer(a->ies); |
340 | a->information_elements, | 346 | if (!ies) |
341 | a->len_information_elements); | 347 | return false; |
348 | |||
349 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len); | ||
342 | if (!ie) | 350 | if (!ie) |
343 | return false; | 351 | return false; |
344 | 352 | ||
345 | ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, | 353 | ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len); |
346 | a->information_elements, | ||
347 | a->len_information_elements); | ||
348 | if (!ie) | 354 | if (!ie) |
349 | return false; | 355 | return false; |
350 | 356 | ||
@@ -355,14 +361,17 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
355 | const u8 *meshid, size_t meshidlen, | 361 | const u8 *meshid, size_t meshidlen, |
356 | const u8 *meshcfg) | 362 | const u8 *meshcfg) |
357 | { | 363 | { |
364 | const struct cfg80211_bss_ies *ies; | ||
358 | const u8 *ie; | 365 | const u8 *ie; |
359 | 366 | ||
360 | if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) | 367 | if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) |
361 | return false; | 368 | return false; |
362 | 369 | ||
363 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, | 370 | ies = rcu_access_pointer(a->ies); |
364 | a->information_elements, | 371 | if (!ies) |
365 | a->len_information_elements); | 372 | return false; |
373 | |||
374 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len); | ||
366 | if (!ie) | 375 | if (!ie) |
367 | return false; | 376 | return false; |
368 | if (ie[1] != meshidlen) | 377 | if (ie[1] != meshidlen) |
@@ -370,9 +379,7 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
370 | if (memcmp(ie + 2, meshid, meshidlen)) | 379 | if (memcmp(ie + 2, meshid, meshidlen)) |
371 | return false; | 380 | return false; |
372 | 381 | ||
373 | ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, | 382 | ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len); |
374 | a->information_elements, | ||
375 | a->len_information_elements); | ||
376 | if (!ie) | 383 | if (!ie) |
377 | return false; | 384 | return false; |
378 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) | 385 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) |
@@ -384,30 +391,33 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
384 | * part in the same mesh. | 391 | * part in the same mesh. |
385 | */ | 392 | */ |
386 | return memcmp(ie + 2, meshcfg, | 393 | return memcmp(ie + 2, meshcfg, |
387 | sizeof(struct ieee80211_meshconf_ie) - 2) == 0; | 394 | sizeof(struct ieee80211_meshconf_ie) - 2) == 0; |
388 | } | 395 | } |
389 | 396 | ||
390 | static int cmp_bss_core(struct cfg80211_bss *a, | 397 | static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b) |
391 | struct cfg80211_bss *b) | ||
392 | { | 398 | { |
399 | const struct cfg80211_bss_ies *a_ies, *b_ies; | ||
393 | int r; | 400 | int r; |
394 | 401 | ||
395 | if (a->channel != b->channel) | 402 | if (a->channel != b->channel) |
396 | return b->channel->center_freq - a->channel->center_freq; | 403 | return b->channel->center_freq - a->channel->center_freq; |
397 | 404 | ||
398 | if (is_mesh_bss(a) && is_mesh_bss(b)) { | 405 | if (is_mesh_bss(a) && is_mesh_bss(b)) { |
406 | a_ies = rcu_access_pointer(a->ies); | ||
407 | if (!a_ies) | ||
408 | return -1; | ||
409 | b_ies = rcu_access_pointer(b->ies); | ||
410 | if (!b_ies) | ||
411 | return 1; | ||
412 | |||
399 | r = cmp_ies(WLAN_EID_MESH_ID, | 413 | r = cmp_ies(WLAN_EID_MESH_ID, |
400 | a->information_elements, | 414 | a_ies->data, a_ies->len, |
401 | a->len_information_elements, | 415 | b_ies->data, b_ies->len); |
402 | b->information_elements, | ||
403 | b->len_information_elements); | ||
404 | if (r) | 416 | if (r) |
405 | return r; | 417 | return r; |
406 | return cmp_ies(WLAN_EID_MESH_CONFIG, | 418 | return cmp_ies(WLAN_EID_MESH_CONFIG, |
407 | a->information_elements, | 419 | a_ies->data, a_ies->len, |
408 | a->len_information_elements, | 420 | b_ies->data, b_ies->len); |
409 | b->information_elements, | ||
410 | b->len_information_elements); | ||
411 | } | 421 | } |
412 | 422 | ||
413 | /* | 423 | /* |
@@ -420,22 +430,28 @@ static int cmp_bss_core(struct cfg80211_bss *a, | |||
420 | static int cmp_bss(struct cfg80211_bss *a, | 430 | static int cmp_bss(struct cfg80211_bss *a, |
421 | struct cfg80211_bss *b) | 431 | struct cfg80211_bss *b) |
422 | { | 432 | { |
433 | const struct cfg80211_bss_ies *a_ies, *b_ies; | ||
423 | int r; | 434 | int r; |
424 | 435 | ||
425 | r = cmp_bss_core(a, b); | 436 | r = cmp_bss_core(a, b); |
426 | if (r) | 437 | if (r) |
427 | return r; | 438 | return r; |
428 | 439 | ||
440 | a_ies = rcu_access_pointer(a->ies); | ||
441 | if (!a_ies) | ||
442 | return -1; | ||
443 | b_ies = rcu_access_pointer(b->ies); | ||
444 | if (!b_ies) | ||
445 | return 1; | ||
446 | |||
429 | return cmp_ies(WLAN_EID_SSID, | 447 | return cmp_ies(WLAN_EID_SSID, |
430 | a->information_elements, | 448 | a_ies->data, a_ies->len, |
431 | a->len_information_elements, | 449 | b_ies->data, b_ies->len); |
432 | b->information_elements, | ||
433 | b->len_information_elements); | ||
434 | } | 450 | } |
435 | 451 | ||
436 | static int cmp_hidden_bss(struct cfg80211_bss *a, | 452 | static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b) |
437 | struct cfg80211_bss *b) | ||
438 | { | 453 | { |
454 | const struct cfg80211_bss_ies *a_ies, *b_ies; | ||
439 | const u8 *ie1; | 455 | const u8 *ie1; |
440 | const u8 *ie2; | 456 | const u8 *ie2; |
441 | int i; | 457 | int i; |
@@ -445,17 +461,26 @@ static int cmp_hidden_bss(struct cfg80211_bss *a, | |||
445 | if (r) | 461 | if (r) |
446 | return r; | 462 | return r; |
447 | 463 | ||
448 | ie1 = cfg80211_find_ie(WLAN_EID_SSID, | 464 | a_ies = rcu_access_pointer(a->ies); |
449 | a->information_elements, | 465 | if (!a_ies) |
450 | a->len_information_elements); | 466 | return -1; |
451 | ie2 = cfg80211_find_ie(WLAN_EID_SSID, | 467 | b_ies = rcu_access_pointer(b->ies); |
452 | b->information_elements, | 468 | if (!b_ies) |
453 | b->len_information_elements); | 469 | return 1; |
470 | |||
471 | ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len); | ||
472 | ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len); | ||
454 | 473 | ||
455 | /* Key comparator must use same algorithm in any rb-tree | 474 | /* |
475 | * Key comparator must use same algorithm in any rb-tree | ||
456 | * search function (order is important), otherwise ordering | 476 | * search function (order is important), otherwise ordering |
457 | * of items in the tree is broken and search gives incorrect | 477 | * of items in the tree is broken and search gives incorrect |
458 | * results. This code uses same order as cmp_ies() does. */ | 478 | * results. This code uses same order as cmp_ies() does. |
479 | * | ||
480 | * Note that due to the differring behaviour with hidden SSIDs | ||
481 | * this function only works when "b" is the tree element and | ||
482 | * "a" is the key we're looking for. | ||
483 | */ | ||
459 | 484 | ||
460 | /* sort missing IE before (left of) present IE */ | 485 | /* sort missing IE before (left of) present IE */ |
461 | if (!ie1) | 486 | if (!ie1) |
@@ -471,10 +496,14 @@ static int cmp_hidden_bss(struct cfg80211_bss *a, | |||
471 | if (ie1[1] != ie2[1]) | 496 | if (ie1[1] != ie2[1]) |
472 | return ie2[1] - ie1[1]; | 497 | return ie2[1] - ie1[1]; |
473 | 498 | ||
474 | /* zeroed SSID ie is another indication of a hidden bss */ | 499 | /* |
500 | * zeroed SSID ie is another indication of a hidden bss; | ||
501 | * if it isn't zeroed just return the regular sort value | ||
502 | * to find the next candidate | ||
503 | */ | ||
475 | for (i = 0; i < ie2[1]; i++) | 504 | for (i = 0; i < ie2[1]; i++) |
476 | if (ie2[i + 2]) | 505 | if (ie2[i + 2]) |
477 | return -1; | 506 | return memcmp(ie1 + 2, ie2 + 2, ie1[1]); |
478 | 507 | ||
479 | return 0; | 508 | return 0; |
480 | } | 509 | } |
@@ -600,7 +629,7 @@ rb_find_bss(struct cfg80211_registered_device *dev, | |||
600 | 629 | ||
601 | static struct cfg80211_internal_bss * | 630 | static struct cfg80211_internal_bss * |
602 | rb_find_hidden_bss(struct cfg80211_registered_device *dev, | 631 | rb_find_hidden_bss(struct cfg80211_registered_device *dev, |
603 | struct cfg80211_internal_bss *res) | 632 | struct cfg80211_internal_bss *res) |
604 | { | 633 | { |
605 | struct rb_node *n = dev->bss_tree.rb_node; | 634 | struct rb_node *n = dev->bss_tree.rb_node; |
606 | struct cfg80211_internal_bss *bss; | 635 | struct cfg80211_internal_bss *bss; |
@@ -623,127 +652,86 @@ rb_find_hidden_bss(struct cfg80211_registered_device *dev, | |||
623 | 652 | ||
624 | static void | 653 | static void |
625 | copy_hidden_ies(struct cfg80211_internal_bss *res, | 654 | copy_hidden_ies(struct cfg80211_internal_bss *res, |
626 | struct cfg80211_internal_bss *hidden) | 655 | struct cfg80211_internal_bss *hidden) |
627 | { | 656 | { |
628 | if (unlikely(res->pub.beacon_ies)) | 657 | const struct cfg80211_bss_ies *ies; |
629 | return; | 658 | |
630 | if (WARN_ON(!hidden->pub.beacon_ies)) | 659 | if (rcu_access_pointer(res->pub.beacon_ies)) |
631 | return; | 660 | return; |
632 | 661 | ||
633 | res->pub.beacon_ies = kmalloc(hidden->pub.len_beacon_ies, GFP_ATOMIC); | 662 | ies = rcu_access_pointer(hidden->pub.beacon_ies); |
634 | if (unlikely(!res->pub.beacon_ies)) | 663 | if (WARN_ON(!ies)) |
635 | return; | 664 | return; |
636 | 665 | ||
637 | res->beacon_ies_allocated = true; | 666 | ies = kmemdup(ies, sizeof(*ies) + ies->len, GFP_ATOMIC); |
638 | res->pub.len_beacon_ies = hidden->pub.len_beacon_ies; | 667 | if (unlikely(!ies)) |
639 | memcpy(res->pub.beacon_ies, hidden->pub.beacon_ies, | 668 | return; |
640 | res->pub.len_beacon_ies); | 669 | rcu_assign_pointer(res->pub.beacon_ies, ies); |
641 | } | 670 | } |
642 | 671 | ||
643 | static struct cfg80211_internal_bss * | 672 | static struct cfg80211_internal_bss * |
644 | cfg80211_bss_update(struct cfg80211_registered_device *dev, | 673 | cfg80211_bss_update(struct cfg80211_registered_device *dev, |
645 | struct cfg80211_internal_bss *res) | 674 | struct cfg80211_internal_bss *tmp) |
646 | { | 675 | { |
647 | struct cfg80211_internal_bss *found = NULL; | 676 | struct cfg80211_internal_bss *found = NULL; |
648 | 677 | ||
649 | /* | 678 | if (WARN_ON(!tmp->pub.channel)) |
650 | * The reference to "res" is donated to this function. | ||
651 | */ | ||
652 | |||
653 | if (WARN_ON(!res->pub.channel)) { | ||
654 | kref_put(&res->ref, bss_release); | ||
655 | return NULL; | 679 | return NULL; |
656 | } | ||
657 | 680 | ||
658 | res->ts = jiffies; | 681 | tmp->ts = jiffies; |
659 | 682 | ||
660 | spin_lock_bh(&dev->bss_lock); | 683 | spin_lock_bh(&dev->bss_lock); |
661 | 684 | ||
662 | found = rb_find_bss(dev, res); | 685 | if (WARN_ON(!rcu_access_pointer(tmp->pub.ies))) { |
686 | spin_unlock_bh(&dev->bss_lock); | ||
687 | return NULL; | ||
688 | } | ||
689 | |||
690 | found = rb_find_bss(dev, tmp); | ||
663 | 691 | ||
664 | if (found) { | 692 | if (found) { |
665 | found->pub.beacon_interval = res->pub.beacon_interval; | 693 | found->pub.beacon_interval = tmp->pub.beacon_interval; |
666 | found->pub.tsf = res->pub.tsf; | 694 | found->pub.tsf = tmp->pub.tsf; |
667 | found->pub.signal = res->pub.signal; | 695 | found->pub.signal = tmp->pub.signal; |
668 | found->pub.capability = res->pub.capability; | 696 | found->pub.capability = tmp->pub.capability; |
669 | found->ts = res->ts; | 697 | found->ts = tmp->ts; |
670 | 698 | ||
671 | /* Update IEs */ | 699 | /* Update IEs */ |
672 | if (res->pub.proberesp_ies) { | 700 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { |
673 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); | 701 | const struct cfg80211_bss_ies *old; |
674 | size_t ielen = res->pub.len_proberesp_ies; | ||
675 | |||
676 | if (found->pub.proberesp_ies && | ||
677 | !found->proberesp_ies_allocated && | ||
678 | ksize(found) >= used + ielen) { | ||
679 | memcpy(found->pub.proberesp_ies, | ||
680 | res->pub.proberesp_ies, ielen); | ||
681 | found->pub.len_proberesp_ies = ielen; | ||
682 | } else { | ||
683 | u8 *ies = found->pub.proberesp_ies; | ||
684 | |||
685 | if (found->proberesp_ies_allocated) | ||
686 | ies = krealloc(ies, ielen, GFP_ATOMIC); | ||
687 | else | ||
688 | ies = kmalloc(ielen, GFP_ATOMIC); | ||
689 | |||
690 | if (ies) { | ||
691 | memcpy(ies, res->pub.proberesp_ies, | ||
692 | ielen); | ||
693 | found->proberesp_ies_allocated = true; | ||
694 | found->pub.proberesp_ies = ies; | ||
695 | found->pub.len_proberesp_ies = ielen; | ||
696 | } | ||
697 | } | ||
698 | 702 | ||
703 | old = rcu_access_pointer(found->pub.proberesp_ies); | ||
704 | |||
705 | rcu_assign_pointer(found->pub.proberesp_ies, | ||
706 | tmp->pub.proberesp_ies); | ||
699 | /* Override possible earlier Beacon frame IEs */ | 707 | /* Override possible earlier Beacon frame IEs */ |
700 | found->pub.information_elements = | 708 | rcu_assign_pointer(found->pub.ies, |
701 | found->pub.proberesp_ies; | 709 | tmp->pub.proberesp_ies); |
702 | found->pub.len_information_elements = | 710 | if (old) |
703 | found->pub.len_proberesp_ies; | 711 | kfree_rcu((struct cfg80211_bss_ies *)old, |
704 | } | 712 | rcu_head); |
705 | if (res->pub.beacon_ies) { | 713 | } else if (rcu_access_pointer(tmp->pub.beacon_ies)) { |
706 | size_t used = dev->wiphy.bss_priv_size + sizeof(*res); | 714 | const struct cfg80211_bss_ies *old, *ies; |
707 | size_t ielen = res->pub.len_beacon_ies; | 715 | |
708 | bool information_elements_is_beacon_ies = | 716 | old = rcu_access_pointer(found->pub.beacon_ies); |
709 | (found->pub.information_elements == | 717 | ies = rcu_access_pointer(found->pub.ies); |
710 | found->pub.beacon_ies); | 718 | |
711 | 719 | rcu_assign_pointer(found->pub.beacon_ies, | |
712 | if (found->pub.beacon_ies && | 720 | tmp->pub.beacon_ies); |
713 | !found->beacon_ies_allocated && | ||
714 | ksize(found) >= used + ielen) { | ||
715 | memcpy(found->pub.beacon_ies, | ||
716 | res->pub.beacon_ies, ielen); | ||
717 | found->pub.len_beacon_ies = ielen; | ||
718 | } else { | ||
719 | u8 *ies = found->pub.beacon_ies; | ||
720 | |||
721 | if (found->beacon_ies_allocated) | ||
722 | ies = krealloc(ies, ielen, GFP_ATOMIC); | ||
723 | else | ||
724 | ies = kmalloc(ielen, GFP_ATOMIC); | ||
725 | |||
726 | if (ies) { | ||
727 | memcpy(ies, res->pub.beacon_ies, | ||
728 | ielen); | ||
729 | found->beacon_ies_allocated = true; | ||
730 | found->pub.beacon_ies = ies; | ||
731 | found->pub.len_beacon_ies = ielen; | ||
732 | } | ||
733 | } | ||
734 | 721 | ||
735 | /* Override IEs if they were from a beacon before */ | 722 | /* Override IEs if they were from a beacon before */ |
736 | if (information_elements_is_beacon_ies) { | 723 | if (old == ies) |
737 | found->pub.information_elements = | 724 | rcu_assign_pointer(found->pub.ies, |
738 | found->pub.beacon_ies; | 725 | tmp->pub.beacon_ies); |
739 | found->pub.len_information_elements = | ||
740 | found->pub.len_beacon_ies; | ||
741 | } | ||
742 | } | ||
743 | 726 | ||
744 | kref_put(&res->ref, bss_release); | 727 | if (old) |
728 | kfree_rcu((struct cfg80211_bss_ies *)old, | ||
729 | rcu_head); | ||
730 | } | ||
745 | } else { | 731 | } else { |
732 | struct cfg80211_internal_bss *new; | ||
746 | struct cfg80211_internal_bss *hidden; | 733 | struct cfg80211_internal_bss *hidden; |
734 | struct cfg80211_bss_ies *ies; | ||
747 | 735 | ||
748 | /* First check if the beacon is a probe response from | 736 | /* First check if the beacon is a probe response from |
749 | * a hidden bss. If so, copy beacon ies (with nullified | 737 | * a hidden bss. If so, copy beacon ies (with nullified |
@@ -754,14 +742,32 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
754 | /* TODO: The code is not trying to update existing probe | 742 | /* TODO: The code is not trying to update existing probe |
755 | * response bss entries when beacon ies are | 743 | * response bss entries when beacon ies are |
756 | * getting changed. */ | 744 | * getting changed. */ |
757 | hidden = rb_find_hidden_bss(dev, res); | 745 | hidden = rb_find_hidden_bss(dev, tmp); |
758 | if (hidden) | 746 | if (hidden) |
759 | copy_hidden_ies(res, hidden); | 747 | copy_hidden_ies(tmp, hidden); |
760 | 748 | ||
761 | /* this "consumes" the reference */ | 749 | /* |
762 | list_add_tail(&res->list, &dev->bss_list); | 750 | * create a copy -- the "res" variable that is passed in |
763 | rb_insert_bss(dev, res); | 751 | * is allocated on the stack since it's not needed in the |
764 | found = res; | 752 | * more common case of an update |
753 | */ | ||
754 | new = kzalloc(sizeof(*new) + dev->wiphy.bss_priv_size, | ||
755 | GFP_ATOMIC); | ||
756 | if (!new) { | ||
757 | ies = (void *)rcu_dereference(tmp->pub.beacon_ies); | ||
758 | if (ies) | ||
759 | kfree_rcu(ies, rcu_head); | ||
760 | ies = (void *)rcu_dereference(tmp->pub.proberesp_ies); | ||
761 | if (ies) | ||
762 | kfree_rcu(ies, rcu_head); | ||
763 | spin_unlock_bh(&dev->bss_lock); | ||
764 | return NULL; | ||
765 | } | ||
766 | memcpy(new, tmp, sizeof(*new)); | ||
767 | kref_init(&new->ref); | ||
768 | list_add_tail(&new->list, &dev->bss_list); | ||
769 | rb_insert_bss(dev, new); | ||
770 | found = new; | ||
765 | } | 771 | } |
766 | 772 | ||
767 | dev->bss_generation++; | 773 | dev->bss_generation++; |
@@ -810,14 +816,12 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
810 | u16 beacon_interval, const u8 *ie, size_t ielen, | 816 | u16 beacon_interval, const u8 *ie, size_t ielen, |
811 | s32 signal, gfp_t gfp) | 817 | s32 signal, gfp_t gfp) |
812 | { | 818 | { |
813 | struct cfg80211_internal_bss *res; | 819 | struct cfg80211_bss_ies *ies; |
814 | size_t privsz; | 820 | struct cfg80211_internal_bss tmp = {}, *res; |
815 | 821 | ||
816 | if (WARN_ON(!wiphy)) | 822 | if (WARN_ON(!wiphy)) |
817 | return NULL; | 823 | return NULL; |
818 | 824 | ||
819 | privsz = wiphy->bss_priv_size; | ||
820 | |||
821 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && | 825 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && |
822 | (signal < 0 || signal > 100))) | 826 | (signal < 0 || signal > 100))) |
823 | return NULL; | 827 | return NULL; |
@@ -826,36 +830,33 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
826 | if (!channel) | 830 | if (!channel) |
827 | return NULL; | 831 | return NULL; |
828 | 832 | ||
829 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); | 833 | memcpy(tmp.pub.bssid, bssid, ETH_ALEN); |
830 | if (!res) | 834 | tmp.pub.channel = channel; |
831 | return NULL; | 835 | tmp.pub.signal = signal; |
832 | 836 | tmp.pub.tsf = tsf; | |
833 | memcpy(res->pub.bssid, bssid, ETH_ALEN); | 837 | tmp.pub.beacon_interval = beacon_interval; |
834 | res->pub.channel = channel; | 838 | tmp.pub.capability = capability; |
835 | res->pub.signal = signal; | ||
836 | res->pub.tsf = tsf; | ||
837 | res->pub.beacon_interval = beacon_interval; | ||
838 | res->pub.capability = capability; | ||
839 | /* | 839 | /* |
840 | * Since we do not know here whether the IEs are from a Beacon or Probe | 840 | * Since we do not know here whether the IEs are from a Beacon or Probe |
841 | * Response frame, we need to pick one of the options and only use it | 841 | * Response frame, we need to pick one of the options and only use it |
842 | * with the driver that does not provide the full Beacon/Probe Response | 842 | * with the driver that does not provide the full Beacon/Probe Response |
843 | * frame. Use Beacon frame pointer to avoid indicating that this should | 843 | * frame. Use Beacon frame pointer to avoid indicating that this should |
844 | * override the information_elements pointer should we have received an | 844 | * override the iies pointer should we have received an earlier |
845 | * earlier indication of Probe Response data. | 845 | * indication of Probe Response data. |
846 | * | 846 | * |
847 | * The initial buffer for the IEs is allocated with the BSS entry and | 847 | * The initial buffer for the IEs is allocated with the BSS entry and |
848 | * is located after the private area. | 848 | * is located after the private area. |
849 | */ | 849 | */ |
850 | res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz; | 850 | ies = kmalloc(sizeof(*ies) + ielen, gfp); |
851 | memcpy(res->pub.beacon_ies, ie, ielen); | 851 | if (!ies) |
852 | res->pub.len_beacon_ies = ielen; | 852 | return NULL; |
853 | res->pub.information_elements = res->pub.beacon_ies; | 853 | ies->len = ielen; |
854 | res->pub.len_information_elements = res->pub.len_beacon_ies; | 854 | memcpy(ies->data, ie, ielen); |
855 | 855 | ||
856 | kref_init(&res->ref); | 856 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); |
857 | rcu_assign_pointer(tmp.pub.ies, ies); | ||
857 | 858 | ||
858 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), res); | 859 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); |
859 | if (!res) | 860 | if (!res) |
860 | return NULL; | 861 | return NULL; |
861 | 862 | ||
@@ -874,10 +875,10 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
874 | struct ieee80211_mgmt *mgmt, size_t len, | 875 | struct ieee80211_mgmt *mgmt, size_t len, |
875 | s32 signal, gfp_t gfp) | 876 | s32 signal, gfp_t gfp) |
876 | { | 877 | { |
877 | struct cfg80211_internal_bss *res; | 878 | struct cfg80211_internal_bss tmp = {}, *res; |
879 | struct cfg80211_bss_ies *ies; | ||
878 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | 880 | size_t ielen = len - offsetof(struct ieee80211_mgmt, |
879 | u.probe_resp.variable); | 881 | u.probe_resp.variable); |
880 | size_t privsz; | ||
881 | 882 | ||
882 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != | 883 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != |
883 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); | 884 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); |
@@ -897,45 +898,31 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
897 | if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) | 898 | if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) |
898 | return NULL; | 899 | return NULL; |
899 | 900 | ||
900 | privsz = wiphy->bss_priv_size; | ||
901 | |||
902 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, | 901 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, |
903 | ielen, channel); | 902 | ielen, channel); |
904 | if (!channel) | 903 | if (!channel) |
905 | return NULL; | 904 | return NULL; |
906 | 905 | ||
907 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); | 906 | ies = kmalloc(sizeof(*ies) + ielen, gfp); |
908 | if (!res) | 907 | if (!ies) |
909 | return NULL; | 908 | return NULL; |
909 | ies->len = ielen; | ||
910 | memcpy(ies->data, mgmt->u.probe_resp.variable, ielen); | ||
910 | 911 | ||
911 | memcpy(res->pub.bssid, mgmt->bssid, ETH_ALEN); | 912 | if (ieee80211_is_probe_resp(mgmt->frame_control)) |
912 | res->pub.channel = channel; | 913 | rcu_assign_pointer(tmp.pub.proberesp_ies, ies); |
913 | res->pub.signal = signal; | 914 | else |
914 | res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); | 915 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); |
915 | res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | 916 | rcu_assign_pointer(tmp.pub.ies, ies); |
916 | res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | 917 | |
917 | /* | 918 | memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); |
918 | * The initial buffer for the IEs is allocated with the BSS entry and | 919 | tmp.pub.channel = channel; |
919 | * is located after the private area. | 920 | tmp.pub.signal = signal; |
920 | */ | 921 | tmp.pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); |
921 | if (ieee80211_is_probe_resp(mgmt->frame_control)) { | 922 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); |
922 | res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz; | 923 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); |
923 | memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable, | 924 | |
924 | ielen); | 925 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); |
925 | res->pub.len_proberesp_ies = ielen; | ||
926 | res->pub.information_elements = res->pub.proberesp_ies; | ||
927 | res->pub.len_information_elements = res->pub.len_proberesp_ies; | ||
928 | } else { | ||
929 | res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz; | ||
930 | memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen); | ||
931 | res->pub.len_beacon_ies = ielen; | ||
932 | res->pub.information_elements = res->pub.beacon_ies; | ||
933 | res->pub.len_information_elements = res->pub.len_beacon_ies; | ||
934 | } | ||
935 | |||
936 | kref_init(&res->ref); | ||
937 | |||
938 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), res); | ||
939 | if (!res) | 926 | if (!res) |
940 | return NULL; | 927 | return NULL; |
941 | 928 | ||
@@ -1127,22 +1114,21 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1127 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); | 1114 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); |
1128 | 1115 | ||
1129 | static void ieee80211_scan_add_ies(struct iw_request_info *info, | 1116 | static void ieee80211_scan_add_ies(struct iw_request_info *info, |
1130 | struct cfg80211_bss *bss, | 1117 | const struct cfg80211_bss_ies *ies, |
1131 | char **current_ev, char *end_buf) | 1118 | char **current_ev, char *end_buf) |
1132 | { | 1119 | { |
1133 | u8 *pos, *end, *next; | 1120 | const u8 *pos, *end, *next; |
1134 | struct iw_event iwe; | 1121 | struct iw_event iwe; |
1135 | 1122 | ||
1136 | if (!bss->information_elements || | 1123 | if (!ies) |
1137 | !bss->len_information_elements) | ||
1138 | return; | 1124 | return; |
1139 | 1125 | ||
1140 | /* | 1126 | /* |
1141 | * If needed, fragment the IEs buffer (at IE boundaries) into short | 1127 | * If needed, fragment the IEs buffer (at IE boundaries) into short |
1142 | * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. | 1128 | * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. |
1143 | */ | 1129 | */ |
1144 | pos = bss->information_elements; | 1130 | pos = ies->data; |
1145 | end = pos + bss->len_information_elements; | 1131 | end = pos + ies->len; |
1146 | 1132 | ||
1147 | while (end - pos > IW_GENERIC_IE_MAX) { | 1133 | while (end - pos > IW_GENERIC_IE_MAX) { |
1148 | next = pos + 2 + pos[1]; | 1134 | next = pos + 2 + pos[1]; |
@@ -1153,7 +1139,8 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info, | |||
1153 | iwe.cmd = IWEVGENIE; | 1139 | iwe.cmd = IWEVGENIE; |
1154 | iwe.u.data.length = next - pos; | 1140 | iwe.u.data.length = next - pos; |
1155 | *current_ev = iwe_stream_add_point(info, *current_ev, | 1141 | *current_ev = iwe_stream_add_point(info, *current_ev, |
1156 | end_buf, &iwe, pos); | 1142 | end_buf, &iwe, |
1143 | (void *)pos); | ||
1157 | 1144 | ||
1158 | pos = next; | 1145 | pos = next; |
1159 | } | 1146 | } |
@@ -1163,7 +1150,8 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info, | |||
1163 | iwe.cmd = IWEVGENIE; | 1150 | iwe.cmd = IWEVGENIE; |
1164 | iwe.u.data.length = end - pos; | 1151 | iwe.u.data.length = end - pos; |
1165 | *current_ev = iwe_stream_add_point(info, *current_ev, | 1152 | *current_ev = iwe_stream_add_point(info, *current_ev, |
1166 | end_buf, &iwe, pos); | 1153 | end_buf, &iwe, |
1154 | (void *)pos); | ||
1167 | } | 1155 | } |
1168 | } | 1156 | } |
1169 | 1157 | ||
@@ -1182,10 +1170,11 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1182 | struct cfg80211_internal_bss *bss, char *current_ev, | 1170 | struct cfg80211_internal_bss *bss, char *current_ev, |
1183 | char *end_buf) | 1171 | char *end_buf) |
1184 | { | 1172 | { |
1173 | const struct cfg80211_bss_ies *ies; | ||
1185 | struct iw_event iwe; | 1174 | struct iw_event iwe; |
1175 | const u8 *ie; | ||
1186 | u8 *buf, *cfg, *p; | 1176 | u8 *buf, *cfg, *p; |
1187 | u8 *ie = bss->pub.information_elements; | 1177 | int rem, i, sig; |
1188 | int rem = bss->pub.len_information_elements, i, sig; | ||
1189 | bool ismesh = false; | 1178 | bool ismesh = false; |
1190 | 1179 | ||
1191 | memset(&iwe, 0, sizeof(iwe)); | 1180 | memset(&iwe, 0, sizeof(iwe)); |
@@ -1250,7 +1239,17 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1250 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 1239 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1251 | &iwe, ""); | 1240 | &iwe, ""); |
1252 | 1241 | ||
1253 | while (rem >= 2) { | 1242 | rcu_read_lock(); |
1243 | ies = rcu_dereference(bss->pub.ies); | ||
1244 | if (ies) { | ||
1245 | rem = ies->len; | ||
1246 | ie = ies->data; | ||
1247 | } else { | ||
1248 | rem = 0; | ||
1249 | ie = NULL; | ||
1250 | } | ||
1251 | |||
1252 | while (ies && rem >= 2) { | ||
1254 | /* invalid data */ | 1253 | /* invalid data */ |
1255 | if (ie[1] > rem - 2) | 1254 | if (ie[1] > rem - 2) |
1256 | break; | 1255 | break; |
@@ -1262,7 +1261,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1262 | iwe.u.data.length = ie[1]; | 1261 | iwe.u.data.length = ie[1]; |
1263 | iwe.u.data.flags = 1; | 1262 | iwe.u.data.flags = 1; |
1264 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 1263 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1265 | &iwe, ie + 2); | 1264 | &iwe, (u8 *)ie + 2); |
1266 | break; | 1265 | break; |
1267 | case WLAN_EID_MESH_ID: | 1266 | case WLAN_EID_MESH_ID: |
1268 | memset(&iwe, 0, sizeof(iwe)); | 1267 | memset(&iwe, 0, sizeof(iwe)); |
@@ -1270,7 +1269,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1270 | iwe.u.data.length = ie[1]; | 1269 | iwe.u.data.length = ie[1]; |
1271 | iwe.u.data.flags = 1; | 1270 | iwe.u.data.flags = 1; |
1272 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 1271 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1273 | &iwe, ie + 2); | 1272 | &iwe, (u8 *)ie + 2); |
1274 | break; | 1273 | break; |
1275 | case WLAN_EID_MESH_CONFIG: | 1274 | case WLAN_EID_MESH_CONFIG: |
1276 | ismesh = true; | 1275 | ismesh = true; |
@@ -1279,7 +1278,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1279 | buf = kmalloc(50, GFP_ATOMIC); | 1278 | buf = kmalloc(50, GFP_ATOMIC); |
1280 | if (!buf) | 1279 | if (!buf) |
1281 | break; | 1280 | break; |
1282 | cfg = ie + 2; | 1281 | cfg = (u8 *)ie + 2; |
1283 | memset(&iwe, 0, sizeof(iwe)); | 1282 | memset(&iwe, 0, sizeof(iwe)); |
1284 | iwe.cmd = IWEVCUSTOM; | 1283 | iwe.cmd = IWEVCUSTOM; |
1285 | sprintf(buf, "Mesh Network Path Selection Protocol ID: " | 1284 | sprintf(buf, "Mesh Network Path Selection Protocol ID: " |
@@ -1377,7 +1376,8 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1377 | kfree(buf); | 1376 | kfree(buf); |
1378 | } | 1377 | } |
1379 | 1378 | ||
1380 | ieee80211_scan_add_ies(info, &bss->pub, ¤t_ev, end_buf); | 1379 | ieee80211_scan_add_ies(info, ies, ¤t_ev, end_buf); |
1380 | rcu_read_unlock(); | ||
1381 | 1381 | ||
1382 | return current_ev; | 1382 | return current_ev; |
1383 | } | 1383 | } |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index c7490027237d..f2431e41a373 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -417,7 +417,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
417 | struct cfg80211_bss *bss) | 417 | struct cfg80211_bss *bss) |
418 | { | 418 | { |
419 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 419 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
420 | u8 *country_ie; | 420 | const u8 *country_ie; |
421 | #ifdef CONFIG_CFG80211_WEXT | 421 | #ifdef CONFIG_CFG80211_WEXT |
422 | union iwreq_data wrqu; | 422 | union iwreq_data wrqu; |
423 | #endif | 423 | #endif |
@@ -501,7 +501,15 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
501 | wdev->sme_state = CFG80211_SME_CONNECTED; | 501 | wdev->sme_state = CFG80211_SME_CONNECTED; |
502 | cfg80211_upload_connect_keys(wdev); | 502 | cfg80211_upload_connect_keys(wdev); |
503 | 503 | ||
504 | country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); | 504 | rcu_read_lock(); |
505 | country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); | ||
506 | if (!country_ie) { | ||
507 | rcu_read_unlock(); | ||
508 | return; | ||
509 | } | ||
510 | |||
511 | country_ie = kmemdup(country_ie, 2 + country_ie[1], GFP_ATOMIC); | ||
512 | rcu_read_unlock(); | ||
505 | 513 | ||
506 | if (!country_ie) | 514 | if (!country_ie) |
507 | return; | 515 | return; |
@@ -515,6 +523,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
515 | bss->channel->band, | 523 | bss->channel->band, |
516 | country_ie + 2, | 524 | country_ie + 2, |
517 | country_ie[1]); | 525 | country_ie[1]); |
526 | kfree(country_ie); | ||
518 | } | 527 | } |
519 | 528 | ||
520 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 529 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 3cce6e486219..16d76a807c2f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -688,10 +688,13 @@ EXPORT_SYMBOL(cfg80211_classify8021d); | |||
688 | 688 | ||
689 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) | 689 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) |
690 | { | 690 | { |
691 | if (bss->information_elements == NULL) | 691 | const struct cfg80211_bss_ies *ies; |
692 | |||
693 | ies = rcu_dereference(bss->ies); | ||
694 | if (!ies) | ||
692 | return NULL; | 695 | return NULL; |
693 | return cfg80211_find_ie(ie, bss->information_elements, | 696 | |
694 | bss->len_information_elements); | 697 | return cfg80211_find_ie(ie, ies->data, ies->len); |
695 | } | 698 | } |
696 | EXPORT_SYMBOL(ieee80211_bss_get_ie); | 699 | EXPORT_SYMBOL(ieee80211_bss_get_ie); |
697 | 700 | ||
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 873af63187c0..fb9622f6d99c 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -242,13 +242,17 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, | |||
242 | 242 | ||
243 | wdev_lock(wdev); | 243 | wdev_lock(wdev); |
244 | if (wdev->current_bss) { | 244 | if (wdev->current_bss) { |
245 | const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub, | 245 | const u8 *ie; |
246 | WLAN_EID_SSID); | 246 | |
247 | rcu_read_lock(); | ||
248 | ie = ieee80211_bss_get_ie(&wdev->current_bss->pub, | ||
249 | WLAN_EID_SSID); | ||
247 | if (ie) { | 250 | if (ie) { |
248 | data->flags = 1; | 251 | data->flags = 1; |
249 | data->length = ie[1]; | 252 | data->length = ie[1]; |
250 | memcpy(ssid, ie + 2, data->length); | 253 | memcpy(ssid, ie + 2, data->length); |
251 | } | 254 | } |
255 | rcu_read_unlock(); | ||
252 | } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { | 256 | } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { |
253 | data->flags = 1; | 257 | data->flags = 1; |
254 | data->length = wdev->wext.connect.ssid_len; | 258 | data->length = wdev->wext.connect.ssid_len; |