diff options
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: | |||
1122 | static void at76_dump_mib_local(struct at76_priv *priv) | 1122 | static 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 | ||
39 | config 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 | |||
39 | config BRCMFMAC_USB | 48 | config 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 | ||
42 | static void brcmf_sdioh_irqhandler(struct sdio_func *func) | 42 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB |
43 | static 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 | |||
63 | int 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 | |||
104 | int 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 */ | ||
122 | static 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 */ |
56 | static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func) | 132 | static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func) |
57 | { | 133 | { |
58 | } | 134 | } |
59 | 135 | ||
60 | int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev) | 136 | int 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 | ||
72 | int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev) | 148 | int 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 | ||
84 | u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, | 161 | u8 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 | }; |
56 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 57 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
57 | 58 | ||
59 | #ifdef CONFIG_BRCMFMAC_SDIO_OOB | ||
60 | static struct list_head oobirq_lh; | ||
61 | struct brcmf_sdio_oobirq { | ||
62 | unsigned int irq; | ||
63 | unsigned long flags; | ||
64 | struct list_head list; | ||
65 | }; | ||
66 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
67 | |||
58 | static bool | 68 | static bool |
59 | brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) | 69 | brcmf_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 | ||
482 | static 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 | ||
502 | static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev) | ||
503 | { | ||
504 | return 0; | ||
505 | } | ||
506 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
507 | |||
470 | static int brcmf_ops_sdio_probe(struct sdio_func *func, | 508 | static 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 | ||
650 | static 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 | |||
680 | static struct platform_driver brcmf_sdio_pd = { | ||
681 | .probe = brcmf_sdio_pd_probe, | ||
682 | .driver = { | ||
683 | .name = "brcmf_sdio_pd" | ||
684 | } | ||
685 | }; | ||
686 | |||
687 | void 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 | |||
696 | void 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 | ||
606 | void brcmf_sdio_exit(void) | 708 | void 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 | ||
2356 | static 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 | ||
2368 | static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | ||
2369 | { | ||
2370 | } | ||
2371 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | ||
2372 | |||
2355 | static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | 2373 | static 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 | ||
2511 | clkwait: | 2529 | clkwait: |
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 | ||
3515 | exit: | 3541 | exit: |
@@ -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. */ |
150 | extern int | 164 | extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); |
151 | brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev); | 165 | extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); |
152 | |||
153 | extern 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() */ | ||
11447 | static 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 | |||
11460 | static int ipw_wdev_init(struct net_device *dev) | 11446 | static 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 | ||
11727 | static const struct net_device_ops ipw_netdev_ops = { | 11713 | static 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. | 190 | static 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 | |||
258 | static 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 | ||
273 | static const __le32 iwlagn_concurrent_lookup[12] = { | 205 | |
206 | /* Loose Coex */ | ||
207 | static 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 */ | ||
223 | static 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 | ||
613 | static void iwlagn_set_kill_msk(struct iwl_priv *priv, | 564 | static 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 */ | 592 | static 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 | ||
638 | int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, | 622 | int 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 | ||
1420 | void iwl_debug_config(struct iwl_priv *priv) | 1423 | /* show what optional capabilities we have */ |
1424 | void 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) | |||
523 | void iwl_setup_deferred_work(struct iwl_priv *priv); | 523 | void iwl_setup_deferred_work(struct iwl_priv *priv); |
524 | int iwl_send_wimax_coex(struct iwl_priv *priv); | 524 | int iwl_send_wimax_coex(struct iwl_priv *priv); |
525 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | 525 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); |
526 | void iwl_debug_config(struct iwl_priv *priv); | 526 | void iwl_option_config(struct iwl_priv *priv); |
527 | void iwl_set_hw_params(struct iwl_priv *priv); | 527 | void iwl_set_hw_params(struct iwl_priv *priv); |
528 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); | 528 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); |
529 | int iwl_init_drv(struct iwl_priv *priv); | 529 | int 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 | ||
1880 | enum 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 | |||
1906 | struct iwl_basic_bt_cmd { | 1915 | struct 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 | |||
3637 | struct iwl_bt_uart_msg { | 3650 | struct 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); |
1013 | MODULE_PARM_DESC(auto_agg, | 1013 | MODULE_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 | |||
1016 | module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz, | ||
1017 | bool, S_IRUGO); | ||
1018 | MODULE_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 | */ |
107 | struct iwl_mod_params { | 108 | struct 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 | ||
12 | config MWIFIEX_SDIO | 12 | config 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 { | |||
993 | struct ieee_types_vendor_header { | 993 | struct 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 */ |
262 | static const struct sdio_device_id mwifiex_ids[] = { | 264 | static 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."); | |||
1807 | MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); | 1813 | MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); |
1808 | MODULE_VERSION(SDIO_VERSION); | 1814 | MODULE_VERSION(SDIO_VERSION); |
1809 | MODULE_LICENSE("GPL v2"); | 1815 | MODULE_LICENSE("GPL v2"); |
1816 | MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME); | ||
1810 | MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME); | 1817 | MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME); |
1811 | MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME); | 1818 | MODULE_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 | }; |
840 | EXPORT_SYMBOL_GPL(rt2800_rt2x00debug); | 847 | EXPORT_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 | ||
136 | void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, | 140 | void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, |
@@ -525,6 +529,7 @@ RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32); | |||
525 | RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16); | 529 | RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16); |
526 | RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8); | 530 | RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8); |
527 | RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32); | 531 | RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32); |
532 | RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8); | ||
528 | 533 | ||
529 | static ssize_t rt2x00debug_read_dev_flags(struct file *file, | 534 | static 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 | */ |
2159 | enum nl80211_meshconf_params { | 2161 | enum 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 | */ |
1518 | struct cfg80211_ops { | 1529 | struct 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 | */ |
2227 | struct ieee80211_ops { | 2235 | struct 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 | ||
453 | static 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 | |||
464 | static 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 | |||
481 | static 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 | |||
559 | do_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 | |||
614 | static 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 | ||
454 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 628 | static 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 | ||
38 | static 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 | |||
49 | static 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 | |||
61 | static 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 | |||
38 | static inline int drv_start(struct ieee80211_local *local) | 75 | static 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 | ||
164 | DEFINE_EVENT(local_u32_evt, drv_get_et_strings, | ||
165 | TP_PROTO(struct ieee80211_local *local, u32 sset), | ||
166 | TP_ARGS(local, sset) | ||
167 | ); | ||
168 | |||
169 | DEFINE_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 | |||
174 | DEFINE_EVENT(local_only_evt, drv_get_et_stats, | ||
175 | TP_PROTO(struct ieee80211_local *local), | ||
176 | TP_ARGS(local) | ||
177 | ); | ||
178 | |||
164 | DEFINE_EVENT(local_only_evt, drv_suspend, | 179 | DEFINE_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); |
1498 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1498 | u8 *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 */ |
1503 | void ieee80211_work_init(struct ieee80211_local *local); | 1504 | void 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 | */ | ||
118 | static 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 | } | ||
148 | out: | ||
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 | ||
1664 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1664 | u8 *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 | ||
71 | static 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 | |||
80 | static 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 | |||
89 | static 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 | |||
71 | const struct ethtool_ops cfg80211_ethtool_ops = { | 97 | const 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 | ||
66 | const struct mesh_setup default_mesh_setup = { | 67 | const 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 | ||
3431 | static const struct nla_policy | 3434 | static 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 | ||
384 | static int cmp_bss(struct cfg80211_bss *a, | 388 | static int cmp_bss(struct cfg80211_bss *a, |