aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/at76c50x-usb.c4
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig9
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c97
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c105
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c39
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h22
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c24
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c44
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c153
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c38
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-modparams.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c1
-rw-r--r--drivers/net/wireless/libertas/firmware.c1
-rw-r--r--drivers/net/wireless/mwifiex/Kconfig4
-rw-r--r--drivers/net/wireless/mwifiex/fw.h3
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c7
-rw-r--r--drivers/net/wireless/mwifiex/sdio.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c7
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c82
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.h1
-rw-r--r--include/linux/nl80211.h3
-rw-r--r--include/net/cfg80211.h18
-rw-r--r--include/net/mac80211.h17
-rw-r--r--net/mac80211/cfg.c182
-rw-r--r--net/mac80211/driver-ops.h37
-rw-r--r--net/mac80211/driver-trace.h15
-rw-r--r--net/mac80211/ibss.c2
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/mesh.c18
-rw-r--r--net/mac80211/mesh_plink.c96
-rw-r--r--net/mac80211/mlme.c2
-rw-r--r--net/mac80211/sta_info.h1
-rw-r--r--net/mac80211/util.c9
-rw-r--r--net/wireless/ethtool.c29
-rw-r--r--net/wireless/mesh.c1
-rw-r--r--net/wireless/nl80211.c7
-rw-r--r--net/wireless/scan.c6
43 files changed, 893 insertions, 244 deletions
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 5ad74c85a038..3df0146b797e 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1122,12 +1122,12 @@ exit:
1122static void at76_dump_mib_local(struct at76_priv *priv) 1122static void at76_dump_mib_local(struct at76_priv *priv)
1123{ 1123{
1124 int ret; 1124 int ret;
1125 struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL); 1125 struct mib_local *m = kmalloc(sizeof(*m), GFP_KERNEL);
1126 1126
1127 if (!m) 1127 if (!m)
1128 return; 1128 return;
1129 1129
1130 ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); 1130 ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(*m));
1131 if (ret < 0) { 1131 if (ret < 0) {
1132 wiphy_err(priv->hw->wiphy, 1132 wiphy_err(priv->hw->wiphy,
1133 "at76_get_mib (LOCAL) failed: %d\n", ret); 1133 "at76_get_mib (LOCAL) failed: %d\n", ret);
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index c5104533e24e..b480088b3dbe 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -36,6 +36,15 @@ config BRCMFMAC_SDIO
36 IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to 36 IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
37 use the driver for a SDIO wireless card. 37 use the driver for a SDIO wireless card.
38 38
39config BRCMFMAC_SDIO_OOB
40 bool "Out of band interrupt support for SDIO interface chipset"
41 depends on BRCMFMAC_SDIO
42 ---help---
43 This option enables out-of-band interrupt support for Broadcom
44 SDIO Wifi chipset using fullmac in order to gain better
45 performance and deep sleep wake up capability on certain
46 platforms. Say N if you are unsure.
47
39config BRCMFMAC_USB 48config BRCMFMAC_USB
40 bool "USB bus interface support for FullMAC driver" 49 bool "USB bus interface support for FullMAC driver"
41 depends on USB 50 depends on USB
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index e925290b432b..4add7da24681 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -39,37 +39,113 @@
39 39
40#define SDIOH_API_ACCESS_RETRY_LIMIT 2 40#define SDIOH_API_ACCESS_RETRY_LIMIT 2
41 41
42static void brcmf_sdioh_irqhandler(struct sdio_func *func) 42#ifdef CONFIG_BRCMFMAC_SDIO_OOB
43static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
43{ 44{
44 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); 45 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(dev_id);
45 46
46 brcmf_dbg(TRACE, "***IRQHandler\n"); 47 brcmf_dbg(INTR, "oob intr triggered\n");
47 48
48 sdio_release_host(func); 49 /*
50 * out-of-band interrupt is level-triggered which won't
51 * be cleared until dpc
52 */
53 if (sdiodev->irq_en) {
54 disable_irq_nosync(irq);
55 sdiodev->irq_en = false;
56 }
49 57
50 brcmf_sdbrcm_isr(sdiodev->bus); 58 brcmf_sdbrcm_isr(sdiodev->bus);
51 59
52 sdio_claim_host(func); 60 return IRQ_HANDLED;
61}
62
63int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
64{
65 int ret = 0;
66 u8 data;
67 unsigned long flags;
68
69 brcmf_dbg(TRACE, "Entering\n");
70
71 brcmf_dbg(ERROR, "requesting irq %d\n", sdiodev->irq);
72 ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
73 sdiodev->irq_flags, "brcmf_oob_intr",
74 &sdiodev->func[1]->card->dev);
75 if (ret != 0)
76 return ret;
77 spin_lock_init(&sdiodev->irq_en_lock);
78 spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
79 sdiodev->irq_en = true;
80 spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
81
82 ret = enable_irq_wake(sdiodev->irq);
83 if (ret != 0)
84 return ret;
85 sdiodev->irq_wake = true;
86
87 /* must configure SDIO_CCCR_IENx to enable irq */
88 data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0,
89 SDIO_CCCR_IENx, &ret);
90 data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
91 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx,
92 data, &ret);
93
94 /* redirect, configure ane enable io for interrupt signal */
95 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
96 if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH)
97 data |= SDIO_SEPINT_ACT_HI;
98 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
99 data, &ret);
100
101 return 0;
102}
103
104int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
105{
106 brcmf_dbg(TRACE, "Entering\n");
107
108 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT,
109 0, NULL);
110 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL);
111
112 if (sdiodev->irq_wake) {
113 disable_irq_wake(sdiodev->irq);
114 sdiodev->irq_wake = false;
115 }
116 free_irq(sdiodev->irq, &sdiodev->func[1]->card->dev);
117 sdiodev->irq_en = false;
118
119 return 0;
120}
121#else /* CONFIG_BRCMFMAC_SDIO_OOB */
122static void brcmf_sdio_irqhandler(struct sdio_func *func)
123{
124 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
125
126 brcmf_dbg(INTR, "ib intr triggered\n");
127
128 brcmf_sdbrcm_isr(sdiodev->bus);
53} 129}
54 130
55/* dummy handler for SDIO function 2 interrupt */ 131/* dummy handler for SDIO function 2 interrupt */
56static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func) 132static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
57{ 133{
58} 134}
59 135
60int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) 136int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
61{ 137{
62 brcmf_dbg(TRACE, "Entering\n"); 138 brcmf_dbg(TRACE, "Entering\n");
63 139
64 sdio_claim_host(sdiodev->func[1]); 140 sdio_claim_host(sdiodev->func[1]);
65 sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler); 141 sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
66 sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler); 142 sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
67 sdio_release_host(sdiodev->func[1]); 143 sdio_release_host(sdiodev->func[1]);
68 144
69 return 0; 145 return 0;
70} 146}
71 147
72int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) 148int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
73{ 149{
74 brcmf_dbg(TRACE, "Entering\n"); 150 brcmf_dbg(TRACE, "Entering\n");
75 151
@@ -80,6 +156,7 @@ int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
80 156
81 return 0; 157 return 0;
82} 158}
159#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
83 160
84u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, 161u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
85 int *err) 162 int *err)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 758c115b556e..dd07d33a927c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -27,6 +27,7 @@
27#include <linux/errno.h> 27#include <linux/errno.h>
28#include <linux/sched.h> /* request_irq() */ 28#include <linux/sched.h> /* request_irq() */
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/platform_device.h>
30#include <net/cfg80211.h> 31#include <net/cfg80211.h>
31 32
32#include <defs.h> 33#include <defs.h>
@@ -55,6 +56,15 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
55}; 56};
56MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); 57MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
57 58
59#ifdef CONFIG_BRCMFMAC_SDIO_OOB
60static struct list_head oobirq_lh;
61struct brcmf_sdio_oobirq {
62 unsigned int irq;
63 unsigned long flags;
64 struct list_head list;
65};
66#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
67
58static bool 68static bool
59brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) 69brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
60{ 70{
@@ -107,7 +117,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
107 } 117 }
108 sdio_release_host(sdfunc); 118 sdio_release_host(sdfunc);
109 } 119 }
110 } else if (regaddr == SDIO_CCCR_ABORT) { 120 } else if ((regaddr == SDIO_CCCR_ABORT) ||
121 (regaddr == SDIO_CCCR_IENx)) {
111 sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func), 122 sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
112 GFP_KERNEL); 123 GFP_KERNEL);
113 if (!sdfunc) 124 if (!sdfunc)
@@ -467,12 +478,40 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
467 478
468} 479}
469 480
481#ifdef CONFIG_BRCMFMAC_SDIO_OOB
482static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
483{
484 struct brcmf_sdio_oobirq *oobirq_entry;
485
486 if (list_empty(&oobirq_lh)) {
487 brcmf_dbg(ERROR, "no valid oob irq resource\n");
488 return -ENXIO;
489 }
490
491 oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
492 list);
493
494 sdiodev->irq = oobirq_entry->irq;
495 sdiodev->irq_flags = oobirq_entry->flags;
496 list_del(&oobirq_entry->list);
497 kfree(oobirq_entry);
498
499 return 0;
500}
501#else
502static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
503{
504 return 0;
505}
506#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
507
470static int brcmf_ops_sdio_probe(struct sdio_func *func, 508static int brcmf_ops_sdio_probe(struct sdio_func *func,
471 const struct sdio_device_id *id) 509 const struct sdio_device_id *id)
472{ 510{
473 int ret = 0; 511 int ret = 0;
474 struct brcmf_sdio_dev *sdiodev; 512 struct brcmf_sdio_dev *sdiodev;
475 struct brcmf_bus *bus_if; 513 struct brcmf_bus *bus_if;
514
476 brcmf_dbg(TRACE, "Enter\n"); 515 brcmf_dbg(TRACE, "Enter\n");
477 brcmf_dbg(TRACE, "func->class=%x\n", func->class); 516 brcmf_dbg(TRACE, "func->class=%x\n", func->class);
478 brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor); 517 brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
@@ -511,6 +550,10 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
511 sdiodev = dev_get_drvdata(&func->card->dev); 550 sdiodev = dev_get_drvdata(&func->card->dev);
512 if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) 551 if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
513 return -ENODEV; 552 return -ENODEV;
553
554 ret = brcmf_sdio_getintrcfg(sdiodev);
555 if (ret)
556 return ret;
514 sdiodev->func[2] = func; 557 sdiodev->func[2] = func;
515 558
516 bus_if = sdiodev->bus_if; 559 bus_if = sdiodev->bus_if;
@@ -603,6 +646,65 @@ static struct sdio_driver brcmf_sdmmc_driver = {
603#endif /* CONFIG_PM_SLEEP */ 646#endif /* CONFIG_PM_SLEEP */
604}; 647};
605 648
649#ifdef CONFIG_BRCMFMAC_SDIO_OOB
650static int brcmf_sdio_pd_probe(struct platform_device *pdev)
651{
652 struct resource *res;
653 struct brcmf_sdio_oobirq *oobirq_entry;
654 int i, ret;
655
656 INIT_LIST_HEAD(&oobirq_lh);
657
658 for (i = 0; ; i++) {
659 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
660 if (!res)
661 break;
662
663 oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
664 GFP_KERNEL);
665 oobirq_entry->irq = res->start;
666 oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
667 list_add_tail(&oobirq_entry->list, &oobirq_lh);
668 }
669 if (i == 0)
670 return -ENXIO;
671
672 ret = sdio_register_driver(&brcmf_sdmmc_driver);
673
674 if (ret)
675 brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
676
677 return ret;
678}
679
680static struct platform_driver brcmf_sdio_pd = {
681 .probe = brcmf_sdio_pd_probe,
682 .driver = {
683 .name = "brcmf_sdio_pd"
684 }
685};
686
687void brcmf_sdio_exit(void)
688{
689 brcmf_dbg(TRACE, "Enter\n");
690
691 sdio_unregister_driver(&brcmf_sdmmc_driver);
692
693 platform_driver_unregister(&brcmf_sdio_pd);
694}
695
696void brcmf_sdio_init(void)
697{
698 int ret;
699
700 brcmf_dbg(TRACE, "Enter\n");
701
702 ret = platform_driver_register(&brcmf_sdio_pd);
703
704 if (ret)
705 brcmf_dbg(ERROR, "platform_driver_register failed: %d\n", ret);
706}
707#else
606void brcmf_sdio_exit(void) 708void brcmf_sdio_exit(void)
607{ 709{
608 brcmf_dbg(TRACE, "Enter\n"); 710 brcmf_dbg(TRACE, "Enter\n");
@@ -621,3 +723,4 @@ void brcmf_sdio_init(void)
621 if (ret) 723 if (ret)
622 brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); 724 brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
623} 725}
726#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index a80b840051a7..149ee67beb2e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2352,6 +2352,24 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
2352 up(&bus->sdsem); 2352 up(&bus->sdsem);
2353} 2353}
2354 2354
2355#ifdef CONFIG_BRCMFMAC_SDIO_OOB
2356static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
2357{
2358 unsigned long flags;
2359
2360 spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
2361 if (!bus->sdiodev->irq_en && !bus->ipend) {
2362 enable_irq(bus->sdiodev->irq);
2363 bus->sdiodev->irq_en = true;
2364 }
2365 spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
2366}
2367#else
2368static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
2369{
2370}
2371#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
2372
2355static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) 2373static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
2356{ 2374{
2357 u32 intstatus, newstatus = 0; 2375 u32 intstatus, newstatus = 0;
@@ -2509,6 +2527,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
2509 bus->intstatus = intstatus; 2527 bus->intstatus = intstatus;
2510 2528
2511clkwait: 2529clkwait:
2530 brcmf_sdbrcm_clrintr(bus);
2531
2512 if (data_ok(bus) && bus->ctrl_frame_stat && 2532 if (data_ok(bus) && bus->ctrl_frame_stat &&
2513 (bus->clkstate == CLK_AVAIL)) { 2533 (bus->clkstate == CLK_AVAIL)) {
2514 int ret, i; 2534 int ret, i;
@@ -3508,8 +3528,14 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
3508 brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, 3528 brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
3509 SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); 3529 SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
3510 3530
3531 if (ret == 0) {
3532 ret = brcmf_sdio_intr_register(bus->sdiodev);
3533 if (ret != 0)
3534 brcmf_dbg(ERROR, "intr register failed:%d\n", ret);
3535 }
3536
3511 /* If we didn't come up, turn off backplane clock */ 3537 /* If we didn't come up, turn off backplane clock */
3512 if (!ret) 3538 if (bus_if->state != BRCMF_BUS_DATA)
3513 brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); 3539 brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
3514 3540
3515exit: 3541exit:
@@ -3867,7 +3893,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
3867 3893
3868 if (bus) { 3894 if (bus) {
3869 /* De-register interrupt handler */ 3895 /* De-register interrupt handler */
3870 brcmf_sdcard_intr_dereg(bus->sdiodev); 3896 brcmf_sdio_intr_unregister(bus->sdiodev);
3871 3897
3872 if (bus->sdiodev->bus_if->drvr) { 3898 if (bus->sdiodev->bus_if->drvr) {
3873 brcmf_detach(bus->sdiodev->dev); 3899 brcmf_detach(bus->sdiodev->dev);
@@ -3968,15 +3994,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
3968 goto fail; 3994 goto fail;
3969 } 3995 }
3970 3996
3971 /* Register interrupt callback, but mask it (not operational yet). */
3972 brcmf_dbg(INTR, "disable SDIO interrupts (not interested yet)\n");
3973 ret = brcmf_sdcard_intr_reg(bus->sdiodev);
3974 if (ret != 0) {
3975 brcmf_dbg(ERROR, "FAILED: sdcard_intr_reg returned %d\n", ret);
3976 goto fail;
3977 }
3978 brcmf_dbg(INTR, "registered SDIO interrupt function ok\n");
3979
3980 brcmf_dbg(INFO, "completed!!\n"); 3997 brcmf_dbg(INFO, "completed!!\n");
3981 3998
3982 /* if firmware path present try to download and bring up bus */ 3999 /* if firmware path present try to download and bring up bus */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 0281d207d998..7010eaf71f99 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -43,6 +43,13 @@
43/* as of sdiod rev 0, supports 3 functions */ 43/* as of sdiod rev 0, supports 3 functions */
44#define SBSDIO_NUM_FUNCTION 3 44#define SBSDIO_NUM_FUNCTION 3
45 45
46/* function 0 vendor specific CCCR registers */
47#define SDIO_CCCR_BRCM_SEPINT 0xf2
48
49#define SDIO_SEPINT_MASK 0x01
50#define SDIO_SEPINT_OE 0x02
51#define SDIO_SEPINT_ACT_HI 0x04
52
46/* function 1 miscellaneous registers */ 53/* function 1 miscellaneous registers */
47 54
48/* sprom command and status */ 55/* sprom command and status */
@@ -144,13 +151,18 @@ struct brcmf_sdio_dev {
144 wait_queue_head_t request_buffer_wait; 151 wait_queue_head_t request_buffer_wait;
145 struct device *dev; 152 struct device *dev;
146 struct brcmf_bus *bus_if; 153 struct brcmf_bus *bus_if;
154#ifdef CONFIG_BRCMFMAC_SDIO_OOB
155 unsigned int irq; /* oob interrupt number */
156 unsigned long irq_flags; /* board specific oob flags */
157 bool irq_en; /* irq enable flags */
158 spinlock_t irq_en_lock;
159 bool irq_wake; /* irq wake enable flags */
160#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
147}; 161};
148 162
149/* Register/deregister device interrupt handler. */ 163/* Register/deregister interrupt handler. */
150extern int 164extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev);
151brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev); 165extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev);
152
153extern int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev);
154 166
155/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). 167/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface).
156 * fn: function number 168 * fn: function number
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index c72136c07774..9cfae0c08707 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -1963,10 +1963,8 @@ static int ipw2100_wdev_init(struct net_device *dev)
1963 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); 1963 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites);
1964 1964
1965 set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); 1965 set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
1966 if (wiphy_register(wdev->wiphy)) { 1966 if (wiphy_register(wdev->wiphy))
1967 ipw2100_down(priv);
1968 return -EIO; 1967 return -EIO;
1969 }
1970 return 0; 1968 return 0;
1971} 1969}
1972 1970
@@ -6331,6 +6329,11 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
6331 printk(KERN_INFO DRV_NAME 6329 printk(KERN_INFO DRV_NAME
6332 ": Detected Intel PRO/Wireless 2100 Network Connection\n"); 6330 ": Detected Intel PRO/Wireless 2100 Network Connection\n");
6333 6331
6332 err = ipw2100_wdev_init(dev);
6333 if (err)
6334 goto fail;
6335 registered = 1;
6336
6334 /* Bring up the interface. Pre 0.46, after we registered the 6337 /* Bring up the interface. Pre 0.46, after we registered the
6335 * network device we would call ipw2100_up. This introduced a race 6338 * network device we would call ipw2100_up. This introduced a race
6336 * condition with newer hotplug configurations (network was coming 6339 * condition with newer hotplug configurations (network was coming
@@ -6347,11 +6350,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
6347 "Error calling register_netdev.\n"); 6350 "Error calling register_netdev.\n");
6348 goto fail; 6351 goto fail;
6349 } 6352 }
6350 registered = 1; 6353 registered = 2;
6351
6352 err = ipw2100_wdev_init(dev);
6353 if (err)
6354 goto fail;
6355 6354
6356 mutex_lock(&priv->action_mutex); 6355 mutex_lock(&priv->action_mutex);
6357 6356
@@ -6390,13 +6389,16 @@ out:
6390 6389
6391 fail_unlock: 6390 fail_unlock:
6392 mutex_unlock(&priv->action_mutex); 6391 mutex_unlock(&priv->action_mutex);
6393 wiphy_unregister(priv->ieee->wdev.wiphy);
6394 kfree(priv->ieee->bg_band.channels);
6395 fail: 6392 fail:
6396 if (dev) { 6393 if (dev) {
6397 if (registered) 6394 if (registered >= 2)
6398 unregister_netdev(dev); 6395 unregister_netdev(dev);
6399 6396
6397 if (registered) {
6398 wiphy_unregister(priv->ieee->wdev.wiphy);
6399 kfree(priv->ieee->bg_band.channels);
6400 }
6401
6400 ipw2100_hw_stop_adapter(priv); 6402 ipw2100_hw_stop_adapter(priv);
6401 6403
6402 ipw2100_disable_interrupts(priv); 6404 ipw2100_disable_interrupts(priv);
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index b3707dadad15..0036737fe8e3 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11443,20 +11443,6 @@ static void ipw_bg_down(struct work_struct *work)
11443 mutex_unlock(&priv->mutex); 11443 mutex_unlock(&priv->mutex);
11444} 11444}
11445 11445
11446/* Called by register_netdev() */
11447static int ipw_net_init(struct net_device *dev)
11448{
11449 int rc = 0;
11450 struct ipw_priv *priv = libipw_priv(dev);
11451
11452 mutex_lock(&priv->mutex);
11453 if (ipw_up(priv))
11454 rc = -EIO;
11455 mutex_unlock(&priv->mutex);
11456
11457 return rc;
11458}
11459
11460static int ipw_wdev_init(struct net_device *dev) 11446static int ipw_wdev_init(struct net_device *dev)
11461{ 11447{
11462 int i, rc = 0; 11448 int i, rc = 0;
@@ -11725,7 +11711,6 @@ static void ipw_prom_free(struct ipw_priv *priv)
11725#endif 11711#endif
11726 11712
11727static const struct net_device_ops ipw_netdev_ops = { 11713static const struct net_device_ops ipw_netdev_ops = {
11728 .ndo_init = ipw_net_init,
11729 .ndo_open = ipw_net_open, 11714 .ndo_open = ipw_net_open,
11730 .ndo_stop = ipw_net_stop, 11715 .ndo_stop = ipw_net_stop,
11731 .ndo_set_rx_mode = ipw_net_set_multicast_list, 11716 .ndo_set_rx_mode = ipw_net_set_multicast_list,
@@ -11848,17 +11833,24 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
11848 goto out_release_irq; 11833 goto out_release_irq;
11849 } 11834 }
11850 11835
11851 mutex_unlock(&priv->mutex); 11836 if (ipw_up(priv)) {
11852 err = register_netdev(net_dev); 11837 mutex_unlock(&priv->mutex);
11853 if (err) { 11838 err = -EIO;
11854 IPW_ERROR("failed to register network device\n");
11855 goto out_remove_sysfs; 11839 goto out_remove_sysfs;
11856 } 11840 }
11857 11841
11842 mutex_unlock(&priv->mutex);
11843
11858 err = ipw_wdev_init(net_dev); 11844 err = ipw_wdev_init(net_dev);
11859 if (err) { 11845 if (err) {
11860 IPW_ERROR("failed to register wireless device\n"); 11846 IPW_ERROR("failed to register wireless device\n");
11861 goto out_unregister_netdev; 11847 goto out_remove_sysfs;
11848 }
11849
11850 err = register_netdev(net_dev);
11851 if (err) {
11852 IPW_ERROR("failed to register network device\n");
11853 goto out_unregister_wiphy;
11862 } 11854 }
11863 11855
11864#ifdef CONFIG_IPW2200_PROMISCUOUS 11856#ifdef CONFIG_IPW2200_PROMISCUOUS
@@ -11867,10 +11859,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
11867 if (err) { 11859 if (err) {
11868 IPW_ERROR("Failed to register promiscuous network " 11860 IPW_ERROR("Failed to register promiscuous network "
11869 "device (error %d).\n", err); 11861 "device (error %d).\n", err);
11870 wiphy_unregister(priv->ieee->wdev.wiphy); 11862 unregister_netdev(priv->net_dev);
11871 kfree(priv->ieee->a_band.channels); 11863 goto out_unregister_wiphy;
11872 kfree(priv->ieee->bg_band.channels);
11873 goto out_unregister_netdev;
11874 } 11864 }
11875 } 11865 }
11876#endif 11866#endif
@@ -11882,8 +11872,10 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
11882 11872
11883 return 0; 11873 return 0;
11884 11874
11885 out_unregister_netdev: 11875 out_unregister_wiphy:
11886 unregister_netdev(priv->net_dev); 11876 wiphy_unregister(priv->ieee->wdev.wiphy);
11877 kfree(priv->ieee->a_band.channels);
11878 kfree(priv->ieee->bg_band.channels);
11887 out_remove_sysfs: 11879 out_remove_sysfs:
11888 sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); 11880 sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
11889 out_release_irq: 11881 out_release_irq:
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index e1c2bb802050..01dc44267317 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -186,76 +186,8 @@ done:
186/* 186/*
187 * BT coex 187 * BT coex
188 */ 188 */
189/* 189/* Notmal TDM */
190 * Macros to access the lookup table. 190static const __le32 iwlagn_def_3w_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
191 *
192 * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req,
193* wifi_prio, wifi_txrx and wifi_sh_ant_req.
194 *
195 * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH
196 *
197 * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits
198 * one after another in 32-bit registers, and "registers" 0 through 7 contain
199 * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order).
200 *
201 * These macros encode that format.
202 */
203#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \
204 wifi_txrx, wifi_sh_ant_req) \
205 (bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \
206 (wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6))
207
208#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \
209 lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f)))
210#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
211 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
212 (!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, \
213 bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
214 wifi_sh_ant_req))))
215#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
216 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
217 LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \
218 bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
219 wifi_sh_ant_req))
220#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
221 wifi_req, wifi_prio, wifi_txrx, \
222 wifi_sh_ant_req) \
223 LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \
224 bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
225 wifi_sh_ant_req))
226
227#define LUT_WLAN_KILL_OP(lut, op, val) \
228 lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e)))
229#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
230 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
231 (!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
232 wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
233#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
234 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
235 LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
236 wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
237#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
238 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
239 LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
240 wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
241
242#define LUT_ANT_SWITCH_OP(lut, op, val) \
243 lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1)))
244#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
245 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
246 (!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
247 wifi_req, wifi_prio, wifi_txrx, \
248 wifi_sh_ant_req))))
249#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
250 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
251 LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
252 wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
253#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
254 wifi_prio, wifi_txrx, wifi_sh_ant_req) \
255 LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
256 wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
257
258static const __le32 iwlagn_def_3w_lookup[12] = {
259 cpu_to_le32(0xaaaaaaaa), 191 cpu_to_le32(0xaaaaaaaa),
260 cpu_to_le32(0xaaaaaaaa), 192 cpu_to_le32(0xaaaaaaaa),
261 cpu_to_le32(0xaeaaaaaa), 193 cpu_to_le32(0xaeaaaaaa),
@@ -270,7 +202,25 @@ static const __le32 iwlagn_def_3w_lookup[12] = {
270 cpu_to_le32(0xf0005000), 202 cpu_to_le32(0xf0005000),
271}; 203};
272 204
273static const __le32 iwlagn_concurrent_lookup[12] = { 205
206/* Loose Coex */
207static const __le32 iwlagn_loose_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
208 cpu_to_le32(0xaaaaaaaa),
209 cpu_to_le32(0xaaaaaaaa),
210 cpu_to_le32(0xaeaaaaaa),
211 cpu_to_le32(0xaaaaaaaa),
212 cpu_to_le32(0xcc00ff28),
213 cpu_to_le32(0x0000aaaa),
214 cpu_to_le32(0xcc00aaaa),
215 cpu_to_le32(0x0000aaaa),
216 cpu_to_le32(0x00000000),
217 cpu_to_le32(0x00000000),
218 cpu_to_le32(0xf0005000),
219 cpu_to_le32(0xf0005000),
220};
221
222/* Full concurrency */
223static const __le32 iwlagn_concurrent_lookup[IWLAGN_BT_DECISION_LUT_SIZE] = {
274 cpu_to_le32(0xaaaaaaaa), 224 cpu_to_le32(0xaaaaaaaa),
275 cpu_to_le32(0xaaaaaaaa), 225 cpu_to_le32(0xaaaaaaaa),
276 cpu_to_le32(0xaaaaaaaa), 226 cpu_to_le32(0xaaaaaaaa),
@@ -325,6 +275,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
325 275
326 basic.kill_ack_mask = priv->kill_ack_mask; 276 basic.kill_ack_mask = priv->kill_ack_mask;
327 basic.kill_cts_mask = priv->kill_cts_mask; 277 basic.kill_cts_mask = priv->kill_cts_mask;
278 basic.reduce_txpower = priv->reduced_txpower;
328 basic.valid = priv->bt_valid; 279 basic.valid = priv->bt_valid;
329 280
330 /* 281 /*
@@ -610,29 +561,62 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
610 BT_UART_MSG_FRAME7CONNECTABLE_POS); 561 BT_UART_MSG_FRAME7CONNECTABLE_POS);
611} 562}
612 563
613static void iwlagn_set_kill_msk(struct iwl_priv *priv, 564static bool iwlagn_set_kill_msk(struct iwl_priv *priv,
614 struct iwl_bt_uart_msg *uart_msg) 565 struct iwl_bt_uart_msg *uart_msg)
615{ 566{
616 u8 kill_msk; 567 bool need_update = false;
617 static const __le32 bt_kill_ack_msg[2] = { 568 u8 kill_msk = IWL_BT_KILL_REDUCE;
569 static const __le32 bt_kill_ack_msg[3] = {
618 IWLAGN_BT_KILL_ACK_MASK_DEFAULT, 570 IWLAGN_BT_KILL_ACK_MASK_DEFAULT,
619 IWLAGN_BT_KILL_ACK_CTS_MASK_SCO }; 571 IWLAGN_BT_KILL_ACK_CTS_MASK_SCO,
620 static const __le32 bt_kill_cts_msg[2] = { 572 IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE};
573 static const __le32 bt_kill_cts_msg[3] = {
621 IWLAGN_BT_KILL_CTS_MASK_DEFAULT, 574 IWLAGN_BT_KILL_CTS_MASK_DEFAULT,
622 IWLAGN_BT_KILL_ACK_CTS_MASK_SCO }; 575 IWLAGN_BT_KILL_ACK_CTS_MASK_SCO,
576 IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE};
623 577
624 kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) 578 if (!priv->reduced_txpower)
625 ? 1 : 0; 579 kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3)
580 ? IWL_BT_KILL_OVERRIDE : IWL_BT_KILL_DEFAULT;
626 if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] || 581 if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] ||
627 priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) { 582 priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) {
628 priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK; 583 priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
629 priv->kill_ack_mask = bt_kill_ack_msg[kill_msk]; 584 priv->kill_ack_mask = bt_kill_ack_msg[kill_msk];
630 priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK; 585 priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK;
631 priv->kill_cts_mask = bt_kill_cts_msg[kill_msk]; 586 priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
587 need_update = true;
588 }
589 return need_update;
590}
632 591
633 /* schedule to send runtime bt_config */ 592static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
634 queue_work(priv->workqueue, &priv->bt_runtime_config); 593 struct iwl_bt_uart_msg *uart_msg)
594{
595 bool need_update = false;
596
597 if (!priv->reduced_txpower &&
598 !iwl_is_associated(priv, IWL_RXON_CTX_PAN) &&
599 (uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
600 BT_UART_MSG_FRAME3OBEX_MSK)) &&
601 !(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
602 BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK))) {
603 /* enabling reduced tx power */
604 priv->reduced_txpower = true;
605 priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR;
606 need_update = true;
607 } else if (priv->reduced_txpower &&
608 (iwl_is_associated(priv, IWL_RXON_CTX_PAN) ||
609 (uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK |
610 BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) ||
611 !(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK |
612 BT_UART_MSG_FRAME3OBEX_MSK)))) {
613 /* disable reduced tx power */
614 priv->reduced_txpower = false;
615 priv->bt_valid &= ~IWLAGN_BT_VALID_REDUCED_TX_PWR;
616 need_update = true;
635 } 617 }
618
619 return need_update;
636} 620}
637 621
638int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, 622int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
@@ -680,7 +664,12 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
680 } 664 }
681 } 665 }
682 666
683 iwlagn_set_kill_msk(priv, uart_msg); 667 /* schedule to send runtime bt_config */
668 /* check reduce power before change ack/cts kill mask */
669 if (iwlagn_fill_txpower_mode(priv, uart_msg) ||
670 iwlagn_set_kill_msk(priv, uart_msg))
671 queue_work(priv->workqueue, &priv->bt_runtime_config);
672
684 673
685 /* FIXME: based on notification, adjust the prio_boost */ 674 /* FIXME: based on notification, adjust the prio_boost */
686 675
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 779f819cc8cb..18a383798e5d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -764,7 +764,8 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
764 fraglen = len - hdrlen; 764 fraglen = len - hdrlen;
765 765
766 if (fraglen) { 766 if (fraglen) {
767 int offset = (void *)hdr - rxb_addr(rxb) + rxb_offset(rxb); 767 int offset = (void *)hdr + hdrlen -
768 rxb_addr(rxb) + rxb_offset(rxb);
768 769
769 skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset, 770 skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
770 fraglen, rxb->truesize); 771 fraglen, rxb->truesize);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8bd9610a5d68..8d7637083fcf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1307,6 +1307,9 @@ static int iwl_init_geos(struct iwl_priv *priv)
1307 priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; 1307 priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
1308 } 1308 }
1309 1309
1310 if (iwlwifi_mod_params.disable_5ghz)
1311 priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0;
1312
1310 IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", 1313 IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
1311 priv->bands[IEEE80211_BAND_2GHZ].n_channels, 1314 priv->bands[IEEE80211_BAND_2GHZ].n_channels,
1312 priv->bands[IEEE80211_BAND_5GHZ].n_channels); 1315 priv->bands[IEEE80211_BAND_5GHZ].n_channels);
@@ -1417,38 +1420,37 @@ void iwl_set_hw_params(struct iwl_priv *priv)
1417 1420
1418 1421
1419 1422
1420void iwl_debug_config(struct iwl_priv *priv) 1423/* show what optional capabilities we have */
1424void iwl_option_config(struct iwl_priv *priv)
1421{ 1425{
1422 dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEBUG "
1423#ifdef CONFIG_IWLWIFI_DEBUG 1426#ifdef CONFIG_IWLWIFI_DEBUG
1424 "enabled\n"); 1427 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n");
1425#else 1428#else
1426 "disabled\n"); 1429 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG disabled\n");
1427#endif 1430#endif
1428 dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEBUGFS " 1431
1429#ifdef CONFIG_IWLWIFI_DEBUGFS 1432#ifdef CONFIG_IWLWIFI_DEBUGFS
1430 "enabled\n"); 1433 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS enabled\n");
1431#else 1434#else
1432 "disabled\n"); 1435 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS disabled\n");
1433#endif 1436#endif
1434 dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEVICE_TRACING " 1437
1435#ifdef CONFIG_IWLWIFI_DEVICE_TRACING 1438#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
1436 "enabled\n"); 1439 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING enabled\n");
1437#else 1440#else
1438 "disabled\n"); 1441 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
1439#endif 1442#endif
1440 1443
1441 dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE "
1442#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE 1444#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
1443 "enabled\n"); 1445 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE enabled\n");
1444#else 1446#else
1445 "disabled\n"); 1447 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE disabled\n");
1446#endif 1448#endif
1447 dev_printk(KERN_INFO, priv->trans->dev, "CONFIG_IWLWIFI_P2P " 1449
1448#ifdef CONFIG_IWLWIFI_P2P 1450#ifdef CONFIG_IWLWIFI_P2P
1449 "enabled\n"); 1451 IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n");
1450#else 1452#else
1451 "disabled\n"); 1453 IWL_INFO(priv, "CONFIG_IWLWIFI_P2P disabled\n");
1452#endif 1454#endif
1453} 1455}
1454 1456
@@ -1567,8 +1569,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1567 1569
1568 SET_IEEE80211_DEV(priv->hw, priv->trans->dev); 1570 SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
1569 1571
1570 /* show what debugging capabilities we have */ 1572 iwl_option_config(priv);
1571 iwl_debug_config(priv);
1572 1573
1573 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); 1574 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
1574 1575
@@ -1586,7 +1587,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1586 /* these spin locks will be used in apm_ops.init and EEPROM access 1587 /* these spin locks will be used in apm_ops.init and EEPROM access
1587 * we should init now 1588 * we should init now
1588 */ 1589 */
1589 spin_lock_init(&priv->trans->reg_lock);
1590 spin_lock_init(&priv->statistics.lock); 1590 spin_lock_init(&priv->statistics.lock);
1591 1591
1592 /*********************** 1592 /***********************
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 34900e6523dd..79c0fe06f4db 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -523,7 +523,7 @@ static inline const char *iwl_dvm_get_cmd_string(u8 cmd)
523void iwl_setup_deferred_work(struct iwl_priv *priv); 523void iwl_setup_deferred_work(struct iwl_priv *priv);
524int iwl_send_wimax_coex(struct iwl_priv *priv); 524int iwl_send_wimax_coex(struct iwl_priv *priv);
525int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); 525int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
526void iwl_debug_config(struct iwl_priv *priv); 526void iwl_option_config(struct iwl_priv *priv);
527void iwl_set_hw_params(struct iwl_priv *priv); 527void iwl_set_hw_params(struct iwl_priv *priv);
528void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); 528void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags);
529int iwl_init_drv(struct iwl_priv *priv); 529int iwl_init_drv(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 296347a8290f..83a6930f3658 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1877,9 +1877,16 @@ struct iwl_bt_cmd {
1877 1877
1878#define IWLAGN_BT3_T7_DEFAULT 1 1878#define IWLAGN_BT3_T7_DEFAULT 1
1879 1879
1880enum iwl_bt_kill_idx {
1881 IWL_BT_KILL_DEFAULT = 0,
1882 IWL_BT_KILL_OVERRIDE = 1,
1883 IWL_BT_KILL_REDUCE = 2,
1884};
1885
1880#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffff0000) 1886#define IWLAGN_BT_KILL_ACK_MASK_DEFAULT cpu_to_le32(0xffff0000)
1881#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffff0000) 1887#define IWLAGN_BT_KILL_CTS_MASK_DEFAULT cpu_to_le32(0xffff0000)
1882#define IWLAGN_BT_KILL_ACK_CTS_MASK_SCO cpu_to_le32(0xffffffff) 1888#define IWLAGN_BT_KILL_ACK_CTS_MASK_SCO cpu_to_le32(0xffffffff)
1889#define IWLAGN_BT_KILL_ACK_CTS_MASK_REDUCE cpu_to_le32(0)
1883 1890
1884#define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT 2 1891#define IWLAGN_BT3_PRIO_SAMPLE_DEFAULT 2
1885 1892
@@ -1891,7 +1898,7 @@ struct iwl_bt_cmd {
1891#define IWLAGN_BT_VALID_3W_TIMERS cpu_to_le16(BIT(3)) 1898#define IWLAGN_BT_VALID_3W_TIMERS cpu_to_le16(BIT(3))
1892#define IWLAGN_BT_VALID_KILL_ACK_MASK cpu_to_le16(BIT(4)) 1899#define IWLAGN_BT_VALID_KILL_ACK_MASK cpu_to_le16(BIT(4))
1893#define IWLAGN_BT_VALID_KILL_CTS_MASK cpu_to_le16(BIT(5)) 1900#define IWLAGN_BT_VALID_KILL_CTS_MASK cpu_to_le16(BIT(5))
1894#define IWLAGN_BT_VALID_BT4_TIMES cpu_to_le16(BIT(6)) 1901#define IWLAGN_BT_VALID_REDUCED_TX_PWR cpu_to_le16(BIT(6))
1895#define IWLAGN_BT_VALID_3W_LUT cpu_to_le16(BIT(7)) 1902#define IWLAGN_BT_VALID_3W_LUT cpu_to_le16(BIT(7))
1896 1903
1897#define IWLAGN_BT_ALL_VALID_MSK (IWLAGN_BT_VALID_ENABLE_FLAGS | \ 1904#define IWLAGN_BT_ALL_VALID_MSK (IWLAGN_BT_VALID_ENABLE_FLAGS | \
@@ -1900,9 +1907,11 @@ struct iwl_bt_cmd {
1900 IWLAGN_BT_VALID_3W_TIMERS | \ 1907 IWLAGN_BT_VALID_3W_TIMERS | \
1901 IWLAGN_BT_VALID_KILL_ACK_MASK | \ 1908 IWLAGN_BT_VALID_KILL_ACK_MASK | \
1902 IWLAGN_BT_VALID_KILL_CTS_MASK | \ 1909 IWLAGN_BT_VALID_KILL_CTS_MASK | \
1903 IWLAGN_BT_VALID_BT4_TIMES | \ 1910 IWLAGN_BT_VALID_REDUCED_TX_PWR | \
1904 IWLAGN_BT_VALID_3W_LUT) 1911 IWLAGN_BT_VALID_3W_LUT)
1905 1912
1913#define IWLAGN_BT_DECISION_LUT_SIZE 12
1914
1906struct iwl_basic_bt_cmd { 1915struct iwl_basic_bt_cmd {
1907 u8 flags; 1916 u8 flags;
1908 u8 ledtime; /* unused */ 1917 u8 ledtime; /* unused */
@@ -1913,8 +1922,9 @@ struct iwl_basic_bt_cmd {
1913 u8 bt3_prio_sample_time; 1922 u8 bt3_prio_sample_time;
1914 u8 bt3_timer_t2_value; 1923 u8 bt3_timer_t2_value;
1915 __le16 bt4_reaction_time; /* unused */ 1924 __le16 bt4_reaction_time; /* unused */
1916 __le32 bt3_lookup_table[12]; 1925 __le32 bt3_lookup_table[IWLAGN_BT_DECISION_LUT_SIZE];
1917 __le16 bt4_decision_time; /* unused */ 1926 u8 reduce_txpower;
1927 u8 reserved;
1918 __le16 valid; 1928 __le16 valid;
1919}; 1929};
1920 1930
@@ -3634,6 +3644,9 @@ enum iwl_bt_coex_profile_traffic_load {
3634 (0x3<<BT_UART_MSG_2_FRAME7RESERVED_POS) 3644 (0x3<<BT_UART_MSG_2_FRAME7RESERVED_POS)
3635 3645
3636 3646
3647#define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62)
3648#define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65)
3649
3637struct iwl_bt_uart_msg { 3650struct iwl_bt_uart_msg {
3638 u8 header; 3651 u8 header;
3639 u8 frame1; 3652 u8 frame1;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index f70219c3b122..70062379d0ec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -921,6 +921,7 @@ struct iwl_priv {
921 __le32 kill_ack_mask; 921 __le32 kill_ack_mask;
922 __le32 kill_cts_mask; 922 __le32 kill_cts_mask;
923 __le16 bt_valid; 923 __le16 bt_valid;
924 bool reduced_txpower;
924 u16 bt_on_thresh; 925 u16 bt_on_thresh;
925 u16 bt_duration; 926 u16 bt_duration;
926 u16 dynamic_frag_thresh; 927 u16 dynamic_frag_thresh;
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 05302d6f989f..3c72bad0ae56 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -66,6 +66,7 @@
66#include <linux/module.h> 66#include <linux/module.h>
67 67
68#include "iwl-drv.h" 68#include "iwl-drv.h"
69#include "iwl-debug.h"
69#include "iwl-trans.h" 70#include "iwl-trans.h"
70#include "iwl-op-mode.h" 71#include "iwl-op-mode.h"
71#include "iwl-agn-hw.h" 72#include "iwl-agn-hw.h"
@@ -892,10 +893,9 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
892 int ret; 893 int ret;
893 894
894 drv = kzalloc(sizeof(*drv), GFP_KERNEL); 895 drv = kzalloc(sizeof(*drv), GFP_KERNEL);
895 if (!drv) { 896 if (!drv)
896 dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_drv");
897 return NULL; 897 return NULL;
898 } 898
899 drv->trans = trans; 899 drv->trans = trans;
900 drv->dev = trans->dev; 900 drv->dev = trans->dev;
901 drv->cfg = cfg; 901 drv->cfg = cfg;
@@ -905,7 +905,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
905 ret = iwl_request_firmware(drv, true); 905 ret = iwl_request_firmware(drv, true);
906 906
907 if (ret) { 907 if (ret) {
908 dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw"); 908 IWL_ERR(trans, "Couldn't request the fw\n");
909 kfree(drv); 909 kfree(drv);
910 drv = NULL; 910 drv = NULL;
911 } 911 }
@@ -1012,3 +1012,7 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg,
1012 bool, S_IRUGO); 1012 bool, S_IRUGO);
1013MODULE_PARM_DESC(auto_agg, 1013MODULE_PARM_DESC(auto_agg,
1014 "enable agg w/o check traffic load (default: enable)"); 1014 "enable agg w/o check traffic load (default: enable)");
1015
1016module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz,
1017 bool, S_IRUGO);
1018MODULE_PARM_DESC(5ghz_disable, "disable 5GHz band (default: 0 [enabled])");
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index 558b2e63c5cf..d9a86d6b2bd7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -60,8 +60,8 @@
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 * 61 *
62 *****************************************************************************/ 62 *****************************************************************************/
63#ifndef __iwl_shared_h__ 63#ifndef __iwl_modparams_h__
64#define __iwl_shared_h__ 64#define __iwl_modparams_h__
65 65
66#include <linux/types.h> 66#include <linux/types.h>
67#include <linux/spinlock.h> 67#include <linux/spinlock.h>
@@ -103,6 +103,7 @@ enum iwl_power_level {
103 * @ant_coupling: antenna coupling in dB, default = 0 103 * @ant_coupling: antenna coupling in dB, default = 0
104 * @bt_ch_announce: BT channel inhibition, default = enable 104 * @bt_ch_announce: BT channel inhibition, default = enable
105 * @auto_agg: enable agg. without check, default = true 105 * @auto_agg: enable agg. without check, default = true
106 * @disable_5ghz: disable 5GHz capability, default = false
106 */ 107 */
107struct iwl_mod_params { 108struct iwl_mod_params {
108 int sw_crypto; 109 int sw_crypto;
@@ -119,6 +120,7 @@ struct iwl_mod_params {
119 int ant_coupling; 120 int ant_coupling;
120 bool bt_ch_announce; 121 bool bt_ch_announce;
121 bool auto_agg; 122 bool auto_agg;
123 bool disable_5ghz;
122}; 124};
123 125
124#endif /* #__iwl_shared_h__ */ 126#endif /* #__iwl_modparams_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index 63557bb85cda..2e57161854b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -2175,6 +2175,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
2175 2175
2176 /* Initialize the wait queue for commands */ 2176 /* Initialize the wait queue for commands */
2177 init_waitqueue_head(&trans->wait_command_queue); 2177 init_waitqueue_head(&trans->wait_command_queue);
2178 spin_lock_init(&trans->reg_lock);
2178 2179
2179 return trans; 2180 return trans;
2180 2181
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c
index 77f6504fd55d..601f2075355e 100644
--- a/drivers/net/wireless/libertas/firmware.c
+++ b/drivers/net/wireless/libertas/firmware.c
@@ -2,6 +2,7 @@
2 * Firmware loading and handling functions. 2 * Firmware loading and handling functions.
3 */ 3 */
4 4
5#include <linux/sched.h>
5#include <linux/firmware.h> 6#include <linux/firmware.h>
6#include <linux/firmware.h> 7#include <linux/firmware.h>
7#include <linux/module.h> 8#include <linux/module.h>
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 7f91cc694787..8e384fae3e68 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -10,12 +10,12 @@ config MWIFIEX
10 mwifiex. 10 mwifiex.
11 11
12config MWIFIEX_SDIO 12config MWIFIEX_SDIO
13 tristate "Marvell WiFi-Ex Driver for SD8787/SD8797" 13 tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797"
14 depends on MWIFIEX && MMC 14 depends on MWIFIEX && MMC
15 select FW_LOADER 15 select FW_LOADER
16 ---help--- 16 ---help---
17 This adds support for wireless adapters based on Marvell 17 This adds support for wireless adapters based on Marvell
18 8787/8797 chipsets with SDIO interface. 18 8786/8787/8797 chipsets with SDIO interface.
19 19
20 If you choose to build it as a module, it will be called 20 If you choose to build it as a module, it will be called
21 mwifiex_sdio. 21 mwifiex_sdio.
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 2a2cabadb9b5..5f6adeb9b950 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -993,8 +993,7 @@ struct mwifiex_ie_types_wmm_queue_status {
993struct ieee_types_vendor_header { 993struct ieee_types_vendor_header {
994 u8 element_id; 994 u8 element_id;
995 u8 len; 995 u8 len;
996 u8 oui[3]; 996 u8 oui[4]; /* 0~2: oui, 3: oui_type */
997 u8 oui_type;
998 u8 oui_subtype; 997 u8 oui_subtype;
999 u8 version; 998 u8 version;
1000} __packed; 999} __packed;
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 1aa45c4295bb..e0377473282f 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -253,6 +253,8 @@ static int mwifiex_sdio_resume(struct device *dev)
253 return 0; 253 return 0;
254} 254}
255 255
256/* Device ID for SD8786 */
257#define SDIO_DEVICE_ID_MARVELL_8786 (0x9116)
256/* Device ID for SD8787 */ 258/* Device ID for SD8787 */
257#define SDIO_DEVICE_ID_MARVELL_8787 (0x9119) 259#define SDIO_DEVICE_ID_MARVELL_8787 (0x9119)
258/* Device ID for SD8797 */ 260/* Device ID for SD8797 */
@@ -260,6 +262,7 @@ static int mwifiex_sdio_resume(struct device *dev)
260 262
261/* WLAN IDs */ 263/* WLAN IDs */
262static const struct sdio_device_id mwifiex_ids[] = { 264static const struct sdio_device_id mwifiex_ids[] = {
265 {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786)},
263 {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)}, 266 {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)},
264 {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797)}, 267 {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797)},
265 {}, 268 {},
@@ -1599,6 +1602,9 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
1599 adapter->dev = &func->dev; 1602 adapter->dev = &func->dev;
1600 1603
1601 switch (func->device) { 1604 switch (func->device) {
1605 case SDIO_DEVICE_ID_MARVELL_8786:
1606 strcpy(adapter->fw_name, SD8786_DEFAULT_FW_NAME);
1607 break;
1602 case SDIO_DEVICE_ID_MARVELL_8797: 1608 case SDIO_DEVICE_ID_MARVELL_8797:
1603 strcpy(adapter->fw_name, SD8797_DEFAULT_FW_NAME); 1609 strcpy(adapter->fw_name, SD8797_DEFAULT_FW_NAME);
1604 break; 1610 break;
@@ -1807,5 +1813,6 @@ MODULE_AUTHOR("Marvell International Ltd.");
1807MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); 1813MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);
1808MODULE_VERSION(SDIO_VERSION); 1814MODULE_VERSION(SDIO_VERSION);
1809MODULE_LICENSE("GPL v2"); 1815MODULE_LICENSE("GPL v2");
1816MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME);
1810MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME); 1817MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
1811MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME); 1818MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 0ead152e3d1e..21033738ef0c 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -28,6 +28,7 @@
28 28
29#include "main.h" 29#include "main.h"
30 30
31#define SD8786_DEFAULT_FW_NAME "mrvl/sd8786_uapsta.bin"
31#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" 32#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
32#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" 33#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin"
33 34
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index d91f4f628f65..9348521e0832 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -102,6 +102,8 @@
102#define BBP_SIZE 0x00ff 102#define BBP_SIZE 0x00ff
103#define RF_BASE 0x0004 103#define RF_BASE 0x0004
104#define RF_SIZE 0x0010 104#define RF_SIZE 0x0010
105#define RFCSR_BASE 0x0000
106#define RFCSR_SIZE 0x0040
105 107
106/* 108/*
107 * Number of TX queues. 109 * Number of TX queues.
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 1cd16b416024..dfc90d34be6d 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -836,6 +836,13 @@ const struct rt2x00debug rt2800_rt2x00debug = {
836 .word_size = sizeof(u32), 836 .word_size = sizeof(u32),
837 .word_count = RF_SIZE / sizeof(u32), 837 .word_count = RF_SIZE / sizeof(u32),
838 }, 838 },
839 .rfcsr = {
840 .read = rt2800_rfcsr_read,
841 .write = rt2800_rfcsr_write,
842 .word_base = RFCSR_BASE,
843 .word_size = sizeof(u8),
844 .word_count = RFCSR_SIZE / sizeof(u8),
845 },
839}; 846};
840EXPORT_SYMBOL_GPL(rt2800_rt2x00debug); 847EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);
841#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 848#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 78787fcc919e..3bb8cafbac59 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -70,6 +70,7 @@ struct rt2x00debug_intf {
70 * - eeprom offset/value files 70 * - eeprom offset/value files
71 * - bbp offset/value files 71 * - bbp offset/value files
72 * - rf offset/value files 72 * - rf offset/value files
73 * - rfcsr offset/value files
73 * - queue folder 74 * - queue folder
74 * - frame dump file 75 * - frame dump file
75 * - queue stats file 76 * - queue stats file
@@ -89,6 +90,8 @@ struct rt2x00debug_intf {
89 struct dentry *bbp_val_entry; 90 struct dentry *bbp_val_entry;
90 struct dentry *rf_off_entry; 91 struct dentry *rf_off_entry;
91 struct dentry *rf_val_entry; 92 struct dentry *rf_val_entry;
93 struct dentry *rfcsr_off_entry;
94 struct dentry *rfcsr_val_entry;
92 struct dentry *queue_folder; 95 struct dentry *queue_folder;
93 struct dentry *queue_frame_dump_entry; 96 struct dentry *queue_frame_dump_entry;
94 struct dentry *queue_stats_entry; 97 struct dentry *queue_stats_entry;
@@ -131,6 +134,7 @@ struct rt2x00debug_intf {
131 unsigned int offset_eeprom; 134 unsigned int offset_eeprom;
132 unsigned int offset_bbp; 135 unsigned int offset_bbp;
133 unsigned int offset_rf; 136 unsigned int offset_rf;
137 unsigned int offset_rfcsr;
134}; 138};
135 139
136void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, 140void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
@@ -525,6 +529,7 @@ RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
525RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16); 529RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
526RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8); 530RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
527RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32); 531RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
532RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8);
528 533
529static ssize_t rt2x00debug_read_dev_flags(struct file *file, 534static ssize_t rt2x00debug_read_dev_flags(struct file *file,
530 char __user *buf, 535 char __user *buf,
@@ -614,7 +619,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
614 const struct rt2x00debug *debug = intf->debug; 619 const struct rt2x00debug *debug = intf->debug;
615 char *data; 620 char *data;
616 621
617 data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL); 622 data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);
618 if (!data) 623 if (!data)
619 return NULL; 624 return NULL;
620 625
@@ -624,22 +629,22 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
624 data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev); 629 data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
625 data += sprintf(data, "\n"); 630 data += sprintf(data, "\n");
626 data += sprintf(data, "register\tbase\twords\twordsize\n"); 631 data += sprintf(data, "register\tbase\twords\twordsize\n");
627 data += sprintf(data, "csr\t%d\t%d\t%d\n", 632#define RT2X00DEBUGFS_SPRINTF_REGISTER(__name) \
628 debug->csr.word_base, 633{ \
629 debug->csr.word_count, 634 if(debug->__name.read) \
630 debug->csr.word_size); 635 data += sprintf(data, __stringify(__name) \
631 data += sprintf(data, "eeprom\t%d\t%d\t%d\n", 636 "\t%d\t%d\t%d\n", \
632 debug->eeprom.word_base, 637 debug->__name.word_base, \
633 debug->eeprom.word_count, 638 debug->__name.word_count, \
634 debug->eeprom.word_size); 639 debug->__name.word_size); \
635 data += sprintf(data, "bbp\t%d\t%d\t%d\n", 640}
636 debug->bbp.word_base, 641 RT2X00DEBUGFS_SPRINTF_REGISTER(csr);
637 debug->bbp.word_count, 642 RT2X00DEBUGFS_SPRINTF_REGISTER(eeprom);
638 debug->bbp.word_size); 643 RT2X00DEBUGFS_SPRINTF_REGISTER(bbp);
639 data += sprintf(data, "rf\t%d\t%d\t%d\n", 644 RT2X00DEBUGFS_SPRINTF_REGISTER(rf);
640 debug->rf.word_base, 645 RT2X00DEBUGFS_SPRINTF_REGISTER(rfcsr);
641 debug->rf.word_count, 646#undef RT2X00DEBUGFS_SPRINTF_REGISTER
642 debug->rf.word_size); 647
643 blob->size = strlen(blob->data); 648 blob->size = strlen(blob->data);
644 649
645 return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); 650 return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
@@ -694,31 +699,34 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
694 if (IS_ERR(intf->register_folder) || !intf->register_folder) 699 if (IS_ERR(intf->register_folder) || !intf->register_folder)
695 goto exit; 700 goto exit;
696 701
697#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ 702#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
698({ \ 703({ \
699 (__intf)->__name##_off_entry = \ 704 if(debug->__name.read) { \
700 debugfs_create_u32(__stringify(__name) "_offset", \ 705 (__intf)->__name##_off_entry = \
701 S_IRUSR | S_IWUSR, \ 706 debugfs_create_u32(__stringify(__name) "_offset", \
702 (__intf)->register_folder, \ 707 S_IRUSR | S_IWUSR, \
703 &(__intf)->offset_##__name); \ 708 (__intf)->register_folder, \
704 if (IS_ERR((__intf)->__name##_off_entry) \ 709 &(__intf)->offset_##__name); \
705 || !(__intf)->__name##_off_entry) \ 710 if (IS_ERR((__intf)->__name##_off_entry) \
706 goto exit; \ 711 || !(__intf)->__name##_off_entry) \
707 \ 712 goto exit; \
708 (__intf)->__name##_val_entry = \ 713 \
709 debugfs_create_file(__stringify(__name) "_value", \ 714 (__intf)->__name##_val_entry = \
710 S_IRUSR | S_IWUSR, \ 715 debugfs_create_file(__stringify(__name) "_value", \
711 (__intf)->register_folder, \ 716 S_IRUSR | S_IWUSR, \
712 (__intf), &rt2x00debug_fop_##__name);\ 717 (__intf)->register_folder, \
713 if (IS_ERR((__intf)->__name##_val_entry) \ 718 (__intf), &rt2x00debug_fop_##__name); \
714 || !(__intf)->__name##_val_entry) \ 719 if (IS_ERR((__intf)->__name##_val_entry) \
715 goto exit; \ 720 || !(__intf)->__name##_val_entry) \
721 goto exit; \
722 } \
716}) 723})
717 724
718 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr); 725 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
719 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom); 726 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
720 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp); 727 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
721 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf); 728 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
729 RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rfcsr);
722 730
723#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY 731#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
724 732
@@ -770,6 +778,8 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
770 debugfs_remove(intf->queue_stats_entry); 778 debugfs_remove(intf->queue_stats_entry);
771 debugfs_remove(intf->queue_frame_dump_entry); 779 debugfs_remove(intf->queue_frame_dump_entry);
772 debugfs_remove(intf->queue_folder); 780 debugfs_remove(intf->queue_folder);
781 debugfs_remove(intf->rfcsr_val_entry);
782 debugfs_remove(intf->rfcsr_off_entry);
773 debugfs_remove(intf->rf_val_entry); 783 debugfs_remove(intf->rf_val_entry);
774 debugfs_remove(intf->rf_off_entry); 784 debugfs_remove(intf->rf_off_entry);
775 debugfs_remove(intf->bbp_val_entry); 785 debugfs_remove(intf->bbp_val_entry);
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h
index fa11409cb5c6..e11d39bdfef7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.h
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.h
@@ -65,6 +65,7 @@ struct rt2x00debug {
65 RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16); 65 RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);
66 RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8); 66 RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);
67 RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32); 67 RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32);
68 RT2X00DEBUGFS_REGISTER_ENTRY(rfcsr, u8);
68}; 69};
69 70
70#endif /* RT2X00DEBUG_H */ 71#endif /* RT2X00DEBUG_H */
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 1335084b1c69..2540e86d99ab 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -2154,6 +2154,8 @@ enum nl80211_mntr_flags {
2154 * @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors 2154 * @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors
2155 * to synchronize to for 11s default synchronization method (see 11C.12.2.2) 2155 * to synchronize to for 11s default synchronization method (see 11C.12.2.2)
2156 * 2156 *
2157 * @NL80211_MESHCONF_HT_OPMODE: set mesh HT protection mode.
2158 *
2157 * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use 2159 * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
2158 */ 2160 */
2159enum nl80211_meshconf_params { 2161enum nl80211_meshconf_params {
@@ -2179,6 +2181,7 @@ enum nl80211_meshconf_params {
2179 NL80211_MESHCONF_FORWARDING, 2181 NL80211_MESHCONF_FORWARDING,
2180 NL80211_MESHCONF_RSSI_THRESHOLD, 2182 NL80211_MESHCONF_RSSI_THRESHOLD,
2181 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, 2183 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
2184 NL80211_MESHCONF_HT_OPMODE,
2182 2185
2183 /* keep last */ 2186 /* keep last */
2184 __NL80211_MESHCONF_ATTR_AFTER_LAST, 2187 __NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 815dc3f37e2b..adb2320bccdf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -821,6 +821,7 @@ struct mesh_config {
821 bool dot11MeshGateAnnouncementProtocol; 821 bool dot11MeshGateAnnouncementProtocol;
822 bool dot11MeshForwarding; 822 bool dot11MeshForwarding;
823 s32 rssi_threshold; 823 s32 rssi_threshold;
824 u16 ht_opmode;
824}; 825};
825 826
826/** 827/**
@@ -1514,6 +1515,16 @@ struct cfg80211_gtk_rekey_data {
1514 * later passes to cfg80211_probe_status(). 1515 * later passes to cfg80211_probe_status().
1515 * 1516 *
1516 * @set_noack_map: Set the NoAck Map for the TIDs. 1517 * @set_noack_map: Set the NoAck Map for the TIDs.
1518 *
1519 * @get_et_sset_count: Ethtool API to get string-set count.
1520 * See @ethtool_ops.get_sset_count
1521 *
1522 * @get_et_stats: Ethtool API to get a set of u64 stats.
1523 * See @ethtool_ops.get_ethtool_stats
1524 *
1525 * @get_et_strings: Ethtool API to get a set of strings to describe stats
1526 * and perhaps other supported types of ethtool data-sets.
1527 * See @ethtool_ops.get_strings
1517 */ 1528 */
1518struct cfg80211_ops { 1529struct cfg80211_ops {
1519 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); 1530 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1712,6 +1723,13 @@ struct cfg80211_ops {
1712 1723
1713 struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy, 1724 struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy,
1714 enum nl80211_channel_type *type); 1725 enum nl80211_channel_type *type);
1726
1727 int (*get_et_sset_count)(struct wiphy *wiphy,
1728 struct net_device *dev, int sset);
1729 void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev,
1730 struct ethtool_stats *stats, u64 *data);
1731 void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
1732 u32 sset, u8 *data);
1715}; 1733};
1716 1734
1717/* 1735/*
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index da3658177997..4d6e6c6818d0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2223,6 +2223,14 @@ enum ieee80211_rate_control_changed {
2223 * The @tids parameter is a bitmap and tells the driver which TIDs the 2223 * The @tids parameter is a bitmap and tells the driver which TIDs the
2224 * frames will be on; it will at most have two bits set. 2224 * frames will be on; it will at most have two bits set.
2225 * This callback must be atomic. 2225 * This callback must be atomic.
2226 *
2227 * @get_et_sset_count: Ethtool API to get string-set count.
2228 *
2229 * @get_et_stats: Ethtool API to get a set of u64 stats.
2230 *
2231 * @get_et_strings: Ethtool API to get a set of strings to describe stats
2232 * and perhaps other supported types of ethtool data-sets.
2233 *
2226 */ 2234 */
2227struct ieee80211_ops { 2235struct ieee80211_ops {
2228 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); 2236 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2353,6 +2361,15 @@ struct ieee80211_ops {
2353 u16 tids, int num_frames, 2361 u16 tids, int num_frames,
2354 enum ieee80211_frame_release_type reason, 2362 enum ieee80211_frame_release_type reason,
2355 bool more_data); 2363 bool more_data);
2364
2365 int (*get_et_sset_count)(struct ieee80211_hw *hw,
2366 struct ieee80211_vif *vif, int sset);
2367 void (*get_et_stats)(struct ieee80211_hw *hw,
2368 struct ieee80211_vif *vif,
2369 struct ethtool_stats *stats, u64 *data);
2370 void (*get_et_strings)(struct ieee80211_hw *hw,
2371 struct ieee80211_vif *vif,
2372 u32 sset, u8 *data);
2356}; 2373};
2357 2374
2358/** 2375/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7e6781f8c57e..495831ee48f1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -450,6 +450,180 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
450 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); 450 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
451} 451}
452 452
453static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
454 "rx_packets", "rx_bytes", "wep_weak_iv_count",
455 "rx_duplicates", "rx_fragments", "rx_dropped",
456 "tx_packets", "tx_bytes", "tx_fragments",
457 "tx_filtered", "tx_retry_failed", "tx_retries",
458 "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
459 "channel", "noise", "ch_time", "ch_time_busy",
460 "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
461};
462#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
463
464static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
465 struct net_device *dev,
466 int sset)
467{
468 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
469 int rv = 0;
470
471 if (sset == ETH_SS_STATS)
472 rv += STA_STATS_LEN;
473
474 rv += drv_get_et_sset_count(sdata, sset);
475
476 if (rv == 0)
477 return -EOPNOTSUPP;
478 return rv;
479}
480
481static void ieee80211_get_et_stats(struct wiphy *wiphy,
482 struct net_device *dev,
483 struct ethtool_stats *stats,
484 u64 *data)
485{
486 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
487 struct sta_info *sta;
488 struct ieee80211_local *local = sdata->local;
489 struct station_info sinfo;
490 struct survey_info survey;
491 int i, q;
492#define STA_STATS_SURVEY_LEN 7
493
494 memset(data, 0, sizeof(u64) * STA_STATS_LEN);
495
496#define ADD_STA_STATS(sta) \
497 do { \
498 data[i++] += sta->rx_packets; \
499 data[i++] += sta->rx_bytes; \
500 data[i++] += sta->wep_weak_iv_count; \
501 data[i++] += sta->num_duplicates; \
502 data[i++] += sta->rx_fragments; \
503 data[i++] += sta->rx_dropped; \
504 \
505 data[i++] += sta->tx_packets; \
506 data[i++] += sta->tx_bytes; \
507 data[i++] += sta->tx_fragments; \
508 data[i++] += sta->tx_filtered_count; \
509 data[i++] += sta->tx_retry_failed; \
510 data[i++] += sta->tx_retry_count; \
511 data[i++] += sta->beacon_loss_count; \
512 } while (0)
513
514 /* For Managed stations, find the single station based on BSSID
515 * and use that. For interface types, iterate through all available
516 * stations and add stats for any station that is assigned to this
517 * network device.
518 */
519
520 rcu_read_lock();
521
522 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
523 sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
524
525 if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
526 goto do_survey;
527
528 i = 0;
529 ADD_STA_STATS(sta);
530
531 data[i++] = sta->sta_state;
532
533 sinfo.filled = 0;
534 sta_set_sinfo(sta, &sinfo);
535
536 if (sinfo.filled | STATION_INFO_TX_BITRATE)
537 data[i] = 100000 *
538 cfg80211_calculate_bitrate(&sinfo.txrate);
539 i++;
540 if (sinfo.filled | STATION_INFO_RX_BITRATE)
541 data[i] = 100000 *
542 cfg80211_calculate_bitrate(&sinfo.rxrate);
543 i++;
544
545 if (sinfo.filled | STATION_INFO_SIGNAL_AVG)
546 data[i] = (u8)sinfo.signal_avg;
547 i++;
548 } else {
549 list_for_each_entry_rcu(sta, &local->sta_list, list) {
550 /* Make sure this station belongs to the proper dev */
551 if (sta->sdata->dev != dev)
552 continue;
553
554 i = 0;
555 ADD_STA_STATS(sta);
556 }
557 }
558
559do_survey:
560 i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
561 /* Get survey stats for current channel */
562 q = 0;
563 while (true) {
564 survey.filled = 0;
565 if (drv_get_survey(local, q, &survey) != 0) {
566 survey.filled = 0;
567 break;
568 }
569
570 if (survey.channel &&
571 (local->oper_channel->center_freq ==
572 survey.channel->center_freq))
573 break;
574 q++;
575 }
576
577 if (survey.filled)
578 data[i++] = survey.channel->center_freq;
579 else
580 data[i++] = 0;
581 if (survey.filled & SURVEY_INFO_NOISE_DBM)
582 data[i++] = (u8)survey.noise;
583 else
584 data[i++] = -1LL;
585 if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
586 data[i++] = survey.channel_time;
587 else
588 data[i++] = -1LL;
589 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
590 data[i++] = survey.channel_time_busy;
591 else
592 data[i++] = -1LL;
593 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
594 data[i++] = survey.channel_time_ext_busy;
595 else
596 data[i++] = -1LL;
597 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
598 data[i++] = survey.channel_time_rx;
599 else
600 data[i++] = -1LL;
601 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
602 data[i++] = survey.channel_time_tx;
603 else
604 data[i++] = -1LL;
605
606 rcu_read_unlock();
607
608 if (WARN_ON(i != STA_STATS_LEN))
609 return;
610
611 drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
612}
613
614static void ieee80211_get_et_strings(struct wiphy *wiphy,
615 struct net_device *dev,
616 u32 sset, u8 *data)
617{
618 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
619 int sz_sta_stats = 0;
620
621 if (sset == ETH_SS_STATS) {
622 sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
623 memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats);
624 }
625 drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
626}
453 627
454static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, 628static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
455 int idx, u8 *mac, struct station_info *sinfo) 629 int idx, u8 *mac, struct station_info *sinfo)
@@ -1364,6 +1538,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
1364 return -ENOTSUPP; 1538 return -ENOTSUPP;
1365 conf->rssi_threshold = nconf->rssi_threshold; 1539 conf->rssi_threshold = nconf->rssi_threshold;
1366 } 1540 }
1541 if (_chg_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask)) {
1542 conf->ht_opmode = nconf->ht_opmode;
1543 sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
1544 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
1545 }
1367 return 0; 1546 return 0;
1368} 1547}
1369 1548
@@ -2794,4 +2973,7 @@ struct cfg80211_ops mac80211_config_ops = {
2794#ifdef CONFIG_PM 2973#ifdef CONFIG_PM
2795 .set_wakeup = ieee80211_set_wakeup, 2974 .set_wakeup = ieee80211_set_wakeup,
2796#endif 2975#endif
2976 .get_et_sset_count = ieee80211_get_et_sset_count,
2977 .get_et_stats = ieee80211_get_et_stats,
2978 .get_et_strings = ieee80211_get_et_strings,
2797}; 2979};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4a0e559cb26b..6d33a0c743ab 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -35,6 +35,43 @@ static inline void drv_tx_frags(struct ieee80211_local *local,
35 local->ops->tx_frags(&local->hw, vif, sta, skbs); 35 local->ops->tx_frags(&local->hw, vif, sta, skbs);
36} 36}
37 37
38static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
39 u32 sset, u8 *data)
40{
41 struct ieee80211_local *local = sdata->local;
42 if (local->ops->get_et_strings) {
43 trace_drv_get_et_strings(local, sset);
44 local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data);
45 trace_drv_return_void(local);
46 }
47}
48
49static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata,
50 struct ethtool_stats *stats,
51 u64 *data)
52{
53 struct ieee80211_local *local = sdata->local;
54 if (local->ops->get_et_stats) {
55 trace_drv_get_et_stats(local);
56 local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data);
57 trace_drv_return_void(local);
58 }
59}
60
61static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata,
62 int sset)
63{
64 struct ieee80211_local *local = sdata->local;
65 int rv = 0;
66 if (local->ops->get_et_sset_count) {
67 trace_drv_get_et_sset_count(local, sset);
68 rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif,
69 sset);
70 trace_drv_return_int(local, rv);
71 }
72 return rv;
73}
74
38static inline int drv_start(struct ieee80211_local *local) 75static inline int drv_start(struct ieee80211_local *local)
39{ 76{
40 int ret; 77 int ret;
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 7c0754bed61b..6de00b2c268c 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -161,6 +161,21 @@ DEFINE_EVENT(local_only_evt, drv_start,
161 TP_ARGS(local) 161 TP_ARGS(local)
162); 162);
163 163
164DEFINE_EVENT(local_u32_evt, drv_get_et_strings,
165 TP_PROTO(struct ieee80211_local *local, u32 sset),
166 TP_ARGS(local, sset)
167);
168
169DEFINE_EVENT(local_u32_evt, drv_get_et_sset_count,
170 TP_PROTO(struct ieee80211_local *local, u32 sset),
171 TP_ARGS(local, sset)
172);
173
174DEFINE_EVENT(local_only_evt, drv_get_et_stats,
175 TP_PROTO(struct ieee80211_local *local),
176 TP_ARGS(local)
177);
178
164DEFINE_EVENT(local_only_evt, drv_suspend, 179DEFINE_EVENT(local_only_evt, drv_suspend,
165 TP_PROTO(struct ieee80211_local *local), 180 TP_PROTO(struct ieee80211_local *local),
166 TP_ARGS(local) 181 TP_ARGS(local)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index d307d3b3e32a..ebafba61c2ff 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -164,7 +164,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
164 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, 164 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
165 sband->ht_cap.cap); 165 sband->ht_cap.cap);
166 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, 166 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
167 chan, channel_type); 167 chan, channel_type, 0);
168 } 168 }
169 169
170 if (local->hw.queues >= IEEE80211_NUM_ACS) { 170 if (local->hw.queues >= IEEE80211_NUM_ACS) {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index fabee974bf6d..3f3cd50fff16 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1497,7 +1497,8 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1497 u16 cap); 1497 u16 cap);
1498u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1498u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1499 struct ieee80211_channel *channel, 1499 struct ieee80211_channel *channel,
1500 enum nl80211_channel_type channel_type); 1500 enum nl80211_channel_type channel_type,
1501 u16 prot_mode);
1501 1502
1502/* internal work items */ 1503/* internal work items */
1503void ieee80211_work_init(struct ieee80211_local *local); 1504void ieee80211_work_init(struct ieee80211_local *local);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 775627166e48..0675a2fec6a6 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -76,6 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
76 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 76 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
77 struct ieee80211_local *local = sdata->local; 77 struct ieee80211_local *local = sdata->local;
78 u32 basic_rates = 0; 78 u32 basic_rates = 0;
79 enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT;
79 80
80 /* 81 /*
81 * As support for each feature is added, check for matching 82 * As support for each feature is added, check for matching
@@ -102,10 +103,15 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
102 if (sdata->vif.bss_conf.basic_rates != basic_rates) 103 if (sdata->vif.bss_conf.basic_rates != basic_rates)
103 goto mismatch; 104 goto mismatch;
104 105
105 /* disallow peering with mismatched channel types for now */ 106 if (ie->ht_operation)
107 sta_channel_type =
108 ieee80211_ht_oper_to_channel_type(ie->ht_operation);
109
110 /* Disallow HT40+/- mismatch */
106 if (ie->ht_operation && 111 if (ie->ht_operation &&
107 (local->_oper_channel_type != 112 local->_oper_channel_type > NL80211_CHAN_HT20 &&
108 ieee80211_ht_oper_to_channel_type(ie->ht_operation))) 113 sta_channel_type > NL80211_CHAN_HT20 &&
114 local->_oper_channel_type != sta_channel_type)
109 goto mismatch; 115 goto mismatch;
110 116
111 return true; 117 return true;
@@ -396,7 +402,8 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
396 return -ENOMEM; 402 return -ENOMEM;
397 403
398 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); 404 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
399 ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type); 405 ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type,
406 sdata->vif.bss_conf.ht_operation_mode);
400 407
401 return 0; 408 return 0;
402} 409}
@@ -588,12 +595,15 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
588 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); 595 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
589 ieee80211_mesh_root_setup(ifmsh); 596 ieee80211_mesh_root_setup(ifmsh);
590 ieee80211_queue_work(&local->hw, &sdata->work); 597 ieee80211_queue_work(&local->hw, &sdata->work);
598 sdata->vif.bss_conf.ht_operation_mode =
599 ifmsh->mshcfg.ht_opmode;
591 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; 600 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
592 sdata->vif.bss_conf.basic_rates = 601 sdata->vif.bss_conf.basic_rates =
593 ieee80211_mandatory_rates(sdata->local, 602 ieee80211_mandatory_rates(sdata->local,
594 sdata->local->hw.conf.channel->band); 603 sdata->local->hw.conf.channel->band);
595 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 604 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
596 BSS_CHANGED_BEACON_ENABLED | 605 BSS_CHANGED_BEACON_ENABLED |
606 BSS_CHANGED_HT |
597 BSS_CHANGED_BASIC_RATES | 607 BSS_CHANGED_BASIC_RATES |
598 BSS_CHANGED_BEACON_INT); 608 BSS_CHANGED_BEACON_INT);
599} 609}
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 1ff2a5c63e43..8cc8461b48a0 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -102,12 +102,70 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
102 102
103 set_sta_flag(sta, WLAN_STA_WME); 103 set_sta_flag(sta, WLAN_STA_WME);
104 104
105 if (sta_info_insert(sta))
106 return NULL;
107
108 return sta; 105 return sta;
109} 106}
110 107
108/** mesh_set_ht_prot_mode - set correct HT protection mode
109 *
110 * Section 9.23.3.5 of IEEE 80211s standard describes the protection rules for
111 * HT mesh STA in a MBSS. Three HT protection modes are supported for now,
112 * non-HT mixed mode, 20MHz-protection and no-protection mode. non-HT mixed
113 * mode is selected if any non-HT peers are present in our MBSS.
114 * 20MHz-protection mode is selected if all peers in our 20/40MHz MBSS support
115 * HT and atleast one HT20 peer is present. Otherwise no-protection mode is
116 * selected.
117 */
118static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
119{
120 struct ieee80211_local *local = sdata->local;
121 struct sta_info *sta;
122 u32 changed = 0;
123 u16 ht_opmode;
124 bool non_ht_sta = false, ht20_sta = false;
125
126 if (local->_oper_channel_type == NL80211_CHAN_NO_HT)
127 return 0;
128
129 rcu_read_lock();
130 list_for_each_entry_rcu(sta, &local->sta_list, list) {
131 if (sdata == sta->sdata &&
132 sta->plink_state == NL80211_PLINK_ESTAB) {
133 switch (sta->ch_type) {
134 case NL80211_CHAN_NO_HT:
135 mpl_dbg("mesh_plink %pM: nonHT sta (%pM) is present",
136 sdata->vif.addr, sta->sta.addr);
137 non_ht_sta = true;
138 goto out;
139 case NL80211_CHAN_HT20:
140 mpl_dbg("mesh_plink %pM: HT20 sta (%pM) is present",
141 sdata->vif.addr, sta->sta.addr);
142 ht20_sta = true;
143 default:
144 break;
145 }
146 }
147 }
148out:
149 rcu_read_unlock();
150
151 if (non_ht_sta)
152 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
153 else if (ht20_sta && local->_oper_channel_type > NL80211_CHAN_HT20)
154 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
155 else
156 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
157
158 if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
159 sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
160 sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
161 changed = BSS_CHANGED_HT;
162 mpl_dbg("mesh_plink %pM: protection mode changed to %d",
163 sdata->vif.addr, ht_opmode);
164 }
165
166 return changed;
167}
168
111/** 169/**
112 * __mesh_plink_deactivate - deactivate mesh peer link 170 * __mesh_plink_deactivate - deactivate mesh peer link
113 * 171 *
@@ -281,6 +339,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
281 struct ieee80211_supported_band *sband; 339 struct ieee80211_supported_band *sband;
282 u32 rates, basic_rates = 0; 340 u32 rates, basic_rates = 0;
283 struct sta_info *sta; 341 struct sta_info *sta;
342 bool insert = false;
284 343
285 sband = local->hw.wiphy->bands[band]; 344 sband = local->hw.wiphy->bands[band];
286 rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates); 345 rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
@@ -290,6 +349,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
290 sta = mesh_plink_alloc(sdata, addr); 349 sta = mesh_plink_alloc(sdata, addr);
291 if (!sta) 350 if (!sta)
292 return NULL; 351 return NULL;
352 insert = true;
293 } 353 }
294 354
295 spin_lock_bh(&sta->lock); 355 spin_lock_bh(&sta->lock);
@@ -303,9 +363,21 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
303 else 363 else
304 memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); 364 memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
305 365
366 if (elems->ht_operation) {
367 if (!(elems->ht_operation->ht_param &
368 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
369 sta->sta.ht_cap.cap &=
370 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
371 sta->ch_type =
372 ieee80211_ht_oper_to_channel_type(elems->ht_operation);
373 }
374
306 rate_control_rate_init(sta); 375 rate_control_rate_init(sta);
307 spin_unlock_bh(&sta->lock); 376 spin_unlock_bh(&sta->lock);
308 377
378 if (insert && sta_info_insert(sta))
379 return NULL;
380
309 return sta; 381 return sta;
310} 382}
311 383
@@ -487,9 +559,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
487 enum plink_event event; 559 enum plink_event event;
488 enum ieee80211_self_protected_actioncode ftype; 560 enum ieee80211_self_protected_actioncode ftype;
489 size_t baselen; 561 size_t baselen;
490 bool deactivated, matches_local = true; 562 bool matches_local = true;
491 u8 ie_len; 563 u8 ie_len;
492 u8 *baseaddr; 564 u8 *baseaddr;
565 u32 changed = 0;
493 __le16 plid, llid, reason; 566 __le16 plid, llid, reason;
494#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG 567#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
495 static const char *mplstates[] = { 568 static const char *mplstates[] = {
@@ -775,7 +848,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
775 sta->plink_state = NL80211_PLINK_ESTAB; 848 sta->plink_state = NL80211_PLINK_ESTAB;
776 spin_unlock_bh(&sta->lock); 849 spin_unlock_bh(&sta->lock);
777 mesh_plink_inc_estab_count(sdata); 850 mesh_plink_inc_estab_count(sdata);
778 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); 851 changed |= mesh_set_ht_prot_mode(sdata);
852 changed |= BSS_CHANGED_BEACON;
779 mpl_dbg("Mesh plink with %pM ESTABLISHED\n", 853 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
780 sta->sta.addr); 854 sta->sta.addr);
781 break; 855 break;
@@ -810,7 +884,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
810 sta->plink_state = NL80211_PLINK_ESTAB; 884 sta->plink_state = NL80211_PLINK_ESTAB;
811 spin_unlock_bh(&sta->lock); 885 spin_unlock_bh(&sta->lock);
812 mesh_plink_inc_estab_count(sdata); 886 mesh_plink_inc_estab_count(sdata);
813 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); 887 changed |= mesh_set_ht_prot_mode(sdata);
888 changed |= BSS_CHANGED_BEACON;
814 mpl_dbg("Mesh plink with %pM ESTABLISHED\n", 889 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
815 sta->sta.addr); 890 sta->sta.addr);
816 mesh_plink_frame_tx(sdata, 891 mesh_plink_frame_tx(sdata,
@@ -828,13 +903,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
828 case CLS_ACPT: 903 case CLS_ACPT:
829 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); 904 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
830 sta->reason = reason; 905 sta->reason = reason;
831 deactivated = __mesh_plink_deactivate(sta); 906 __mesh_plink_deactivate(sta);
832 sta->plink_state = NL80211_PLINK_HOLDING; 907 sta->plink_state = NL80211_PLINK_HOLDING;
833 llid = sta->llid; 908 llid = sta->llid;
834 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); 909 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
835 spin_unlock_bh(&sta->lock); 910 spin_unlock_bh(&sta->lock);
836 if (deactivated) 911 changed |= mesh_set_ht_prot_mode(sdata);
837 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); 912 changed |= BSS_CHANGED_BEACON;
838 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, 913 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
839 sta->sta.addr, llid, plid, reason); 914 sta->sta.addr, llid, plid, reason);
840 break; 915 break;
@@ -881,4 +956,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
881 } 956 }
882 957
883 rcu_read_unlock(); 958 rcu_read_unlock();
959
960 if (changed)
961 ieee80211_bss_info_change_notify(sdata, changed);
884} 962}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b1c617fdabd6..52cd301245ae 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -210,7 +210,7 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
210 disable_40 = true; 210 disable_40 = true;
211 211
212 if (sta && (!reconfig || 212 if (sta && (!reconfig ||
213 (disable_40 != !!(sta->sta.ht_cap.cap & 213 (disable_40 != !(sta->sta.ht_cap.cap &
214 IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) { 214 IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) {
215 215
216 if (disable_40) 216 if (disable_40)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index e920b229fb8c..3bb24a121c95 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -362,6 +362,7 @@ struct sta_info {
362 struct timer_list plink_timer; 362 struct timer_list plink_timer;
363 s64 t_offset; 363 s64 t_offset;
364 s64 t_offset_setpoint; 364 s64 t_offset_setpoint;
365 enum nl80211_channel_type ch_type;
365#endif 366#endif
366 367
367#ifdef CONFIG_MAC80211_DEBUGFS 368#ifdef CONFIG_MAC80211_DEBUGFS
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d9a747d387f0..22f2216b397e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1663,7 +1663,8 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1663 1663
1664u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1664u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1665 struct ieee80211_channel *channel, 1665 struct ieee80211_channel *channel,
1666 enum nl80211_channel_type channel_type) 1666 enum nl80211_channel_type channel_type,
1667 u16 prot_mode)
1667{ 1668{
1668 struct ieee80211_ht_operation *ht_oper; 1669 struct ieee80211_ht_operation *ht_oper;
1669 /* Build HT Information */ 1670 /* Build HT Information */
@@ -1689,11 +1690,7 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1689 channel_type != NL80211_CHAN_HT20) 1690 channel_type != NL80211_CHAN_HT20)
1690 ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; 1691 ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
1691 1692
1692 /* 1693 ht_oper->operation_mode = cpu_to_le16(prot_mode);
1693 * Note: According to 802.11n-2009 9.13.3.1, HT Protection field and
1694 * RIFS Mode are reserved in IBSS mode, therefore keep them at 0
1695 */
1696 ht_oper->operation_mode = 0x0000;
1697 ht_oper->stbc_param = 0x0000; 1694 ht_oper->stbc_param = 0x0000;
1698 1695
1699 /* It seems that Basic MCS set and Supported MCS set 1696 /* It seems that Basic MCS set and Supported MCS set
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c
index 9bde4d1d3e9b..7eecdf40cf80 100644
--- a/net/wireless/ethtool.c
+++ b/net/wireless/ethtool.c
@@ -68,6 +68,32 @@ static int cfg80211_set_ringparam(struct net_device *dev,
68 return -ENOTSUPP; 68 return -ENOTSUPP;
69} 69}
70 70
71static int cfg80211_get_sset_count(struct net_device *dev, int sset)
72{
73 struct wireless_dev *wdev = dev->ieee80211_ptr;
74 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
75 if (rdev->ops->get_et_sset_count)
76 return rdev->ops->get_et_sset_count(wdev->wiphy, dev, sset);
77 return -EOPNOTSUPP;
78}
79
80static void cfg80211_get_stats(struct net_device *dev,
81 struct ethtool_stats *stats, u64 *data)
82{
83 struct wireless_dev *wdev = dev->ieee80211_ptr;
84 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
85 if (rdev->ops->get_et_stats)
86 rdev->ops->get_et_stats(wdev->wiphy, dev, stats, data);
87}
88
89static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
90{
91 struct wireless_dev *wdev = dev->ieee80211_ptr;
92 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
93 if (rdev->ops->get_et_strings)
94 rdev->ops->get_et_strings(wdev->wiphy, dev, sset, data);
95}
96
71const struct ethtool_ops cfg80211_ethtool_ops = { 97const struct ethtool_ops cfg80211_ethtool_ops = {
72 .get_drvinfo = cfg80211_get_drvinfo, 98 .get_drvinfo = cfg80211_get_drvinfo,
73 .get_regs_len = cfg80211_get_regs_len, 99 .get_regs_len = cfg80211_get_regs_len,
@@ -75,4 +101,7 @@ const struct ethtool_ops cfg80211_ethtool_ops = {
75 .get_link = ethtool_op_get_link, 101 .get_link = ethtool_op_get_link,
76 .get_ringparam = cfg80211_get_ringparam, 102 .get_ringparam = cfg80211_get_ringparam,
77 .set_ringparam = cfg80211_set_ringparam, 103 .set_ringparam = cfg80211_set_ringparam,
104 .get_strings = cfg80211_get_strings,
105 .get_ethtool_stats = cfg80211_get_stats,
106 .get_sset_count = cfg80211_get_sset_count,
78}; 107};
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 8c747fa9319b..2749cb86b462 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -61,6 +61,7 @@ const struct mesh_config default_mesh_config = {
61 .dot11MeshGateAnnouncementProtocol = false, 61 .dot11MeshGateAnnouncementProtocol = false,
62 .dot11MeshForwarding = true, 62 .dot11MeshForwarding = true,
63 .rssi_threshold = MESH_RSSI_THRESHOLD, 63 .rssi_threshold = MESH_RSSI_THRESHOLD,
64 .ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED,
64}; 65};
65 66
66const struct mesh_setup default_mesh_setup = { 67const struct mesh_setup default_mesh_setup = {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d5005c59c472..b67b1114e25a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3390,7 +3390,9 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
3390 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, 3390 nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
3391 cur_params.dot11MeshForwarding) || 3391 cur_params.dot11MeshForwarding) ||
3392 nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, 3392 nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
3393 cur_params.rssi_threshold)) 3393 cur_params.rssi_threshold) ||
3394 nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE,
3395 cur_params.ht_opmode))
3394 goto nla_put_failure; 3396 goto nla_put_failure;
3395 nla_nest_end(msg, pinfoattr); 3397 nla_nest_end(msg, pinfoattr);
3396 genlmsg_end(msg, hdr); 3398 genlmsg_end(msg, hdr);
@@ -3426,6 +3428,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
3426 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, 3428 [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
3427 [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, 3429 [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
3428 [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32}, 3430 [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32},
3431 [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16},
3429}; 3432};
3430 3433
3431static const struct nla_policy 3434static const struct nla_policy
@@ -3523,6 +3526,8 @@ do {\
3523 mask, NL80211_MESHCONF_FORWARDING, nla_get_u8); 3526 mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
3524 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, 3527 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold,
3525 mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32); 3528 mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32);
3529 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode,
3530 mask, NL80211_MESHCONF_HT_OPMODE, nla_get_u16);
3526 if (mask_out) 3531 if (mask_out)
3527 *mask_out = mask; 3532 *mask_out = mask;
3528 3533
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 26d96d7ffba8..af2b1caa37fa 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -378,7 +378,11 @@ static int cmp_bss_core(struct cfg80211_bss *a,
378 b->len_information_elements); 378 b->len_information_elements);
379 } 379 }
380 380
381 return compare_ether_addr(a->bssid, b->bssid); 381 /*
382 * we can't use compare_ether_addr here since we need a < > operator.
383 * The binary return value of compare_ether_addr isn't enough
384 */
385 return memcmp(a->bssid, b->bssid, sizeof(a->bssid));
382} 386}
383 387
384static int cmp_bss(struct cfg80211_bss *a, 388static int cmp_bss(struct cfg80211_bss *a,